diff --git a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml index 2c0b8a2..27e49e0 100644 --- a/api/crds/manifests/openmcp.cloud_clusterproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_clusterproviders.yaml @@ -41,6 +41,27 @@ spec: spec: description: ClusterProviderSpec defines the desired state of ClusterProvider. properties: + env: + description: Env is a list of environment variables to set in the + containers of the init job and deployment of the provider. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name is the name of the environment variable. + minLength: 1 + type: string + value: + description: Value is the value of the environment variable. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map image: description: Image is the name of the image of a provider. minLength: 1 @@ -59,6 +80,14 @@ spec: - name type: object type: array + verbosity: + default: INFO + description: Verbosity is the verbosity level of the provider. + enum: + - DEBUG + - INFO + - ERROR + type: string required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_platformservices.yaml b/api/crds/manifests/openmcp.cloud_platformservices.yaml index 215d301..de1ba11 100644 --- a/api/crds/manifests/openmcp.cloud_platformservices.yaml +++ b/api/crds/manifests/openmcp.cloud_platformservices.yaml @@ -41,6 +41,27 @@ spec: spec: description: PlatformServiceSpec defines the desired state of PlatformService. properties: + env: + description: Env is a list of environment variables to set in the + containers of the init job and deployment of the provider. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name is the name of the environment variable. + minLength: 1 + type: string + value: + description: Value is the value of the environment variable. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map image: description: Image is the name of the image of a provider. minLength: 1 @@ -59,6 +80,14 @@ spec: - name type: object type: array + verbosity: + default: INFO + description: Verbosity is the verbosity level of the provider. + enum: + - DEBUG + - INFO + - ERROR + type: string required: - image type: object diff --git a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml index 60778c5..a4c92b1 100644 --- a/api/crds/manifests/openmcp.cloud_serviceproviders.yaml +++ b/api/crds/manifests/openmcp.cloud_serviceproviders.yaml @@ -41,6 +41,27 @@ spec: spec: description: ServiceProviderSpec defines the desired state of ServiceProvider. properties: + env: + description: Env is a list of environment variables to set in the + containers of the init job and deployment of the provider. + items: + description: EnvVar represents an environment variable present in + a Container. + properties: + name: + description: Name is the name of the environment variable. + minLength: 1 + type: string + value: + description: Value is the value of the environment variable. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map image: description: Image is the name of the image of a provider. minLength: 1 @@ -59,6 +80,14 @@ spec: - name type: object type: array + verbosity: + default: INFO + description: Verbosity is the verbosity level of the provider. + enum: + - DEBUG + - INFO + - ERROR + type: string required: - image type: object diff --git a/api/provider/v1alpha1/deployment_types.go b/api/provider/v1alpha1/deployment_types.go index 1f6491c..ee0ad59 100644 --- a/api/provider/v1alpha1/deployment_types.go +++ b/api/provider/v1alpha1/deployment_types.go @@ -32,6 +32,19 @@ type DeploymentSpec struct { // ImagePullSecrets are secrets in the same namespace. // They can be used to fetch provider images from private registries. ImagePullSecrets []ObjectReference `json:"imagePullSecrets,omitempty"` + + // Env is a list of environment variables to set in the containers of the init job and deployment of the provider. + // +optional + // +patchMergeKey=name + // +patchStrategy=merge + // +listType=map + // +listMapKey=name + Env []EnvVar `json:"env,omitempty" patchStrategy:"merge" patchMergeKey:"name"` + + // Verbosity is the verbosity level of the provider. + // +kubebuilder:validation:Enum=DEBUG;INFO;ERROR + // +kubebuilder:default=INFO + Verbosity string `json:"verbosity,omitempty"` } // DeploymentStatus defines the observed state of a provider. @@ -50,3 +63,13 @@ type ObjectReference struct { // +kubebuilder:validation:MinLength=1 Name string `json:"name"` } + +// EnvVar represents an environment variable present in a Container. +type EnvVar struct { + // Name is the name of the environment variable. + // +kubebuilder:validation:MinLength=1 + Name string `json:"name"` + // Value is the value of the environment variable. + // +optional + Value string `json:"value,omitempty"` +} diff --git a/api/provider/v1alpha1/zz_generated.deepcopy.go b/api/provider/v1alpha1/zz_generated.deepcopy.go index fdc8222..cab9f7f 100644 --- a/api/provider/v1alpha1/zz_generated.deepcopy.go +++ b/api/provider/v1alpha1/zz_generated.deepcopy.go @@ -108,6 +108,11 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { *out = make([]ObjectReference, len(*in)) copy(*out, *in) } + if in.Env != nil { + in, out := &in.Env, &out.Env + *out = make([]EnvVar, len(*in)) + copy(*out, *in) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. @@ -142,6 +147,21 @@ func (in *DeploymentStatus) DeepCopy() *DeploymentStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EnvVar) DeepCopyInto(out *EnvVar) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvVar. +func (in *EnvVar) DeepCopy() *EnvVar { + if in == nil { + return nil + } + out := new(EnvVar) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ObjectReference) DeepCopyInto(out *ObjectReference) { *out = *in diff --git a/docs/README.md b/docs/README.md index 998425d..01ec6c1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,6 +4,7 @@ ## Controller - [AccessRequest Controller](controller/accessrequest.md) +- [Deployment Controllers](controller/deployment.md) - [Cluster Scheduler](controller/scheduler.md) ## Resources diff --git a/docs/controller/deployment.md b/docs/controller/deployment.md new file mode 100644 index 0000000..96935ea --- /dev/null +++ b/docs/controller/deployment.md @@ -0,0 +1,51 @@ +# Deployment Controllers + +An OpenMCP landscape has three controllers (called _deployment controllers_) which are responsible for deploying other controllers (called _providers_): + +- the **ClusterProvider Controller** is responsible for deploying cluster providers. +- the **ServiceProvider Controller** is responsible for deploying service providers. +- the **PlatformService Controller** is responsible for deploying platform services. + +The deployments are specified in kubernetes resources of the kinds `ClusterProvider`, `ServiceProvider`, and `PlatformService` respectively. + +## Provider Image + +To be deployable, each provider must have an image available in a container registry. The image must have an executable as entrypoint. It will be used twice: to initialize the provider and to run it. For the initialization, a Job is started with the executable, and the following arguments are supplied: + +```shell +init +--environment +--verbosity +``` + +Once the initialization job has completed, a Deployment is created/updated with the same image and the following arguments: + +```shell +run +--environment +--verbosity +``` + +## Provider Resource + +The provider resources specify how to deploy the providers. They are of the kind `ClusterProvider`, `ServiceProvider`, or `PlatformService`. They are cluster-scoped, and have the following common structure: + +```yaml +apiVersion: openmcp.cloud/v1alpha1 +kind: +metadata: + name: +spec: + image: + imagePullSecrets: + - name: + env: + - name: + value: + verbosity: +``` + +- The `image` field specifies the container image to use for the init job and deployment of the provider. +- The `imagePullSecrets` field specifies a list of secrets that contain the credentials to pull the image from a registry. +- The `env` field specifies a list of name-value pairs that are passed as environment variables to the init job and deployment of the provider. +- The `verbosity` field specifies the logging level. Supported values are DEBUG, INFO, and ERROR. The default is INFO. diff --git a/internal/controllers/provider/install/deployment.go b/internal/controllers/provider/install/deployment.go index 7b4cfca..a8ccf58 100644 --- a/internal/controllers/provider/install/deployment.go +++ b/internal/controllers/provider/install/deployment.go @@ -67,7 +67,9 @@ func (m *deploymentMutator) Mutate(d *appsv1.Deployment) error { Args: []string{ "run", "--environment=" + m.values.Environment(), + "--verbosity=" + m.values.Verbosity(), }, + Env: m.values.EnvironmentVariables(), }, }, ImagePullSecrets: m.values.ImagePullSecrets(), diff --git a/internal/controllers/provider/install/job.go b/internal/controllers/provider/install/job.go index 179ddda..84e3a51 100644 --- a/internal/controllers/provider/install/job.go +++ b/internal/controllers/provider/install/job.go @@ -70,7 +70,9 @@ func (m *jobMutator) Mutate(j *v1.Job) error { Args: []string{ "init", "--environment=" + m.values.Environment(), + "--verbosity=" + m.values.Verbosity(), }, + Env: m.values.EnvironmentVariables(), }, }, ServiceAccountName: m.values.NamespacedResourceName(initPrefix), diff --git a/internal/controllers/provider/install/values.go b/internal/controllers/provider/install/values.go index bdfd10d..c8ea98e 100644 --- a/internal/controllers/provider/install/values.go +++ b/internal/controllers/provider/install/values.go @@ -100,3 +100,18 @@ func (v *Values) LabelsController() map[string]string { m["app.kubernetes.io/component"] = "controller" return m } + +func (v *Values) Verbosity() string { + return v.deploymentSpec.Verbosity +} + +func (v *Values) EnvironmentVariables() []corev1.EnvVar { + env := make([]corev1.EnvVar, len(v.deploymentSpec.Env)) + for i, e := range v.deploymentSpec.Env { + env[i] = corev1.EnvVar{ + Name: e.Name, + Value: e.Value, + } + } + return env +}