From 1c46464eaa72599630292132366b154c0a9367d2 Mon Sep 17 00:00:00 2001 From: Steve Kuznetsov Date: Thu, 7 Sep 2023 11:24:03 -0600 Subject: [PATCH] controller/registry: implement content extraction for catalog sources Signed-off-by: Steve Kuznetsov --- .../0000_50_olm_00-catalogsources.crd.yaml | 14 +- pkg/controller/operators/catalog/operator.go | 2 +- .../operators/catalog/operator_test.go | 4 +- .../registry/reconciler/configmap.go | 2 +- .../registry/reconciler/configmap_test.go | 2 +- pkg/controller/registry/reconciler/grpc.go | 8 +- .../registry/reconciler/grpc_test.go | 4 +- .../registry/reconciler/reconciler.go | 42 +++- .../registry/reconciler/reconciler_test.go | 188 +++++++++++++++++- 9 files changed, 247 insertions(+), 19 deletions(-) diff --git a/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml b/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml index f678b426c3f..4544665cd11 100644 --- a/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml +++ b/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml @@ -532,8 +532,20 @@ spec: topologyKey: description: This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching the labelSelector in the specified namespaces, where co-located is defined as running on a node whose value of the label with key topologyKey matches that of any node on which any of the selected pods is running. Empty topologyKey is not allowed. type: string + extractContent: + description: ExtractContent configures the gRPC catalog Pod to extract catalog metadata from the provided index image and use a well-known version of the `opm` server to expose it. The catalog index image that this CatalogSource is configured to use *must* be using the file-based catalogs in order to utilize this feature. + type: object + required: + - configDir + properties: + cacheDir: + description: CacheDir is the directory storing the pre-calculated API cache. + type: string + configDir: + description: ConfigDir is the directory storing the file-based catalog contents. + type: string memoryTarget: - description: "MemoryTarget configures the $GOMEMLIMIT value for the gRPC catalog Pod. This is a soft memory limit for the server, which the runtime will attempt to meet but makes no guarantees that it will do so. If this value is set, the Pod will have the following modifications made to the container running the server: - the $GOMEMLIMIT environment variable will be set to this value in bytes - the memory request will be set to this value - the memory limit will be set to 200% of this value \n This field should be set if it's desired to reduce the footprint of a catalog server as much as possible, or if a catalog being served is very large and needs more than the default allocation. If your index image has a file- system cache, determine a good approximation for this value by doubling the size of the package cache at /tmp/cache/cache/packages.json in the index image. \n This field is best-effort; if unset, no default will be used and no Pod memory limit or $GOMEMLIMIT value will be set." + description: "MemoryTarget configures the $GOMEMLIMIT value for the gRPC catalog Pod. This is a soft memory limit for the server, which the runtime will attempt to meet but makes no guarantees that it will do so. If this value is set, the Pod will have the following modifications made to the container running the server: - the $GOMEMLIMIT environment variable will be set to this value in bytes - the memory request will be set to this value \n This field should be set if it's desired to reduce the footprint of a catalog server as much as possible, or if a catalog being served is very large and needs more than the default allocation. If your index image has a file- system cache, determine a good approximation for this value by doubling the size of the package cache at /tmp/cache/cache/packages.json in the index image. \n This field is best-effort; if unset, no default will be used and no Pod memory limit or $GOMEMLIMIT value will be set." pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ anyOf: - type: integer diff --git a/pkg/controller/operators/catalog/operator.go b/pkg/controller/operators/catalog/operator.go index 2904c10c38b..5b056e58eaf 100644 --- a/pkg/controller/operators/catalog/operator.go +++ b/pkg/controller/operators/catalog/operator.go @@ -217,7 +217,7 @@ func NewOperator(ctx context.Context, kubeconfigPath string, clock utilclock.Clo op.sources = grpc.NewSourceStore(logger, 10*time.Second, 10*time.Minute, op.syncSourceState) op.sourceInvalidator = resolver.SourceProviderFromRegistryClientProvider(op.sources, logger) resolverSourceProvider := NewOperatorGroupToggleSourceProvider(op.sourceInvalidator, logger, op.lister.OperatorsV1().OperatorGroupLister()) - op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now, ssaClient, workloadUserID) + op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, opClient, configmapRegistryImage, op.now, ssaClient, workloadUserID, opmImage) res := resolver.NewOperatorStepResolver(lister, crClient, operatorNamespace, resolverSourceProvider, logger) op.resolver = resolver.NewInstrumentedResolver(res, metrics.RegisterDependencyResolutionSuccess, metrics.RegisterDependencyResolutionFailure) diff --git a/pkg/controller/operators/catalog/operator_test.go b/pkg/controller/operators/catalog/operator_test.go index 2da59792850..b894e6d94d8 100644 --- a/pkg/controller/operators/catalog/operator_test.go +++ b/pkg/controller/operators/catalog/operator_test.go @@ -1773,7 +1773,7 @@ func NewFakeOperator(ctx context.Context, namespace string, namespaces []string, } applier := controllerclient.NewFakeApplier(s, "testowner") - op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now, applier, 1001) + op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now, applier, 1001, "") } op.RunInformers(ctx) @@ -1929,7 +1929,7 @@ func toManifest(t *testing.T, obj runtime.Object) string { } func pod(s v1alpha1.CatalogSource) *corev1.Pod { - pod := reconciler.Pod(&s, "registry-server", s.Spec.Image, s.GetName(), s.GetLabels(), s.GetAnnotations(), 5, 10, 1001) + pod := reconciler.Pod(&s, "registry-server", "ocp-payload-opm", s.Spec.Image, s.GetName(), s.GetLabels(), s.GetAnnotations(), 5, 10, 1001) ownerutil.AddOwner(pod, &s, false, true) return pod } diff --git a/pkg/controller/registry/reconciler/configmap.go b/pkg/controller/registry/reconciler/configmap.go index a4aee1c2f04..7e5a6cdd316 100644 --- a/pkg/controller/registry/reconciler/configmap.go +++ b/pkg/controller/registry/reconciler/configmap.go @@ -106,7 +106,7 @@ func (s *configMapCatalogSourceDecorator) Service() *corev1.Service { } func (s *configMapCatalogSourceDecorator) Pod(image string) *corev1.Pod { - pod := Pod(s.CatalogSource, "configmap-registry-server", image, "", s.Labels(), s.Annotations(), 5, 5, s.runAsUser) + pod := Pod(s.CatalogSource, "configmap-registry-server", image, "", "", s.Labels(), s.Annotations(), 5, 5, s.runAsUser) pod.Spec.ServiceAccountName = s.GetName() + ConfigMapServerPostfix pod.Spec.Containers[0].Command = []string{"configmap-server", "-c", s.Spec.ConfigMap, "-n", s.GetNamespace()} ownerutil.AddOwner(pod, s.CatalogSource, false, true) diff --git a/pkg/controller/registry/reconciler/configmap_test.go b/pkg/controller/registry/reconciler/configmap_test.go index 281217a1bfa..e9d987bf9cc 100644 --- a/pkg/controller/registry/reconciler/configmap_test.go +++ b/pkg/controller/registry/reconciler/configmap_test.go @@ -198,7 +198,7 @@ func objectsForCatalogSource(catsrc *v1alpha1.CatalogSource) []runtime.Object { ) case v1alpha1.SourceTypeGrpc: if catsrc.Spec.Image != "" { - decorated := grpcCatalogSourceDecorator{catsrc, runAsUser} + decorated := grpcCatalogSourceDecorator{CatalogSource: catsrc, createPodAsUser: runAsUser, opmImage: ""} objs = clientfake.AddSimpleGeneratedNames( decorated.Pod(catsrc.GetName()), decorated.Service(), diff --git a/pkg/controller/registry/reconciler/grpc.go b/pkg/controller/registry/reconciler/grpc.go index 31e87bccb54..68fb9e7ee27 100644 --- a/pkg/controller/registry/reconciler/grpc.go +++ b/pkg/controller/registry/reconciler/grpc.go @@ -35,6 +35,7 @@ const ( type grpcCatalogSourceDecorator struct { *v1alpha1.CatalogSource createPodAsUser int64 + opmImage string } type UpdateNotReadyErr struct { @@ -128,7 +129,7 @@ func (s *grpcCatalogSourceDecorator) ServiceAccount() *corev1.ServiceAccount { } func (s *grpcCatalogSourceDecorator) Pod(saName string) *corev1.Pod { - pod := Pod(s.CatalogSource, "registry-server", s.Spec.Image, saName, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser) + pod := Pod(s.CatalogSource, "registry-server", s.opmImage, s.Spec.Image, saName, s.Labels(), s.Annotations(), 5, 10, s.createPodAsUser) ownerutil.AddOwner(pod, s.CatalogSource, false, true) return pod } @@ -139,6 +140,7 @@ type GrpcRegistryReconciler struct { OpClient operatorclient.ClientInterface SSAClient *controllerclient.ServerSideApplier createPodAsUser int64 + opmImage string } var _ RegistryReconciler = &GrpcRegistryReconciler{} @@ -205,7 +207,7 @@ func (c *GrpcRegistryReconciler) currentPodsWithCorrectImageAndSpec(source grpcC // EnsureRegistryServer ensures that all components of registry server are up to date. func (c *GrpcRegistryReconciler) EnsureRegistryServer(catalogSource *v1alpha1.CatalogSource) error { - source := grpcCatalogSourceDecorator{catalogSource, c.createPodAsUser} + source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage} // if service status is nil, we force create every object to ensure they're created the first time overwrite := source.Status.RegistryServiceStatus == nil || !isRegistryServiceStatusValid(&source) @@ -454,7 +456,7 @@ func (c *GrpcRegistryReconciler) removePods(pods []*corev1.Pod, namespace string // CheckRegistryServer returns true if the given CatalogSource is considered healthy; false otherwise. func (c *GrpcRegistryReconciler) CheckRegistryServer(catalogSource *v1alpha1.CatalogSource) (healthy bool, err error) { - source := grpcCatalogSourceDecorator{catalogSource, c.createPodAsUser} + source := grpcCatalogSourceDecorator{CatalogSource: catalogSource, createPodAsUser: c.createPodAsUser, opmImage: c.opmImage} // Check on registry resources // TODO: add gRPC health check if len(c.currentPodsWithCorrectImageAndSpec(source, source.ServiceAccount().GetName())) < 1 || diff --git a/pkg/controller/registry/reconciler/grpc_test.go b/pkg/controller/registry/reconciler/grpc_test.go index 2a8d69a5953..94298170d33 100644 --- a/pkg/controller/registry/reconciler/grpc_test.go +++ b/pkg/controller/registry/reconciler/grpc_test.go @@ -355,7 +355,7 @@ func TestGrpcRegistryReconciler(t *testing.T) { } // Check for resource existence - decorated := grpcCatalogSourceDecorator{tt.in.catsrc, runAsUser} + decorated := grpcCatalogSourceDecorator{CatalogSource: tt.in.catsrc, createPodAsUser: runAsUser} pod := decorated.Pod(tt.in.catsrc.GetName()) service := decorated.Service() sa := decorated.ServiceAccount() @@ -445,7 +445,7 @@ func TestRegistryPodPriorityClass(t *testing.T) { require.NoError(t, err) // Check for resource existence - decorated := grpcCatalogSourceDecorator{tt.in.catsrc, runAsUser} + decorated := grpcCatalogSourceDecorator{CatalogSource: tt.in.catsrc, createPodAsUser: runAsUser} pod := decorated.Pod(tt.in.catsrc.GetName()) listOptions := metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labels.Set{CatalogSourceLabelKey: tt.in.catsrc.GetName()}).String()} outPods, podErr := client.KubernetesInterface().CoreV1().Pods(pod.GetNamespace()).List(context.TODO(), listOptions) diff --git a/pkg/controller/registry/reconciler/reconciler.go b/pkg/controller/registry/reconciler/reconciler.go index 1fe786c692d..4005b43ba6f 100644 --- a/pkg/controller/registry/reconciler/reconciler.go +++ b/pkg/controller/registry/reconciler/reconciler.go @@ -4,6 +4,7 @@ package reconciler import ( "fmt" "hash/fnv" + "path/filepath" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" corev1 "k8s.io/api/core/v1" @@ -64,6 +65,7 @@ type registryReconcilerFactory struct { ConfigMapServerImage string SSAClient *controllerclient.ServerSideApplier createPodAsUser int64 + opmImage string } // ReconcilerForSource returns a RegistryReconciler based on the configuration of the given CatalogSource. @@ -86,6 +88,7 @@ func (r *registryReconcilerFactory) ReconcilerForSource(source *operatorsv1alpha OpClient: r.OpClient, SSAClient: r.SSAClient, createPodAsUser: r.createPodAsUser, + opmImage: r.opmImage, } } else if source.Spec.Address != "" { return &GrpcAddressRegistryReconciler{ @@ -97,7 +100,7 @@ func (r *registryReconcilerFactory) ReconcilerForSource(source *operatorsv1alpha } // NewRegistryReconcilerFactory returns an initialized RegistryReconcilerFactory. -func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient operatorclient.ClientInterface, configMapServerImage string, now nowFunc, ssaClient *controllerclient.ServerSideApplier, createPodAsUser int64) RegistryReconcilerFactory { +func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient operatorclient.ClientInterface, configMapServerImage string, now nowFunc, ssaClient *controllerclient.ServerSideApplier, createPodAsUser int64, opmImage string) RegistryReconcilerFactory { return ®istryReconcilerFactory{ now: now, Lister: lister, @@ -105,10 +108,11 @@ func NewRegistryReconcilerFactory(lister operatorlister.OperatorLister, opClient ConfigMapServerImage: configMapServerImage, SSAClient: ssaClient, createPodAsUser: createPodAsUser, + opmImage: opmImage, } } -func Pod(source *operatorsv1alpha1.CatalogSource, name string, img string, saName string, labels map[string]string, annotations map[string]string, readinessDelay int32, livenessDelay int32, runAsUser int64) *corev1.Pod { +func Pod(source *operatorsv1alpha1.CatalogSource, name string, opmImg, img string, saName string, labels map[string]string, annotations map[string]string, readinessDelay int32, livenessDelay int32, runAsUser int64) *corev1.Pod { // make a copy of the labels and annotations to avoid mutating the input parameters podLabels := make(map[string]string) podAnnotations := make(map[string]string) @@ -236,6 +240,40 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, img string, saNam Value: grpcPodConfig.MemoryTarget.String() + "B", // k8s resources use Mi, GOMEMLIMIT wants MiB }) } + + // Reconfigure pod to extract content + if grpcPodConfig.ExtractContent != nil { + pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{ + Name: "catalog-content", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }) + const catalogPath = "/catalog" + volumeMount := corev1.VolumeMount{ + Name: "catalog-content", + MountPath: catalogPath, + } + pod.Spec.InitContainers = append(pod.Spec.InitContainers, corev1.Container{ + Name: "extract-content", + Image: img, + Command: []string{"/bin/sh", "-c"}, + Args: []string{fmt.Sprintf("cp -r %s %s/catalog && cp -r %s %s/cache", + grpcPodConfig.ExtractContent.CatalogDir, catalogPath, + grpcPodConfig.ExtractContent.CacheDir, catalogPath, + )}, + VolumeMounts: []corev1.VolumeMount{volumeMount}, + }) + + pod.Spec.Containers[0].Image = opmImg + pod.Spec.Containers[0].Command = []string{"/bin/opm"} + pod.Spec.Containers[0].Args = []string{ + "serve", + filepath.Join(catalogPath, "catalog"), + "--cache-dir=" + filepath.Join(catalogPath, "cache"), + } + pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, volumeMount) + } } // Set priorityclass if its annotation exists diff --git a/pkg/controller/registry/reconciler/reconciler_test.go b/pkg/controller/registry/reconciler/reconciler_test.go index 7e288338f57..bd84e075401 100644 --- a/pkg/controller/registry/reconciler/reconciler_test.go +++ b/pkg/controller/registry/reconciler/reconciler_test.go @@ -167,7 +167,183 @@ func TestPodMemoryTarget(t *testing.T) { } for _, testCase := range testCases { - pod := Pod(testCase.input, "name", "image", "service-account", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) + pod := Pod(testCase.input, "name", "opmImage", "image", "service-account", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) + if diff := cmp.Diff(pod, testCase.expected); diff != "" { + t.Errorf("got incorrect pod: %v", diff) + } + } +} + +func TestPodExtractContent(t *testing.T) { + var testCases = []struct { + name string + input *v1alpha1.CatalogSource + expected *corev1.Pod + }{ + { + name: "content extraction not requested", + input: &v1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "testns", + }, + }, + expected: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-", + Namespace: "testns", + Labels: map[string]string{"olm.pod-spec-hash": "68d7885bb7", "olm.managed": "true"}, + Annotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "name", + Image: "image", + Ports: []corev1.ContainerPort{{Name: "grpc", ContainerPort: 50051}}, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 5, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 5, + }, + StartupProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + FailureThreshold: 10, + PeriodSeconds: 10, + TimeoutSeconds: 5, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + ReadOnlyRootFilesystem: pointer.Bool(false), + }, + ImagePullPolicy: image.InferImagePullPolicy("image"), + TerminationMessagePolicy: "FallbackToLogsOnError", + }, + }, + NodeSelector: map[string]string{"kubernetes.io/os": "linux"}, + ServiceAccountName: "service-account", + }, + }, + }, + { + name: "content extraction expected", + input: &v1alpha1.CatalogSource{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "testns", + }, + Spec: v1alpha1.CatalogSourceSpec{ + GrpcPodConfig: &v1alpha1.GrpcPodConfig{ + ExtractContent: &v1alpha1.ExtractContentConfig{ + CacheDir: "/tmp/cache", + CatalogDir: "/catalog", + }, + }, + }, + }, + expected: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "test-", + Namespace: "testns", + Labels: map[string]string{"olm.pod-spec-hash": "7cc8fc96f8", "olm.managed": "true"}, + Annotations: map[string]string{"cluster-autoscaler.kubernetes.io/safe-to-evict": "true"}, + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: "catalog-content", + VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}, + }, + }, + InitContainers: []corev1.Container{ + { + Name: "extract-content", + Image: "image", + Command: []string{"/bin/sh", "-c"}, + Args: []string{"cp -r /catalog /catalog/catalog && cp -r /tmp/cache /catalog/cache"}, + VolumeMounts: []corev1.VolumeMount{{Name: "catalog-content", MountPath: "/catalog"}}, + }, + }, + Containers: []corev1.Container{ + { + Name: "name", + Image: "opmImage", + Command: []string{"/bin/opm"}, + Args: []string{"serve", "/catalog/catalog", "--cache-dir=/catalog/cache"}, + Ports: []corev1.ContainerPort{{Name: "grpc", ContainerPort: 50051}}, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 5, + }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 5, + }, + StartupProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"grpc_health_probe", "-addr=:50051"}, + }, + }, + FailureThreshold: 10, + PeriodSeconds: 10, + TimeoutSeconds: 5, + }, + Resources: corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("50Mi"), + }, + }, + SecurityContext: &corev1.SecurityContext{ + ReadOnlyRootFilesystem: pointer.Bool(false), + }, + ImagePullPolicy: image.InferImagePullPolicy("image"), + TerminationMessagePolicy: "FallbackToLogsOnError", + VolumeMounts: []corev1.VolumeMount{{Name: "catalog-content", MountPath: "/catalog"}}, + }, + }, + NodeSelector: map[string]string{"kubernetes.io/os": "linux"}, + ServiceAccountName: "service-account", + }, + }, + }, + } + + for _, testCase := range testCases { + pod := Pod(testCase.input, "name", "opmImage", "image", "service-account", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) if diff := cmp.Diff(pod, testCase.expected); diff != "" { t.Errorf("got incorrect pod: %v", diff) } @@ -185,7 +361,7 @@ func TestPodNodeSelector(t *testing.T) { key := "kubernetes.io/os" value := "linux" - gotCatSrcPod := Pod(catsrc, "hello", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) + gotCatSrcPod := Pod(catsrc, "hello", "opmImage", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) gotCatSrcPodSelector := gotCatSrcPod.Spec.NodeSelector if gotCatSrcPodSelector[key] != value { @@ -233,7 +409,7 @@ func TestPullPolicy(t *testing.T) { } for _, tt := range table { - p := Pod(source, "catalog", tt.image, "", nil, nil, int32(0), int32(0), int64(workloadUserID)) + p := Pod(source, "catalog", "opmImage", tt.image, "", nil, nil, int32(0), int32(0), int64(workloadUserID)) policy := p.Spec.Containers[0].ImagePullPolicy if policy != tt.policy { t.Fatalf("expected pull policy %s for image %s", tt.policy, tt.image) @@ -345,7 +521,7 @@ func TestPodContainerSecurityContext(t *testing.T) { }, } for _, testcase := range testcases { - outputPod := Pod(testcase.inputCatsrc, "hello", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) + outputPod := Pod(testcase.inputCatsrc, "hello", "opmImage", "busybox", "", map[string]string{}, map[string]string{}, int32(0), int32(0), int64(workloadUserID)) if testcase.expectedSecurityContext != nil { require.Equal(t, testcase.expectedSecurityContext, outputPod.Spec.SecurityContext) } @@ -375,7 +551,7 @@ func TestPodAvoidsConcurrentWrite(t *testing.T) { "annotation": "somethingelse", } - gotPod := Pod(catsrc, "hello", "busybox", "", labels, annotations, int32(0), int32(0), int64(workloadUserID)) + gotPod := Pod(catsrc, "hello", "opmImage", "busybox", "", labels, annotations, int32(0), int32(0), int64(workloadUserID)) // check labels and annotations point to different addresses between parameters and what's in the pod require.NotEqual(t, &labels, &gotPod.Labels) @@ -604,7 +780,7 @@ func TestPodSchedulingOverrides(t *testing.T) { } for _, testCase := range testCases { - pod := Pod(testCase.catalogSource, "hello", "busybox", "", map[string]string{}, testCase.annotations, int32(0), int32(0), int64(workloadUserID)) + pod := Pod(testCase.catalogSource, "hello", "opmImage", "busybox", "", map[string]string{}, testCase.annotations, int32(0), int32(0), int64(workloadUserID)) require.Equal(t, testCase.expectedNodeSelectors, pod.Spec.NodeSelector) require.Equal(t, testCase.expectedPriorityClassName, pod.Spec.PriorityClassName) require.Equal(t, testCase.expectedTolerations, pod.Spec.Tolerations)