Skip to content

Commit

Permalink
better validation
Browse files Browse the repository at this point in the history
  • Loading branch information
eaudetcobello committed Nov 7, 2024
1 parent 4a09647 commit 8dc67cc
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 27 deletions.
16 changes: 11 additions & 5 deletions charms/worker/k8s/lib/charms/k8s/v0/k8sd_api_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class utilises different connection factories (UnixSocketConnectionFactory
from typing import Any, Dict, Generator, List, Optional, Type, TypeVar

import yaml
from pydantic import AnyHttpUrl, BaseModel, Field, SecretStr, validator
from pydantic import AnyHttpUrl, BaseModel, Field, SecretStr, validator, root_validator

# The unique Charmhub library identifier, never change it
LIBID = "6a5f235306864667a50437c08ba7e83f"
Expand Down Expand Up @@ -526,11 +526,17 @@ class FeatureRelationData(BaseModel):
Attributes:
name (str): The feature name.
version (str): The library version that was used to create the feature object.
attributes (Dict[str, str]): The serialized Pydantic model representing the feature.
attributes (str): The serialized Pydantic model representing the feature configuration.
"""
name: Optional[str] = Field(None)
version: Optional[str] = Field(None)
attributes: Optional[str] = Field(None)
name: str
version: str
attributes: str

@root_validator(pre=True)
def check_data(cls, values):
assert 'name' in values, "name must be provided"
assert 'version' in values, "version must be provided"
assert 'attributes' in values, "attributes must be provided"

class GetKubeConfigResponse(BaseRequestModel):
"""Response model for getting the kubeconfig from the cluster.
Expand Down
46 changes: 24 additions & 22 deletions charms/worker/k8s/src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
from snap import version as snap_version
from token_distributor import ClusterTokenType, TokenCollector, TokenDistributor, TokenStrategy
from typing_extensions import Literal
from pydantic import ValidationError

# Log messages can be retrieved using juju debug-log
log = logging.getLogger(__name__)
Expand Down Expand Up @@ -165,33 +166,34 @@ def _resolve_feature_relations(self, event: ops.EventBase):
raw_relation_data = relation.data[unit]

if not raw_relation_data:
log.warning("No relation data found for feature relation on %s", relation.name)
log.warning("No relation data found for %s relation", relation.name)
continue

try:
parsed_relation_data = FeatureRelationData.parse_obj(raw_relation_data)
except ValidationError as e:
log.warning("The relation data for %s relation is not valid: %s", relation.name, e)
continue

parsed_relation_data = FeatureRelationData.parse_obj(raw_relation_data)
feature_name = parsed_relation_data.name
feature_version = parsed_relation_data.version
feature_attributes = parsed_relation_data.attributes

if feature_name and feature_version and feature_attributes:
feature_config_classes: Dict[str, type] = {
"load-balancer": LoadBalancerConfig,
"local-storage": LocalStorageConfig,
}
if not (config_class := feature_config_classes.get(feature_name)):
status.add(ops.BlockedStatus(f"Unsupported feature {feature_name}"))
continue

feature_config = config_class.parse_raw(feature_attributes)
log.info("Updating feature [%s] with config [%s]", feature_name, feature_config)

cluster_config = UserFacingClusterConfig(**{feature_name: feature_config})
update_request = UpdateClusterConfigRequest(config=cluster_config)
self.api_manager.update_cluster_config(update_request)

log.info("Feature [%s] updated", feature_name)
else:
log.warning("Couldn't resolve feature relation because the relation data is not valid")
feature_config_classes: Dict[str, type] = {
"load-balancer": LoadBalancerConfig,
"local-storage": LocalStorageConfig,
}
if not (config_class := feature_config_classes.get(feature_name)):
status.add(ops.BlockedStatus(f"Unsupported feature {feature_name}"))
continue

feature_config = config_class.parse_raw(feature_attributes)
log.info("Updating feature [%s] with config [%s]", feature_name, feature_config)

cluster_config = UserFacingClusterConfig(**{feature_name: feature_config})
update_request = UpdateClusterConfigRequest(config=cluster_config)
self.api_manager.update_cluster_config(update_request)

log.info("Feature [%s] updated", feature_name)

def _k8s_info(self, event: ops.EventBase):
"""Send cluster information on the kubernetes-info relation.
Expand Down

0 comments on commit 8dc67cc

Please sign in to comment.