From fdfcb35e6d330fca94841b113c8140cf58930e35 Mon Sep 17 00:00:00 2001 From: Kutluhan Metin Date: Tue, 25 Jul 2023 20:27:55 +0300 Subject: [PATCH] Fix min kube version validation (#286) * fixes https://github.com/operator-framework/operator-sdk/issues/5995 * fix comment change * fix imports --- pkg/validation/internal/csv.go | 15 +++++++++ pkg/validation/internal/csv_test.go | 13 +++++++- pkg/validation/internal/operatorhub.go | 2 +- pkg/validation/internal/operatorhub_test.go | 2 +- .../testdata/badAnnotationNames.csv.yaml | 1 + .../internal/testdata/badName.csv.yaml | 1 + .../testdata/correct.csv.empty.example.yaml | 1 + ...correct.csv.olm.properties.annotation.yaml | 1 + .../correct.csv.with.conversion.webhook.yaml | 1 + .../internal/testdata/correct.csv.yaml | 1 + .../testdata/dataTypeMismatch.csv.yaml | 1 + .../testdata/invalid.alm-examples.csv.yaml | 1 + .../invalid_min_kube_version.csv.yaml | 32 +++++++++++++++++++ .../internal/testdata/noInstallMode.csv.yaml | 1 + 14 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 pkg/validation/internal/testdata/invalid_min_kube_version.csv.yaml diff --git a/pkg/validation/internal/csv.go b/pkg/validation/internal/csv.go index b5b7683c0..f0c185385 100644 --- a/pkg/validation/internal/csv.go +++ b/pkg/validation/internal/csv.go @@ -3,6 +3,7 @@ package internal import ( "encoding/json" "fmt" + "github.com/blang/semver/v4" "io" "reflect" "strings" @@ -45,6 +46,8 @@ func validateCSV(csv *v1alpha1.ClusterServiceVersion) errors.ManifestResult { result.Add(validateExamplesAnnotations(csv)...) // validate installModes result.Add(validateInstallModes(csv)...) + // validate min Kubernetes version + result.Add(validateMinKubeVersion(*csv)...) // check missing optional/mandatory fields. result.Add(checkFields(*csv)...) // validate case sensitive annotation names @@ -240,3 +243,15 @@ func validateVersionKind(csv *v1alpha1.ClusterServiceVersion) (errs []errors.Err } return } + +// validateMinKubeVersion checks format of spec.minKubeVersion field +func validateMinKubeVersion(csv v1alpha1.ClusterServiceVersion) (errs []errors.Error) { + if len(strings.TrimSpace(csv.Spec.MinKubeVersion)) == 0 { + errs = append(errs, errors.WarnInvalidCSV(minKubeVersionWarnMessage, csv.GetName())) + } else { + if _, err := semver.Parse(csv.Spec.MinKubeVersion); err != nil { + errs = append(errs, errors.ErrInvalidCSV(fmt.Sprintf("csv.Spec.MinKubeVersion has an invalid value: %s", csv.Spec.MinKubeVersion), csv.GetName())) + } + } + return errs +} diff --git a/pkg/validation/internal/csv_test.go b/pkg/validation/internal/csv_test.go index 44f1ae870..6925216aa 100644 --- a/pkg/validation/internal/csv_test.go +++ b/pkg/validation/internal/csv_test.go @@ -6,8 +6,9 @@ import ( "path/filepath" "testing" - "github.com/ghodss/yaml" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + + "github.com/ghodss/yaml" "github.com/operator-framework/api/pkg/validation/errors" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -107,6 +108,16 @@ func TestValidateCSV(t *testing.T) { }, filepath.Join("testdata", "correct.csv.olm.properties.annotation.yaml"), }, + { + validatorFuncTest{ + description: "should fail when spec.minKubeVersion is not in semantic version format", + wantErr: true, + errors: []errors.Error{ + errors.ErrInvalidCSV(`csv.Spec.MinKubeVersion has an invalid value: 1.21`, "test-operator.v0.0.1"), + }, + }, + filepath.Join("testdata", "invalid_min_kube_version.csv.yaml"), + }, } for _, c := range cases { diff --git a/pkg/validation/internal/operatorhub.go b/pkg/validation/internal/operatorhub.go index f5da37a27..e82d10287 100644 --- a/pkg/validation/internal/operatorhub.go +++ b/pkg/validation/internal/operatorhub.go @@ -240,7 +240,7 @@ func checkSpecMinKubeVersion(checks CSVChecks) CSVChecks { if len(strings.TrimSpace(checks.csv.Spec.MinKubeVersion)) == 0 { checks.warns = append(checks.warns, fmt.Errorf(minKubeVersionWarnMessage)) } else { - if _, err := semver.ParseTolerant(checks.csv.Spec.MinKubeVersion); err != nil { + if _, err := semver.Parse(checks.csv.Spec.MinKubeVersion); err != nil { checks.errs = append(checks.errs, fmt.Errorf("csv.Spec.MinKubeVersion has an invalid value: %s", checks.csv.Spec.MinKubeVersion)) } } diff --git a/pkg/validation/internal/operatorhub_test.go b/pkg/validation/internal/operatorhub_test.go index 6e3406283..d8c049180 100644 --- a/pkg/validation/internal/operatorhub_test.go +++ b/pkg/validation/internal/operatorhub_test.go @@ -218,7 +218,7 @@ func TestCheckSpecMinKubeVersion(t *testing.T) { }{ { name: "should work with a valid value", - args: args{minKubeVersion: "1.16"}, + args: args{minKubeVersion: "1.16.0"}, }, { name: "should return a warning when the minKubeVersion is not informed ", diff --git a/pkg/validation/internal/testdata/badAnnotationNames.csv.yaml b/pkg/validation/internal/testdata/badAnnotationNames.csv.yaml index af2c3e74f..f95a02c6c 100644 --- a/pkg/validation/internal/testdata/badAnnotationNames.csv.yaml +++ b/pkg/validation/internal/testdata/badAnnotationNames.csv.yaml @@ -14,6 +14,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: | etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd. diff --git a/pkg/validation/internal/testdata/badName.csv.yaml b/pkg/validation/internal/testdata/badName.csv.yaml index 582aa8d93..ad306cc26 100644 --- a/pkg/validation/internal/testdata/badName.csv.yaml +++ b/pkg/validation/internal/testdata/badName.csv.yaml @@ -11,6 +11,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: something keywords: ['etcd', 'key value', 'database', 'coreos', 'open source'] diff --git a/pkg/validation/internal/testdata/correct.csv.empty.example.yaml b/pkg/validation/internal/testdata/correct.csv.empty.example.yaml index 2aa19870d..6c1db26e8 100644 --- a/pkg/validation/internal/testdata/correct.csv.empty.example.yaml +++ b/pkg/validation/internal/testdata/correct.csv.empty.example.yaml @@ -8,6 +8,7 @@ metadata: annotations: "alm-examples": "" spec: + minKubeVersion: 1.21.0 version: 0.9.0 installModes: - type: AllNamespaces diff --git a/pkg/validation/internal/testdata/correct.csv.olm.properties.annotation.yaml b/pkg/validation/internal/testdata/correct.csv.olm.properties.annotation.yaml index 6794c5121..2d9773a5e 100644 --- a/pkg/validation/internal/testdata/correct.csv.olm.properties.annotation.yaml +++ b/pkg/validation/internal/testdata/correct.csv.olm.properties.annotation.yaml @@ -9,6 +9,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' olm.properties: '[{"type": "foo", "value": "bar"}]' spec: + minKubeVersion: 1.21.0 version: 0.9.0 installModes: - type: AllNamespaces diff --git a/pkg/validation/internal/testdata/correct.csv.with.conversion.webhook.yaml b/pkg/validation/internal/testdata/correct.csv.with.conversion.webhook.yaml index 2bef1ecb2..fc791c472 100644 --- a/pkg/validation/internal/testdata/correct.csv.with.conversion.webhook.yaml +++ b/pkg/validation/internal/testdata/correct.csv.with.conversion.webhook.yaml @@ -11,6 +11,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: | etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd. diff --git a/pkg/validation/internal/testdata/correct.csv.yaml b/pkg/validation/internal/testdata/correct.csv.yaml index 4dad39663..9ba9a487d 100644 --- a/pkg/validation/internal/testdata/correct.csv.yaml +++ b/pkg/validation/internal/testdata/correct.csv.yaml @@ -11,6 +11,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: | etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd. diff --git a/pkg/validation/internal/testdata/dataTypeMismatch.csv.yaml b/pkg/validation/internal/testdata/dataTypeMismatch.csv.yaml index a915b115c..5c65ee045 100644 --- a/pkg/validation/internal/testdata/dataTypeMismatch.csv.yaml +++ b/pkg/validation/internal/testdata/dataTypeMismatch.csv.yaml @@ -11,6 +11,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: | etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd. diff --git a/pkg/validation/internal/testdata/invalid.alm-examples.csv.yaml b/pkg/validation/internal/testdata/invalid.alm-examples.csv.yaml index 1d6bfc13b..2eb8e9adb 100644 --- a/pkg/validation/internal/testdata/invalid.alm-examples.csv.yaml +++ b/pkg/validation/internal/testdata/invalid.alm-examples.csv.yaml @@ -7,6 +7,7 @@ metadata: name: test-operator.v0.0.1 namespace: placeholder spec: + minKubeVersion: 1.21.0 displayName: test-operator install: strategy: deployment diff --git a/pkg/validation/internal/testdata/invalid_min_kube_version.csv.yaml b/pkg/validation/internal/testdata/invalid_min_kube_version.csv.yaml new file mode 100644 index 000000000..a46f55ec7 --- /dev/null +++ b/pkg/validation/internal/testdata/invalid_min_kube_version.csv.yaml @@ -0,0 +1,32 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + name: test-operator.v0.0.1 + namespace: placeholder +spec: + minKubeVersion: 1.21 + displayName: test-operator + install: + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: false + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - test-operator + links: + - name: Test Operator + url: https://test-operator.domain + maintainers: + - email: your@email.com + name: Maintainer Name + maturity: alpha + provider: + name: Provider Name + url: https://your.domain + version: 0.0.1 \ No newline at end of file diff --git a/pkg/validation/internal/testdata/noInstallMode.csv.yaml b/pkg/validation/internal/testdata/noInstallMode.csv.yaml index f6d3e9297..db5eeae44 100644 --- a/pkg/validation/internal/testdata/noInstallMode.csv.yaml +++ b/pkg/validation/internal/testdata/noInstallMode.csv.yaml @@ -11,6 +11,7 @@ metadata: alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"","awsSecret":""}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":[""],"storageType":"S3","s3":{"path":"","awsSecret":""}}}]' description: etcd is a distributed key value store providing a reliable way to store data across a cluster of machines. spec: + minKubeVersion: 1.21.0 displayName: etcd description: | etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.