diff --git a/Makefile b/Makefile index 78a3fcbe0..df407949b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ MOD_FLAGS := $(shell (go version | grep -q -E "1\.(11|12)") && echo -mod=vendor) CMDS := $(addprefix bin/, $(shell ls ./cmd)) +SPECIFIC_UNIT_TEST := $(if $(TEST),-run $(TEST),) .PHONY: build test vendor clean @@ -15,7 +16,7 @@ static: extra_flags=-ldflags '-w -extldflags "-static"' static: build unit: - go test $(MOD_FLAGS) -count=1 -v -race ./pkg/... + go test $(MOD_FLAGS) $(SPECIFIC_UNIT_TEST) -count=1 -v -race ./pkg/... image: docker build . diff --git a/pkg/configmap/configmap.go b/pkg/configmap/configmap.go index 9400bcf6e..6dcba668f 100644 --- a/pkg/configmap/configmap.go +++ b/pkg/configmap/configmap.go @@ -3,11 +3,14 @@ package configmap import ( "errors" "fmt" - libbundle "github.com/operator-framework/operator-registry/pkg/lib/bundle" - "github.com/operator-framework/operator-registry/pkg/registry" + "strings" + "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" - "strings" + + "github.com/operator-framework/operator-registry/pkg/api" + "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/operator-framework/operator-registry/pkg/sqlite" ) func NewBundleLoader() *BundleLoader { @@ -21,12 +24,6 @@ func NewBundleLoaderWithLogger(logger *logrus.Entry) *BundleLoader { } } -// Manifest contains a bundle and a PackageManifest. -type Manifest struct { - Bundle *registry.Bundle - PackageManifest *registry.PackageManifest -} - type BundleLoader struct { logger *logrus.Entry } @@ -35,7 +32,7 @@ type BundleLoader struct { // creates an operator registry Bundle object. // If the Data section has a PackageManifest resource then it is also // deserialized and included in the result. -func (l *BundleLoader) Load(cm *corev1.ConfigMap) (manifest *Manifest, err error) { +func (l *BundleLoader) Load(cm *corev1.ConfigMap) (bundle *api.Bundle, err error) { if cm == nil { err = errors.New("ConfigMap must not be ") return @@ -45,48 +42,17 @@ func (l *BundleLoader) Load(cm *corev1.ConfigMap) (manifest *Manifest, err error "configmap": fmt.Sprintf("%s/%s", cm.GetNamespace(), cm.GetName()), }) - bundle, _, bundleErr := loadBundle(logger, cm.Data) + bundle, skipped, bundleErr := loadBundle(logger, cm.Data) if bundleErr != nil { err = fmt.Errorf("failed to extract bundle from configmap - %v", bundleErr) return } - - // get package manifest information from required annotations - annotations := cm.GetAnnotations() - if len(annotations) == 0 { - err = fmt.Errorf("missing required annoations on configmap %v", cm.GetName()) - return - } - - switch mediatype := annotations[libbundle.MediatypeLabel]; mediatype { - case "registry+v1": - // supported, proceed - default: - err = fmt.Errorf("failed to parse annotations due to unsupported media type %v", mediatype) - return - } - - var packageChannels []registry.PackageChannel - channels := strings.Split(annotations[libbundle.ChannelsLabel], ",") - for _, channel := range channels { - packageChannels = append(packageChannels, registry.PackageChannel{ - Name: channel, - }) - } - - manifest = &Manifest{ - Bundle: bundle, - PackageManifest: ®istry.PackageManifest{ - PackageName: annotations[libbundle.PackageLabel], - Channels: packageChannels, - DefaultChannelName: annotations[libbundle.ChannelDefaultLabel], - }, - } + l.logger.Debugf("couldn't unpack skipped: %#v", skipped) return } -func loadBundle(entry *logrus.Entry, data map[string]string) (bundle *registry.Bundle, skipped map[string]string, err error) { - bundle = ®istry.Bundle{} +func loadBundle(entry *logrus.Entry, data map[string]string) (bundle *api.Bundle, skipped map[string]string, err error) { + bundle = &api.Bundle{Object: []string{}} skipped = map[string]string{} // Add kube resources to the bundle. @@ -106,44 +72,16 @@ func loadBundle(entry *logrus.Entry, data map[string]string) (bundle *registry.B continue } - // It's a valid kube resource, - // could be a crd, csv or other raw kube manifest(s). - bundle.Add(resource) + if resource.GetKind() == sqlite.ClusterServiceVersionKind { + csvBytes, err := resource.MarshalJSON() + if err != nil { + return nil, nil, err + } + bundle.CsvJson = string(csvBytes) + } + bundle.Object = append(bundle.Object, content) logger.Infof("added to bundle, Kind=%s", resource.GetKind()) } return } - -func loadPackageManifest(entry *logrus.Entry, resources map[string]string) *registry.PackageManifest { - // Let's inspect if any of the skipped non kube resources is a PackageManifest type. - // The first one we run into will be selected. - for name, content := range resources { - logger := entry.WithFields(logrus.Fields{ - "key": name, - }) - - // Is it a package yaml file? - reader := strings.NewReader(content) - packageManifest, decodeErr := registry.DecodePackageManifest(reader) - if decodeErr != nil { - logger.Infof("skipping, not a PackageManifest type - %v", decodeErr) - continue - } - - logger.Infof("found a PackageManifest type resource - packageName=%s", packageManifest.PackageName) - - return packageManifest - } - - return nil -} - -func extract(data map[string]string) []string { - resources := make([]string, 0) - for _, v := range data { - resources = append(resources, v) - } - - return resources -} diff --git a/pkg/configmap/configmap_test.go b/pkg/configmap/configmap_test.go index 27dc97ba5..8284187f8 100644 --- a/pkg/configmap/configmap_test.go +++ b/pkg/configmap/configmap_test.go @@ -2,11 +2,14 @@ package configmap import ( "os" + "strings" "testing" + "github.com/operator-framework/operator-registry/pkg/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" ) @@ -14,82 +17,63 @@ func TestLoad(t *testing.T) { tests := []struct { name string source string - assertFunc func(t *testing.T, manifestGot *Manifest) + assertFunc func(t *testing.T, bundleGot *api.Bundle) }{ { name: "BundleWithCsvAndCrd", source: "testdata/bundle.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - assert.NotNil(t, manifestGot.PackageManifest) - - csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() - assert.NoError(t, errGot) + assertFunc: func(t *testing.T, bundleGot *api.Bundle) { + csvGot := bundleGot.GetCsvJson() assert.NotNil(t, csvGot) - crdListGot, errGot := manifestGot.Bundle.CustomResourceDefinitions() - assert.NoError(t, errGot) - assert.Equal(t, 1, len(crdListGot)) + crdListGot := bundleGot.GetObject() + // 1 CSV + 1 CRD = 2 objects + assert.Equal(t, 2, len(crdListGot)) }, }, { name: "BundleWithBuiltInKubeTypes", source: "testdata/bundle-with-kube-resources.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - assert.NotNil(t, manifestGot.Bundle.Objects) - - objects := manifestGot.Bundle.Objects + assertFunc: func(t *testing.T, bundleGot *api.Bundle) { + objects := bundleGot.GetObject() + assert.NotNil(t, objects) assert.Equal(t, 1, len(objects)) - assert.True(t, objects[0].GetKind() == "Foo") + + unst := getUnstructured(t, objects[0]) + assert.True(t, unst.GetKind() == "Foo") }, }, { name: "BundleWithMultipleCsvs", source: "testdata/bundle-with-multiple-csvs.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - - csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() - assert.NoError(t, errGot) + assertFunc: func(t *testing.T, bundleGot *api.Bundle) { + csvGot := bundleGot.GetCsvJson() assert.NotNil(t, csvGot) - assert.True(t, csvGot.GetName() == "first" || csvGot.GetName() == "second") + + unst := getUnstructured(t, csvGot) + assert.True(t, unst.GetName() == "first" || unst.GetName() == "second") }, }, { name: "BundleWithBadResource", source: "testdata/bundle-with-bad-resource.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - - csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() - assert.NoError(t, errGot) + assertFunc: func(t *testing.T, bundleGot *api.Bundle) { + csvGot := bundleGot.GetCsvJson() assert.NotNil(t, csvGot) }, }, { name: "BundleWithAll", source: "testdata/bundle-with-all.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - assert.NotNil(t, manifestGot.PackageManifest) - - csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() - assert.NoError(t, errGot) + assertFunc: func(t *testing.T, bundleGot *api.Bundle) { + csvGot := bundleGot.GetCsvJson() assert.NotNil(t, csvGot) - assert.True(t, csvGot.GetName() == "kiali-operator.v1.4.2") - - crdListGot, errGot := manifestGot.Bundle.CustomResourceDefinitions() - assert.NoError(t, errGot) - assert.Equal(t, 2, len(crdListGot)) + unst := getUnstructured(t, csvGot) + assert.True(t, unst.GetName() == "kiali-operator.v1.4.2") - providedAPIList, errGot := manifestGot.Bundle.ProvidedAPIs() - assert.NoError(t, errGot) - assert.Equal(t, 2, len(providedAPIList)) - - requiredAPIList, errGot := manifestGot.Bundle.RequiredAPIs() - assert.NoError(t, errGot) - assert.Equal(t, 0, len(requiredAPIList)) + objects := bundleGot.GetObject() + // 2 CRDs + 1 CSV == 3 objects + assert.Equal(t, 3, len(objects)) }, }, } @@ -99,13 +83,13 @@ func TestLoad(t *testing.T) { cm := loadfromFile(t, tt.source) loader := NewBundleLoader() - manifestGot, errGot := loader.Load(cm) + bundleGot, errGot := loader.Load(cm) assert.NoError(t, errGot) - assert.NotNil(t, manifestGot) + assert.NotNil(t, bundleGot) if tt.assertFunc != nil { - tt.assertFunc(t, manifestGot) + tt.assertFunc(t, bundleGot) } }) } @@ -122,3 +106,11 @@ func loadfromFile(t *testing.T, path string) *corev1.ConfigMap { return bundle } + +func getUnstructured(t *testing.T, str string) *unstructured.Unstructured { + dec := yaml.NewYAMLOrJSONDecoder(strings.NewReader(str), 1) + unst := &unstructured.Unstructured{} + err := dec.Decode(unst) + assert.NoError(t, err) + return unst +}