Add fields for configuring project clone container to CheCluster CRD (#1687)
* Update devworkspace-operator dependency version to v0.21.0
Update devworkspace-operator dependency to v0.21.0 and update vendor dir
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
* Add project clone container config field to CheCluster CR
Add field .spec.devEnvironments.projectCloneContainer to allow
configuring image, env, resources, and pull policy for the project clone
container.
This change reuses the existing Container struct for storing this
config, which means that
* The name field is ignored (it appears to be a discriminator for the
Deployment struct's containers[] field
* Defaults are handled differently:
* Default imagePullPolicy is the general pull policy for DWO, with
default value "Always" (instead of depending on tag as documented)
* Resource requirements set to "0" are interpreted as "do not set this
field"
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
* Add reconcile step that syncs CheCluster project clone to DevWorkspace
Sync the field CheCluster.devEnvironments.projectCloneConfig to the
DevWorkspaceOperatorConfig owned by the operator.
Update tests to cover new functionality.
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
---------
Signed-off-by: Angel Misevski <amisevsk@redhat.com>
pull/1692/head
parent
be2afadd93
commit
02ce7749f0
|
|
@ -448,7 +448,7 @@
|
|||
| [golang.org/x/mobile@d3739f865fa66d07c1f506505c18aac71a8ead6e](https://cs.opensource.google/go) | BSD-3-Clause | N/A |
|
||||
| [github.com/devfile/api/v2@0d163445376d4d28898f3fbac4f2ff62863b944b](https://github.com/devfile/api.git) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/git/github/devfile/api/0d163445376d4d28898f3fbac4f2ff62863b944b) |
|
||||
| [github.com/che-incubator/kubernetes-image-puller-operator@0128446f5af78587c0427a35d693bbb8d24036bc](https://github.com/che-incubator/kubernetes-image-puller-operator.git) | EPL-2.0 | todo |
|
||||
| [github.com/devfile/devworkspace-operator@v0.20.0](https://github.com/devfile/devworkspace-operator.git) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/git/github/devfile/devworkspace-operator/ef761d812e029d094d2e9936d11ce4a3f6b8efd3) |
|
||||
| [github.com/devfile/devworkspace-operator@v0.21.0](https://github.com/devfile/devworkspace-operator.git) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/git/github/devfile/devworkspace-operator/21edf4373322c228ed54a5d4747b0451435a8f08) |
|
||||
| [github.com/gophercloud/gophercloud@v0.1.0](https://github.com/gophercloud/gophercloud) | Apache-2.0 | [clearlydefined](https://clearlydefined.io/definitions/go/golang/github.com%2Fgophercloud/gophercloud/v0.1.0) |
|
||||
| [gopkg.in/imdario/mergo.v0@v0.3.7](https://github.com/imdario/mergo/) | BSD-3-Clause | [clearlydefined](https://clearlydefined.io/definitions/go/golang/github.com%2Fimdario/mergo/v0.3.7) |
|
||||
| [github.com/mikefarah/yq/v2@v2.4.1](https://github.com/mikefarah/yq) | MIT | [clearlydefined](https://clearlydefined.io/definitions/git/github/mikefarah/yq/b8b2c9de6189471c0cdbd459b5b0b49a57844bd4) |
|
||||
|
|
|
|||
|
|
@ -78,6 +78,9 @@ type CheClusterDevEnvironments struct {
|
|||
// GatewayContainer configuration.
|
||||
// +optional
|
||||
GatewayContainer *Container `json:"gatewayContainer,omitempty"`
|
||||
// Project clone container configuration.
|
||||
// +optional
|
||||
ProjectCloneContainer *Container `json:"projectCloneContainer,omitempty"`
|
||||
// Workspaces persistent storage.
|
||||
// +optional
|
||||
// +kubebuilder:default:={pvcStrategy: per-user}
|
||||
|
|
@ -779,7 +782,7 @@ type CheCluster struct {
|
|||
Status CheClusterStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
// +kubebuilder:object:root=true
|
||||
// The CheClusterList contains a list of CheClusters.
|
||||
type CheClusterList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
|
|
|
|||
|
|
@ -152,6 +152,11 @@ func (in *CheClusterDevEnvironments) DeepCopyInto(out *CheClusterDevEnvironments
|
|||
*out = new(Container)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ProjectCloneContainer != nil {
|
||||
in, out := &in.ProjectCloneContainer, &out.ProjectCloneContainer
|
||||
*out = new(Container)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
in.Storage.DeepCopyInto(&out.Storage)
|
||||
if in.DefaultPlugins != nil {
|
||||
in, out := &in.DefaultPlugins, &out.DefaultPlugins
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ metadata:
|
|||
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
|
||||
repository: https://github.com/eclipse-che/che-operator
|
||||
support: Eclipse Foundation
|
||||
name: eclipse-che.v7.68.0-794.next
|
||||
name: eclipse-che.v7.68.0-795.next
|
||||
namespace: placeholder
|
||||
spec:
|
||||
apiservicedefinitions: {}
|
||||
|
|
@ -1235,7 +1235,7 @@ spec:
|
|||
minKubeVersion: 1.19.0
|
||||
provider:
|
||||
name: Eclipse Foundation
|
||||
version: 7.68.0-794.next
|
||||
version: 7.68.0-795.next
|
||||
webhookdefinitions:
|
||||
- admissionReviewVersions:
|
||||
- v1
|
||||
|
|
|
|||
|
|
@ -7001,6 +7001,198 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the
|
||||
container.
|
||||
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 previously 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.
|
||||
Double $$ are reduced to a single $, which allows
|
||||
for escaping the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)"
|
||||
will produce the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty
|
||||
to use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute
|
||||
resources allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If
|
||||
the value is not specified, then the default value
|
||||
is set depending on the component. If value is
|
||||
`0`, then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB =
|
||||
500 * 1024 * 1024 * 1024) If the value is not
|
||||
specified, then the default value is set depending
|
||||
on the component. If value is `0`, then no value
|
||||
is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute
|
||||
resources required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If
|
||||
the value is not specified, then the default value
|
||||
is set depending on the component. If value is
|
||||
`0`, then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB =
|
||||
500 * 1024 * 1024 * 1024) If the value is not
|
||||
specified, then the default value is set depending
|
||||
on the component. If value is `0`, then no value
|
||||
is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -6804,6 +6804,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -6823,6 +6823,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -6818,6 +6818,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -6823,6 +6823,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -6818,6 +6818,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -5,7 +5,7 @@ go 1.18
|
|||
require (
|
||||
github.com/che-incubator/kubernetes-image-puller-operator v0.0.0-20210929175054-0128446f5af7
|
||||
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd
|
||||
github.com/devfile/devworkspace-operator v0.20.0
|
||||
github.com/devfile/devworkspace-operator v0.21.0
|
||||
github.com/go-logr/logr v1.2.3
|
||||
github.com/golang/mock v1.5.0
|
||||
github.com/google/go-cmp v0.5.9
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -102,8 +102,8 @@ github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC
|
|||
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
|
||||
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd h1:HpGR728CfB6BB9ZuFtQb0UeTIYNFgpuGsuoMOJNMUTM=
|
||||
github.com/devfile/api/v2 v2.2.1-alpha.0.20230413012049-a6c32fca0dbd/go.mod h1:qp8jcw12y1JdCsxjK/7LJ7uWaJOxcY1s2LUk5PhbkbM=
|
||||
github.com/devfile/devworkspace-operator v0.20.0 h1:xm8+vCzVGf1D7AV05d4liRijIzWxnNwuV1Z976uzIOU=
|
||||
github.com/devfile/devworkspace-operator v0.20.0/go.mod h1:LTraBqSugk9bR/ZKj3HAry+pnAdYOfwEYCl/FkuIjfI=
|
||||
github.com/devfile/devworkspace-operator v0.21.0 h1:AiN2HEBpBkYoOcKClFZsOut46zKhsMIlHwmjI+OB2Oc=
|
||||
github.com/devfile/devworkspace-operator v0.21.0/go.mod h1:42cQKSbE+Zdqez8X5IqlEfdeeA0a/LkOTe2kkekJX6c=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dhui/dktest v0.3.2/go.mod h1:l1/ib23a/CmxAe7yixtrYPc8Iy90Zy2udyaHINM5p58=
|
||||
github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492 h1:FwssHbCDJD025h+BchanCwE1Q8fyMgqDr2mOQAWOLGw=
|
||||
|
|
|
|||
|
|
@ -6818,6 +6818,194 @@ spec:
|
|||
description: Pod scheduler for the workspace pods. If not specified,
|
||||
the pod scheduler is set to the default scheduler on the cluster.
|
||||
type: string
|
||||
projectCloneContainer:
|
||||
description: Project clone container configuration.
|
||||
properties:
|
||||
env:
|
||||
description: List of environment variables to set in the container.
|
||||
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 previously 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. Double $$ are
|
||||
reduced to a single $, which allows for escaping the
|
||||
$(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce
|
||||
the string literal "$(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[''<KEY>'']`,
|
||||
`metadata.annotations[''<KEY>'']`, 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
|
||||
image:
|
||||
description: Container image. Omit it or leave it empty to
|
||||
use the default container image provided by the Operator.
|
||||
type: string
|
||||
imagePullPolicy:
|
||||
description: Image pull policy. Default value is `Always`
|
||||
for `nightly`, `next` or `latest` images, and `IfNotPresent`
|
||||
in other cases.
|
||||
enum:
|
||||
- Always
|
||||
- IfNotPresent
|
||||
- Never
|
||||
type: string
|
||||
name:
|
||||
description: Container name.
|
||||
type: string
|
||||
resources:
|
||||
description: Compute resources required by this container.
|
||||
properties:
|
||||
limits:
|
||||
description: Describes the maximum amount of compute resources
|
||||
allowed.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
request:
|
||||
description: Describes the minimum amount of compute resources
|
||||
required.
|
||||
properties:
|
||||
cpu:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: CPU, in cores. (500m = .5 cores) If the
|
||||
value is not specified, then the default value is
|
||||
set depending on the component. If value is `0`,
|
||||
then no value is set for the component.
|
||||
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
|
||||
x-kubernetes-int-or-string: true
|
||||
memory:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Memory, in bytes. (500Gi = 500GiB = 500
|
||||
* 1024 * 1024 * 1024) If the value is not specified,
|
||||
then the default value is set depending on the component.
|
||||
If value is `0`, then no value is set for the component.
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
secondsOfInactivityBeforeIdling:
|
||||
default: 1800
|
||||
description: Idle timeout for workspaces in seconds. This timeout
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package devworkspaceconfig
|
||||
|
||||
import (
|
||||
|
|
@ -21,6 +22,7 @@ import (
|
|||
"github.com/eclipse-che/che-operator/pkg/common/utils"
|
||||
"github.com/eclipse-che/che-operator/pkg/deploy"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/utils/pointer"
|
||||
|
|
@ -84,14 +86,14 @@ func updateWorkspaceConfig(cheCluster *chev2.CheCluster, operatorConfig *control
|
|||
return err
|
||||
}
|
||||
|
||||
if err := updateWorkspaceServiceAccountConfig(devEnvironments, operatorConfig.Workspace); err != nil {
|
||||
return err
|
||||
}
|
||||
updateWorkspaceServiceAccountConfig(devEnvironments, operatorConfig.Workspace)
|
||||
|
||||
if err := updateWorkspacePodSchedulerNameConfig(devEnvironments, operatorConfig.Workspace); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updateProjectCloneConfig(devEnvironments, operatorConfig.Workspace)
|
||||
|
||||
operatorConfig.Workspace.ContainerSecurityContext = nil
|
||||
if cheCluster.IsContainerBuildCapabilitiesEnabled() {
|
||||
operatorConfig.Workspace.ContainerSecurityContext = constants.DefaultWorkspaceContainerSecurityContext.DeepCopy()
|
||||
|
|
@ -146,19 +148,63 @@ func updateWorkspaceStorageConfig(devEnvironments *chev2.CheClusterDevEnvironmen
|
|||
return nil
|
||||
}
|
||||
|
||||
func updateWorkspaceServiceAccountConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) error {
|
||||
isNamespaceAutoProvisioned := pointer.BoolPtrDerefOr(devEnvironments.DefaultNamespace.AutoProvision, constants.DefaultAutoProvision)
|
||||
func updateWorkspaceServiceAccountConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) {
|
||||
isNamespaceAutoProvisioned := pointer.BoolDeref(devEnvironments.DefaultNamespace.AutoProvision, constants.DefaultAutoProvision)
|
||||
|
||||
workspaceConfig.ServiceAccount = &controllerv1alpha1.ServiceAccountConfig{
|
||||
ServiceAccountName: devEnvironments.ServiceAccount,
|
||||
ServiceAccountTokens: devEnvironments.ServiceAccountTokens,
|
||||
// If user's Namespace is not auto provisioned (is pre-created by admin), then ServiceAccount must be pre-created as well
|
||||
DisableCreation: pointer.BoolPtr(!isNamespaceAutoProvisioned && devEnvironments.ServiceAccount != ""),
|
||||
DisableCreation: pointer.Bool(!isNamespaceAutoProvisioned && devEnvironments.ServiceAccount != ""),
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateWorkspacePodSchedulerNameConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) error {
|
||||
workspaceConfig.SchedulerName = devEnvironments.PodSchedulerName
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateProjectCloneConfig(devEnvironments *chev2.CheClusterDevEnvironments, workspaceConfig *controllerv1alpha1.WorkspaceConfig) {
|
||||
if devEnvironments.ProjectCloneContainer == nil {
|
||||
return
|
||||
}
|
||||
if workspaceConfig.ProjectCloneConfig == nil {
|
||||
workspaceConfig.ProjectCloneConfig = &controllerv1alpha1.ProjectCloneConfig{}
|
||||
}
|
||||
container := devEnvironments.ProjectCloneContainer
|
||||
|
||||
workspaceConfig.ProjectCloneConfig.Image = container.Image
|
||||
workspaceConfig.ProjectCloneConfig.ImagePullPolicy = container.ImagePullPolicy
|
||||
workspaceConfig.ProjectCloneConfig.Env = container.Env
|
||||
workspaceConfig.ProjectCloneConfig.Resources = cheResourcesToCoreV1Resources(container.Resources)
|
||||
}
|
||||
|
||||
// cheResourcesToCoreV1Resources converts a Che resources struct to the usual Kubernetes object by directly copying fields.
|
||||
// It does not set any default values or include logic for removing requests/limits that are set to "0" as it is intended
|
||||
// to prepare resources for the DevWorkspace Operator, which has its own defaults and handling of "0" values.
|
||||
func cheResourcesToCoreV1Resources(resources *chev2.ResourceRequirements) *corev1.ResourceRequirements {
|
||||
if resources == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := &corev1.ResourceRequirements{}
|
||||
if resources.Limits != nil {
|
||||
result.Limits = corev1.ResourceList{}
|
||||
if resources.Limits.Memory != nil {
|
||||
result.Limits[corev1.ResourceMemory] = *resources.Limits.Memory
|
||||
}
|
||||
if resources.Limits.Cpu != nil {
|
||||
result.Limits[corev1.ResourceCPU] = *resources.Limits.Cpu
|
||||
}
|
||||
}
|
||||
if resources.Requests != nil {
|
||||
result.Requests = corev1.ResourceList{}
|
||||
if resources.Requests.Memory != nil {
|
||||
result.Requests[corev1.ResourceMemory] = *resources.Requests.Memory
|
||||
}
|
||||
if resources.Requests.Cpu != nil {
|
||||
result.Requests[corev1.ResourceCPU] = *resources.Requests.Cpu
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,30 +9,28 @@
|
|||
// Contributors:
|
||||
// Red Hat, Inc. - initial API and implementation
|
||||
//
|
||||
|
||||
package devworkspaceconfig
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"context"
|
||||
|
||||
controllerv1alpha1 "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
|
||||
"github.com/devfile/devworkspace-operator/pkg/infrastructure"
|
||||
chev2 "github.com/eclipse-che/che-operator/api/v2"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/constants"
|
||||
"github.com/eclipse-che/che-operator/pkg/common/test"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
||||
|
|
@ -52,6 +50,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
|
||||
var quantity15Gi = resource.MustParse("15Gi")
|
||||
var quantity10Gi = resource.MustParse("10Gi")
|
||||
var quantity1CPU = resource.MustParse("1000m")
|
||||
var quantity500mCPU = resource.MustParse("500m")
|
||||
|
||||
var expectedErrorTestCases = []errorTestCase{
|
||||
{
|
||||
|
|
@ -87,7 +87,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -102,7 +102,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.EphemeralPVCStorageStrategy,
|
||||
PerUserStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -128,7 +128,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerUserPVCStorageStrategy,
|
||||
PerUserStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -140,7 +140,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
},
|
||||
|
|
@ -154,7 +154,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerUserPVCStorageStrategy,
|
||||
PerUserStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -167,7 +167,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity15Gi,
|
||||
},
|
||||
|
|
@ -184,7 +184,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerWorkspacePVCStorageStrategy,
|
||||
PerWorkspaceStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -197,7 +197,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
PerWorkspace: &quantity15Gi,
|
||||
},
|
||||
|
|
@ -214,7 +214,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerWorkspacePVCStorageStrategy,
|
||||
PerWorkspaceStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -237,7 +237,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
PerWorkspace: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -247,7 +247,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
PerWorkspace: &quantity15Gi,
|
||||
},
|
||||
|
|
@ -264,7 +264,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerUserPVCStorageStrategy,
|
||||
PerUserStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -287,7 +287,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -297,7 +297,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity15Gi,
|
||||
},
|
||||
|
|
@ -314,7 +314,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
Storage: chev2.WorkspaceStorage{
|
||||
PvcStrategy: constants.PerUserPVCStorageStrategy,
|
||||
PerUserStrategyPvcConfig: &chev2.PVC{
|
||||
|
|
@ -351,7 +351,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ImagePullPolicy: "Always",
|
||||
StorageClassName: pointer.StringPtr("test-storage"),
|
||||
StorageClassName: pointer.String("test-storage"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity15Gi,
|
||||
},
|
||||
|
|
@ -368,7 +368,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -387,7 +387,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(false),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -400,7 +400,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
"SETUID",
|
||||
},
|
||||
},
|
||||
AllowPrivilegeEscalation: pointer.BoolPtr(true),
|
||||
AllowPrivilegeEscalation: pointer.Bool(true),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -415,7 +415,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(false),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -431,7 +431,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -441,7 +441,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -452,7 +452,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
"SETUID",
|
||||
},
|
||||
},
|
||||
AllowPrivilegeEscalation: pointer.BoolPtr(true),
|
||||
AllowPrivilegeEscalation: pointer.Bool(true),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -467,7 +467,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -483,7 +483,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -495,7 +495,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -512,8 +512,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
StartTimeoutSeconds: pointer.Int32Ptr(600),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
StartTimeoutSeconds: pointer.Int32(600),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -533,8 +533,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
StartTimeoutSeconds: pointer.Int32Ptr(600),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
StartTimeoutSeconds: pointer.Int32(600),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -550,7 +550,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -560,7 +560,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -578,8 +578,8 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
StartTimeoutSeconds: pointer.Int32Ptr(420),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
StartTimeoutSeconds: pointer.Int32(420),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -595,7 +595,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -606,7 +606,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -624,7 +624,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.BoolPtr(true),
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -640,7 +640,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -651,7 +651,7 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.StringPtr("default-storage-class"),
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
|
|
@ -659,6 +659,87 @@ func TestReconcileDevWorkspaceConfigPerUserStorage(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Configures ProjectCloneConfig in DevWorkspaceOperatorConfig",
|
||||
cheCluster: &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "eclipse-che",
|
||||
Name: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DisableContainerBuildCapabilities: pointer.Bool(true),
|
||||
ProjectCloneContainer: &chev2.Container{
|
||||
Name: "project-clone",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &chev2.ResourceRequirements{
|
||||
Requests: &chev2.ResourceList{
|
||||
Memory: &quantity10Gi,
|
||||
Cpu: &quantity500mCPU,
|
||||
},
|
||||
Limits: &chev2.ResourceList{
|
||||
Memory: &quantity15Gi,
|
||||
Cpu: &quantity1CPU,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
existedObjects: []runtime.Object{
|
||||
&controllerv1alpha1.DevWorkspaceOperatorConfig{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: devWorkspaceConfigName,
|
||||
Namespace: "eclipse-che",
|
||||
},
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "DevWorkspaceOperatorConfig",
|
||||
APIVersion: controllerv1alpha1.GroupVersion.String(),
|
||||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
ProgressTimeout: "1h30m",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
StorageClassName: pointer.String("default-storage-class"),
|
||||
DefaultStorageSize: &controllerv1alpha1.StorageSizes{
|
||||
Common: &quantity10Gi,
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
ProjectCloneConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: quantity10Gi,
|
||||
corev1.ResourceCPU: quantity500mCPU,
|
||||
},
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: quantity15Gi,
|
||||
corev1.ResourceCPU: quantity1CPU,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
|
|
@ -717,7 +798,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{
|
||||
ServiceAccountName: "service-account",
|
||||
DisableCreation: pointer.BoolPtr(false),
|
||||
DisableCreation: pointer.Bool(false),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -733,7 +814,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DefaultNamespace: chev2.DefaultNamespace{
|
||||
AutoProvision: pointer.BoolPtr(false),
|
||||
AutoProvision: pointer.Bool(false),
|
||||
},
|
||||
ServiceAccount: "service-account",
|
||||
},
|
||||
|
|
@ -743,7 +824,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{
|
||||
ServiceAccountName: "service-account",
|
||||
DisableCreation: pointer.BoolPtr(true),
|
||||
DisableCreation: pointer.Bool(true),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -763,7 +844,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{
|
||||
DisableCreation: pointer.BoolPtr(false),
|
||||
DisableCreation: pointer.Bool(false),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -779,7 +860,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
DefaultNamespace: chev2.DefaultNamespace{
|
||||
AutoProvision: pointer.BoolPtr(false),
|
||||
AutoProvision: pointer.Bool(false),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -787,7 +868,7 @@ func TestReconcileServiceAccountConfig(t *testing.T) {
|
|||
expectedOperatorConfig: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ServiceAccount: &controllerv1alpha1.ServiceAccountConfig{
|
||||
DisableCreation: pointer.BoolPtr(false),
|
||||
DisableCreation: pointer.Bool(false),
|
||||
},
|
||||
DeploymentStrategy: "Recreate",
|
||||
},
|
||||
|
|
@ -1328,3 +1409,194 @@ func TestReconcileDevWorkspaceConfigDeploymentStrategy(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileDevWorkspaceProjectCloneCOnfig(t *testing.T) {
|
||||
const testNamespace = "eclipse-che"
|
||||
testMemLimit := resource.MustParse("2Gi")
|
||||
testCpuLimit := resource.MustParse("1000m")
|
||||
testMemRequest := resource.MustParse("1Gi")
|
||||
testCpuRequest := resource.MustParse("500m")
|
||||
|
||||
type testCase struct {
|
||||
name string
|
||||
cheProjectCloneConfig *chev2.Container
|
||||
expectedDevWorkspaceConfig *controllerv1alpha1.ProjectCloneConfig
|
||||
existingDevWorkspaceConfig *controllerv1alpha1.ProjectCloneConfig
|
||||
}
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
name: "Syncs Che project clone config to DevWorkspaceOperatorConfig",
|
||||
cheProjectCloneConfig: &chev2.Container{
|
||||
Name: "project-clone",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &chev2.ResourceRequirements{
|
||||
Limits: &chev2.ResourceList{
|
||||
Memory: &testMemLimit,
|
||||
Cpu: &testCpuLimit,
|
||||
},
|
||||
Requests: &chev2.ResourceList{
|
||||
Memory: &testMemRequest,
|
||||
Cpu: &testCpuRequest,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedDevWorkspaceConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: testMemLimit,
|
||||
corev1.ResourceCPU: testCpuLimit,
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: testMemRequest,
|
||||
corev1.ResourceCPU: testCpuRequest,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Updates existing DevWorkspaceOperatorConfig with new Che project clone config",
|
||||
cheProjectCloneConfig: &chev2.Container{
|
||||
Name: "project-clone",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &chev2.ResourceRequirements{
|
||||
Limits: &chev2.ResourceList{
|
||||
Memory: &testMemLimit,
|
||||
Cpu: &testCpuLimit,
|
||||
},
|
||||
Requests: &chev2.ResourceList{
|
||||
Memory: &testMemRequest,
|
||||
Cpu: &testCpuRequest,
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedDevWorkspaceConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "test-env-1", Value: "test-val-1"},
|
||||
{Name: "test-env-2", Value: "test-val-2"},
|
||||
},
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: testMemLimit,
|
||||
corev1.ResourceCPU: testCpuLimit,
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: testMemRequest,
|
||||
corev1.ResourceCPU: testCpuRequest,
|
||||
},
|
||||
},
|
||||
},
|
||||
existingDevWorkspaceConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "other image",
|
||||
ImagePullPolicy: "Always",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "other-env", Value: "other-val"},
|
||||
},
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("1234Mi"),
|
||||
corev1.ResourceCPU: resource.MustParse("1234m"),
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("1111Mi"),
|
||||
corev1.ResourceCPU: resource.MustParse("1111m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Removes fields from existing config when removed from CheCluster",
|
||||
cheProjectCloneConfig: &chev2.Container{
|
||||
Name: "",
|
||||
Image: "",
|
||||
ImagePullPolicy: "",
|
||||
Env: nil,
|
||||
Resources: nil,
|
||||
},
|
||||
expectedDevWorkspaceConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "",
|
||||
ImagePullPolicy: "",
|
||||
Env: nil,
|
||||
Resources: nil,
|
||||
},
|
||||
existingDevWorkspaceConfig: &controllerv1alpha1.ProjectCloneConfig{
|
||||
Image: "other image",
|
||||
ImagePullPolicy: "Always",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "other-env", Value: "other-val"},
|
||||
},
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("1234Mi"),
|
||||
corev1.ResourceCPU: resource.MustParse("1234m"),
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("1111Mi"),
|
||||
corev1.ResourceCPU: resource.MustParse("1111m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range tests {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
cheCluster := &chev2.CheCluster{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
Name: "eclipse-che",
|
||||
},
|
||||
Spec: chev2.CheClusterSpec{
|
||||
DevEnvironments: chev2.CheClusterDevEnvironments{
|
||||
ProjectCloneContainer: testCase.cheProjectCloneConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
existingDWOC := &controllerv1alpha1.DevWorkspaceOperatorConfig{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: devWorkspaceConfigName,
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Config: &controllerv1alpha1.OperatorConfiguration{
|
||||
Workspace: &controllerv1alpha1.WorkspaceConfig{
|
||||
ProjectCloneConfig: testCase.existingDevWorkspaceConfig,
|
||||
},
|
||||
},
|
||||
}
|
||||
runtimeDWOC := runtime.Object(existingDWOC)
|
||||
|
||||
deployContext := test.GetDeployContext(cheCluster, []runtime.Object{runtimeDWOC})
|
||||
infrastructure.InitializeForTesting(infrastructure.OpenShiftv4)
|
||||
|
||||
devWorkspaceConfigReconciler := NewDevWorkspaceConfigReconciler()
|
||||
_, _, err := devWorkspaceConfigReconciler.Reconcile(deployContext)
|
||||
assert.NoError(t, err)
|
||||
|
||||
dwoc := &controllerv1alpha1.DevWorkspaceOperatorConfig{}
|
||||
err = deployContext.ClusterAPI.Client.Get(context.TODO(), types.NamespacedName{Name: devWorkspaceConfigName, Namespace: testNamespace}, dwoc)
|
||||
assert.NoError(t, err)
|
||||
|
||||
diff := cmp.Diff(testCase.expectedDevWorkspaceConfig, dwoc.Config.Workspace.ProjectCloneConfig)
|
||||
assert.Empty(t, diff)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,76 +62,10 @@ type RoutingConfig struct {
|
|||
ProxyConfig *Proxy `json:"proxyConfig,omitempty"`
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
// HttpProxy is the URL of the proxy for HTTP requests, in the format http://USERNAME:PASSWORD@SERVER:PORT/
|
||||
HttpProxy string `json:"httpProxy,omitempty"`
|
||||
// HttpsProxy is the URL of the proxy for HTTPS requests, in the format http://USERNAME:PASSWORD@SERVER:PORT/
|
||||
HttpsProxy string `json:"httpsProxy,omitempty"`
|
||||
// NoProxy is a comma-separated list of hostnames and/or CIDRs for which the proxy should not be used. Ignored
|
||||
// when HttpProxy and HttpsProxy are unset
|
||||
NoProxy string `json:"noProxy,omitempty"`
|
||||
}
|
||||
|
||||
type StorageSizes struct {
|
||||
// The default Persistent Volume Claim size for the "common" storage class.
|
||||
// Note that the "async" storage class also uses the PVC size set for the "common" storage class.
|
||||
// If not specified, the "common" and "async" Persistent Volume Claim sizes are set to 10Gi
|
||||
Common *resource.Quantity `json:"common,omitempty"`
|
||||
// The default Persistent Volume Claim size for the "per-workspace" storage class.
|
||||
// If not specified, the "per-workspace" Persistent Volume Claim size is set to 5Gi
|
||||
PerWorkspace *resource.Quantity `json:"perWorkspace,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceAccountConfig struct {
|
||||
// ServiceAccountName defines a fixed name to be used for all DevWorkspaces. If set, the DevWorkspace
|
||||
// Operator will not generate a separate ServiceAccount for each DevWorkspace, and will instead create
|
||||
// a ServiceAccount with the specified name in each namespace where DevWorkspaces are created. If specified,
|
||||
// the created ServiceAccount will not be removed when DevWorkspaces are deleted and must be cleaned up manually.
|
||||
// +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||
// +kubebuilder:validation:MaxLength=63
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
// Disable creation of DevWorkspace ServiceAccounts by the DevWorkspace Operator. If set to true, the serviceAccountName
|
||||
// field must also be set. If ServiceAccount creation is disabled, it is assumed that the specified ServiceAccount already
|
||||
// exists in any namespace where a workspace is created. If a suitable ServiceAccount does not exist, starting DevWorkspaces
|
||||
// will fail.
|
||||
DisableCreation *bool `json:"disableCreation,omitempty"`
|
||||
// List of ServiceAccount tokens that will be mounted into workspace pods as projected volumes.
|
||||
ServiceAccountTokens []ServiceAccountToken `json:"serviceAccountTokens,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceAccountToken struct {
|
||||
// Identifiable name of the ServiceAccount token.
|
||||
// If multiple ServiceAccount tokens use the same mount path, a generic name will be used
|
||||
// for the projected volume instead.
|
||||
// +kubebuilder:validation:Required
|
||||
Name string `json:"name"`
|
||||
// Path within the workspace container at which the token should be mounted. Must
|
||||
// not contain ':'.
|
||||
// +kubebuilder:validation:Required
|
||||
MountPath string `json:"mountPath"`
|
||||
// Path is the path relative to the mount point of the file to project the
|
||||
// token into.
|
||||
// +kubebuilder:validation:Required
|
||||
Path string `json:"path"`
|
||||
// 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.
|
||||
// +kubebuilder:validation:Optional
|
||||
Audience string `json:"audience,omitempty"`
|
||||
// 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.
|
||||
// +kubebuilder:validation:Minimum=600
|
||||
// +kubebuilder:default:=3600
|
||||
// +kubebuilder:validation:Optional
|
||||
ExpirationSeconds int64 `json:"expirationSeconds,omitempty"`
|
||||
}
|
||||
|
||||
type WorkspaceConfig struct {
|
||||
// ProjectCloneConfig defines configuration related to the project clone init container
|
||||
// that is used to clone git projects into the DevWorkspace.
|
||||
ProjectCloneConfig *ProjectCloneConfig `json:"projectClone,omitempty"`
|
||||
// ImagePullPolicy defines the imagePullPolicy used for containers in a DevWorkspace
|
||||
// For additional information, see Kubernetes documentation for imagePullPolicy. If
|
||||
// not specified, the default value of "Always" is used.
|
||||
|
|
@ -203,6 +137,89 @@ type WorkspaceConfig struct {
|
|||
SchedulerName string `json:"schedulerName,omitempty"`
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
// HttpProxy is the URL of the proxy for HTTP requests, in the format http://USERNAME:PASSWORD@SERVER:PORT/
|
||||
HttpProxy string `json:"httpProxy,omitempty"`
|
||||
// HttpsProxy is the URL of the proxy for HTTPS requests, in the format http://USERNAME:PASSWORD@SERVER:PORT/
|
||||
HttpsProxy string `json:"httpsProxy,omitempty"`
|
||||
// NoProxy is a comma-separated list of hostnames and/or CIDRs for which the proxy should not be used. Ignored
|
||||
// when HttpProxy and HttpsProxy are unset
|
||||
NoProxy string `json:"noProxy,omitempty"`
|
||||
}
|
||||
|
||||
type StorageSizes struct {
|
||||
// The default Persistent Volume Claim size for the "common" storage class.
|
||||
// Note that the "async" storage class also uses the PVC size set for the "common" storage class.
|
||||
// If not specified, the "common" and "async" Persistent Volume Claim sizes are set to 10Gi
|
||||
Common *resource.Quantity `json:"common,omitempty"`
|
||||
// The default Persistent Volume Claim size for the "per-workspace" storage class.
|
||||
// If not specified, the "per-workspace" Persistent Volume Claim size is set to 5Gi
|
||||
PerWorkspace *resource.Quantity `json:"perWorkspace,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceAccountConfig struct {
|
||||
// ServiceAccountName defines a fixed name to be used for all DevWorkspaces. If set, the DevWorkspace
|
||||
// Operator will not generate a separate ServiceAccount for each DevWorkspace, and will instead create
|
||||
// a ServiceAccount with the specified name in each namespace where DevWorkspaces are created. If specified,
|
||||
// the created ServiceAccount will not be removed when DevWorkspaces are deleted and must be cleaned up manually.
|
||||
// +kubebuilder:validation:Pattern=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
|
||||
// +kubebuilder:validation:MaxLength=63
|
||||
ServiceAccountName string `json:"serviceAccountName,omitempty"`
|
||||
// Disable creation of DevWorkspace ServiceAccounts by the DevWorkspace Operator. If set to true, the serviceAccountName
|
||||
// field must also be set. If ServiceAccount creation is disabled, it is assumed that the specified ServiceAccount already
|
||||
// exists in any namespace where a workspace is created. If a suitable ServiceAccount does not exist, starting DevWorkspaces
|
||||
// will fail.
|
||||
DisableCreation *bool `json:"disableCreation,omitempty"`
|
||||
// List of ServiceAccount tokens that will be mounted into workspace pods as projected volumes.
|
||||
ServiceAccountTokens []ServiceAccountToken `json:"serviceAccountTokens,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceAccountToken struct {
|
||||
// Identifiable name of the ServiceAccount token.
|
||||
// If multiple ServiceAccount tokens use the same mount path, a generic name will be used
|
||||
// for the projected volume instead.
|
||||
// +kubebuilder:validation:Required
|
||||
Name string `json:"name"`
|
||||
// Path within the workspace container at which the token should be mounted. Must
|
||||
// not contain ':'.
|
||||
// +kubebuilder:validation:Required
|
||||
MountPath string `json:"mountPath"`
|
||||
// Path is the path relative to the mount point of the file to project the
|
||||
// token into.
|
||||
// +kubebuilder:validation:Required
|
||||
Path string `json:"path"`
|
||||
// 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.
|
||||
// +kubebuilder:validation:Optional
|
||||
Audience string `json:"audience,omitempty"`
|
||||
// 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.
|
||||
// +kubebuilder:validation:Minimum=600
|
||||
// +kubebuilder:default:=3600
|
||||
// +kubebuilder:validation:Optional
|
||||
ExpirationSeconds int64 `json:"expirationSeconds,omitempty"`
|
||||
}
|
||||
|
||||
type ProjectCloneConfig struct {
|
||||
// Image is the container image to use for cloning projects
|
||||
Image string `json:"image,omitempty"`
|
||||
// ImagePullPolicy configures the imagePullPolicy for the project clone container.
|
||||
// If undefined, the general setting .config.workspace.imagePullPolicy is used instead.
|
||||
ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"`
|
||||
// Resources defines the resource (cpu, memory) limits and requests for the project
|
||||
// clone container. To explicitly not specify a limit or request, define the resource
|
||||
// quantity as zero ('0')
|
||||
Resources *corev1.ResourceRequirements `json:"resources,omitempty"`
|
||||
// Env allows defining additional environment variables for the project clone container.
|
||||
Env []corev1.EnvVar `json:"env,omitempty"`
|
||||
}
|
||||
|
||||
// DevWorkspaceOperatorConfig is the Schema for the devworkspaceoperatorconfigs API
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:resource:path=devworkspaceoperatorconfigs,scope=Namespaced,shortName=dwoc
|
||||
|
|
|
|||
|
|
@ -444,6 +444,33 @@ func (in *PodAdditions) DeepCopy() *PodAdditions {
|
|||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProjectCloneConfig) DeepCopyInto(out *ProjectCloneConfig) {
|
||||
*out = *in
|
||||
if in.Resources != nil {
|
||||
in, out := &in.Resources, &out.Resources
|
||||
*out = new(v1.ResourceRequirements)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Env != nil {
|
||||
in, out := &in.Env, &out.Env
|
||||
*out = make([]v1.EnvVar, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProjectCloneConfig.
|
||||
func (in *ProjectCloneConfig) DeepCopy() *ProjectCloneConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProjectCloneConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Proxy) DeepCopyInto(out *Proxy) {
|
||||
*out = *in
|
||||
|
|
@ -547,6 +574,11 @@ func (in *StorageSizes) DeepCopy() *StorageSizes {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WorkspaceConfig) DeepCopyInto(out *WorkspaceConfig) {
|
||||
*out = *in
|
||||
if in.ProjectCloneConfig != nil {
|
||||
in, out := &in.ProjectCloneConfig, &out.ProjectCloneConfig
|
||||
*out = new(ProjectCloneConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ServiceAccount != nil {
|
||||
in, out := &in.ServiceAccount, &out.ServiceAccount
|
||||
*out = new(ServiceAccountConfig)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,18 @@ var defaultConfig = &v1alpha1.OperatorConfiguration{
|
|||
PodSecurityContext: nil,
|
||||
ContainerSecurityContext: &corev1.SecurityContext{},
|
||||
DefaultTemplate: nil,
|
||||
ProjectCloneConfig: &v1alpha1.ProjectCloneConfig{
|
||||
Resources: &corev1.ResourceRequirements{
|
||||
Limits: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("1Gi"),
|
||||
corev1.ResourceCPU: resource.MustParse("1000m"),
|
||||
},
|
||||
Requests: corev1.ResourceList{
|
||||
corev1.ResourceMemory: resource.MustParse("128Mi"),
|
||||
corev1.ResourceCPU: resource.MustParse("100m"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -334,6 +334,29 @@ func mergeConfig(from, to *controller.OperatorConfiguration) {
|
|||
if from.Workspace.SchedulerName != "" {
|
||||
to.Workspace.SchedulerName = from.Workspace.SchedulerName
|
||||
}
|
||||
if from.Workspace.ProjectCloneConfig != nil {
|
||||
if to.Workspace.ProjectCloneConfig == nil {
|
||||
to.Workspace.ProjectCloneConfig = &controller.ProjectCloneConfig{}
|
||||
}
|
||||
if from.Workspace.ProjectCloneConfig.Image != "" {
|
||||
to.Workspace.ProjectCloneConfig.Image = from.Workspace.ProjectCloneConfig.Image
|
||||
}
|
||||
if from.Workspace.ProjectCloneConfig.ImagePullPolicy != "" {
|
||||
to.Workspace.ProjectCloneConfig.ImagePullPolicy = from.Workspace.ProjectCloneConfig.ImagePullPolicy
|
||||
}
|
||||
if from.Workspace.ProjectCloneConfig.Resources != nil {
|
||||
if to.Workspace.ProjectCloneConfig.Resources == nil {
|
||||
to.Workspace.ProjectCloneConfig.Resources = &corev1.ResourceRequirements{}
|
||||
}
|
||||
to.Workspace.ProjectCloneConfig.Resources = mergeResources(from.Workspace.ProjectCloneConfig.Resources, to.Workspace.ProjectCloneConfig.Resources)
|
||||
}
|
||||
|
||||
// Overwrite env instead of trying to merge, don't want to bother merging lists when
|
||||
// the default is empty
|
||||
if from.Workspace.ProjectCloneConfig.Env != nil {
|
||||
to.Workspace.ProjectCloneConfig.Env = from.Workspace.ProjectCloneConfig.Env
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -385,6 +408,33 @@ func mergeContainerSecurityContext(base, patch *corev1.SecurityContext) *corev1.
|
|||
return patched
|
||||
}
|
||||
|
||||
func mergeResources(from, to *corev1.ResourceRequirements) *corev1.ResourceRequirements {
|
||||
result := to.DeepCopy()
|
||||
if from.Limits != nil {
|
||||
if result.Limits == nil {
|
||||
result.Limits = corev1.ResourceList{}
|
||||
}
|
||||
if cpu, ok := from.Limits[corev1.ResourceCPU]; ok {
|
||||
result.Limits[corev1.ResourceCPU] = cpu
|
||||
}
|
||||
if memory, ok := from.Limits[corev1.ResourceMemory]; ok {
|
||||
result.Limits[corev1.ResourceMemory] = memory
|
||||
}
|
||||
}
|
||||
if from.Requests != nil {
|
||||
if result.Requests == nil {
|
||||
result.Requests = corev1.ResourceList{}
|
||||
}
|
||||
if cpu, ok := from.Requests[corev1.ResourceCPU]; ok {
|
||||
result.Requests[corev1.ResourceCPU] = cpu
|
||||
}
|
||||
if memory, ok := from.Requests[corev1.ResourceMemory]; ok {
|
||||
result.Requests[corev1.ResourceMemory] = memory
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetCurrentConfigString(currConfig *controller.OperatorConfiguration) string {
|
||||
if currConfig == nil {
|
||||
return ""
|
||||
|
|
@ -462,6 +512,20 @@ func GetCurrentConfigString(currConfig *controller.OperatorConfiguration) string
|
|||
if workspace.SchedulerName != "" {
|
||||
config = append(config, fmt.Sprintf("workspace.schedulerName=%s", workspace.SchedulerName))
|
||||
}
|
||||
if workspace.ProjectCloneConfig != nil {
|
||||
if workspace.ProjectCloneConfig.Image != defaultConfig.Workspace.ProjectCloneConfig.Image {
|
||||
config = append(config, fmt.Sprintf("workspace.projectClone.image=%s", workspace.ProjectCloneConfig.Image))
|
||||
}
|
||||
if workspace.ProjectCloneConfig.ImagePullPolicy != defaultConfig.Workspace.ProjectCloneConfig.ImagePullPolicy {
|
||||
config = append(config, fmt.Sprintf("workspace.projectClone.imagePullPolicy=%s", workspace.ProjectCloneConfig.ImagePullPolicy))
|
||||
}
|
||||
if workspace.ProjectCloneConfig.Env != nil {
|
||||
config = append(config, "workspace.projectClone.env is set")
|
||||
}
|
||||
if !reflect.DeepEqual(workspace.ProjectCloneConfig.Resources, defaultConfig.Workspace.ProjectCloneConfig.Resources) {
|
||||
config = append(config, "workspace.projectClone.resources is set")
|
||||
}
|
||||
}
|
||||
}
|
||||
if currConfig.EnableExperimentalFeatures != nil && *currConfig.EnableExperimentalFeatures {
|
||||
config = append(config, "enableExperimentalFeatures=true")
|
||||
|
|
|
|||
|
|
@ -65,12 +65,6 @@ const (
|
|||
// PVCCleanupPodCPURequest is the cpu request used for PVC clean up pods
|
||||
PVCCleanupPodCPURequest = "5m"
|
||||
|
||||
// Resource limits/requests for project cloner init container
|
||||
ProjectCloneMemoryLimit = "1Gi"
|
||||
ProjectCloneMemoryRequest = "128Mi"
|
||||
ProjectCloneCPULimit = "1000m"
|
||||
ProjectCloneCPURequest = "100m"
|
||||
|
||||
// Constants describing storage classes supported by the controller
|
||||
|
||||
// CommonStorageClassType defines the 'common' storage policy, which is an alias of the 'per-user' storage policy, and operates in the same fashion as the 'per-user' storage policy.
|
||||
|
|
|
|||
|
|
@ -200,17 +200,19 @@ func printDiff(specObj, clusterObj crclient.Object, log logr.Logger) {
|
|||
diffOpts = podDiffOpts
|
||||
case *corev1.ConfigMap:
|
||||
diffOpts = configmapDiffOpts
|
||||
case *corev1.Secret:
|
||||
diffOpts = secretDiffOpts
|
||||
case *v1alpha1.DevWorkspaceRouting:
|
||||
diffOpts = routingDiffOpts
|
||||
case *networkingv1.Ingress:
|
||||
diffOpts = ingressDiffOpts
|
||||
case *routev1.Route:
|
||||
diffOpts = routeDiffOpts
|
||||
case *corev1.Secret:
|
||||
log.Info(fmt.Sprintf("Diff: secret %s data upated", specObj.GetName()))
|
||||
return
|
||||
default:
|
||||
diffOpts = nil
|
||||
}
|
||||
|
||||
log.Info(fmt.Sprintf("Diff: %s", cmp.Diff(specObj, clusterObj, diffOpts)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ github.com/davecgh/go-spew/spew
|
|||
github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2
|
||||
github.com/devfile/api/v2/pkg/attributes
|
||||
github.com/devfile/api/v2/pkg/devfile
|
||||
# github.com/devfile/devworkspace-operator v0.20.0
|
||||
# github.com/devfile/devworkspace-operator v0.21.0
|
||||
## explicit; go 1.18
|
||||
github.com/devfile/devworkspace-operator/apis/controller/v1alpha1
|
||||
github.com/devfile/devworkspace-operator/controllers/controller/devworkspacerouting
|
||||
|
|
|
|||
Loading…
Reference in New Issue