diff --git a/.github/bin/check-resources.sh b/.github/bin/check-resources.sh index b2bc3e9ae..270cf4e28 100755 --- a/.github/bin/check-resources.sh +++ b/.github/bin/check-resources.sh @@ -13,6 +13,8 @@ # Checks if repository resources are up to date: # - CRDs # - nightly olm bundle +# - Dockerfile & operator.yaml +# - DW resources set -e @@ -27,13 +29,17 @@ installOperatorSDK() { if [[ ! -x "${OPERATOR_SDK_BINARY}" ]]; then OPERATOR_SDK_TEMP_DIR="$(mktemp -q -d -t "OPERATOR_SDK_XXXXXX" 2>/dev/null || mktemp -q -d)" pushd "${OPERATOR_SDK_TEMP_DIR}" || exit + echo "[INFO] Downloading 'operator-sdk' cli tool..." + OPERATOR_SDK=$(yq -r ".\"operator-sdk\"" "${ROOT_PROJECT_DIR}/REQUIREMENTS") curl -sLo operator-sdk $(curl -sL https://api.github.com/repos/operator-framework/operator-sdk/releases/tags/${OPERATOR_SDK} | jq -r "[.assets[] | select(.name == \"operator-sdk-${OPERATOR_SDK}-x86_64-linux-gnu\")] | first | .browser_download_url") export OPERATOR_SDK_BINARY="${OPERATOR_SDK_TEMP_DIR}/operator-sdk" chmod +x "${OPERATOR_SDK_BINARY}" + echo "[INFO] Downloading completed!" echo "[INFO] $(${OPERATOR_SDK_BINARY} version)" + popd || exit fi } @@ -41,10 +47,7 @@ installOperatorSDK() { updateResources() { export NO_DATE_UPDATE="true" export NO_INCREMENT="true" - - pushd "${ROOT_PROJECT_DIR}" || true - source "${ROOT_PROJECT_DIR}/olm/update-resources.sh" - popd || true + . "${ROOT_PROJECT_DIR}/olm/update-resources.sh" } # check_che_types function check first if pkg/apis/org/v1/che_types.go file suffer modifications and @@ -63,10 +66,9 @@ checkCRDs() { local checlusterbackup_CRD_V1BETA1="deploy/crds/org.eclipse.che_checlusterbackups_crd-v1beta1.yaml" local checlusterrestore_CRD_V1BETA1="deploy/crds/org.eclipse.che_checlusterrestores_crd-v1beta1.yaml" - pushd "${ROOT_PROJECT_DIR}" - source "${ROOT_PROJECT_DIR}/olm/update-resources.sh" - - changedFiles=($(git diff --name-only)) + changedFiles=( + $(git diff --name-only) + ) # Check if there are any difference in the crds. If yes, then fail check. if [[ " ${changedFiles[*]} " =~ $checluster_CRD_V1 ]] || [[ " ${changedFiles[*]} " =~ $checluster_CRD_V1BETA1 ]] || \ @@ -80,7 +82,6 @@ checkCRDs() { else echo "[INFO] CRDs files are up to date." fi - popd } checkNightlyOlmBundle() { @@ -90,9 +91,9 @@ checkNightlyOlmBundle() { local CRD_FILE_KUBERNETES="deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/org_v1_che_crd.yaml" local CRD_FILE_OPENSHIFT="deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/org_v1_che_crd.yaml" - pushd "${ROOT_PROJECT_DIR}" || true - - changedFiles=($(git diff --name-only)) + changedFiles=( + $(git diff --name-only) + ) if [[ " ${changedFiles[*]} " =~ $CSV_FILE_OPENSHIFT ]] || [[ " ${changedFiles[*]} " =~ $CSV_FILE_OPENSHIFT ]] || \ [[ " ${changedFiles[*]} " =~ $CRD_FILE_KUBERNETES ]] || [[ " ${changedFiles[*]} " =~ $CRD_FILE_OPENSHIFT ]]; then echo "[ERROR] Nighlty bundle is not up to date: ${BASH_REMATCH}" @@ -101,17 +102,15 @@ checkNightlyOlmBundle() { else echo "[INFO] Nightly bundles are up to date." fi - - popd || true } checkDockerfile() { # files to check local Dockerfile="Dockerfile" - pushd "${ROOT_PROJECT_DIR}" || true - - changedFiles=($(git diff --name-only)) + changedFiles=( + $(git diff --name-only) + ) if [[ " ${changedFiles[*]} " =~ $Dockerfile ]]; then echo "[ERROR] Dockerfile is not up to date" echo "[ERROR] Run 'olm/update-resources.sh' to update Dockerfile" @@ -119,17 +118,15 @@ checkDockerfile() { else echo "[INFO] Dockerfile is up to date." fi - - popd || true } checkOperatorYaml() { # files to check local OperatorYaml="deploy/operator.yaml" - pushd "${ROOT_PROJECT_DIR}" || true - - changedFiles=($(git diff --name-only)) + changedFiles=( + $(git diff --name-only) + ) if [[ " ${changedFiles[*]} " =~ $OperatorYaml ]]; then echo "[ERROR] $OperatorYaml is not up to date" echo "[ERROR] Run 'olm/update-resources.sh' to update $OperatorYaml" @@ -137,15 +134,37 @@ checkOperatorYaml() { else echo "[INFO] $OperatorYaml is up to date." fi +} - popd || true +checkRoles() { + # files to check + local RoleYaml="deploy/role.yaml" + local ClusterRoleYaml="deploy/cluster_role.yaml" + local ProxyClusterRoleYaml="deploy/proxy_cluster_role.yaml" + + changedFiles=( + $(git diff --name-only) + ) + if [[ " ${changedFiles[*]} " =~ $RoleYaml ]] || [[ " ${changedFiles[*]} " =~ $ClusterRoleYaml ]] || [[ " ${changedFiles[*]} " =~ $ProxyClusterRoleYaml ]]; then + echo "[ERROR] Roles are not up to date: ${BASH_REMATCH}" + echo "[ERROR] Run 'olm/update-resources.sh' to update them." + exit 1 + else + echo "[INFO] Roles are up to date." + fi } installOperatorSDK + +pushd "${ROOT_PROJECT_DIR}" || true + updateResources checkCRDs +checkRoles checkNightlyOlmBundle checkDockerfile checkOperatorYaml +popd || true + echo "[INFO] Done." diff --git a/Dockerfile b/Dockerfile index 924e1e242..81afb10b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -57,6 +57,7 @@ COPY --from=builder /che-operator/templates/keycloak-update.sh /tmp/keycloak-upd COPY --from=builder /che-operator/templates/oauth-provision.sh /tmp/oauth-provision.sh COPY --from=builder /che-operator/templates/delete-identity-provider.sh /tmp/delete-identity-provider.sh COPY --from=builder /che-operator/templates/create-github-identity-provider.sh /tmp/create-github-identity-provider.sh + COPY --from=builder /tmp/devworkspace-operator/templates/deploy /tmp/devworkspace-operator/templates COPY --from=builder /tmp/devworkspace-che-operator/templates/deploy /tmp/devworkspace-che-operator/templates COPY --from=builder /tmp/restic/restic /usr/local/bin/restic diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 8e755de0b..6aa647ce1 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -119,6 +119,7 @@ func main() { // Create a new Cmd to provide shared dependencies and start components options := manager.Options{ Namespace: namespace, + MetricsBindAddress: ":8081", HealthProbeBindAddress: ":6789", } diff --git a/deploy.sh b/deploy.sh index 7fd9c790b..df573c8f1 100755 --- a/deploy.sh +++ b/deploy.sh @@ -11,18 +11,27 @@ # Red Hat, Inc. - initial API and implementation set -e -set -x BASE_DIR=$(cd "$(dirname "$0")"; pwd) +NAMESPACE="eclipse-che" +CHE_OPERATOR_IMAGE="quay.io/eclipse/che-operator:nightly" -NAMESPACE=$1 +while [[ "$#" -gt 0 ]]; do + case $1 in + '--namespace'|'-n') NAMESPACE=$2; shift 1;; + '--che-operator-image'|'-i') CHE_OPERATOR_IMAGE=$2; shift 1;; + esac + shift 1 +done +set +e; oc create namespace $NAMESPACE; set -e oc apply -f ${BASE_DIR}/deploy/service_account.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/role.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/role_binding.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/cluster_role.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/cluster_role_binding.yaml -n $NAMESPACE - +oc apply -f ${BASE_DIR}/deploy/proxy_cluster_role.yaml -n $NAMESPACE +oc apply -f ${BASE_DIR}/deploy/proxy_cluster_role_binding.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/crds/org_v1_che_crd.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml -n $NAMESPACE @@ -30,5 +39,11 @@ oc apply -f ${BASE_DIR}/deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml # sometimes the operator cannot get CRD right away sleep 2 -oc apply -f ${BASE_DIR}/deploy/operator.yaml -n $NAMESPACE +cp -f ${BASE_DIR}/deploy/operator.yaml /tmp/operator.yaml +yq -riyY "( .spec.template.spec.containers[] | select(.name == \"che-operator\") | .image ) = \"${CHE_OPERATOR_IMAGE}\"" /tmp/operator.yaml +oc apply -f /tmp/operator.yaml -n $NAMESPACE oc apply -f ${BASE_DIR}/deploy/crds/org_v1_che_cr.yaml -n $NAMESPACE + +echo "[INFO] Start printing logs..." +oc wait --for=condition=ready pod -l app.kubernetes.io/component=che-operator -n $NAMESPACE --timeout=60s +oc logs $(oc get pods -o json -n $NAMESPACE | jq -r '.items[] | select(.metadata.name | test("che-operator-")).metadata.name') -n $NAMESPACE --all-containers -f diff --git a/deploy/cluster_role.yaml b/deploy/cluster_role.yaml index 13a643a76..4dbe8e814 100644 --- a/deploy/cluster_role.yaml +++ b/deploy/cluster_role.yaml @@ -17,6 +17,7 @@ metadata: app.kubernetes.io/instance: che app.kubernetes.io/component: che-operator rules: + ### CHE-OPERATOR ROLES ONLY: BEGIN - apiGroups: - oauth.openshift.io resources: @@ -281,450 +282,469 @@ rules: - subscriptions verbs: - get -# devworkspace requirements: devworkspace-controller-edit-workspaces cluster roles - apiGroups: - - workspace.devfile.io + - metrics.k8s.io resources: - - devworkspaces - - devworkspacetemplates + - pods + - nodes verbs: - - create - - delete - - deletecollection - - patch - - update + - get + - list + - watch + ### CHE-OPERATOR ROLES ONLY: END + # devworkspace-controller-view-workspaces.ClusterRole.yaml - apiGroups: - - controller.devfile.io + - workspace.devfile.io resources: - - devworkspaceroutings - - components + - devworkspaces + - devworkspacetemplates verbs: - - create - - delete - - deletecollection - - patch - - update -# devworkspace requirements: devworkspace-controller-proxy-role cluster roles + - get + - list + - watch - apiGroups: - - authentication.k8s.io + - controller.devfile.io resources: - - tokenreviews + - devworkspaceroutings + - components verbs: - - create + - get + - list + - watch + # devworkspace-controller-edit-workspaces.ClusterRole.yaml - apiGroups: - - authorization.k8s.io + - workspace.devfile.io resources: - - subjectaccessreviews + - devworkspaces + - devworkspacetemplates verbs: - - create -# devworkspace requirements: devworkspace-controller-role cluster roles + - create + - delete + - deletecollection + - patch + - update - apiGroups: - - "" + - controller.devfile.io resources: - - configmaps - - persistentvolumeclaims - - pods - - secrets - - serviceaccounts + - devworkspaceroutings + - components verbs: - - '*' + - create + - delete + - deletecollection + - patch + - update + # devworkspace-controller-leader-election-role.Role.yaml - apiGroups: - - "" + - "" resources: - - namespaces + - configmaps verbs: - - get - - list - - watch + - get + - list + - watch + - create + - update + - patch + - delete - apiGroups: - - metrics.k8s.io + - "" resources: - - pods - - nodes + - configmaps/status verbs: - - get - - list - - watch + - get + - update + - patch - apiGroups: - - batch - - "" + - "" resources: - - pods/exec + - events verbs: - - create + - create + - patch + # devworkspace-controller-proxy-role.ClusterRole.yaml - apiGroups: - - "" + - authentication.k8s.io resources: - - services + - tokenreviews verbs: - - '*' + - create - apiGroups: - - admissionregistration.k8s.io + - authorization.k8s.io resources: - - mutatingwebhookconfigurations - - validatingwebhookconfigurations + - subjectaccessreviews verbs: - - create - - delete - - get - - list - - patch - - update - - watch + - create + # devworkspace-controller-role.ClusterRole.yaml - apiGroups: - - apps - resourceNames: - - devworkspace-controller + - "" resources: - - deployments/finalizers + - configmaps + - persistentvolumeclaims + - pods + - secrets + - serviceaccounts verbs: - - update + - '*' - apiGroups: - - apps - - extensions + - "" resources: - - deployments + - namespaces verbs: - - get - - list - - watch + - get + - list + - watch - apiGroups: - - apps - - extensions + - "" resources: - - deployments - - replicasets + - pods/exec verbs: - - '*' + - create - apiGroups: - - apps - - extensions + - "" resources: - - replicasets + - services verbs: - - get - - list - - watch + - '*' - apiGroups: - - batch + - admissionregistration.k8s.io resources: - - jobs + - mutatingwebhookconfigurations + - validatingwebhookconfigurations verbs: - - create - - delete - - get - - list - - patch - - update - - watch + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - - controller.devfile.io + - apps + resourceNames: + - devworkspace-controller resources: - - '*' + - deployments/finalizers verbs: - - '*' + - update - apiGroups: - - controller.devfile.io + - apps + - extensions resources: - - devworkspaceroutings + - deployments verbs: - - '*' + - get + - list + - watch - apiGroups: - - controller.devfile.io + - apps + - extensions resources: - - devworkspaceroutings/status + - deployments + - replicasets verbs: - - get - - patch - - update + - '*' - apiGroups: - - extensions + - apps + - extensions resources: - - ingresses + - replicasets verbs: - - '*' + - get + - list + - watch - apiGroups: - - monitoring.coreos.com + - batch resources: - - servicemonitors + - jobs verbs: - - create - - get + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - - oauth.openshift.io + - controller.devfile.io resources: - - oauthclients + - '*' verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch + - '*' - apiGroups: - - rbac.authorization.k8s.io + - controller.devfile.io resources: - - clusterrolebindings - - clusterroles - - rolebindings - - roles + - devworkspaceroutings verbs: - - create - - get - - list - - update - - watch + - '*' - apiGroups: - - route.openshift.io + - controller.devfile.io resources: - - routes + - devworkspaceroutings/status verbs: - - '*' + - get + - patch + - update - apiGroups: - - route.openshift.io + - extensions resources: - - routes/custom-host + - ingresses verbs: - - create + - '*' - apiGroups: - - workspace.devfile.io + - monitoring.coreos.com resources: - - '*' + - servicemonitors verbs: - - '*' -# devworkspace requirements: devworkspace-controller-view-workspaces cluster roles + - create + - get - apiGroups: - - workspace.devfile.io + - oauth.openshift.io resources: - - devworkspaces - - devworkspacetemplates + - oauthclients verbs: - - get - - list - - watch + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch - apiGroups: - - controller.devfile.io + - rbac.authorization.k8s.io resources: - - devworkspaceroutings - - components + - clusterrolebindings + - clusterroles + - rolebindings + - roles verbs: - - get - - list - - watch -# devworkspace requirements: devworkspace-controller-metrics-reader cluster roles - - nonResourceURLs: - - /metrics + - create + - get + - list + - update + - watch + - apiGroups: + - route.openshift.io + resources: + - routes verbs: - - get -# devworkspace requirements: devworkspace-controller-leader-election-role roles + - '*' - apiGroups: - - "" + - route.openshift.io resources: - - configmaps + - routes/custom-host verbs: - - get - - list - - watch - - create - - update - - patch - - delete + - create - apiGroups: - - "" + - workspace.devfile.io resources: - - configmaps/status + - '*' verbs: - - get - - update - - patch + - '*' + # devworkspace-controller-view-workspaces.ClusterRole.yaml - apiGroups: - - "" + - workspace.devfile.io resources: - - events + - devworkspaces + - devworkspacetemplates verbs: - - create - - patch -# devworkspace-che requirements + - get + - list + - watch - apiGroups: - - "" + - controller.devfile.io resources: - - configmaps - - persistentvolumeclaims - - pods - - secrets - - serviceaccounts + - devworkspaceroutings + - components verbs: - - '*' + - get + - list + - watch + # devworkspace-che-role.ClusterRole.yaml - apiGroups: - - "" + - "" resources: - - namespaces + - configmaps + - persistentvolumeclaims + - pods + - secrets + - serviceaccounts verbs: - - get + - '*' - apiGroups: - - "" + - "" resources: - - pods/exec + - namespaces verbs: - - create + - get - apiGroups: - - "" + - "" resources: - - services + - pods/exec verbs: - - '*' + - create - apiGroups: - - apps + - "" + resources: + - services + verbs: + - '*' + - apiGroups: + - apps resourceNames: - - devworkspace-che-operator + - devworkspace-che-operator resources: - - deployments/finalizers + - deployments/finalizers verbs: - - update + - update - apiGroups: - - apps - - extensions + - apps + - extensions resources: - deployments verbs: - - get - - list - - watch + - get + - list + - watch - apiGroups: - - apps - - extensions + - apps + - extensions resources: - - deployments - - replicasets + - deployments + - replicasets verbs: - - '*' + - '*' - apiGroups: - - apps - - extensions + - apps + - extensions resources: - - replicasets + - replicasets verbs: - - get - - list - - watch + - get + - list + - watch - apiGroups: - - batch + - batch resources: - - jobs + - jobs verbs: - - create - - delete - - get - - update - - watch + - create + - delete + - get + - update + - watch - apiGroups: - - che.eclipse.org + - che.eclipse.org resources: - - '*' + - '*' verbs: - - '*' + - '*' - apiGroups: - - che.eclipse.org + - che.eclipse.org resources: - - chemanagers + - chemanagers verbs: - - '*' + - '*' - apiGroups: - - che.eclipse.org + - che.eclipse.org resources: - - chemanagers/status + - chemanagers/status verbs: - - get - - patch - - update + - get + - patch + - update - apiGroups: - - che.eclipse.org + - che.eclipse.org resources: - - chemanagers/finalizers + - chemanagers/finalizers verbs: - - update + - update - apiGroups: - - controller.devfile.io + - controller.devfile.io resources: - - devworkspaceroutings + - devworkspaceroutings verbs: - - '*' + - '*' - apiGroups: - - controller.devfile.io + - controller.devfile.io resources: - - devworkspaceroutings/finalizers + - devworkspaceroutings/finalizers verbs: - - update + - update - apiGroups: - - controller.devfile.io + - controller.devfile.io resources: - - devworkspaceroutings/status + - devworkspaceroutings/status verbs: - - get - - patch - - update + - get + - patch + - update - apiGroups: - - "" + - "" resources: - - configmap + - configmap verbs: - - create - - delete - - get - - list - - patch - - update - - watch + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - - extensions + - extensions resources: - - ingresses + - ingresses verbs: - - '*' + - '*' - apiGroups: - - monitoring.coreos.com + - monitoring.coreos.com resources: - - servicemonitors + - servicemonitors verbs: - - create - - get + - create + - get - apiGroups: - - oauth.openshift.io + - oauth.openshift.io resources: - - oauthclients + - oauthclients verbs: - - create - - delete - - deletecollection - - get - - list - - patch - - update - - watch + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch - apiGroups: - - rbac.authorization.k8s.io + - rbac.authorization.k8s.io resources: - - clusterrolebindings - - clusterroles - - rolebindings - - roles + - clusterrolebindings + - clusterroles + - rolebindings + - roles verbs: - - create - - get - - list - - update - - watch + - create + - get + - list + - update + - watch - apiGroups: - - route.openshift.io + - route.openshift.io resources: - - routes + - routes verbs: - - '*' + - '*' - apiGroups: - - route.openshift.io + - route.openshift.io resources: - - routes/custom-host + - routes/custom-host verbs: - - create + - create + # devworkspace-che-metrics-reader.ClusterRole.yaml + - nonResourceURLs: + - /metrics + verbs: + - get diff --git a/deploy/crds/chemanagers.che.eclipse.org.CustomResourceDefinition.yaml b/deploy/crds/chemanagers.che.eclipse.org.CustomResourceDefinition.yaml new file mode 100644 index 000000000..fbbf1c06b --- /dev/null +++ b/deploy/crds/chemanagers.che.eclipse.org.CustomResourceDefinition.yaml @@ -0,0 +1,145 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.5.0 + creationTimestamp: null + labels: + app.kubernetes.io/name: devworkspace-che-operator + app.kubernetes.io/part-of: devworkspace-che-operator + name: chemanagers.che.eclipse.org +spec: + group: che.eclipse.org + names: + kind: CheManager + listKind: CheManagerList + plural: chemanagers + singular: chemanager + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: CheManager is the configuration of the CheManager layer of Devworkspace. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CheManagerSpec holds the configuration of the Che controller. + properties: + gatewayConfigurerImage: + description: GatewayConfigurerImage is the docker image to use for + the sidecar of the Che gateway that is used to configure it. This + is only used when GatewayDisabled is false. If not defined in the + CR, it is taken from the `RELATED_IMAGE_gateway_configurer` environment + variable of the che operator deployment/pod. If not defined there, + it defaults to a hardcoded value. + type: string + gatewayDisabled: + description: "GatewayDisabled enables or disables routing of the url + rewrite supporting devworkspace endpoints through a common gateway + (the hostname of which is defined by the GatewayHost). \n Default + value is \"false\" meaning that the gateway is enabled. \n If set + to false (i.e. the gateway is enabled), endpoints marked using the + \"urlRewriteSupported\" attribute are exposed on unique subpaths + of the GatewayHost, while the rest of the devworkspace endpoints + are exposed on subdomains of the RoutingSuffix specified by the + DevWorkspaceRouting of the devworkspace. \n If set to true (i.e. + the gateway is disabled), all endpoints are deployed on subdomains + of the RoutingSuffix." + type: boolean + gatewayHost: + description: "GatewayHost is the full host name used to expose devworkspace + endpoints that support url rewriting reverse proxy. See the GatewayDisabled + attribute for a more detailed description of where and how are devworkspace + endpoints exposed in various configurations. \n This attribute is + mandatory on Kubernetes, optional on OpenShift." + type: string + gatewayImage: + description: GatewayImage is the docker image to use for the Che gateway. This + is only used if GatewayDisabled is false. If not defined in the + CR, it is taken from the `RELATED_IMAGE_gateway` environment variable + of the che operator deployment/pod. If not defined there, it defaults + to a hardcoded value. + type: string + k8s: + description: K8s contains the configuration specific only to Kubernetes + properties: + ingressAnnotations: + additionalProperties: + type: string + description: "IngressAnnotations are the annotations to be put + on the generated ingresses. This can be used to configure the + ingress class and the ingress-controller-specific behavior for + both the gateway and the ingresses created to expose the Devworkspace + component endpoints. When not specified, this defaults to: \n + \ kubernetes.io/ingress.class: \"nginx\" + \ nginx.ingress.kubernetes.io/proxy-read-timeout: \"3600\", + \ nginx.ingress.kubernetes.io/proxy-connect-timeout: \"3600\", + \ nginx.ingress.kubernetes.io/ssl-redirect: \"true\"" + type: object + type: object + tlsSecretName: + description: "Name of a secret that will be used to setup ingress/route + TLS certificate. When the field is empty string, the default cluster + certificate will be used. The same secret is assumed to exist in + the same namespace as the CheManager CR and is used for both the + gateway and all devworkspace endpoints. In case of the devworkspace + endpoints, the secret is copied to the namespace of the devworkspace. + \n The secret has to be of type \"tls\"." + type: string + workspaceBaseDomain: + description: The workspace endpoints that need to be deployed on a + subdomain will be deployed on subdomains of this base domain. This + is mandatory on Kubernetes. On OpenShift, an attempt is made to + automatically figure out the base domain of the routes. The resolved + value of this property is written to the status. + type: string + type: object + status: + properties: + gatewayHost: + description: GatewayHost is the resolved host of the ingress/route, + on which the gateway is accessible. + type: string + gatewayPhase: + description: GatewayPhase specifies the phase in which the singlehost + gateway deployment currently is. If the manager routing is not singlehost, + this is "Inactive" + type: string + message: + description: Message contains further human-readable info for why + the manager is in the phase it currently is. + type: string + phase: + description: Phase is the phase in which the manager as a whole finds + itself in. + type: string + workspaceBaseDomain: + description: The resolved workspace base domain. This is either the + copy of the explicitly defined property of the same name in the + spec or, if it is undefined in the spec and we're running on OpenShift, + the automatically resolved basedomain for routes. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/deploy/crds/devworkspaceroutings.controller.devfile.io.CustomResourceDefinition.yaml b/deploy/crds/devworkspaceroutings.controller.devfile.io.CustomResourceDefinition.yaml new file mode 100644 index 000000000..acf37cc41 --- /dev/null +++ b/deploy/crds/devworkspaceroutings.controller.devfile.io.CustomResourceDefinition.yaml @@ -0,0 +1,3684 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + creationTimestamp: null + labels: + app.kubernetes.io/name: devworkspace-controller + app.kubernetes.io/part-of: devworkspace-operator + name: devworkspaceroutings.controller.devfile.io +spec: + group: controller.devfile.io + names: + kind: DevWorkspaceRouting + listKind: DevWorkspaceRoutingList + plural: devworkspaceroutings + shortNames: + - dwr + singular: devworkspacerouting + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The owner DevWorkspace's unique id + jsonPath: .spec.devworkspaceId + name: DevWorkspace ID + type: string + - description: The current phase + jsonPath: .status.phase + name: Phase + type: string + - description: Additional info about DevWorkspaceRouting state + jsonPath: .status.message + name: Info + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: DevWorkspaceRouting is the Schema for the devworkspaceroutings + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: DevWorkspaceRoutingSpec defines the desired state of DevWorkspaceRouting + properties: + devworkspaceId: + description: Id for the DevWorkspace being routed + type: string + endpoints: + additionalProperties: + items: + properties: + attributes: + additionalProperties: + x-kubernetes-preserve-unknown-fields: true + description: "Map of implementation-dependant string-based + free-form attributes. \n Examples of Che-specific attributes: + \n - cookiesAuthEnabled: \"true\" / \"false\", \n - type: + \"terminal\" / \"ide\" / \"ide-dev\"," + type: object + x-kubernetes-preserve-unknown-fields: true + exposure: + default: public + description: "Describes how the endpoint should be exposed + on the network. \n - `public` means that the endpoint will + be exposed on the public network, typically through a K8S + ingress or an OpenShift route. \n - `internal` means that + the endpoint will be exposed internally outside of the main + devworkspace POD, typically by K8S services, to be consumed + by other elements running on the same cloud internal network. + \n - `none` means that the endpoint will not be exposed + and will only be accessible inside the main devworkspace + POD, on a local address. \n Default value is `public`" + enum: + - public + - internal + - none + type: string + name: + maxLength: 63 + pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ + type: string + path: + description: Path of the endpoint URL + type: string + protocol: + default: http + description: "Describes the application and transport protocols + of the traffic that will go through this endpoint. \n - + `http`: Endpoint will have `http` traffic, typically on + a TCP connection. It will be automaticaly promoted to `https` + when the `secure` field is set to `true`. \n - `https`: + Endpoint will have `https` traffic, typically on a TCP connection. + \n - `ws`: Endpoint will have `ws` traffic, typically on + a TCP connection. It will be automaticaly promoted to `wss` + when the `secure` field is set to `true`. \n - `wss`: Endpoint + will have `wss` traffic, typically on a TCP connection. + \n - `tcp`: Endpoint will have traffic on a TCP connection, + without specifying an application protocol. \n - `udp`: + Endpoint will have traffic on an UDP connection, without + specifying an application protocol. \n Default value is + `http`" + enum: + - http + - https + - ws + - wss + - tcp + - udp + type: string + secure: + description: Describes whether the endpoint should be secured + and protected by some authentication process. This requires + a protocol of `https` or `wss`. + type: boolean + targetPort: + type: integer + required: + - name + - targetPort + type: object + type: array + description: Machines to endpoints map + type: object + podSelector: + additionalProperties: + type: string + description: Selector that should be used by created services to point + to the devworkspace Pod + type: object + routingClass: + description: 'Class of the routing: this drives which DevWorkspaceRouting + controller will manage this routing' + type: string + required: + - devworkspaceId + - endpoints + - podSelector + type: object + status: + description: DevWorkspaceRoutingStatus defines the observed state of DevWorkspaceRouting + properties: + exposedEndpoints: + additionalProperties: + items: + properties: + attributes: + additionalProperties: + x-kubernetes-preserve-unknown-fields: true + description: Attributes of the exposed endpoint + type: object + x-kubernetes-preserve-unknown-fields: true + name: + description: Name of the exposed endpoint + type: string + url: + description: Public URL of the exposed endpoint + type: string + required: + - name + - url + type: object + type: array + description: Machine name to exposed endpoint map + type: object + message: + description: Message is a user-readable message explaining the current + phase (e.g. reason for failure) + type: string + phase: + description: Routing reconcile phase + type: string + podAdditions: + description: Additions to main devworkspace deployment + properties: + annotations: + additionalProperties: + type: string + description: Annotations to be applied to devworkspace deployment + type: object + containers: + description: Containers to add to devworkspace deployment + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker image''s + CMD is used if this is not provided. Variable references + $(VAR_NAME) are expanded using the container''s environment. + If a variable cannot be resolved, the reference in the + input string will be unchanged. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(VAR_NAME). Escaped + references will never be expanded, regardless of whether + the variable exists or not. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The docker image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. If a variable cannot + be resolved, the reference in the input string will be + unchanged. The $(VAR_NAME) syntax can be escaped with + a double $$, ie: $$(VAR_NAME). Escaped references will + never be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are + expanded using the previous defined environment + variables in the container and any service environment + variables. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, metadata.labels, + metadata.annotations, spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. When a key exists + in multiple sources, the value associated with the last + source will take precedence. Values defined by an Env + with a duplicate key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The reason for + termination is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop hooked + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period. Other management + of the container blocks until the hook completes or + until the termination grace period is reached. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + - protocol + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run with. + More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. This is + a beta feature enabled by the StartupProbe feature flag. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + initContainers: + description: Init containers to add to devworkspace deployment + items: + description: A single application container that you want to + run within a pod. + properties: + args: + description: 'Arguments to the entrypoint. The docker image''s + CMD is used if this is not provided. Variable references + $(VAR_NAME) are expanded using the container''s environment. + If a variable cannot be resolved, the reference in the + input string will be unchanged. The $(VAR_NAME) syntax + can be escaped with a double $$, ie: $$(VAR_NAME). Escaped + references will never be expanded, regardless of whether + the variable exists or not. Cannot be updated. More info: + https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + command: + description: 'Entrypoint array. Not executed within a shell. + The docker image''s ENTRYPOINT is used if this is not + provided. Variable references $(VAR_NAME) are expanded + using the container''s environment. If a variable cannot + be resolved, the reference in the input string will be + unchanged. The $(VAR_NAME) syntax can be escaped with + a double $$, ie: $$(VAR_NAME). Escaped references will + never be expanded, regardless of whether the variable + exists or not. Cannot be updated. More info: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#running-a-command-in-a-shell' + items: + type: string + type: array + env: + description: List of environment variables to set in the + container. Cannot be updated. + items: + description: EnvVar represents an environment variable + present in a Container. + properties: + name: + description: Name of the environment variable. Must + be a C_IDENTIFIER. + type: string + value: + description: 'Variable references $(VAR_NAME) are + expanded using the previous defined environment + variables in the container and any service environment + variables. If a variable cannot be resolved, the + reference in the input string will be unchanged. + The $(VAR_NAME) syntax can be escaped with a double + $$, ie: $$(VAR_NAME). Escaped references will never + be expanded, regardless of whether the variable + exists or not. Defaults to "".' + type: string + valueFrom: + description: Source for the environment variable's + value. Cannot be used if value is not empty. + properties: + configMapKeyRef: + description: Selects a key of a ConfigMap. + properties: + key: + description: The key to select. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its key must be defined + type: boolean + required: + - key + type: object + fieldRef: + description: 'Selects a field of the pod: supports + metadata.name, metadata.namespace, metadata.labels, + metadata.annotations, spec.nodeName, spec.serviceAccountName, + status.hostIP, status.podIP, status.podIPs.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, limits.ephemeral-storage, requests.cpu, + requests.memory and requests.ephemeral-storage) + are currently supported.' + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + secretKeyRef: + description: Selects a key of a secret in the + pod's namespace + properties: + key: + description: The key of the secret to select + from. Must be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + required: + - key + type: object + type: object + required: + - name + type: object + type: array + envFrom: + description: List of sources to populate environment variables + in the container. The keys defined within a source must + be a C_IDENTIFIER. All invalid keys will be reported as + an event when the container is starting. When a key exists + in multiple sources, the value associated with the last + source will take precedence. Values defined by an Env + with a duplicate key will take precedence. Cannot be updated. + items: + description: EnvFromSource represents the source of a + set of ConfigMaps + properties: + configMapRef: + description: The ConfigMap to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the ConfigMap must + be defined + type: boolean + type: object + prefix: + description: An optional identifier to prepend to + each key in the ConfigMap. Must be a C_IDENTIFIER. + type: string + secretRef: + description: The Secret to select from + properties: + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret must be + defined + type: boolean + type: object + type: object + type: array + image: + description: 'Docker image name. More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management + to default or override container images in workload controllers + like Deployments and StatefulSets.' + type: string + imagePullPolicy: + description: 'Image pull policy. One of Always, Never, IfNotPresent. + Defaults to Always if :latest tag is specified, or IfNotPresent + otherwise. Cannot be updated. More info: https://kubernetes.io/docs/concepts/containers/images#updating-images' + type: string + lifecycle: + description: Actions that the management system should take + in response to container lifecycle events. Cannot be updated. + properties: + postStart: + description: 'PostStart is called immediately after + a container is created. If the handler fails, the + container is terminated and restarted according to + its restart policy. Other management of the container + blocks until the hook completes. More info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + preStop: + description: 'PreStop is called immediately before a + container is terminated due to an API request or management + event such as liveness/startup probe failure, preemption, + resource contention, etc. The handler is not called + if the container crashes or exits. The reason for + termination is passed to the handler. The Pod''s termination + grace period countdown begins before the PreStop hooked + is executed. Regardless of the outcome of the handler, + the container will eventually terminate within the + Pod''s termination grace period. Other management + of the container blocks until the hook completes or + until the termination grace period is reached. More + info: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to + execute inside the container, the working + directory for the command is root ('/') in + the container's filesystem. The command is + simply exec'd, it is not run inside a shell, + so traditional shell instructions ('|', etc) + won't work. To use a shell, you need to explicitly + call out to that shell. Exit status of 0 is + treated as live/healthy and non-zero is unhealthy. + items: + type: string + type: array + type: object + httpGet: + description: HTTPGet specifies the http request + to perform. + properties: + host: + description: Host name to connect to, defaults + to the pod IP. You probably want to set "Host" + in httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom + header to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to + the host. Defaults to HTTP. + type: string + required: + - port + type: object + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: + implement a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect + to, defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + type: object + type: object + livenessProbe: + description: 'Periodic probe of container liveness. Container + will be restarted if the probe fails. Cannot be updated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + name: + description: Name of the container specified as a DNS_LABEL. + Each container in a pod must have a unique name (DNS_LABEL). + Cannot be updated. + type: string + ports: + description: List of ports to expose from the container. + Exposing a port here gives the system additional information + about the network connections a container uses, but is + primarily informational. Not specifying a port here DOES + NOT prevent that port from being exposed. Any port which + is listening on the default "0.0.0.0" address inside a + container will be accessible from the network. Cannot + be updated. + items: + description: ContainerPort represents a network port in + a single container. + properties: + containerPort: + description: Number of port to expose on the pod's + IP address. This must be a valid port number, 0 + < x < 65536. + format: int32 + type: integer + hostIP: + description: What host IP to bind the external port + to. + type: string + hostPort: + description: Number of port to expose on the host. + If specified, this must be a valid port number, + 0 < x < 65536. If HostNetwork is specified, this + must match ContainerPort. Most containers do not + need this. + format: int32 + type: integer + name: + description: If specified, this must be an IANA_SVC_NAME + and unique within the pod. Each named port in a + pod must have a unique name. Name for the port that + can be referred to by services. + type: string + protocol: + description: Protocol for port. Must be UDP, TCP, + or SCTP. Defaults to "TCP". + type: string + required: + - containerPort + - protocol + type: object + type: array + x-kubernetes-list-map-keys: + - containerPort + - protocol + x-kubernetes-list-type: map + readinessProbe: + description: 'Periodic probe of container service readiness. + Container will be removed from service endpoints if the + probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + resources: + description: 'Compute Resources required by this container. + Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + securityContext: + description: 'Security options the pod should run with. + More info: https://kubernetes.io/docs/concepts/policy/security-context/ + More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/' + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent + process. This bool directly controls if the no_new_privs + flag will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only + root filesystem. Default is false. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if + it does. If unset or false, no such validation will + be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both + SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name + of the GMSA credential spec to use. + type: string + runAsUserName: + description: The UserName in Windows to run the + entrypoint of the container process. Defaults + to the user specified in image metadata if unspecified. + May also be set in PodSecurityContext. If set + in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: string + type: object + type: object + startupProbe: + description: 'StartupProbe indicates that the Pod has successfully + initialized. If specified, no other probes are executed + until this completes successfully. If this probe fails, + the Pod will be restarted, just as if the livenessProbe + failed. This can be used to provide different probe parameters + at the beginning of a Pod''s lifecycle, when it might + take a long time to load data or warm a cache, than during + steady-state operation. This cannot be updated. This is + a beta feature enabled by the StartupProbe feature flag. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + properties: + exec: + description: One and only one of the following should + be specified. Exec specifies the action to take. + properties: + command: + description: Command is the command line to execute + inside the container, the working directory for + the command is root ('/') in the container's + filesystem. The command is simply exec'd, it is + not run inside a shell, so traditional shell instructions + ('|', etc) won't work. To use a shell, you need + to explicitly call out to that shell. Exit status + of 0 is treated as live/healthy and non-zero is + unhealthy. + items: + type: string + type: array + type: object + failureThreshold: + description: Minimum consecutive failures for the probe + to be considered failed after having succeeded. Defaults + to 3. Minimum value is 1. + format: int32 + type: integer + httpGet: + description: HTTPGet specifies the http request to perform. + properties: + host: + description: Host name to connect to, defaults to + the pod IP. You probably want to set "Host" in + httpHeaders instead. + type: string + httpHeaders: + description: Custom headers to set in the request. + HTTP allows repeated headers. + items: + description: HTTPHeader describes a custom header + to be used in HTTP probes + properties: + name: + description: The header field name + type: string + value: + description: The header field value + type: string + required: + - name + - value + type: object + type: array + path: + description: Path to access on the HTTP server. + type: string + port: + anyOf: + - type: integer + - type: string + description: Name or number of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + scheme: + description: Scheme to use for connecting to the + host. Defaults to HTTP. + type: string + required: + - port + type: object + initialDelaySeconds: + description: 'Number of seconds after the container + has started before liveness probes are initiated. + More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + periodSeconds: + description: How often (in seconds) to perform the probe. + Default to 10 seconds. Minimum value is 1. + format: int32 + type: integer + successThreshold: + description: Minimum consecutive successes for the probe + to be considered successful after having failed. Defaults + to 1. Must be 1 for liveness and startup. Minimum + value is 1. + format: int32 + type: integer + tcpSocket: + description: 'TCPSocket specifies an action involving + a TCP port. TCP hooks not yet supported TODO: implement + a realistic TCP lifecycle hook' + properties: + host: + description: 'Optional: Host name to connect to, + defaults to the pod IP.' + type: string + port: + anyOf: + - type: integer + - type: string + description: Number or name of the port to access + on the container. Number must be in the range + 1 to 65535. Name must be an IANA_SVC_NAME. + x-kubernetes-int-or-string: true + required: + - port + type: object + timeoutSeconds: + description: 'Number of seconds after which the probe + times out. Defaults to 1 second. Minimum value is + 1. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes' + format: int32 + type: integer + type: object + stdin: + description: Whether this container should allocate a buffer + for stdin in the container runtime. If this is not set, + reads from stdin in the container will always result in + EOF. Default is false. + type: boolean + stdinOnce: + description: Whether the container runtime should close + the stdin channel after it has been opened by a single + attach. When stdin is true the stdin stream will remain + open across multiple attach sessions. If stdinOnce is + set to true, stdin is opened on container start, is empty + until the first client attaches to stdin, and then remains + open and accepts data until the client disconnects, at + which time stdin is closed and remains closed until the + container is restarted. If this flag is false, a container + processes that reads from stdin will never receive an + EOF. Default is false + type: boolean + terminationMessagePath: + description: 'Optional: Path at which the file to which + the container''s termination message will be written is + mounted into the container''s filesystem. Message written + is intended to be brief final status, such as an assertion + failure message. Will be truncated by the node if greater + than 4096 bytes. The total message length across all containers + will be limited to 12kb. Defaults to /dev/termination-log. + Cannot be updated.' + type: string + terminationMessagePolicy: + description: Indicate how the termination message should + be populated. File will use the contents of terminationMessagePath + to populate the container status message on both success + and failure. FallbackToLogsOnError will use the last chunk + of container log output if the termination message file + is empty and the container exited with an error. The log + output is limited to 2048 bytes or 80 lines, whichever + is smaller. Defaults to File. Cannot be updated. + type: string + tty: + description: Whether this container should allocate a TTY + for itself, also requires 'stdin' to be true. Default + is false. + type: boolean + volumeDevices: + description: volumeDevices is the list of block devices + to be used by the container. + items: + description: volumeDevice describes a mapping of a raw + block device within a container. + properties: + devicePath: + description: devicePath is the path inside of the + container that the device will be mapped to. + type: string + name: + description: name must match the name of a persistentVolumeClaim + in the pod + type: string + required: + - devicePath + - name + type: object + type: array + volumeMounts: + description: Pod volumes to mount into the container's filesystem. + Cannot be updated. + items: + description: VolumeMount describes a mounting of a Volume + within a container. + properties: + mountPath: + description: Path within the container at which the + volume should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts + are propagated from the host to container and the + other way around. When not set, MountPropagationNone + is used. This field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write + otherwise (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the + container's volume should be mounted. Defaults to + "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from + which the container's volume should be mounted. + Behaves similarly to SubPath but environment variable + references $(VAR_NAME) are expanded using the container's + environment. Defaults to "" (volume's root). SubPathExpr + and SubPath are mutually exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + workingDir: + description: Container's working directory. If not specified, + the container runtime's default will be used, which might + be configured in the container image. Cannot be updated. + type: string + required: + - name + type: object + type: array + labels: + additionalProperties: + type: string + description: Labels to be applied to devworkspace deployment + type: object + pullSecrets: + description: ImagePullSecrets to add to devworkspace deployment + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + serviceAccountAnnotations: + additionalProperties: + type: string + description: Annotations for the devworkspace service account, + it might be used for e.g. OpenShift oauth with SA as auth client + type: object + volumeMounts: + description: VolumeMounts to add to all containers in a devworkspace + deployment + items: + description: VolumeMount describes a mounting of a Volume within + a container. + properties: + mountPath: + description: Path within the container at which the volume + should be mounted. Must not contain ':'. + type: string + mountPropagation: + description: mountPropagation determines how mounts are + propagated from the host to container and the other way + around. When not set, MountPropagationNone is used. This + field is beta in 1.10. + type: string + name: + description: This must match the Name of a Volume. + type: string + readOnly: + description: Mounted read-only if true, read-write otherwise + (false or unspecified). Defaults to false. + type: boolean + subPath: + description: Path within the volume from which the container's + volume should be mounted. Defaults to "" (volume's root). + type: string + subPathExpr: + description: Expanded path within the volume from which + the container's volume should be mounted. Behaves similarly + to SubPath but environment variable references $(VAR_NAME) + are expanded using the container's environment. Defaults + to "" (volume's root). SubPathExpr and SubPath are mutually + exclusive. + type: string + required: + - mountPath + - name + type: object + type: array + volumes: + description: Volumes to add to devworkspace deployment + items: + description: Volume represents a named volume in a pod that + may be accessed by any container in the pod. + properties: + awsElasticBlockStore: + description: 'AWSElasticBlockStore represents an AWS Disk + resource that is attached to a kubelet''s host machine + and then exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + properties: + fsType: + description: 'Filesystem type of the volume that you + want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'The partition in the volume that you want + to mount. If omitted, the default is to mount by volume + name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property + empty).' + format: int32 + type: integer + readOnly: + description: 'Specify "true" to force and set the ReadOnly + property in VolumeMounts to "true". If omitted, the + default is "false". More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: boolean + volumeID: + description: 'Unique ID of the persistent disk resource + in AWS (Amazon EBS volume). More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore' + type: string + required: + - volumeID + type: object + azureDisk: + description: AzureDisk represents an Azure Data Disk mount + on the host and bind mount to the pod. + properties: + cachingMode: + description: 'Host Caching mode: None, Read Only, Read + Write.' + type: string + diskName: + description: The Name of the data disk in the blob storage + type: string + diskURI: + description: The URI the data disk in the blob storage + type: string + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if + unspecified. + type: string + kind: + description: 'Expected values Shared: multiple blob + disks per storage account Dedicated: single blob + disk per storage account Managed: azure managed data + disk (only in managed availability set). defaults + to shared' + type: string + readOnly: + description: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + required: + - diskName + - diskURI + type: object + azureFile: + description: AzureFile represents an Azure File Service + mount on the host and bind mount to the pod. + properties: + readOnly: + description: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretName: + description: the name of secret that contains Azure + Storage Account Name and Key + type: string + shareName: + description: Share Name + type: string + required: + - secretName + - shareName + type: object + cephfs: + description: CephFS represents a Ceph FS mount on the host + that shares a pod's lifetime + properties: + monitors: + description: 'Required: Monitors is a collection of + Ceph monitors More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + items: + type: string + type: array + path: + description: 'Optional: Used as the mounted root, rather + than the full Ceph tree, default is /' + type: string + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: boolean + secretFile: + description: 'Optional: SecretFile is the path to key + ring for User, default is /etc/ceph/user.secret More + info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + secretRef: + description: 'Optional: SecretRef is reference to the + authentication secret for User, default is empty. + More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'Optional: User is the rados user name, + default is admin More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it' + type: string + required: + - monitors + type: object + cinder: + description: 'Cinder represents a cinder volume attached + and mounted on kubelets host machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + properties: + fsType: + description: 'Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts. + More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: boolean + secretRef: + description: 'Optional: points to a secret object containing + parameters used to connect to OpenStack.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeID: + description: 'volume id used to identify the volume + in cinder. More info: https://examples.k8s.io/mysql-cinder-pd/README.md' + type: string + required: + - volumeID + type: object + configMap: + description: ConfigMap represents a configMap that should + populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a value between 0 and 0777. + Defaults to 0644. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like + fsGroup, and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: If unspecified, each key-value pair in + the Data field of the referenced ConfigMap will be + projected into the volume as a file whose name is + the key and content is the value. If specified, the + listed keys will be projected into the specified paths, + and unlisted keys will not be present. If a key is + specified which is not present in the ConfigMap, the + volume setup will error unless it is marked optional. + Paths must be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits to use on this + file, must be a value between 0 and 0777. If + not specified, the volume defaultMode will be + used. This might be in conflict with other options + that affect the file mode, like fsGroup, and + the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap or its keys + must be defined + type: boolean + type: object + csi: + description: CSI (Container Storage Interface) represents + storage that is handled by an external CSI driver (Alpha + feature). + properties: + driver: + description: Driver is the name of the CSI driver that + handles this volume. Consult with your admin for the + correct name as registered in the cluster. + type: string + fsType: + description: Filesystem type to mount. Ex. "ext4", "xfs", + "ntfs". If not provided, the empty value is passed + to the associated CSI driver which will determine + the default filesystem to apply. + type: string + nodePublishSecretRef: + description: NodePublishSecretRef is a reference to + the secret object containing sensitive information + to pass to the CSI driver to complete the CSI NodePublishVolume + and NodeUnpublishVolume calls. This field is optional, + and may be empty if no secret is required. If the + secret object contains more than one secret, all secret + references are passed. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + readOnly: + description: Specifies a read-only configuration for + the volume. Defaults to false (read/write). + type: boolean + volumeAttributes: + additionalProperties: + type: string + description: VolumeAttributes stores driver-specific + properties that are passed to the CSI driver. Consult + your driver's documentation for supported values. + type: object + required: + - driver + type: object + downwardAPI: + description: DownwardAPI represents downward API about the + pod that should populate this volume + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a value between 0 and 0777. + Defaults to 0644. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like + fsGroup, and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: Items is a list of downward API volume + file + items: + description: DownwardAPIVolumeFile represents information + to create the file containing the pod field + properties: + fieldRef: + description: 'Required: Selects a field of the + pod: only annotations, labels, name and namespace + are supported.' + properties: + apiVersion: + description: Version of the schema the FieldPath + is written in terms of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to select in + the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits to use on this + file, must be a value between 0 and 0777. If + not specified, the volume defaultMode will be + used. This might be in conflict with other options + that affect the file mode, like fsGroup, and + the result can be other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the relative + path name of the file to be created. Must not + be absolute or contain the ''..'' path. Must + be utf-8 encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of the container: + only resources limits and requests (limits.cpu, + limits.memory, requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required for + volumes, optional for env vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output format of + the exposed resources, defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + emptyDir: + description: 'EmptyDir represents a temporary directory + that shares a pod''s lifetime. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + properties: + medium: + description: 'What type of storage medium should back + this directory. The default is "" which means to use + the node''s default medium. Must be an empty string + (default) or Memory. More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir' + type: string + sizeLimit: + anyOf: + - type: integer + - type: string + description: 'Total amount of local storage required + for this EmptyDir volume. The size limit is also applicable + for memory medium. The maximum usage on memory medium + EmptyDir would be the minimum value between the SizeLimit + specified here and the sum of memory limits of all + containers in a pod. The default is nil which means + that the limit is undefined. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir' + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + type: object + fc: + description: FC represents a Fibre Channel resource that + is attached to a kubelet's host machine and then exposed + to the pod. + properties: + fsType: + description: 'Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if + unspecified. TODO: how do we prevent errors in the + filesystem from compromising the machine' + type: string + lun: + description: 'Optional: FC target lun number' + format: int32 + type: integer + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + targetWWNs: + description: 'Optional: FC target worldwide names (WWNs)' + items: + type: string + type: array + wwids: + description: 'Optional: FC volume world wide identifiers + (wwids) Either wwids or combination of targetWWNs + and lun must be set, but not both simultaneously.' + items: + type: string + type: array + type: object + flexVolume: + description: FlexVolume represents a generic volume resource + that is provisioned/attached using an exec based plugin. + properties: + driver: + description: Driver is the name of the driver to use + for this volume. + type: string + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". The default filesystem depends on FlexVolume + script. + type: string + options: + additionalProperties: + type: string + description: 'Optional: Extra command options if any.' + type: object + readOnly: + description: 'Optional: Defaults to false (read/write). + ReadOnly here will force the ReadOnly setting in VolumeMounts.' + type: boolean + secretRef: + description: 'Optional: SecretRef is reference to the + secret object containing sensitive information to + pass to the plugin scripts. This may be empty if no + secret object is specified. If the secret object contains + more than one secret, all secrets are passed to the + plugin scripts.' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + required: + - driver + type: object + flocker: + description: Flocker represents a Flocker volume attached + to a kubelet's host machine. This depends on the Flocker + control service being running + properties: + datasetName: + description: Name of the dataset stored as metadata + -> name on the dataset for Flocker should be considered + as deprecated + type: string + datasetUUID: + description: UUID of the dataset. This is unique identifier + of a Flocker dataset + type: string + type: object + gcePersistentDisk: + description: 'GCEPersistentDisk represents a GCE Disk resource + that is attached to a kubelet''s host machine and then + exposed to the pod. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + properties: + fsType: + description: 'Filesystem type of the volume that you + want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + partition: + description: 'The partition in the volume that you want + to mount. If omitted, the default is to mount by volume + name. Examples: For volume /dev/sda1, you specify + the partition as "1". Similarly, the volume partition + for /dev/sda is "0" (or you can leave the property + empty). More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + format: int32 + type: integer + pdName: + description: 'Unique name of the PD resource in GCE. + Used to identify the disk in GCE. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: string + readOnly: + description: 'ReadOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk' + type: boolean + required: + - pdName + type: object + gitRepo: + description: 'GitRepo represents a git repository at a particular + revision. DEPRECATED: GitRepo is deprecated. To provision + a container with a git repo, mount an EmptyDir into an + InitContainer that clones the repo using git, then mount + the EmptyDir into the Pod''s container.' + properties: + directory: + description: Target directory name. Must not contain + or start with '..'. If '.' is supplied, the volume + directory will be the git repository. Otherwise, + if specified, the volume will contain the git repository + in the subdirectory with the given name. + type: string + repository: + description: Repository URL + type: string + revision: + description: Commit hash for the specified revision. + type: string + required: + - repository + type: object + glusterfs: + description: 'Glusterfs represents a Glusterfs mount on + the host that shares a pod''s lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md' + properties: + endpoints: + description: 'EndpointsName is the endpoint name that + details Glusterfs topology. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + path: + description: 'Path is the Glusterfs volume path. More + info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: string + readOnly: + description: 'ReadOnly here will force the Glusterfs + volume to be mounted with read-only permissions. Defaults + to false. More info: https://examples.k8s.io/volumes/glusterfs/README.md#create-a-pod' + type: boolean + required: + - endpoints + - path + type: object + hostPath: + description: 'HostPath represents a pre-existing file or + directory on the host machine that is directly exposed + to the container. This is generally used for system agents + or other privileged things that are allowed to see the + host machine. Most containers will NOT need this. More + info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath + --- TODO(jonesdl) We need to restrict who can use host + directory mounts and who can/can not mount host directories + as read/write.' + properties: + path: + description: 'Path of the directory on the host. If + the path is a symlink, it will follow the link to + the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + type: + description: 'Type for HostPath Volume Defaults to "" + More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath' + type: string + required: + - path + type: object + iscsi: + description: 'ISCSI represents an ISCSI Disk resource that + is attached to a kubelet''s host machine and then exposed + to the pod. More info: https://examples.k8s.io/volumes/iscsi/README.md' + properties: + chapAuthDiscovery: + description: whether support iSCSI Discovery CHAP authentication + type: boolean + chapAuthSession: + description: whether support iSCSI Session CHAP authentication + type: boolean + fsType: + description: 'Filesystem type of the volume that you + want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + initiatorName: + description: Custom iSCSI Initiator Name. If initiatorName + is specified with iscsiInterface simultaneously, new + iSCSI interface : will + be created for the connection. + type: string + iqn: + description: Target iSCSI Qualified Name. + type: string + iscsiInterface: + description: iSCSI Interface Name that uses an iSCSI + transport. Defaults to 'default' (tcp). + type: string + lun: + description: iSCSI Target Lun number. + format: int32 + type: integer + portals: + description: iSCSI Target Portal List. The portal is + either an IP or ip_addr:port if the port is other + than default (typically TCP ports 860 and 3260). + items: + type: string + type: array + readOnly: + description: ReadOnly here will force the ReadOnly setting + in VolumeMounts. Defaults to false. + type: boolean + secretRef: + description: CHAP Secret for iSCSI target and initiator + authentication + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + targetPortal: + description: iSCSI Target Portal. The Portal is either + an IP or ip_addr:port if the port is other than default + (typically TCP ports 860 and 3260). + type: string + required: + - iqn + - lun + - targetPortal + type: object + name: + description: 'Volume''s name. Must be a DNS_LABEL and unique + within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + nfs: + description: 'NFS represents an NFS mount on the host that + shares a pod''s lifetime More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + properties: + path: + description: 'Path that is exported by the NFS server. + More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + readOnly: + description: 'ReadOnly here will force the NFS export + to be mounted with read-only permissions. Defaults + to false. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: boolean + server: + description: 'Server is the hostname or IP address of + the NFS server. More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs' + type: string + required: + - path + - server + type: object + persistentVolumeClaim: + description: 'PersistentVolumeClaimVolumeSource represents + a reference to a PersistentVolumeClaim in the same namespace. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + properties: + claimName: + description: 'ClaimName is the name of a PersistentVolumeClaim + in the same namespace as the pod using this volume. + More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims' + type: string + readOnly: + description: Will force the ReadOnly setting in VolumeMounts. + Default false. + type: boolean + required: + - claimName + type: object + photonPersistentDisk: + description: PhotonPersistentDisk represents a PhotonController + persistent disk attached and mounted on kubelets host + machine + properties: + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if + unspecified. + type: string + pdID: + description: ID that identifies Photon Controller persistent + disk + type: string + required: + - pdID + type: object + portworxVolume: + description: PortworxVolume represents a portworx volume + attached and mounted on kubelets host machine + properties: + fsType: + description: FSType represents the filesystem type to + mount Must be a filesystem type supported by the host + operating system. Ex. "ext4", "xfs". Implicitly inferred + to be "ext4" if unspecified. + type: string + readOnly: + description: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + volumeID: + description: VolumeID uniquely identifies a Portworx + volume + type: string + required: + - volumeID + type: object + projected: + description: Items for all in one resources secrets, configmaps, + and downward API + properties: + defaultMode: + description: Mode bits to use on created files by default. + Must be a value between 0 and 0777. Directories within + the path are not affected by this setting. This might + be in conflict with other options that affect the + file mode, like fsGroup, and the result can be other + mode bits set. + format: int32 + type: integer + sources: + description: list of volume projections + items: + description: Projection that may be projected along + with other supported volume types + properties: + configMap: + description: information about the configMap data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced + ConfigMap will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the ConfigMap, the volume setup will + error unless it is marked optional. Paths + must be relative and may not contain the + '..' path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits to + use on this file, must be a value + between 0 and 0777. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be + an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the ConfigMap + or its keys must be defined + type: boolean + type: object + downwardAPI: + description: information about the downwardAPI + data to project + properties: + items: + description: Items is a list of DownwardAPIVolume + file + items: + description: DownwardAPIVolumeFile represents + information to create the file containing + the pod field + properties: + fieldRef: + description: 'Required: Selects a field + of the pod: only annotations, labels, + name and namespace are supported.' + properties: + apiVersion: + description: Version of the schema + the FieldPath is written in terms + of, defaults to "v1". + type: string + fieldPath: + description: Path of the field to + select in the specified API version. + type: string + required: + - fieldPath + type: object + mode: + description: 'Optional: mode bits to + use on this file, must be a value + between 0 and 0777. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: 'Required: Path is the + relative path name of the file to + be created. Must not be absolute or + contain the ''..'' path. Must be utf-8 + encoded. The first item of the relative + path must not start with ''..''' + type: string + resourceFieldRef: + description: 'Selects a resource of + the container: only resources limits + and requests (limits.cpu, limits.memory, + requests.cpu and requests.memory) + are currently supported.' + properties: + containerName: + description: 'Container name: required + for volumes, optional for env + vars' + type: string + divisor: + anyOf: + - type: integer + - type: string + description: Specifies the output + format of the exposed resources, + defaults to "1" + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + resource: + description: 'Required: resource + to select' + type: string + required: + - resource + type: object + required: + - path + type: object + type: array + type: object + secret: + description: information about the secret data + to project + properties: + items: + description: If unspecified, each key-value + pair in the Data field of the referenced + Secret will be projected into the volume + as a file whose name is the key and content + is the value. If specified, the listed keys + will be projected into the specified paths, + and unlisted keys will not be present. If + a key is specified which is not present + in the Secret, the volume setup will error + unless it is marked optional. Paths must + be relative and may not contain the '..' + path or start with '..'. + items: + description: Maps a string key to a path + within a volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits to + use on this file, must be a value + between 0 and 0777. If not specified, + the volume defaultMode will be used. + This might be in conflict with other + options that affect the file mode, + like fsGroup, and the result can be + other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the + file to map the key to. May not be + an absolute path. May not contain + the path element '..'. May not start + with the string '..'. + type: string + required: + - key + - path + type: object + type: array + name: + description: 'Name of the referent. More info: + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, + kind, uid?' + type: string + optional: + description: Specify whether the Secret or + its key must be defined + type: boolean + type: object + serviceAccountToken: + description: information about the serviceAccountToken + data to project + properties: + audience: + description: Audience is the intended audience + of the token. A recipient of a token must + identify itself with an identifier specified + in the audience of the token, and otherwise + should reject the token. The audience defaults + to the identifier of the apiserver. + type: string + expirationSeconds: + description: ExpirationSeconds is the requested + duration of validity of the service account + token. As the token approaches expiration, + the kubelet volume plugin will proactively + rotate the service account token. The kubelet + will start trying to rotate the token if + the token is older than 80 percent of its + time to live or if the token is older than + 24 hours.Defaults to 1 hour and must be + at least 10 minutes. + format: int64 + type: integer + path: + description: Path is the path relative to + the mount point of the file to project the + token into. + type: string + required: + - path + type: object + type: object + type: array + required: + - sources + type: object + quobyte: + description: Quobyte represents a Quobyte mount on the host + that shares a pod's lifetime + properties: + group: + description: Group to map volume access to Default is + no group + type: string + readOnly: + description: ReadOnly here will force the Quobyte volume + to be mounted with read-only permissions. Defaults + to false. + type: boolean + registry: + description: Registry represents a single or multiple + Quobyte Registry services specified as a string as + host:port pair (multiple entries are separated with + commas) which acts as the central registry for volumes + type: string + tenant: + description: Tenant owning the given Quobyte volume + in the Backend Used with dynamically provisioned Quobyte + volumes, value is set by the plugin + type: string + user: + description: User to map volume access to Defaults to + serivceaccount user + type: string + volume: + description: Volume is a string that references an already + created Quobyte volume by name. + type: string + required: + - registry + - volume + type: object + rbd: + description: 'RBD represents a Rados Block Device mount + on the host that shares a pod''s lifetime. More info: + https://examples.k8s.io/volumes/rbd/README.md' + properties: + fsType: + description: 'Filesystem type of the volume that you + want to mount. Tip: Ensure that the filesystem type + is supported by the host operating system. Examples: + "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" + if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd + TODO: how do we prevent errors in the filesystem from + compromising the machine' + type: string + image: + description: 'The rados image name. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + keyring: + description: 'Keyring is the path to key ring for RBDUser. + Default is /etc/ceph/keyring. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + monitors: + description: 'A collection of Ceph monitors. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + items: + type: string + type: array + pool: + description: 'The rados pool name. Default is rbd. More + info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + readOnly: + description: 'ReadOnly here will force the ReadOnly + setting in VolumeMounts. Defaults to false. More info: + https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: boolean + secretRef: + description: 'SecretRef is name of the authentication + secret for RBDUser. If provided overrides keyring. + Default is nil. More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + user: + description: 'The rados user name. Default is admin. + More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it' + type: string + required: + - image + - monitors + type: object + scaleIO: + description: ScaleIO represents a ScaleIO persistent volume + attached and mounted on Kubernetes nodes. + properties: + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Default is "xfs". + type: string + gateway: + description: The host address of the ScaleIO API Gateway. + type: string + protectionDomain: + description: The name of the ScaleIO Protection Domain + for the configured storage. + type: string + readOnly: + description: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: SecretRef references to the secret for + ScaleIO user and other sensitive information. If this + is not provided, Login operation will fail. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + sslEnabled: + description: Flag to enable/disable SSL communication + with Gateway, default false + type: boolean + storageMode: + description: Indicates whether the storage for a volume + should be ThickProvisioned or ThinProvisioned. Default + is ThinProvisioned. + type: string + storagePool: + description: The ScaleIO Storage Pool associated with + the protection domain. + type: string + system: + description: The name of the storage system as configured + in ScaleIO. + type: string + volumeName: + description: The name of a volume already created in + the ScaleIO system that is associated with this volume + source. + type: string + required: + - gateway + - secretRef + - system + type: object + secret: + description: 'Secret represents a secret that should populate + this volume. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + properties: + defaultMode: + description: 'Optional: mode bits to use on created + files by default. Must be a value between 0 and 0777. + Defaults to 0644. Directories within the path are + not affected by this setting. This might be in conflict + with other options that affect the file mode, like + fsGroup, and the result can be other mode bits set.' + format: int32 + type: integer + items: + description: If unspecified, each key-value pair in + the Data field of the referenced Secret will be projected + into the volume as a file whose name is the key and + content is the value. If specified, the listed keys + will be projected into the specified paths, and unlisted + keys will not be present. If a key is specified which + is not present in the Secret, the volume setup will + error unless it is marked optional. Paths must be + relative and may not contain the '..' path or start + with '..'. + items: + description: Maps a string key to a path within a + volume. + properties: + key: + description: The key to project. + type: string + mode: + description: 'Optional: mode bits to use on this + file, must be a value between 0 and 0777. If + not specified, the volume defaultMode will be + used. This might be in conflict with other options + that affect the file mode, like fsGroup, and + the result can be other mode bits set.' + format: int32 + type: integer + path: + description: The relative path of the file to + map the key to. May not be an absolute path. + May not contain the path element '..'. May not + start with the string '..'. + type: string + required: + - key + - path + type: object + type: array + optional: + description: Specify whether the Secret or its keys + must be defined + type: boolean + secretName: + description: 'Name of the secret in the pod''s namespace + to use. More info: https://kubernetes.io/docs/concepts/storage/volumes#secret' + type: string + type: object + storageos: + description: StorageOS represents a StorageOS volume attached + and mounted on Kubernetes nodes. + properties: + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if + unspecified. + type: string + readOnly: + description: Defaults to false (read/write). ReadOnly + here will force the ReadOnly setting in VolumeMounts. + type: boolean + secretRef: + description: SecretRef specifies the secret to use for + obtaining the StorageOS API credentials. If not specified, + default values will be attempted. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + type: object + volumeName: + description: VolumeName is the human-readable name of + the StorageOS volume. Volume names are only unique + within a namespace. + type: string + volumeNamespace: + description: VolumeNamespace specifies the scope of + the volume within StorageOS. If no namespace is specified + then the Pod's namespace will be used. This allows + the Kubernetes name scoping to be mirrored within + StorageOS for tighter integration. Set VolumeName + to any name to override the default behaviour. Set + to "default" if you are not using namespaces within + StorageOS. Namespaces that do not pre-exist within + StorageOS will be created. + type: string + type: object + vsphereVolume: + description: VsphereVolume represents a vSphere volume attached + and mounted on kubelets host machine + properties: + fsType: + description: Filesystem type to mount. Must be a filesystem + type supported by the host operating system. Ex. "ext4", + "xfs", "ntfs". Implicitly inferred to be "ext4" if + unspecified. + type: string + storagePolicyID: + description: Storage Policy Based Management (SPBM) + profile ID associated with the StoragePolicyName. + type: string + storagePolicyName: + description: Storage Policy Based Management (SPBM) + profile name. + type: string + volumePath: + description: Path that identifies vSphere volume vmdk + type: string + required: + - volumePath + type: object + required: + - name + type: object + type: array + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/build-roles.sh b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/build-roles.sh index 2ba206409..2982982db 100755 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/build-roles.sh +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/build-roles.sh @@ -16,6 +16,7 @@ mkdir -p "${BASE_DIR}/generated/roles" cp "${BASE_DIR}/../../../role.yaml" "${BASE_DIR}/generated/roles/role.yaml" cp "${BASE_DIR}/../../../cluster_role.yaml" "${BASE_DIR}/generated/roles/cluster_role.yaml" +cp "${BASE_DIR}/../../../proxy_cluster_role.yaml" "${BASE_DIR}/generated/roles/proxy_cluster_role.yaml" for role in ${BASE_DIR}/generated/roles/*.yaml; do index=0 diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/csv-config.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/csv-config.yaml index d24722ff1..65a556d5a 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/csv-config.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/csv-config.yaml @@ -1,3 +1,3 @@ -role-paths: [ "deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/generated/roles/role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/generated/roles/cluster_role.yaml" ] +role-paths: [ "deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/generated/roles/role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/generated/roles/cluster_role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/generated/roles/proxy_cluster_role.yaml"] operator-path: deploy/operator.yaml crd-cr-paths: ["deploy/crds/org_v1_che_crd.yaml", "deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml", deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml", "deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml"] diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml index 92a4aac74..42822d227 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-kubernetes/manifests/che-operator.clusterserviceversion.yaml @@ -1,3 +1,13 @@ +# +# Copyright (c) 2019-2021 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: @@ -76,13 +86,13 @@ metadata: categories: Developer Tools certified: "false" containerImage: quay.io/eclipse/che-operator:next - createdAt: "2021-06-29T12:30:28Z" + createdAt: "2021-06-30T12:42:36Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces. operatorframework.io/suggested-namespace: eclipse-che repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che-preview-kubernetes.v7.33.0-242.nightly + name: eclipse-che-preview-kubernetes.v7.33.0-244.nightly namespace: placeholder spec: apiservicedefinitions: {} @@ -436,6 +446,33 @@ spec: - subscriptions verbs: - get + - apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - workspace.devfile.io + resources: + - devworkspaces + - devworkspacetemplates + verbs: + - get + - list + - watch + - apiGroups: + - controller.devfile.io + resources: + - devworkspaceroutings + - components + verbs: + - get + - list + - watch - apiGroups: - workspace.devfile.io resources: @@ -458,6 +495,33 @@ spec: - deletecollection - patch - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - authentication.k8s.io resources: @@ -489,16 +553,6 @@ spec: - list - watch - apiGroups: - - metrics.k8s.io - resources: - - pods - - nodes - verbs: - - get - - list - - watch - - apiGroups: - - batch - "" resources: - pods/exec @@ -664,37 +718,6 @@ spec: - get - list - watch - - nonResourceURLs: - - /metrics - verbs: - - get - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - configmaps/status - verbs: - - get - - update - - patch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - apiGroups: - "" resources: @@ -876,7 +899,25 @@ spec: - routes/custom-host verbs: - create + - nonResourceURLs: + - /metrics + verbs: + - get serviceAccountName: che-operator + - rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: default deployments: - name: che-operator spec: @@ -922,7 +963,7 @@ spec: - name: RELATED_IMAGE_che_tls_secrets_creation_job value: quay.io/eclipse/che-tls-secret-creator:alpine-d1ed4ad - name: RELATED_IMAGE_pvc_jobs - value: registry.access.redhat.com/ubi8-minimal:8.4-200.1622548483 + value: registry.access.redhat.com/ubi8-minimal:8.4-205 - name: RELATED_IMAGE_postgres value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_keycloak @@ -999,6 +1040,47 @@ spec: - ALL privileged: false readOnlyRootFilesystem: false + - args: + - --enable-leader-election + - --metrics-addr + - "0" + command: + - /usr/local/bin/devworkspace-che-operator + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: devworkspace-operator + - name: MAX_CONCURRENT_RECONCILES + value: "1" + - name: CONTROLLER_SERVICE_ACCOUNT_NAME + value: che-operator + - name: RELATED_IMAGE_gateway + value: quay.io/eclipse/che--traefik:v2.3.2-6e6d4dc5a19afe06778ca092cdbbb98e31cb9f9c313edafa23f81a0e6ddf8a23 + - name: RELATED_IMAGE_gateway_configurer + value: quay.io/che-incubator/configbump:0.1.4 + image: quay.io/che-incubator/devworkspace-che-operator:ci + imagePullPolicy: Always + name: devworkspace-che-operator + resources: + limits: + cpu: 100m + memory: 256Mi + requests: + cpu: 100m + memory: 32Mi + securityContext: + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false hostIPC: false hostNetwork: false hostPID: false @@ -1113,6 +1195,32 @@ spec: verbs: - get - list + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create serviceAccountName: che-operator strategy: deployment installModes: @@ -1144,4 +1252,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.33.0-242.nightly + version: 7.33.0-244.nightly diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/build-roles.sh b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/build-roles.sh index 69a963098..c18c5ed7b 100755 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/build-roles.sh +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/build-roles.sh @@ -15,3 +15,4 @@ rm -Rf "${BASE_DIR}/generated/roles" mkdir -p "${BASE_DIR}/generated/roles" cp "${BASE_DIR}/../../../role.yaml" "${BASE_DIR}/generated/roles/role.yaml" cp "${BASE_DIR}/../../../cluster_role.yaml" "${BASE_DIR}/generated/roles/cluster_role.yaml" +cp "${BASE_DIR}/../../../proxy_cluster_role.yaml" "${BASE_DIR}/generated/roles/proxy_cluster_role.yaml" diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/csv-config.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/csv-config.yaml index 87e5a0423..92ed85388 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/csv-config.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/csv-config.yaml @@ -1,3 +1,3 @@ operator-path: deploy/operator.yaml -role-paths: [ "deploy/olm-catalog/nightly/eclipse-che-preview-openshift/generated/roles/role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-openshift/generated/roles/cluster_role.yaml"] +role-paths: [ "deploy/olm-catalog/nightly/eclipse-che-preview-openshift/generated/roles/role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-openshift/generated/roles/cluster_role.yaml", "deploy/olm-catalog/nightly/eclipse-che-preview-openshift/generated/roles/proxy_cluster_role.yaml"] crd-cr-paths: ["deploy/crds/org_v1_che_crd.yaml", "deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml", "deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml", "deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml"] diff --git a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml index 7cc605a9e..892262e1a 100644 --- a/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml +++ b/deploy/olm-catalog/nightly/eclipse-che-preview-openshift/manifests/che-operator.clusterserviceversion.yaml @@ -1,3 +1,13 @@ +# +# Copyright (c) 2019-2021 Red Hat, Inc. +# This program and the accompanying materials are made +# available under the terms of the Eclipse Public License 2.0 +# which is available at https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# Red Hat, Inc. - initial API and implementation apiVersion: operators.coreos.com/v1alpha1 kind: ClusterServiceVersion metadata: @@ -67,13 +77,13 @@ metadata: categories: Developer Tools, OpenShift Optional certified: "false" containerImage: quay.io/eclipse/che-operator:next - createdAt: "2021-06-29T12:30:36Z" + createdAt: "2021-06-30T12:42:43Z" description: A Kube-native development solution that delivers portable and collaborative developer workspaces in OpenShift. operatorframework.io/suggested-namespace: eclipse-che repository: https://github.com/eclipse-che/che-operator support: Eclipse Foundation - name: eclipse-che-preview-openshift.v7.33.0-242.nightly + name: eclipse-che-preview-openshift.v7.33.0-244.nightly namespace: placeholder spec: apiservicedefinitions: {} @@ -505,6 +515,33 @@ spec: - subscriptions verbs: - get + - apiGroups: + - metrics.k8s.io + resources: + - pods + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - workspace.devfile.io + resources: + - devworkspaces + - devworkspacetemplates + verbs: + - get + - list + - watch + - apiGroups: + - controller.devfile.io + resources: + - devworkspaceroutings + - components + verbs: + - get + - list + - watch - apiGroups: - workspace.devfile.io resources: @@ -527,6 +564,33 @@ spec: - deletecollection - patch - update + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - patch - apiGroups: - authentication.k8s.io resources: @@ -558,16 +622,6 @@ spec: - list - watch - apiGroups: - - metrics.k8s.io - resources: - - pods - - nodes - verbs: - - get - - list - - watch - - apiGroups: - - batch - "" resources: - pods/exec @@ -733,37 +787,6 @@ spec: - get - list - watch - - nonResourceURLs: - - /metrics - verbs: - - get - - apiGroups: - - "" - resources: - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - "" - resources: - - configmaps/status - verbs: - - get - - update - - patch - - apiGroups: - - "" - resources: - - events - verbs: - - create - - patch - apiGroups: - "" resources: @@ -945,7 +968,25 @@ spec: - routes/custom-host verbs: - create + - nonResourceURLs: + - /metrics + verbs: + - get serviceAccountName: che-operator + - rules: + - apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + serviceAccountName: default deployments: - name: che-operator spec: @@ -989,7 +1030,7 @@ spec: - name: RELATED_IMAGE_devfile_registry value: quay.io/eclipse/che-devfile-registry:next - name: RELATED_IMAGE_pvc_jobs - value: registry.access.redhat.com/ubi8-minimal:8.4-200.1622548483 + value: registry.access.redhat.com/ubi8-minimal:8.4-205 - name: RELATED_IMAGE_postgres value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_keycloak @@ -1068,6 +1109,49 @@ spec: privileged: false readOnlyRootFilesystem: false runAsNonRoot: true + - args: + - --enable-leader-election + - --metrics-addr + - "0" + command: + - /usr/local/bin/devworkspace-che-operator + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: devworkspace-operator + - name: MAX_CONCURRENT_RECONCILES + value: "1" + - name: CONTROLLER_SERVICE_ACCOUNT_NAME + value: che-operator + - name: RELATED_IMAGE_gateway + value: quay.io/eclipse/che--traefik:v2.3.2-6e6d4dc5a19afe06778ca092cdbbb98e31cb9f9c313edafa23f81a0e6ddf8a23 + - name: RELATED_IMAGE_gateway_configurer + value: quay.io/che-incubator/configbump:0.1.4 + image: quay.io/che-incubator/devworkspace-che-operator:ci + imagePullPolicy: Always + name: devworkspace-che-operator + resources: + limits: + cpu: 100m + memory: 256Mi + requests: + cpu: 100m + memory: 32Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: false + runAsNonRoot: true hostIPC: false hostNetwork: false hostPID: false @@ -1189,6 +1273,32 @@ spec: verbs: - get - list + - apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + - apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch + - apiGroups: + - "" + resources: + - events + verbs: + - create serviceAccountName: che-operator strategy: deployment installModes: @@ -1219,4 +1329,4 @@ spec: maturity: stable provider: name: Eclipse Foundation - version: 7.33.0-242.nightly + version: 7.33.0-244.nightly diff --git a/deploy/operator.yaml b/deploy/operator.yaml index c70eeb9f2..9ed93b91a 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -12,6 +12,10 @@ apiVersion: apps/v1 kind: Deployment metadata: name: che-operator + labels: + app.kubernetes.io/name: che + app.kubernetes.io/instance: che + app.kubernetes.io/component: che-operator spec: replicas: 1 selector: @@ -60,7 +64,7 @@ spec: - name: RELATED_IMAGE_che_tls_secrets_creation_job value: quay.io/eclipse/che-tls-secret-creator:alpine-d1ed4ad - name: RELATED_IMAGE_pvc_jobs - value: registry.access.redhat.com/ubi8-minimal:8.4-200.1622548483 + value: registry.access.redhat.com/ubi8-minimal:8.4-205 - name: RELATED_IMAGE_postgres value: quay.io/eclipse/che--centos--postgresql-96-centos7:9.6-b681d78125361519180a6ac05242c296f8906c11eab7e207b5ca9a89b6344392 - name: RELATED_IMAGE_keycloak @@ -131,6 +135,47 @@ spec: limits: memory: 256Mi cpu: 500m + - args: + - --enable-leader-election + - --metrics-addr + - '0' + command: + - /usr/local/bin/devworkspace-che-operator + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: devworkspace-operator + - name: MAX_CONCURRENT_RECONCILES + value: "1" + - name: CONTROLLER_SERVICE_ACCOUNT_NAME + value: che-operator + - name: RELATED_IMAGE_gateway + value: quay.io/eclipse/che--traefik:v2.3.2-6e6d4dc5a19afe06778ca092cdbbb98e31cb9f9c313edafa23f81a0e6ddf8a23 + - name: RELATED_IMAGE_gateway_configurer + value: quay.io/che-incubator/configbump:0.1.4 + image: quay.io/che-incubator/devworkspace-che-operator:ci + imagePullPolicy: Always + name: devworkspace-che-operator + resources: + limits: + cpu: 100m + memory: 256Mi + requests: + cpu: 100m + memory: 32Mi + securityContext: + privileged: false + readOnlyRootFilesystem: false + capabilities: + drop: + - ALL hostIPC: false hostNetwork: false hostPID: false diff --git a/deploy/proxy_cluster_role.yaml b/deploy/proxy_cluster_role.yaml new file mode 100644 index 000000000..c12576874 --- /dev/null +++ b/deploy/proxy_cluster_role.yaml @@ -0,0 +1,21 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: che-operator-proxy + labels: + app.kubernetes.io/name: che + app.kubernetes.io/instance: che + app.kubernetes.io/component: che-operator +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create diff --git a/deploy/proxy_cluster_role_binding.yaml b/deploy/proxy_cluster_role_binding.yaml new file mode 100644 index 000000000..54069d252 --- /dev/null +++ b/deploy/proxy_cluster_role_binding.yaml @@ -0,0 +1,16 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: che-operator-proxy + labels: + app.kubernetes.io/name: che + app.kubernetes.io/instance: che + app.kubernetes.io/component: che-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: che-operator-proxy +subjects: +- kind: ServiceAccount + name: default + namespace: eclipse-che diff --git a/deploy/role.yaml b/deploy/role.yaml index 65448c998..08dc1b7d6 100644 --- a/deploy/role.yaml +++ b/deploy/role.yaml @@ -8,6 +8,7 @@ metadata: app.kubernetes.io/name: che name: che-operator rules: +### CHE-OPERATOR ROLES ONLY: BEGIN - apiGroups: - extensions resources: @@ -121,3 +122,31 @@ rules: verbs: - get - list +### CHE-OPERATOR ROLES ONLY: END +# devworkspace-che-leader-election-role.Role.yaml +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create diff --git a/local-debug.sh b/local-debug.sh index 249c5ceb8..3d339cb01 100755 --- a/local-debug.sh +++ b/local-debug.sh @@ -21,6 +21,7 @@ ECLIPSE_CHE_CRD="./deploy/crds/org_v1_che_crd.yaml" ECLIPSE_CHE_BACKUP_SERVER_CONFIGURATION_CRD="./deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml" ECLIPSE_CHE_BACKUP_CRD="./deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml" ECLIPSE_CHE_RESTORE_CRD="./deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml" +ECLIPSE_CHE_CRD_V1BETA1="./deploy/crds/org_v1_che_crd-v1beta1.yaml" DEV_WORKSPACE_CONTROLLER_VERSION="main" DEV_WORKSPACE_CHE_OPERATOR_VERSION="main" @@ -65,8 +66,8 @@ prepareTemplates() { curl -sL https://api.github.com/repos/devfile/devworkspace-operator/zipball/${DEV_WORKSPACE_CONTROLLER_VERSION} > /tmp/devworkspace-operator.zip - unzip /tmp/devworkspace-operator.zip '*/deploy/deployment/*' -d /tmp - cp -r /tmp/devfile-devworkspace-operator*/deploy/* /tmp/devworkspace-operator/templates + unzip -q /tmp/devworkspace-operator.zip '*/deploy/deployment/*' -d /tmp + cp -rf /tmp/devfile-devworkspace-operator*/deploy/* /tmp/devworkspace-operator/templates echo "[INFO] Downloading Dev Workspace operator templates completed." # Download Dev Workspace Che operator templates @@ -78,9 +79,9 @@ prepareTemplates() { curl -sL https://api.github.com/repos/che-incubator/devworkspace-che-operator/zipball/${DEV_WORKSPACE_CHE_OPERATOR_VERSION} > /tmp/devworkspace-che-operator.zip - unzip /tmp/devworkspace-che-operator.zip '*/deploy/deployment/*' -d /tmp + unzip -q /tmp/devworkspace-che-operator.zip '*/deploy/deployment/*' -d /tmp cp -r /tmp/che-incubator-devworkspace-che-operator*/deploy/* /tmp/devworkspace-che-operator/templates - echo "[INFO] Downloading Dev Workspace Che operator templates completed." + echo "[INFO] Downloading Dev Workspace operator templates completed." } createNamespace() { @@ -89,7 +90,8 @@ createNamespace() { set -e } -applyCRandCRD() { +applyResources() { + # kubectl apply -f ${ECLIPSE_CHE_CRD_V1BETA1} kubectl apply -f ${ECLIPSE_CHE_CRD} kubectl apply -f ${ECLIPSE_CHE_BACKUP_SERVER_CONFIGURATION_CRD} kubectl apply -f ${ECLIPSE_CHE_BACKUP_CRD} @@ -118,5 +120,5 @@ runDebug() { prepareTemplates createNamespace -applyCRandCRD +applyResources runDebug diff --git a/make-release.sh b/make-release.sh index 17ce3c9a4..6c6d785e0 100755 --- a/make-release.sh +++ b/make-release.sh @@ -130,8 +130,13 @@ if ! grep -q "value: quay.io/eclipse/che-dashboard:$RELEASE" $filename; then echo "[ERROR] Unable to find ubi8_minimal image in the $filename"; exit 1 fi + # use ${RELEASE} instead of master wget https://raw.githubusercontent.com/eclipse-che/che-server/${RELEASE}/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties -q -O /tmp/che.properties + if ! grep -q "value: quay.io/che-incubator/devworkspace-che-operator:$RELEASE" $filename; then + echo "[ERROR] Unable to find devworkspace che operator image with version ${RELEASE} in the $filename"; exit 1 + fi + plugin_broker_meta_image=$(cat /tmp/che.properties | grep che.workspace.plugin_broker.metadata.image | cut -d '=' -f2) if ! grep -q "value: $plugin_broker_meta_image" $filename; then echo "[ERROR] Unable to find plugin broker meta image '$plugin_broker_meta_image' in the $filename"; exit 1 @@ -202,6 +207,7 @@ replaceImagesTags() { yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_keycloak\") | .value ) = \"${KEYCLOAK_IMAGE_RELEASE}\"" | \ yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_plugin_registry\") | .value ) = \"${PLUGIN_REGISTRY_IMAGE_RELEASE}\"" | \ yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_devfile_registry\") | .value ) = \"${DEVFILE_REGISTRY_IMAGE_RELEASE}\"" \ + yq -ryY "( .spec.template.spec.containers[] | select(.name == \"devworkspace-che-operator\") | .image ) = \"quay.io/che-incubator/devworkspace-che-operator:${RELEASE}\"" | \ >> "${NEW_OPERATOR_YAML}" mv "${NEW_OPERATOR_YAML}" "${OPERATOR_YAML}" } diff --git a/olm/buildOLMBundlesFromReleaseManifestFiles.sh b/olm/buildOLMBundlesFromReleaseManifestFiles.sh deleted file mode 100755 index 4b50d8706..000000000 --- a/olm/buildOLMBundlesFromReleaseManifestFiles.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2012-2021 Red Hat, Inc. -# This program and the accompanying materials are made -# available under the terms of the Eclipse Public License 2.0 -# which is available at https://www.eclipse.org/legal/epl-2.0/ -# -# SPDX-License-Identifier: EPL-2.0 -# -# Contributors: -# Red Hat, Inc. - initial API and implementation - -set -e -set -x - -unset PLATFORM -unset FROM_INDEX_IMAGE - -SCRIPT=$(readlink -f "$0") -OPERATOR_REPO=$(dirname "$(dirname "$SCRIPT")") -BASE_DIR="${OPERATOR_REPO}/olm" -source "${BASE_DIR}/olm.sh" - -usage () { - echo "Usage: $0 -p platform [-i from-index-image]" - echo "Example: $0 -p openshift -i quay.io/eclipse/eclipse-che-openshift-opm-catalog:preview" -} - -while [[ "$#" -gt 0 ]]; do - case $1 in - '-p') PLATFORM="$2"; shift 1;; - '-i') FROM_INDEX_IMAGE="$2"; shift 1;; - '--help'|'-h') usage; exit;; - esac - shift 1 -done - -run() { - manifestsFormatRootFolder="${OPERATOR_REPO}/olm/eclipse-che-preview-${PLATFORM}/deploy/olm-catalog/eclipse-che-preview-${PLATFORM}" - pushd "${manifestsFormatRootFolder}" || exit 1 - - stableBundleDir=$(getBundlePath "${PLATFORM}" "stable") - echo "[INFO] Stable bundle directory: ${stableBundleDir}" - bundle_dir=$(mktemp -d -t che-releases-XXX) - echo "[INFO] Bundle directory ${bundle_dir}" - - readarray -t dirs < <(find . -maxdepth 1 -type d -printf '%P\n' | sort) - for versionDir in ${dirs[*]} ; do - if [[ "${versionDir}" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; then - echo "[INFO] Converting manifest format folder ${versionDir} to the bundle format..." - - manifestFormatDir="${manifestsFormatRootFolder}/${versionDir}" - bundleDir="${bundle_dir}/${versionDir}" - mkdir -p "${bundleDir}/manifests" - cp -rf "${stableBundleDir}/bundle.Dockerfile" "${stableBundleDir}/metadata" "${bundleDir}" - packageName=$(getPackageName "${PLATFORM}") - - # Copying resources to bundle directory - cp -rf "${manifestFormatDir}/${packageName}.v${versionDir}.clusterserviceversion.yaml" "${bundleDir}/manifests/che-operator.clusterserviceversion.yaml" - cp -rf "${manifestFormatDir}/${packageName}.crd.yaml" "${bundleDir}/manifests/org_v1_che_crd.yaml" - cp -rf "${manifestFormatDir}/${packageName}.v${versionDir}.clusterserviceversion.yaml.diff" "${bundleDir}/manifests/che-operator.clusterserviceversion.yaml.diff" - cp -rf "${manifestFormatDir}/${packageName}.crd.yaml.diff" "${bundleDir}/manifests/org_v1_che_crd.yaml.diff" - - OPM_BUNDLE_DIR="${bundle_dir}/${versionDir}" - export OPM_BUNDLE_DIR - - # Build and push images - "${OPERATOR_REPO}/olm/buildAndPushBundleImages.sh" -c "stable" -p $PLATFORM -i $FROM_INDEX_IMAGE - fi - done - - popd || true -} - -installOPM -run diff --git a/olm/release-olm-files.sh b/olm/release-olm-files.sh index e3ebb9efe..8cab11cb4 100755 --- a/olm/release-olm-files.sh +++ b/olm/release-olm-files.sh @@ -90,6 +90,7 @@ do -e 's/imagePullPolicy: *Always/imagePullPolicy: IfNotPresent/' \ -e 's/"cheImageTag": *"nightly"/"cheImageTag": ""/' \ -e 's|quay.io/eclipse/che-dashboard:next|quay.io/eclipse/che-dashboard:'${RELEASE}'|' \ + -e 's|quay.io/che-incubator/devworkspace-che-operator:ci|quay.io/che-incubator/devworkspace-che-operator:'${RELEASE}'|' \ -e 's|"identityProviderImage": *"quay.io/eclipse/che-keycloak:nightly"|"identityProviderImage": ""|' \ -e 's|"devfileRegistryImage": *"quay.io/eclipse/che-devfile-registry:nightly"|"devfileRegistryImage": ""|' \ -e 's|"pluginRegistryImage": *"quay.io/eclipse/che-plugin-registry:nightly"|"pluginRegistryImage": ""|' \ diff --git a/olm/update-resources.sh b/olm/update-resources.sh index 97d5479ff..ade6e2887 100755 --- a/olm/update-resources.sh +++ b/olm/update-resources.sh @@ -10,10 +10,6 @@ # Contributors: # Red Hat, Inc. - initial API and implementation -# Generated CRDs based on pkg/apis/org/v1/che_types.go: -# - deploy/crds/org_v1_che_crd.yaml -# - deploy/crds/org_v1_che_crd-v1beta1.yaml - set -e unset UBI8_MINIMAL_IMAGE @@ -45,15 +41,13 @@ checkOperatorSDKVersion() { generateCRD() { version=$1 - pushd "${ROOT_PROJECT_DIR}" || true "${OPERATOR_SDK_BINARY}" generate k8s "${OPERATOR_SDK_BINARY}" generate crds --crd-version $version - popd - addLicenseHeader ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusters_crd.yaml - addLicenseHeader ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml - addLicenseHeader ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml - addLicenseHeader ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml + ensureLicense ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusters_crd.yaml + ensureLicense ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml + ensureLicense ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml + ensureLicense ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml if [[ $version == "v1" ]]; then mv ${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusters_crd.yaml ${ROOT_PROJECT_DIR}/deploy/crds/org_v1_che_crd.yaml @@ -120,13 +114,105 @@ detectImages() { echo "[INFO] Plugin broker jwt proxy image: $JWT_PROXY_IMAGE" } +updateRoles() { + echo "[INFO] Updating roles with DW and DWCO roles" + + CLUSTER_ROLES=( + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-view-workspaces.ClusterRole.yaml + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-edit-workspaces.ClusterRole.yaml + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-leader-election-role.Role.yaml + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-proxy-role.ClusterRole.yaml + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-role.ClusterRole.yaml + https://raw.githubusercontent.com/devfile/devworkspace-operator/main/deploy/deployment/openshift/objects/devworkspace-controller-view-workspaces.ClusterRole.yaml + https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/deploy/deployment/openshift/objects/devworkspace-che-role.ClusterRole.yaml + https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/deploy/deployment/openshift/objects/devworkspace-che-metrics-reader.ClusterRole.yaml + ) + + # Updates cluster_role.yaml based on DW and DWCO roles + ## Removes old cluster roles + cat $ROOT_PROJECT_DIR/deploy/cluster_role.yaml | sed '/CHE-OPERATOR ROLES ONLY: END/q0' > $ROOT_PROJECT_DIR/deploy/cluster_role.yaml.tmp + mv $ROOT_PROJECT_DIR/deploy/cluster_role.yaml.tmp $ROOT_PROJECT_DIR/deploy/cluster_role.yaml + + ## Copy new cluster roles + for roles in "${CLUSTER_ROLES[@]}"; do + echo " # "$(basename $roles) >> $ROOT_PROJECT_DIR/deploy/cluster_role.yaml + + CONTENT=$(curl -sL $roles | sed '1,/rules:/d') + while IFS= read -r line; do + echo " $line" >> $ROOT_PROJECT_DIR/deploy/cluster_role.yaml + done <<< "$CONTENT" + done + + ROLES=( + https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/deploy/deployment/openshift/objects/devworkspace-che-leader-election-role.Role.yaml + ) + + # Updates role.yaml + ## Removes old roles + cat $ROOT_PROJECT_DIR/deploy/role.yaml | sed '/CHE-OPERATOR ROLES ONLY: END/q0' > $ROOT_PROJECT_DIR/deploy/role.yaml.tmp + mv $ROOT_PROJECT_DIR/deploy/role.yaml.tmp $ROOT_PROJECT_DIR/deploy/role.yaml + + + ## Copy new roles + for roles in "${ROLES[@]}"; do + echo "# "$(basename $roles) >> $ROOT_PROJECT_DIR/deploy/role.yaml + + CONTENT=$(curl -sL $roles | sed '1,/rules:/d') + while IFS= read -r line; do + echo "$line" >> $ROOT_PROJECT_DIR/deploy/role.yaml + done <<< "$CONTENT" + done + + # Updates proxy_cluster_role.yaml based on DWCO + ## Remove old roles + cat $ROOT_PROJECT_DIR/deploy/proxy_cluster_role.yaml | sed '/rules:/q0' > $ROOT_PROJECT_DIR/deploy/proxy_cluster_role.yaml.tmp + mv $ROOT_PROJECT_DIR/deploy/proxy_cluster_role.yaml.tmp $ROOT_PROJECT_DIR/deploy/proxy_cluster_role.yaml + + ## Copy new roles + CLUSTER_PROXY_ROLES=https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/deploy/deployment/openshift/objects/devworkspace-che-proxy-role.ClusterRole.yaml + CONTENT=$(curl -sL $CLUSTER_PROXY_ROLES | sed '1,/rules:/d') + while IFS= read -r line; do + echo "$line" >> $ROOT_PROJECT_DIR/deploy/proxy_cluster_role.yaml + done <<< "$CONTENT" +} + updateOperatorYaml() { OPERATOR_YAML="${ROOT_PROJECT_DIR}/deploy/operator.yaml" yq -riY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_pvc_jobs\") | .value ) = \"${UBI8_MINIMAL_IMAGE}\"" ${OPERATOR_YAML} yq -riY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_che_workspace_plugin_broker_metadata\") | .value ) = \"${PLUGIN_BROKER_METADATA_IMAGE}\"" ${OPERATOR_YAML} yq -riY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_che_workspace_plugin_broker_artifacts\") | .value ) = \"${PLUGIN_BROKER_ARTIFACTS_IMAGE}\"" ${OPERATOR_YAML} yq -riY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_che_server_secure_exposer_jwt_proxy_image\") | .value ) = \"${JWT_PROXY_IMAGE}\"" ${OPERATOR_YAML} - addLicenseHeader $OPERATOR_YAML + + # Deletes old DWCO container + yq -riY "del(.spec.template.spec.containers[1])" $OPERATOR_YAML + yq -riY ".spec.template.spec.containers[1] = \"devworkspace-container\"" $OPERATOR_YAML + + # Extract DWCO container spec from deployment + DWCO_CONTAINER=$(curl -sL https://raw.githubusercontent.com/che-incubator/devworkspace-che-operator/main/deploy/deployment/openshift/objects/devworkspace-che-manager.Deployment.yaml \ + | sed '1,/containers:/d' \ + | sed -n '/serviceAccountName:/q;p' \ + | sed -e 's/^/ /') + echo "$DWCO_CONTAINER" > dwcontainer + + # Add DWCO container to operator.yaml + sed -i -e '/- devworkspace-container/{r dwcontainer' -e 'd}' $OPERATOR_YAML + rm dwcontainer + + # update securityContext + yq -riY ".spec.template.spec.containers[1].securityContext.privileged = false" ${OPERATOR_YAML} + yq -riY ".spec.template.spec.containers[1].securityContext.readOnlyRootFilesystem = false" ${OPERATOR_YAML} + yq -riY ".spec.template.spec.containers[1].securityContext.capabilities.drop[0] = \"ALL\"" ${OPERATOR_YAML} + + # update env variable + yq -riY "del( .spec.template.spec.containers[1].env[] | select(.name == \"CONTROLLER_SERVICE_ACCOUNT_NAME\") | .valueFrom)" ${OPERATOR_YAML} + yq -riY "( .spec.template.spec.containers[1].env[] | select(.name == \"CONTROLLER_SERVICE_ACCOUNT_NAME\") | .value) = \"che-operator\"" ${OPERATOR_YAML} + yq -riY "del( .spec.template.spec.containers[1].env[] | select(.name == \"WATCH_NAMESPACE\") | .value)" ${OPERATOR_YAML} + yq -riY "( .spec.template.spec.containers[1].env[] | select(.name == \"WATCH_NAMESPACE\") | .valueFrom.fieldRef.fieldPath) = \"metadata.namespace\"" ${OPERATOR_YAML} + + yq -riY ".spec.template.spec.containers[1].args[1] = \"--metrics-addr\"" ${OPERATOR_YAML} + yq -riY ".spec.template.spec.containers[1].args[2] = \"0\"" ${OPERATOR_YAML} + + ensureLicense $OPERATOR_YAML } updateDockerfile() { @@ -146,29 +232,27 @@ updateNighltyBundle() { echo "[INFO] Updating OperatorHub bundle for platform '${platform}'" - pushd "${ROOT_PROJECT_DIR}" || true - NIGHTLY_BUNDLE_PATH=$(getBundlePath "${platform}" "nightly") - bundleCSVName="che-operator.clusterserviceversion.yaml" - NEW_CSV=${NIGHTLY_BUNDLE_PATH}/manifests/${bundleCSVName} + NEW_CSV=${NIGHTLY_BUNDLE_PATH}/manifests/che-operator.clusterserviceversion.yaml newNightlyBundleVersion=$(yq -r ".spec.version" "${NEW_CSV}") echo "[INFO] Creation new nightly bundle version: ${newNightlyBundleVersion}" - csv_config=${NIGHTLY_BUNDLE_PATH}/csv-config.yaml generateFolder=${NIGHTLY_BUNDLE_PATH}/generated rm -rf "${generateFolder}" - mkdir -p "${generateFolder}" + mkdir -p "${generateFolder}/crds" + # copy roles "${NIGHTLY_BUNDLE_PATH}/build-roles.sh" - operatorYaml=$(yq -r ".\"operator-path\"" "${csv_config}") - cp -rf "${operatorYaml}" "${generateFolder}/" + # copy operator.yaml + operatorYaml=$(yq -r ".\"operator-path\"" "${NIGHTLY_BUNDLE_PATH}/csv-config.yaml") + cp -rf "${operatorYaml}" "${generateFolder}" - crdsDir=${ROOT_PROJECT_DIR}/deploy/crds - mkdir -p ${generateFolder}/crds - cp -f "${crdsDir}/org_v1_che_cr.yaml" "${generateFolder}/crds" - cp -f "${crdsDir}/org_v1_che_crd.yaml" "${generateFolder}/crds" + # copy CR/CRD + cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org_v1_che_cr.yaml" "${generateFolder}/crds" + cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org_v1_che_crd.yaml" "${generateFolder}/crds" + # generate a new CSV "${OPERATOR_SDK_BINARY}" generate csv \ --csv-version "${newNightlyBundleVersion}" \ --deploy-dir "${generateFolder}" \ @@ -191,16 +275,13 @@ updateNighltyBundle() { incrementNightlyVersion "${platform}" fi - templateCRD="${ROOT_PROJECT_DIR}/deploy/crds/org_v1_che_crd.yaml" - platformCRD="${NIGHTLY_BUNDLE_PATH}/manifests/org_v1_che_crd.yaml" - - cp -rf $templateCRD $platformCRD + cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org_v1_che_crd.yaml" "${NIGHTLY_BUNDLE_PATH}/manifests" cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_chebackupserverconfigurations_crd.yaml" "${NIGHTLY_BUNDLE_PATH}/manifests/org.eclipse.che_chebackupserverconfigurations_crd.yaml" cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterbackups_crd.yaml" "${NIGHTLY_BUNDLE_PATH}/manifests/org.eclipse.che_checlusterbackups_crd.yaml" cp -f "${ROOT_PROJECT_DIR}/deploy/crds/org.eclipse.che_checlusterrestores_crd.yaml" "${NIGHTLY_BUNDLE_PATH}/manifests/org.eclipse.che_checlusterrestores_crd.yaml" + CRD="${NIGHTLY_BUNDLE_PATH}/manifests/org_v1_che_crd.yaml" if [[ $platform == "openshift" ]]; then - yq -riSY '.spec.preserveUnknownFields = false' $platformCRD - eval head -10 $templateCRD | cat - ${platformCRD} > tmp.crd && mv tmp.crd ${platformCRD} + yq -riSY '.spec.preserveUnknownFields = false' $CRD fi echo "Done for ${platform}" @@ -223,6 +304,9 @@ updateNighltyBundle() { done fi + # Fix account name + sed -i 's|serviceAccountName: che-operator-proxy|serviceAccountName: default|g' $NEW_CSV + # Fix sample if [ "${platform}" == "openshift" ]; then echo "[INFO] Fix openshift sample" @@ -251,17 +335,21 @@ updateNighltyBundle() { if [ "${platform}" == "openshift" ]; then yq -riSY '(.spec.install.spec.deployments[0].spec.template.spec.containers[0].securityContext."allowPrivilegeEscalation") = false' "${NEW_CSV}" yq -riSY '(.spec.install.spec.deployments[0].spec.template.spec.containers[0].securityContext."runAsNonRoot") = true' "${NEW_CSV}" + yq -riSY '(.spec.install.spec.deployments[0].spec.template.spec.containers[1].securityContext."allowPrivilegeEscalation") = false' "${NEW_CSV}" + yq -riSY '(.spec.install.spec.deployments[0].spec.template.spec.containers[1].securityContext."runAsNonRoot") = true' "${NEW_CSV}" fi # Format code. yq -rY "." "${NEW_CSV}" > "${NEW_CSV}.old" mv "${NEW_CSV}.old" "${NEW_CSV}" - popd || true + ensureLicense "${NIGHTLY_BUNDLE_PATH}/manifests/org_v1_che_crd.yaml" + ensureLicense "${NIGHTLY_BUNDLE_PATH}/manifests/che-operator.clusterserviceversion.yaml" done } -addLicenseHeader() { +ensureLicense() { + if [[ $(sed -n '/^#$/p;q' $1) != "#" ]]; then echo -e "# # Copyright (c) 2019-2021 Red Hat, Inc. # This program and the accompanying materials are made @@ -273,12 +361,19 @@ echo -e "# # Contributors: # Red Hat, Inc. - initial API and implementation $(cat $1)" > $1 +fi } checkOperatorSDKVersion detectImages + +pushd "${ROOT_PROJECT_DIR}" || true + generateCRD "v1beta1" generateCRD "v1" +updateRoles updateOperatorYaml updateDockerfile updateNighltyBundle + +popd || true diff --git a/pkg/apis/org/conversion_test.go b/pkg/apis/org/conversion_test.go index 4c6d1394e..c051f750a 100644 --- a/pkg/apis/org/conversion_test.go +++ b/pkg/apis/org/conversion_test.go @@ -563,7 +563,7 @@ func TestExposureStrategyConversions(t *testing.T) { if old.Spec.Server.ServerExposureStrategy != "" { t.Errorf("The server exposure strategy should have been left empty after conversion but was: %v", old.Spec.Server.ServerExposureStrategy) } - if old.Spec.K8s.IngressStrategy != "multi-host" { + if old.Spec.K8s.IngressStrategy != "single-host" { t.Errorf("The ingress strategy should have been unchanged after conversion but was: %v", old.Spec.K8s.IngressStrategy) } }) diff --git a/pkg/deploy/dev-workspace/dev_workspace.go b/pkg/deploy/dev-workspace/dev_workspace.go index e737094cc..ba73429f9 100644 --- a/pkg/deploy/dev-workspace/dev_workspace.go +++ b/pkg/deploy/dev-workspace/dev_workspace.go @@ -22,6 +22,7 @@ import ( "github.com/eclipse-che/che-operator/pkg/deploy" "github.com/eclipse-che/che-operator/pkg/util" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/sirupsen/logrus" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -47,9 +48,9 @@ var ( CheManagerResourcename = "chemanagers" OpenshiftDevWorkspaceTemplatesPath = "/tmp/devworkspace-operator/templates/deployment/openshift/objects" - OpenshiftDevWorkspaceCheTemplatesPath = "/tmp/devworkspace-che-operator/templates/deployment/openshift/objects/" + OpenshiftDevWorkspaceCheTemplatesPath = "/tmp/devworkspace-che-operator/templates/deployment/openshift/objects" KubernetesDevWorkspaceTemplatesPath = "/tmp/devworkspace-operator/templates/deployment/kubernetes/objects" - KubernetesDevWorkspaceCheTemplatesPath = "/tmp/devworkspace-che-operator/templates/deployment/kubernetes/objects/" + KubernetesDevWorkspaceCheTemplatesPath = "/tmp/devworkspace-che-operator/templates/deployment/kubernetes/objects" DevWorkspaceTemplates = devWorkspaceTemplatesPath() DevWorkspaceCheTemplates = devWorkspaceCheTemplatesPath() @@ -113,28 +114,24 @@ var ( } syncDwCheItems = []func(*deploy.DeployContext) (bool, error){ - createDwCheNamespace, - syncDwCheServiceAccount, - syncDwCheClusterRole, - syncDwCheProxyClusterRole, - syncDwCheMetricsClusterRole, - syncDwCheLeaderRole, - syncDwCheLeaderRoleBinding, - syncDwCheProxyRoleBinding, - syncDwCheRoleBinding, syncDwCheCRD, - synDwCheCR, - syncDwCheConfigMap, + syncDwCheCR, syncDwCheMetricsService, - synDwCheDeployment, } ) func ReconcileDevWorkspace(deployContext *deploy.DeployContext) (bool, error) { + if util.IsOpenShift && !util.IsOpenShift4 { + // OpenShift 3.x is not supported + return true, nil + } + + // do nothing if dev workspace is disabled if !deployContext.CheCluster.Spec.DevWorkspace.Enable { return true, nil } + // check if DW exists on the cluster devWorkspaceWebhookExists, err := deploy.Get( deployContext, client.ObjectKey{Name: DevWorkspaceWebhookName}, @@ -145,6 +142,7 @@ func ReconcileDevWorkspace(deployContext *deploy.DeployContext) (bool, error) { } if devWorkspaceWebhookExists { + // if DW exists then check if version matches if err := checkWebTerminalSubscription(deployContext); err != nil { return false, err } @@ -159,6 +157,11 @@ func ReconcileDevWorkspace(deployContext *deploy.DeployContext) (bool, error) { } } + if !util.IsOpenShift && util.GetServerExposureStrategy(deployContext.CheCluster) == "single-host" { + logrus.Warn(`DevWorkspace Che operator can't be enabled in 'single-host' mode on a Kubernetes cluster. See https://github.com/eclipse/che/issues/19714 for more details. To enable DevWorkspace Che operator set 'spec.server.serverExposureStrategy' to 'multi-host'.`) + return true, nil + } + for _, syncItem := range syncDwCheItems { done, err := syncItem(deployContext) if !util.IsTestMode() { @@ -211,60 +214,60 @@ func createDwNamespace(deployContext *deploy.DeployContext) (bool, error) { } func syncDwServiceAccount(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceServiceAccountFile, &corev1.ServiceAccount{}) + return readAndSyncObject(deployContext, DevWorkspaceServiceAccountFile, &corev1.ServiceAccount{}, DevWorkspaceNamespace) } func syncDwRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceRoleFile, &rbacv1.Role{}) + return readAndSyncObject(deployContext, DevWorkspaceRoleFile, &rbacv1.Role{}, DevWorkspaceNamespace) } func syncDwRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceRoleBindingFile, &rbacv1.RoleBinding{}) + return readAndSyncObject(deployContext, DevWorkspaceRoleBindingFile, &rbacv1.RoleBinding{}, DevWorkspaceNamespace) } func syncDwClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) + return readAndSyncObject(deployContext, DevWorkspaceClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}, "") } func syncDwProxyClusterRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceProxyClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) + return readAndSyncObject(deployContext, DevWorkspaceProxyClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}, "") } func syncDwClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceClusterRoleFile, &rbacv1.ClusterRole{}) + return readAndSyncObject(deployContext, DevWorkspaceClusterRoleFile, &rbacv1.ClusterRole{}, "") } func syncDwProxyClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceProxyClusterRoleFile, &rbacv1.ClusterRole{}) + return readAndSyncObject(deployContext, DevWorkspaceProxyClusterRoleFile, &rbacv1.ClusterRole{}, "") } func syncDwViewWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceViewWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}) + return readAndSyncObject(deployContext, DevWorkspaceViewWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}, "") } func syncDwEditWorkspacesClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceEditWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}) + return readAndSyncObject(deployContext, DevWorkspaceEditWorkspacesClusterRoleFile, &rbacv1.ClusterRole{}, "") } func syncDwWorkspaceRoutingCRD(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceWorkspaceRoutingCRDFile, &apiextensionsv1.CustomResourceDefinition{}) + return readAndSyncObject(deployContext, DevWorkspaceWorkspaceRoutingCRDFile, &apiextensionsv1.CustomResourceDefinition{}, "") } func syncDwTemplatesCRD(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceTemplatesCRDFile, &apiextensionsv1.CustomResourceDefinition{}) + return readAndSyncObject(deployContext, DevWorkspaceTemplatesCRDFile, &apiextensionsv1.CustomResourceDefinition{}, "") } func syncDwCRD(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCRDFile, &apiextensionsv1.CustomResourceDefinition{}) + return readAndSyncObject(deployContext, DevWorkspaceCRDFile, &apiextensionsv1.CustomResourceDefinition{}, "") } func syncDwConfigMap(deployContext *deploy.DeployContext) (bool, error) { - devObject, err := readK8SObject(DevWorkspaceConfigMapFile, &corev1.ConfigMap{}) + obj2sync, err := readK8SObject(DevWorkspaceConfigMapFile, &corev1.ConfigMap{}) if err != nil { return false, err } - configMap := devObject.obj.(*corev1.ConfigMap) + configMap := obj2sync.obj.(*corev1.ConfigMap) // Remove when DevWorkspace controller should not care about DWR base host #373 https://github.com/devfile/devworkspace-operator/issues/373 if !util.IsOpenShift { if configMap.Data == nil { @@ -273,82 +276,31 @@ func syncDwConfigMap(deployContext *deploy.DeployContext) (bool, error) { configMap.Data["devworkspace.routing.cluster_host_suffix"] = deployContext.CheCluster.Spec.K8s.IngressDomain } - return syncObject(deployContext, devObject) + return syncObject(deployContext, obj2sync, DevWorkspaceNamespace) } func syncDwDeployment(deployContext *deploy.DeployContext) (bool, error) { - devObject, err := readK8SObject(DevWorkspaceDeploymentFile, &appsv1.Deployment{}) + obj2sync, err := readK8SObject(DevWorkspaceDeploymentFile, &appsv1.Deployment{}) if err != nil { return false, err } devworkspaceControllerImage := util.GetValue(deployContext.CheCluster.Spec.DevWorkspace.ControllerImage, deploy.DefaultDevworkspaceControllerImage(deployContext.CheCluster)) - deploymentObject := devObject.obj.(*appsv1.Deployment) + deploymentObject := obj2sync.obj.(*appsv1.Deployment) deploymentObject.Spec.Template.Spec.Containers[0].Image = devworkspaceControllerImage - return syncObject(deployContext, devObject) -} - -func createDwCheNamespace(deployContext *deploy.DeployContext) (bool, error) { - namespace := &corev1.Namespace{ - TypeMeta: metav1.TypeMeta{ - Kind: "Namespace", - APIVersion: corev1.SchemeGroupVersion.String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: DevWorkspaceCheNamespace, - }, - Spec: corev1.NamespaceSpec{}, - } - - return deploy.CreateIfNotExists(deployContext, namespace) -} - -func syncDwCheServiceAccount(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheServiceAccountFile, &corev1.ServiceAccount{}) -} - -func syncDwCheClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheClusterRoleFile, &rbacv1.ClusterRole{}) -} - -func syncDwCheProxyClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheProxyClusterRoleFile, &rbacv1.ClusterRole{}) -} - -func syncDwCheMetricsClusterRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheMetricsReaderClusterRoleFile, &rbacv1.ClusterRole{}) -} - -func syncDwCheLeaderRole(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheRoleFile, &rbacv1.Role{}) -} - -func syncDwCheLeaderRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheRoleBindingFile, &rbacv1.RoleBinding{}) -} - -func syncDwCheProxyRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheProxyClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) -} - -func syncDwCheRoleBinding(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheClusterRoleBindingFile, &rbacv1.ClusterRoleBinding{}) + return syncObject(deployContext, obj2sync, DevWorkspaceNamespace) } func syncDwCheCRD(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheManagersCRDFile, &apiextensionsv1.CustomResourceDefinition{}) -} - -func syncDwCheConfigMap(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheConfigMapFile, &corev1.ConfigMap{}) + return readAndSyncObject(deployContext, DevWorkspaceCheManagersCRDFile, &apiextensionsv1.CustomResourceDefinition{}, "") } func syncDwCheMetricsService(deployContext *deploy.DeployContext) (bool, error) { - return readAndSyncObject(deployContext, DevWorkspaceCheMetricsServiceFile, &corev1.Service{}) + return readAndSyncObject(deployContext, DevWorkspaceCheMetricsServiceFile, &corev1.Service{}, deployContext.CheCluster.Namespace) } -func synDwCheCR(deployContext *deploy.DeployContext) (bool, error) { +func syncDwCheCR(deployContext *deploy.DeployContext) (bool, error) { // We want to create a default CheManager instance to be able to configure the che-specific // parts of the installation, but at the same time we don't want to add a dependency on // devworkspace-che-operator. Note that this way of initializing will probably see changes @@ -361,7 +313,7 @@ func synDwCheCR(deployContext *deploy.DeployContext) (bool, error) { obj := &unstructured.Unstructured{} obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager"}) - err := deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: DevWorkspaceCheNamespace}, obj) + err := deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: deployContext.CheCluster.Namespace}, obj) if err != nil { if apierrors.IsNotFound(err) { obj = nil @@ -372,13 +324,20 @@ func synDwCheCR(deployContext *deploy.DeployContext) (bool, error) { if obj == nil { obj := &unstructured.Unstructured{} + if !util.IsOpenShift { + obj.SetUnstructuredContent(map[string]interface{}{ + "spec": map[string]interface{}{ + "gatewayHost": deployContext.CheCluster.Spec.K8s.IngressDomain, + }, + }) + } obj.SetGroupVersionKind(schema.GroupVersionKind{ Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager", }) obj.SetName("devworkspace-che") - obj.SetNamespace(DevWorkspaceCheNamespace) + obj.SetNamespace(deployContext.CheCluster.Namespace) err = deployContext.ClusterAPI.Client.Create(context.TODO(), obj) if err != nil { @@ -392,29 +351,18 @@ func synDwCheCR(deployContext *deploy.DeployContext) (bool, error) { return true, nil } -func synDwCheDeployment(deployContext *deploy.DeployContext) (bool, error) { - devObject, err := readK8SObject(DevWorkspaceCheDeploymentFile, &appsv1.Deployment{}) - if err != nil { - return false, err - } - - devworkspaceCheOperatorImage := deploy.DefaultDevworkspaceCheOperatorImage(deployContext.CheCluster) - deploymentObject := devObject.obj.(*appsv1.Deployment) - deploymentObject.Spec.Template.Spec.Containers[0].Image = devworkspaceCheOperatorImage - - return syncObject(deployContext, devObject) -} - -func readAndSyncObject(deployContext *deploy.DeployContext, yamlFile string, obj interface{}) (bool, error) { +func readAndSyncObject(deployContext *deploy.DeployContext, yamlFile string, obj interface{}, namespace string) (bool, error) { obj2sync, err := readK8SObject(yamlFile, obj) if err != nil { return false, err } - return syncObject(deployContext, obj2sync) + return syncObject(deployContext, obj2sync, namespace) } -func syncObject(deployContext *deploy.DeployContext, obj2sync *Object2Sync) (bool, error) { +func syncObject(deployContext *deploy.DeployContext, obj2sync *Object2Sync, namespace string) (bool, error) { + obj2sync.obj.SetNamespace(namespace) + runtimeObject, ok := obj2sync.obj.(runtime.Object) if !ok { return false, fmt.Errorf("object %T is not a runtime.Object. Cannot sync it", runtimeObject) diff --git a/pkg/deploy/dev-workspace/dev_workspace_test.go b/pkg/deploy/dev-workspace/dev_workspace_test.go index 1d0d053cd..46d835609 100644 --- a/pkg/deploy/dev-workspace/dev_workspace_test.go +++ b/pkg/deploy/dev-workspace/dev_workspace_test.go @@ -20,6 +20,7 @@ import ( operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" admissionregistrationv1 "k8s.io/api/admissionregistration/v1" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -31,56 +32,144 @@ import ( ) func TestReconcileDevWorkspace(t *testing.T) { - cheCluster := &orgv1.CheCluster{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: "eclipse-che", - }, - Spec: orgv1.CheClusterSpec{ - DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ - Enable: true, - }, - Auth: orgv1.CheClusterSpecAuth{ - OpenShiftoAuth: util.NewBoolPointer(true), + type testCase struct { + name string + IsOpenShift bool + IsOpenShift4 bool + cheCluster *orgv1.CheCluster + } + + testCases := []testCase{ + { + name: "Reconcile DevWorkspace on OpenShift", + cheCluster: &orgv1.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + }, + Spec: orgv1.CheClusterSpec{ + DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ + Enable: true, + }, + Auth: orgv1.CheClusterSpecAuth{ + OpenShiftoAuth: util.NewBoolPointer(true), + }, + Server: orgv1.CheClusterSpecServer{ + ServerExposureStrategy: "single-host", + }, + }, }, - Server: orgv1.CheClusterSpecServer{ - ServerExposureStrategy: "single-host", + IsOpenShift: true, + IsOpenShift4: true, + }, + { + name: "Reconcile DevWorkspace on K8S multi-host", + cheCluster: &orgv1.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + }, + Spec: orgv1.CheClusterSpec{ + DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ + Enable: true, + }, + Auth: orgv1.CheClusterSpecAuth{ + OpenShiftoAuth: util.NewBoolPointer(true), + }, + Server: orgv1.CheClusterSpecServer{ + ServerExposureStrategy: "multi-host", + }, + K8s: orgv1.CheClusterSpecK8SOnly{ + IngressDomain: "che.domain", + }, + }, }, + IsOpenShift: false, + IsOpenShift4: false, }, - } - - deployContext := deploy.GetTestDeployContext(cheCluster, []runtime.Object{}) - deployContext.ClusterAPI.Scheme.AddKnownTypes(operatorsv1alpha1.SchemeGroupVersion, &operatorsv1alpha1.Subscription{}) - deployContext.ClusterAPI.DiscoveryClient.(*fakeDiscovery.FakeDiscovery).Fake.Resources = []*metav1.APIResourceList{ { - APIResources: []metav1.APIResource{ - {Name: CheManagerResourcename}, + name: "Reconcile DevWorkspace on K8S single-host", + cheCluster: &orgv1.CheCluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "eclipse-che", + }, + Spec: orgv1.CheClusterSpec{ + DevWorkspace: orgv1.CheClusterSpecDevWorkspace{ + Enable: true, + }, + Auth: orgv1.CheClusterSpecAuth{ + OpenShiftoAuth: util.NewBoolPointer(true), + }, + Server: orgv1.CheClusterSpecServer{ + ServerExposureStrategy: "single-host", + }, + K8s: orgv1.CheClusterSpecK8SOnly{ + IngressDomain: "che.domain", + }, + }, }, + IsOpenShift: false, + IsOpenShift4: false, }, } - util.IsOpenShift4 = true - done, err := ReconcileDevWorkspace(deployContext) - - if err != nil { - t.Fatalf("Error: %v", err) - } - - if !done { - t.Fatalf("Dev Workspace operator has not been provisioned") + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployContext := deploy.GetTestDeployContext(testCase.cheCluster, []runtime.Object{}) + deployContext.ClusterAPI.Scheme.AddKnownTypes(operatorsv1alpha1.SchemeGroupVersion, &operatorsv1alpha1.Subscription{}) + deployContext.ClusterAPI.DiscoveryClient.(*fakeDiscovery.FakeDiscovery).Fake.Resources = []*metav1.APIResourceList{ + { + APIResources: []metav1.APIResource{ + {Name: CheManagerResourcename}, + }, + }, + } + + util.IsOpenShift = testCase.IsOpenShift + util.IsOpenShift4 = testCase.IsOpenShift4 + done, err := ReconcileDevWorkspace(deployContext) + if err != nil { + t.Fatalf("Error: %v", err) + } + if !done { + t.Fatalf("Dev Workspace operator has not been provisioned") + } + + t.Run("defaultCheManagerDeployed", func(t *testing.T) { + obj := &unstructured.Unstructured{} + obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager"}) + err := deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: deployContext.CheCluster.Namespace}, obj) + + if testCase.IsOpenShift { + if err != nil { + t.Fatalf("Should have found a CheManager with default config but got an error: %s", err) + } + + if obj.GetName() != "devworkspace-che" { + t.Fatalf("Should have found a CheManager with default config but found: %s", obj.GetName()) + } + } else { + if testCase.cheCluster.Spec.Server.ServerExposureStrategy == "single-host" { + if err == nil || !apierrors.IsNotFound(err) { + t.Fatalf("Should not have found a CheManager") + } + } else { + if err != nil { + t.Fatalf("Should have found a CheManager with default config but got an error: %s", err) + } + + if obj.GetName() != "devworkspace-che" { + t.Fatalf("Should have found a CheManager with default config but found: %s", obj.GetName()) + } + + spec := obj.Object["spec"].(map[string]interface{}) + gatewayHost := spec["gatewayHost"].(string) + if gatewayHost != deployContext.CheCluster.Spec.K8s.IngressDomain { + t.Fatalf("gatewayHost wasn't set correctly, expected: %s, actual: %s", deployContext.CheCluster.Spec.K8s.IngressDomain, gatewayHost) + } + } + } + }) + }) } - - t.Run("defaultCheManagerDeployed", func(t *testing.T) { - obj := &unstructured.Unstructured{} - obj.SetGroupVersionKind(schema.GroupVersionKind{Group: "che.eclipse.org", Version: "v1alpha1", Kind: "CheManager"}) - err := deployContext.ClusterAPI.Client.Get(context.TODO(), client.ObjectKey{Name: "devworkspace-che", Namespace: DevWorkspaceCheNamespace}, obj) - if err != nil { - t.Fatalf("Should have found a CheManager with default config but got an error: %s", err) - } - - if obj.GetName() != "devworkspace-che" { - t.Fatalf("Should have found a CheManager with default config but found: %s", obj.GetName()) - } - }) } func TestReconcileDevWorkspaceShouldThrowErrorIfWebTerminalSubscriptionExists(t *testing.T) { @@ -124,6 +213,7 @@ func TestReconcileDevWorkspaceShouldThrowErrorIfWebTerminalSubscriptionExists(t }, } + util.IsOpenShift = true util.IsOpenShift4 = true _, err := ReconcileDevWorkspace(deployContext) @@ -142,7 +232,7 @@ func TestShouldSyncNewObject(t *testing.T) { } // tries to sync a new object - done, err := syncObject(deployContext, obj2sync) + done, err := syncObject(deployContext, obj2sync, "eclipse-che") if err != nil { t.Fatalf("Failed to sync object: %v", err) } else if !done { @@ -194,7 +284,7 @@ func TestShouldSyncObjectIfItWasCreatedByAnotherOriginHashDifferent(t *testing.T obj: newObject, hash256: "hash", } - _, err := syncObject(deployContext, obj2sync) + _, err := syncObject(deployContext, obj2sync, "eclipse-che") if err != nil { t.Fatalf("Failed to sync object: %v", err) } @@ -238,7 +328,7 @@ func TestShouldSyncObjectIfItWasCreatedBySameOriginHashDifferent(t *testing.T) { } // tries to sync object with a new - _, err := syncObject(deployContext, obj2sync) + _, err := syncObject(deployContext, obj2sync, "eclipse-che") if err != nil { t.Fatalf("Failed to sync object: %v", err) } @@ -303,7 +393,7 @@ func TestShouldNotSyncObjectIfThereIsAnotherCheCluster(t *testing.T) { obj: newObject, hash256: "hash-1", } - done, err := syncObject(deployContext, obj2sync) + done, err := syncObject(deployContext, obj2sync, "eclipse-che") if err != nil { t.Fatalf("Failed to sync object: %v", err) } else if !done { @@ -347,7 +437,7 @@ func TestShouldNotSyncObjectIfHashIsEqual(t *testing.T) { obj: newObject, hash256: "hash", } - done, err := syncObject(deployContext, obj2sync) + done, err := syncObject(deployContext, obj2sync, "eclipse-che") if err != nil { t.Fatalf("Failed to sync object: %v", err) } else if !done { diff --git a/pkg/util/util.go b/pkg/util/util.go index aa3c29c34..90e8d1dc7 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -200,17 +200,21 @@ func MergeMaps(first map[string]string, second map[string]string) map[string]str return ret } -func GetServerExposureStrategy(c *orgv1.CheCluster) string { - strategy := c.Spec.Server.ServerExposureStrategy - if strategy != "" { - return strategy - } else if c.Spec.DevWorkspace.Enable { +func GetServerExposureStrategy(cheCluster *orgv1.CheCluster) string { + if cheCluster.Spec.Server.ServerExposureStrategy != "" { + return cheCluster.Spec.Server.ServerExposureStrategy + } + + if !IsOpenShift && cheCluster.Spec.K8s.IngressStrategy != "" { + return cheCluster.Spec.K8s.IngressStrategy + } + + // Explicitly switch to `single-host` mode + if cheCluster.Spec.DevWorkspace.Enable { return "single-host" - } else if IsOpenShift { - return "multi-host" - } else { - return GetValue(c.Spec.K8s.IngressStrategy, "multi-host") } + + return "multi-host" } func IsTestMode() (isTesting bool) { diff --git a/replace-images-tags.sh b/replace-images-tags.sh deleted file mode 100644 index 8ce75e211..000000000 --- a/replace-images-tags.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2019 Red Hat, Inc. -# This program and the accompanying materials are made -# available under the terms of the Eclipse Public License 2.0 -# which is available at https://www.eclipse.org/legal/epl-2.0/ -# -# SPDX-License-Identifier: EPL-2.0 -# -# Contributors: -# Red Hat, Inc. - initial API and implementation -# -# Updates images into: -# - deploy/operator.yaml -# Usage: -# ./release-operator-code.sh - -set -e - -function init() { - BASE_DIR=$(cd "$(dirname "$0")"; pwd) - RELEASE_TAG="$1" - CHE_RELEASE_BRANCH="$2" -} - -function replaceImageTag() { - echo "${1}" | sed -e "s/\(.*:\).*/\1${2}/" -} - -replaceImagesTags() { - OPERATOR_YAML="${BASE_DIR}"/deploy/operator.yaml - - lastDefaultCheServerImage=$(yq -r ".spec.template.spec.containers[] | select(.name == \"che-operator\") | .env[] | select(.name == \"RELATED_IMAGE_che_server\") | .value" "${OPERATOR_YAML}") - lastDefaultKeycloakImage=$(yq -r ".spec.template.spec.containers[] | select(.name == \"che-operator\") | .env[] | select(.name == \"RELATED_IMAGE_keycloak\") | .value" "${OPERATOR_YAML}") - lastDefaultPluginRegistryImage=$(yq -r ".spec.template.spec.containers[] | select(.name == \"che-operator\") | .env[] | select(.name == \"RELATED_IMAGE_plugin_registry\") | .value" "${OPERATOR_YAML}") - lastDefaultDevfileRegistryImage=$(yq -r ".spec.template.spec.containers[] | select(.name == \"che-operator\") | .env[] | select(.name == \"RELATED_IMAGE_devfile_registry\") | .value" "${OPERATOR_YAML}") - - CHE_SERVER_IMAGE_REALEASE=$(replaceImageTag "${lastDefaultCheServerImage}" "${RELEASE_TAG}") - KEYCLOAK_IMAGE_RELEASE=$(replaceImageTag "${lastDefaultKeycloakImage}" "${RELEASE_TAG}") - PLUGIN_REGISTRY_IMAGE_RELEASE=$(replaceImageTag "${lastDefaultPluginRegistryImage}" "${RELEASE_TAG}") - DEVFILE_REGISTRY_IMAGE_RELEASE=$(replaceImageTag "${lastDefaultDevfileRegistryImage}" "${RELEASE_TAG}") - - NEW_OPERATOR_YAML="${OPERATOR_YAML}.new" - # copy licence header - eval head -10 "${OPERATOR_YAML}" > ${NEW_OPERATOR_YAML} - - cat "${OPERATOR_YAML}" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\") | .image ) = \"quay.io/eclipse/che-operator:${RELEASE_TAG}\"" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"CHE_VERSION\") | .value ) = \"${RELEASE_TAG}\"" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_che_server\") | .value ) = \"${CHE_SERVER_IMAGE_REALEASE}\"" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_keycloak\") | .value ) = \"${KEYCLOAK_IMAGE_RELEASE}\"" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_plugin_registry\") | .value ) = \"${PLUGIN_REGISTRY_IMAGE_RELEASE}\"" | \ - yq -ryY "( .spec.template.spec.containers[] | select(.name == \"che-operator\").env[] | select(.name == \"RELATED_IMAGE_devfile_registry\") | .value ) = \"${DEVFILE_REGISTRY_IMAGE_RELEASE}\"" \ - >> "${NEW_OPERATOR_YAML}" - mv "${NEW_OPERATOR_YAML}" "${OPERATOR_YAML}" -} - -init "$@" -replaceImagesTags "$@"