def reconcile_kubernetes_resource( kube_client: KubeClient, service: str, instance_configs: Mapping[str, Any], custom_resources: Sequence[KubeCustomResource], kind: KubeKind, version: str, group: str, ) -> bool: results = [] for instance, config in instance_configs.items(): formatted_resource = format_custom_resource( instance_config=config, service=service, instance=instance, kind=kind.singular, version=version, group=group, ) desired_resource = KubeCustomResource( service=service, instance=instance, config_sha=formatted_resource['metadata']['labels'] ['yelp.com/paasta_config_sha'], kind=kind.singular, ) try: if not (service, instance, kind.singular) in [ (c.service, c.instance, c.kind) for c in custom_resources ]: log.info(f"{desired_resource} does not exist so creating") create_custom_resource( kube_client=kube_client, version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) elif desired_resource not in custom_resources: sanitised_service = service.replace('_', '--') sanitised_instance = instance.replace('_', '--') log.info( f"{desired_resource} exists but config_sha doesn't match") update_custom_resource( kube_client=kube_client, name=f'{sanitised_service}-{sanitised_instance}', version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) else: log.info(f"{desired_resource} is up to date, no action taken") except Exception as e: log.error(str(e)) results.append(False) results.append(True) return all(results) if results else True
def test_reconcile_kubernetes_resource(): with mock.patch( "paasta_tools.setup_kubernetes_cr.format_custom_resource", autospec=True ) as mock_format_custom_resource, mock.patch( "paasta_tools.setup_kubernetes_cr.create_custom_resource", autospec=True ) as mock_create_custom_resource, mock.patch( "paasta_tools.setup_kubernetes_cr.update_custom_resource", autospec=True ) as mock_update_custom_resource: mock_kind = mock.Mock(singular="flink", plural="flinks") mock_custom_resources = [ KubeCustomResource( service="kurupt", instance="fm", config_sha="conf123", kind="flink", name="foo", namespace="paasta-flinks", ) ] mock_client = mock.Mock() # no instances, do nothing assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service="mc", instance_configs={}, cluster="mycluster", custom_resources=mock_custom_resources, kind=mock_kind, version="v1", group="yelp.com", ) assert not mock_create_custom_resource.called assert not mock_update_custom_resource.called # instance up to date, do nothing mock_format_custom_resource.return_value = { "metadata": { "labels": { "yelp.com/paasta_config_sha": "conf123", "paasta.yelp.com/config_sha": "conf123", }, "name": "foo", "namespace": "paasta-flinks", } } assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service="kurupt", instance_configs={"fm": {"some": "config"}}, cluster="cluster", custom_resources=mock_custom_resources, kind=mock_kind, version="v1", group="yelp.com", ) assert not mock_create_custom_resource.called assert not mock_update_custom_resource.called # instance diff config, update mock_format_custom_resource.return_value = { "metadata": { "labels": {"yelp.com/paasta_config_sha": "conf456"}, "name": "foo", "namespace": "paasta-flinks", } } assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service="kurupt", instance_configs={"fm": {"some": "config"}}, cluster="mycluster", custom_resources=mock_custom_resources, kind=mock_kind, version="v1", group="yelp.com", ) assert not mock_create_custom_resource.called mock_update_custom_resource.assert_called_with( kube_client=mock_client, name="kurupt-fm", version="v1", kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group="yelp.com", ) # instance not exist, create assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service="mc", instance_configs={"grindah": {"some": "conf"}}, cluster="mycluster", custom_resources=mock_custom_resources, kind=mock_kind, version="v1", group="yelp.com", ) mock_create_custom_resource.assert_called_with( kube_client=mock_client, version="v1", kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group="yelp.com", ) # instance not exist, create but error with k8s mock_create_custom_resource.side_effect = Exception assert not setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service="mc", instance_configs={"grindah": {"some": "conf"}}, cluster="mycluster", custom_resources=mock_custom_resources, kind=mock_kind, version="v1", group="yelp.com", ) mock_create_custom_resource.assert_called_with( kube_client=mock_client, version="v1", kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group="yelp.com", )
def test_reconcile_kubernetes_resource(): with mock.patch( 'paasta_tools.setup_kubernetes_cr.format_custom_resource', autospec=True, ) as mock_format_custom_resource, mock.patch( 'paasta_tools.setup_kubernetes_cr.create_custom_resource', autospec=True, ) as mock_create_custom_resource, mock.patch( 'paasta_tools.setup_kubernetes_cr.update_custom_resource', autospec=True, ) as mock_update_custom_resource: mock_kind = mock.Mock(singular='flinkcluster') mock_custom_resources = [ KubeCustomResource( service='kurupt', instance='fm', config_sha='conf123', kind='flinkcluster', ), ] mock_client = mock.Mock() # no instances, do nothing assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service='mc', instance_configs={}, custom_resources=mock_custom_resources, kind=mock_kind, version='v1', group='yelp.com', ) assert not mock_create_custom_resource.called assert not mock_update_custom_resource.called # instance up to date, do nothing mock_format_custom_resource.return_value = { 'metadata': { 'labels': { 'yelp.com/paasta_config_sha': 'conf123', }, }, } assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service='kurupt', instance_configs={'fm': { 'some': 'config' }}, custom_resources=mock_custom_resources, kind=mock_kind, version='v1', group='yelp.com', ) assert not mock_create_custom_resource.called assert not mock_update_custom_resource.called # instance diff config, update mock_format_custom_resource.return_value = { 'metadata': { 'labels': { 'yelp.com/paasta_config_sha': 'conf456', }, }, } assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service='kurupt', instance_configs={'fm': { 'some': 'config' }}, custom_resources=mock_custom_resources, kind=mock_kind, version='v1', group='yelp.com', ) assert not mock_create_custom_resource.called mock_update_custom_resource.assert_called_with( kube_client=mock_client, name='kurupt-fm', version='v1', kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group='yelp.com', ) # instance not exist, create assert setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service='mc', instance_configs={'grindah': { 'some': 'conf' }}, custom_resources=mock_custom_resources, kind=mock_kind, version='v1', group='yelp.com', ) mock_create_custom_resource.assert_called_with( kube_client=mock_client, version='v1', kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group='yelp.com', ) # instance not exist, create but error with k8s mock_create_custom_resource.side_effect = Exception assert not setup_kubernetes_cr.reconcile_kubernetes_resource( kube_client=mock_client, service='mc', instance_configs={'grindah': { 'some': 'conf' }}, custom_resources=mock_custom_resources, kind=mock_kind, version='v1', group='yelp.com', ) mock_create_custom_resource.assert_called_with( kube_client=mock_client, version='v1', kind=mock_kind, formatted_resource=mock_format_custom_resource.return_value, group='yelp.com', )
def reconcile_kubernetes_resource( kube_client: KubeClient, service: str, instance_configs: Mapping[str, Any], custom_resources: Sequence[KubeCustomResource], kind: KubeKind, version: str, group: str, cluster: str, instance: str = None, ) -> bool: results = [] for inst, config in instance_configs.items(): if instance is not None and instance != inst: continue formatted_resource = format_custom_resource( instance_config=config, service=service, instance=inst, cluster=cluster, kind=kind.singular, version=version, group=group, namespace=f"paasta-{kind.plural}", ) desired_resource = KubeCustomResource( service=service, instance=inst, config_sha=formatted_resource["metadata"]["labels"] ["paasta.yelp.com/config_sha"], kind=kind.singular, name=formatted_resource["metadata"]["name"], namespace=f"paasta-{kind.plural}", ) try: if not (service, inst, kind.singular) in [ (c.service, c.instance, c.kind) for c in custom_resources ]: log.info(f"{desired_resource} does not exist so creating") create_custom_resource( kube_client=kube_client, version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) elif desired_resource not in custom_resources: sanitised_service = sanitise_kubernetes_name(service) sanitised_instance = sanitise_kubernetes_name(inst) log.info( f"{desired_resource} exists but config_sha doesn't match") update_custom_resource( kube_client=kube_client, name=f"{sanitised_service}-{sanitised_instance}", version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) else: log.info(f"{desired_resource} is up to date, no action taken") except Exception as e: log.error(str(e)) results.append(False) results.append(True) return all(results) if results else True
def reconcile_kubernetes_resource( kube_client: KubeClient, service: str, instance_configs: Mapping[str, Any], custom_resources: Sequence[KubeCustomResource], kind: KubeKind, version: str, group: str, crd: CustomResourceDefinition, cluster: str, instance: str = None, ) -> bool: succeeded = True config_handler = LONG_RUNNING_INSTANCE_TYPE_HANDLERS[crd.file_prefix] for inst, config in instance_configs.items(): if instance is not None and instance != inst: continue try: soa_config = config_handler.loader( service=service, instance=inst, cluster=cluster, load_deployments=True, soa_dir=DEFAULT_SOA_DIR, ) git_sha = get_git_sha_from_dockerurl(soa_config.get_docker_url(), long=True) formatted_resource = format_custom_resource( instance_config=config, service=service, instance=inst, cluster=cluster, kind=kind.singular, version=version, group=group, namespace=f"paasta-{kind.plural}", git_sha=git_sha, ) desired_resource = KubeCustomResource( service=service, instance=inst, config_sha=formatted_resource["metadata"]["labels"][ paasta_prefixed("config_sha")], git_sha=formatted_resource["metadata"]["labels"].get( paasta_prefixed("git_sha")), kind=kind.singular, name=formatted_resource["metadata"]["name"], namespace=f"paasta-{kind.plural}", ) if not (service, inst, kind.singular) in [ (c.service, c.instance, c.kind) for c in custom_resources ]: log.info(f"{desired_resource} does not exist so creating") create_custom_resource( kube_client=kube_client, version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) elif desired_resource not in custom_resources: sanitised_service = sanitise_kubernetes_name(service) sanitised_instance = sanitise_kubernetes_name(inst) log.info( f"{desired_resource} exists but config_sha doesn't match") update_custom_resource( kube_client=kube_client, name=f"{sanitised_service}-{sanitised_instance}", version=version, kind=kind, formatted_resource=formatted_resource, group=group, ) else: log.info(f"{desired_resource} is up to date, no action taken") except Exception as e: log.error(str(e)) succeeded = False return succeeded