@@ -39,7 +39,7 @@ import (
3939
4040// CRDInstallOptions are the options for installing CRDs
4141type CRDInstallOptions struct {
42- // Paths is a list of paths to the directories containing CRDs
42+ // Paths is a list of paths to the directories or files containing CRDs
4343 Paths []string
4444
4545 // CRDs is a list of CRDs to install
@@ -88,16 +88,12 @@ func InstallCRDs(config *rest.Config, options CRDInstallOptions) ([]*apiextensio
8888// readCRDFiles reads the directories of CRDs in options.Paths and adds the CRD structs to options.CRDs
8989func readCRDFiles (options * CRDInstallOptions ) error {
9090 if len (options .Paths ) > 0 {
91- for _ , path := range options .Paths {
92- if _ , err := os .Stat (path ); ! options .ErrorIfPathMissing && os .IsNotExist (err ) {
93- continue
94- }
95- new , err := readCRDs (path )
96- if err != nil {
97- return err
98- }
99- options .CRDs = append (options .CRDs , new ... )
91+ crdList , err := renderCRDs (options )
92+ if err != nil {
93+ return err
10094 }
95+
96+ options .CRDs = append (options .CRDs , crdList ... )
10197 }
10298 return nil
10399}
@@ -232,28 +228,67 @@ func CreateCRDs(config *rest.Config, crds []*apiextensionsv1beta1.CustomResource
232228 return nil
233229}
234230
235- // readCRDs reads the CRDs from files and Unmarshals them into structs
236- func readCRDs (path string ) ([]* apiextensionsv1beta1.CustomResourceDefinition , error ) {
237- // Get the CRD files
238- var files []os.FileInfo
239- var err error
240- log .V (1 ).Info ("reading CRDs from path" , "path" , path )
241- if files , err = ioutil .ReadDir (path ); err != nil {
242- return nil , err
231+ // renderCRDs iterate through options.Paths and extract all CRD files.
232+ func renderCRDs (options * CRDInstallOptions ) ([]* apiextensionsv1beta1.CustomResourceDefinition , error ) {
233+ var (
234+ err error
235+ info os.FileInfo
236+ crds []* apiextensionsv1beta1.CustomResourceDefinition
237+ files []os.FileInfo
238+ )
239+
240+ for _ , path := range options .Paths {
241+ var filePath = path
242+
243+ // Return the error if ErrorIfPathMissing exists
244+ if info , err = os .Stat (path ); os .IsNotExist (err ) {
245+ if options .ErrorIfPathMissing {
246+ return nil , err
247+ }
248+ continue
249+ }
250+
251+ if ! info .IsDir () {
252+ filePath , files = filepath .Dir (path ), append (files , info )
253+ } else {
254+ if files , err = ioutil .ReadDir (path ); err != nil {
255+ return nil , err
256+ }
257+ }
258+
259+ log .V (1 ).Info ("reading CRDs from path" , "path" , path )
260+
261+ crdList , err := readCRDs (filePath , files )
262+ if err != nil {
263+ return nil , err
264+ }
265+
266+ // If CRD already in the list, skip it.
267+ if existsCRDs (crds , crdList ) {
268+ continue
269+ }
270+
271+ crds = append (crds , crdList ... )
243272 }
244273
274+ return crds , nil
275+ }
276+
277+ // readCRDs reads the CRDs from files and Unmarshals them into structs
278+ func readCRDs (basePath string , files []os.FileInfo ) ([]* apiextensionsv1beta1.CustomResourceDefinition , error ) {
279+ var crds []* apiextensionsv1beta1.CustomResourceDefinition
280+
245281 // White list the file extensions that may contain CRDs
246282 crdExts := sets .NewString (".json" , ".yaml" , ".yml" )
247283
248- var crds []* apiextensionsv1beta1.CustomResourceDefinition
249284 for _ , file := range files {
250285 // Only parse whitelisted file types
251286 if ! crdExts .Has (filepath .Ext (file .Name ())) {
252287 continue
253288 }
254289
255290 // Unmarshal CRDs from file into structs
256- docs , err := readDocuments (filepath .Join (path , file .Name ()))
291+ docs , err := readDocuments (filepath .Join (basePath , file .Name ()))
257292 if err != nil {
258293 return nil , err
259294 }
0 commit comments