def test_make_pod_with_extra_container_config(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', extra_container_config={ 'envFrom': [ { 'configMapRef': { 'name': 'special-config' } } ] } )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } }, 'envFrom': [ { 'configMapRef': { 'name': 'special-config' } } ] } ], 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_set_pod_uid_fs_gid(): """ Test specification of the simplest possible pod specification """ assert api_client.sanitize_for_serialization( make_pod( name='test', image_spec='jupyter/singleuser:latest', env={}, volumes=[], volume_mounts=[], cmd=['jupyterhub-singleuser'], working_dir=None, port=8888, cpu_limit=None, cpu_guarantee=None, mem_limit=None, mem_guarantee=None, node_selector=None, run_as_uid=1000, fs_gid=1000, image_pull_policy='IfNotPresent', image_pull_secret=None, labels={}, lifecycle_hooks=None, init_containers=None, )) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": { "runAsUser": 1000, "fsGroup": 1000 }, "containers": [{ "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } }], 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_env(): """ Test specification of a pod with custom environment variables """ assert api_client.sanitize_for_serialization( make_pod( name='test', image_spec='jupyter/singleuser:latest', env={'TEST_KEY': 'TEST_VALUE'}, volumes=[], volume_mounts=[], cmd=['jupyterhub-singleuser'], working_dir=None, port=8888, cpu_limit=None, cpu_guarantee=None, mem_limit=None, mem_guarantee=None, image_pull_policy='IfNotPresent', image_pull_secret=None, node_selector=None, run_as_uid=None, fs_gid=None, labels={}, lifecycle_hooks=None, init_containers=None, )) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "containers": [{ "env": [{ 'name': 'TEST_KEY', 'value': 'TEST_VALUE' }], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } }], 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_extra_pod_config(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', extra_pod_config={ 'tolerations': [ { 'key': 'dedicated', 'operator': 'Equal', 'value': 'notebook' } ] } )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True}], "resources": { "limits": { }, "requests": { } } } ], 'volumes': [{'name': 'no-api-access-please', 'emptyDir': {}}], 'tolerations': [ { 'key': 'dedicated', 'operator': 'Equal', 'value': 'notebook' } ] }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_node_affinity_preferred(): """ Test specification of the simplest possible pod specification with non-empty node_affinity_preferred """ node_affinity_preferred = [{ "weight": 1, "preference": { "matchExpressions": [{ "key": "hub.jupyter.org/node-purpose", "operator": "In", "values": ["user"], }], } }] assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', node_affinity_preferred=node_affinity_preferred )) == { "metadata": { "name": "test", "labels": {}, "annotations": {} }, "spec": { "automountServiceAccountToken": False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', "volumes": [], "affinity": { "nodeAffinity": { "preferredDuringSchedulingIgnoredDuringExecution": node_affinity_preferred } } }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_pod_anti_affinity_required(): """ Test specification of the simplest possible pod specification with non-empty pod_anti_affinity_required """ pod_anti_affinity_required = [{ "labelSelector": { "matchExpressions": [{ "key": "security", "operator": "In", "values": ["S1"], }] }, "topologyKey": "failure-domain.beta.kubernetes.io/zone" }] assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', pod_anti_affinity_required=pod_anti_affinity_required )) == { "metadata": { "name": "test", "labels": {}, "annotations": {} }, "spec": { "automountServiceAccountToken": False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', "volumes": [], "affinity": { "podAntiAffinity": { "requiredDuringSchedulingIgnoredDuringExecution": pod_anti_affinity_required } } }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_lifecycle(): """ Test specification of a pod with lifecycle """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', lifecycle_hooks={ 'preStop': { 'exec': { 'command': ['/bin/sh', 'test'] } } } )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } }, "lifecycle": { "preStop": { "exec": { "command": ["/bin/sh", "test"] } } } } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_extra_resources(): """ Test specification of extra resources (like GPUs) """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cpu_limit=2, cpu_guarantee=1, extra_resource_limits={"nvidia.com/gpu": "5", "k8s.io/new-resource": "1"}, extra_resource_guarantees={"nvidia.com/gpu": "3"}, cmd=['jupyterhub-singleuser'], port=8888, mem_limit='1Gi', mem_guarantee='512Mi', image_pull_policy='IfNotPresent', image_pull_secret="myregistrykey", node_selector={"disk": "ssd"} )) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "imagePullSecrets": [{"name": "myregistrykey"}], "nodeSelector": {"disk": "ssd"}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True}], "resources": { "limits": { "cpu": 2, "memory": '1Gi', "nvidia.com/gpu": "5", "k8s.io/new-resource": "1" }, "requests": { "cpu": 1, "memory": '512Mi', "nvidia.com/gpu": "3" } } } ], 'volumes': [{'name': 'no-api-access-please', 'emptyDir': {}}], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_tolerations(): """ Test specification of the simplest possible pod specification with non-empty tolerations """ tolerations = [ { 'key': 'hub.jupyter.org/dedicated', 'operator': 'Equal', 'value': 'user', 'effect': 'NoSchedule' }, { 'key': 'key', 'operator': 'Exists', 'effect': 'NoSchedule' } ] assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', tolerations=tolerations )) == { "metadata": { "name": "test", "labels": {}, "annotations": {} }, "spec": { "automountServiceAccountToken": False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', 'volumes': [], 'tolerations': tolerations }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_resources_all(): """ Test specifying all possible resource limits & guarantees """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cpu_limit=2, cpu_guarantee=1, cmd=['jupyterhub-singleuser'], port=8888, mem_limit='1Gi', mem_guarantee='512Mi', image_pull_policy='IfNotPresent', image_pull_secret="myregistrykey", node_selector={"disk": "ssd"} )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "imagePullSecrets": [{"name": "myregistrykey"}], "nodeSelector": {"disk": "ssd"}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { "cpu": 2, "memory": '1Gi' }, "requests": { "cpu": 1, "memory": '512Mi' } } } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_set_pod_supplemental_gids(): """ Test specification of the simplest possible pod specification """ assert api_client.sanitize_for_serialization( make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, run_as_uid=1000, supplemental_gids=[100], image_pull_policy='IfNotPresent')) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": { "runAsUser": 1000, "supplementalGroups": [100] }, 'automountServiceAccountToken': False, "containers": [{ "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{ 'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True }], "resources": { "limits": {}, "requests": {} } }], 'volumes': [{ 'name': 'no-api-access-please', 'emptyDir': {} }], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_extra_containers(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', extra_containers=[ { 'name': 'crontab', 'image': 'supercronic', 'command': ['/usr/local/bin/supercronic', '/etc/crontab'] } ] )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } }, }, { 'name': 'crontab', 'image': 'supercronic', 'command': ['/usr/local/bin/supercronic', '/etc/crontab'] } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def get_pod_manifest(self): """ Make a pod manifest that will spawn current user's notebook pod. """ if callable(self.singleuser_uid): singleuser_uid = yield gen.maybe_future(self.singleuser_uid(self)) else: singleuser_uid = self.singleuser_uid if callable(self.singleuser_fs_gid): singleuser_fs_gid = yield gen.maybe_future( self.singleuser_fs_gid(self)) else: singleuser_fs_gid = self.singleuser_fs_gid if self.cmd: real_cmd = self.cmd + self.get_args() else: real_cmd = None # Default set of labels, picked up from # https://github.com/kubernetes/helm/blob/master/docs/chart_best_practices/labels.md labels = { 'heritage': 'jupyterhub', 'component': 'singleuser-server', 'app': 'jupyterhub', 'hub.jupyter.org/username': escapism.escape(self.user.name) } if self.name: # FIXME: Make sure this is dns safe? labels['hub.jupyter.org/servername'] = self.name labels.update(self._expand_all(self.singleuser_extra_labels)) return make_pod(name=self.pod_name, cmd=real_cmd, port=self.port, image_spec=self.singleuser_image_spec, image_pull_policy=self.singleuser_image_pull_policy, image_pull_secret=self.singleuser_image_pull_secrets, node_selector=self.singleuser_node_selector, run_as_uid=singleuser_uid, fs_gid=singleuser_fs_gid, run_privileged=self.singleuser_privileged, env=self.get_env(), volumes=self._expand_all(self.volumes), volume_mounts=self._expand_all(self.volume_mounts), working_dir=self.singleuser_working_dir, labels=labels, cpu_limit=self.cpu_limit, cpu_guarantee=self.cpu_guarantee, mem_limit=self.mem_limit, mem_guarantee=self.mem_guarantee, lifecycle_hooks=self.singleuser_lifecycle_hooks, init_containers=self.singleuser_init_containers, service_account=self.singleuser_service_account)
def test_make_pod_with_lifecycle(): """ Test specification of a pod with lifecycle """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', lifecycle_hooks={ 'preStop': { 'exec': { 'command': ['/bin/sh', 'test'] } } } )) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True}], "resources": { "limits": { }, "requests": { } }, "lifecycle": { "preStop": { "exec": { "command": ["/bin/sh", "test"] } } } } ], 'volumes': [{'name': 'no-api-access-please', 'emptyDir': {}}], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_extra_containers(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', extra_containers=[ { 'name': 'crontab', 'image': 'supercronic', 'command': ['/usr/local/bin/supercronic', '/etc/crontab'] } ] )) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True}], "resources": { "limits": { }, "requests": { } }, }, { 'name': 'crontab', 'image': 'supercronic', 'command': ['/usr/local/bin/supercronic', '/etc/crontab'] } ], 'volumes': [{'name': 'no-api-access-please', 'emptyDir': {}}], }, "kind": "Pod", "apiVersion": "v1" }
def get_pod_manifest(self): """ Make a pod manifest that will spawn current user's notebook pod. """ if callable(self.singleuser_uid): singleuser_uid = yield gen.maybe_future(self.singleuser_uid(self)) else: singleuser_uid = self.singleuser_uid if callable(self.singleuser_fs_gid): singleuser_fs_gid = yield gen.maybe_future( self.singleuser_fs_gid(self)) else: singleuser_fs_gid = self.singleuser_fs_gid if self.cmd: real_cmd = self.cmd + self.get_args() else: real_cmd = None labels = self._build_pod_labels( self._expand_all(self.singleuser_extra_labels)) annotations = self._expand_all(self.singleuser_extra_annotations) return make_pod( name=self.pod_name, cmd=real_cmd, port=self.port, image_spec=self.singleuser_image_spec, image_pull_policy=self.singleuser_image_pull_policy, image_pull_secret=self.singleuser_image_pull_secrets, node_selector=self.singleuser_node_selector, run_as_uid=singleuser_uid, fs_gid=singleuser_fs_gid, run_privileged=self.singleuser_privileged, env=self.get_env(), volumes=self._expand_all(self.volumes), volume_mounts=self._expand_all(self.volume_mounts), working_dir=self.singleuser_working_dir, labels=labels, annotations=annotations, cpu_limit=self.cpu_limit, cpu_guarantee=self.cpu_guarantee, mem_limit=self.mem_limit, mem_guarantee=self.mem_guarantee, extra_resource_limits=self.extra_resource_limits, extra_resource_guarantees=self.extra_resource_guarantees, lifecycle_hooks=self.singleuser_lifecycle_hooks, init_containers=self.singleuser_init_containers, service_account=self.singleuser_service_account, extra_container_config=self.singleuser_extra_container_config, extra_pod_config=self.singleuser_extra_pod_config, extra_containers=self.singleuser_extra_containers)
def test_run_privileged_container(): """ Test specification of the container to run as privileged """ assert api_client.sanitize_for_serialization( make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, run_privileged=True, image_pull_policy='IfNotPresent')) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "containers": [{ "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], "resources": { "limits": {}, "requests": {} }, "securityContext": { "privileged": True, }, 'volumeMounts': [{ 'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True }], }], 'volumes': [{ 'name': 'no-api-access-please', 'emptyDir': {} }], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_env(): """ Test specification of a pod with custom environment variables """ assert api_client.sanitize_for_serialization( make_pod( name='test', image_spec='jupyter/singleuser:latest', env={'TEST_KEY': 'TEST_VALUE'}, cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent')) == { "metadata": { "name": "test", "labels": {}, }, "spec": { "securityContext": {}, "containers": [{ "env": [{ 'name': 'TEST_KEY', 'value': 'TEST_VALUE' }], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{ 'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True }], "resources": { "limits": {}, "requests": {} } }], 'volumes': [{ 'name': 'no-api-access-please', 'emptyDir': {} }], }, "kind": "Pod", "apiVersion": "v1" }
def pod(containers): p = make_pod(name='test', image='image', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent' ) p.metadata.labels['primehub.io/group'] = escape_to_primehub_label(_TEST_GROUP) p.spec.containers = containers p.status = V1PodStatus() p.status.phase = "Pending" return p
def test_override_image_url(self): image = { 'spec': { 'url': "jupyter/test-notebook", } } self.spawner.apply_kubespawner_override( self.spawner.image_to_override(image, 0)) pod = make_pod(name='test', image=self.spawner.image, cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent') self.assertEqual(pod.spec.containers[0].image, 'jupyter/test-notebook') self.assertIsNone(pod.spec.image_pull_secrets)
def test_override_image_pull_secret(self): image = { 'spec': { 'url': "jupyter/base-notebook", 'pullSecret': "image-test" } } self.spawner.apply_kubespawner_override( self.spawner.image_to_override(image, 0)) pod_def = dict(name='test', image='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent') try: pod = make_pod(image_pull_secret=self.spawner.image_pull_secrets, **pod_def) except Exception: pod = make_pod(image_pull_secrets=self.spawner.image_pull_secrets, **pod_def) self.assertEqual(pod.spec.image_pull_secrets[0].name, 'image-test')
def test_override_image_url_for_gpu_without_url_for_gpu(self): image = { 'spec': { 'url': "jupyter/test-notebook-cpu", } } self.spawner.apply_kubespawner_override( self.spawner.image_to_override(image, 1)) pod = make_pod(name='test', image=self.spawner.image, cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent') self.assertEqual(pod.spec.containers[0].image, 'jupyter/test-notebook-cpu')
def test_make_pod_with_env(): """ Test specification of a pod with custom environment variables """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', env={ 'TEST_KEY': 'TEST_VALUE' }, cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [{'name': 'TEST_KEY', 'value': 'TEST_VALUE'}], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } } } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_set_pod_supplemental_gids(): """ Test specification of the simplest possible pod specification """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, run_as_uid=1000, supplemental_gids=[100], image_pull_policy='IfNotPresent' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": { "runAsUser": 1000, "supplementalGroups": [100] }, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_set_pod_uid_fs_gid(): """ Test specification of the simplest possible pod specification """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, run_as_uid=1000, fs_gid=1000, image_pull_policy='IfNotPresent' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": { "runAsUser": 1000, "fsGroup": 1000 }, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_run_privileged_container(): """ Test specification of the container to run as privileged """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, run_privileged=True, image_pull_policy='IfNotPresent' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], "resources": { "limits": {}, "requests": {} }, "securityContext": { "privileged": True, }, 'volumeMounts': [], } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_image_pull_secrets(): """ Test specification of the simplest possible pod specification """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', image_pull_secret='super-sekrit' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "imagePullSecrets": [ {'name': 'super-sekrit'} ], "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_priority_class_name(): """ Test specification of the simplest possible pod specification with non-default priorityClassName set """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', priority_class_name='my-custom-priority-class' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', 'volumes': [], 'priorityClassName': 'my-custom-priority-class', }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_scheduler_name(): """ Test specification of the simplest possible pod specification with non-default scheduler name """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', scheduler_name='my-custom-scheduler' )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { "securityContext": {}, 'automountServiceAccountToken': False, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": {}, "requests": {} } } ], 'restartPolicy': 'OnFailure', 'volumes': [], 'schedulerName': 'my-custom-scheduler', }, "kind": "Pod", "apiVersion": "v1" }
def get_pod_manifest(self): """ Make a pod manifest that will spawn current user's notebook pod. """ if callable(self.uid): uid = yield gen.maybe_future(self.uid(self)) else: uid = self.uid if callable(self.gid): gid = yield gen.maybe_future(self.gid(self)) else: gid = self.gid if callable(self.fs_gid): fs_gid = yield gen.maybe_future(self.fs_gid(self)) else: fs_gid = self.fs_gid if callable(self.supplemental_gids): supplemental_gids = yield gen.maybe_future( self.supplemental_gids(self)) else: supplemental_gids = self.supplemental_gids if self.cmd: real_cmd = self.cmd + self.get_args() else: real_cmd = None labels = self._build_pod_labels(self._expand_all(self.extra_labels)) annotations = self._build_common_annotations( self._expand_all(self.extra_annotations)) # The above was from the superclass. # This part is our custom LSST stuff. if os.getenv("ALLOW_DASK_SPAWN"): self.service_account = 'dask' pod_name = self.pod_name image = (self.image or os.getenv("LAB_IMAGE") or "lsstsqre/sciplat-lab:latest") image_name = image tag = "latest" size = None image_size = None # First pulls can be really slow for the LSST stack containers, # so let's give it a big timeout self.http_timeout = 60 * 15 self.start_timeout = 60 * 15 # We are running the Lab at the far end, not the old Notebook self.default_url = '/lab' self.image_pull_policy = 'Always' clear_dotlocal = False if self.user_options: self.log.debug( "user_options: %s" % json.dumps(self.user_options, sort_keys=True, indent=4)) if self.user_options.get('kernel_image'): image = self.user_options.get('kernel_image') colon = image.find(':') if colon > -1: imgname = image[:colon] tag = image[(colon + 1):] if tag == "recommended" or tag.startswith("latest"): self.log.info("Resolving tag '{}'".format(tag)) if self._scanner: qtag = self._scanner.resolve_tag(tag) if qtag: tag = qtag image = imgname + ":" + tag image_name = image else: self.log.warning( "Failed to resolve tag '{}'".format(tag)) self.log.debug("Image name: %s ; tag: %s" % (imgname, tag)) if tag == "__custom": cit = self.user_options.get('image_tag') if cit: image = imgname + ":" + cit image_name = image self.log.info("Replacing image from options form: %s" % image) size = self.user_options.get('size') if size: image_size = self._sizemap[size] clear_dotlocal = self.user_options.get('clear_dotlocal') mem_limit = os.getenv('LAB_MEM_LIMIT') or '2048M' cpu_limit = os.getenv('LAB_CPU_LIMIT') or 1.0 if image_size: mem_limit = str(int(image_size["mem"])) + "M" cpu_limit = float(image_size["cpu"]) if type(cpu_limit) is str: cpu_limit = float(cpu_limit) self.mem_limit = mem_limit self.cpu_limit = cpu_limit mem_guar = os.getenv('LAB_MEM_GUARANTEE') or '64K' cpu_guar = os.getenv('LAB_CPU_GUARANTEE') or 0.02 if type(cpu_guar) is str: cpu_guar = float(cpu_guar) # Tiny gets the "basically nothing" above (or the explicit # guarantee). All others get 1/LAB_SIZE_RANGE times their # maximum, with a default of 1/4. size_range = os.getenv('LAB_SIZE_RANGE') or 4.0 if type(size_range) is str: size_range = float(size_range) if image_size and size != 'tiny': mem_guar = int(image_size["mem"] / size_range) cpu_guar = float(image_size["cpu"] / size_range) self.mem_guarantee = mem_guar self.cpu_guarantee = cpu_guar self.log.debug("Image: {}".format(image)) self.image = image # Parse the image name + tag i_l = image.split("/") if len(i_l) == 1: repo_tag = i_l[0] else: repo_tag = i_l[1] repo = repo_tag.split(":")[0] rt_tag = tag.replace('_', '-') abbr_pn = repo if repo == 'sciplat-lab': # Saving characters because tags can be long abbr_pn = "nb" pn_template = abbr_pn + "-{username}-" + rt_tag pod_name = self._expand_user_properties(pn_template) self.pod_name = pod_name self.log.info("Replacing pod name from options form: %s" % pod_name) pod_env = self.get_env() idle_timeout = int(os.getenv('LAB_IDLE_TIMEOUT') or 43200) if idle_timeout > 0 and 'JUPYTERLAB_IDLE_TIMEOUT' not in pod_env: pod_env['JUPYTERLAB_IDLE_TIMEOUT'] = str(idle_timeout) if os.getenv('RESTRICT_DASK_NODES'): pod_env['RESTRICT_DASK_NODES'] = "true" if os.getenv('LAB_NODEJS_MAX_MEM'): pod_env['NODE_OPTIONS'] = ("--max-old-space-size=" + os.getenv('LAB_NODEJS_MAX_MEM')) external_hub_url = os.getenv('EXTERNAL_HUB_URL') hub_route = os.getenv('HUB_ROUTE') while (hub_route.endswith('/') and hub_route != "/"): hub_route = hub_route[:-1] if not external_hub_url: oauth_callback = os.getenv('OAUTH_CALLBACK_URL') endstr = "/hub/oauth_callback" if oauth_callback and oauth_callback.endswith(endstr): external_hub_url = oauth_callback[:-len(endstr)] # Guaranteed external endpoints pod_env['EXTERNAL_URL'] = external_hub_url pod_env['EXTERNAL_HUB_URL'] = external_hub_url external_instance_url = os.getenv('EXTERNAL_INSTANCE_URL') if not external_instance_url: if external_hub_url.endswith(hub_route): external_instance_url = external_hub_url[:-len(hub_route)] pod_env['EXTERNAL_INSTANCE_URL'] = external_instance_url if os.getenv('DEBUG'): pod_env['DEBUG'] = os.getenv('DEBUG') if clear_dotlocal: pod_env['CLEAR_DOTLOCAL'] = "true" # Add service routes # Check if we need trailing slash anymore for firefly hub_route = os.getenv('HUB_ROUTE') or "/nb" firefly_route = os.getenv('FIREFLY_ROUTE') or "/firefly/" js9_route = os.getenv('JS9_ROUTE') or "/js9" api_route = os.getenv('API_ROUTE') or "/api" tap_route = os.getenv('TAP_ROUTE') or "/api/tap" soda_route = os.getenv('SODA_ROUTE') or "/api/image/soda" pod_env['HUB_ROUTE'] = hub_route pod_env['FIREFLY_ROUTE'] = firefly_route pod_env['JS9_ROUTE'] = js9_route pod_env['API_ROUTE'] = api_route pod_env['TAP_ROUTE'] = tap_route pod_env['SODA_ROUTE'] = soda_route # Optional external endpoints for i in ['firefly', 'js9', 'api', 'tap', 'soda']: envvar = 'EXTERNAL_' + i.upper() + '_URL' if os.getenv(envvar): pod_env[envvar] = os.getenv(envvar) auto_repo_urls = os.getenv('AUTO_REPO_URLS') if auto_repo_urls: pod_env['AUTO_REPO_URLS'] = auto_repo_urls vollist = self._get_volume_list() self._splice_volumes(vollist) pod_env['DASK_VOLUME_B64'] = self._get_dask_volume_b64() if self._quota: pod_env['NAMESPACE_CPU_LIMIT'] = self._quota["limits.cpu"] nmlimit = self._quota["limits.memory"] if nmlimit[-2:] == "Mi": # Not technically correct, but matches mem_limit nmlimit = nmlimit[:-2] + "M" pod_env['NAMESPACE_MEM_LIMIT'] = nmlimit pod_env['CPU_LIMIT'] = str(cpu_limit) pod_env['MEM_LIMIT'] = str(mem_limit) self.image = image self.log.debug("Image: %s" % json.dumps(image, indent=4, sort_keys=True)) self.log.debug("Pod env: %s" % json.dumps(pod_env, indent=4, sort_keys=True)) if not pod_env.get("EXTERNAL_UID"): raise ValueError("EXTERNAL_UID is not set!") self.log.debug("About to run make_pod()") pod = make_pod( name=self.pod_name, cmd=real_cmd, port=self.port, image=self.image, image_pull_policy=self.image_pull_policy, image_pull_secret=self.image_pull_secrets, node_selector=self.node_selector, run_as_uid=uid, run_as_gid=gid, fs_gid=fs_gid, supplemental_gids=supplemental_gids, run_privileged=self.privileged, # env is locally-modified env=pod_env, volumes=self._expand_all(self.volumes), volume_mounts=self._expand_all(self.volume_mounts), working_dir=self.working_dir, labels=labels, annotations=annotations, cpu_limit=self.cpu_limit, cpu_guarantee=self.cpu_guarantee, mem_limit=self.mem_limit, mem_guarantee=self.mem_guarantee, extra_resource_limits=self.extra_resource_limits, extra_resource_guarantees=self.extra_resource_guarantees, lifecycle_hooks=self.lifecycle_hooks, init_containers=self._expand_all(self.init_containers), service_account=self.service_account, extra_container_config=self.extra_container_config, extra_pod_config=self.extra_pod_config, extra_containers=self.extra_containers, node_affinity_preferred=self.node_affinity_preferred, node_affinity_required=self.node_affinity_required, pod_affinity_preferred=self.pod_affinity_preferred, pod_affinity_required=self.pod_affinity_required, pod_anti_affinity_preferred=self.pod_anti_affinity_preferred, pod_anti_affinity_required=self.pod_anti_affinity_required, priority_class_name=self.priority_class_name, logger=self.log, ) return pod
def test_make_pod_with_init_containers(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', init_containers=[ { 'name': 'init-myservice', 'image': 'busybox', 'command': ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] }, { 'name': 'init-mydb', 'image': 'busybox', 'command': ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;'] } ] )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [{'name': 'no-api-access-please', 'mountPath': '/var/run/secrets/kubernetes.io/serviceaccount', 'readOnly': True}], "resources": { "limits": { }, "requests": { } }, } ], "initContainers": [ { "name": "init-myservice", "image": "busybox", "command": ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done;"] }, { "name": "init-mydb", "image": "busybox", "command": ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done;"] } ], 'volumes': [{'name': 'no-api-access-please', 'emptyDir': {}}], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_init_containers(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', init_containers=[ { 'name': 'init-myservice', 'image': 'busybox', 'command': ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;'] }, { 'name': 'init-mydb', 'image': 'busybox', 'command': ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;'] } ] )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } }, } ], "initContainers": [ { "name": "init-myservice", "image": "busybox", "command": ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done;"] }, { "name": "init-mydb", "image": "busybox", "command": ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done;"] } ], 'restartPolicy': 'OnFailure', 'volumes': [], }, "kind": "Pod", "apiVersion": "v1" }
def test_make_pod_with_extra_pod_config(): """ Test specification of a pod with initContainers """ assert api_client.sanitize_for_serialization(make_pod( name='test', image_spec='jupyter/singleuser:latest', cmd=['jupyterhub-singleuser'], port=8888, image_pull_policy='IfNotPresent', tolerations=[{ 'key': 'wrong_toleration', 'operator': 'Equal', 'value': 'wrong_value' }], extra_pod_config={ 'dns_policy': 'ClusterFirstWithHostNet', 'restartPolicy': 'Always', 'tolerations': [{ 'key': 'correct_toleration', 'operator': 'Equal', 'value': 'correct_value' }], }, )) == { "metadata": { "name": "test", "annotations": {}, "labels": {}, }, "spec": { 'automountServiceAccountToken': False, "securityContext": {}, "containers": [ { "env": [], "name": "notebook", "image": "jupyter/singleuser:latest", "imagePullPolicy": "IfNotPresent", "args": ["jupyterhub-singleuser"], "ports": [{ "name": "notebook-port", "containerPort": 8888 }], 'volumeMounts': [], "resources": { "limits": { }, "requests": { } } } ], 'volumes': [], 'dnsPolicy': 'ClusterFirstWithHostNet', 'restartPolicy': 'Always', 'tolerations': [ { 'key': 'correct_toleration', 'operator': 'Equal', 'value': 'correct_value' } ] }, "kind": "Pod", "apiVersion": "v1" }
def get_pod_manifest(self): """ Make a pod manifest that will spawn current user's notebook pod. """ uid = gen.maybe_future(self.uid(self)) if callable( self.uid) else self.uid fs_gid = gen.maybe_future(self.fs_gid(self)) if callable( self.fs_gid) else self.fs_gid real_cmd = self.cmd + self.get_args() if self.cmd else None # Default set of labels, picked up from # https://github.com/kubernetes/helm/blob/master/docs/chart_best_practices/labels.md labels = { 'heritage': 'jupyterhub', 'component': 'singleuser-server', 'app': 'jupyterhub', 'hub.jupyter.org/username': escapism.escape(self.user.name) } labels.update(self._expand_all(self.extra_labels)) pod_name = self.pod_name image_spec = (self.image or os.getenv("LAB_IMAGE")) image_name = image_spec if self.user_options: if self.user_options.get('kernel_image'): image_spec = self.user_options.get('kernel_image') image_name = image_spec self.log.info("Replacing image spec from options form: %s" % image_spec) self.image = image_spec s_idx = image_spec.find('/') c_idx = image_spec.find(':') tag = "latest" if s_idx != -1: image_name = image_spec[(s_idx + 1):] if c_idx > 0: image_name = image_spec[(s_idx + 1):c_idx] tag = image_spec[(c_idx + 1):].replace('_', '.') pn_template = image_name + "-{username}-" + tag # self.log.info('running image: %s' % (image_name,)) auth_state = yield self.user.get_auth_state() # self.log.info("AuthState: %s"%(auth_state,)) if auth_state and "id" in auth_state: if auth_state["id"] != self.user.id: self.log.info("Updating userid from %d to %d" % (self.user.id, auth_state["id"])) pod_name = self._expand_user_properties(pn_template) self.pod_name = pod_name # self.log.info("Replacing pod name from options form: %s" % pod_name) # ast chance to overload some env variables for the notebox pod_env = self.get_env() idle_timeout = int(os.getenv('LAB_IDLE_TIMEOUT') or 43200) if idle_timeout > 0 and 'JUPYTERLAB_IDLE_TIMEOUT' not in pod_env: pod_env['JUPYTERLAB_IDLE_TIMEOUT'] = str(idle_timeout) oauth_callback = os.getenv('OAUTH_CALLBACK_URL') endstr = "/hub/oauth_callback" if oauth_callback and oauth_callback.endswith(endstr): pod_env['EXTERNAL_URL'] = oauth_callback[:-len(endstr)] # use the hub service instead of pod if os.getenv('HUB_SERVICE_HOST') and os.getenv('HUB_SERVICE_PORT_API'): pod_env['JUPYTERHUB_API_URL'] = "http://%s:%s/hub/api" % ( os.getenv('HUB_SERVICE_HOST'), os.getenv('HUB_SERVICE_PORT_API')) # inject google drive client id if os.getenv('JUPYTERLAB_GOOGLE_OAUTH_CLIENTID'): pod_env['JUPYTERLAB_GOOGLE_OAUTH_CLIENTID'] = os.getenv( 'JUPYTERLAB_GOOGLE_OAUTH_CLIENTID') # determine which labels to schedule the jupyterlab pod on # get names of groups gnames = [i.split(':')[0] for i in self.user_gids] spawn_on = {} volumes = [] volume_mounts = [] config = {} spec = {} with open(self.node_selector_config_file, 'r') as f: config = yaml.safe_load(f) if 'node_defaults' in config: this = config['node_defaults'] if 'spawn_on' in this: spawn_on = this['spawn_on'] if 'spec' in this: spec = this['spec'] # self.log.info("node-selectors config: %s" % (config,)) if 'node_selectors' in config: for idx, item in enumerate(config['node_selectors']): if 'filter' in item: this = item['filter'] matching = [] self.log.info("checking filter: %s" % (this, )) for n in ('gnames', 'images', 'uid'): if n in this: a = [] if n == 'gnames': a = gnames elif n == 'images': a = [ image_name, ] # TODO: hwo to get the uid? self.log.info(" %s against %s" % (n, a)) if set(this[n]).intersection(a): matching.append(True) else: matching.append(False) self.log.info(" matching: %s" % (matching, )) if False in matching: continue else: spawn_on = item['spawn_on'] spec = item['spec'] if 'cpu' in spec: self.cpu_limit = spec['cpu'] #self.cpu_guarantee = spec['cpu'] if 'memory' in spec: self.mem_limit = spec['memory'] #self.mem_guarantee = spec['memory'] if 'env' in spec: for k, v in spec['env'].items(): pod_env[k] = str(v) self.log.info(" using spec: %s" % (spec, )) break self.log.info("spawning pod %s on %s, spec %s" % (pod_name, spawn_on, spec)) return make_pod( name=self.pod_name, image=self.image, image_pull_policy=self.image_pull_policy, image_pull_secret=self.image_pull_secrets, port=self.port, cmd=real_cmd, node_selector=spawn_on, run_as_uid=uid, fs_gid=fs_gid, run_privileged=self.privileged, env=pod_env, volumes=self._expand_all(spec['volumes']) if 'volumes' in spec else self._expand_all([]), volume_mounts=self._expand_all(spec['volume_mounts']) if 'volume_mounts' in spec else self._expand_all([]), working_dir=self.working_dir, labels=labels, cpu_limit=self.cpu_limit, cpu_guarantee=self.cpu_guarantee, mem_limit=self.mem_limit, mem_guarantee=self.mem_guarantee, extra_resource_limits=spec['extra_resource_limits'] if 'extra_resource_limits' in spec else {}, lifecycle_hooks=self.lifecycle_hooks, init_containers=self.init_containers, service_account=None, extra_pod_config=spec['extra_pod_config'] if 'extra_pod_config' in spec else {}, # extra_container_config = { 'securityContext': { 'capabilities': { 'add': [ 'ALL', ] } } }, extra_container_config=spec['extra_container_config'] if 'extra_container_config' in spec else {}, )