Skip to content

Commit

Permalink
Add unit test cases
Browse files Browse the repository at this point in the history
Signed-off-by: Vu Dinh <vdinh@redhat.com>
  • Loading branch information
dinhxuanvu committed Apr 17, 2020
1 parent 648efcd commit efbfd24
Show file tree
Hide file tree
Showing 23 changed files with 1,222 additions and 33 deletions.
@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdbackups.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdBackup
listKind: EtcdBackupList
plural: etcdbackups
singular: etcdbackup
scope: Namespaced
version: v1beta2
@@ -0,0 +1,16 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdclusters.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdCluster
listKind: EtcdClusterList
plural: etcdclusters
shortNames:
- etcdclus
- etcd
singular: etcdcluster
scope: Namespaced
version: v1beta2

Large diffs are not rendered by default.

@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdrestores.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdRestore
listKind: EtcdRestoreList
plural: etcdrestores
singular: etcdrestore
scope: Namespaced
version: v1beta2
@@ -0,0 +1,7 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable,beta
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: etcd
@@ -0,0 +1,5 @@
dependencies:
- type: olm.crd
group: test.coreos.com
version: v1alpha1
kind: testcrd
@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdbackups.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdBackup
listKind: EtcdBackupList
plural: etcdbackups
singular: etcdbackup
scope: Namespaced
version: v1beta2
@@ -0,0 +1,16 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdclusters.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdCluster
listKind: EtcdClusterList
plural: etcdclusters
shortNames:
- etcdclus
- etcd
singular: etcdcluster
scope: Namespaced
version: v1beta2

Large diffs are not rendered by default.

@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdrestores.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdRestore
listKind: EtcdRestoreList
plural: etcdrestores
singular: etcdrestore
scope: Namespaced
version: v1beta2
@@ -0,0 +1,7 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable,beta
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: etcd
@@ -0,0 +1,2 @@
dependencies:
- type: olm.gvk
@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdbackups.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdBackup
listKind: EtcdBackupList
plural: etcdbackups
singular: etcdbackup
scope: Namespaced
version: v1beta2
@@ -0,0 +1,16 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdclusters.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdCluster
listKind: EtcdClusterList
plural: etcdclusters
shortNames:
- etcdclus
- etcd
singular: etcdcluster
scope: Namespaced
version: v1beta2

Large diffs are not rendered by default.

@@ -0,0 +1,13 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: etcdrestores.etcd.database.coreos.com
spec:
group: etcd.database.coreos.com
names:
kind: EtcdRestore
listKind: EtcdRestoreList
plural: etcdrestores
singular: etcdrestore
scope: Namespaced
version: v1beta2
@@ -0,0 +1,7 @@
annotations:
operators.operatorframework.io.bundle.channel.default.v1: stable
operators.operatorframework.io.bundle.channels.v1: stable,beta
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: etcd
@@ -0,0 +1,8 @@
dependencies:
- type: olm.package
version: "0.2.0"
- type: olm.package
packageName: testoperator
version: ">!0.2.0"
- type: olm.package
packageName: testoperator2
@@ -0,0 +1,8 @@
dependencies:
- type: olm.package
packgeName: testoperator
version: >0.2.0
- type: olm.gvk
group: test.coreos.com
kind: testapi
version: v1
80 changes: 56 additions & 24 deletions pkg/lib/bundle/validate.go
Expand Up @@ -22,7 +22,6 @@ import (

y "github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"gopkg.in/yaml.v2"
)

type Meta struct {
Expand Down Expand Up @@ -114,28 +113,42 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
continue
}

err = registry.ParseDependenciesFile(filepath.Join(metadataDir, f.Name()), dependenciesFile)
err = parseDependenciesFile(filepath.Join(metadataDir, f.Name()), dependenciesFile)
if err != nil || len(dependenciesFile.Dependencies) < 1 {
continue
} else {
i.logger.Info("found dependencies file")
}
}

if len(dependenciesFile.Dependencies) < 1 {
i.logger.Info("Could not find dependencies file")
} else {
i.logger.Info("Found dependencies file")
errs := validateDependencies(dependenciesFile)
if errs != nil {
validationErrors = append(validationErrors, errs...)
}
}

if fileAnnotations.Annotations == nil {
validationErrors = append(validationErrors, fmt.Errorf("Could not find annotations file"))
} else {
i.logger.Info("Found annotations file")
errs := validateAnnotations(mediaType, fileAnnotations)
if errs != nil {
validationErrors = append(validationErrors, errs...)
}
}

annotationsFile, err := ioutil.ReadFile(filepath.Join(metadataDir, AnnotationsFile))
if err != nil {
fmtErr := fmt.Errorf("Unable to read annotations.yaml file: %s", err.Error())
validationErrors = append(validationErrors, fmtErr)
if len(validationErrors) > 0 {
return NewValidationError(validationErrors)
}

return nil
}

// Validate the annotations file
func validateAnnotations(mediaType string, fileAnnotations *AnnotationMetadata) []error {
var validationErrors []error
annotations := map[string]string{
MediatypeLabel: mediaType,
ManifestsLabel: ManifestsDir,
Expand All @@ -145,18 +158,9 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
ChannelDefaultLabel: "",
}

i.logger.Debug("Validating annotations file")

err = yaml.Unmarshal(annotationsFile, &fileAnnotations)
if err != nil {
validationErrors = append(validationErrors, fmt.Errorf("Unable to parse annotations file"))
}

for label, item := range annotations {
val, ok := fileAnnotations.Annotations[label]
if ok {
i.logger.Debugf(`Found annotation "%s" with value "%s"`, label, val)
} else {
if !ok {
aErr := fmt.Errorf("Missing annotation %q", label)
validationErrors = append(validationErrors, aErr)
}
Expand Down Expand Up @@ -187,10 +191,16 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
}
}

_, err = ValidateChannelDefault(annotations[ChannelsLabel], annotations[ChannelDefaultLabel])
_, err := ValidateChannelDefault(annotations[ChannelsLabel], annotations[ChannelDefaultLabel])
if err != nil {
validationErrors = append(validationErrors, err)
}
return validationErrors
}

// Validate the dependencies file
func validateDependencies(dependenciesFile *registry.DependenciesFile) []error {
var validationErrors []error

// Validate dependencies if exists
for _, d := range dependenciesFile.Dependencies {
Expand All @@ -207,13 +217,9 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
errs = append(errs, fmt.Errorf("Unsupported dependency type %s", d.GetType()))
}
validationErrors = append(validationErrors, errs...)

if len(validationErrors) > 0 {
return NewValidationError(validationErrors)
}
}

return nil
return validationErrors
}

// ValidateBundleContent confirms that the CSV and CRD files inside the bundle
Expand Down Expand Up @@ -333,6 +339,32 @@ func (i imageValidator) ValidateBundleContent(manifestDir string) error {
return nil
}

func parseDependenciesFile(path string, depFile *registry.DependenciesFile) error {
deps := registry.Dependencies{}
err := registry.DecodeFile(path, &deps)

if err != nil || len(deps.RawMessage) == 0 {
return fmt.Errorf("Unable to decode the dependencies file %s", path)
}

depList := []registry.Dependency{}
for _, v := range deps.RawMessage {
jsonStr, _ := json.Marshal(v)
dep := registry.Dependency{}
err := json.Unmarshal(jsonStr, &dep)
if err != nil {
return err
}

dep.Value = string(jsonStr)
depList = append(depList, dep)
}

depFile.Dependencies = depList

return nil
}

// Validate if the file is kubecle-able
func validateKubectlable(fileBytes []byte) error {
exampleFileBytesJSON, err := y.YAMLToJSON(fileBytes)
Expand Down
59 changes: 59 additions & 0 deletions pkg/lib/bundle/validate_test.go
Expand Up @@ -64,6 +64,65 @@ func TestValidateBundleFormat(t *testing.T) {
require.NoError(t, err)
}

func TestValidateBundleDependencies(t *testing.T) {
logger := logrus.NewEntry(logrus.New())

validator := imageValidator{
logger: logger,
}

var table = []struct {
description string
mediaType string
directory string
errStrings map[string]struct{}
}{
{
description: "registryv1 bundle/invalid gvk dependency",
mediaType: RegistryV1Type,
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_gvk_dependency/",
errStrings: map[string]struct{}{
"API Group is empty": struct{}{},
"API Version is empty": struct{}{},
"API Kind is empty": struct{}{},
},
},
{
description: "registryv1 bundle/invalid package dependency",
mediaType: RegistryV1Type,
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_package_dependency/",
errStrings: map[string]struct{}{
"Invalid semver format version": struct{}{},
"Package version is empty": struct{}{},
"Package name is empty": struct{}{},
},
},
{
description: "registryv1 bundle/invalid dependency type",
mediaType: RegistryV1Type,
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_dependency_type/",
errStrings: map[string]struct{}{
"Unsupported dependency type olm.crd": struct{}{},
},
},
}

for i, tt := range table {
fmt.Println(tt.directory)
err := validator.ValidateBundleFormat(tt.directory)
var validationError ValidationError
if err != nil {
isValidationErr := errors.As(err, &validationError)
require.True(t, isValidationErr)
}
require.Len(t, validationError.Errors, len(tt.errStrings), table[i].description)
for _, e := range validationError.Errors {
_, ok := tt.errStrings[e.Error()]
require.True(t, ok, "Unable to find this error %s", e.Error())
}
}
}

func TestValidateBundle_InvalidRegistryVersion(t *testing.T) {
dir := "./testdata/validate/invalid_annotations_bundle"

Expand Down

0 comments on commit efbfd24

Please sign in to comment.