Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions internal/rukpak/convert/registryv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,17 +195,17 @@ func Convert(in RegistryV1, installNamespace string, targetNamespaces []string)
for _, depSpec := range in.CSV.Spec.InstallStrategy.StrategySpec.DeploymentSpecs {
annotations := util.MergeMaps(in.CSV.Annotations, depSpec.Spec.Template.Annotations)
annotations["olm.targetNamespaces"] = strings.Join(targetNamespaces, ",")
depSpec.Spec.Template.Annotations = annotations
deployments = append(deployments, appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: "Deployment",
APIVersion: appsv1.SchemeGroupVersion.String(),
},

ObjectMeta: metav1.ObjectMeta{
Namespace: installNamespace,
Name: depSpec.Name,
Labels: depSpec.Label,
Annotations: annotations,
Copy link
Contributor

@camilamacedo86 camilamacedo86 Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@joelanford, I have a quick question: should we not keep the annotations in both places, given that we’re merging other annotations with annotations := util.MergeMaps(in.CSV.Annotations, depSpec.Spec.Template.Annotations)?

Could we not have more annotations ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just trying to match OLMv0's behavior (which I may still not have exactly right, btw. It's complicated). We are also dealing with the etcd size limit, so I don't want to duplicate stuff more than necessary. There is a Subscription.spec.config.annotations in OLMv0 that I think propagates to the deployment's annotations. So once we have the parameterized value stuff design/implemented/supported, users will be able to provide custom annotations.

Copy link
Contributor

@camilamacedo86 camilamacedo86 Nov 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dealing with the etcd size limit
Bit by bit, memories are resurfacing... I remember this

Make sense 👍

Namespace: installNamespace,
Name: depSpec.Name,
Labels: depSpec.Label,
},
Spec: depSpec.Spec,
})
Expand Down
191 changes: 103 additions & 88 deletions internal/rukpak/convert/registryv1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package convert

import (
"fmt"
"strings"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
schedulingv1 "k8s.io/api/scheduling/v1"
Expand Down Expand Up @@ -73,7 +75,7 @@ var _ = Describe("RegistryV1 Suite", func() {
Expect(plainBundle.Objects).To(HaveLen(1))

By("verifying if ns has been set correctly")
resObj := containsObject(unstructuredSvc, plainBundle.Objects)
resObj := findObjectByName(svc.Name, plainBundle.Objects)
Expect(resObj).NotTo(BeNil())
Expect(resObj.GetNamespace()).To(BeEquivalentTo(installNamespace))
})
Expand All @@ -99,7 +101,7 @@ var _ = Describe("RegistryV1 Suite", func() {
Expect(plainBundle.Objects).To(HaveLen(1))

By("verifying if ns has been set correctly")
resObj := containsObject(unstructuredSvc, plainBundle.Objects)
resObj := findObjectByName(svc.Name, plainBundle.Objects)
Expect(resObj).NotTo(BeNil())
Expect(resObj.GetNamespace()).To(BeEquivalentTo(installNamespace))
})
Expand Down Expand Up @@ -157,7 +159,7 @@ var _ = Describe("RegistryV1 Suite", func() {
Expect(plainBundle.Objects).To(HaveLen(1))

By("verifying if ns has been set correctly")
resObj := containsObject(unstructuredpriorityclass, plainBundle.Objects)
resObj := findObjectByName(pc.Name, plainBundle.Objects)
Expect(resObj).NotTo(BeNil())
Expect(resObj.GetNamespace()).To(BeEmpty())
})
Expand All @@ -167,22 +169,39 @@ var _ = Describe("RegistryV1 Suite", func() {
Context("Should generate objects successfully based on target namespaces", func() {
var (
svc corev1.Service
csv v1alpha1.ClusterServiceVersion
baseCSV v1alpha1.ClusterServiceVersion
watchNamespaces []string
)

BeforeEach(func() {
csv = v1alpha1.ClusterServiceVersion{
// base CSV definition that each test case will deep copy and modify
baseCSV = v1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "testCSV",
Annotations: map[string]string{
"olm.properties": fmt.Sprintf("[{\"type\": %s, \"value\": \"%s\"}]", property.TypeConstraint, "value"),
},
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallModes: []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that it was removed because, after the conversion, we expect InstallStrategy, correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the piece of the CSV that I want to configure in each of the test scenarios, so I removed it here and then each test scenario does a deep copy before setting InstallModes for that scenario.

InstallStrategy: v1alpha1.NamedInstallStrategy{
StrategySpec: v1alpha1.StrategyDetailsDeployment{
DeploymentSpecs: []v1alpha1.StrategyDeploymentSpec{
{
Name: "testDeployment",
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "testContainer",
Image: "testImage",
},
},
},
},
},
},
},
Permissions: []v1alpha1.StrategyDeploymentPermissions{
{
ServiceAccountName: "testServiceAccount",
Expand All @@ -199,6 +218,7 @@ var _ = Describe("RegistryV1 Suite", func() {
},
},
}

svc = corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "testService",
Expand All @@ -208,13 +228,16 @@ var _ = Describe("RegistryV1 Suite", func() {
installNamespace = "testInstallNamespace"
})

It("should convert into plain manifests successfully", func() {
It("should convert into plain manifests successfully with AllNamespaces", func() {
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1", "testWatchNs2"}
watchNamespaces = []string{""}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -224,41 +247,51 @@ var _ = Describe("RegistryV1 Suite", func() {

By("verifying if plain bundle has required objects")
Expect(plainBundle).ShouldNot(BeNil())
Expect(plainBundle.Objects).To(HaveLen(6))
Expect(plainBundle.Objects).To(HaveLen(5))

By("verifying olm.targetNamespaces annotation in the deployment's pod template")
dep := findObjectByName("testDeployment", plainBundle.Objects)
Expect(dep).NotTo(BeNil())
Expect(dep.(*appsv1.Deployment).Spec.Template.Annotations).To(HaveKeyWithValue("olm.targetNamespaces", strings.Join(watchNamespaces, ",")))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are checking here the change 👍

})

It("should convert into plain manifests successfully with single namespace", func() {
csv = v1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "testCSV",
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallModes: []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}},
InstallStrategy: v1alpha1.NamedInstallStrategy{
StrategySpec: v1alpha1.StrategyDetailsDeployment{
Permissions: []v1alpha1.StrategyDeploymentPermissions{
{
ServiceAccountName: "testServiceAccount",
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{"test"},
Resources: []string{"pods"},
Verbs: []string{"*"},
},
},
},
},
},
},
},
It("should convert into plain manifests successfully with MultiNamespace", func() {
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1", "testWatchNs2"}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

By("converting to plain")
plainBundle, err := Convert(registryv1Bundle, installNamespace, watchNamespaces)
Expect(err).NotTo(HaveOccurred())

By("verifying if plain bundle has required objects")
Expect(plainBundle).ShouldNot(BeNil())
Expect(plainBundle.Objects).To(HaveLen(7))

By("verifying olm.targetNamespaces annotation in the deployment's pod template")
dep := findObjectByName("testDeployment", plainBundle.Objects)
Expect(dep).NotTo(BeNil())
Expect(dep.(*appsv1.Deployment).Spec.Template.Annotations).To(HaveKeyWithValue("olm.targetNamespaces", strings.Join(watchNamespaces, ",")))
})

It("should convert into plain manifests successfully with SingleNamespace", func() {
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1"}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -268,41 +301,24 @@ var _ = Describe("RegistryV1 Suite", func() {

By("verifying if plain bundle has required objects")
Expect(plainBundle).ShouldNot(BeNil())
Expect(plainBundle.Objects).To(HaveLen(4))
Expect(plainBundle.Objects).To(HaveLen(5))

By("verifying olm.targetNamespaces annotation in the deployment's pod template")
dep := findObjectByName("testDeployment", plainBundle.Objects)
Expect(dep).NotTo(BeNil())
Expect(dep.(*appsv1.Deployment).Spec.Template.Annotations).To(HaveKeyWithValue("olm.targetNamespaces", strings.Join(watchNamespaces, ",")))
})

It("should convert into plain manifests successfully with own namespace", func() {
csv = v1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "testCSV",
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallModes: []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}},
InstallStrategy: v1alpha1.NamedInstallStrategy{
StrategySpec: v1alpha1.StrategyDetailsDeployment{
Permissions: []v1alpha1.StrategyDeploymentPermissions{
{
ServiceAccountName: "testServiceAccount",
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{"test"},
Resources: []string{"pods"},
Verbs: []string{"*"},
},
},
},
},
},
},
},
}
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{installNamespace}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -312,16 +328,24 @@ var _ = Describe("RegistryV1 Suite", func() {

By("verifying if plain bundle has required objects")
Expect(plainBundle).ShouldNot(BeNil())
Expect(plainBundle.Objects).To(HaveLen(4))
Expect(plainBundle.Objects).To(HaveLen(5))

By("verifying olm.targetNamespaces annotation in the deployment's pod template")
dep := findObjectByName("testDeployment", plainBundle.Objects)
Expect(dep).NotTo(BeNil())
Expect(dep.(*appsv1.Deployment).Spec.Template.Annotations).To(HaveKeyWithValue("olm.targetNamespaces", strings.Join(watchNamespaces, ",")))
})

It("should error when multinamespace mode is supported with an empty string in target namespaces", func() {
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1", ""}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -332,21 +356,15 @@ var _ = Describe("RegistryV1 Suite", func() {
})

It("should error when single namespace mode is disabled with more than one target namespaces", func() {
csv = v1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "testCSV",
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallModes: []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}},
},
}
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: false}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1", "testWatchNs2"}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -357,26 +375,20 @@ var _ = Describe("RegistryV1 Suite", func() {
})

It("should error when all namespace mode is disabled with target namespace containing an empty string", func() {
csv = v1alpha1.ClusterServiceVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "testCSV",
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallModes: []v1alpha1.InstallMode{
{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false},
{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true},
{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true},
{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true},
},
},
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{
{Type: v1alpha1.InstallModeTypeAllNamespaces, Supported: false},
{Type: v1alpha1.InstallModeTypeOwnNamespace, Supported: true},
{Type: v1alpha1.InstallModeTypeSingleNamespace, Supported: true},
{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true},
}

By("creating a registry v1 bundle")
watchNamespaces = []string{""}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand All @@ -387,12 +399,15 @@ var _ = Describe("RegistryV1 Suite", func() {
})

It("should propagate csv annotations to chart metadata annotation", func() {
csv := baseCSV.DeepCopy()
csv.Spec.InstallModes = []v1alpha1.InstallMode{{Type: v1alpha1.InstallModeTypeMultiNamespace, Supported: true}}

By("creating a registry v1 bundle")
watchNamespaces = []string{"testWatchNs1", "testWatchNs2"}
unstructuredSvc := convertToUnstructured(svc)
registryv1Bundle = RegistryV1{
PackageName: "testPkg",
CSV: csv,
CSV: *csv,
Others: []unstructured.Unstructured{unstructuredSvc},
}

Expand Down Expand Up @@ -462,11 +477,11 @@ func convertToUnstructured(obj interface{}) unstructured.Unstructured {
return unstructured.Unstructured{Object: unstructuredObj}
}

func containsObject(obj unstructured.Unstructured, result []client.Object) client.Object {
func findObjectByName(name string, result []client.Object) client.Object {
Copy link
Contributor

@camilamacedo86 camilamacedo86 Nov 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sense the change to allow we mock the data like above for testDeployment 👍

for _, o := range result {
// Since this is a controlled env, comparing only the names is sufficient for now.
// In future, compare GVKs too by ensuring its set on the unstructuredObj.
if o.GetName() == obj.GetName() {
if o.GetName() == name {
return o
}
}
Expand Down
Loading