def test_createService(self, client_mock): service = KubernetesService() client_mock.reset_mock() client_mock.CoreV1Api.return_value.create_namespaced_service.return_value = V1Service( kind="unit") expected_body = V1Service(metadata=self._createMeta(self.name), spec=V1ServiceSpec( cluster_ip="None", ports=[ V1ServicePort(name='mongod', port=27017, protocol='TCP') ], selector={ 'heritage': 'mongos', 'name': self.name, 'operated-by': 'operators.ultimaker.com' }, )) expected_calls = [ call.CoreV1Api().create_namespaced_service(self.namespace, expected_body) ] result = service.createService(self.cluster_object) self.assertEqual(expected_calls, client_mock.mock_calls) self.assertEqual(V1Service(kind="unit"), result)
def test_createService(self, client_mock): service = KubernetesService() client_mock.reset_mock() client_mock.CoreV1Api.return_value.create_namespaced_service.return_value = V1Service( kind="unit") expected_body = V1Service(metadata=self._createMeta(self.name), spec=V1ServiceSpec( cluster_ip="None", ports=[ V1ServicePort(name="mongod", port=27017, protocol="TCP") ], selector={ "heritage": "mongos", "name": self.name, "operated-by": "operators.javamachr.cz" }, )) expected_calls = [ call.CoreV1Api().create_namespaced_service(self.namespace, expected_body) ] result = service.createService(self.cluster_object) self.assertEqual(expected_calls, client_mock.mock_calls) self.assertEqual(V1Service(kind="unit"), result)
def create_service( self, service_name: str, namespace: str, port: int = 80, protocol: str = 'TCP', service_type: str = 'LoadBalancer', target_port: int = 8080, ): self.core_api.create_namespaced_service( namespace=namespace, body=V1Service( kind='Service', metadata=V1ObjectMeta(name=service_name, ), spec=V1ServiceSpec( type=service_type, ports=[ V1ServicePort(protocol=protocol, port=port, target_port=target_port), ], selector={'app': service_name}, session_affinity='None', ), ))
def test_updateService(self, client_mock): service = KubernetesService() client_mock.reset_mock() expected_body = V1Service(metadata=self._createMeta(self.name), spec=V1ServiceSpec( cluster_ip="None", ports=[ V1ServicePort(name="mongod", port=27017, protocol="TCP") ], selector={ "heritage": "mongos", "name": self.name, "operated-by": "operators.ultimaker.com" }, )) result = service.updateService(self.cluster_object) expected_calls = [ call.CoreV1Api().patch_namespaced_service(self.name, self.namespace, expected_body) ] self.assertEqual(expected_calls, client_mock.mock_calls) self.assertEqual( client_mock.CoreV1Api().patch_namespaced_service.return_value, result)
def hub_pod_ssl(kube_client, kube_ns, ssl_app): """Start a hub pod with internal_ssl enabled""" # load ssl dir to tarfile buf = io.BytesIO() tf = tarfile.TarFile(fileobj=buf, mode="w") tf.add(ssl_app.internal_certs_location, arcname="internal-ssl", recursive=True) # store tarfile in a secret b64_certs = base64.b64encode(buf.getvalue()).decode("ascii") secret_name = "hub-ssl-secret" secret_manifest = V1Secret( metadata={"name": secret_name}, data={"internal-ssl.tar": b64_certs} ) create_resource(kube_client, kube_ns, "secret", secret_manifest) name = "hub-ssl" service_manifest = V1Service( metadata=dict(name=name), spec=V1ServiceSpec( type="ClusterIP", ports=[V1ServicePort(port=8081, target_port=8081)], selector={"hub-name": name}, ), ) create_resource(kube_client, kube_ns, "service", service_manifest) return create_hub_pod( kube_client, kube_ns, pod_name=name, ssl=True, )
def get_reference_object(self) -> V1Service: """Get deployment object for outpost""" meta = self.get_object_meta(name=self.name) ports = [] for port in self.controller.deployment_ports: ports.append( V1ServicePort( name=port.name, port=port.port, protocol=port.protocol.upper(), target_port=port.inner_port or port.port, )) if self.is_embedded: selector_labels = { "app.kubernetes.io/name": "authentik", "app.kubernetes.io/component": "server", } else: selector_labels = DeploymentReconciler( self.controller).get_pod_meta() return V1Service( metadata=meta, spec=V1ServiceSpec( ports=ports, selector=selector_labels, type=self.controller.outpost.config.kubernetes_service_type, ), )
def deploy(self): spec = V1ServiceSpec(selector=self.selector, type=self.service_type, ports=self.ports) body = V1Service(metadata=self.meta, spec=spec) return k8sclient.apiV1.create_namespaced_service( self.meta.namespace, body)
def __init__(self, api_client, name, app, port, namespace='default'): self.api = client.CoreV1Api(api_client) self.name = name self.namespace = namespace self._app = app self._port = port context = {'name': name, 'app': app, 'port': port} config = yaml.safe_load( self.generate_template('service.yaml.j2', context)) V1Service.__init__(self, api_version=config['apiVersion'], kind=config['kind'], metadata=config['metadata'], spec=config['spec'], status=None)
def service_definition(self): return V1Service(metadata=V1ObjectMeta(name=self.name, namespace=self.namespace), spec=V1ServiceSpec( ports=self.ports_to_expose, publish_not_ready_addresses=True, session_affinity=None, type='LoadBalancer', selector={self.selector_key: self.selector_value}))
def __init__(self) -> None: service_port = V1ServicePort(name="sql", port=5432) self.service = V1Service( api_version="v1", kind="Service", metadata=V1ObjectMeta(name="postgres", labels={"app": "postgres"}), spec=V1ServiceSpec( type="NodePort", ports=[service_port], selector={"app": "postgres"} ), )
def __init__(self) -> None: ports = [ V1ServicePort(name="kafka", port=9092), V1ServicePort(name="schema-registry", port=8081), ] self.service = V1Service( metadata=V1ObjectMeta(name="redpanda", labels={"app": "redpanda"}), spec=V1ServiceSpec( type="NodePort", ports=ports, selector={"app": "redpanda"} ), )
def ensure_ingress_routed_svc(api_core_v1: client.CoreV1Api, api_custom: client.CustomObjectsApi, domain, hostname, name, target_name, namespace, port_name, svc_port, target_port): ensure_service(api=api_core_v1, service=V1Service(api_version="v1", metadata=V1ObjectMeta(name=name), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort( protocol='TCP', port=svc_port, name=port_name, target_port=target_port), ], selector={'app': target_name})), name=name, namespace=namespace) ensure_custom_object(api=api_custom, custom_object={ 'apiVersion': 'traefik.containo.us/v1alpha1', 'kind': 'IngressRoute', 'metadata': { 'name': name, }, 'spec': { 'entryPoints': ['websecure'], 'routes': [{ 'match': f'Host(`{hostname}.{domain}`)', 'kind': 'Rule', 'services': [{ 'name': name, 'port': svc_port }], 'middlewares': [{ 'name': 'traefik-forward-auth', 'namespace': 'default' }] }], 'tls': { 'certResolver': 'default' } } }, group='traefik.containo.us', plural='ingressroutes', version='v1alpha1', name=hostname, namespace=namespace)
def test_delete_cate_with_prune(self, namespace_p, get_p, list_p, service_p): get_p.return_value = None list_p.return_value = V1ServiceList(items=[]) res = cate.delete_cate('drwho', prune=True) list_p.assert_called_once() self.assertTrue(res) list_p.return_value = V1ServiceList( items=[V1Service(metadata=V1ObjectMeta(name='drwho-cate'))]) res = cate.delete_cate('drwho', prune=True) service_p.assert_called_once() self.assertTrue(res)
def create_gluster_service(self, v1_api, namespace_name): service = V1Service() service.api_version = "v1" service.kind = "Service" meta = V1ObjectMeta() meta.generate_name = "gluster-service" service.metadata = meta service_spec = V1ServiceSpec() service_port = V1ServicePort(port=5) service_spec.ports = [service_port] service.spec = service_spec api_response = v1_api.create_namespaced_service( namespace=namespace_name, body=service) return api_response.metadata.name
def create_service(self, namespace, name, selector, port, protocol="TCP", service_type="ClusterIP"): metadata = V1ObjectMeta(name=name, namespace=namespace) port = V1ServicePort(name=name, port=port, protocol=protocol) spec = V1ServiceSpec(selector=selector, type=service_type, ports=[port]) body = V1Service(metadata=metadata, spec=spec) return self.apiV1.create_namespaced_service(namespace, body)
def deploy(self, force=False): spec = V1ServiceSpec(selector=self.selector, type=self.service_type, ports=self.ports) body = V1Service(metadata=self.meta, spec=spec) try: k8sclient.apiV1.create_namespaced_service(self.meta.namespace, body) except ApiException as e: if e.status != 409 or not force: raise e k8sclient.remove_service(self.meta.namespace, self.meta.name) k8sclient.apiV1.create_namespaced_service(self.meta.namespace, body)
def generate_secrets_server_service( secrets_server_config: SecretsServerConfig, ): # We need to ensure that the labels and selectors match between the deployment and the service, # therefore we base them on the configured service name. service_name = secrets_server_config.service_name() selector = {'app': service_name} return V1Service( kind='Service', metadata=V1ObjectMeta(name=service_name, ), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(protocol='TCP', port=80, target_port=8080), ], selector=selector, session_affinity='None', ), )
def generate_delaying_proxy_service(): return V1Service( kind='Service', metadata=V1ObjectMeta( name='delaying-proxy-svc', labels={'app': 'delaying-proxy-svc'}, ), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(name='default', protocol='TCP', port=80, target_port=8080), ], selector={'app': 'delaying-proxy'}, session_affinity='None', ), )
def get_reference_object(self) -> V1Service: """Get deployment object for outpost""" meta = self.get_object_meta(name=self.name) ports = [] for port in self.controller.deployment_ports: ports.append( V1ServicePort( name=port.name, port=port.port, protocol=port.protocol.upper(), target_port=port.port, )) selector_labels = DeploymentReconciler(self.controller).get_pod_meta() return V1Service( metadata=meta, spec=V1ServiceSpec(ports=ports, selector=selector_labels, type="ClusterIP"), )
def _create(self, namespace, name, app_name, labels, ports, spec_type): """Create service. :param str namespace: :param str name: :param str app_name: :param dict labels: :param List[int] ports: :param str spec_type: :rtype: V1Service """ core_v1_api = self._clients.core_api annotations = {} # todo add annotations to services meta = V1ObjectMeta(name=name, labels=labels, annotations=annotations) service_ports = [] for port in ports: service_ports.append( V1ServicePort( name="port" + str(port), port=port, target_port=port, protocol="TCP" ) ) selector_tag = {TagsService.get_default_selector(app_name): app_name} if spec_type == "LoadBalancer": allowed_ips = None # todo - alexaz - add option to restrict source ips specs = V1ServiceSpec( ports=service_ports, selector=selector_tag, type=spec_type, load_balancer_source_ranges=allowed_ips, ) else: specs = V1ServiceSpec( ports=service_ports, selector=selector_tag, type=spec_type ) service = V1Service(metadata=meta, spec=specs) return core_v1_api.create_namespaced_service( namespace=namespace, body=service, pretty="true" )
def _create_kube_service(self, k8s_id, ports, namespace=KubernetesConfig.K8S_NAMESPACE): ''' :param ports: List of [[int targetport, int port]] to expose thru the service :return: Service object ''' name = k8s_id + "-service" serviceports = [] for portname, targetport, portnumber in ports: serviceports.append( V1ServicePort(name=portname, target_port=targetport, port=portnumber)) metadata = client.V1ObjectMeta(name=name, namespace=namespace) spec = V1ServiceSpec( selector={KubernetesConfig.K8S_LABELS_OPGUID: k8s_id}, ports=serviceports) service = V1Service(metadata=metadata, spec=spec) return service
def manage_service(self, logger): create_service = False try: service = core_v1_api.read_namespaced_service( self.deployment_name, self.deployment_namespace) except ApiException as e: if e.status == 404: create_service = True else: raise if create_service: logger.info( f"Creating Service {self.deployment_name} in {self.deployment_namespace}" ) service = core_v1_api.create_namespaced_service( self.deployment_namespace, V1Service( metadata=V1ObjectMeta( annotations={ owner_annotation: self.make_owner_annotation(), }, labels={owner_uid_label: self.uid}, name=self.deployment_name, ), spec=V1ServiceSpec( ports=[ V1ServicePort( name="10080-tcp", port=10080, protocol="TCP", target_port=10080, ) ], selector={"name": self.deployment_name}, type="ClusterIP", ), ), ) return service
def create_nifi_instances(api_apps_v1, api_core_v1, api_custom, domain): for instance in NifiInstance.objects.filter(state='PENDING_CREATE'): instance.state = 'CREATING' instance.save() port_name = 'web' instance.state = 'CREATE_FAILED' try: namespace = 'default' if instance.namespace is not None and instance.namespace != 'default': namespace = instance.namespace ensure_namespace(api_core_v1, namespace) else: instance.namespace = 'default' # deploy nifi nifi_volume_paths = [ ('db-repo', '/opt/nifi/nifi-current/database_repository', '20Gi', 'standard'), ('flowfile-repo', '/opt/nifi/nifi-current/flowfile_repository', '20Gi', 'standard'), ('provenance-repo', '/opt/nifi/nifi-current/provenance_repository', '20Gi', 'standard'), ('content-repo', '/opt/nifi/nifi-current/content_repository', '20Gi', 'standard'), ] ensure_statefulset_with_containers( api_apps_v1=api_apps_v1, name=instance.hostname, namespace=namespace, replicas=1, containers=[ V1Container(name='nifi', image=instance.image, env=[ V1EnvVar(name='NIFI_WEB_HTTP_HOST', value='0.0.0.0') ], ports=[V1ContainerPort(container_port=8080)], volume_mounts=[ V1VolumeMount(name=path[0], mount_path=path[1]) for path in nifi_volume_paths ]) ], init_containers=[ V1Container(name='init-permissions', image='busybox', command=[ 'sh', '-c', 'chown -R 1000:1000 /opt/nifi/nifi-current' ], volume_mounts=[ V1VolumeMount(name=path[0], mount_path=path[1]) for path in nifi_volume_paths ]) ], volume_paths=nifi_volume_paths) ensure_ingress_routed_svc(api_core_v1=api_core_v1, api_custom=api_custom, domain=domain, hostname=instance.hostname, name=instance.hostname, target_name=instance.hostname, namespace=namespace, port_name=port_name, svc_port=80, target_port=8080) # deploy mongo if instance.deploy_mongo: mongo_volume_paths = [ ('db', '/data/db', '20Gi', 'standard'), ] ensure_statefulset_with_containers( api_apps_v1=api_apps_v1, name='mongo', namespace=namespace, replicas=1, containers=[ V1Container( name='mongo', image='mongo', env=[ V1EnvVar(name='MONGO_INITDB_ROOT_USERNAME', value='admin'), V1EnvVar(name='MONGO_INITDB_ROOT_PASSWORD', value='admin') ], ports=[ V1ContainerPort(name='mongo', container_port=27017) ], volume_mounts=[ V1VolumeMount(name=path[0], mount_path=path[1]) for path in mongo_volume_paths ]) ], volume_paths=mongo_volume_paths) ensure_service(api=api_core_v1, service=V1Service( api_version="v1", metadata=V1ObjectMeta(name='mongo'), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(protocol='TCP', port=27017, name='mongo', target_port=27017), ], selector={'app': 'mongo'})), name='mongo', namespace=namespace) ensure_single_container_deployment( api_apps_v1, V1Container( name='mongo-express', image='mongo-express', env=[ V1EnvVar(name='ME_CONFIG_MONGODB_ADMINUSERNAME', value='admin'), V1EnvVar(name='ME_CONFIG_MONGODB_ADMINPASSWORD', value='admin') ], ports=[V1ContainerPort(container_port=8000)]), 'mongo-express', instance.namespace) ensure_ingress_routed_svc(api_core_v1=api_core_v1, api_custom=api_custom, domain=domain, hostname="mongo-" + instance.hostname, name="mongo-" + instance.hostname, target_name="mongo-express", namespace=namespace, port_name=port_name, svc_port=80, target_port=8081) if instance.deploy_kafka: # deploy zookeeper ensure_single_container_deployment( api_apps_v1, V1Container(name='zookeeper', image='wurstmeister/zookeeper', env=[], ports=[V1ContainerPort(container_port=2181)]), 'zookeeper', instance.namespace) ensure_service(api=api_core_v1, service=V1Service( api_version="v1", metadata=V1ObjectMeta(name='zookeeper'), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(protocol='TCP', port=2181, name='zookeeper', target_port=2181), ], selector={'app': 'zookeeper'})), name='zookeeper', namespace=namespace) # deploy kafka ensure_single_container_deployment( api_apps_v1, V1Container(name='kafka', image='wurstmeister/kafka', env=[ V1EnvVar(name='KAFKA_ADVERTISED_HOST_NAME', value='kafka'), V1EnvVar(name='KAFKA_ZOOKEEPER_CONNECT', value='zookeeper:2181'), V1EnvVar(name='KAFKA_PORT', value='9092') ], ports=[V1ContainerPort(container_port=9092)]), 'kafka', instance.namespace) ensure_service(api=api_core_v1, service=V1Service( api_version="v1", metadata=V1ObjectMeta(name='kafka'), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(protocol='TCP', port=9092, name='kafka', target_port=9092), ], selector={'app': 'kafka'})), name='kafka', namespace=namespace) if instance.deploy_prometheus: # deploy prometheus ensure_single_container_deployment( api_apps_v1, V1Container(name='prometheus', image='prom/prometheus', env=[], ports=[V1ContainerPort(container_port=9090)]), 'prometheus', instance.namespace) ensure_ingress_routed_svc(api_core_v1=api_core_v1, api_custom=api_custom, domain=domain, hostname="prometheus-" + instance.hostname, name="prometheus", target_name="prometheus", namespace=namespace, port_name=port_name, svc_port=9090, target_port=9090) if instance.deploy_jupyter: # deploy jupyter instance.jupyter_token = str(uuid.uuid1()) ensure_single_container_deployment( api_apps_v1, V1Container( name='jupyter', image='jupyter/datascience-notebook', command=[ 'start-notebook.sh', '--NotebookApp.token=' + instance.jupyter_token ], env=[], ports=[V1ContainerPort(container_port=8888)]), 'jupyter', instance.namespace) ensure_ingress_routed_svc(api_core_v1=api_core_v1, api_custom=api_custom, domain=domain, hostname="jupyter-" + instance.hostname, name="jupyter", target_name="jupyter", namespace=namespace, port_name=port_name, svc_port=8888, target_port=8888) # deploy custom instance types custom_instances = Instance.objects.filter(parent=instance) for ci in custom_instances: inst_type: InstanceType = ci.instance_type env_vars = [ V1EnvVar(name=e.name, value=e.default_value) for e in InstanceTypeEnvVar.objects.filter( instance_type=inst_type) ] ports = [ V1ContainerPort(container_port=p.internal) for p in InstanceTypePort.objects.filter( instance_type=inst_type) ] ensure_single_container_deployment( api_apps_v1, V1Container(name=inst_type.container_name, image=inst_type.image, env=env_vars, ports=ports), inst_type.container_name, instance.namespace) for svc in InstanceTypeIngressRoutedService.objects.filter( instance_type=inst_type): ensure_ingress_routed_svc( api_core_v1=api_core_v1, api_custom=api_custom, domain=domain, hostname=svc.service_name + '-' + instance.hostname, name=svc.service_name + '-' + instance.hostname, target_name=inst_type.container_name, namespace=namespace, port_name=port_name, svc_port=svc.svc_port, target_port=svc.target_port) instance.state = 'RUNNING' finally: instance.save()
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from pytest import raises, fixture from kubernetes.client import V1ObjectMeta, V1ServiceList, V1Service, V1ServiceSpec, V1ServicePort import util.k8s.kubectl as kubectl from util.app_names import NAUTAAppNames from util.exceptions import KubectlConnectionError, LocalPortOccupiedError, KubernetesError from cli_text_consts import UtilKubectlTexts as Texts SERVICES_LIST_MOCK = V1ServiceList(items=[ V1Service(metadata=V1ObjectMeta(name="service", namespace="namespace"), spec=V1ServiceSpec(ports=[V1ServicePort(port=5000, node_port=33451)])) ]).items TOP_RESULT_SUCCESS = "NAME CPU(cores) MEMORY(bytes)\nnauta-fluentd-hdr2p 9m 155Mi" TOP_RESULT_FAILURE = "NAME CPU(cores) MEMORY(bytes)\nnauta-fluentd-hdr2p 9m" @fixture def mock_k8s_svc(mocker): svcs_list_mock = mocker.patch('util.k8s.kubectl.get_app_services') svcs_list_mock.return_value = SERVICES_LIST_MOCK # noinspection PyUnusedLocal,PyShadowingNames def test_start_port_forwarding_success(mock_k8s_svc, mocker): subprocess_command_mock = mocker.patch('util.system.execute_subprocess_command')
def ensure_traefik(api_core_v1, api_ext_v1_beta1, api_apps_v1, api_custom, api_rbac_auth_v1_b1, admin_email, domain, static_ip, oauth_client_id, oauth_client_secret, oauth_domain, oauth_secret): ensure_crd(api=api_ext_v1_beta1, name='ingressroutes.traefik.containo.us', group='traefik.containo.us', kind='IngressRoute', plural='ingressroutes', singular='ingressroute', scope='Namespaced') ensure_crd(api=api_ext_v1_beta1, name='ingressroutetcps.traefik.containo.us', group='traefik.containo.us', kind='IngressRouteTCP', plural='ingressroutetcps', singular='ingressroutetcp', scope='Namespaced') ensure_crd(api=api_ext_v1_beta1, name='middlewares.traefik.containo.us', group='traefik.containo.us', kind='Middleware', plural='middlewares', singular='middleware', scope='Namespaced') ensure_crd(api=api_ext_v1_beta1, name='tlsoptions.traefik.containo.us', group='traefik.containo.us', kind='TLSOption', plural='tlsoptions', singular='tlsoption', scope='Namespaced') ensure_role(api=api_rbac_auth_v1_b1, role=V1ClusterRole( api_version='rbac.authorization.k8s.io/v1beta1', kind='ClusterRole', metadata=V1ObjectMeta(name='traefik-ingress-controller'), rules=[ V1PolicyRule( api_groups=[''], resources=['services', 'endpoints', 'secrets'], verbs=['get', 'list', 'watch']), V1PolicyRule(api_groups=['extensions'], resources=['ingresses'], verbs=['get', 'list', 'watch']), V1PolicyRule(api_groups=['extensions'], resources=['ingresses/status'], verbs=['update']), V1PolicyRule(api_groups=['traefik.containo.us'], resources=['middlewares'], verbs=['get', 'list', 'watch']), V1PolicyRule(api_groups=['traefik.containo.us'], resources=['ingressroutes'], verbs=['get', 'list', 'watch']), V1PolicyRule(api_groups=['traefik.containo.us'], resources=['ingressroutetcps'], verbs=['get', 'list', 'watch']), V1PolicyRule(api_groups=['traefik.containo.us'], resources=['tlsoptions'], verbs=['get', 'list', 'watch']) ]), name='traefik-ingress-controller') ensure_role_binding( api=api_rbac_auth_v1_b1, role_binding=V1ClusterRoleBinding( api_version='rbac.authorization.k8s.io/v1beta1', kind='ClusterRoleBinding', metadata=V1ObjectMeta(name='traefik-ingress-controller'), role_ref=V1RoleRef(api_group='rbac.authorization.k8s.io', kind='ClusterRole', name='traefik-ingress-controller'), subjects=[ V1Subject(kind='ServiceAccount', name='traefik-ingress-controller', namespace='default') ]), name='traefik-ingress-controller') ensure_service( api=api_core_v1, service=V1Service( api_version="v1", metadata=V1ObjectMeta(name='traefik'), spec=V1ServiceSpec( type='LoadBalancer', load_balancer_ip=static_ip, ports=[ # V1ServicePort( # protocol='TCP', # port=80, # name='web' # ), V1ServicePort(protocol='TCP', port=443, name='websecure'), ], selector={'app': 'traefik'})), name='traefik', namespace='default') ensure_service_account( api=api_core_v1, account=V1ServiceAccount( api_version="v1", metadata=V1ObjectMeta(name='traefik-ingress-controller'), ), name='traefik-ingress-controller', namespace='default') ensure_deployment( api=api_apps_v1, deployment=V1Deployment( api_version="apps/v1", metadata=V1ObjectMeta(name='traefik', labels={'app': 'traefik'}), spec=V1DeploymentSpec( replicas=1, selector=V1LabelSelector(match_labels={'app': 'traefik'}), template=V1PodTemplateSpec( metadata=V1ObjectMeta(name='traefik', labels={'app': 'traefik'}), spec=V1PodSpec( service_account_name='traefik-ingress-controller', containers=[ V1Container( name='traefik', image='traefik:v2.0', args=[ '--api.insecure', '--accesslog', '--entrypoints.web.Address=:80', '--entrypoints.websecure.Address=:443', '--providers.kubernetescrd', '--certificatesresolvers.default.acme.tlschallenge', f'--certificatesresolvers.default.acme.email={admin_email}', '--certificatesresolvers.default.acme.storage=acme.json', # '--certificatesresolvers.default.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory', ], ports=[ V1ContainerPort(name='web', container_port=8000), V1ContainerPort(name='websecure', container_port=4443), V1ContainerPort(name='admin', container_port=8080), ]) ])))), name='traefik', namespace='default') ensure_deployment( api=api_apps_v1, deployment=V1Deployment( api_version="apps/v1", metadata=V1ObjectMeta(name='traefik-forward-auth', labels={'app': 'traefik-forward-auth'}), spec=V1DeploymentSpec( replicas=1, selector=V1LabelSelector( match_labels={'app': 'traefik-forward-auth'}), template=V1PodTemplateSpec( metadata=V1ObjectMeta( name='traefik-forward-auth', labels={'app': 'traefik-forward-auth'}), spec=V1PodSpec(containers=[ V1Container( name='traefik-forward-auth', image='thomseddon/traefik-forward-auth:2', ports=[ V1ContainerPort(name='auth', container_port=4181), ], env=[ V1EnvVar(name='PROVIDERS_GOOGLE_CLIENT_ID', value=oauth_client_id), # V1EnvVar(name='LOG_LEVEL', value='trace'), V1EnvVar(name='PROVIDERS_GOOGLE_CLIENT_SECRET', value=oauth_client_secret), V1EnvVar(name='SECRET', value=oauth_secret), V1EnvVar(name='DOMAIN', value=oauth_domain), V1EnvVar(name='COOKIE_DOMAIN', value=domain), V1EnvVar(name='AUTH_HOST', value=f'auth.{domain}'), ]) ])))), name='traefik-forward-auth', namespace='default') ensure_custom_object(api=api_custom, custom_object={ 'apiVersion': 'traefik.containo.us/v1alpha1', 'kind': 'IngressRoute', 'metadata': { 'name': 'traefik-forward-auth', }, 'spec': { 'entryPoints': ['websecure'], 'routes': [{ 'match': f'Host(`auth.{domain}`)', 'kind': 'Rule', 'services': [{ 'name': 'traefik-forward-auth', 'port': 4181 }], 'middlewares': [{ 'name': 'traefik-forward-auth' }] }], 'tls': { 'certResolver': 'default' } } }, group='traefik.containo.us', plural='ingressroutes', version='v1alpha1', name='traefik-forward-auth', namespace='default') ensure_custom_object(api=api_custom, custom_object={ 'apiVersion': 'traefik.containo.us/v1alpha1', 'kind': 'Middleware', 'metadata': { 'name': 'traefik-forward-auth', }, 'spec': { 'forwardAuth': { 'address': 'http://traefik-forward-auth:4181', 'authResponseHeaders': ['X-Forwarded-User'], } } }, group='traefik.containo.us', plural='middlewares', version='v1alpha1', name='traefik-forward-auth', namespace='default') ensure_service(api=api_core_v1, service=V1Service( api_version="v1", metadata=V1ObjectMeta(name='traefik-forward-auth'), spec=V1ServiceSpec( type='ClusterIP', ports=[ V1ServicePort(protocol='TCP', port=4181, name='auth'), ], selector={'app': 'traefik-forward-auth'})), name='traefik-forward-auth', namespace='default') ensure_whoami(api_apps_v1, api_core_v1, api_custom, domain)
def start_stateful_container(self, service_name: str, container_name: str, spec, labels: dict[str, str], change_key: str): # Setup PVC deployment_name = self._dependency_name(service_name, container_name) mounts, volumes = [], [] for volume_name, volume_spec in spec.volumes.items(): mount_name = f'{deployment_name}-{volume_name}' # Check if the PVC exists, create if not self._ensure_pvc(mount_name, volume_spec.storage_class, volume_spec.capacity, deployment_name) # Create the volume info volumes.append(V1Volume( name=mount_name, persistent_volume_claim=V1PersistentVolumeClaimVolumeSource(mount_name) )) mounts.append(V1VolumeMount(mount_path=volume_spec.mount_path, name=mount_name)) # Read the key being used for the deployment instance or generate a new one instance_key = uuid.uuid4().hex try: old_deployment = self.apps_api.read_namespaced_deployment(deployment_name, self.namespace) for container in old_deployment.spec.template.spec.containers: for env in container.env: if env.name == 'AL_INSTANCE_KEY': instance_key = env.value break except ApiException as error: if error.status != 404: raise # Setup the deployment itself labels['container'] = container_name spec.container.environment.append({'name': 'AL_INSTANCE_KEY', 'value': instance_key}) self._create_deployment(service_name, deployment_name, spec.container, 30, 1, labels, volumes=volumes, mounts=mounts, core_mounts=spec.run_as_core, change_key=change_key) # Setup a service to direct to the deployment try: service = self.api.read_namespaced_service(deployment_name, self.namespace) service.metadata.labels = labels service.spec.selector = labels service.spec.ports = [V1ServicePort(port=int(_p)) for _p in spec.container.ports] self.api.patch_namespaced_service(deployment_name, self.namespace, service) except ApiException as error: if error.status != 404: raise service = V1Service( metadata=V1ObjectMeta(name=deployment_name, labels=labels), spec=V1ServiceSpec( cluster_ip='None', selector=labels, ports=[V1ServicePort(port=int(_p)) for _p in spec.container.ports] ) ) self.api.create_namespaced_service(self.namespace, service) # Add entries to the environment variable list to point to this container self._service_limited_env[service_name][f'{container_name}_host'] = deployment_name self._service_limited_env[service_name][f'{container_name}_key'] = instance_key if spec.container.ports: self._service_limited_env[service_name][f'{container_name}_port'] = spec.container.ports[0]
complex_job = Job( configuration_cls=AppConfiguration, objects=[ AppsV1beta1Deployment( metadata=V1ObjectMeta(name=AppConfiguration.name, ), spec=AppsV1beta1DeploymentSpec( replicas=2, template=V1PodTemplateSpec( metadata=V1ObjectMeta( name='pod-name', labels={ 'app': 'foo-app', }, ), spec=V1PodSpec(containers=[ V1Container( name='container-name', command=[ 'sh', '-c', 'while date; do sleep 1; done' ], image='busybox', ), ], ), ), ), ), V1Service(metadata=V1ObjectMeta(name=AppConfiguration.service_name, ), spec=V1ServiceSpec(selector={'app': 'foo-app'})) ])