Skip to content

Commit a25687c

Browse files
authoredApr 20, 2020
Merge pull request operator-framework#277 from dinhxuanvu/opm-dep
Add dependencies validation to opm
2 parents 71ced38 + d76b2b5 commit a25687c

26 files changed

+1358
-42
lines changed
 

‎pkg/lib/bundle/generate.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ func GenerateDockerfile(mediaType, manifests, metadata, copyManifestDir, copyMet
384384

385385
// CONTENT
386386
fileContent += fmt.Sprintf("COPY %s %s\n", relativeManifestDirectory, "/manifests/")
387-
fileContent += fmt.Sprintf("COPY %s %s%s\n", filepath.Join(relativeMetadataDirectory, AnnotationsFile), "/metadata/", AnnotationsFile)
387+
fileContent += fmt.Sprintf("COPY %s %s\n", relativeMetadataDirectory, "/metadata/")
388388

389389
return []byte(fileContent), nil
390390
}

‎pkg/lib/bundle/generate_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ func TestGenerateDockerfileFunc(t *testing.T) {
209209
"LABEL operators.operatorframework.io.bundle.channels.v1=test5\n"+
210210
"LABEL operators.operatorframework.io.bundle.channel.default.v1=test5\n\n"+
211211
"COPY test2 /manifests/\n"+
212-
"COPY metadata/annotations.yaml /metadata/annotations.yaml\n", MetadataDir)
212+
"COPY metadata /metadata/\n", MetadataDir)
213213

214214
content, err := GenerateDockerfile("test1", "test2", MetadataDir, "test2/", "metadata/", "./", "test4", "test5", "")
215215
require.NoError(t, err)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdbackups.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdBackup
9+
listKind: EtcdBackupList
10+
plural: etcdbackups
11+
singular: etcdbackup
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdclusters.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdCluster
9+
listKind: EtcdClusterList
10+
plural: etcdclusters
11+
shortNames:
12+
- etcdclus
13+
- etcd
14+
singular: etcdcluster
15+
scope: Namespaced
16+
version: v1beta2

‎pkg/lib/bundle/testdata/validate/invalid_dependencies_bundle/invalid_dependency_type/manifests/etcdoperator.v0.9.4.clusterserviceversion.yaml

+309
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdrestores.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdRestore
9+
listKind: EtcdRestoreList
10+
plural: etcdrestores
11+
singular: etcdrestore
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
annotations:
2+
operators.operatorframework.io.bundle.channel.default.v1: stable
3+
operators.operatorframework.io.bundle.channels.v1: stable,beta
4+
operators.operatorframework.io.bundle.manifests.v1: manifests/
5+
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
6+
operators.operatorframework.io.bundle.metadata.v1: metadata/
7+
operators.operatorframework.io.bundle.package.v1: etcd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
dependencies:
2+
- type: olm.crd
3+
group: test.coreos.com
4+
version: v1alpha1
5+
kind: testcrd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdbackups.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdBackup
9+
listKind: EtcdBackupList
10+
plural: etcdbackups
11+
singular: etcdbackup
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdclusters.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdCluster
9+
listKind: EtcdClusterList
10+
plural: etcdclusters
11+
shortNames:
12+
- etcdclus
13+
- etcd
14+
singular: etcdcluster
15+
scope: Namespaced
16+
version: v1beta2

‎pkg/lib/bundle/testdata/validate/invalid_dependencies_bundle/invalid_gvk_dependency/manifests/etcdoperator.v0.9.4.clusterserviceversion.yaml

+309
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdrestores.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdRestore
9+
listKind: EtcdRestoreList
10+
plural: etcdrestores
11+
singular: etcdrestore
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
annotations:
2+
operators.operatorframework.io.bundle.channel.default.v1: stable
3+
operators.operatorframework.io.bundle.channels.v1: stable,beta
4+
operators.operatorframework.io.bundle.manifests.v1: manifests/
5+
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
6+
operators.operatorframework.io.bundle.metadata.v1: metadata/
7+
operators.operatorframework.io.bundle.package.v1: etcd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dependencies:
2+
- type: olm.gvk
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdbackups.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdBackup
9+
listKind: EtcdBackupList
10+
plural: etcdbackups
11+
singular: etcdbackup
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdclusters.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdCluster
9+
listKind: EtcdClusterList
10+
plural: etcdclusters
11+
shortNames:
12+
- etcdclus
13+
- etcd
14+
singular: etcdcluster
15+
scope: Namespaced
16+
version: v1beta2

‎pkg/lib/bundle/testdata/validate/invalid_dependencies_bundle/invalid_package_dependency/manifests/etcdoperator.v0.9.4.clusterserviceversion.yaml

+309
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: apiextensions.k8s.io/v1beta1
2+
kind: CustomResourceDefinition
3+
metadata:
4+
name: etcdrestores.etcd.database.coreos.com
5+
spec:
6+
group: etcd.database.coreos.com
7+
names:
8+
kind: EtcdRestore
9+
listKind: EtcdRestoreList
10+
plural: etcdrestores
11+
singular: etcdrestore
12+
scope: Namespaced
13+
version: v1beta2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
annotations:
2+
operators.operatorframework.io.bundle.channel.default.v1: stable
3+
operators.operatorframework.io.bundle.channels.v1: stable,beta
4+
operators.operatorframework.io.bundle.manifests.v1: manifests/
5+
operators.operatorframework.io.bundle.mediatype.v1: registry+v1
6+
operators.operatorframework.io.bundle.metadata.v1: metadata/
7+
operators.operatorframework.io.bundle.package.v1: etcd
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
dependencies:
2+
- type: olm.package
3+
version: "0.2.0"
4+
- type: olm.package
5+
packageName: testoperator
6+
version: ">!0.2.0"
7+
- type: olm.package
8+
packageName: testoperator2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
dependencies:
2+
- type: olm.package
3+
packgeName: testoperator
4+
version: >0.2.0
5+
- type: olm.gvk
6+
group: test.coreos.com
7+
kind: testapi
8+
version: v1

‎pkg/lib/bundle/validate.go

+106-23
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ import (
2222

2323
y "github.com/ghodss/yaml"
2424
log "github.com/sirupsen/logrus"
25-
"gopkg.in/yaml.v2"
2625
)
2726

2827
type Meta struct {
@@ -57,8 +56,8 @@ func (i imageValidator) PullBundleImage(imageTag, directory string) error {
5756
// Outputs:
5857
// error: ValidattionError which contains a list of errors
5958
func (i imageValidator) ValidateBundleFormat(directory string) error {
60-
var manifestsFound, metadataFound bool
61-
var annotationsDir, manifestsDir string
59+
var manifestsFound, metadataFound, annotationsFound, dependenciesFound bool
60+
var metadataDir, manifestsDir string
6261
var validationErrors []error
6362

6463
items, err := ioutil.ReadDir(directory)
@@ -76,7 +75,7 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
7675
case strings.TrimSuffix(MetadataDir, "/"):
7776
i.logger.Debug("Found metadata directory")
7877
metadataFound = true
79-
annotationsDir = filepath.Join(directory, MetadataDir)
78+
metadataDir = filepath.Join(directory, MetadataDir)
8079
}
8180
}
8281
}
@@ -99,16 +98,62 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
9998
validationErrors = append(validationErrors, err)
10099
}
101100

102-
// Validate annotations.yaml
103-
annotationsFile, err := ioutil.ReadFile(filepath.Join(annotationsDir, AnnotationsFile))
101+
// Validate annotations file
102+
files, err := ioutil.ReadDir(metadataDir)
104103
if err != nil {
105-
fmtErr := fmt.Errorf("Unable to read annotations.yaml file: %s", err.Error())
106-
validationErrors = append(validationErrors, fmtErr)
104+
validationErrors = append(validationErrors, err)
105+
}
106+
107+
// Look for the metadata and manifests sub-directories to find the annotations file
108+
fileAnnotations := &AnnotationMetadata{}
109+
dependenciesFile := &registry.DependenciesFile{}
110+
for _, f := range files {
111+
if !annotationsFound {
112+
err = registry.DecodeFile(filepath.Join(metadataDir, f.Name()), fileAnnotations)
113+
if err == nil && fileAnnotations.Annotations != nil {
114+
annotationsFound = true
115+
continue
116+
}
117+
}
118+
119+
if !dependenciesFound {
120+
err = parseDependenciesFile(filepath.Join(metadataDir, f.Name()), dependenciesFile)
121+
if err == nil && len(dependenciesFile.Dependencies) > 0 {
122+
dependenciesFound = true
123+
}
124+
}
125+
}
126+
127+
if !annotationsFound {
128+
validationErrors = append(validationErrors, fmt.Errorf("Could not find annotations file"))
129+
} else {
130+
i.logger.Info("Found annotations file")
131+
errs := validateAnnotations(mediaType, fileAnnotations)
132+
if errs != nil {
133+
validationErrors = append(validationErrors, errs...)
134+
}
135+
}
136+
137+
if !dependenciesFound {
138+
i.logger.Info("Could not find dependencies file")
139+
} else {
140+
i.logger.Info("Found dependencies file")
141+
errs := validateDependencies(dependenciesFile)
142+
if errs != nil {
143+
validationErrors = append(validationErrors, errs...)
144+
}
145+
}
146+
147+
if len(validationErrors) > 0 {
107148
return NewValidationError(validationErrors)
108149
}
109150

110-
var fileAnnotations AnnotationMetadata
151+
return nil
152+
}
111153

154+
// Validate the annotations file
155+
func validateAnnotations(mediaType string, fileAnnotations *AnnotationMetadata) []error {
156+
var validationErrors []error
112157
annotations := map[string]string{
113158
MediatypeLabel: mediaType,
114159
ManifestsLabel: ManifestsDir,
@@ -118,18 +163,9 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
118163
ChannelDefaultLabel: "",
119164
}
120165

121-
i.logger.Debug("Validating annotations.yaml")
122-
123-
err = yaml.Unmarshal(annotationsFile, &fileAnnotations)
124-
if err != nil {
125-
validationErrors = append(validationErrors, fmt.Errorf("Unable to parse annotations.yaml file"))
126-
}
127-
128166
for label, item := range annotations {
129167
val, ok := fileAnnotations.Annotations[label]
130-
if ok {
131-
i.logger.Debugf(`Found annotation "%s" with value "%s"`, label, val)
132-
} else {
168+
if !ok {
133169
aErr := fmt.Errorf("Missing annotation %q", label)
134170
validationErrors = append(validationErrors, aErr)
135171
}
@@ -160,16 +196,37 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
160196
}
161197
}
162198

163-
_, err = ValidateChannelDefault(annotations[ChannelsLabel], annotations[ChannelDefaultLabel])
199+
_, err := ValidateChannelDefault(annotations[ChannelsLabel], annotations[ChannelDefaultLabel])
164200
if err != nil {
165201
validationErrors = append(validationErrors, err)
166202
}
203+
return validationErrors
204+
}
167205

168-
if len(validationErrors) > 0 {
169-
return NewValidationError(validationErrors)
206+
// Validate the dependencies file
207+
func validateDependencies(dependenciesFile *registry.DependenciesFile) []error {
208+
var validationErrors []error
209+
210+
// Validate dependencies if exists
211+
for _, d := range dependenciesFile.Dependencies {
212+
dep := d.GetTypeValue()
213+
errs := []error{}
214+
if dep != nil {
215+
switch dp := dep.(type) {
216+
case registry.GVKDependency:
217+
errs = dp.Validate()
218+
case registry.PackageDependency:
219+
errs = dp.Validate()
220+
default:
221+
errs = append(errs, fmt.Errorf("Unsupported dependency type %s", d.GetType()))
222+
}
223+
} else {
224+
errs = append(errs, fmt.Errorf("Unsupported dependency type %s", d.GetType()))
225+
}
226+
validationErrors = append(validationErrors, errs...)
170227
}
171228

172-
return nil
229+
return validationErrors
173230
}
174231

175232
// ValidateBundleContent confirms that the CSV and CRD files inside the bundle
@@ -289,6 +346,32 @@ func (i imageValidator) ValidateBundleContent(manifestDir string) error {
289346
return nil
290347
}
291348

349+
func parseDependenciesFile(path string, depFile *registry.DependenciesFile) error {
350+
deps := registry.Dependencies{}
351+
err := registry.DecodeFile(path, &deps)
352+
353+
if err != nil || len(deps.RawMessage) == 0 {
354+
return fmt.Errorf("Unable to decode the dependencies file %s", path)
355+
}
356+
357+
depList := []registry.Dependency{}
358+
for _, v := range deps.RawMessage {
359+
jsonStr, _ := json.Marshal(v)
360+
dep := registry.Dependency{}
361+
err := json.Unmarshal(jsonStr, &dep)
362+
if err != nil {
363+
return err
364+
}
365+
366+
dep.Value = string(jsonStr)
367+
depList = append(depList, dep)
368+
}
369+
370+
depFile.Dependencies = depList
371+
372+
return nil
373+
}
374+
292375
// Validate if the file is kubecle-able
293376
func validateKubectlable(fileBytes []byte) error {
294377
exampleFileBytesJSON, err := y.YAMLToJSON(fileBytes)

‎pkg/lib/bundle/validate_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,65 @@ func TestValidateBundleFormat(t *testing.T) {
6464
require.NoError(t, err)
6565
}
6666

67+
func TestValidateBundleDependencies(t *testing.T) {
68+
logger := logrus.NewEntry(logrus.New())
69+
70+
validator := imageValidator{
71+
logger: logger,
72+
}
73+
74+
var table = []struct {
75+
description string
76+
mediaType string
77+
directory string
78+
errStrings map[string]struct{}
79+
}{
80+
{
81+
description: "registryv1 bundle/invalid gvk dependency",
82+
mediaType: RegistryV1Type,
83+
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_gvk_dependency/",
84+
errStrings: map[string]struct{}{
85+
"API Group is empty": struct{}{},
86+
"API Version is empty": struct{}{},
87+
"API Kind is empty": struct{}{},
88+
},
89+
},
90+
{
91+
description: "registryv1 bundle/invalid package dependency",
92+
mediaType: RegistryV1Type,
93+
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_package_dependency/",
94+
errStrings: map[string]struct{}{
95+
"Invalid semver format version": struct{}{},
96+
"Package version is empty": struct{}{},
97+
"Package name is empty": struct{}{},
98+
},
99+
},
100+
{
101+
description: "registryv1 bundle/invalid dependency type",
102+
mediaType: RegistryV1Type,
103+
directory: "./testdata/validate/invalid_dependencies_bundle/invalid_dependency_type/",
104+
errStrings: map[string]struct{}{
105+
"Unsupported dependency type olm.crd": struct{}{},
106+
},
107+
},
108+
}
109+
110+
for i, tt := range table {
111+
fmt.Println(tt.directory)
112+
err := validator.ValidateBundleFormat(tt.directory)
113+
var validationError ValidationError
114+
if err != nil {
115+
isValidationErr := errors.As(err, &validationError)
116+
require.True(t, isValidationErr)
117+
}
118+
require.Len(t, validationError.Errors, len(tt.errStrings), table[i].description)
119+
for _, e := range validationError.Errors {
120+
_, ok := tt.errStrings[e.Error()]
121+
require.True(t, ok, "Unable to find this error %s", e.Error())
122+
}
123+
}
124+
}
125+
67126
func TestValidateBundle_InvalidRegistryVersion(t *testing.T) {
68127
dir := "./testdata/validate/invalid_annotations_bundle"
69128

‎pkg/registry/imageinput.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type ImageInput struct {
2222
}
2323

2424
func NewImageInput(to image.Reference, from string) (*ImageInput, error) {
25+
var annotationsFound, dependenciesFound bool
2526
path := from
2627
manifests := filepath.Join(path, "manifests")
2728
metadata := filepath.Join(path, "metadata")
@@ -39,22 +40,28 @@ func NewImageInput(to image.Reference, from string) (*ImageInput, error) {
3940
annotationsFile := &AnnotationsFile{}
4041
dependenciesFile := &DependenciesFile{}
4142
for _, f := range files {
42-
err = decodeFile(filepath.Join(metadata, f.Name()), annotationsFile)
43-
if err != nil || *annotationsFile == (AnnotationsFile{}) {
44-
log.Info("found annotations file searching for csv")
45-
continue
43+
if !annotationsFound {
44+
err = DecodeFile(filepath.Join(metadata, f.Name()), annotationsFile)
45+
if err == nil && *annotationsFile != (AnnotationsFile{}) {
46+
annotationsFound = true
47+
continue
48+
}
4649
}
4750

48-
err = parseDependenciesFile(filepath.Join(metadata, f.Name()), dependenciesFile)
49-
if err != nil || len(dependenciesFile.Dependencies) < 1 {
50-
continue
51-
} else {
52-
log.Info("found dependencies file searching for csv")
51+
if !dependenciesFound {
52+
err = parseDependenciesFile(filepath.Join(metadata, f.Name()), dependenciesFile)
53+
if err == nil && len(dependenciesFile.Dependencies) > 0 {
54+
dependenciesFound = true
55+
}
5356
}
5457
}
5558

56-
if *annotationsFile == (AnnotationsFile{}) {
57-
return nil, fmt.Errorf("Could not find annotations.yaml file")
59+
if !annotationsFound {
60+
return nil, fmt.Errorf("Could not find annotations file")
61+
}
62+
63+
if !dependenciesFound {
64+
log.Info("Could not find dependencies file")
5865
}
5966

6067
imageInput := &ImageInput{

‎pkg/registry/populator.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ func loadBundle(csvName string, dir string) (*Bundle, error) {
258258
obj = &unstructured.Unstructured{}
259259
path = filepath.Join(dir, f.Name())
260260
)
261-
if err = decodeFile(path, obj); err != nil {
261+
if err = DecodeFile(path, obj); err != nil {
262262
log.WithError(err).Debugf("could not decode file contents for %s", path)
263263
continue
264264
}
@@ -301,7 +301,7 @@ func (i *ImageInput) findCSV(manifests string) (*unstructured.Unstructured, erro
301301
obj = &unstructured.Unstructured{}
302302
path = filepath.Join(manifests, f.Name())
303303
)
304-
if err = decodeFile(path, obj); err != nil {
304+
if err = DecodeFile(path, obj); err != nil {
305305
log.WithError(err).Debugf("could not decode file contents for %s", path)
306306
continue
307307
}
@@ -355,8 +355,8 @@ func translateAnnotationsIntoPackage(annotations *AnnotationsFile, csv *ClusterS
355355
return manifest, nil
356356
}
357357

358-
// decodeFile decodes the file at a path into the given interface.
359-
func decodeFile(path string, into interface{}) error {
358+
// DecodeFile decodes the file at a path into the given interface.
359+
func DecodeFile(path string, into interface{}) error {
360360
if into == nil {
361361
panic("programmer error: decode destination must be instantiated before decode")
362362
}
@@ -374,7 +374,7 @@ func decodeFile(path string, into interface{}) error {
374374

375375
func parseDependenciesFile(path string, depFile *DependenciesFile) error {
376376
deps := Dependencies{}
377-
err := decodeFile(path, &deps)
377+
err := DecodeFile(path, &deps)
378378
if err != nil || len(deps.RawMessage) == 0 {
379379
return fmt.Errorf("Unable to decode the dependencies file %s", path)
380380
}
@@ -391,7 +391,7 @@ func parseDependenciesFile(path string, depFile *DependenciesFile) error {
391391
}
392392

393393
switch dep.GetType() {
394-
case "olm.gvk", "olm.package":
394+
case GVKType, PackageType:
395395
dep.Value = string(jsonStr)
396396
default:
397397
return fmt.Errorf("Unsupported dependency type %s", dep.GetType())

‎pkg/registry/types.go

+70
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package registry
22

33
import (
4+
"encoding/json"
45
"errors"
56
"fmt"
67
"strings"
8+
9+
"github.com/blang/semver"
710
)
811

912
var (
@@ -154,6 +157,41 @@ type PackageDependency struct {
154157
Version string `json:"version" yaml:"version"`
155158
}
156159

160+
// Validate will validate GVK dependency type and return error(s)
161+
func (gd *GVKDependency) Validate() []error {
162+
errs := []error{}
163+
if gd.Group == "" {
164+
errs = append(errs, fmt.Errorf("API Group is empty"))
165+
}
166+
if gd.Version == "" {
167+
errs = append(errs, fmt.Errorf("API Version is empty"))
168+
}
169+
if gd.Kind == "" {
170+
errs = append(errs, fmt.Errorf("API Kind is empty"))
171+
}
172+
return errs
173+
}
174+
175+
// Validate will validate package dependency type and return error(s)
176+
func (pd *PackageDependency) Validate() []error {
177+
errs := []error{}
178+
if pd.PackageName == "" {
179+
errs = append(errs, fmt.Errorf("Package name is empty"))
180+
}
181+
if pd.Version == "" {
182+
errs = append(errs, fmt.Errorf("Package version is empty"))
183+
} else {
184+
_, err := semver.Parse(pd.Version)
185+
if err != nil {
186+
_, err := semver.ParseRange(pd.Version)
187+
if err != nil {
188+
errs = append(errs, fmt.Errorf("Invalid semver format version"))
189+
}
190+
}
191+
}
192+
return errs
193+
}
194+
157195
// GetDependencies returns the list of dependency
158196
func (d *DependenciesFile) GetDependencies() []*Dependency {
159197
var dependencies []*Dependency
@@ -171,6 +209,38 @@ func (e *Dependency) GetType() string {
171209
return ""
172210
}
173211

212+
// GetTypeValue returns the dependency object that is converted
213+
// from value string
214+
func (e *Dependency) GetTypeValue() interface{} {
215+
if e.Type != "" {
216+
switch e.GetType() {
217+
case GVKType:
218+
dep := GVKDependency{}
219+
err := json.Unmarshal([]byte(e.GetValue()), &dep)
220+
if err != nil {
221+
return nil
222+
}
223+
return dep
224+
case PackageType:
225+
dep := PackageDependency{}
226+
err := json.Unmarshal([]byte(e.GetValue()), &dep)
227+
if err != nil {
228+
return nil
229+
}
230+
return dep
231+
}
232+
}
233+
return nil
234+
}
235+
236+
// GetValue returns the value content of dependency
237+
func (e *Dependency) GetValue() string {
238+
if e.Value != "" {
239+
return e.Value
240+
}
241+
return ""
242+
}
243+
174244
// GetName returns the package name of the bundle
175245
func (a *AnnotationsFile) GetName() string {
176246
if a.Annotations.PackageName != "" {

0 commit comments

Comments
 (0)
Please sign in to comment.