Skip to content

Commit 91ef628

Browse files
author
bowenislandsong
committed
Update PkgManifest upon catsrc update
The catsrc update sync triggered by the informer does not update pkgmanifest. This commit adds an update mechanism.
1 parent fd7b441 commit 91ef628

File tree

2 files changed

+225
-85
lines changed

2 files changed

+225
-85
lines changed

pkg/package-server/provider/registry.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"sync"
1010
"time"
1111

12-
"github.com/operator-framework/operator-registry/pkg/api"
1312
"github.com/sirupsen/logrus"
1413
"google.golang.org/grpc"
1514
"google.golang.org/grpc/connectivity"
@@ -29,6 +28,7 @@ import (
2928
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/queueinformer"
3029
"github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/apis/operators"
3130
pkglisters "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/listers/operators/internalversion"
31+
"github.com/operator-framework/operator-registry/pkg/api"
3232
)
3333

3434
const (
@@ -189,9 +189,17 @@ func (p *RegistryProvider) syncCatalogSource(obj interface{}) (syncError error)
189189
Namespace: source.GetNamespace(),
190190
Name: source.GetName(),
191191
}
192+
192193
if sourceMeta := p.sources.GetMeta(key); sourceMeta != nil && sourceMeta.Address == address {
193-
// If the address hasn't changed, don't bother creating a new source
194-
logger.Debug("catalog address unchanged, skipping source creation")
194+
logger.Infof("updating PackageManifest based on CatalogSource changes: %v", key)
195+
timeout, cancel := context.WithTimeout(context.Background(), cacheTimeout)
196+
defer cancel()
197+
var client *registryClient
198+
client, syncError = p.registryClient(key)
199+
if syncError != nil {
200+
return
201+
}
202+
syncError = p.refreshCache(timeout, client)
195203
return
196204
}
197205

test/e2e/packagemanifest_e2e_test.go

Lines changed: 214 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package e2e
22

33
import (
4-
"testing"
5-
"time"
4+
"context"
5+
"encoding/json"
66

77
"github.com/blang/semver"
88
"github.com/stretchr/testify/require"
@@ -17,15 +17,222 @@ import (
1717
pmversioned "github.com/operator-framework/operator-lifecycle-manager/pkg/package-server/client/clientset/versioned"
1818
)
1919

20+
var _ = Describe("Package Manifest API lists available Operators from Catalog Sources", func() {
21+
22+
var (
23+
crc versioned.Interface
24+
pmc pmversioned.Interface
25+
c operatorclient.ClientInterface
26+
)
27+
BeforeEach(func() {
28+
crc = newCRClient()
29+
pmc = newPMClient()
30+
c = newKubeClient()
31+
})
32+
33+
AfterEach(func() {
34+
cleaner.NotifyTestComplete(true)
35+
})
36+
37+
Context("Given a CatalogSource created using the ConfigMap as catalog source type", func() {
38+
39+
var (
40+
packageName string
41+
packageStable string
42+
cleanupCatalogSource cleanupFunc
43+
csvJSON []byte
44+
csv v1alpha1.ClusterServiceVersion
45+
catsrcName string
46+
)
47+
BeforeEach(func() {
48+
49+
// create a simple catalogsource
50+
packageName = genName("nginx")
51+
stableChannel := "stable"
52+
packageStable = packageName + "-stable"
53+
manifests := []registry.PackageManifest{
54+
{
55+
PackageName: packageName,
56+
Channels: []registry.PackageChannel{
57+
{Name: stableChannel, CurrentCSVName: packageStable},
58+
},
59+
DefaultChannelName: stableChannel,
60+
},
61+
}
62+
63+
crdPlural := genName("ins")
64+
crd := newCRD(crdPlural)
65+
catsrcName = genName("mock-ocs")
66+
namedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil)
67+
csv = newCSV(packageStable, testNamespace, "", semver.MustParse("0.1.0"), []apiextensions.CustomResourceDefinition{crd}, nil, namedStrategy)
68+
csv.SetLabels(map[string]string{"projected": "label"})
69+
csv.Spec.Keywords = []string{"foo", "bar"}
70+
csv.Spec.Links = []v1alpha1.AppLink{
71+
{
72+
Name: "foo",
73+
URL: "example.com",
74+
},
75+
}
76+
csv.Spec.Maintainers = []v1alpha1.Maintainer{
77+
{
78+
Name: "foo",
79+
80+
},
81+
}
82+
csv.Spec.Maturity = "foo"
83+
csv.Spec.NativeAPIs = []metav1.GroupVersionKind{{Group: "kubenative.io", Version: "v1", Kind: "Native"}}
84+
85+
var err error
86+
csvJSON, err = json.Marshal(csv)
87+
Expect(err).ToNot(HaveOccurred())
88+
89+
_, cleanupCatalogSource = createInternalCatalogSource(c, crc, catsrcName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csv})
90+
91+
// Verify catalog source was created
92+
_, err = fetchCatalogSourceOnStatus(crc, catsrcName, testNamespace, catalogSourceRegistryPodSynced)
93+
Expect(err).ToNot(HaveOccurred())
94+
})
95+
96+
AfterEach(func() {
97+
if cleanupCatalogSource != nil {
98+
cleanupCatalogSource()
99+
}
100+
})
101+
102+
It("retrieves the PackageManifest by package name and validates its fields", func() {
103+
104+
expectedStatus := packagev1.PackageManifestStatus{
105+
CatalogSource: catsrcName,
106+
CatalogSourceNamespace: testNamespace,
107+
PackageName: packageName,
108+
Channels: []packagev1.PackageChannel{
109+
{
110+
Name: stableChannel,
111+
CurrentCSV: packageStable,
112+
CurrentCSVDesc: packagev1.CreateCSVDescription(&csv, string(csvJSON)),
113+
},
114+
},
115+
DefaultChannel: stableChannel,
116+
}
117+
118+
pm, err := fetchPackageManifest(pmc, testNamespace, packageName, packageManifestHasStatus)
119+
Expect(err).ToNot(HaveOccurred(), "error getting package manifest")
120+
Expect(pm).ShouldNot(BeNil())
121+
Expect(pm.GetName()).Should(Equal(packageName))
122+
Expect(pm.Status).Should(Equal(expectedStatus))
123+
Expect(pm.Status.Channels[0].CurrentCSVDesc.MinKubeVersion).Should(Equal("0.0.0"))
124+
Expect(pm.Status.Channels[0].CurrentCSVDesc.RelatedImages[0]).Should(Equal(*dummyImage))
125+
Expect(pm.Status.Channels[0].CurrentCSVDesc.NativeAPIs).Should(Equal(csv.Spec.NativeAPIs))
126+
Expect(pm.GetLabels()["projected"]).Should(Equal("label"))
127+
Expect(pm.GetLabels()["operatorframework.io/arch.amd64"]).Should(Equal("supported"))
128+
Expect(pm.GetLabels()["operatorframework.io/os.linux"]).Should(Equal("supported"))
129+
Expect(pm.Status.Channels[0].CurrentCSVDesc.Keywords).Should(Equal([]string{"foo", "bar"}))
130+
Expect(pm.Status.Channels[0].CurrentCSVDesc.Maturity).Should(Equal("foo"))
131+
Expect(pm.Status.Channels[0].CurrentCSVDesc.Links).Should(Equal([]packagev1.AppLink{{Name: "foo", URL: "example.com"}}))
132+
Expect(pm.Status.Channels[0].CurrentCSVDesc.Maintainers).Should(Equal([]packagev1.Maintainer{{Name: "foo", Email: "[email protected]"}}))
133+
})
134+
It("lists PackageManifest and ensures it has valid PackageManifest item", func() {
135+
// Get a PackageManifestList and ensure it has the correct items
136+
Eventually(func() (bool, error) {
137+
pmList, err := pmc.OperatorsV1().PackageManifests(testNamespace).List(context.TODO(), metav1.ListOptions{})
138+
return containsPackageManifest(pmList.Items, packageName), err
139+
}).Should(BeTrue(), "required package name not found in the list")
140+
})
141+
142+
})
143+
144+
Context("Given a CatalogSource created using gRPC catalog source type", func() {
145+
var (
146+
packageName, displayName string
147+
catalogSource *v1alpha1.CatalogSource
148+
)
149+
BeforeEach(func() {
150+
sourceName := genName("catalog-")
151+
packageName = "etcd-test"
152+
displayName = "etcd test catalog"
153+
image := "quay.io/olmtest/catsrc-update-test:related"
154+
155+
catalogSource = &v1alpha1.CatalogSource{
156+
TypeMeta: metav1.TypeMeta{
157+
Kind: v1alpha1.CatalogSourceKind,
158+
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
159+
},
160+
ObjectMeta: metav1.ObjectMeta{
161+
Name: sourceName,
162+
Namespace: testNamespace,
163+
Labels: map[string]string{"olm.catalogSource": sourceName},
164+
},
165+
Spec: v1alpha1.CatalogSourceSpec{
166+
SourceType: v1alpha1.SourceTypeGrpc,
167+
Image: image,
168+
DisplayName: displayName,
169+
},
170+
}
171+
172+
var err error
173+
catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(catalogSource.GetNamespace()).Create(context.TODO(), catalogSource, metav1.CreateOptions{})
174+
Expect(err).NotTo(HaveOccurred())
175+
})
176+
177+
AfterEach(func() {
178+
err := crc.OperatorsV1alpha1().CatalogSources(catalogSource.GetNamespace()).Delete(context.TODO(), catalogSource.GetName(), metav1.DeleteOptions{})
179+
Expect(err).NotTo(HaveOccurred())
180+
})
181+
182+
It("lists the CatalogSource contents using the PackageManifest API", func() {
183+
184+
pm, err := fetchPackageManifest(pmc, testNamespace, packageName, packageManifestHasStatus)
185+
Expect(err).NotTo(HaveOccurred(), "error getting package manifest")
186+
Expect(pm).ShouldNot(BeNil())
187+
Expect(pm.GetName()).Should(Equal(packageName))
188+
189+
// Verify related images from the package manifest
190+
relatedImages := pm.Status.Channels[0].CurrentCSVDesc.RelatedImages
191+
192+
Expect(relatedImages).To(ConsistOf([]string{
193+
"quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84",
194+
"quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f",
195+
"quay.io/coreos/etcd-operator@sha256:c0301e4686c3ed4206e370b42de5a3bd2229b9fb4906cf85f3f30650424abec2",
196+
}), "Expected images to exist in the related images list\n")
197+
})
198+
199+
When("the display name for catalog source is updated", func() {
200+
201+
BeforeEach(func() {
202+
203+
pm, err := fetchPackageManifest(pmc, testNamespace, packageName, packageManifestHasStatus)
204+
Expect(err).NotTo(HaveOccurred(), "error getting package manifest")
205+
Expect(pm).ShouldNot(BeNil())
206+
Expect(pm.GetName()).Should(Equal(packageName))
207+
Expect(pm.Status.CatalogSourceDisplayName).Should(Equal(displayName))
208+
209+
catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(testNamespace).Get(context.TODO(), catalogSource.GetName(), metav1.GetOptions{})
210+
Expect(err).NotTo(HaveOccurred(), "error getting catalogSource")
211+
212+
displayName = "updated Name"
213+
catalogSource.Spec.DisplayName = displayName
214+
catalogSource, err = crc.OperatorsV1alpha1().CatalogSources(testNamespace).Update(context.TODO(), catalogSource, metav1.UpdateOptions{})
215+
Expect(err).NotTo(HaveOccurred(), "error updating catalogSource")
216+
Expect(catalogSource.Spec.DisplayName).Should(Equal(displayName))
217+
})
218+
It("should successfully update the CatalogSource field", func() {
219+
220+
Eventually(func() string {
221+
pm, err := fetchPackageManifest(pmc, testNamespace, packageName,
222+
packageManifestHasStatus)
223+
Expect(err).NotTo(HaveOccurred(), "error getting package manifest after updating catsrc")
224+
return pm.Status.CatalogSourceDisplayName
225+
}).Should(Equal(displayName))
226+
})
227+
})
228+
})
229+
})
230+
20231
type packageManifestCheckFunc func(*packagev1.PackageManifest) bool
21232

22233
func packageManifestHasStatus(pm *packagev1.PackageManifest) bool {
23234
// as long as it has a package name we consider the status non-empty
24-
if pm == nil || pm.Status.PackageName == "" {
25-
return false
26-
}
27-
28-
return true
235+
return pm != nil && pm.Status.PackageName != ""
29236
}
30237

31238
func fetchPackageManifest(t *testing.T, pmc pmversioned.Interface, namespace, name string, check packageManifestCheckFunc) (*packagev1.PackageManifest, error) {
@@ -43,78 +250,3 @@ func fetchPackageManifest(t *testing.T, pmc pmversioned.Interface, namespace, na
43250

44251
return fetched, err
45252
}
46-
47-
func TestPackageManifestLoading(t *testing.T) {
48-
defer cleaner.NotifyTestComplete(t, true)
49-
50-
// create a simple catalogsource
51-
packageName := genName("nginx")
52-
stableChannel := "stable"
53-
packageStable := packageName + "-stable"
54-
manifests := []registry.PackageManifest{
55-
{
56-
PackageName: packageName,
57-
Channels: []registry.PackageChannel{
58-
{Name: stableChannel, CurrentCSVName: packageStable},
59-
},
60-
DefaultChannelName: stableChannel,
61-
},
62-
}
63-
64-
crdPlural := genName("ins")
65-
crd := newCRD(crdPlural)
66-
catalogSourceName := genName("mock-ocs")
67-
namedStrategy := newNginxInstallStrategy(genName("dep-"), nil, nil)
68-
csv := newCSV(packageStable, testNamespace, "", semver.MustParse("0.1.0"), []apiextensions.CustomResourceDefinition{crd}, nil, namedStrategy)
69-
csv.SetLabels(map[string]string{"projected": "label"})
70-
c := newKubeClient(t)
71-
crc := newCRClient(t)
72-
pmc := newPMClient(t)
73-
74-
expectedStatus := packagev1.PackageManifestStatus{
75-
CatalogSource: catalogSourceName,
76-
CatalogSourceNamespace: testNamespace,
77-
PackageName: packageName,
78-
Channels: []packagev1.PackageChannel{
79-
{
80-
Name: stableChannel,
81-
CurrentCSV: packageStable,
82-
CurrentCSVDesc: packagev1.CreateCSVDescription(&csv),
83-
},
84-
},
85-
DefaultChannel: stableChannel,
86-
}
87-
88-
// Wait for package-server to be ready
89-
err := wait.Poll(pollInterval, 1*time.Minute, func() (bool, error) {
90-
t.Logf("Polling package-server...")
91-
_, err := pmc.OperatorsV1().PackageManifests(testNamespace).List(metav1.ListOptions{})
92-
if err == nil {
93-
return true, nil
94-
}
95-
return false, nil
96-
})
97-
require.NoError(t, err, "package-server not available")
98-
99-
_, cleanupCatalogSource := createInternalCatalogSource(t, c, crc, catalogSourceName, testNamespace, manifests, []apiextensions.CustomResourceDefinition{crd}, []v1alpha1.ClusterServiceVersion{csv})
100-
require.NoError(t, err)
101-
defer cleanupCatalogSource()
102-
103-
_, err = fetchCatalogSource(t, crc, catalogSourceName, testNamespace, catalogSourceRegistryPodSynced)
104-
require.NoError(t, err)
105-
106-
pm, err := fetchPackageManifest(t, pmc, testNamespace, packageName, packageManifestHasStatus)
107-
require.NoError(t, err, "error getting package manifest")
108-
require.NotNil(t, pm)
109-
require.Equal(t, packageName, pm.GetName())
110-
require.Equal(t, expectedStatus, pm.Status)
111-
require.Equal(t, "label", pm.GetLabels()["projected"])
112-
require.Equal(t, "supported", pm.GetLabels()["operatorframework.io/arch.amd64"])
113-
require.Equal(t, "supported", pm.GetLabels()["operatorframework.io/os.linux"])
114-
115-
// Get a PackageManifestList and ensure it has the correct items
116-
pmList, err := pmc.OperatorsV1().PackageManifests(testNamespace).List(metav1.ListOptions{})
117-
require.NoError(t, err, "could not access package manifests list meta")
118-
require.NotNil(t, pmList.ListMeta, "package manifest list metadata empty")
119-
require.NotNil(t, pmList.Items)
120-
}

0 commit comments

Comments
 (0)