Skip to content

Commit

Permalink
Merge pull request #24 from njhale/op-disc-2
Browse files Browse the repository at this point in the history
feat(operators): add v2alpha1 operator types
  • Loading branch information
njhale authored Apr 9, 2020
2 parents d9f7449 + 6acca52 commit 3973134
Show file tree
Hide file tree
Showing 428 changed files with 77,551 additions and 4,630 deletions.
35 changes: 28 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ endif
REPO = github.com/operator-framework/api
BUILD_PATH = $(REPO)/cmd/operator-verify
PKGS = $(shell go list ./... | grep -v /vendor/)
YQ_INTERNAL := $(Q) go run $(MOD_FLAGS) ./vendor/github.com/mikefarah/yq/v2/

.PHONY: help
help: ## Show this help screen
Expand All @@ -23,7 +24,7 @@ help: ## Show this help screen

.PHONY: install

install: ## Build & install the operator-verify
install: ## Build & install operator-verify

$(Q)go install \
-gcflags "all=-trimpath=${GOPATH}" \
Expand All @@ -35,22 +36,35 @@ install: ## Build & install the operator-verify
$(BUILD_PATH)

# Code management.
.PHONY: format tidy clean
.PHONY: format tidy clean vendor generate

format: ## Format the source code
$(Q)go fmt $(PKGS)

tidy: ## Update dependencies
$(Q)go mod tidy -v

vendor: tidy ## Update vendor directory
$(Q)go mod vendor

clean: ## Clean up the build artifacts
$(Q)rm -rf build

##############################
# Tests #
##############################
generate: controller-gen ## Generate code
$(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths=./...

manifests: controller-gen ## Generate manifests e.g. CRD, RBAC etc
@# Handle >v1 APIs
$(CONTROLLER_GEN) crd paths=./pkg/operators/v2alpha1... output:crd:dir=./crds

@# Handle <=v1 APIs
$(CONTROLLER_GEN) schemapatch:manifests=./crds output:dir=./crds paths=./pkg/operators/...

@# Preserve unknown fields on the CSV spec (prevents install strategy from being pruned)
$(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

##@ Tests
@# Update embedded CRD files.
@go generate ./crds/...

# Static tests.
.PHONY: test test-unit
Expand All @@ -59,4 +73,11 @@ test: test-unit ## Run the tests

TEST_PKGS:=$(shell go list ./...)
test-unit: ## Run the unit tests
$(Q)go test -short ${TEST_PKGS}
$(Q)go test -count=1 -short ${TEST_PKGS}

# Utilities.
.PHONY: controller-gen

controller-gen: vendor ## Find or download controller-gen
CONTROLLER_GEN=$(Q)go run -mod=vendor ./vendor/sigs.k8s.io/controller-tools/cmd/controller-gen

117 changes: 117 additions & 0 deletions crds/defs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package crds

// Generate embedded files from CRDs to avoid file path changes when this package is imported.
//go:generate go run github.com/go-bindata/go-bindata/v3/go-bindata -pkg crds -o zz_defs.go -ignore=.*\.go .

import (
"bytes"
"fmt"
"sync"

"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/yaml"
)

// crdFile is a descriptor of a file containing a CustomResourceDefinition.
type crdFile string

// path returns the path of the file.
func (c crdFile) path() string {
s := string(c)
return s
}

// mustUnmarshal unmarshals the file into a CRD and panics on failure.
func (c crdFile) mustUnmarshal() *apiextensionsv1.CustomResourceDefinition {
path := c.path()
data, err := Asset(path)
if err != nil {
panic(fmt.Errorf("unable to read crd file %s: %s", path, err))
}

u := &unstructured.Unstructured{}
reader := bytes.NewReader(data)
decoder := yaml.NewYAMLOrJSONDecoder(reader, 30)
if err = decoder.Decode(u); err != nil {
panic(fmt.Errorf("crd unmarshaling failed: %s", err))
}

// Step through unversioned type to support v1beta1 -> v1
unversioned := &apiextensions.CustomResourceDefinition{}
if err = scheme.Convert(u, unversioned, nil); err != nil {
panic(fmt.Errorf("failed to convert crd: %s\nto v1: %s", u, err))
}

crd := &apiextensionsv1.CustomResourceDefinition{}
if err = scheme.Convert(unversioned, crd, nil); err != nil {
panic(fmt.Errorf("failed to convert crd: %s\nto v1: %s", u, err))
}

return crd
}

var (
lock sync.Mutex

// loaded stores previously unmarshaled CustomResourceDefinitions indexed by their file descriptor.
loaded = map[crdFile]*apiextensionsv1.CustomResourceDefinition{}
// scheme provides conversions between type versions.
scheme = runtime.NewScheme()
)

func init() {
// Add conversions between CRD versions
install.Install(scheme)
}

// getCRD lazily loads and returns the CustomResourceDefinition unmarshaled from a file.
func getCRD(file crdFile) *apiextensionsv1.CustomResourceDefinition {
lock.Lock()
defer lock.Unlock()

if crd, ok := loaded[file]; ok && crd != nil {
return crd
}

// Unmarshal and memoize
crd := file.mustUnmarshal()
loaded[file] = crd

return crd
}

// TODO(njhale): codegen this.

// CatalogSource returns a copy of the CustomResourceDefinition for the latest version of the CatalogSource API.
func CatalogSource() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_catalogsources.yaml").DeepCopy()
}

// ClusterServiceVersion returns a copy of the CustomResourceDefinition for the latest version of the ClusterServiceVersion API.
func ClusterServiceVersion() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_clusterserviceversions.yaml").DeepCopy()
}

// InstallPlan returns a copy of the CustomResourceDefinition for the latest version of the InstallPlan API.
func InstallPlan() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_installplans.yaml").DeepCopy()
}

// OperatorGroup returns a copy of the CustomResourceDefinition for the latest version of the OperatorGroup API.
func OperatorGroup() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_operatorgroups.yaml").DeepCopy()
}

// Operator returns a copy of the CustomResourceDefinition for the latest version of the Operator API.
func Operator() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_operators.yaml").DeepCopy()
}

// Subscription returns a copy of the CustomResourceDefinition for the latest version of the Subscription API.
func Subscription() *apiextensionsv1.CustomResourceDefinition {
return getCRD("operators.coreos.com_subscriptions.yaml").DeepCopy()
}
56 changes: 56 additions & 0 deletions crds/defs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package crds

import (
"reflect"
"testing"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

var emptyCRD = &apiextensionsv1.CustomResourceDefinition{}

func TestGetters(t *testing.T) {
tests := []struct {
description string
get func() *apiextensionsv1.CustomResourceDefinition
}{
{
description: "CatalogSource",
get: CatalogSource,
},
{
description: "ClusterServiceVersion",
get: ClusterServiceVersion,
},
{
description: "InstallPlan",
get: InstallPlan,
},
{
description: "OperatorGroup",
get: OperatorGroup,
},
{
description: "Operator",
get: Operator,
},
{
description: "Subscription",
get: Subscription,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
defer func() {
if x := recover(); x != nil {
t.Errorf("panic loading crd: %v", x)
}
}()

crd := tt.get()
if crd == nil || reflect.DeepEqual(crd, emptyCRD) {
t.Error("loaded CustomResourceDefinition is empty")
}
})
}
}
2 changes: 2 additions & 0 deletions crds/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package crds contains CustomResourceDefinition manifests for operator-framework APIs.
package crds
Loading

0 comments on commit 3973134

Please sign in to comment.