def setup_kube_crd( kube_client: KubeClient, cluster: str, services: Sequence[str], soa_dir: str = DEFAULT_SOA_DIR, ) -> bool: existing_crds = kube_client.apiextensions.list_custom_resource_definition( label_selector=paasta_prefixed("service")) desired_crds = [] for service in services: crd_config = service_configuration_lib.read_extra_service_information( service, f"crd-{cluster}", soa_dir=soa_dir) if not crd_config: log.info("nothing to deploy") continue metadata = crd_config.get("metadata", {}) if "labels" not in metadata: metadata["labels"] = {} metadata["labels"]["yelp.com/paasta_service"] = service metadata["labels"][paasta_prefixed("service")] = service desired_crd = V1beta1CustomResourceDefinition( api_version=crd_config.get("apiVersion"), kind=crd_config.get("kind"), metadata=metadata, spec=crd_config.get("spec"), ) desired_crds.append(desired_crd) return update_crds( kube_client=kube_client, desired_crds=desired_crds, existing_crds=existing_crds, )
def test_createMongoObjectDefinition(self, client_mock): service = KubernetesService() client_mock.reset_mock() expected_def = V1beta1CustomResourceDefinition( api_version="apiextensions.k8s.io/v1beta1", kind="CustomResourceDefinition", metadata=V1ObjectMeta(name="mongos.operators.ultimaker.com"), spec=V1beta1CustomResourceDefinitionSpec( group="operators.ultimaker.com", version="v1", scope="Namespaced", names=V1beta1CustomResourceDefinitionNames(plural="mongos", singular="mongo", kind="Mongo", short_names=["mng" ]))) client_mock.ApiextensionsV1beta1Api.return_value.list_custom_resource_definition.return_value = \ V1beta1CustomResourceDefinitionList(items=[]) client_mock.ApiextensionsV1beta1Api.return_value.create_custom_resource_definition.return_value = expected_def result = service.createMongoObjectDefinition() self.assertEquals(expected_def, result) expected_calls = [ call.ApiextensionsV1beta1Api().list_custom_resource_definition(), call.ApiextensionsV1beta1Api().create_custom_resource_definition( expected_def), ] self.assertEqual(expected_calls, client_mock.mock_calls)
def ensure_crd(api, name, group, kind, plural, singular, scope): if len( api.list_custom_resource_definition( field_selector=f'metadata.name={name}').items) == 0: logger.info(f'creating CustomResourceDefinition: {name}') try: api.create_custom_resource_definition( V1beta1CustomResourceDefinition( api_version='apiextensions.k8s.io/v1beta1', kind='CustomResourceDefinition', metadata=V1ObjectMeta(name=name), spec=V1beta1CustomResourceDefinitionSpec( group=group, version='v1alpha1', names={ 'kind': kind, 'plural': plural, 'singular': singular }, scope=scope), )) except ValueError: # unforunate workaround due to client library bug # https://github.com/kubernetes-client/python/issues/415 logger.warning( f'swallowed ValueError when creating CRD {name} to workaround API client issue' ) pass else: logger.info(f'CustomResourceDefinition exists: {name}')
def setup_kube_crd( kube_client: KubeClient, cluster: str, services: Sequence[str], soa_dir: str = DEFAULT_SOA_DIR, ) -> bool: existing_crds = kube_client.apiextensions.list_custom_resource_definition( label_selector="paasta.yelp.com/service") success = True for service in services: crd_config = service_configuration_lib.read_extra_service_information( service, f"crd-{cluster}", soa_dir=soa_dir) if not crd_config: log.info("nothing to deploy") continue metadata = crd_config.get("metadata", {}) if "labels" not in metadata: metadata["labels"] = {} metadata["labels"]["yelp.com/paasta_service"] = service metadata["labels"]["paasta.yelp.com/service"] = service desired_crd = V1beta1CustomResourceDefinition( api_version=crd_config.get("apiVersion"), kind=crd_config.get("kind"), metadata=metadata, spec=crd_config.get("spec"), ) existing_crd = None for crd in existing_crds.items: if crd.metadata.name == desired_crd.metadata["name"]: existing_crd = crd break try: if existing_crd: desired_crd.metadata[ "resourceVersion"] = existing_crd.metadata.resource_version kube_client.apiextensions.replace_custom_resource_definition( name=desired_crd.metadata["name"], body=desired_crd) else: try: kube_client.apiextensions.create_custom_resource_definition( body=desired_crd) except ValueError as err: # TODO: kubernetes server will sometimes reply with conditions:null, # figure out how to deal with this correctly, for more details: # https://github.com/kubernetes/kubernetes/pull/64996 if "`conditions`, must not be `None`" in str(err): pass else: raise err log.info( f"deployed {desired_crd.metadata['name']} for {cluster}:{service}" ) except ApiException as exc: log.error(f"error deploying crd for {cluster}:{service}, " f"status: {exc.status}, reason: {exc.reason}") log.debug(exc.body) success = False return success
V1beta1CustomResourceDefinition( api_version="apiextensions.k8s.io/v1beta1", kind="CustomResourceDefinition", metadata={ "name": "deploygroups.paasta.yelp.com", "labels": { paasta_prefixed("internal"): "true", }, }, spec={ "group": "paasta.yelp.com", "versions": [{"name": "v1beta1", "served": True, "storage": True}], "scope": "Namespaced", "names": { "plural": "deploygroups", "singular": "deploygroup", "kind": "DeployGroup", "shortNames": ["dg"], }, "validation": { "openAPIV3Schema": { "type": "object", "properties": { "service": {"type": "string"}, "deploy_group": {"type": "string"}, "git_sha": {"type": "string"}, "image_version": {"type": "string"}, }, } }, }, ),