def _find_or_create_cluster_resources_for_cases(self, cases_dict, api: k8s.client.CoreV1Api): resolved_cases = {} from_host_mappings = {} to_host_mappings = {} port_mappings = {} for from_host_string, target_dict in cases_dict.items(): from_host = Host.from_identifier(from_host_string) self.logger.debug("Searching pod for host %s", from_host) if not isinstance(from_host, (ClusterHost, GenericClusterHost)): raise ValueError( "Only ClusterHost and GenericClusterHost fromHosts are supported by this Orchestrator" ) namespaces_for_host = self._find_or_create_namespace_for_host( from_host, api) from_host = ClusterHost(namespaces_for_host[0].metadata.name, from_host.pod_labels) self.logger.debug("Updated fromHost with found namespace: %s", from_host) pods_for_host = [ pod for pod in self._current_pods if from_host.matches(pod) ] # create pod if none for fromHost is in cluster (and add it to podsForHost) if not pods_for_host: self.logger.debug("Creating dummy pod for host %s", from_host) additional_labels = { ROLE_LABEL: "from_host_dummy", CLEANUP_LABEL: CLEANUP_ALWAYS, } # TODO replace 'dummy' with a more suitable name to prevent potential conflicts container = k8s.client.V1Container( image=self.oci_images["target"], name="dummy") dummy = create_pod_manifest(from_host, additional_labels, f"{PROJECT_PREFIX}-dummy-", container) resp = api.create_namespaced_pod(dummy.metadata.namespace, dummy) if isinstance(resp, k8s.client.V1Pod): self.logger.debug("Dummy pod %s created succesfully", resp.metadata.name) pods_for_host = [resp] self._current_pods.append(resp) else: self.logger.error("Failed to create dummy pod! Resp: %s", resp) else: self.logger.debug("Pods matching %s already exist: ", from_host, pods_for_host) # resolve target names for fromHost and add them to resolved cases dict pod_identifier = "%s:%s" % ( pods_for_host[0].metadata.namespace, pods_for_host[0].metadata.name, ) self.logger.debug("Mapped pod_identifier: %s", pod_identifier) from_host_mappings[from_host_string] = pod_identifier ( names_per_host, port_names_per_host, ) = self._get_target_names_creating_them_if_missing( target_dict, api) to_host_mappings[from_host_string] = names_per_host port_mappings[from_host_string] = port_names_per_host resolved_cases[pod_identifier] = { names_per_host[t]: [port_names_per_host[t][p] for p in target_dict[t]] for t in target_dict } return resolved_cases, from_host_mappings, to_host_mappings, port_mappings
def _find_or_create_cluster_resources_for_cases(self, cases_dict, api: k8s.client.CoreV1Api): resolved_cases = {} from_host_mappings = {} to_host_mappings = {} port_mappings = {} for from_host_string, target_dict in cases_dict.items(): from_host = Host.from_identifier(from_host_string) logger.debug("Searching pod for host " + str(from_host)) if not (isinstance(from_host, ClusterHost) or isinstance(from_host, GenericClusterHost)): raise ValueError( "Only ClusterHost and GenericClusterHost fromHosts are supported by this Orchestrator" ) namespaces_for_host = self._find_or_create_namespace_for_host( from_host, api) from_host = ClusterHost(namespaces_for_host[0].metadata.name, from_host.pod_labels) logger.debug("Updated fromHost with found namespace: " + str(from_host)) pods_for_host = [ pod for pod in self._current_pods if from_host.matches(pod) ] # create pod if none for fromHost is in cluster (and add it to podsForHost) if not pods_for_host: logger.debug("Creating dummy pod for host " + str(from_host)) additional_labels = { ROLE_LABEL: "from_host_dummy", CLEANUP_LABEL: CLEANUP_ALWAYS } container = k8s.client.V1Container(image="nginx:stable", name="dummy") dummy = init_pod(from_host, additional_labels, PROJECT_PREFIX + "-dummy-", container) resp = api.create_namespaced_pod(dummy.metadata.namespace, dummy) if isinstance(resp, k8s.client.V1Pod): logger.debug("Dummy pod " + resp.metadata.name + " created succesfully") pods_for_host = [resp] self._current_pods.append(resp) else: logger.error("Failed to create dummy pod! Resp: " + str(resp)) else: logger.debug("Pods matching " + str(from_host) + " already exist: " + str(pods_for_host)) # resolve target names for fromHost and add them to resolved cases dict pod_identifier = pods_for_host[ 0].metadata.namespace + ":" + pods_for_host[0].metadata.name logger.debug("Mapped pod_identifier: " + str(pod_identifier)) from_host_mappings[from_host_string] = pod_identifier names_per_host, port_names_per_host = self._get_target_names_creating_them_if_missing( target_dict, api) to_host_mappings[from_host_string] = names_per_host port_mappings[from_host_string] = port_names_per_host resolved_cases[pod_identifier] = { names_per_host[t]: [port_names_per_host[t][p] for p in target_dict[t]] for t in target_dict } return resolved_cases, from_host_mappings, to_host_mappings, port_mappings
def _get_target_names_creating_them_if_missing(self, target_dict, api: k8s.client.CoreV1Api): service_names_per_host = {} port_dict_per_host = {} for host_string in target_dict.keys(): host = Host.from_identifier(host_string) if isinstance(host, GenericClusterHost): self.logger.debug( "Found GenericClusterHost %s," "Rewriting it to a ClusterHost in default namespace now.", host, ) host = ClusterHost("default", host.pod_labels) if not isinstance(host, ClusterHost): raise ValueError( "Only ClusterHost targets are supported by this Orchestrator." " Host: %s, hostString: %s" % (host, host_string)) self.logger.debug("Searching service for host %s", host) services_for_host = [ svc for svc in self._current_services if host.matches(svc) ] self.logger.debug( "Found services %s for host %s ", [svc.metadata for svc in services_for_host], host, ) rewritten_ports = self._rewrite_ports_for_host( target_dict[host_string], services_for_host) self.logger.debug("Rewritten ports: %s", rewritten_ports) port_dict_per_host[host_string] = rewritten_ports if not services_for_host: gen_name = "%s-test-target-pod-" % PROJECT_PREFIX target_container = k8s.client.V1Container( image=self.oci_images["target"], name="runner") pod_labels_tuple = (ROLE_LABEL, "test_target_pod") target_pod = create_pod_manifest( host=host, additional_labels={ pod_labels_tuple[0]: pod_labels_tuple[1], CLEANUP_LABEL: CLEANUP_ALWAYS, }, generate_name=gen_name, container=target_container, ) target_ports = [ int(port.replace("-", "")) for port in port_dict_per_host[host_string].values() ] svc = create_service_manifest( host, {pod_labels_tuple[0]: pod_labels_tuple[1]}, { ROLE_LABEL: "test_target_svc", CLEANUP_LABEL: CLEANUP_ALWAYS }, target_ports, ) target_pod_namespace = host.namespace resp = api.create_namespaced_pod( namespace=target_pod_namespace, body=target_pod) if isinstance(resp, k8s.client.V1Pod): self.logger.debug("Target pod %s created succesfully", resp.metadata.name) self._current_pods.append(resp) else: self.logger.error("Failed to create pod! Resp: %s", resp) resp = api.create_namespaced_service(namespace=host.namespace, body=svc) if isinstance(resp, k8s.client.V1Service): service_names_per_host[host_string] = resp.spec.cluster_ip self.logger.debug("Target svc %s created succesfully", resp.metadata.name) self._current_services.append(resp) else: self.logger.error("Failed to create target svc! Resp: %s", resp) else: service_names_per_host[host_string] = services_for_host[ 0].spec.cluster_ip return service_names_per_host, port_dict_per_host
def _get_target_names_creating_them_if_missing(self, target_dict, api: k8s.client.CoreV1Api): svc_names_per_host = {} port_dict_per_host = {} for host_string in target_dict.keys(): host = Host.from_identifier(host_string) if isinstance(host, GenericClusterHost): logger.debug( "Found GenericClusterHost " + str(host) + ". Rewriting it to a ClusterHost in default namespace now." ) host = ClusterHost("default", host.pod_labels) if not isinstance(host, ClusterHost): raise ValueError( "Only ClusterHost targets are supported by this Orchestrator. Host: " + str(host) + ", hostString: " + host_string) logger.debug("Searching service for host " + str(host)) services_for_host = [ svc for svc in self._current_services if host.matches(svc) ] logger.debug("Found services {} for host {} ".format( [svc.metadata for svc in services_for_host], host)) rewritten_ports = self._rewrite_ports_for_host( target_dict[host_string], services_for_host) logger.debug("Rewritten ports: " + str(rewritten_ports)) port_dict_per_host[host_string] = rewritten_ports if not services_for_host: gen_name = PROJECT_PREFIX + "-test-target-pod-" target_container = k8s.client.V1Container( image=self.target_image, name="runner") pod_labels_tuple = (ROLE_LABEL, "test_target_pod") target_pod = init_pod(host=host, additional_labels={ pod_labels_tuple[0]: pod_labels_tuple[1], CLEANUP_LABEL: CLEANUP_ALWAYS }, generate_name=gen_name, container=target_container) target_ports = [ int(port.replace("-", "")) for port in port_dict_per_host[host_string].values() ] # ToDo we should use the cluser ip instead of the DNS names # so we don't need the lookups svc_name = "svc-" + convert_to_resource_name( host.to_identifier()) svc = init_svc(host, {pod_labels_tuple[0]: pod_labels_tuple[1]}, { ROLE_LABEL: "test_target_svc", CLEANUP_LABEL: CLEANUP_ALWAYS }, svc_name, target_ports) target_pod_namespace = host.namespace svc_names_per_host[ host_string] = target_pod_namespace + ":" + svc_name resp = api.create_namespaced_pod( namespace=target_pod_namespace, body=target_pod) if isinstance(resp, k8s.client.V1Pod): logger.debug("Target pod " + resp.metadata.name + " created succesfully") self._current_pods.append(resp) else: logger.error("Failed to create pod! Resp: " + str(resp)) resp = api.create_namespaced_service(namespace=host.namespace, body=svc) if isinstance(resp, k8s.client.V1Service): logger.debug("Target svc " + resp.metadata.name + " created succesfully") self._current_services.append(resp) else: logger.error("Failed to create target svc! Resp: " + str(resp)) else: svc_names_per_host[host_string] = services_for_host[ 0].metadata.namespace + ":" + services_for_host[ 0].metadata.name return svc_names_per_host, port_dict_per_host