From f5c95c0b9dfad2d142a115f8e43ca3df54a8394e Mon Sep 17 00:00:00 2001 From: Abu Kashem Date: Mon, 30 Sep 2019 16:37:10 -0400 Subject: [PATCH 1/3] (feat) Load operator registry bundle from ConfigMap - Iterate through the Data section of a ConfigMap, process each resource and construct a registry.Bundle object for use. - The ConfigMap may have a resource that contains a `PackageManifest` resource. Process this resource if present and deserialize. --- pkg/configmap/configmap.go | 123 +++++++++++++++++ pkg/configmap/configmap_test.go | 129 ++++++++++++++++++ .../testdata/bundle-with-bad-resource.cm.yaml | 17 +++ .../bundle-with-kube-resources.cm.yaml | 10 ++ .../bundle-with-multiple-csvs.cm.yaml | 21 +++ ...le-with-multiple-package-manifests.cm.yaml | 12 ++ .../bundle-with-package-manifest.cm.yaml | 28 ++++ pkg/configmap/testdata/bundle.cm.yaml | 20 +++ pkg/registry/decode.go | 43 ++++++ pkg/registry/decode_test.go | 97 +++++++++++++ .../testdata/invalid-package-manifest.yaml | 2 + .../testdata/invalid-unstructured.yaml | 4 + .../testdata/valid-package-manifest.yaml | 7 + pkg/registry/testdata/valid-unstructured.yaml | 5 + 14 files changed, 518 insertions(+) create mode 100644 pkg/configmap/configmap.go create mode 100644 pkg/configmap/configmap_test.go create mode 100644 pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml create mode 100644 pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml create mode 100644 pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml create mode 100644 pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml create mode 100644 pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml create mode 100644 pkg/configmap/testdata/bundle.cm.yaml create mode 100644 pkg/registry/decode.go create mode 100644 pkg/registry/decode_test.go create mode 100644 pkg/registry/testdata/invalid-package-manifest.yaml create mode 100644 pkg/registry/testdata/invalid-unstructured.yaml create mode 100644 pkg/registry/testdata/valid-package-manifest.yaml create mode 100644 pkg/registry/testdata/valid-unstructured.yaml diff --git a/pkg/configmap/configmap.go b/pkg/configmap/configmap.go new file mode 100644 index 000000000..58e6240d0 --- /dev/null +++ b/pkg/configmap/configmap.go @@ -0,0 +1,123 @@ +package configmap + +import ( + "errors" + "fmt" + "github.com/operator-framework/operator-registry/pkg/registry" + "github.com/sirupsen/logrus" + corev1 "k8s.io/api/core/v1" + "strings" +) + +func NewBundleLoader() *BundleLoader { + logger := logrus.NewEntry(logrus.New()) + return NewBundleLoaderWithLogger(logger) +} + +func NewBundleLoaderWithLogger(logger *logrus.Entry) *BundleLoader { + return &BundleLoader{ + logger: logger, + } +} + +// Manifest contains a bundle and a PackageManifest. +type Manifest struct { + Bundle *registry.Bundle + PackageManifest *registry.PackageManifest +} + +type BundleLoader struct { + logger *logrus.Entry +} + +// Load accepts a ConfigMap object, iterates through the Data section and +// 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) { + if cm == nil { + err = errors.New("ConfigMap must not be ") + return + } + + logger := l.logger.WithFields(logrus.Fields{ + "configmap": fmt.Sprintf("%s/%s", cm.GetNamespace(), cm.GetName()), + }) + + bundle, skipped, bundleErr := loadBundle(logger, cm.Data) + if bundleErr != nil { + err = fmt.Errorf("failed to extract bundle from configmap - %v", bundleErr) + return + } + + packageManifest := loadPackageManifest(logger, skipped) + + manifest = &Manifest{ + Bundle: bundle, + PackageManifest: packageManifest, + } + return +} + +func loadBundle(entry *logrus.Entry, data map[string]string) (bundle *registry.Bundle, skipped map[string]string, err error) { + bundle = ®istry.Bundle{} + skipped = map[string]string{} + + // Add kube resources to the bundle. + for name, content := range data { + reader := strings.NewReader(content) + logger := entry.WithFields(logrus.Fields{ + "key": name, + }) + + resource, decodeErr := registry.DecodeUnstructured(reader) + if decodeErr != nil { + logger.Infof("skipping due to decode error - %v", decodeErr) + + // It may not be not a kube resource, let's add it to the skipped + // list so the caller can act on ot. + skipped[name] = content + continue + } + + // It's a valid kube resource, + // could be a crd, csv or other raw kube manifest(s). + bundle.Add(resource) + 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 new file mode 100644 index 000000000..e35b1c9e9 --- /dev/null +++ b/pkg/configmap/configmap_test.go @@ -0,0 +1,129 @@ +package configmap + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/yaml" + "os" + "testing" +) + +func TestLoad(t *testing.T) { + tests := []struct { + name string + source string + assertFunc func(t *testing.T, manifestGot *Manifest) + }{ + { + name: "BundleWithCsvAndCrdOnly", + source: "testdata/bundle.cm.yaml", + assertFunc: func(t *testing.T, manifestGot *Manifest) { + assert.NotNil(t, manifestGot.Bundle) + assert.Nil(t, manifestGot.PackageManifest) + + // We don't populate package, channel and name of a bundle object. + assert.Empty(t, manifestGot.Bundle.Package) + assert.Empty(t, manifestGot.Bundle.Channel) + assert.Empty(t, manifestGot.Bundle.Name) + + csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() + assert.NoError(t, errGot) + assert.NotNil(t, csvGot) + + crdListGot, errGot := manifestGot.Bundle.CustomResourceDefinitions() + assert.NoError(t, errGot) + assert.Equal(t, 1, len(crdListGot)) + }, + }, + + { + name: "BundleWithPackageManifest", + source: "testdata/bundle-with-package-manifest.cm.yaml", + assertFunc: func(t *testing.T, manifestGot *Manifest) { + assert.NotNil(t, manifestGot.Bundle) + assert.NotNil(t, manifestGot.PackageManifest) + + assert.Equal(t, "etcd", manifestGot.PackageManifest.PackageName) + }, + }, + + { + name: "BundleWithMultiplePackageManifests", + source: "testdata/bundle-with-multiple-package-manifests.cm.yaml", + assertFunc: func(t *testing.T, manifestGot *Manifest) { + assert.NotNil(t, manifestGot.Bundle) + assert.NotNil(t, manifestGot.PackageManifest) + + name := manifestGot.PackageManifest.PackageName + assert.True(t, name == "first" || name == "second") + }, + }, + + { + 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 + assert.Equal(t, 1, len(objects)) + assert.True(t, objects[0].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) + assert.NotNil(t, csvGot) + assert.True(t, csvGot.GetName() == "first" || csvGot.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) + assert.NotNil(t, csvGot) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cm := loadfromFile(t, tt.source) + + loader := NewBundleLoader() + manifestGot, errGot := loader.Load(cm) + + assert.NoError(t, errGot) + assert.NotNil(t, manifestGot) + + if tt.assertFunc != nil { + tt.assertFunc(t, manifestGot) + } + }) + } +} + +func loadfromFile(t *testing.T, path string) *corev1.ConfigMap { + reader, err := os.Open(path) + require.NoError(t, err, "unable to load from file %s", path) + + decoder := yaml.NewYAMLOrJSONDecoder(reader, 30) + bundle := &corev1.ConfigMap{} + err = decoder.Decode(bundle) + require.NoError(t, err, "could not decode into configmap, file=%s", path) + + return bundle +} diff --git a/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml b/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml new file mode 100644 index 000000000..35899ffb3 --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml @@ -0,0 +1,17 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + crd.yaml: |- + apiVersion:: + -> + csv.yaml: |- + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: etcdoperator.v0.6.1 + namespace: placeholder + spec: diff --git a/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml b/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml new file mode 100644 index 000000000..ed498f877 --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml @@ -0,0 +1,10 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + my.kube.type.yaml: |- + apiVersion: fakes.k8s.io/v1alpha1 + kind: Foo diff --git a/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml b/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml new file mode 100644 index 000000000..21051b502 --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml @@ -0,0 +1,21 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + first.csv.yaml: |- + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: first + namespace: placeholder + spec: + second.csv.yaml: |- + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: second + namespace: placeholder + spec: diff --git a/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml b/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml new file mode 100644 index 000000000..e060ccd3d --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml @@ -0,0 +1,12 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + first.package.yaml: |- + packageName: first + second.package.yaml: |- + packageName: second + diff --git a/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml b/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml new file mode 100644 index 000000000..e09f6c2d4 --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml @@ -0,0 +1,28 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + crd.yaml: |- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + name: alertmanagers.monitoring.coreos.com + spec: + csv.yaml: |- + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: etcdoperator.v0.6.1 + namespace: placeholder + spec: + package.yaml: |- + packageName: etcd + defaultChannel: alpha + channels: + - name: alpha + currentCSV: etcdoperator.v0.9.4 + - name: beta + currentCSV: etcdoperator.v0.9.4-beta diff --git a/pkg/configmap/testdata/bundle.cm.yaml b/pkg/configmap/testdata/bundle.cm.yaml new file mode 100644 index 000000000..b6ecb6092 --- /dev/null +++ b/pkg/configmap/testdata/bundle.cm.yaml @@ -0,0 +1,20 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: ocs + namespace: kube-system + +data: + crd.yaml: |- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + name: alertmanagers.monitoring.coreos.com + spec: + csv.yaml: |- + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: etcdoperator.v0.6.1 + namespace: placeholder + spec: diff --git a/pkg/registry/decode.go b/pkg/registry/decode.go new file mode 100644 index 000000000..4d418df76 --- /dev/null +++ b/pkg/registry/decode.go @@ -0,0 +1,43 @@ +package registry + +import ( + "errors" + "fmt" + "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/yaml" +) + +// DecodeUnstructured decodes a raw stream into a an +// unstructured.Unstructured instance. +func DecodeUnstructured(reader io.Reader) (obj *unstructured.Unstructured, err error) { + decoder := yaml.NewYAMLOrJSONDecoder(reader, 30) + + t := &unstructured.Unstructured{} + if err = decoder.Decode(t); err != nil { + return + } + + obj = t + return +} + +// DecodePackageManifest decodes a raw stream into a a PackageManifest instance. +// If a package name is empty we consider the object invalid! +func DecodePackageManifest(reader io.Reader) (manifest *PackageManifest, err error) { + decoder := yaml.NewYAMLOrJSONDecoder(reader, 30) + + obj := &PackageManifest{} + if decodeErr := decoder.Decode(obj); decodeErr != nil { + err = fmt.Errorf("could not decode contents into package manifest - %v", decodeErr) + return + } + + if obj.PackageName == "" { + err = errors.New("name of package (packageName) is missing") + return + } + + manifest = obj + return +} diff --git a/pkg/registry/decode_test.go b/pkg/registry/decode_test.go new file mode 100644 index 000000000..0d0e08667 --- /dev/null +++ b/pkg/registry/decode_test.go @@ -0,0 +1,97 @@ +package registry + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "io" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "os" + "testing" +) + +func TestDecodeUnstructured(t *testing.T) { + tests := []struct { + name string + file string + assertFunc func(t *testing.T, objGot *unstructured.Unstructured, errGot error) + }{ + { + name: "ValidObjectWithKind", + file: "testdata/valid-unstructured.yaml", + assertFunc: func(t *testing.T, objGot *unstructured.Unstructured, errGot error) { + assert.NoError(t, errGot) + assert.NotNil(t, objGot) + + assert.Equal(t, "FooKind", objGot.GetKind()) + }, + }, + + { + name: "InvalidObjectWithoutKind", + file: "testdata/invalid-unstructured.yaml", + assertFunc: func(t *testing.T, objGot *unstructured.Unstructured, errGot error) { + assert.Error(t, errGot) + assert.Nil(t, objGot) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reader := loadFile(t, tt.file) + + objGot, errGot := DecodeUnstructured(reader) + + if tt.assertFunc != nil { + tt.assertFunc(t, objGot, errGot) + } + }) + } +} + +func TestDecodePackageManifest(t *testing.T) { + tests := []struct { + name string + file string + assertFunc func(t *testing.T, packageManifestGot *PackageManifest, errGot error) + }{ + { + name: "WithValidObject", + file: "testdata/valid-package-manifest.yaml", + assertFunc: func(t *testing.T, packageManifestGot *PackageManifest, errGot error) { + assert.NoError(t, errGot) + assert.NotNil(t, packageManifestGot) + + assert.Equal(t, "foo", packageManifestGot.PackageName) + }, + }, + + { + name: "WithoutPackageName", + file: "testdata/invalid-package-manifest.yaml", + assertFunc: func(t *testing.T, packageManifestGot *PackageManifest, errGot error) { + assert.Error(t, errGot) + assert.Nil(t, packageManifestGot) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reader := loadFile(t, tt.file) + + packageManifestGot, errGot := DecodePackageManifest(reader) + + if tt.assertFunc != nil { + tt.assertFunc(t, packageManifestGot, errGot) + } + }) + } +} + +func loadFile(t *testing.T, path string) io.Reader { + reader, err := os.Open(path) + require.NoError(t, err, "unable to load from file %s", path) + + return reader +} diff --git a/pkg/registry/testdata/invalid-package-manifest.yaml b/pkg/registry/testdata/invalid-package-manifest.yaml new file mode 100644 index 000000000..f7b158f4b --- /dev/null +++ b/pkg/registry/testdata/invalid-package-manifest.yaml @@ -0,0 +1,2 @@ +defaultChannel: alpha +channels: diff --git a/pkg/registry/testdata/invalid-unstructured.yaml b/pkg/registry/testdata/invalid-unstructured.yaml new file mode 100644 index 000000000..b5142a4ad --- /dev/null +++ b/pkg/registry/testdata/invalid-unstructured.yaml @@ -0,0 +1,4 @@ +apiVersion: fake.com/v1alpha1 +metadata: + name: foo + namespace: placeholder diff --git a/pkg/registry/testdata/valid-package-manifest.yaml b/pkg/registry/testdata/valid-package-manifest.yaml new file mode 100644 index 000000000..1493ac8f6 --- /dev/null +++ b/pkg/registry/testdata/valid-package-manifest.yaml @@ -0,0 +1,7 @@ +packageName: foo +defaultChannel: alpha +channels: + - name: alpha + currentCSV: foo + - name: beta + currentCSV: bar diff --git a/pkg/registry/testdata/valid-unstructured.yaml b/pkg/registry/testdata/valid-unstructured.yaml new file mode 100644 index 000000000..6015cc0a7 --- /dev/null +++ b/pkg/registry/testdata/valid-unstructured.yaml @@ -0,0 +1,5 @@ +apiVersion: fake.com/v1alpha1 +kind: FooKind +metadata: + name: foo + namespace: placeholder From 7804c8c35833a5606bb08e954adae10ee97a898a Mon Sep 17 00:00:00 2001 From: Jeff Peeler Date: Mon, 14 Oct 2019 16:20:27 -0400 Subject: [PATCH 2/3] test(unit): add test case from generated configmap This verifies that the configmap is being properly read from the extracted data of a bundle image (from #94). --- pkg/configmap/configmap_test.go | 35 +- pkg/configmap/testdata/bundle-with-all.yaml | 616 ++++++++++++++++++++ 2 files changed, 644 insertions(+), 7 deletions(-) create mode 100644 pkg/configmap/testdata/bundle-with-all.yaml diff --git a/pkg/configmap/configmap_test.go b/pkg/configmap/configmap_test.go index e35b1c9e9..523a40837 100644 --- a/pkg/configmap/configmap_test.go +++ b/pkg/configmap/configmap_test.go @@ -1,12 +1,13 @@ package configmap import ( + "os" + "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/yaml" - "os" - "testing" ) func TestLoad(t *testing.T) { @@ -36,7 +37,6 @@ func TestLoad(t *testing.T) { assert.Equal(t, 1, len(crdListGot)) }, }, - { name: "BundleWithPackageManifest", source: "testdata/bundle-with-package-manifest.cm.yaml", @@ -47,7 +47,6 @@ func TestLoad(t *testing.T) { assert.Equal(t, "etcd", manifestGot.PackageManifest.PackageName) }, }, - { name: "BundleWithMultiplePackageManifests", source: "testdata/bundle-with-multiple-package-manifests.cm.yaml", @@ -59,7 +58,6 @@ func TestLoad(t *testing.T) { assert.True(t, name == "first" || name == "second") }, }, - { name: "BundleWithBuiltInKubeTypes", source: "testdata/bundle-with-kube-resources.cm.yaml", @@ -72,7 +70,6 @@ func TestLoad(t *testing.T) { assert.True(t, objects[0].GetKind() == "Foo") }, }, - { name: "BundleWithMultipleCsvs", source: "testdata/bundle-with-multiple-csvs.cm.yaml", @@ -85,7 +82,6 @@ func TestLoad(t *testing.T) { assert.True(t, csvGot.GetName() == "first" || csvGot.GetName() == "second") }, }, - { name: "BundleWithBadResource", source: "testdata/bundle-with-bad-resource.cm.yaml", @@ -97,6 +93,31 @@ func TestLoad(t *testing.T) { 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) + 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)) + + 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)) + }, + }, } for _, tt := range tests { diff --git a/pkg/configmap/testdata/bundle-with-all.yaml b/pkg/configmap/testdata/bundle-with-all.yaml new file mode 100644 index 000000000..c0fdd6776 --- /dev/null +++ b/pkg/configmap/testdata/bundle-with-all.yaml @@ -0,0 +1,616 @@ +apiVersion: v1 +data: + kiali.crd.yaml: | + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + name: kialis.kiali.io + labels: + app: kiali-operator + spec: + group: kiali.io + names: + kind: Kiali + listKind: KialiList + plural: kialis + singular: kiali + scope: Namespaced + subresources: + status: {} + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true + kiali.monitoringdashboards.crd.yaml: | + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + name: monitoringdashboards.monitoring.kiali.io + labels: + app: kiali + spec: + group: monitoring.kiali.io + names: + kind: MonitoringDashboard + listKind: MonitoringDashboardList + plural: monitoringdashboards + singular: monitoringdashboard + scope: Namespaced + version: v1alpha1 + kiali.package.yaml: | + packageName: kiali + channels: + - name: alpha + currentCSV: kiali-operator.v1.4.2 + - name: stable + currentCSV: kiali-operator.v1.4.2 + defaultChannel: stable + kiali.v1.4.2.clusterserviceversion.yaml: | + apiVersion: operators.coreos.com/v1alpha1 + kind: ClusterServiceVersion + metadata: + name: kiali-operator.v1.4.2 + namespace: placeholder + annotations: + categories: Monitoring,Logging & Tracing + certified: "false" + containerImage: quay.io/kiali/kiali-operator:v1.4.2 + capabilities: Basic Install + support: Kiali + description: "Kiali project provides answers to the questions: What microservices are part of my Istio service mesh and how are they connected?" + repository: https://github.com/kiali/kiali + createdAt: 2019-09-12T00:00:00Z + alm-examples: |- + [ + { + "apiVersion": "kiali.io/v1alpha1", + "kind": "Kiali", + "metadata": { + "name": "kiali" + }, + "spec": { + "installation_tag": "My Kiali", + "istio_namespace": "istio-system", + "deployment": { + "namespace": "istio-system", + "verbose_mode": "4", + "view_only_mode": false + }, + "external_services": { + "grafana": { + "url": "" + }, + "prometheus": { + "url": "" + }, + "tracing": { + "url": "" + } + }, + "server": { + "web_root": "/mykiali" + } + } + }, + { + "apiVersion": "monitoring.kiali.io/v1alpha1", + "kind": "MonitoringDashboard", + "metadata": { + "name": "myappdashboard" + }, + "spec": { + "title": "My App Dashboard", + "items": [ + { + "chart": { + "name": "My App Processing Duration", + "unit": "seconds", + "spans": 6, + "metricName": "my_app_duration_seconds", + "dataType": "histogram", + "aggregations": [ + { + "label": "id", + "displayName": "ID" + } + ] + } + } + ] + } + } + ] + spec: + version: 1.4.2 + maturity: stable + replaces: kiali-operator.v1.3.1 + displayName: Kiali Operator + description: |- + A Microservice Architecture breaks up the monolith into many smaller pieces that are composed together. Patterns to secure the communication between services like fault tolerance (via timeout, retry, circuit breaking, etc.) have come up as well as distributed tracing to be able to see where calls are going. + + A service mesh can now provide these services on a platform level and frees the application writers from those tasks. Routing decisions are done at the mesh level. + + Kiali works with Istio, in OpenShift or Kubernetes, to visualize the service mesh topology, to provide visibility into features like circuit breakers, request rates and more. It offers insights about the mesh components at different levels, from abstract Applications to Services and Workloads. + + See [https://www.kiali.io](https://www.kiali.io) to read more. + + ### Prerequisites + + Today Kiali works with Istio. So before you install Kiali, you must have already installed Istio. Note that Istio can come pre-bundled with Kiali (specifically if you installed the Istio demo helm profile or if you installed Istio with the helm option '--set kiali.enabled=true'). If you already have the pre-bundled Kiali in your Istio environment and you want to install Kiali via the Kiali Operator, uninstall the pre-bundled Kiali first. You can do this via this command: + + kubectl delete --ignore-not-found=true all,secrets,sa,templates,configmaps,deployments,clusterroles,clusterrolebindings,ingresses,customresourcedefinitions --selector="app=kiali" -n istio-system + + When you install Kiali in a non-OpenShift Kubernetes environment, the authentication strategy will default to `login`. When using the authentication strategy of `login`, you are required to create a Kubernetes Secret with a `username` and `passphrase` that you want users to provide in order to successfully log into Kiali. Here is an example command you can execute to create such a secret (with a username of `admin` and a passphrase of `admin`): + + kubectl create secret generic kiali -n istio-system --from-literal "username=admin" --from-literal "passphrase=admin" + + ### Kiali Custom Resource Configuration Settings + + For quick descriptions of all the settings you can configure in the Kiali Custom Resource (CR), see the file [kiali_cr.yaml](https://github.com/kiali/kiali/blob/v1.4.2/operator/deploy/kiali/kiali_cr.yaml) + + ### Accessing the UI + + By default, the Kiali operator exposes the Kiali UI as a Route on OpenShift or Ingress on Kubernetes. + On OpenShift, the default root context path is '/' and on Kubernetes it is '/kiali' though you can change this by configuring the 'web_root' setting in the Kiali CR. + icon: + - base64data: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxMjgwIDEyODAiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDEyODAgMTI4MDsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiMwMTMxNDQ7fQoJLnN0MXtmaWxsOiMwMDkzREQ7fQo8L3N0eWxlPgo8Zz4KCTxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik04MTAuOSwxODAuOWMtMjUzLjYsMC00NTkuMSwyMDUuNS00NTkuMSw0NTkuMXMyMDUuNSw0NTkuMSw0NTkuMSw0NTkuMVMxMjcwLDg5My42LDEyNzAsNjQwCgkJUzEwNjQuNSwxODAuOSw4MTAuOSwxODAuOXogTTgxMC45LDEwMjkuMmMtMjE1LDAtMzg5LjItMTc0LjMtMzg5LjItMzg5LjJjMC0yMTUsMTc0LjMtMzg5LjIsMzg5LjItMzg5LjJTMTIwMC4xLDQyNSwxMjAwLjEsNjQwCgkJUzEwMjUuOSwxMDI5LjIsODEwLjksMTAyOS4yeiIvPgoJPHBhdGggY2xhc3M9InN0MSIgZD0iTTY1My4zLDI4NGMtMTM2LjQsNjAuNS0yMzEuNiwxOTcuMS0yMzEuNiwzNTZjMCwxNTguOCw5NS4yLDI5NS41LDIzMS42LDM1NmM5OC40LTg3LjEsMTYwLjQtMjE0LjMsMTYwLjQtMzU2CgkJQzgxMy43LDQ5OC4zLDc1MS42LDM3MS4xLDY1My4zLDI4NHoiLz4KCTxwYXRoIGNsYXNzPSJzdDEiIGQ9Ik0zNTEuOCw2NDBjMC0xMDkuOCwzOC42LTIxMC41LDEwMi44LTI4OS41Yy0zOS42LTE4LjItODMuNi0yOC4zLTEzMC0yOC4zQzE1MC45LDMyMi4yLDEwLDQ2NC41LDEwLDY0MAoJCXMxNDAuOSwzMTcuOCwzMTQuNiwzMTcuOGM0Ni4zLDAsOTAuNC0xMC4xLDEzMC0yOC4zQzM5MC4zLDg1MC41LDM1MS44LDc0OS44LDM1MS44LDY0MHoiLz4KPC9nPgo8L3N2Zz4K + mediatype: image/svg+xml + keywords: ['service-mesh', 'observability', 'monitoring', 'maistra', 'istio'] + maintainers: + - name: Kiali Developers Google Group + email: kiali-dev@googlegroups.com + provider: + name: Kiali + labels: + name: kiali-operator + selector: + matchLabels: + name: kiali-operator + links: + - name: Getting Started Guide + url: https://www.kiali.io/documentation/getting-started/ + - name: Features + url: https://www.kiali.io/documentation/features + - name: Documentation Home + url: https://www.kiali.io/documentation + - name: Blogs and Articles + url: https://medium.com/kialiproject + - name: Server Source Code + url: https://github.com/kiali/kiali + - name: UI Source Code + url: https://github.com/kiali/kiali-ui + installModes: + - type: OwnNamespace + supported: true + - type: SingleNamespace + supported: true + - type: MultiNamespace + supported: false + - type: AllNamespaces + supported: true + customresourcedefinitions: + owned: + - name: kialis.kiali.io + group: kiali.io + description: A configuration file for a Kiali installation. + displayName: Kiali + kind: Kiali + version: v1alpha1 + resources: + - kind: Deployment + version: apps/v1 + - kind: Pod + version: v1 + - kind: Service + version: v1 + - kind: ConfigMap + version: v1 + - kind: OAuthClient + version: oauth.openshift.io/v1 + - kind: Route + version: route.openshift.io/v1 + - kind: Ingress + version: extensions/v1beta1 + specDescriptors: + - displayName: Authentication Strategy + description: "Determines how a user is to log into Kiali. Choose 'login' to use a username and passphrase as defined in a Secret. Choose 'anonymous' to allow full access to Kiali without requiring credentials (use this at your own risk). Choose 'openshift' if on OpenShift to use the OpenShift OAuth login which controls access based on the individual's OpenShift RBAC roles. Default: openshift (when deployed in OpenShift); login (when deployed in Kubernetes)" + path: auth.strategy + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:label' + - displayName: Kiali Namespace + description: "The namespace where Kiali and its associated resources will be created. Default: istio-system" + path: deployment.namespace + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:label' + - displayName: Secret Name + description: "If Kiali is configured with auth.strategy 'login', an admin must create a Secret with credentials ('username' and 'passphrase') which will be used to authenticate users logging into Kiali. This setting defines the name of that secret. Default: kiali" + path: deployment.secret_name + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Secret' + - displayName: Verbose Mode + description: "Determines the priority levels of log messages Kiali will output. Typical values are '3' for INFO and higher priority messages, '4' for DEBUG and higher priority messages (this makes the logs more noisy). Default: 3" + path: deployment.verbose_mode + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:label' + - displayName: View Only Mode + description: "When true, Kiali will be in 'view only' mode, allowing the user to view and retrieve management and monitoring data for the service mesh, but not allow the user to modify the service mesh. Default: false" + path: deployment.view_only_mode + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:booleanSwitch' + - displayName: Web Root + description: "Defines the root context path for the Kiali console, API endpoints and readiness/liveness probes. Default: / (when deployed on OpenShift; /kiali (when deployed on Kubernetes)" + path: server.web_root + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:label' + - name: monitoringdashboards.monitoring.kiali.io + group: monitoring.kiali.io + description: A configuration file for defining an individual metric dashboard. + displayName: Monitoring Dashboard + kind: MonitoringDashboard + version: v1alpha1 + resources: [] + specDescriptors: + - displayName: Title + description: "The title of the dashboard." + path: title + x-descriptors: + - 'urn:alm:descriptor:com.tectonic.ui:label' + apiservicedefinitions: {} + install: + strategy: deployment + spec: + deployments: + - name: kiali-operator + spec: + replicas: 1 + selector: + matchLabels: + app: kiali-operator + template: + metadata: + name: kiali-operator + labels: + app: kiali-operator + version: v1.4.2 + spec: + serviceAccountName: kiali-operator + containers: + - name: ansible + command: + - /usr/local/bin/ao-logs + - /tmp/ansible-operator/runner + - stdout + image: quay.io/kiali/kiali-operator:v1.4.2 + imagePullPolicy: "IfNotPresent" + volumeMounts: + - mountPath: /tmp/ansible-operator/runner + name: runner + readOnly: true + - name: operator + image: quay.io/kiali/kiali-operator:v1.4.2 + imagePullPolicy: "IfNotPresent" + volumeMounts: + - mountPath: /tmp/ansible-operator/runner + name: runner + env: + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: "kiali-operator" + volumes: + - name: runner + emptyDir: {} + clusterPermissions: + - rules: + - apiGroups: [""] + resources: + - configmaps + - endpoints + - events + - persistentvolumeclaims + - pods + - serviceaccounts + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: [""] + resources: + - namespaces + verbs: + - get + - list + - patch + - apiGroups: ["apps"] + resources: + - deployments + - replicasets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["monitoring.coreos.com"] + resources: + - servicemonitors + verbs: + - create + - get + - apiGroups: ["apps"] + resourceNames: + - kiali-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: ["kiali.io"] + resources: + - '*' + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["rbac.authorization.k8s.io"] + resources: + - clusterrolebindings + - clusterroles + - rolebindings + - roles + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["apiextensions.k8s.io"] + resources: + - customresourcedefinitions + verbs: + - get + - list + - watch + - apiGroups: ["extensions"] + resources: + - ingresses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["route.openshift.io"] + resources: + - routes + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["oauth.openshift.io"] + resources: + - oauthclients + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: ["monitoring.kiali.io"] + resources: + - monitoringdashboards + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + # The permissions below are for Kiali itself; operator needs these so it can escalate when creating Kiali's roles + - apiGroups: [""] + resources: + - configmaps + - endpoints + - namespaces + - nodes + - pods + - pods/log + - replicationcontrollers + - services + verbs: + - get + - list + - watch + - apiGroups: ["extensions", "apps"] + resources: + - deployments + - replicasets + - statefulsets + verbs: + - get + - list + - watch + - apiGroups: ["autoscaling"] + resources: + - horizontalpodautoscalers + verbs: + - get + - list + - watch + - apiGroups: ["batch"] + resources: + - cronjobs + - jobs + verbs: + - get + - list + - watch + - apiGroups: ["config.istio.io"] + resources: + - adapters + - apikeys + - bypasses + - authorizations + - checknothings + - circonuses + - cloudwatches + - deniers + - dogstatsds + - edges + - fluentds + - handlers + - instances + - kubernetesenvs + - kuberneteses + - listcheckers + - listentries + - logentries + - memquotas + - metrics + - noops + - opas + - prometheuses + - quotas + - quotaspecbindings + - quotaspecs + - rbacs + - redisquotas + - reportnothings + - rules + - signalfxs + - solarwindses + - stackdrivers + - statsds + - stdios + - templates + - tracespans + - zipkins + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["networking.istio.io"] + resources: + - destinationrules + - gateways + - serviceentries + - sidecars + - virtualservices + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["authentication.istio.io"] + resources: + - meshpolicies + - policies + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["rbac.istio.io"] + resources: + - clusterrbacconfigs + - rbacconfigs + - servicerolebindings + - serviceroles + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["authentication.maistra.io"] + resources: + - servicemeshpolicies + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["rbac.maistra.io"] + resources: + - servicemeshrbacconfigs + verbs: + - create + - delete + - get + - list + - patch + - watch + - apiGroups: ["apps.openshift.io"] + resources: + - deploymentconfigs + verbs: + - get + - list + - watch + - apiGroups: ["project.openshift.io"] + resources: + - projects + verbs: + - get + - apiGroups: ["route.openshift.io"] + resources: + - routes + verbs: + - get + - apiGroups: ["monitoring.kiali.io"] + resources: + - monitoringdashboards + verbs: + - get + - list + serviceAccountName: kiali-operator +kind: ConfigMap +metadata: + annotations: + olm.sourceImage: bundle-image + operators.coreos.com.bundle.mediatype: operator-registry+v1 + operators.coreos.com.bundle.resources: manifests+metadata + creationTimestamp: "2019-10-14T19:33:09Z" + name: myconfigmap + namespace: default + resourceVersion: "485" + selfLink: /api/v1/namespaces/default/configmaps/myconfigmap + uid: b2474832-0847-4d50-9336-93e253ebf708 From 914eee25824242ef049cf61e466e212e68f653b9 Mon Sep 17 00:00:00 2001 From: Jeff Peeler Date: Wed, 23 Oct 2019 18:01:22 -0400 Subject: [PATCH 3/3] chore(configmap): load packagemanifest data from annotations Previously, the package manifest data was going to be included as a file within the bundle. The planning changed and this updates the implementation to match. The configmap annotations for manifest data has been made as a requirement. --- pkg/configmap/configmap.go | 34 ++++++++++++++++--- pkg/configmap/configmap_test.go | 30 ++-------------- pkg/configmap/testdata/bundle-with-all.yaml | 14 +++++--- .../testdata/bundle-with-bad-resource.cm.yaml | 7 ++++ .../bundle-with-kube-resources.cm.yaml | 7 ++++ .../bundle-with-multiple-csvs.cm.yaml | 7 ++++ ...le-with-multiple-package-manifests.cm.yaml | 12 ------- .../bundle-with-package-manifest.cm.yaml | 28 --------------- pkg/configmap/testdata/bundle.cm.yaml | 7 ++++ 9 files changed, 69 insertions(+), 77 deletions(-) delete mode 100644 pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml delete mode 100644 pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml diff --git a/pkg/configmap/configmap.go b/pkg/configmap/configmap.go index 58e6240d0..9400bcf6e 100644 --- a/pkg/configmap/configmap.go +++ b/pkg/configmap/configmap.go @@ -3,6 +3,7 @@ package configmap import ( "errors" "fmt" + libbundle "github.com/operator-framework/operator-registry/pkg/lib/bundle" "github.com/operator-framework/operator-registry/pkg/registry" "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" @@ -44,17 +45,42 @@ func (l *BundleLoader) Load(cm *corev1.ConfigMap) (manifest *Manifest, err error "configmap": fmt.Sprintf("%s/%s", cm.GetNamespace(), cm.GetName()), }) - bundle, skipped, bundleErr := loadBundle(logger, cm.Data) + bundle, _, bundleErr := loadBundle(logger, cm.Data) if bundleErr != nil { err = fmt.Errorf("failed to extract bundle from configmap - %v", bundleErr) return } - packageManifest := loadPackageManifest(logger, skipped) + // 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: packageManifest, + Bundle: bundle, + PackageManifest: ®istry.PackageManifest{ + PackageName: annotations[libbundle.PackageLabel], + Channels: packageChannels, + DefaultChannelName: annotations[libbundle.ChannelDefaultLabel], + }, } return } diff --git a/pkg/configmap/configmap_test.go b/pkg/configmap/configmap_test.go index 523a40837..27dc97ba5 100644 --- a/pkg/configmap/configmap_test.go +++ b/pkg/configmap/configmap_test.go @@ -17,16 +17,11 @@ func TestLoad(t *testing.T) { assertFunc func(t *testing.T, manifestGot *Manifest) }{ { - name: "BundleWithCsvAndCrdOnly", + name: "BundleWithCsvAndCrd", source: "testdata/bundle.cm.yaml", assertFunc: func(t *testing.T, manifestGot *Manifest) { assert.NotNil(t, manifestGot.Bundle) - assert.Nil(t, manifestGot.PackageManifest) - - // We don't populate package, channel and name of a bundle object. - assert.Empty(t, manifestGot.Bundle.Package) - assert.Empty(t, manifestGot.Bundle.Channel) - assert.Empty(t, manifestGot.Bundle.Name) + assert.NotNil(t, manifestGot.PackageManifest) csvGot, errGot := manifestGot.Bundle.ClusterServiceVersion() assert.NoError(t, errGot) @@ -37,27 +32,6 @@ func TestLoad(t *testing.T) { assert.Equal(t, 1, len(crdListGot)) }, }, - { - name: "BundleWithPackageManifest", - source: "testdata/bundle-with-package-manifest.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - assert.NotNil(t, manifestGot.PackageManifest) - - assert.Equal(t, "etcd", manifestGot.PackageManifest.PackageName) - }, - }, - { - name: "BundleWithMultiplePackageManifests", - source: "testdata/bundle-with-multiple-package-manifests.cm.yaml", - assertFunc: func(t *testing.T, manifestGot *Manifest) { - assert.NotNil(t, manifestGot.Bundle) - assert.NotNil(t, manifestGot.PackageManifest) - - name := manifestGot.PackageManifest.PackageName - assert.True(t, name == "first" || name == "second") - }, - }, { name: "BundleWithBuiltInKubeTypes", source: "testdata/bundle-with-kube-resources.cm.yaml", diff --git a/pkg/configmap/testdata/bundle-with-all.yaml b/pkg/configmap/testdata/bundle-with-all.yaml index c0fdd6776..66a703d92 100644 --- a/pkg/configmap/testdata/bundle-with-all.yaml +++ b/pkg/configmap/testdata/bundle-with-all.yaml @@ -606,11 +606,15 @@ kind: ConfigMap metadata: annotations: olm.sourceImage: bundle-image - operators.coreos.com.bundle.mediatype: operator-registry+v1 - operators.coreos.com.bundle.resources: manifests+metadata - creationTimestamp: "2019-10-14T19:33:09Z" + operators.operatorframework.io.bundle.channel.default.v1: stable + operators.operatorframework.io.bundle.channels.v1: alpha,stable + operators.operatorframework.io.bundle.manifests.v1: /manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: /metadata/ + operators.operatorframework.io.bundle.package.v1: kiali-operator.v1.4.2 + creationTimestamp: "2019-10-18T18:35:16Z" name: myconfigmap namespace: default - resourceVersion: "485" + resourceVersion: "98847" selfLink: /api/v1/namespaces/default/configmaps/myconfigmap - uid: b2474832-0847-4d50-9336-93e253ebf708 + uid: 96a7866e-7b9c-4807-882f-18f3ffb11568 diff --git a/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml b/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml index 35899ffb3..220986021 100644 --- a/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml +++ b/pkg/configmap/testdata/bundle-with-bad-resource.cm.yaml @@ -3,6 +3,13 @@ apiVersion: v1 metadata: name: ocs namespace: kube-system + annotations: + operators.operatorframework.io.bundle.channel.default.v1: stable + operators.operatorframework.io.bundle.channels.v1: alpha,stable + operators.operatorframework.io.bundle.manifests.v1: /manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: /metadata/ + operators.operatorframework.io.bundle.package.v1: kiali-operator.v1.4.2 data: crd.yaml: |- diff --git a/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml b/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml index ed498f877..476594948 100644 --- a/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml +++ b/pkg/configmap/testdata/bundle-with-kube-resources.cm.yaml @@ -3,6 +3,13 @@ apiVersion: v1 metadata: name: ocs namespace: kube-system + annotations: + operators.operatorframework.io.bundle.channel.default.v1: stable + operators.operatorframework.io.bundle.channels.v1: alpha,stable + operators.operatorframework.io.bundle.manifests.v1: /manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: /metadata/ + operators.operatorframework.io.bundle.package.v1: kiali-operator.v1.4.2 data: my.kube.type.yaml: |- diff --git a/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml b/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml index 21051b502..f263711af 100644 --- a/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml +++ b/pkg/configmap/testdata/bundle-with-multiple-csvs.cm.yaml @@ -3,6 +3,13 @@ apiVersion: v1 metadata: name: ocs namespace: kube-system + annotations: + operators.operatorframework.io.bundle.channel.default.v1: stable + operators.operatorframework.io.bundle.channels.v1: alpha,stable + operators.operatorframework.io.bundle.manifests.v1: /manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: /metadata/ + operators.operatorframework.io.bundle.package.v1: kiali-operator.v1.4.2 data: first.csv.yaml: |- diff --git a/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml b/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml deleted file mode 100644 index e060ccd3d..000000000 --- a/pkg/configmap/testdata/bundle-with-multiple-package-manifests.cm.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: ocs - namespace: kube-system - -data: - first.package.yaml: |- - packageName: first - second.package.yaml: |- - packageName: second - diff --git a/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml b/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml deleted file mode 100644 index e09f6c2d4..000000000 --- a/pkg/configmap/testdata/bundle-with-package-manifest.cm.yaml +++ /dev/null @@ -1,28 +0,0 @@ -kind: ConfigMap -apiVersion: v1 -metadata: - name: ocs - namespace: kube-system - -data: - crd.yaml: |- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - name: alertmanagers.monitoring.coreos.com - spec: - csv.yaml: |- - apiVersion: operators.coreos.com/v1alpha1 - kind: ClusterServiceVersion - metadata: - name: etcdoperator.v0.6.1 - namespace: placeholder - spec: - package.yaml: |- - packageName: etcd - defaultChannel: alpha - channels: - - name: alpha - currentCSV: etcdoperator.v0.9.4 - - name: beta - currentCSV: etcdoperator.v0.9.4-beta diff --git a/pkg/configmap/testdata/bundle.cm.yaml b/pkg/configmap/testdata/bundle.cm.yaml index b6ecb6092..de0f9c2a9 100644 --- a/pkg/configmap/testdata/bundle.cm.yaml +++ b/pkg/configmap/testdata/bundle.cm.yaml @@ -3,6 +3,13 @@ apiVersion: v1 metadata: name: ocs namespace: kube-system + annotations: + operators.operatorframework.io.bundle.channel.default.v1: stable + operators.operatorframework.io.bundle.channels.v1: alpha,stable + operators.operatorframework.io.bundle.manifests.v1: /manifests/ + operators.operatorframework.io.bundle.mediatype.v1: registry+v1 + operators.operatorframework.io.bundle.metadata.v1: /metadata/ + operators.operatorframework.io.bundle.package.v1: kiali-operator.v1.4.2 data: crd.yaml: |-