diff --git a/kubeflow/core/prototypes/tf-job-operator.jsonnet b/kubeflow/core/prototypes/tf-job-operator.jsonnet index 97504750e19..378d9df35d8 100644 --- a/kubeflow/core/prototypes/tf-job-operator.jsonnet +++ b/kubeflow/core/prototypes/tf-job-operator.jsonnet @@ -5,10 +5,12 @@ // @param name string Name to give to each of the components // @optionalParam namespace string null Namespace to use for the components. It is automatically inherited from the environment if not set. // @optionalParam cloud string null String identifying the cloud to customize the deployment for. -// @optionalParam tfJobImage string gcr.io/kubeflow-images-public/tf_operator:v20180809-d2509aa The image for the TfJob controller. +// @optionalParam tfJobImage string gcr.io/kubeflow-images-public/tf_operator:v20180822-b576c253 The image for the TfJob controller. // @optionalParam tfDefaultImage string null The default image to use for TensorFlow. // @optionalParam tfJobUiServiceType string ClusterIP The service type for the UI. // @optionalParam tfJobVersion string v1alpha2 which version of the TFJob operator to use +// @optionalParam deploymentScope string cluster The scope at which tf-job-operator should be deployed - valid values are cluster, namespace. +// @optionalParam deploymentNamespace string null The namespace to which tf-job-operator should be scoped. If deploymentScope is set to cluster, this is ignored. local k = import "k.libsonnet"; local tfjob = import "kubeflow/core/tf-job-operator.libsonnet"; diff --git a/kubeflow/core/tests/tf-job_test.jsonnet b/kubeflow/core/tests/tf-job_test.jsonnet index eea13d79b40..d139fc1f30d 100644 --- a/kubeflow/core/tests/tf-job_test.jsonnet +++ b/kubeflow/core/tests/tf-job_test.jsonnet @@ -106,7 +106,7 @@ std.assertEqual( ) && std.assertEqual( - tfjob.parts(params.namespace).operatorRole, + tfjob.parts(params.namespace).operatorRole("cluster", "default"), { apiVersion: "rbac.authorization.k8s.io/v1beta1", kind: "ClusterRole", @@ -195,7 +195,7 @@ std.assertEqual( ) && std.assertEqual( - tfjob.parts(params.namespace).operatorRoleBinding, + tfjob.parts(params.namespace).operatorRoleBinding("cluster", "default"), { apiVersion: "rbac.authorization.k8s.io/v1beta1", kind: "ClusterRoleBinding", diff --git a/kubeflow/core/tf-job-operator.libsonnet b/kubeflow/core/tf-job-operator.libsonnet index 5b2d86abce3..fc32a2f08d3 100644 --- a/kubeflow/core/tf-job-operator.libsonnet +++ b/kubeflow/core/tf-job-operator.libsonnet @@ -3,8 +3,8 @@ $.parts(params.namespace).configMap(params.cloud, params.tfDefaultImage), $.parts(params.namespace).serviceAccount, - $.parts(params.namespace).operatorRole, - $.parts(params.namespace).operatorRoleBinding, + $.parts(params.namespace).operatorRole(params.deploymentScope, params.deploymentNamespace), + $.parts(params.namespace).operatorRoleBinding(params.deploymentScope, params.deploymentNamespace), $.parts(params.namespace).uiRole, $.parts(params.namespace).uiRoleBinding, $.parts(params.namespace).uiService(params.tfJobUiServiceType), @@ -15,7 +15,7 @@ if params.tfJobVersion == "v1alpha2" then [ $.parts(params.namespace).crdv1alpha2, - $.parts(params.namespace).tfJobDeployV1Alpha2(params.tfJobImage), + $.parts(params.namespace).tfJobDeployV1Alpha2(params.tfJobImage, params.deploymentScope, params.deploymentNamespace), ] else [ @@ -167,7 +167,7 @@ }, }, // tfJobDeploy - tfJobDeployV1Alpha2(image): { + tfJobDeployV1Alpha2(image, deploymentScope, deploymentNamespace): { apiVersion: "extensions/v1beta1", kind: "Deployment", metadata: { @@ -185,12 +185,13 @@ spec: { containers: [ { - command: [ + command: std.prune([ "/opt/kubeflow/tf-operator.v2", "--alsologtostderr", "-v=1", - ], - env: [ + if deploymentScope == "namespace" then ("--namespace=" + deploymentNamespace), + ]), + env: std.prune([ { name: "MY_POD_NAMESPACE", valueFrom: { @@ -207,7 +208,15 @@ }, }, }, - ], + if deploymentScope == "namespace" then { + name: "KUBEFLOW_NAMESPACE", + valueFrom: { + fieldRef: { + fieldPath: "metadata.namespace", + }, + }, + }, + ]), image: image, name: "tf-job-operator", volumeMounts: [ @@ -303,14 +312,16 @@ }, }, - operatorRole: { + operatorRole(deploymentScope, deploymentNamespace): { + local roleType = if deploymentScope == "cluster" then "ClusterRole" else "Role", apiVersion: "rbac.authorization.k8s.io/v1beta1", - kind: "ClusterRole", + kind: roleType, metadata: { labels: { app: "tf-job-operator", }, name: "tf-job-operator", + [if deploymentScope == "namespace" then "namespace"]: deploymentNamespace, }, rules: [ { @@ -389,18 +400,21 @@ ], }, // operator-role - operatorRoleBinding:: { + operatorRoleBinding(deploymentScope, deploymentNamespace): { + local bindingType = if deploymentScope == "cluster" then "ClusterRoleBinding" else "RoleBinding", + local roleType = if deploymentScope == "cluster" then "ClusterRole" else "Role", apiVersion: "rbac.authorization.k8s.io/v1beta1", - kind: "ClusterRoleBinding", + kind: bindingType, metadata: { labels: { app: "tf-job-operator", }, name: "tf-job-operator", + [if deploymentScope == "namespace" then "namespace"]: deploymentNamespace, }, roleRef: { apiGroup: "rbac.authorization.k8s.io", - kind: "ClusterRole", + kind: roleType, name: "tf-job-operator", }, subjects: [