Skip to content

Commit eb3f619

Browse files
bouskaJosmman
authored andcommitted
test: Add OLMv1 test support
1 parent 2b84812 commit eb3f619

File tree

7 files changed

+377
-139
lines changed

7 files changed

+377
-139
lines changed

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ require (
1111
github.com/google/go-containerregistry v0.20.6
1212
github.com/google/trillian v1.7.2
1313
github.com/google/uuid v1.6.0
14-
github.com/onsi/ginkgo/v2 v2.23.4
15-
github.com/onsi/gomega v1.37.0
14+
github.com/onsi/ginkgo/v2 v2.25.1
15+
github.com/onsi/gomega v1.38.2
1616
github.com/openshift/api v0.0.0-20251023193535-8691c3014652
1717
github.com/operator-framework/api v0.35.0
1818
github.com/operator-framework/operator-lib v0.19.0
@@ -30,11 +30,12 @@ require (
3030
)
3131

3232
require (
33+
github.com/Masterminds/semver/v3 v3.4.0 // indirect
3334
github.com/beorn7/perks v1.0.1 // indirect
3435
github.com/cespare/xxhash/v2 v2.3.0 // indirect
3536
github.com/containerd/stargz-snapshotter/estargz v0.18.0 // indirect
3637
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
37-
github.com/docker/cli v28.2.2+incompatible // indirect
38+
github.com/docker/cli v28.3.3+incompatible // indirect
3839
github.com/docker/distribution v2.8.3+incompatible // indirect
3940
github.com/docker/docker-credential-helpers v0.9.4 // indirect
4041
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
@@ -95,7 +96,6 @@ require (
9596
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
9697
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
9798
gopkg.in/inf.v0 v0.9.1 // indirect
98-
gopkg.in/yaml.v3 v3.0.1 // indirect
9999
k8s.io/apiextensions-apiserver v0.34.1 // indirect
100100
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
101101
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect

go.sum

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
2+
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
13
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
24
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
35
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
@@ -12,8 +14,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
1214
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1315
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
1416
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
15-
github.com/docker/cli v28.2.2+incompatible h1:qzx5BNUDFqlvyq4AHzdNB7gSyVTmU4cgsyN9SdInc1A=
16-
github.com/docker/cli v28.2.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
17+
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
18+
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
1719
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
1820
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
1921
github.com/docker/docker-credential-helpers v0.9.4 h1:76ItO69/AP/V4yT9V4uuuItG0B1N8hvt0T0c0NN/DzI=
@@ -113,10 +115,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
113115
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
114116
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
115117
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
116-
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
117-
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
118-
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
119-
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
118+
github.com/onsi/ginkgo/v2 v2.25.1 h1:Fwp6crTREKM+oA6Cz4MsO8RhKQzs2/gOIVOUscMAfZY=
119+
github.com/onsi/ginkgo/v2 v2.25.1/go.mod h1:ppTWQ1dh9KM/F1XgpeRqelR+zHVwV81DGRSDnFxK7Sk=
120+
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
121+
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
120122
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
121123
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
122124
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=

test/e2e/support/common.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ import (
2929
"github.com/onsi/ginkgo/v2"
3030
"github.com/onsi/ginkgo/v2/dsl/core"
3131
. "github.com/onsi/gomega"
32-
olm "github.com/operator-framework/api/pkg/operators/v1"
33-
olmAlpha "github.com/operator-framework/api/pkg/operators/v1alpha1"
3432
"github.com/securesign/operator/api/v1alpha1"
3533
v1 "k8s.io/api/core/v1"
3634
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -52,8 +50,6 @@ func CreateClient() (client.Client, error) {
5250
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
5351
utilruntime.Must(v1alpha1.AddToScheme(scheme))
5452
utilruntime.Must(routev1.AddToScheme(scheme))
55-
utilruntime.Must(olmAlpha.AddToScheme(scheme))
56-
utilruntime.Must(olm.AddToScheme(scheme))
5753

5854
cfg, err := config.GetConfig()
5955
if err != nil {
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package olm
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strconv"
7+
"strings"
8+
9+
olm "github.com/operator-framework/api/pkg/operators/v1"
10+
"github.com/operator-framework/api/pkg/operators/v1alpha1"
11+
coreV1 "k8s.io/api/core/v1"
12+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
13+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
14+
"sigs.k8s.io/controller-runtime/pkg/client"
15+
)
16+
17+
// olm types
18+
type subscriptionExtension struct {
19+
v1alpha1.Subscription
20+
}
21+
22+
func (e *subscriptionExtension) Unwrap() client.Object {
23+
return &e.Subscription
24+
}
25+
26+
func (e *subscriptionExtension) IsReady(ctx context.Context, cli client.Client) bool {
27+
s := e.getInstalledCSV(ctx, cli)
28+
return s != nil
29+
}
30+
31+
func (e *subscriptionExtension) GetVersion(ctx context.Context, cli client.Client) string {
32+
s := e.getInstalledCSV(ctx, cli)
33+
if s == nil {
34+
return ""
35+
}
36+
return s.Spec.Version.String()
37+
38+
}
39+
40+
func (e *subscriptionExtension) getInstalledCSV(ctx context.Context, cli client.Client) *v1alpha1.ClusterServiceVersion {
41+
lst := v1alpha1.ClusterServiceVersionList{}
42+
if err := cli.List(ctx, &lst, client.InNamespace(e.Namespace)); err != nil {
43+
return nil
44+
}
45+
for _, s := range lst.Items {
46+
if strings.Contains(s.Name, e.Name) && s.Status.Phase == v1alpha1.CSVPhaseSucceeded {
47+
return &s
48+
49+
}
50+
}
51+
return nil
52+
}
53+
54+
type catalogSourceWrapper struct {
55+
v1alpha1.CatalogSource
56+
}
57+
58+
func (c *catalogSourceWrapper) Unwrap() client.Object {
59+
return &c.CatalogSource
60+
}
61+
62+
func (c *catalogSourceWrapper) IsReady(ctx context.Context, cli client.Client) bool {
63+
if c.Status.GRPCConnectionState == nil {
64+
return false
65+
}
66+
return c.Status.GRPCConnectionState.LastObservedState == "READY"
67+
}
68+
69+
func (c *catalogSourceWrapper) UpdateSourceImage(s string) {
70+
c.Spec.Image = s
71+
}
72+
73+
func OlmInstaller(ctx context.Context, cli client.Client, catalogImage, ns, packageName, channel string, ocp bool) (Extension, ExtensionSource, error) {
74+
scheme := cli.Scheme()
75+
utilruntime.Must(v1alpha1.AddToScheme(scheme))
76+
utilruntime.Must(olm.AddToScheme(scheme))
77+
78+
og := &olm.OperatorGroup{
79+
ObjectMeta: metav1.ObjectMeta{
80+
Namespace: ns,
81+
Name: packageName,
82+
},
83+
Spec: olm.OperatorGroupSpec{
84+
TargetNamespaces: []string{},
85+
},
86+
}
87+
88+
catalog := &catalogSourceWrapper{
89+
90+
v1alpha1.CatalogSource{
91+
ObjectMeta: metav1.ObjectMeta{
92+
Namespace: ns,
93+
Name: fmt.Sprintf("%s-catalog", packageName),
94+
},
95+
Spec: v1alpha1.CatalogSourceSpec{
96+
Image: catalogImage,
97+
SourceType: "grpc",
98+
DisplayName: "OLM upgrade test Catalog",
99+
Publisher: "grpc",
100+
},
101+
},
102+
}
103+
104+
subscription := &subscriptionExtension{
105+
v1alpha1.Subscription{
106+
ObjectMeta: metav1.ObjectMeta{
107+
Name: packageName,
108+
Namespace: ns,
109+
},
110+
Spec: &v1alpha1.SubscriptionSpec{
111+
CatalogSource: catalog.Name,
112+
CatalogSourceNamespace: catalog.Namespace,
113+
Package: packageName,
114+
Channel: channel,
115+
Config: &v1alpha1.SubscriptionConfig{
116+
Env: []coreV1.EnvVar{
117+
{
118+
Name: "OPENSHIFT",
119+
Value: strconv.FormatBool(ocp),
120+
},
121+
},
122+
},
123+
},
124+
},
125+
}
126+
127+
for _, obj := range []client.Object{catalog.Unwrap(), subscription.Unwrap(), og} {
128+
if err := cli.Create(ctx, obj); client.IgnoreAlreadyExists(err) != nil {
129+
return nil, nil, err
130+
}
131+
}
132+
133+
return subscription, catalog, nil
134+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package olm
2+
3+
import (
4+
"context"
5+
6+
"sigs.k8s.io/controller-runtime/pkg/client"
7+
)
8+
9+
type ExtensionSource interface {
10+
client.Object
11+
IsReady(context.Context, client.Client) bool
12+
UpdateSourceImage(string)
13+
Unwrap() client.Object
14+
}
15+
16+
type Extension interface {
17+
client.Object
18+
IsReady(context.Context, client.Client) bool
19+
GetVersion(context.Context, client.Client) string
20+
Unwrap() client.Object
21+
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package olm
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
coreV1 "k8s.io/api/core/v1"
8+
rbacV1 "k8s.io/api/rbac/v1"
9+
"k8s.io/apimachinery/pkg/api/meta"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
12+
"k8s.io/apimachinery/pkg/util/json"
13+
"sigs.k8s.io/controller-runtime/pkg/client"
14+
)
15+
16+
type clusterExtensionWrapper struct {
17+
*unstructured.Unstructured
18+
}
19+
20+
func (e *clusterExtensionWrapper) Unwrap() client.Object {
21+
return e.Unstructured
22+
}
23+
24+
func (e *clusterExtensionWrapper) IsReady(_ context.Context, _ client.Client) bool {
25+
return meta.IsStatusConditionTrue(conditions(e.Object), "Installed")
26+
}
27+
28+
func (e *clusterExtensionWrapper) GetVersion(_ context.Context, _ client.Client) string {
29+
version, _, _ := unstructured.NestedString(e.Object, "status", "install", "bundle", "version")
30+
return version
31+
}
32+
33+
type clusterCatalogSource struct {
34+
*unstructured.Unstructured
35+
}
36+
37+
func (c *clusterCatalogSource) Unwrap() client.Object {
38+
return c.Unstructured
39+
}
40+
41+
func (c *clusterCatalogSource) IsReady(_ context.Context, _ client.Client) bool {
42+
return meta.IsStatusConditionTrue(conditions(c.Object), "Serving")
43+
}
44+
45+
func (c *clusterCatalogSource) UpdateSourceImage(s string) {
46+
_ = unstructured.SetNestedField(c.Object, s, "spec", "source", "image", "ref")
47+
}
48+
49+
func OlmV1Installer(ctx context.Context, cli client.Client, catalogImage, ns, packageName string) (Extension, ExtensionSource, error) {
50+
sa := &coreV1.ServiceAccount{
51+
ObjectMeta: metav1.ObjectMeta{
52+
Name: fmt.Sprintf("%s-installer", packageName),
53+
Namespace: ns,
54+
},
55+
}
56+
57+
crb := &rbacV1.ClusterRoleBinding{
58+
ObjectMeta: metav1.ObjectMeta{
59+
Name: fmt.Sprintf("%s-installer-%s", packageName, ns),
60+
},
61+
RoleRef: rbacV1.RoleRef{
62+
APIGroup: coreV1.SchemeGroupVersion.Group,
63+
Kind: "ClusterRole",
64+
Name: "cluster-admin",
65+
},
66+
Subjects: []rbacV1.Subject{{Kind: "ServiceAccount", Name: sa.Name, Namespace: ns}},
67+
}
68+
69+
selector := map[string]string{"catalog": "test"}
70+
71+
cs := &clusterCatalogSource{
72+
Unstructured: &unstructured.Unstructured{},
73+
}
74+
cs.SetKind("ClusterCatalog")
75+
cs.SetAPIVersion("olm.operatorframework.io/v1")
76+
cs.SetName(fmt.Sprintf("%s-catalog", packageName))
77+
cs.SetLabels(selector)
78+
if err := unstructured.SetNestedMap(cs.Object, map[string]interface{}{
79+
"availabilityMode": "Available",
80+
"priority": int64(-300),
81+
"source": map[string]interface{}{
82+
"type": "Image",
83+
"image": map[string]interface{}{
84+
"ref": catalogImage,
85+
},
86+
},
87+
}, "spec"); err != nil {
88+
return nil, nil, err
89+
}
90+
91+
es := &clusterExtensionWrapper{
92+
Unstructured: &unstructured.Unstructured{},
93+
}
94+
es.SetKind("ClusterExtension")
95+
es.SetAPIVersion("olm.operatorframework.io/v1")
96+
es.SetName(packageName)
97+
98+
if err := unstructured.SetNestedMap(es.Object, map[string]interface{}{
99+
"namespace": ns,
100+
"serviceAccount": map[string]interface{}{"name": sa.Name},
101+
"source": map[string]interface{}{
102+
"sourceType": "Catalog",
103+
"catalog": map[string]interface{}{
104+
"packageName": packageName,
105+
},
106+
},
107+
}, "spec"); err != nil {
108+
return nil, nil, err
109+
}
110+
if err := unstructured.SetNestedStringMap(cs.Object, selector, "spec", "source", "catalog", "selector", "matchLabels"); err != nil {
111+
return nil, nil, err
112+
}
113+
114+
for _, obj := range []client.Object{sa, crb, es.Unwrap(), cs.Unwrap()} {
115+
if err := cli.Create(ctx, obj); err != nil {
116+
return nil, nil, err
117+
}
118+
}
119+
120+
return es, cs, nil
121+
}
122+
123+
func conditions(object map[string]interface{}) []metav1.Condition {
124+
var (
125+
conditionsSlice []interface{}
126+
found bool
127+
err error
128+
)
129+
if conditionsSlice, found, err = unstructured.NestedSlice(object, "status", "conditions"); !found || err != nil {
130+
return nil
131+
}
132+
133+
jsonBytes, err := json.Marshal(conditionsSlice)
134+
if err != nil {
135+
return nil
136+
}
137+
138+
var typedConditions []metav1.Condition
139+
if err := json.Unmarshal(jsonBytes, &typedConditions); err != nil {
140+
return nil
141+
}
142+
return typedConditions
143+
}

0 commit comments

Comments
 (0)