diff --git a/api/v1/runtimecomponent_types.go b/api/v1/runtimecomponent_types.go index 9c875478..0b9de330 100644 --- a/api/v1/runtimecomponent_types.go +++ b/api/v1/runtimecomponent_types.go @@ -56,112 +56,116 @@ type RuntimeComponentSpec struct { // +operator-sdk:csv:customresourcedefinitions:order=5,type=spec,displayName="Pull Secret",xDescriptors="urn:alm:descriptor:io.kubernetes:Secret" PullSecret *string `json:"pullSecret,omitempty"` + // List of Secrets to use to pull images from one or more specified repositories. It is not required if the cluster is configured with a global image pull secret. + // +operator-sdk:csv:customresourcedefinitions:order=6,type=spec,displayName="Pull Secrets" + PullSecrets []string `json:"pullSecrets,omitempty"` + // Deprecated. .spec.serviceAccount.name should be used instead. If both are specified, .spec.serviceAccount.name will override this. - // +operator-sdk:csv:customresourcedefinitions:order=6,type=spec,displayName="Service Account Name",xDescriptors="urn:alm:descriptor:com.tectonic.ui:hidden" + // +operator-sdk:csv:customresourcedefinitions:order=7,type=spec,displayName="Service Account Name",xDescriptors="urn:alm:descriptor:com.tectonic.ui:hidden" ServiceAccountName *string `json:"serviceAccountName,omitempty"` // The service account to use for deploying the application. A service account is automatically created if this is not specifed. - // +operator-sdk:csv:customresourcedefinitions:order=6,type=spec,displayName="Service Account" + // +operator-sdk:csv:customresourcedefinitions:order=8,type=spec,displayName="Service Account" ServiceAccount *RuntimeComponentServiceAccount `json:"serviceAccount,omitempty"` // Create Knative resources and use Knative serving. - // +operator-sdk:csv:customresourcedefinitions:order=7,type=spec,displayName="Create Knative Service",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + // +operator-sdk:csv:customresourcedefinitions:order=9,type=spec,displayName="Create Knative Service",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" CreateKnativeService *bool `json:"createKnativeService,omitempty"` // Expose the application externally via a Route, a Knative Route or an Ingress resource. - // +operator-sdk:csv:customresourcedefinitions:order=8,type=spec,displayName="Expose",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + // +operator-sdk:csv:customresourcedefinitions:order=10,type=spec,displayName="Expose",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" Expose *bool `json:"expose,omitempty"` // Enable management of TLS certificates. Defaults to true. - // +operator-sdk:csv:customresourcedefinitions:order=8,type=spec,displayName="Manage TLS",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + // +operator-sdk:csv:customresourcedefinitions:order=11,type=spec,displayName="Manage TLS",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" ManageTLS *bool `json:"manageTLS,omitempty"` // Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. - // +operator-sdk:csv:customresourcedefinitions:order=9,type=spec,displayName="Replicas",xDescriptors="urn:alm:descriptor:com.tectonic.ui:podCount" + // +operator-sdk:csv:customresourcedefinitions:order=12,type=spec,displayName="Replicas",xDescriptors="urn:alm:descriptor:com.tectonic.ui:podCount" Replicas *int32 `json:"replicas,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=10,type=spec,displayName="Auto Scaling" + // +operator-sdk:csv:customresourcedefinitions:order=13,type=spec,displayName="Auto Scaling" Autoscaling *RuntimeComponentAutoScaling `json:"autoscaling,omitempty"` // Resource requests and limits for the application container. - // +operator-sdk:csv:customresourcedefinitions:order=11,type=spec,displayName="Resource Requirements",xDescriptors="urn:alm:descriptor:com.tectonic.ui:resourceRequirements" + // +operator-sdk:csv:customresourcedefinitions:order=14,type=spec,displayName="Resource Requirements",xDescriptors="urn:alm:descriptor:com.tectonic.ui:resourceRequirements" Resources *corev1.ResourceRequirements `json:"resources,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=12,type=spec,displayName="Probes" + // +operator-sdk:csv:customresourcedefinitions:order=15,type=spec,displayName="Probes" Probes *RuntimeComponentProbes `json:"probes,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=13,type=spec,displayName="Deployment" + // +operator-sdk:csv:customresourcedefinitions:order=16,type=spec,displayName="Deployment" Deployment *RuntimeComponentDeployment `json:"deployment,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=14,type=spec,displayName="StatefulSet" + // +operator-sdk:csv:customresourcedefinitions:order=17,type=spec,displayName="StatefulSet" StatefulSet *RuntimeComponentStatefulSet `json:"statefulSet,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=15,type=spec,displayName="Service" + // +operator-sdk:csv:customresourcedefinitions:order=18,type=spec,displayName="Service" Service *RuntimeComponentService `json:"service,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=16,type=spec,displayName="Route" + // +operator-sdk:csv:customresourcedefinitions:order=19,type=spec,displayName="Route" Route *RuntimeComponentRoute `json:"route,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=16,type=spec,displayName="Network Policy" + // +operator-sdk:csv:customresourcedefinitions:order=20,type=spec,displayName="Network Policy" NetworkPolicy *RuntimeComponentNetworkPolicy `json:"networkPolicy,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=17,type=spec,displayName="Monitoring" + // +operator-sdk:csv:customresourcedefinitions:order=21,type=spec,displayName="Monitoring" Monitoring *RuntimeComponentMonitoring `json:"monitoring,omitempty"` // An array of environment variables for the application container. // +listType=map // +listMapKey=name - // +operator-sdk:csv:customresourcedefinitions:order=18,type=spec,displayName="Environment Variables" + // +operator-sdk:csv:customresourcedefinitions:order=22,type=spec,displayName="Environment Variables" Env []corev1.EnvVar `json:"env,omitempty"` // List of sources to populate environment variables in the application container. // +listType=atomic - // +operator-sdk:csv:customresourcedefinitions:order=19,type=spec,displayName="Environment Variables from Sources" + // +operator-sdk:csv:customresourcedefinitions:order=23,type=spec,displayName="Environment Variables from Sources" EnvFrom []corev1.EnvFromSource `json:"envFrom,omitempty"` // Represents a volume with data that is accessible to the application container. // +listType=map // +listMapKey=name - // +operator-sdk:csv:customresourcedefinitions:order=20,type=spec,displayName="Volumes" + // +operator-sdk:csv:customresourcedefinitions:order=24,type=spec,displayName="Volumes" Volumes []corev1.Volume `json:"volumes,omitempty"` // Represents where to mount the volumes into the application container. // +listType=atomic - // +operator-sdk:csv:customresourcedefinitions:order=21,type=spec,displayName="Volume Mounts" + // +operator-sdk:csv:customresourcedefinitions:order=25,type=spec,displayName="Volume Mounts" VolumeMounts []corev1.VolumeMount `json:"volumeMounts,omitempty"` // List of containers to run before other containers in a pod. // +listType=map // +listMapKey=name - // +operator-sdk:csv:customresourcedefinitions:order=22,type=spec,displayName="Init Containers" + // +operator-sdk:csv:customresourcedefinitions:order=26,type=spec,displayName="Init Containers" InitContainers []corev1.Container `json:"initContainers,omitempty"` // List of sidecar containers. These are additional containers to be added to the pods. // +listType=map // +listMapKey=name - // +operator-sdk:csv:customresourcedefinitions:order=23,type=spec,displayName="Sidecar Containers" + // +operator-sdk:csv:customresourcedefinitions:order=27,type=spec,displayName="Sidecar Containers" SidecarContainers []corev1.Container `json:"sidecarContainers,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=24,type=spec,displayName="Affinity" + // +operator-sdk:csv:customresourcedefinitions:order=28,type=spec,displayName="Affinity" Affinity *RuntimeComponentAffinity `json:"affinity,omitempty"` // Security context for the application container. - // +operator-sdk:csv:customresourcedefinitions:order=25,type=spec,displayName="Security Context" + // +operator-sdk:csv:customresourcedefinitions:order=29,type=spec,displayName="Security Context" SecurityContext *corev1.SecurityContext `json:"securityContext,omitempty"` - // +operator-sdk:csv:customresourcedefinitions:order=26,type=spec,displayName="Topology Spread Constraints" + // +operator-sdk:csv:customresourcedefinitions:order=30,type=spec,displayName="Topology Spread Constraints" TopologySpreadConstraints *RuntimeComponentTopologySpreadConstraints `json:"topologySpreadConstraints,omitempty"` // Disable information about services being injected into the application pod's environment variables. Default to false. - // +operator-sdk:csv:customresourcedefinitions:order=27,type=spec,displayName="Disable Service Links",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" + // +operator-sdk:csv:customresourcedefinitions:order=31,type=spec,displayName="Disable Service Links",xDescriptors="urn:alm:descriptor:com.tectonic.ui:booleanSwitch" DisableServiceLinks *bool `json:"disableServiceLinks,omitempty"` // Tolerations to be added to application pods. Tolerations allow the scheduler to schedule pods on nodes with matching taints. - // +operator-sdk:csv:customresourcedefinitions:order=28,type=spec,displayName="Tolerations" + // +operator-sdk:csv:customresourcedefinitions:order=32,type=spec,displayName="Tolerations" Tolerations []corev1.Toleration `json:"tolerations,omitempty"` // DNS settings for the pod. - // +operator-sdk:csv:customresourcedefinitions:order=29,type=spec,displayName="DNS" + // +operator-sdk:csv:customresourcedefinitions:order=33,type=spec,displayName="DNS" DNS *RuntimeComponentDNS `json:"dns,omitempty"` } @@ -566,6 +570,11 @@ func (cr *RuntimeComponent) GetPullSecret() *string { return cr.Spec.PullSecret } +// GetPullSecrets returns the secret list for additional docker registry credentials +func (cr *RuntimeComponent) GetPullSecrets() []string { + return cr.Spec.PullSecrets +} + // GetToleration returns pod tolerations slice func (cr *RuntimeComponent) GetTolerations() []corev1.Toleration { return cr.Spec.Tolerations diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index b29eed28..d2c734cc 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -532,6 +532,11 @@ func (in *RuntimeComponentSpec) DeepCopyInto(out *RuntimeComponentSpec) { *out = new(string) **out = **in } + if in.PullSecrets != nil { + in, out := &in.PullSecrets, &out.PullSecrets + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.ServiceAccountName != nil { in, out := &in.ServiceAccountName, &out.ServiceAccountName *out = new(string) diff --git a/bundle/manifests/rc.app.stacks_runtimecomponents.yaml b/bundle/manifests/rc.app.stacks_runtimecomponents.yaml index 35d6d5fe..f69ce343 100644 --- a/bundle/manifests/rc.app.stacks_runtimecomponents.yaml +++ b/bundle/manifests/rc.app.stacks_runtimecomponents.yaml @@ -4856,6 +4856,13 @@ spec: repository. It is not required if the cluster is configured with a global image pull secret. type: string + pullSecrets: + description: List of Secrets to use to pull images from one or more + specified repositories. It is not required if the cluster is configured + with a global image pull secret. + items: + type: string + type: array replicas: description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. diff --git a/bundle/manifests/runtime-component.clusterserviceversion.yaml b/bundle/manifests/runtime-component.clusterserviceversion.yaml index e75f09e8..526059e3 100644 --- a/bundle/manifests/runtime-component.clusterserviceversion.yaml +++ b/bundle/manifests/runtime-component.clusterserviceversion.yaml @@ -71,7 +71,7 @@ metadata: categories: Application Runtime certified: "true" containerImage: icr.io/appcafe/runtime-component-operator:daily - createdAt: "2025-12-08T16:01:38Z" + createdAt: "2025-12-15T19:54:22Z" description: Deploys any runtime component with dynamic and auto-tuning configuration features.operators.openshift.io/disconnected: "true" features.operators.openshift.io/fips-compliant: "true" @@ -223,68 +223,64 @@ spec: path: pullSecret x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret - - description: The service account to use for deploying the application. A service - account is automatically created if this is not specifed. - displayName: Service Account - path: serviceAccount + - description: List of Secrets to use to pull images from one or more specified + repositories. It is not required if the cluster is configured with a global + image pull secret. + displayName: Pull Secrets + path: pullSecrets - description: Deprecated. .spec.serviceAccount.name should be used instead. If both are specified, .spec.serviceAccount.name will override this. displayName: Service Account Name path: serviceAccountName x-descriptors: - urn:alm:descriptor:com.tectonic.ui:hidden + - description: The service account to use for deploying the application. A service + account is automatically created if this is not specifed. + displayName: Service Account + path: serviceAccount - description: Create Knative resources and use Knative serving. displayName: Create Knative Service path: createKnativeService x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: The port exposed by the container. + displayName: Service Port + path: service.port + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number - description: Expose the application externally via a Route, a Knative Route or an Ingress resource. displayName: Expose path: expose x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - displayName: Service Type + path: service.type + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text - description: Enable management of TLS certificates. Defaults to true. displayName: Manage TLS path: manageTLS x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Node proxies this port into your service. + displayName: Node Port + path: service.nodePort + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number - description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. displayName: Replicas path: replicas x-descriptors: - urn:alm:descriptor:com.tectonic.ui:podCount - - description: The port exposed by the container. - displayName: Service Port - path: service.port - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:number - - displayName: Auto Scaling - path: autoscaling - - displayName: Service Type - path: service.type - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:text - - description: Resource requests and limits for the application container. - displayName: Resource Requirements - path: resources - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:resourceRequirements - - description: Node proxies this port into your service. - displayName: Node Port - path: service.nodePort - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:number - - displayName: Probes - path: probes - description: The name for the port exposed by the container. displayName: Port Name path: service.portName x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Deployment - path: deployment + - displayName: Auto Scaling + path: autoscaling - description: Annotations to be added to the service. displayName: Service Annotations path: service.annotations @@ -295,16 +291,19 @@ spec: path: service.certificate.annotations x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: Resource requests and limits for the application container. + displayName: Resource Requirements + path: resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements - description: The port that the operator assigns to containers inside pods. Defaults to the value of .spec.service.port. displayName: Target Port path: service.targetPort x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number - - displayName: StatefulSet - path: statefulSet - - displayName: Service - path: service + - displayName: Probes + path: probes - description: 'A name of a secret that already contains TLS key, certificate and CA to be mounted in the pod. The following keys are valid in the secret: ca.crt, tls.crt, and tls.key.' @@ -312,130 +311,136 @@ spec: path: service.certificateSecretRef x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Network Policy - path: networkPolicy - - displayName: Route - path: route + - displayName: Deployment + path: deployment - description: Configure service certificate. displayName: Service Certificate path: service.certificate - - displayName: Monitoring - path: monitoring - description: An array consisting of service ports. displayName: Ports path: service.ports - - description: An array of environment variables for the application container. - displayName: Environment Variables - path: env + - displayName: StatefulSet + path: statefulSet + - displayName: Service + path: service - description: Expose the application as a bindable service. Defaults to false. displayName: Bindable path: service.bindable x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - - description: List of sources to populate environment variables in the application - container. - displayName: Environment Variables from Sources - path: envFrom + - displayName: Route + path: route - description: Configure service session affinity. displayName: Session Affinity path: service.sessionAffinity + - displayName: Network Policy + path: networkPolicy - description: Setting to maintain session affinity. Must be ClientIP or None. Defaults to None. displayName: Session Affinity Type path: service.sessionAffinity.type x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - description: Represents a volume with data that is accessible to the application - container. - displayName: Volumes - path: volumes - description: Specifies the strategy to replace old deployment pods with new pods. displayName: Deployment Update Strategy path: deployment.updateStrategy x-descriptors: - urn:alm:descriptor:com.tectonic.ui:updateStrategy + - displayName: Monitoring + path: monitoring - description: Configurations of session affinity. displayName: Config path: service.sessionAffinity.config - - description: Represents where to mount the volumes into the application container. - displayName: Volume Mounts - path: volumeMounts - - description: List of containers to run before other containers in a pod. - displayName: Init Containers - path: initContainers - - description: List of sidecar containers. These are additional containers to - be added to the pods. - displayName: Sidecar Containers - path: sidecarContainers + - description: An array of environment variables for the application container. + displayName: Environment Variables + path: env + - description: List of sources to populate environment variables in the application + container. + displayName: Environment Variables from Sources + path: envFrom - description: Specifies the strategy to replace old statefulSet pods with new pods. displayName: StatefulSet Update Strategy path: statefulSet.updateStrategy x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Affinity - path: affinity - displayName: Storage path: statefulSet.storage - - description: Security context for the application container. - displayName: Security Context - path: securityContext + - description: Represents a volume with data that is accessible to the application + container. + displayName: Volumes + path: volumes - description: A convenient field to set the size of the persisted storage. displayName: Storage Size path: statefulSet.storage.size x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: Represents where to mount the volumes into the application container. + displayName: Volume Mounts + path: volumeMounts + - description: List of containers to run before other containers in a pod. + displayName: Init Containers + path: initContainers - description: A convenient field to request the storage class of the persisted storage. The name can not be specified or updated after the storage is created. displayName: Storage Class Name path: statefulSet.storage.className x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Topology Spread Constraints - path: topologySpreadConstraints - - description: Disable information about services being injected into the application - pod's environment variables. Default to false. - displayName: Disable Service Links - path: disableServiceLinks - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of sidecar containers. These are additional containers to + be added to the pods. + displayName: Sidecar Containers + path: sidecarContainers - description: The directory inside the container where this persisted storage will be bound to. displayName: Storage Mount Path path: statefulSet.storage.mountPath x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - displayName: Affinity + path: affinity - description: A YAML object that represents a volumeClaimTemplate component of a StatefulSet. displayName: Storage Volume Claim Template path: statefulSet.storage.volumeClaimTemplate x-descriptors: - urn:alm:descriptor:com.tectonic.ui:PersistentVolumeClaim - - description: Tolerations to be added to application pods. Tolerations allow - the scheduler to schedule pods on nodes with matching taints. - displayName: Tolerations - path: tolerations - - description: DNS settings for the pod. - displayName: DNS - path: dns + - description: Security context for the application container. + displayName: Security Context + path: securityContext - description: Labels to set on ServiceMonitor. displayName: Monitoring Labels path: monitoring.labels x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - displayName: Topology Spread Constraints + path: topologySpreadConstraints + - description: Disable information about services being injected into the application + pod's environment variables. Default to false. + displayName: Disable Service Links + path: disableServiceLinks + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - description: A YAML snippet representing an array of Endpoint component from ServiceMonitor. displayName: Monitoring Endpoints path: monitoring.endpoints x-descriptors: - urn:alm:descriptor:com.tectonic.ui:endpointList + - description: Tolerations to be added to application pods. Tolerations allow + the scheduler to schedule pods on nodes with matching taints. + displayName: Tolerations + path: tolerations - description: Controls which nodes the pod are scheduled to run on, based on labels on the node. displayName: Node Affinity path: affinity.nodeAffinity x-descriptors: - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: DNS settings for the pod. + displayName: DNS + path: dns - description: Controls the nodes the pod are scheduled to run on, based on labels on the pods that are already running on the node. displayName: Pod Affinity diff --git a/common/types.go b/common/types.go index c9232ad6..dc731ecf 100644 --- a/common/types.go +++ b/common/types.go @@ -22,6 +22,7 @@ type StatusReferences map[string]string const ( StatusReferenceCertSecretName = "svcCertSecretName" StatusReferencePullSecretName = "saPullSecretName" + StatusReferencePullSecrets = "saPullSecrets" StatusReferenceSAResourceVersion = "saResourceVersion" StatusReferenceRouteHost = "routeHost" ) @@ -227,6 +228,7 @@ type BaseComponent interface { GetApplicationImage() string GetPullPolicy() *corev1.PullPolicy GetPullSecret() *string + GetPullSecrets() []string GetServiceAccountName() *string GetServiceAccount() BaseComponentServiceAccount GetReplicas() *int32 diff --git a/config/crd/bases/rc.app.stacks_runtimecomponents.yaml b/config/crd/bases/rc.app.stacks_runtimecomponents.yaml index 2a0b5f72..8612a104 100644 --- a/config/crd/bases/rc.app.stacks_runtimecomponents.yaml +++ b/config/crd/bases/rc.app.stacks_runtimecomponents.yaml @@ -4852,6 +4852,13 @@ spec: repository. It is not required if the cluster is configured with a global image pull secret. type: string + pullSecrets: + description: List of Secrets to use to pull images from one or more + specified repositories. It is not required if the cluster is configured + with a global image pull secret. + items: + type: string + type: array replicas: description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. diff --git a/config/manifests/bases/runtime-component.clusterserviceversion.yaml b/config/manifests/bases/runtime-component.clusterserviceversion.yaml index d147ca9a..0dae28ed 100644 --- a/config/manifests/bases/runtime-component.clusterserviceversion.yaml +++ b/config/manifests/bases/runtime-component.clusterserviceversion.yaml @@ -157,68 +157,64 @@ spec: path: pullSecret x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret - - description: The service account to use for deploying the application. A service - account is automatically created if this is not specifed. - displayName: Service Account - path: serviceAccount + - description: List of Secrets to use to pull images from one or more specified + repositories. It is not required if the cluster is configured with a global + image pull secret. + displayName: Pull Secrets + path: pullSecrets - description: Deprecated. .spec.serviceAccount.name should be used instead. If both are specified, .spec.serviceAccount.name will override this. displayName: Service Account Name path: serviceAccountName x-descriptors: - urn:alm:descriptor:com.tectonic.ui:hidden + - description: The service account to use for deploying the application. A service + account is automatically created if this is not specifed. + displayName: Service Account + path: serviceAccount - description: Create Knative resources and use Knative serving. displayName: Create Knative Service path: createKnativeService x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: The port exposed by the container. + displayName: Service Port + path: service.port + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number - description: Expose the application externally via a Route, a Knative Route or an Ingress resource. displayName: Expose path: expose x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - displayName: Service Type + path: service.type + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text - description: Enable management of TLS certificates. Defaults to true. displayName: Manage TLS path: manageTLS x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Node proxies this port into your service. + displayName: Node Port + path: service.nodePort + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number - description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. displayName: Replicas path: replicas x-descriptors: - urn:alm:descriptor:com.tectonic.ui:podCount - - description: The port exposed by the container. - displayName: Service Port - path: service.port - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:number - - displayName: Auto Scaling - path: autoscaling - - displayName: Service Type - path: service.type - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:text - - description: Resource requests and limits for the application container. - displayName: Resource Requirements - path: resources - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:resourceRequirements - - description: Node proxies this port into your service. - displayName: Node Port - path: service.nodePort - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:number - - displayName: Probes - path: probes - description: The name for the port exposed by the container. displayName: Port Name path: service.portName x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Deployment - path: deployment + - displayName: Auto Scaling + path: autoscaling - description: Annotations to be added to the service. displayName: Service Annotations path: service.annotations @@ -229,16 +225,19 @@ spec: path: service.certificate.annotations x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: Resource requests and limits for the application container. + displayName: Resource Requirements + path: resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements - description: The port that the operator assigns to containers inside pods. Defaults to the value of .spec.service.port. displayName: Target Port path: service.targetPort x-descriptors: - urn:alm:descriptor:com.tectonic.ui:number - - displayName: StatefulSet - path: statefulSet - - displayName: Service - path: service + - displayName: Probes + path: probes - description: 'A name of a secret that already contains TLS key, certificate and CA to be mounted in the pod. The following keys are valid in the secret: ca.crt, tls.crt, and tls.key.' @@ -246,130 +245,136 @@ spec: path: service.certificateSecretRef x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Network Policy - path: networkPolicy - - displayName: Route - path: route + - displayName: Deployment + path: deployment - description: Configure service certificate. displayName: Service Certificate path: service.certificate - - displayName: Monitoring - path: monitoring - description: An array consisting of service ports. displayName: Ports path: service.ports - - description: An array of environment variables for the application container. - displayName: Environment Variables - path: env + - displayName: StatefulSet + path: statefulSet + - displayName: Service + path: service - description: Expose the application as a bindable service. Defaults to false. displayName: Bindable path: service.bindable x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - - description: List of sources to populate environment variables in the application - container. - displayName: Environment Variables from Sources - path: envFrom + - displayName: Route + path: route - description: Configure service session affinity. displayName: Session Affinity path: service.sessionAffinity + - displayName: Network Policy + path: networkPolicy - description: Setting to maintain session affinity. Must be ClientIP or None. Defaults to None. displayName: Session Affinity Type path: service.sessionAffinity.type x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - description: Represents a volume with data that is accessible to the application - container. - displayName: Volumes - path: volumes - description: Specifies the strategy to replace old deployment pods with new pods. displayName: Deployment Update Strategy path: deployment.updateStrategy x-descriptors: - urn:alm:descriptor:com.tectonic.ui:updateStrategy + - displayName: Monitoring + path: monitoring - description: Configurations of session affinity. displayName: Config path: service.sessionAffinity.config - - description: Represents where to mount the volumes into the application container. - displayName: Volume Mounts - path: volumeMounts - - description: List of containers to run before other containers in a pod. - displayName: Init Containers - path: initContainers - - description: List of sidecar containers. These are additional containers to - be added to the pods. - displayName: Sidecar Containers - path: sidecarContainers + - description: An array of environment variables for the application container. + displayName: Environment Variables + path: env + - description: List of sources to populate environment variables in the application + container. + displayName: Environment Variables from Sources + path: envFrom - description: Specifies the strategy to replace old statefulSet pods with new pods. displayName: StatefulSet Update Strategy path: statefulSet.updateStrategy x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Affinity - path: affinity - displayName: Storage path: statefulSet.storage - - description: Security context for the application container. - displayName: Security Context - path: securityContext + - description: Represents a volume with data that is accessible to the application + container. + displayName: Volumes + path: volumes - description: A convenient field to set the size of the persisted storage. displayName: Storage Size path: statefulSet.storage.size x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - description: Represents where to mount the volumes into the application container. + displayName: Volume Mounts + path: volumeMounts + - description: List of containers to run before other containers in a pod. + displayName: Init Containers + path: initContainers - description: A convenient field to request the storage class of the persisted storage. The name can not be specified or updated after the storage is created. displayName: Storage Class Name path: statefulSet.storage.className x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text - - displayName: Topology Spread Constraints - path: topologySpreadConstraints - - description: Disable information about services being injected into the application - pod's environment variables. Default to false. - displayName: Disable Service Links - path: disableServiceLinks - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of sidecar containers. These are additional containers to + be added to the pods. + displayName: Sidecar Containers + path: sidecarContainers - description: The directory inside the container where this persisted storage will be bound to. displayName: Storage Mount Path path: statefulSet.storage.mountPath x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - displayName: Affinity + path: affinity - description: A YAML object that represents a volumeClaimTemplate component of a StatefulSet. displayName: Storage Volume Claim Template path: statefulSet.storage.volumeClaimTemplate x-descriptors: - urn:alm:descriptor:com.tectonic.ui:PersistentVolumeClaim - - description: Tolerations to be added to application pods. Tolerations allow - the scheduler to schedule pods on nodes with matching taints. - displayName: Tolerations - path: tolerations - - description: DNS settings for the pod. - displayName: DNS - path: dns + - description: Security context for the application container. + displayName: Security Context + path: securityContext - description: Labels to set on ServiceMonitor. displayName: Monitoring Labels path: monitoring.labels x-descriptors: - urn:alm:descriptor:com.tectonic.ui:text + - displayName: Topology Spread Constraints + path: topologySpreadConstraints + - description: Disable information about services being injected into the application + pod's environment variables. Default to false. + displayName: Disable Service Links + path: disableServiceLinks + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - description: A YAML snippet representing an array of Endpoint component from ServiceMonitor. displayName: Monitoring Endpoints path: monitoring.endpoints x-descriptors: - urn:alm:descriptor:com.tectonic.ui:endpointList + - description: Tolerations to be added to application pods. Tolerations allow + the scheduler to schedule pods on nodes with matching taints. + displayName: Tolerations + path: tolerations - description: Controls which nodes the pod are scheduled to run on, based on labels on the node. displayName: Node Affinity path: affinity.nodeAffinity x-descriptors: - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: DNS settings for the pod. + displayName: DNS + path: dns - description: Controls the nodes the pod are scheduled to run on, based on labels on the pods that are already running on the node. displayName: Pod Affinity diff --git a/internal/deploy/kubectl/runtime-component-crd.yaml b/internal/deploy/kubectl/runtime-component-crd.yaml index 5eadacb5..7ebf108a 100644 --- a/internal/deploy/kubectl/runtime-component-crd.yaml +++ b/internal/deploy/kubectl/runtime-component-crd.yaml @@ -4855,6 +4855,13 @@ spec: repository. It is not required if the cluster is configured with a global image pull secret. type: string + pullSecrets: + description: List of Secrets to use to pull images from one or more + specified repositories. It is not required if the cluster is configured + with a global image pull secret. + items: + type: string + type: array replicas: description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. diff --git a/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml b/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml index 5eadacb5..7ebf108a 100644 --- a/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml +++ b/internal/deploy/kustomize/daily/base/runtime-component-crd.yaml @@ -4855,6 +4855,13 @@ spec: repository. It is not required if the cluster is configured with a global image pull secret. type: string + pullSecrets: + description: List of Secrets to use to pull images from one or more + specified repositories. It is not required if the cluster is configured + with a global image pull secret. + items: + type: string + type: array replicas: description: Number of pods to create. Defaults to 1. Not applicable when .spec.autoscaling or .spec.createKnativeService is specified. diff --git a/utils/utils.go b/utils/utils.go index 3d016372..9efc03df 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -3,10 +3,12 @@ package utils import ( "bytes" "context" + "encoding/base64" "encoding/json" "errors" "fmt" "os" + "slices" "sort" "strconv" "strings" @@ -912,9 +914,64 @@ func CustomizeServiceAccount(sa *corev1.ServiceAccount, ba common.BaseComponent, } } + pssr := ba.GetStatus().GetReferences()[common.StatusReferencePullSecrets] + pullSecrets := Set(DecodePullSecrets(pssr)) + crPullSecrets := Set(ba.GetPullSecrets()) + if pssr != "" && !SetEquals(crPullSecrets, pullSecrets) { + // There is a reference to a pull secret but it doesn't match the one + // from the CR (which is empty or different) + // so delete the refered pull secret from the service account + missingPullSecrets := SetDiff(pullSecrets, crPullSecrets) + removePullSecrets(sa, missingPullSecrets) + } + if len(crPullSecrets) == 0 { + // There is no pull secret so delete the status reference + // This has to happen after the reference has been used to remove the pull + // secret from the service account + delete(ba.GetStatus().GetReferences(), common.StatusReferencePullSecrets) + } else { + // Add the pull secrets from the CR to the service account. First check that all are valid + for _, ps := range crPullSecrets { + err := client.Get(context.TODO(), types.NamespacedName{Name: ps, Namespace: ba.(metav1.Object).GetNamespace()}, &corev1.Secret{}) + if err != nil { + return err + } + } + ba.GetStatus().SetReference(common.StatusReferencePullSecrets, EncodePullSecrets(pullSecrets)) + if len(sa.ImagePullSecrets) == 0 { + for _, ps := range crPullSecrets { + sa.ImagePullSecrets = append(sa.ImagePullSecrets, corev1.LocalObjectReference{ + Name: ps, + }) + } + } else { + for _, ps := range crPullSecrets { + pullSecretName := ps + found := false + for _, obj := range sa.ImagePullSecrets { + if obj.Name == pullSecretName { + found = true + break + } + } + if !found { + sa.ImagePullSecrets = append(sa.ImagePullSecrets, corev1.LocalObjectReference{ + Name: pullSecretName, + }) + } + } + } + } + return nil } +func removePullSecrets(sa *corev1.ServiceAccount, pullSecrets []string) { + for _, ps := range pullSecrets { + removePullSecret(sa, ps) + } +} + func removePullSecret(sa *corev1.ServiceAccount, pullSecretName string) { index := -1 for i, obj := range sa.ImagePullSecrets { @@ -1985,3 +2042,58 @@ func parseEnvAsBool(envValue string) bool { } return false } + +// Encodes a pullSecrets list into a comma-separated and base64 encoded string +func EncodePullSecrets(pullSecrets []string) string { + return base64.RawURLEncoding.EncodeToString([]byte(strings.Join(pullSecrets, ","))) +} + +// Decodes a comma-separated and base64 encoded pull secrets string into a list +func DecodePullSecrets(pullSecretsString string) []string { + output, err := base64.RawURLEncoding.DecodeString(pullSecretsString) + if err != nil { + return []string{} + } + return strings.Split(string(output), ",") +} + +// Returns true if set A and B are equivalent +func SetEquals(a []string, b []string) bool { + if len(a) != len(b) { + return false + } + // track seen items in a + seen := map[string]bool{} + for _, v := range a { + seen[v] = true + } + // return false if b contains an element not in a + for _, v := range b { + if _, found := seen[v]; !found { + return false + } + } + return true +} + +// Converts list A into a set without repeated values +func Set(a []string) []string { + out := []string{} + for _, v := range a { + if !slices.Contains(out, v) { + out = append(out, v) + } + } + return out +} + +// Returns the set difference of A \ B +func SetDiff(a []string, b []string) []string { + out := []string{} + for _, v := range a { + if !slices.Contains(b, v) { + out = append(out, v) + } + } + return out +}