@@ -22,7 +22,6 @@ import (
22
22
23
23
y "github.com/ghodss/yaml"
24
24
log "github.com/sirupsen/logrus"
25
- "gopkg.in/yaml.v2"
26
25
)
27
26
28
27
type Meta struct {
@@ -57,8 +56,8 @@ func (i imageValidator) PullBundleImage(imageTag, directory string) error {
57
56
// Outputs:
58
57
// error: ValidattionError which contains a list of errors
59
58
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
62
61
var validationErrors []error
63
62
64
63
items , err := ioutil .ReadDir (directory )
@@ -76,7 +75,7 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
76
75
case strings .TrimSuffix (MetadataDir , "/" ):
77
76
i .logger .Debug ("Found metadata directory" )
78
77
metadataFound = true
79
- annotationsDir = filepath .Join (directory , MetadataDir )
78
+ metadataDir = filepath .Join (directory , MetadataDir )
80
79
}
81
80
}
82
81
}
@@ -99,16 +98,62 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
99
98
validationErrors = append (validationErrors , err )
100
99
}
101
100
102
- // Validate annotations.yaml
103
- annotationsFile , err := ioutil .ReadFile ( filepath . Join ( annotationsDir , AnnotationsFile ) )
101
+ // Validate annotations file
102
+ files , err := ioutil .ReadDir ( metadataDir )
104
103
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 {
107
148
return NewValidationError (validationErrors )
108
149
}
109
150
110
- var fileAnnotations AnnotationMetadata
151
+ return nil
152
+ }
111
153
154
+ // Validate the annotations file
155
+ func validateAnnotations (mediaType string , fileAnnotations * AnnotationMetadata ) []error {
156
+ var validationErrors []error
112
157
annotations := map [string ]string {
113
158
MediatypeLabel : mediaType ,
114
159
ManifestsLabel : ManifestsDir ,
@@ -118,18 +163,9 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
118
163
ChannelDefaultLabel : "" ,
119
164
}
120
165
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
-
128
166
for label , item := range annotations {
129
167
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 {
133
169
aErr := fmt .Errorf ("Missing annotation %q" , label )
134
170
validationErrors = append (validationErrors , aErr )
135
171
}
@@ -160,16 +196,37 @@ func (i imageValidator) ValidateBundleFormat(directory string) error {
160
196
}
161
197
}
162
198
163
- _ , err = ValidateChannelDefault (annotations [ChannelsLabel ], annotations [ChannelDefaultLabel ])
199
+ _ , err : = ValidateChannelDefault (annotations [ChannelsLabel ], annotations [ChannelDefaultLabel ])
164
200
if err != nil {
165
201
validationErrors = append (validationErrors , err )
166
202
}
203
+ return validationErrors
204
+ }
167
205
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 ... )
170
227
}
171
228
172
- return nil
229
+ return validationErrors
173
230
}
174
231
175
232
// ValidateBundleContent confirms that the CSV and CRD files inside the bundle
@@ -289,6 +346,32 @@ func (i imageValidator) ValidateBundleContent(manifestDir string) error {
289
346
return nil
290
347
}
291
348
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
+
292
375
// Validate if the file is kubecle-able
293
376
func validateKubectlable (fileBytes []byte ) error {
294
377
exampleFileBytesJSON , err := y .YAMLToJSON (fileBytes )
0 commit comments