Add support for imagePullSecrets (#2589)

* Add support for imagePullSecrets in the CDI CR, to support pulling
images from repositories that require secrets.

The imagePullSecrets is propagated to the following components: cdi-apiserver,
cdi-deployment, and cdi-uploadproxy. The definition of imagePullSecrets in
cdi-operator must be done manually.

Signed-off-by: Gleb Aronsky <gleb.aronsky@windriver.com>

* Modifying code to incorporate review comments.

Signed-off-by: Gleb Aronsky <gleb.aronsky@windriver.com>

---------

Signed-off-by: Gleb Aronsky <gleb.aronsky@windriver.com>
Co-authored-by: Gleb Aronsky <gleb.aronsky@windriver.com>
This commit is contained in:
garonsky 2023-03-17 21:41:35 -04:00 committed by GitHub
parent 184ee03acf
commit 4e3ee4c44d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 225 additions and 27 deletions

View File

@ -4044,6 +4044,17 @@
}
}
},
"v1.LocalObjectReference": {
"description": "LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.",
"type": "object",
"properties": {
"name": {
"description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
"type": "string"
}
},
"x-kubernetes-map-type": "atomic"
},
"v1.ManagedFieldsEntry": {
"description": "ManagedFieldsEntry is a workflow-id, a FieldSet and the group version of the resource that the fieldset applies to.",
"type": "object",
@ -4893,6 +4904,14 @@
"description": "FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A value is between 0 and 1, if not defined it is 0.055 (5.5% overhead)",
"$ref": "#/definitions/v1beta1.FilesystemOverhead"
},
"imagePullSecrets": {
"description": "The imagePullSecrets used to pull the container images",
"type": "array",
"items": {
"default": {},
"$ref": "#/definitions/v1.LocalObjectReference"
}
},
"importProxy": {
"description": "ImportProxy contains importer pod proxy configuration.",
"$ref": "#/definitions/v1beta1.ImportProxy"
@ -4939,6 +4958,14 @@
"description": "FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A percentage value is between 0 and 1",
"$ref": "#/definitions/v1beta1.FilesystemOverhead"
},
"imagePullSecrets": {
"description": "The imagePullSecrets used to pull the container images",
"type": "array",
"items": {
"default": {},
"$ref": "#/definitions/v1.LocalObjectReference"
}
},
"importProxy": {
"description": "ImportProxy contains importer pod proxy configuration.",
"$ref": "#/definitions/v1beta1.ImportProxy"

View File

@ -22986,11 +22986,25 @@ func schema_pkg_apis_core_v1beta1_CDIConfigSpec(ref common.ReferenceCallback) co
Ref: ref("github.com/openshift/api/config/v1.TLSSecurityProfile"),
},
},
"imagePullSecrets": {
SchemaProps: spec.SchemaProps{
Description: "The imagePullSecrets used to pull the container images",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/api/core/v1.LocalObjectReference"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"github.com/openshift/api/config/v1.TLSSecurityProfile", "k8s.io/api/core/v1.ResourceRequirements", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.FilesystemOverhead", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.ImportProxy"},
"github.com/openshift/api/config/v1.TLSSecurityProfile", "k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.ResourceRequirements", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.FilesystemOverhead", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.ImportProxy"},
}
}
@ -23040,11 +23054,25 @@ func schema_pkg_apis_core_v1beta1_CDIConfigStatus(ref common.ReferenceCallback)
Format: "",
},
},
"imagePullSecrets": {
SchemaProps: spec.SchemaProps{
Description: "The imagePullSecrets used to pull the container images",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
Ref: ref("k8s.io/api/core/v1.LocalObjectReference"),
},
},
},
},
},
},
},
},
Dependencies: []string{
"k8s.io/api/core/v1.ResourceRequirements", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.FilesystemOverhead", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.ImportProxy"},
"k8s.io/api/core/v1.LocalObjectReference", "k8s.io/api/core/v1.ResourceRequirements", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.FilesystemOverhead", "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1.ImportProxy"},
}
}

View File

@ -497,6 +497,11 @@ func (r *CloneReconciler) CreateCloneSourcePod(image, pullPolicy string, pvc *co
return nil, err
}
imagePullSecrets, err := cc.GetImagePullSecrets(r.client)
if err != nil {
return nil, err
}
workloadNodePlacement, err := cc.GetWorkloadNodePlacement(r.client)
if err != nil {
return nil, err
@ -514,7 +519,7 @@ func (r *CloneReconciler) CreateCloneSourcePod(image, pullPolicy string, pvc *co
sourceVolumeMode = corev1.PersistentVolumeFilesystem
}
pod := MakeCloneSourcePodSpec(sourceVolumeMode, image, pullPolicy, sourcePvcName, sourcePvcNamespace, ownerKey, serverCABundle, pvc, podResourceRequirements, workloadNodePlacement)
pod := MakeCloneSourcePodSpec(sourceVolumeMode, image, pullPolicy, imagePullSecrets, sourcePvcName, sourcePvcNamespace, ownerKey, serverCABundle, pvc, podResourceRequirements, workloadNodePlacement)
util.SetRecommendedLabels(pod, r.installerLabels, "cdi-controller")
if err := r.client.Create(context.TODO(), pod); err != nil {
@ -527,7 +532,7 @@ func (r *CloneReconciler) CreateCloneSourcePod(image, pullPolicy string, pvc *co
}
// MakeCloneSourcePodSpec creates and returns the clone source pod spec based on the target pvc.
func MakeCloneSourcePodSpec(sourceVolumeMode corev1.PersistentVolumeMode, image, pullPolicy, sourcePvcName, sourcePvcNamespace, ownerRefAnno string,
func MakeCloneSourcePodSpec(sourceVolumeMode corev1.PersistentVolumeMode, image, pullPolicy string, imagePullSecrets []corev1.LocalObjectReference, sourcePvcName, sourcePvcNamespace, ownerRefAnno string,
serverCACert []byte, targetPvc *corev1.PersistentVolumeClaim, resourceRequirements *corev1.ResourceRequirements,
workloadNodePlacement *sdkapi.NodePlacement) *corev1.Pod {
@ -617,7 +622,8 @@ func MakeCloneSourcePodSpec(sourceVolumeMode corev1.PersistentVolumeMode, image,
},
},
},
RestartPolicy: corev1.RestartPolicyOnFailure,
ImagePullSecrets: imagePullSecrets,
RestartPolicy: corev1.RestartPolicyOnFailure,
Volumes: []corev1.Volume{
{
Name: cc.DataVolName,

View File

@ -415,6 +415,17 @@ func GetDefaultPodResourceRequirements(client client.Client) (*v1.ResourceRequir
return cdiconfig.Status.DefaultPodResourceRequirements, nil
}
// GetImagePullSecrets gets the imagePullSecrets needed to pull images from the cdi config
func GetImagePullSecrets(client client.Client) ([]corev1.LocalObjectReference, error) {
cdiconfig := &cdiv1.CDIConfig{}
if err := client.Get(context.TODO(), types.NamespacedName{Name: common.ConfigName}, cdiconfig); err != nil {
klog.Errorf("Unable to find CDI configuration, %v\n", err)
return nil, err
}
return cdiconfig.Status.ImagePullSecrets, nil
}
// AddVolumeDevices returns VolumeDevice slice with one block device for pods using PV with block volume mode
func AddVolumeDevices() []v1.VolumeDevice {
volumeDevices := []v1.VolumeDevice{

View File

@ -97,6 +97,10 @@ func (r *CDIConfigReconciler) Reconcile(_ context.Context, req reconcile.Request
return reconcile.Result{}, err
}
if err := r.reconcileImagePullSecrets(config); err != nil {
return reconcile.Result{}, err
}
if err := r.reconcileFilesystemOverhead(config); err != nil {
return reconcile.Result{}, err
}
@ -232,6 +236,11 @@ func (r *CDIConfigReconciler) reconcileStorageClass(config *cdiv1.CDIConfig) err
return nil
}
func (r *CDIConfigReconciler) reconcileImagePullSecrets(config *cdiv1.CDIConfig) error {
config.Status.ImagePullSecrets = config.Spec.ImagePullSecrets
return nil
}
func (r *CDIConfigReconciler) reconcileDefaultPodResourceRequirements(config *cdiv1.CDIConfig) error {
cpuLimit, _ := resource.ParseQuantity(defaultCPULimit)
memLimit, _ := resource.ParseQuantity(defaultMemLimit)

View File

@ -860,6 +860,10 @@ func (r *DataImportCronReconciler) newCronJob(cron *cdiv1.DataImportCron) (*batc
addEnvVarFromImportProxyConfig(common.ImportProxyHTTPS)
addEnvVarFromImportProxyConfig(common.ImportProxyNoProxy)
imagePullSecrets, err := cc.GetImagePullSecrets(r.client)
if err != nil {
return nil, err
}
cronJobName := GetCronJobName(cron)
cronJob := &batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
@ -880,6 +884,7 @@ func (r *DataImportCronReconciler) newCronJob(cron *cdiv1.DataImportCron) (*batc
Containers: []corev1.Container{container},
ServiceAccountName: common.CronJobServiceAccountName,
Volumes: volumes,
ImagePullSecrets: imagePullSecrets,
},
},
BackoffLimit: pointer.Int32(2),

View File

@ -420,6 +420,11 @@ func (r *CloneReconcilerBase) createExpansionPod(pvc *corev1.PersistentVolumeCla
return nil, err
}
imagePullSecrets, err := cc.GetImagePullSecrets(r.client)
if err != nil {
return nil, err
}
workloadNodePlacement, err := cc.GetWorkloadNodePlacement(r.client)
if err != nil {
return nil, err
@ -447,7 +452,8 @@ func (r *CloneReconcilerBase) createExpansionPod(pvc *corev1.PersistentVolumeCla
Args: []string{"-c", "echo", "'hello cdi'"},
},
},
RestartPolicy: corev1.RestartPolicyOnFailure,
ImagePullSecrets: imagePullSecrets,
RestartPolicy: corev1.RestartPolicyOnFailure,
Volumes: []corev1.Volume{
{
Name: cc.DataVolName,

View File

@ -1253,6 +1253,11 @@ func (r *PvcCloneReconciler) makeSizeDetectionPodSpec(
if container == nil {
return nil
}
imagePullSecrets, err := cc.GetImagePullSecrets(r.client)
if err != nil {
return nil
}
// Assemble the pod
pod := &corev1.Pod{
ObjectMeta: *objectMeta,
@ -1268,6 +1273,7 @@ func (r *PvcCloneReconciler) makeSizeDetectionPodSpec(
Tolerations: workloadNodePlacement.Tolerations,
Affinity: workloadNodePlacement.Affinity,
PriorityClassName: cc.GetPriorityClass(sourcePvc),
ImagePullSecrets: imagePullSecrets,
},
}

View File

@ -111,6 +111,7 @@ type importerPodArgs struct {
pvc *corev1.PersistentVolumeClaim
scratchPvcName *string
podResourceRequirements *corev1.ResourceRequirements
imagePullSecrets []corev1.LocalObjectReference
workloadNodePlacement *sdkapi.NodePlacement
vddkImageName *string
priorityClassName string
@ -866,6 +867,11 @@ func createImporterPod(log logr.Logger, client client.Client, args *importerPodA
return nil, err
}
args.imagePullSecrets, err = cc.GetImagePullSecrets(client)
if err != nil {
return nil, err
}
args.workloadNodePlacement, err = cc.GetWorkloadNodePlacement(client)
if err != nil {
return nil, err
@ -970,6 +976,7 @@ func makeNodeImporterPodSpec(args *importerPodArgs) *corev1.Pod {
Tolerations: args.workloadNodePlacement.Tolerations,
Affinity: args.workloadNodePlacement.Affinity,
PriorityClassName: args.priorityClassName,
ImagePullSecrets: args.imagePullSecrets,
},
}
@ -1002,7 +1009,7 @@ func makeNodeImporterPodSpec(args *importerPodArgs) *corev1.Pod {
args.podEnvVar.ep = "http://localhost:8100/disk.img"
args.podEnvVar.readyFile = "/shared/ready"
args.podEnvVar.doneFile = "/shared/done"
setImporterPodCommons(pod, args.podEnvVar, args.pvc, args.podResourceRequirements)
setImporterPodCommons(pod, args.podEnvVar, args.pvc, args.podResourceRequirements, args.imagePullSecrets)
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
MountPath: "/shared",
Name: "shared-volume",
@ -1084,10 +1091,11 @@ func makeImporterPodSpec(args *importerPodArgs) *corev1.Pod {
Tolerations: args.workloadNodePlacement.Tolerations,
Affinity: args.workloadNodePlacement.Affinity,
PriorityClassName: args.priorityClassName,
ImagePullSecrets: args.imagePullSecrets,
},
}
setImporterPodCommons(pod, args.podEnvVar, args.pvc, args.podResourceRequirements)
setImporterPodCommons(pod, args.podEnvVar, args.pvc, args.podResourceRequirements, args.imagePullSecrets)
if args.scratchPvcName != nil {
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{
@ -1161,12 +1169,13 @@ func makeImporterPodSpec(args *importerPodArgs) *corev1.Pod {
return pod
}
func setImporterPodCommons(pod *corev1.Pod, podEnvVar *importPodEnvVar, pvc *corev1.PersistentVolumeClaim, podResourceRequirements *corev1.ResourceRequirements) {
func setImporterPodCommons(pod *corev1.Pod, podEnvVar *importPodEnvVar, pvc *corev1.PersistentVolumeClaim, podResourceRequirements *corev1.ResourceRequirements, imagePullSecrets []corev1.LocalObjectReference) {
if podResourceRequirements != nil {
for i := range pod.Spec.Containers {
pod.Spec.Containers[i].Resources = *podResourceRequirements
}
}
pod.Spec.ImagePullSecrets = imagePullSecrets
ownerUID := pvc.UID
if len(pvc.OwnerReferences) == 1 {

View File

@ -578,12 +578,17 @@ func (r *UploadReconciler) createUploadPod(args UploadPodArgs) (*v1.Pod, error)
return nil, err
}
imagePullSecrets, err := cc.GetImagePullSecrets(r.client)
if err != nil {
return nil, err
}
workloadNodePlacement, err := cc.GetWorkloadNodePlacement(r.client)
if err != nil {
return nil, err
}
pod := r.makeUploadPodSpec(args, podResourceRequirements, workloadNodePlacement)
pod := r.makeUploadPodSpec(args, podResourceRequirements, imagePullSecrets, workloadNodePlacement)
util.SetRecommendedLabels(pod, r.installerLabels, "cdi-controller")
if err := r.client.Get(context.TODO(), types.NamespacedName{Name: args.Name, Namespace: ns}, pod); err != nil {
@ -729,7 +734,7 @@ func createUploadServiceNameFromPvcName(pvc string) string {
return naming.GetServiceNameFromResourceName(createUploadResourceName(pvc))
}
func (r *UploadReconciler) makeUploadPodSpec(args UploadPodArgs, resourceRequirements *v1.ResourceRequirements, workloadNodePlacement *sdkapi.NodePlacement) *v1.Pod {
func (r *UploadReconciler) makeUploadPodSpec(args UploadPodArgs, resourceRequirements *v1.ResourceRequirements, imagePullSecrets []v1.LocalObjectReference, workloadNodePlacement *sdkapi.NodePlacement) *v1.Pod {
requestImageSize, _ := cc.GetRequestedImageSize(args.PVC)
serviceName := naming.GetServiceNameFromResourceName(args.Name)
pod := &v1.Pod{
@ -839,6 +844,7 @@ func (r *UploadReconciler) makeUploadPodSpec(args UploadPodArgs, resourceRequire
Tolerations: workloadNodePlacement.Tolerations,
Affinity: workloadNodePlacement.Affinity,
PriorityClassName: cc.GetPriorityClass(args.PVC),
ImagePullSecrets: imagePullSecrets,
},
}

View File

@ -1244,7 +1244,9 @@ var _ = Describe("Controller", func() {
Entry("verify - unused deployment deleted",
func() (client.Object, error) {
deployment := utils.CreateDeployment("fake-cdi-deployment", "app", "containerized-data-importer", "fake-sa", int32(1), &sdkapi.NodePlacement{})
const imagePullSecretName = "fake-registry-key"
var imagePullSecrets = []corev1.LocalObjectReference{{Name: imagePullSecretName}}
deployment := utils.CreateDeployment("fake-cdi-deployment", "app", "containerized-data-importer", "fake-sa", imagePullSecrets, int32(1), &sdkapi.NodePlacement{})
return deployment, nil
}),
Entry("verify - unused service deleted",

View File

@ -83,6 +83,9 @@ func (r *ReconcileCDI) getNamespacedArgs(cr *cdiv1.CDI) *cdinamespaced.FactoryAr
if cr.Spec.ImagePullPolicy != "" {
result.PullPolicy = string(cr.Spec.ImagePullPolicy)
}
if cr.Spec.Config != nil && len(cr.Spec.Config.ImagePullSecrets) > 0 {
result.ImagePullSecrets = cr.Spec.Config.ImagePullSecrets
}
if cr.Spec.PriorityClass != nil && string(*cr.Spec.PriorityClass) != "" {
result.PriorityClassName = string(*cr.Spec.PriorityClass)
} else {

View File

@ -125,6 +125,19 @@ spec:
global value
type: object
type: object
imagePullSecrets:
description: The imagePullSecrets used to pull the container images
items:
description: LocalObjectReference contains enough information
to let you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
type: array
importProxy:
description: ImportProxy contains importer pod proxy configuration.
properties:
@ -2341,6 +2354,19 @@ spec:
global value
type: object
type: object
imagePullSecrets:
description: The imagePullSecrets used to pull the container images
items:
description: LocalObjectReference contains enough information
to let you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
type: array
importProxy:
description: ImportProxy contains importer pod proxy configuration.
properties:
@ -4531,6 +4557,19 @@ spec:
value
type: object
type: object
imagePullSecrets:
description: The imagePullSecrets used to pull the container images
items:
description: LocalObjectReference contains enough information to
let you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
type: array
importProxy:
description: ImportProxy contains importer pod proxy configuration.
properties:
@ -4748,6 +4787,19 @@ spec:
value
type: object
type: object
imagePullSecrets:
description: The imagePullSecrets used to pull the container images
items:
description: LocalObjectReference contains enough information to
let you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
type: array
importProxy:
description: ImportProxy contains importer pod proxy configuration.
properties:

View File

@ -22,6 +22,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -46,7 +47,7 @@ func createAPIServerResources(args *FactoryArgs) []client.Object {
createAPIServerRoleBinding(),
createAPIServerRole(),
createAPIServerService(),
createAPIServerDeployment(args.APIServerImage, args.Verbosity, args.PullPolicy, args.PriorityClassName, args.InfraNodePlacement),
createAPIServerDeployment(args.APIServerImage, args.Verbosity, args.PullPolicy, args.ImagePullSecrets, args.PriorityClassName, args.InfraNodePlacement),
}
}
@ -91,9 +92,9 @@ func createAPIServerService() *corev1.Service {
return service
}
func createAPIServerDeployment(image, verbosity, pullPolicy, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
func createAPIServerDeployment(image, verbosity, pullPolicy string, imagePullSecrets []corev1.LocalObjectReference, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
defaultMode := corev1.ConfigMapVolumeSourceDefaultMode
deployment := utils.CreateDeployment(apiServerRessouceName, cdiLabel, apiServerRessouceName, apiServerRessouceName, 1, infraNodePlacement)
deployment := utils.CreateDeployment(apiServerRessouceName, cdiLabel, apiServerRessouceName, apiServerRessouceName, imagePullSecrets, 1, infraNodePlacement)
if priorityClassName != "" {
deployment.Spec.Template.Spec.PriorityClassName = priorityClassName
}

View File

@ -50,6 +50,7 @@ func createControllerResources(args *FactoryArgs) []client.Object {
args.UploadServerImage,
args.Verbosity,
args.PullPolicy,
args.ImagePullSecrets,
args.PriorityClassName,
args.InfraNodePlacement),
createInsecureRegConfigMap(),
@ -161,9 +162,9 @@ func createControllerServiceAccount() *corev1.ServiceAccount {
return utils.ResourceBuilder.CreateServiceAccount(common.ControllerServiceAccountName)
}
func createControllerDeployment(controllerImage, importerImage, clonerImage, uploadServerImage, verbosity, pullPolicy, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
func createControllerDeployment(controllerImage, importerImage, clonerImage, uploadServerImage, verbosity, pullPolicy string, imagePullSecrets []corev1.LocalObjectReference, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
defaultMode := corev1.ConfigMapVolumeSourceDefaultMode
deployment := utils.CreateDeployment(controllerResourceName, "app", "containerized-data-importer", common.ControllerServiceAccountName, int32(1), infraNodePlacement)
deployment := utils.CreateDeployment(controllerResourceName, "app", "containerized-data-importer", common.ControllerServiceAccountName, imagePullSecrets, int32(1), infraNodePlacement)
if priorityClassName != "" {
deployment.Spec.Template.Spec.PriorityClassName = priorityClassName
}

View File

@ -19,6 +19,7 @@ package namespaced
import (
"fmt"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -39,6 +40,7 @@ type FactoryArgs struct {
UploadServerImage string `required:"true" split_words:"true"`
Verbosity string `required:"true"`
PullPolicy string `required:"true" split_words:"true"`
ImagePullSecrets []corev1.LocalObjectReference
PriorityClassName string
Namespace string
InfraNodePlacement *sdkapi.NodePlacement

View File

@ -39,7 +39,7 @@ func createUploadProxyResources(args *FactoryArgs) []client.Object {
createUploadProxyService(),
createUploadProxyRoleBinding(),
createUploadProxyRole(),
createUploadProxyDeployment(args.UploadProxyImage, args.Verbosity, args.PullPolicy, args.PriorityClassName, args.InfraNodePlacement),
createUploadProxyDeployment(args.UploadProxyImage, args.Verbosity, args.PullPolicy, args.ImagePullSecrets, args.PriorityClassName, args.InfraNodePlacement),
}
}
@ -84,9 +84,9 @@ func createUploadProxyRole() *rbacv1.Role {
return utils.ResourceBuilder.CreateRole(uploadProxyResourceName, rules)
}
func createUploadProxyDeployment(image, verbosity, pullPolicy, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
func createUploadProxyDeployment(image, verbosity, pullPolicy string, imagePullSecrets []corev1.LocalObjectReference, priorityClassName string, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
defaultMode := corev1.ConfigMapVolumeSourceDefaultMode
deployment := utils.CreateDeployment(uploadProxyResourceName, cdiLabel, uploadProxyResourceName, uploadProxyResourceName, int32(1), infraNodePlacement)
deployment := utils.CreateDeployment(uploadProxyResourceName, cdiLabel, uploadProxyResourceName, uploadProxyResourceName, imagePullSecrets, int32(1), infraNodePlacement)
if priorityClassName != "" {
deployment.Spec.Template.Spec.PriorityClassName = priorityClassName
}

View File

@ -20,6 +20,7 @@ import (
"fmt"
csvv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
corev1 "k8s.io/api/core/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -60,6 +61,7 @@ type ClusterServiceVersionData struct {
ReplacesCsvVersion string
Namespace string
ImagePullPolicy string
ImagePullSecrets []corev1.LocalObjectReference
IconBase64 string
Verbosity string

View File

@ -290,7 +290,8 @@ func createDeployment(args *FactoryArgs) []client.Object {
args.NamespacedArgs.UploadProxyImage,
args.NamespacedArgs.UploadServerImage,
args.NamespacedArgs.Verbosity,
args.NamespacedArgs.PullPolicy),
args.NamespacedArgs.PullPolicy,
args.NamespacedArgs.ImagePullSecrets),
createOperatorLeaderElectionConfigMap(args.NamespacedArgs.Namespace),
}
}
@ -324,6 +325,7 @@ func createCDIListCRD() *extv1.CustomResourceDefinition {
}
func createOperatorEnvVar(operatorVersion, deployClusterResources, operatorImage, controllerImage, importerImage, clonerImage, apiServerImage, uploadProxyImage, uploadServerImage, verbosity, pullPolicy string) []corev1.EnvVar {
return []corev1.EnvVar{
{
Name: "DEPLOY_CLUSTER_RESOURCES",
@ -372,8 +374,8 @@ func createOperatorEnvVar(operatorVersion, deployClusterResources, operatorImage
}
}
func createOperatorDeployment(operatorVersion, namespace, deployClusterResources, operatorImage, controllerImage, importerImage, clonerImage, apiServerImage, uploadProxyImage, uploadServerImage, verbosity, pullPolicy string) *appsv1.Deployment {
deployment := utils.CreateOperatorDeployment("cdi-operator", namespace, "name", "cdi-operator", serviceAccountName, int32(1))
func createOperatorDeployment(operatorVersion, namespace, deployClusterResources, operatorImage, controllerImage, importerImage, clonerImage, apiServerImage, uploadProxyImage, uploadServerImage, verbosity, pullPolicy string, imagePullSecrets []corev1.LocalObjectReference) *appsv1.Deployment {
deployment := utils.CreateOperatorDeployment("cdi-operator", namespace, "name", "cdi-operator", serviceAccountName, imagePullSecrets, int32(1))
container := utils.CreatePortsContainer("cdi-operator", operatorImage, pullPolicy, createPrometheusPorts())
container.Resources = corev1.ResourceRequirements{
Requests: corev1.ResourceList{
@ -431,7 +433,8 @@ _The CDI Operator does not support updates yet._
data.UplodaProxyImage,
data.UplodaServerImage,
data.Verbosity,
data.ImagePullPolicy)
data.ImagePullPolicy,
data.ImagePullSecrets)
deployment.Spec.Template.Spec.PriorityClassName = utils.CDIPriorityClass

View File

@ -87,23 +87,26 @@ func CreatePortsContainer(name, image, pullPolicy string, ports []corev1.Contain
}
// CreateDeployment creates deployment
func CreateDeployment(name, matchKey, matchValue, serviceAccountName string, replicas int32, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
func CreateDeployment(name, matchKey, matchValue, serviceAccountName string, imagePullSecrets []corev1.LocalObjectReference, replicas int32, infraNodePlacement *sdkapi.NodePlacement) *appsv1.Deployment {
podSpec := corev1.PodSpec{
SecurityContext: &corev1.PodSecurityContext{
RunAsNonRoot: &[]bool{true}[0],
},
ImagePullSecrets: imagePullSecrets,
}
deployment := ResourceBuilder.CreateDeployment(name, "", matchKey, matchValue, serviceAccountName, replicas, podSpec, infraNodePlacement)
return deployment
}
// CreateOperatorDeployment creates operator deployment
func CreateOperatorDeployment(name, namespace, matchKey, matchValue, serviceAccount string, numReplicas int32) *appsv1.Deployment {
func CreateOperatorDeployment(name, namespace, matchKey, matchValue, serviceAccount string, imagePullSecrets []corev1.LocalObjectReference, numReplicas int32) *appsv1.Deployment {
podSpec := corev1.PodSpec{
SecurityContext: &corev1.PodSecurityContext{
RunAsNonRoot: &[]bool{true}[0],
},
NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
ImagePullSecrets: imagePullSecrets,
NodeSelector: map[string]string{"kubernetes.io/os": "linux"},
Tolerations: []corev1.Toleration{
{
Key: "CriticalAddonsOnly",

View File

@ -775,6 +775,8 @@ type CDIConfigSpec struct {
DataVolumeTTLSeconds *int32 `json:"dataVolumeTTLSeconds,omitempty"`
// TLSSecurityProfile is used by operators to apply cluster-wide TLS security settings to operands.
TLSSecurityProfile *ocpconfigv1.TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"`
// The imagePullSecrets used to pull the container images
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
}
// CDIConfigStatus provides the most recently observed status of the CDI Config resource
@ -792,6 +794,8 @@ type CDIConfigStatus struct {
FilesystemOverhead *FilesystemOverhead `json:"filesystemOverhead,omitempty"`
// Preallocation controls whether storage for DataVolumes should be allocated in advance.
Preallocation bool `json:"preallocation,omitempty"`
// The imagePullSecrets used to pull the container images
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
}
// CDIConfigList provides the needed parameters to do request a list of CDIConfigs from the system

View File

@ -376,6 +376,7 @@ func (CDIConfigSpec) SwaggerDoc() map[string]string {
"insecureRegistries": "InsecureRegistries is a list of TLS disabled registries",
"dataVolumeTTLSeconds": "DataVolumeTTLSeconds is the time in seconds after DataVolume completion it can be garbage collected. The default is 0 sec. To disable GC use -1.\n+optional",
"tlsSecurityProfile": "TLSSecurityProfile is used by operators to apply cluster-wide TLS security settings to operands.",
"imagePullSecrets": "The imagePullSecrets used to pull the container images",
}
}
@ -388,6 +389,7 @@ func (CDIConfigStatus) SwaggerDoc() map[string]string {
"defaultPodResourceRequirements": "ResourceRequirements describes the compute resource requirements.",
"filesystemOverhead": "FilesystemOverhead describes the space reserved for overhead when using Filesystem volumes. A percentage value is between 0 and 1",
"preallocation": "Preallocation controls whether storage for DataVolumes should be allocated in advance.",
"imagePullSecrets": "The imagePullSecrets used to pull the container images",
}
}

View File

@ -196,6 +196,11 @@ func (in *CDIConfigSpec) DeepCopyInto(out *CDIConfigSpec) {
*out = new(configv1.TLSSecurityProfile)
(*in).DeepCopyInto(*out)
}
if in.ImagePullSecrets != nil {
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
*out = make([]v1.LocalObjectReference, len(*in))
copy(*out, *in)
}
return
}
@ -232,6 +237,11 @@ func (in *CDIConfigStatus) DeepCopyInto(out *CDIConfigStatus) {
*out = new(FilesystemOverhead)
(*in).DeepCopyInto(*out)
}
if in.ImagePullSecrets != nil {
in, out := &in.ImagePullSecrets, &out.ImagePullSecrets
*out = make([]v1.LocalObjectReference, len(*in))
copy(*out, *in)
}
return
}