Merge "Add scheduler, volumes, and labels to k8s/openshift"
This commit is contained in:
commit
7ffb3f1fd6
@ -188,6 +188,15 @@ Selecting the kubernetes driver adds the following options to the
|
|||||||
|
|
||||||
The ImagePullPolicy, can be IfNotPresent, Always or Never.
|
The ImagePullPolicy, can be IfNotPresent, Always or Never.
|
||||||
|
|
||||||
|
.. attr:: labels
|
||||||
|
:type: dict
|
||||||
|
|
||||||
|
A dictionary of additional values to be added to the
|
||||||
|
namespace or pod metadata. The value of this field is
|
||||||
|
added to the `metadata.labels` field in Kubernetes. Note
|
||||||
|
that this field contains arbitrary key/value pairs and is
|
||||||
|
unrelated to the concept of labels in Nodepool.
|
||||||
|
|
||||||
.. attr:: python-path
|
.. attr:: python-path
|
||||||
:type: str
|
:type: str
|
||||||
:default: auto
|
:default: auto
|
||||||
@ -262,6 +271,15 @@ Selecting the kubernetes driver adds the following options to the
|
|||||||
A map of key-value pairs to ensure the Kubernetes scheduler
|
A map of key-value pairs to ensure the Kubernetes scheduler
|
||||||
places the Pod on a node with specific node labels.
|
places the Pod on a node with specific node labels.
|
||||||
|
|
||||||
|
.. attr:: scheduler-name
|
||||||
|
:type: str
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[kubernetes].pools.labels.type.pod`
|
||||||
|
label type. Sets the `schedulerName` field on the
|
||||||
|
container. Normally left unset for the Kubernetes
|
||||||
|
default.
|
||||||
|
|
||||||
.. attr:: privileged
|
.. attr:: privileged
|
||||||
:type: bool
|
:type: bool
|
||||||
|
|
||||||
@ -269,3 +287,21 @@ Selecting the kubernetes driver adds the following options to the
|
|||||||
:value:`providers.[kubernetes].pools.labels.type.pod`
|
:value:`providers.[kubernetes].pools.labels.type.pod`
|
||||||
label type. Sets the `securityContext.privileged` flag on
|
label type. Sets the `securityContext.privileged` flag on
|
||||||
the container. Normally left unset for the Kubernetes default.
|
the container. Normally left unset for the Kubernetes default.
|
||||||
|
|
||||||
|
.. attr:: volumes
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[kubernetes].pools.labels.type.pod`
|
||||||
|
label type. Sets the `volumes` field on the pod. If
|
||||||
|
supplied, this should be a list of Kubernetes Pod Volume
|
||||||
|
definitions.
|
||||||
|
|
||||||
|
.. attr:: volume-mounts
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[kubernetes].pools.labels.type.pod`
|
||||||
|
label type. Sets the `volumeMounts` flag on the
|
||||||
|
container. If supplied, this should be a list of
|
||||||
|
Kubernetes Container VolumeMount definitions.
|
||||||
|
@ -123,6 +123,15 @@ Selecting the openshift pods driver adds the following options to the
|
|||||||
image-pull-secrets:
|
image-pull-secrets:
|
||||||
- name: registry-secret
|
- name: registry-secret
|
||||||
|
|
||||||
|
.. attr:: labels
|
||||||
|
:type: dict
|
||||||
|
|
||||||
|
A dictionary of additional values to be added to the
|
||||||
|
namespace or pod metadata. The value of this field is
|
||||||
|
added to the `metadata.labels` field in OpenShift. Note
|
||||||
|
that this field contains arbitrary key/value pairs and is
|
||||||
|
unrelated to the concept of labels in Nodepool.
|
||||||
|
|
||||||
.. attr:: cpu
|
.. attr:: cpu
|
||||||
:type: int
|
:type: int
|
||||||
|
|
||||||
@ -182,8 +191,27 @@ Selecting the openshift pods driver adds the following options to the
|
|||||||
A map of key-value pairs to ensure the OpenShift scheduler
|
A map of key-value pairs to ensure the OpenShift scheduler
|
||||||
places the Pod on a node with specific node labels.
|
places the Pod on a node with specific node labels.
|
||||||
|
|
||||||
|
.. attr:: scheduler-name
|
||||||
|
:type: str
|
||||||
|
|
||||||
|
Sets the `schedulerName` field on the container. Normally
|
||||||
|
left unset for the OpenShift default.
|
||||||
|
|
||||||
.. attr:: privileged
|
.. attr:: privileged
|
||||||
:type: bool
|
:type: bool
|
||||||
|
|
||||||
Sets the `securityContext.privileged` flag on the
|
Sets the `securityContext.privileged` flag on the
|
||||||
container. Normally left unset for the OpenShift default.
|
container. Normally left unset for the OpenShift default.
|
||||||
|
|
||||||
|
.. attr:: volumes
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Sets the `volumes` field on the pod. If supplied, this
|
||||||
|
should be a list of OpenShift Pod Volume definitions.
|
||||||
|
|
||||||
|
.. attr:: volume-mounts
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Sets the `volumeMounts` flag on the container. If
|
||||||
|
supplied, this should be a list of OpenShift Container
|
||||||
|
VolumeMount definitions.
|
||||||
|
@ -159,6 +159,15 @@ Selecting the openshift driver adds the following options to the
|
|||||||
image-pull-secrets:
|
image-pull-secrets:
|
||||||
- name: registry-secret
|
- name: registry-secret
|
||||||
|
|
||||||
|
.. attr:: labels
|
||||||
|
:type: dict
|
||||||
|
|
||||||
|
A dictionary of additional values to be added to the
|
||||||
|
namespace or pod metadata. The value of this field is
|
||||||
|
added to the `metadata.labels` field in OpenShift. Note
|
||||||
|
that this field contains arbitrary key/value pairs and is
|
||||||
|
unrelated to the concept of labels in Nodepool.
|
||||||
|
|
||||||
.. attr:: python-path
|
.. attr:: python-path
|
||||||
:type: str
|
:type: str
|
||||||
:default: auto
|
:default: auto
|
||||||
@ -226,6 +235,15 @@ Selecting the openshift driver adds the following options to the
|
|||||||
A map of key-value pairs to ensure the OpenShift scheduler
|
A map of key-value pairs to ensure the OpenShift scheduler
|
||||||
places the Pod on a node with specific node labels.
|
places the Pod on a node with specific node labels.
|
||||||
|
|
||||||
|
.. attr:: scheduler-name
|
||||||
|
:type: str
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[openshift].pools.labels.type.pod`
|
||||||
|
label type. Sets the `schedulerName` field on the
|
||||||
|
container. Normally left unset for the OpenShift
|
||||||
|
default.
|
||||||
|
|
||||||
.. attr:: privileged
|
.. attr:: privileged
|
||||||
:type: bool
|
:type: bool
|
||||||
|
|
||||||
@ -233,3 +251,21 @@ Selecting the openshift driver adds the following options to the
|
|||||||
:value:`providers.[openshift].pools.labels.type.pod`
|
:value:`providers.[openshift].pools.labels.type.pod`
|
||||||
label type. Sets the `securityContext.privileged` flag on
|
label type. Sets the `securityContext.privileged` flag on
|
||||||
the container. Normally left unset for the OpenShift default.
|
the container. Normally left unset for the OpenShift default.
|
||||||
|
|
||||||
|
.. attr:: volumes
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[openshift].pools.labels.type.pod`
|
||||||
|
label type. Sets the `volumes` field on the pod. If
|
||||||
|
supplied, this should be a list of OpenShift Pod Volume
|
||||||
|
definitions.
|
||||||
|
|
||||||
|
.. attr:: volume-mounts
|
||||||
|
:type: list
|
||||||
|
|
||||||
|
Only used by the
|
||||||
|
:value:`providers.[openshift].pools.labels.type.pod`
|
||||||
|
label type. Sets the `volumeMounts` flag on the
|
||||||
|
container. If supplied, this should be a list of
|
||||||
|
OpenShift Container VolumeMount definitions.
|
||||||
|
@ -57,6 +57,10 @@ class KubernetesPool(ConfigPool):
|
|||||||
pl.env = label.get('env', [])
|
pl.env = label.get('env', [])
|
||||||
pl.node_selector = label.get('node-selector')
|
pl.node_selector = label.get('node-selector')
|
||||||
pl.privileged = label.get('privileged')
|
pl.privileged = label.get('privileged')
|
||||||
|
pl.scheduler_name = label.get('scheduler-name')
|
||||||
|
pl.volumes = label.get('volumes')
|
||||||
|
pl.volume_mounts = label.get('volume-mounts')
|
||||||
|
pl.labels = label.get('labels')
|
||||||
pl.pool = self
|
pl.pool = self
|
||||||
self.labels[pl.name] = pl
|
self.labels[pl.name] = pl
|
||||||
full_config.labels[label['name']].pools.append(self)
|
full_config.labels[label['name']].pools.append(self)
|
||||||
@ -104,6 +108,10 @@ class KubernetesProviderConfig(ProviderConfig):
|
|||||||
'env': [env_var],
|
'env': [env_var],
|
||||||
'node-selector': dict,
|
'node-selector': dict,
|
||||||
'privileged': bool,
|
'privileged': bool,
|
||||||
|
'scheduler-name': str,
|
||||||
|
'volumes': list,
|
||||||
|
'volume-mounts': list,
|
||||||
|
'labels': dict,
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = ConfigPool.getCommonSchemaDict()
|
pool = ConfigPool.getCommonSchemaDict()
|
||||||
|
@ -32,7 +32,7 @@ class K8SLauncher(NodeLauncher):
|
|||||||
self.log.debug("Creating resource")
|
self.log.debug("Creating resource")
|
||||||
if self.label.type == "namespace":
|
if self.label.type == "namespace":
|
||||||
resource = self.handler.manager.createNamespace(
|
resource = self.handler.manager.createNamespace(
|
||||||
self.node, self.handler.pool.name)
|
self.node, self.handler.pool.name, self.label)
|
||||||
else:
|
else:
|
||||||
resource = self.handler.manager.createPod(
|
resource = self.handler.manager.createPod(
|
||||||
self.node, self.handler.pool.name, self.label)
|
self.node, self.handler.pool.name, self.label)
|
||||||
|
@ -155,23 +155,30 @@ class KubernetesProvider(Provider, QuotaSupport):
|
|||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
def createNamespace(self, node, pool, restricted_access=False):
|
def createNamespace(self, node, pool, label, restricted_access=False):
|
||||||
name = node.id
|
name = node.id
|
||||||
namespace = "%s-%s" % (pool, name)
|
namespace = "%s-%s" % (pool, name)
|
||||||
user = "zuul-worker"
|
user = "zuul-worker"
|
||||||
|
|
||||||
self.log.debug("%s: creating namespace" % namespace)
|
self.log.debug("%s: creating namespace" % namespace)
|
||||||
|
|
||||||
|
k8s_labels = {}
|
||||||
|
if label.labels:
|
||||||
|
k8s_labels.update(label.labels)
|
||||||
|
k8s_labels.update({
|
||||||
|
'nodepool_node_id': node.id,
|
||||||
|
'nodepool_provider_name': self.provider.name,
|
||||||
|
'nodepool_pool_name': pool,
|
||||||
|
'nodepool_node_label': label.name,
|
||||||
|
})
|
||||||
|
|
||||||
# Create the namespace
|
# Create the namespace
|
||||||
ns_body = {
|
ns_body = {
|
||||||
'apiVersion': 'v1',
|
'apiVersion': 'v1',
|
||||||
'kind': 'Namespace',
|
'kind': 'Namespace',
|
||||||
'metadata': {
|
'metadata': {
|
||||||
'name': namespace,
|
'name': namespace,
|
||||||
'labels': {
|
'labels': k8s_labels,
|
||||||
'nodepool_node_id': node.id,
|
|
||||||
'nodepool_provider_name': self.provider.name,
|
|
||||||
'nodepool_pool_name': pool,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
proj = self.k8s_client.create_namespace(ns_body)
|
proj = self.k8s_client.create_namespace(ns_body)
|
||||||
@ -330,28 +337,43 @@ class KubernetesProvider(Provider, QuotaSupport):
|
|||||||
if label.node_selector:
|
if label.node_selector:
|
||||||
spec_body['nodeSelector'] = label.node_selector
|
spec_body['nodeSelector'] = label.node_selector
|
||||||
|
|
||||||
|
if label.scheduler_name:
|
||||||
|
spec_body['schedulerName'] = label.scheduler_name
|
||||||
|
|
||||||
|
if label.volumes:
|
||||||
|
spec_body['volumes'] = label.volumes
|
||||||
|
|
||||||
|
if label.volume_mounts:
|
||||||
|
container_body['volumeMounts'] = label.volume_mounts
|
||||||
|
|
||||||
if label.privileged is not None:
|
if label.privileged is not None:
|
||||||
container_body['securityContext'] = {
|
container_body['securityContext'] = {
|
||||||
'privileged': label.privileged,
|
'privileged': label.privileged,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k8s_labels = {}
|
||||||
|
if label.labels:
|
||||||
|
k8s_labels.update(label.labels)
|
||||||
|
k8s_labels.update({
|
||||||
|
'nodepool_node_id': node.id,
|
||||||
|
'nodepool_provider_name': self.provider.name,
|
||||||
|
'nodepool_pool_name': pool,
|
||||||
|
'nodepool_node_label': label.name,
|
||||||
|
})
|
||||||
|
|
||||||
pod_body = {
|
pod_body = {
|
||||||
'apiVersion': 'v1',
|
'apiVersion': 'v1',
|
||||||
'kind': 'Pod',
|
'kind': 'Pod',
|
||||||
'metadata': {
|
'metadata': {
|
||||||
'name': label.name,
|
'name': label.name,
|
||||||
'labels': {
|
'labels': k8s_labels,
|
||||||
'nodepool_node_id': node.id,
|
|
||||||
'nodepool_provider_name': self.provider.name,
|
|
||||||
'nodepool_pool_name': pool,
|
|
||||||
'nodepool_node_label': label.name,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
'spec': spec_body,
|
'spec': spec_body,
|
||||||
'restartPolicy': 'Never',
|
'restartPolicy': 'Never',
|
||||||
}
|
}
|
||||||
|
|
||||||
resource = self.createNamespace(node, pool, restricted_access=True)
|
resource = self.createNamespace(node, pool, label,
|
||||||
|
restricted_access=True)
|
||||||
namespace = resource['namespace']
|
namespace = resource['namespace']
|
||||||
|
|
||||||
self.k8s_client.create_namespaced_pod(namespace, pod_body)
|
self.k8s_client.create_namespaced_pod(namespace, pod_body)
|
||||||
|
@ -53,6 +53,10 @@ class OpenshiftPool(ConfigPool):
|
|||||||
pl.env = label.get('env', [])
|
pl.env = label.get('env', [])
|
||||||
pl.node_selector = label.get('node-selector')
|
pl.node_selector = label.get('node-selector')
|
||||||
pl.privileged = label.get('privileged')
|
pl.privileged = label.get('privileged')
|
||||||
|
pl.scheduler_name = label.get('scheduler-name')
|
||||||
|
pl.volumes = label.get('volumes')
|
||||||
|
pl.volume_mounts = label.get('volume-mounts')
|
||||||
|
pl.labels = label.get('labels')
|
||||||
pl.pool = self
|
pl.pool = self
|
||||||
self.labels[pl.name] = pl
|
self.labels[pl.name] = pl
|
||||||
full_config.labels[label['name']].pools.append(self)
|
full_config.labels[label['name']].pools.append(self)
|
||||||
@ -101,6 +105,10 @@ class OpenshiftProviderConfig(ProviderConfig):
|
|||||||
'env': [env_var],
|
'env': [env_var],
|
||||||
'node-selector': dict,
|
'node-selector': dict,
|
||||||
'privileged': bool,
|
'privileged': bool,
|
||||||
|
'scheduler-name': str,
|
||||||
|
'volumes': list,
|
||||||
|
'volume-mounts': list,
|
||||||
|
'labels': dict,
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = ConfigPool.getCommonSchemaDict()
|
pool = ConfigPool.getCommonSchemaDict()
|
||||||
|
@ -31,12 +31,14 @@ class OpenshiftLauncher(NodeLauncher):
|
|||||||
def _launchLabel(self):
|
def _launchLabel(self):
|
||||||
self.log.debug("Creating resource")
|
self.log.debug("Creating resource")
|
||||||
project = "%s-%s" % (self.handler.pool.name, self.node.id)
|
project = "%s-%s" % (self.handler.pool.name, self.node.id)
|
||||||
self.node.external_id = self.handler.manager.createProject(project)
|
self.node.external_id = self.handler.manager.createProject(
|
||||||
|
self.node, self.handler.pool.name, project, self.label)
|
||||||
self.zk.storeNode(self.node)
|
self.zk.storeNode(self.node)
|
||||||
|
|
||||||
resource = self.handler.manager.prepareProject(project)
|
resource = self.handler.manager.prepareProject(project)
|
||||||
if self.label.type == "pod":
|
if self.label.type == "pod":
|
||||||
self.handler.manager.createPod(
|
self.handler.manager.createPod(
|
||||||
|
self.node, self.handler.pool.name,
|
||||||
project, self.label.name, self.label)
|
project, self.label.name, self.label)
|
||||||
self.handler.manager.waitForPod(project, self.label.name)
|
self.handler.manager.waitForPod(project, self.label.name)
|
||||||
resource['pod'] = self.label.name
|
resource['pod'] = self.label.name
|
||||||
|
@ -125,14 +125,26 @@ class OpenshiftProvider(Provider, QuotaSupport):
|
|||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
def createProject(self, project):
|
def createProject(self, node, pool, project, label):
|
||||||
self.log.debug("%s: creating project" % project)
|
self.log.debug("%s: creating project" % project)
|
||||||
# Create the project
|
# Create the project
|
||||||
|
|
||||||
|
k8s_labels = {}
|
||||||
|
if label.labels:
|
||||||
|
k8s_labels.update(label.labels)
|
||||||
|
k8s_labels.update({
|
||||||
|
'nodepool_node_id': node.id,
|
||||||
|
'nodepool_provider_name': self.provider.name,
|
||||||
|
'nodepool_pool_name': pool,
|
||||||
|
'nodepool_node_label': label.name,
|
||||||
|
})
|
||||||
|
|
||||||
proj_body = {
|
proj_body = {
|
||||||
'apiVersion': 'project.openshift.io/v1',
|
'apiVersion': 'project.openshift.io/v1',
|
||||||
'kind': 'ProjectRequest',
|
'kind': 'ProjectRequest',
|
||||||
'metadata': {
|
'metadata': {
|
||||||
'name': project,
|
'name': project,
|
||||||
|
'labels': k8s_labels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
projects = self.os_client.resources.get(
|
projects = self.os_client.resources.get(
|
||||||
@ -211,7 +223,7 @@ class OpenshiftProvider(Provider, QuotaSupport):
|
|||||||
self.log.info("%s: project created" % project)
|
self.log.info("%s: project created" % project)
|
||||||
return resource
|
return resource
|
||||||
|
|
||||||
def createPod(self, project, pod_name, label):
|
def createPod(self, node, pool, project, pod_name, label):
|
||||||
self.log.debug("%s: creating pod in project %s" % (pod_name, project))
|
self.log.debug("%s: creating pod in project %s" % (pod_name, project))
|
||||||
container_body = {
|
container_body = {
|
||||||
'name': label.name,
|
'name': label.name,
|
||||||
@ -239,15 +251,37 @@ class OpenshiftProvider(Provider, QuotaSupport):
|
|||||||
if label.node_selector:
|
if label.node_selector:
|
||||||
spec_body['nodeSelector'] = label.node_selector
|
spec_body['nodeSelector'] = label.node_selector
|
||||||
|
|
||||||
|
if label.scheduler_name:
|
||||||
|
spec_body['schedulerName'] = label.scheduler_name
|
||||||
|
|
||||||
|
if label.volumes:
|
||||||
|
spec_body['volumes'] = label.volumes
|
||||||
|
|
||||||
|
if label.volume_mounts:
|
||||||
|
container_body['volumeMounts'] = label.volume_mounts
|
||||||
|
|
||||||
if label.privileged is not None:
|
if label.privileged is not None:
|
||||||
container_body['securityContext'] = {
|
container_body['securityContext'] = {
|
||||||
'privileged': label.privileged,
|
'privileged': label.privileged,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k8s_labels = {}
|
||||||
|
if label.labels:
|
||||||
|
k8s_labels.update(label.labels)
|
||||||
|
k8s_labels.update({
|
||||||
|
'nodepool_node_id': node.id,
|
||||||
|
'nodepool_provider_name': self.provider.name,
|
||||||
|
'nodepool_pool_name': pool,
|
||||||
|
'nodepool_node_label': label.name,
|
||||||
|
})
|
||||||
|
|
||||||
pod_body = {
|
pod_body = {
|
||||||
'apiVersion': 'v1',
|
'apiVersion': 'v1',
|
||||||
'kind': 'Pod',
|
'kind': 'Pod',
|
||||||
'metadata': {'name': pod_name},
|
'metadata': {
|
||||||
|
'name': pod_name,
|
||||||
|
'labels': k8s_labels,
|
||||||
|
},
|
||||||
'spec': spec_body,
|
'spec': spec_body,
|
||||||
'restartPolicy': 'Never',
|
'restartPolicy': 'Never',
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,10 @@ class OpenshiftPodsProviderConfig(OpenshiftProviderConfig):
|
|||||||
'env': [env_var],
|
'env': [env_var],
|
||||||
'node-selector': dict,
|
'node-selector': dict,
|
||||||
'privileged': bool,
|
'privileged': bool,
|
||||||
|
'scheduler-name': str,
|
||||||
|
'volumes': list,
|
||||||
|
'volume-mounts': list,
|
||||||
|
'labels': dict,
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = ConfigPool.getCommonSchemaDict()
|
pool = ConfigPool.getCommonSchemaDict()
|
||||||
|
@ -25,7 +25,8 @@ class OpenshiftPodLauncher(OpenshiftLauncher):
|
|||||||
self.log.debug("Creating resource")
|
self.log.debug("Creating resource")
|
||||||
pod_name = "%s-%s" % (self.label.name, self.node.id)
|
pod_name = "%s-%s" % (self.label.name, self.node.id)
|
||||||
project = self.handler.pool.name
|
project = self.handler.pool.name
|
||||||
self.handler.manager.createPod(project, pod_name, self.label)
|
self.handler.manager.createPod(self.node, self.handler.pool.name,
|
||||||
|
project, pod_name, self.label)
|
||||||
self.node.external_id = "%s-%s" % (project, pod_name)
|
self.node.external_id = "%s-%s" % (project, pod_name)
|
||||||
self.node.interface_ip = pod_name
|
self.node.interface_ip = pod_name
|
||||||
self.zk.storeNode(self.node)
|
self.zk.storeNode(self.node)
|
||||||
|
@ -158,6 +158,16 @@ providers:
|
|||||||
node-selector:
|
node-selector:
|
||||||
storageType: ssd
|
storageType: ssd
|
||||||
privileged: true
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
csi:
|
||||||
|
driver: inline.storage.kubernetes.io
|
||||||
|
volume-mounts:
|
||||||
|
- mountPath: "/data"
|
||||||
|
name: my-csi-inline-vol
|
||||||
|
scheduler-name: niftyScheduler
|
||||||
|
labels:
|
||||||
|
environment: qa
|
||||||
|
|
||||||
- name: openshift
|
- name: openshift
|
||||||
driver: openshift
|
driver: openshift
|
||||||
@ -181,6 +191,16 @@ providers:
|
|||||||
node-selector:
|
node-selector:
|
||||||
storageType: ssd
|
storageType: ssd
|
||||||
privileged: true
|
privileged: true
|
||||||
|
volumes:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
csi:
|
||||||
|
driver: inline.storage.kubernetes.io
|
||||||
|
volume-mounts:
|
||||||
|
- mountPath: "/data"
|
||||||
|
name: my-csi-inline-vol
|
||||||
|
scheduler-name: niftyScheduler
|
||||||
|
labels:
|
||||||
|
environment: qa
|
||||||
|
|
||||||
- name: ec2-us-east-2
|
- name: ec2-us-east-2
|
||||||
driver: aws
|
driver: aws
|
||||||
|
17
nodepool/tests/fixtures/kubernetes.yaml
vendored
17
nodepool/tests/fixtures/kubernetes.yaml
vendored
@ -14,6 +14,7 @@ tenant-resource-limits:
|
|||||||
|
|
||||||
labels:
|
labels:
|
||||||
- name: pod-fedora
|
- name: pod-fedora
|
||||||
|
- name: pod-extra
|
||||||
- name: kubernetes-namespace
|
- name: kubernetes-namespace
|
||||||
|
|
||||||
providers:
|
providers:
|
||||||
@ -31,3 +32,19 @@ providers:
|
|||||||
- name: pod-fedora
|
- name: pod-fedora
|
||||||
type: pod
|
type: pod
|
||||||
image: docker.io/fedora:28
|
image: docker.io/fedora:28
|
||||||
|
- name: pod-extra
|
||||||
|
type: pod
|
||||||
|
image: docker.io/fedora:28
|
||||||
|
labels:
|
||||||
|
environment: qa
|
||||||
|
privileged: true
|
||||||
|
node-selector:
|
||||||
|
storageType: ssd
|
||||||
|
scheduler-name: myscheduler
|
||||||
|
volumes:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
csi:
|
||||||
|
driver: inline.storage.kubernetes.io
|
||||||
|
volume-mounts:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
mountPath: /data
|
||||||
|
21
nodepool/tests/fixtures/openshift.yaml
vendored
21
nodepool/tests/fixtures/openshift.yaml
vendored
@ -14,6 +14,7 @@ tenant-resource-limits:
|
|||||||
|
|
||||||
labels:
|
labels:
|
||||||
- name: pod-fedora
|
- name: pod-fedora
|
||||||
|
- name: pod-extra
|
||||||
- name: openshift-project
|
- name: openshift-project
|
||||||
- name: pod-fedora-secret
|
- name: pod-fedora-secret
|
||||||
|
|
||||||
@ -32,10 +33,26 @@ providers:
|
|||||||
- name: pod-fedora
|
- name: pod-fedora
|
||||||
type: pod
|
type: pod
|
||||||
image: docker.io/fedora:28
|
image: docker.io/fedora:28
|
||||||
python-path: '/usr/bin/python3'
|
|
||||||
shell-type: csh
|
|
||||||
- name: pod-fedora-secret
|
- name: pod-fedora-secret
|
||||||
type: pod
|
type: pod
|
||||||
image: docker.io/fedora:28
|
image: docker.io/fedora:28
|
||||||
image-pull-secrets:
|
image-pull-secrets:
|
||||||
- name: registry-secret
|
- name: registry-secret
|
||||||
|
- name: pod-extra
|
||||||
|
type: pod
|
||||||
|
image: docker.io/fedora:28
|
||||||
|
python-path: '/usr/bin/python3'
|
||||||
|
shell-type: csh
|
||||||
|
labels:
|
||||||
|
environment: qa
|
||||||
|
privileged: true
|
||||||
|
node-selector:
|
||||||
|
storageType: ssd
|
||||||
|
scheduler-name: myscheduler
|
||||||
|
volumes:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
csi:
|
||||||
|
driver: inline.storage.kubernetes.io
|
||||||
|
volume-mounts:
|
||||||
|
- name: my-csi-inline-vol
|
||||||
|
mountPath: /data
|
||||||
|
@ -24,6 +24,7 @@ from nodepool.zk import zookeeper as zk
|
|||||||
class FakeCoreClient(object):
|
class FakeCoreClient(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.namespaces = []
|
self.namespaces = []
|
||||||
|
self._pod_requests = []
|
||||||
|
|
||||||
class FakeApi:
|
class FakeApi:
|
||||||
class configuration:
|
class configuration:
|
||||||
@ -73,7 +74,7 @@ class FakeCoreClient(object):
|
|||||||
return FakeSecret
|
return FakeSecret
|
||||||
|
|
||||||
def create_namespaced_pod(self, ns, pod_body):
|
def create_namespaced_pod(self, ns, pod_body):
|
||||||
return
|
self._pod_requests.append((ns, pod_body))
|
||||||
|
|
||||||
def read_namespaced_pod(self, name, ns):
|
def read_namespaced_pod(self, name, ns):
|
||||||
class FakePod:
|
class FakePod:
|
||||||
@ -109,6 +110,7 @@ class TestDriverKubernetes(tests.DBTestCase):
|
|||||||
fake_get_client))
|
fake_get_client))
|
||||||
|
|
||||||
def test_kubernetes_machine(self):
|
def test_kubernetes_machine(self):
|
||||||
|
# Test a pod with default values
|
||||||
configfile = self.setup_config('kubernetes.yaml')
|
configfile = self.setup_config('kubernetes.yaml')
|
||||||
pool = self.useNodepool(configfile, watermark_sleep=1)
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
pool.start()
|
pool.start()
|
||||||
@ -133,12 +135,91 @@ class TestDriverKubernetes(tests.DBTestCase):
|
|||||||
{'key1': 'value1', 'key2': 'value2'})
|
{'key1': 'value1', 'key2': 'value2'})
|
||||||
self.assertEqual(node.cloud, 'admin-cluster.local')
|
self.assertEqual(node.cloud, 'admin-cluster.local')
|
||||||
self.assertEqual(node.host_id, 'k8s-default-pool-abcd-1234')
|
self.assertEqual(node.host_id, 'k8s-default-pool-abcd-1234')
|
||||||
|
ns, pod = self.fake_k8s_client._pod_requests[0]
|
||||||
|
self.assertEqual(pod['metadata'], {
|
||||||
|
'name': 'pod-fedora',
|
||||||
|
'labels': {
|
||||||
|
'nodepool_node_id': '0000000000',
|
||||||
|
'nodepool_provider_name': 'kubespray',
|
||||||
|
'nodepool_pool_name': 'main',
|
||||||
|
'nodepool_node_label': 'pod-fedora'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
self.assertEqual(pod['spec'], {
|
||||||
|
'containers': [{
|
||||||
|
'name': 'pod-fedora',
|
||||||
|
'image': 'docker.io/fedora:28',
|
||||||
|
'imagePullPolicy': 'IfNotPresent',
|
||||||
|
'command': ['/bin/sh', '-c'],
|
||||||
|
'args': ['while true; do sleep 30; done;'],
|
||||||
|
'env': []
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
|
||||||
node.state = zk.DELETING
|
node.state = zk.DELETING
|
||||||
self.zk.storeNode(node)
|
self.zk.storeNode(node)
|
||||||
|
|
||||||
self.waitForNodeDeletion(node)
|
self.waitForNodeDeletion(node)
|
||||||
|
|
||||||
|
def test_kubernetes_machine_extra(self):
|
||||||
|
# Test a pod with lots of extra settings
|
||||||
|
configfile = self.setup_config('kubernetes.yaml')
|
||||||
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
|
pool.start()
|
||||||
|
req = zk.NodeRequest()
|
||||||
|
req.state = zk.REQUESTED
|
||||||
|
req.tenant_name = 'tenant-1'
|
||||||
|
req.node_types.append('pod-extra')
|
||||||
|
self.zk.storeNodeRequest(req)
|
||||||
|
|
||||||
|
self.log.debug("Waiting for request %s", req.id)
|
||||||
|
req = self.waitForNodeRequest(req)
|
||||||
|
self.assertEqual(req.state, zk.FULFILLED)
|
||||||
|
|
||||||
|
self.assertNotEqual(req.nodes, [])
|
||||||
|
node = self.zk.getNode(req.nodes[0])
|
||||||
|
self.assertEqual(node.allocated_to, req.id)
|
||||||
|
self.assertEqual(node.state, zk.READY)
|
||||||
|
self.assertIsNotNone(node.launcher)
|
||||||
|
self.assertEqual(node.connection_type, 'kubectl')
|
||||||
|
self.assertEqual(node.connection_port.get('token'), 'fake-token')
|
||||||
|
self.assertEqual(node.attributes,
|
||||||
|
{'key1': 'value1', 'key2': 'value2'})
|
||||||
|
self.assertEqual(node.cloud, 'admin-cluster.local')
|
||||||
|
self.assertEqual(node.host_id, 'k8s-default-pool-abcd-1234')
|
||||||
|
ns, pod = self.fake_k8s_client._pod_requests[0]
|
||||||
|
self.assertEqual(pod['metadata'], {
|
||||||
|
'name': 'pod-extra',
|
||||||
|
'labels': {
|
||||||
|
'environment': 'qa',
|
||||||
|
'nodepool_node_id': '0000000000',
|
||||||
|
'nodepool_provider_name': 'kubespray',
|
||||||
|
'nodepool_pool_name': 'main',
|
||||||
|
'nodepool_node_label': 'pod-extra'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
self.assertEqual(pod['spec'], {
|
||||||
|
'containers': [{
|
||||||
|
'args': ['while true; do sleep 30; done;'],
|
||||||
|
'command': ['/bin/sh', '-c'],
|
||||||
|
'env': [],
|
||||||
|
'image': 'docker.io/fedora:28',
|
||||||
|
'imagePullPolicy': 'IfNotPresent',
|
||||||
|
'name': 'pod-extra',
|
||||||
|
'securityContext': {'privileged': True},
|
||||||
|
'volumeMounts': [{
|
||||||
|
'mountPath': '/data',
|
||||||
|
'name': 'my-csi-inline-vol'
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
'nodeSelector': {'storageType': 'ssd'},
|
||||||
|
'schedulerName': 'myscheduler',
|
||||||
|
'volumes': [{
|
||||||
|
'csi': {'driver': 'inline.storage.kubernetes.io'},
|
||||||
|
'name': 'my-csi-inline-vol'
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
|
||||||
def test_kubernetes_native(self):
|
def test_kubernetes_native(self):
|
||||||
configfile = self.setup_config('kubernetes.yaml')
|
configfile = self.setup_config('kubernetes.yaml')
|
||||||
pool = self.useNodepool(configfile, watermark_sleep=1)
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
|
@ -92,6 +92,9 @@ class FakeOpenshiftClient(object):
|
|||||||
|
|
||||||
|
|
||||||
class FakeCoreClient(object):
|
class FakeCoreClient(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._pod_requests = []
|
||||||
|
|
||||||
def create_namespaced_service_account(self, ns, sa_body):
|
def create_namespaced_service_account(self, ns, sa_body):
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -108,7 +111,7 @@ class FakeCoreClient(object):
|
|||||||
return FakeSecret
|
return FakeSecret
|
||||||
|
|
||||||
def create_namespaced_pod(self, ns, pod_body):
|
def create_namespaced_pod(self, ns, pod_body):
|
||||||
return
|
self._pod_requests.append((ns, pod_body))
|
||||||
|
|
||||||
def read_namespaced_pod(self, name, ns):
|
def read_namespaced_pod(self, name, ns):
|
||||||
class FakePod:
|
class FakePod:
|
||||||
@ -136,6 +139,7 @@ class TestDriverOpenshift(tests.DBTestCase):
|
|||||||
fake_get_client))
|
fake_get_client))
|
||||||
|
|
||||||
def test_openshift_machine(self):
|
def test_openshift_machine(self):
|
||||||
|
# Test a pod with default values
|
||||||
configfile = self.setup_config('openshift.yaml')
|
configfile = self.setup_config('openshift.yaml')
|
||||||
pool = self.useNodepool(configfile, watermark_sleep=1)
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
pool.start()
|
pool.start()
|
||||||
@ -149,6 +153,61 @@ class TestDriverOpenshift(tests.DBTestCase):
|
|||||||
req = self.waitForNodeRequest(req)
|
req = self.waitForNodeRequest(req)
|
||||||
self.assertEqual(req.state, zk.FULFILLED)
|
self.assertEqual(req.state, zk.FULFILLED)
|
||||||
|
|
||||||
|
self.assertNotEqual(req.nodes, [])
|
||||||
|
node = self.zk.getNode(req.nodes[0])
|
||||||
|
self.assertEqual(node.allocated_to, req.id)
|
||||||
|
self.assertEqual(node.state, zk.READY)
|
||||||
|
self.assertIsNotNone(node.launcher)
|
||||||
|
self.assertEqual(node.connection_type, 'kubectl')
|
||||||
|
self.assertEqual(node.connection_port.get('token'), 'fake-token')
|
||||||
|
self.assertEqual(node.python_path, 'auto')
|
||||||
|
self.assertEqual(node.shell_type, None)
|
||||||
|
self.assertEqual(node.attributes,
|
||||||
|
{'key1': 'value1', 'key2': 'value2'})
|
||||||
|
self.assertEqual(node.cloud, 'admin-cluster.local')
|
||||||
|
self.assertIsNone(node.host_id)
|
||||||
|
ns, pod = self.fake_k8s_client._pod_requests[0]
|
||||||
|
self.assertEqual(pod['metadata'], {
|
||||||
|
'name': 'pod-fedora',
|
||||||
|
'labels': {
|
||||||
|
'nodepool_node_id': '0000000000',
|
||||||
|
'nodepool_provider_name': 'openshift',
|
||||||
|
'nodepool_pool_name': 'main',
|
||||||
|
'nodepool_node_label': 'pod-fedora'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
self.assertEqual(pod['spec'], {
|
||||||
|
'containers': [{
|
||||||
|
'name': 'pod-fedora',
|
||||||
|
'image': 'docker.io/fedora:28',
|
||||||
|
'imagePullPolicy': 'IfNotPresent',
|
||||||
|
'command': ['/bin/sh', '-c'],
|
||||||
|
'args': ['while true; do sleep 30; done;'],
|
||||||
|
'env': []
|
||||||
|
}],
|
||||||
|
'imagePullSecrets': [],
|
||||||
|
})
|
||||||
|
|
||||||
|
node.state = zk.DELETING
|
||||||
|
self.zk.storeNode(node)
|
||||||
|
|
||||||
|
self.waitForNodeDeletion(node)
|
||||||
|
|
||||||
|
def test_openshift_machine_extra(self):
|
||||||
|
# Test a pod with lots of extra settings
|
||||||
|
configfile = self.setup_config('openshift.yaml')
|
||||||
|
pool = self.useNodepool(configfile, watermark_sleep=1)
|
||||||
|
pool.start()
|
||||||
|
req = zk.NodeRequest()
|
||||||
|
req.state = zk.REQUESTED
|
||||||
|
req.tenant_name = 'tenant-1'
|
||||||
|
req.node_types.append('pod-extra')
|
||||||
|
self.zk.storeNodeRequest(req)
|
||||||
|
|
||||||
|
self.log.debug("Waiting for request %s", req.id)
|
||||||
|
req = self.waitForNodeRequest(req)
|
||||||
|
self.assertEqual(req.state, zk.FULFILLED)
|
||||||
|
|
||||||
self.assertNotEqual(req.nodes, [])
|
self.assertNotEqual(req.nodes, [])
|
||||||
node = self.zk.getNode(req.nodes[0])
|
node = self.zk.getNode(req.nodes[0])
|
||||||
self.assertEqual(node.allocated_to, req.id)
|
self.assertEqual(node.allocated_to, req.id)
|
||||||
@ -162,6 +221,39 @@ class TestDriverOpenshift(tests.DBTestCase):
|
|||||||
{'key1': 'value1', 'key2': 'value2'})
|
{'key1': 'value1', 'key2': 'value2'})
|
||||||
self.assertEqual(node.cloud, 'admin-cluster.local')
|
self.assertEqual(node.cloud, 'admin-cluster.local')
|
||||||
self.assertIsNone(node.host_id)
|
self.assertIsNone(node.host_id)
|
||||||
|
ns, pod = self.fake_k8s_client._pod_requests[0]
|
||||||
|
self.assertEqual(pod['metadata'], {
|
||||||
|
'name': 'pod-extra',
|
||||||
|
'labels': {
|
||||||
|
'environment': 'qa',
|
||||||
|
'nodepool_node_id': '0000000000',
|
||||||
|
'nodepool_provider_name': 'openshift',
|
||||||
|
'nodepool_pool_name': 'main',
|
||||||
|
'nodepool_node_label': 'pod-extra'
|
||||||
|
},
|
||||||
|
})
|
||||||
|
self.assertEqual(pod['spec'], {
|
||||||
|
'containers': [{
|
||||||
|
'args': ['while true; do sleep 30; done;'],
|
||||||
|
'command': ['/bin/sh', '-c'],
|
||||||
|
'env': [],
|
||||||
|
'image': 'docker.io/fedora:28',
|
||||||
|
'imagePullPolicy': 'IfNotPresent',
|
||||||
|
'name': 'pod-extra',
|
||||||
|
'securityContext': {'privileged': True},
|
||||||
|
'volumeMounts': [{
|
||||||
|
'mountPath': '/data',
|
||||||
|
'name': 'my-csi-inline-vol'
|
||||||
|
}],
|
||||||
|
}],
|
||||||
|
'nodeSelector': {'storageType': 'ssd'},
|
||||||
|
'schedulerName': 'myscheduler',
|
||||||
|
'imagePullSecrets': [],
|
||||||
|
'volumes': [{
|
||||||
|
'csi': {'driver': 'inline.storage.kubernetes.io'},
|
||||||
|
'name': 'my-csi-inline-vol'
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
|
||||||
node.state = zk.DELETING
|
node.state = zk.DELETING
|
||||||
self.zk.storeNode(node)
|
self.zk.storeNode(node)
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Added support for specifying the scheduler name, additional metadata, and volume mounts in Kubernetes and OpenShift drivers.
|
Loading…
x
Reference in New Issue
Block a user