Skip to content

Commit 41349c0

Browse files
committed
feat(crds): add unmarshaled convenience getters
Add convenience getters that lazily unmarshal and memoize each of the latest CRDs.
1 parent b8573f3 commit 41349c0

File tree

7 files changed

+545
-67
lines changed

7 files changed

+545
-67
lines changed

Makefile

Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ ifeq ($(BUILD_VERBOSE),1)
88
else
99
Q = @
1010
endif
11-
12-
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
13-
ifeq (,$(shell go env GOBIN))
14-
GOBIN=$(shell go env GOPATH)/bin
15-
else
16-
GOBIN=$(shell go env GOBIN)
17-
endif
1811

1912
REPO = github.com/operator-framework/api
2013
BUILD_PATH = $(REPO)/cmd/operator-verify
@@ -70,66 +63,8 @@ manifests: controller-gen ## Generate manifests e.g. CRD, RBAC etc
7063
@# Preserve unknown fields on the CSV spec (prevents install strategy from being pruned)
7164
$(YQ_INTERNAL) w --inplace ./crds/operators.coreos.com_clusterserviceversions.yaml spec.validation.openAPIV3Schema.properties.spec.properties.install.properties.spec.properties.deployments.items.properties.spec.properties.template.properties.metadata.x-kubernetes-preserve-unknown-fields true
7265

73-
# Generate deepcopy, conversion, clients, listers, and informers
74-
codegen:
75-
# Deepcopy
76-
$(CONTROLLER_GEN) object:headerFile=./boilerplate.go.txt paths=./pkg/api/apis/operators/...i
77-
# Conversion, clients, listers, and informers
78-
$(CODEGEN)
79-
80-
# Generate mock types.
81-
mockgen:
82-
$(MOCKGEN)
83-
84-
# Generates everything.
85-
gen-all: codegen mockgen manifests
86-
87-
diff:
88-
git diff --exit-code
89-
90-
verify-codegen: codegen diff
91-
verify-mockgen: mockgen diff
92-
verify-manifests: manifests diff
93-
verify: verify-codegen verify-mockgen verify-manifests
94-
95-
96-
# before running release, bump the version in OLM_VERSION and push to master,
97-
# then tag those builds in quay with the version in OLM_VERSION
98-
release: ver=$(shell cat OLM_VERSION)
99-
release:
100-
docker pull quay.io/operator-framework/olm:$(ver)
101-
$(MAKE) target=upstream ver=$(ver) quickstart=true package
102-
$(MAKE) target=ocp ver=$(ver) package
103-
rm -rf manifests
104-
mkdir manifests
105-
cp -R deploy/ocp/manifests/$(ver)/. manifests
106-
# requires gnu sed if on mac
107-
find ./manifests -type f -exec sed -i "/^#/d" {} \;
108-
find ./manifests -type f -exec sed -i "1{/---/d}" {} \;
109-
110-
verify-release: release diff
111-
112-
package: olmref=$(shell docker inspect --format='{{index .RepoDigests 0}}' quay.io/operator-framework/olm:$(ver))
113-
package:
114-
ifndef target
115-
$(error target is undefined)
116-
endif
117-
ifndef ver
118-
$(error ver is undefined)
119-
endif
120-
$(YQ_INTERNAL) w -i deploy/$(target)/values.yaml olm.image.ref $(olmref)
121-
$(YQ_INTERNAL) w -i deploy/$(target)/values.yaml catalog.image.ref $(olmref)
122-
$(YQ_INTERNAL) w -i deploy/$(target)/values.yaml package.image.ref $(olmref)
123-
./scripts/package_release.sh $(ver) deploy/$(target)/manifests/$(ver) deploy/$(target)/values.yaml
124-
ln -sfFn ./$(ver) deploy/$(target)/manifests/latest
125-
ifeq ($(quickstart), true)
126-
./scripts/package_quickstart.sh deploy/$(target)/manifests/$(ver) deploy/$(target)/quickstart/olm.yaml deploy/$(target)/quickstart/crds.yaml deploy/$(target)/quickstart/install.sh
127-
endif
128-
129-
.PHONY: run-console-local
130-
run-console-local:
131-
@echo Running script to run the OLM console locally:
132-
. ./scripts/run_console_local.sh
66+
@# Update embedded CRD files.
67+
@go generate ./crds/...
13368

13469
# Static tests.
13570
.PHONY: test test-unit

crds/defs.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package crds
2+
3+
// Generate embedded files from CRDs to avoid file path changes when this package is imported.
4+
//go:generate go run github.com/go-bindata/go-bindata/v3/go-bindata -pkg crds -o zz_defs.go -ignore=.*\.go .
5+
6+
import (
7+
"bytes"
8+
"fmt"
9+
"sync"
10+
11+
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
12+
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
13+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
14+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
15+
"k8s.io/apimachinery/pkg/runtime"
16+
"k8s.io/apimachinery/pkg/util/yaml"
17+
)
18+
19+
// crdFile is a descriptor of a file containing a CustomResourceDefinition.
20+
type crdFile string
21+
22+
// path returns the path of the file.
23+
func (c crdFile) path() string {
24+
s := string(c)
25+
return s
26+
}
27+
28+
// mustUnmarshal unmarshals the file into a CRD and panics on failure.
29+
func (c crdFile) mustUnmarshal() *apiextensionsv1.CustomResourceDefinition {
30+
path := c.path()
31+
data, err := Asset(path)
32+
if err != nil {
33+
panic(fmt.Errorf("unable to read crd file %s: %s", path, err))
34+
}
35+
36+
u := &unstructured.Unstructured{}
37+
reader := bytes.NewReader(data)
38+
decoder := yaml.NewYAMLOrJSONDecoder(reader, 30)
39+
if err = decoder.Decode(u); err != nil {
40+
panic(fmt.Errorf("crd unmarshaling failed: %s", err))
41+
}
42+
43+
// Step through unversioned type to support v1beta1 -> v1
44+
unversioned := &apiextensions.CustomResourceDefinition{}
45+
if err = scheme.Convert(u, unversioned, nil); err != nil {
46+
panic(fmt.Errorf("failed to convert crd: %s\nto v1: %s", u, err))
47+
}
48+
49+
crd := &apiextensionsv1.CustomResourceDefinition{}
50+
if err = scheme.Convert(unversioned, crd, nil); err != nil {
51+
panic(fmt.Errorf("failed to convert crd: %s\nto v1: %s", u, err))
52+
}
53+
54+
return crd
55+
}
56+
57+
var (
58+
lock sync.Mutex
59+
60+
// loaded stores previously unmarshaled CustomResourceDefinitions indexed by their file descriptor.
61+
loaded = map[crdFile]*apiextensionsv1.CustomResourceDefinition{}
62+
// scheme provides conversions between type versions.
63+
scheme = runtime.NewScheme()
64+
)
65+
66+
func init() {
67+
// Add conversions between CRD versions
68+
install.Install(scheme)
69+
}
70+
71+
// getCRD lazily loads and returns the CustomResourceDefinition unmarshaled from a file.
72+
func getCRD(file crdFile) *apiextensionsv1.CustomResourceDefinition {
73+
lock.Lock()
74+
defer lock.Unlock()
75+
76+
if crd, ok := loaded[file]; ok && crd != nil {
77+
return crd
78+
}
79+
80+
// Unmarshal and memoize
81+
crd := file.mustUnmarshal()
82+
loaded[file] = crd
83+
84+
return crd
85+
}
86+
87+
// TODO(njhale): codegen this.
88+
89+
// CatalogSource returns a copy of the CustomResourceDefinition for the latest version of the CatalogSource API.
90+
func CatalogSource() *apiextensionsv1.CustomResourceDefinition {
91+
return getCRD("operators.coreos.com_catalogsources.yaml").DeepCopy()
92+
}
93+
94+
// ClusterServiceVersion returns a copy of the CustomResourceDefinition for the latest version of the ClusterServiceVersion API.
95+
func ClusterServiceVersion() *apiextensionsv1.CustomResourceDefinition {
96+
return getCRD("operators.coreos.com_clusterserviceversions.yaml").DeepCopy()
97+
}
98+
99+
// InstallPlan returns a copy of the CustomResourceDefinition for the latest version of the InstallPlan API.
100+
func InstallPlan() *apiextensionsv1.CustomResourceDefinition {
101+
return getCRD("operators.coreos.com_installplans.yaml").DeepCopy()
102+
}
103+
104+
// OperatorGroup returns a copy of the CustomResourceDefinition for the latest version of the OperatorGroup API.
105+
func OperatorGroup() *apiextensionsv1.CustomResourceDefinition {
106+
return getCRD("operators.coreos.com_operatorgroups.yaml").DeepCopy()
107+
}
108+
109+
// Operator returns a copy of the CustomResourceDefinition for the latest version of the Operator API.
110+
func Operator() *apiextensionsv1.CustomResourceDefinition {
111+
return getCRD("operators.coreos.com_operators.yaml").DeepCopy()
112+
}
113+
114+
// Subscription returns a copy of the CustomResourceDefinition for the latest version of the Subscription API.
115+
func Subscription() *apiextensionsv1.CustomResourceDefinition {
116+
return getCRD("operators.coreos.com_subscriptions.yaml").DeepCopy()
117+
}

crds/defs_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package crds
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
8+
)
9+
10+
var emptyCRD = &apiextensionsv1.CustomResourceDefinition{}
11+
12+
func TestGetters(t *testing.T) {
13+
tests := []struct {
14+
description string
15+
get func() *apiextensionsv1.CustomResourceDefinition
16+
}{
17+
{
18+
description: "CatalogSource",
19+
get: CatalogSource,
20+
},
21+
{
22+
description: "ClusterServiceVersion",
23+
get: ClusterServiceVersion,
24+
},
25+
{
26+
description: "InstallPlan",
27+
get: InstallPlan,
28+
},
29+
{
30+
description: "OperatorGroup",
31+
get: OperatorGroup,
32+
},
33+
{
34+
description: "Operator",
35+
get: Operator,
36+
},
37+
{
38+
description: "Subscription",
39+
get: Subscription,
40+
},
41+
}
42+
for _, tt := range tests {
43+
t.Run(tt.description, func(t *testing.T) {
44+
defer func() {
45+
if x := recover(); x != nil {
46+
t.Errorf("panic loading crd: %v", x)
47+
}
48+
}()
49+
50+
crd := tt.get()
51+
if crd == nil || reflect.DeepEqual(crd, emptyCRD) {
52+
t.Error("loaded CustomResourceDefinition is empty")
53+
}
54+
})
55+
}
56+
}

crds/zz_defs.go

Lines changed: 360 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.13
55
require (
66
github.com/blang/semver v3.5.0+incompatible
77
github.com/ghodss/yaml v1.0.0
8+
github.com/go-bindata/go-bindata/v3 v3.1.3
89
github.com/mikefarah/yq/v2 v2.4.1
910
github.com/operator-framework/operator-registry v1.5.3
1011
github.com/pkg/errors v0.8.1

go.sum

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb h1:D4uzjWwKYQ5XnAvU
117117
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
118118
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is=
119119
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
120+
github.com/go-bindata/go-bindata/v3 v3.1.3 h1:F0nVttLC3ws0ojc7p60veTurcOm//D4QBODNM7EGrCI=
121+
github.com/go-bindata/go-bindata/v3 v3.1.3/go.mod h1:1/zrpXsLD8YDIbhZRqXzm1Ghc7NhEvIN9+Z6R5/xH4I=
120122
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
121123
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
122124
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
@@ -285,6 +287,7 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
285287
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
286288
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
287289
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
290+
github.com/kisielk/errcheck v1.2.0 h1:reN85Pxc5larApoH1keMBiu2GWtPqXQ1nc9gx+jOU+E=
288291
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
289292
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
290293
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
@@ -488,6 +491,8 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
488491
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
489492
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
490493
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
494+
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
495+
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
491496
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
492497
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
493498
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -580,6 +585,8 @@ golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh3
580585
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
581586
golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0 h1:s5lp4ug7qHzUccgyFdjsX7OZDzHXRaePrF3B3vmUiuM=
582587
golang.org/x/tools v0.0.0-20191030203535-5e247c9ad0a0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
588+
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f h1:kDxGY2VmgABOe55qheT/TFqUMtcTHnomIPS1iv3G4Ms=
589+
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
583590
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
584591
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
585592
gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=

tools.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ import (
77
_ "sigs.k8s.io/controller-tools/cmd/controller-gen"
88
// Manipulate YAML.
99
_ "github.com/mikefarah/yq/v2"
10+
// Generate embedded files.
11+
_ "github.com/go-bindata/go-bindata/v3"
1012
)

0 commit comments

Comments
 (0)