def _build_smartstack_location_dict( synapse_host: str, synapse_port: int, synapse_haproxy_url_format: str, registration: str, pods: Iterable[V1Pod], location: str, should_return_individual_backends: bool, ) -> MutableMapping[str, Any]: sorted_backends = sorted( smartstack_tools.get_backends( registration, synapse_host=synapse_host, synapse_port=synapse_port, synapse_haproxy_url_format=synapse_haproxy_url_format, ), key=lambda backend: backend["status"], reverse=True, # put 'UP' backends above 'MAINT' backends ) matched_backends_and_pods = match_backends_and_pods(sorted_backends, pods) location_dict = smartstack_tools.build_smartstack_location_dict( location, matched_backends_and_pods, should_return_individual_backends ) return location_dict
def smartstack_status( service: str, instance: str, job_config: LongRunningServiceConfig, service_namespace_config: ServiceNamespaceConfig, pods: Sequence[V1Pod], settings: Any, should_return_individual_backends: bool = False, ) -> Mapping[str, Any]: registration = job_config.get_registrations()[0] instance_pool = job_config.get_pool() smartstack_replication_checker = KubeSmartstackReplicationChecker( nodes=kubernetes_tools.get_all_nodes(settings.kubernetes_client), system_paasta_config=settings.system_paasta_config, ) node_hostname_by_location = smartstack_replication_checker.get_allowed_locations_and_hosts( job_config ) expected_smartstack_count = marathon_tools.get_expected_instance_count_for_namespace( service=service, namespace=instance, cluster=settings.cluster, instance_type_class=KubernetesDeploymentConfig, ) expected_count_per_location = int( expected_smartstack_count / len(node_hostname_by_location) ) smartstack_status: MutableMapping[str, Any] = { "registration": registration, "expected_backends_per_location": expected_count_per_location, "locations": [], } for location, hosts in node_hostname_by_location.items(): synapse_host = smartstack_replication_checker.get_first_host_in_pool( hosts, instance_pool ) sorted_backends = sorted( smartstack_tools.get_backends( registration, synapse_host=synapse_host, synapse_port=settings.system_paasta_config.get_synapse_port(), synapse_haproxy_url_format=settings.system_paasta_config.get_synapse_haproxy_url_format(), ), key=lambda backend: backend["status"], reverse=True, # put 'UP' backends above 'MAINT' backends ) matched_backends_and_pods = match_backends_and_pods(sorted_backends, pods) location_dict = smartstack_tools.build_smartstack_location_dict( location, matched_backends_and_pods, should_return_individual_backends ) smartstack_status["locations"].append(location_dict) return smartstack_status
def test_match_backends_and_pods(): backends = [ { "pxname": "servicename.main", "svname": "10.50.2.4:31000_box4", "status": "UP", }, { "pxname": "servicename.main", "svname": "10.50.2.5:31000_box5", "status": "UP", }, { "pxname": "servicename.main", "svname": "10.50.2.6:31000_box6", "status": "UP", }, { "pxname": "servicename.main", "svname": "10.50.2.8:31000_box8", "status": "UP", }, ] good_pod1 = mock.Mock(status=mock.Mock(pod_ip="10.50.2.4")) good_pod2 = mock.Mock(status=mock.Mock(pod_ip="10.50.2.5")) bad_pod = mock.Mock(status=mock.Mock(pod_ip="10.50.2.7")) pods = [good_pod1, good_pod2, bad_pod] expected = [ (backends[0], good_pod1), (backends[1], good_pod2), (None, bad_pod), (backends[2], None), (backends[3], None), ] actual = match_backends_and_pods(backends, pods) def keyfunc(t): return tuple(sorted((t[0] or {}).items())), t[1] assert sorted(actual, key=keyfunc) == sorted(expected, key=keyfunc)