@@ -39,23 +39,21 @@ import (
3939)
4040
4141var (
42- filenames []string
43- recursive bool
42+ crdsDir []string
4443)
4544
4645func initFlags () {
4746 pflag .CommandLine .AddGoFlagSet (flag .CommandLine )
48- pflag .StringSliceVarP (& filenames , "filename" , "f" , filenames , "The files that contain the configurations to apply." )
49- pflag .BoolVarP (& recursive , "recursive" , "R" , false , "Process the directory used in -f, --filename recursively." )
47+ pflag .StringSliceVarP (& crdsDir , "crds-dir" , "f" , crdsDir , "The files or directories that contain the CRDs to apply." )
5048 pflag .Parse ()
5149
52- if len (filenames ) == 0 {
50+ if len (crdsDir ) == 0 {
5351 log .Fatalf ("CRDs directory or single CRDs are required" )
5452 }
5553
56- for _ , crdDir := range filenames {
57- if _ , err := os .Stat (crdDir ); os .IsNotExist (err ) {
58- log .Fatalf ("CRDs directory %s does not exist" , filenames )
54+ for _ , path := range crdsDir {
55+ if _ , err := os .Stat (path ); os .IsNotExist (err ) {
56+ log .Fatalf ("path does not exist: %s " , path )
5957 }
6058 }
6159}
@@ -78,30 +76,32 @@ func EnsureCRDsCmd() {
7876 log .Fatalf ("Failed to create API extensions client: %v" , err )
7977 }
8078
81- dirsToApply , err := walkCRDs ( recursive , filenames )
79+ pathsToApply , err := collectYamlPaths ( crdsDir )
8280 if err != nil {
8381 log .Fatalf ("Failed to walk through CRDs: %v" , err )
8482 }
8583
86- for _ , dir := range dirsToApply {
87- log .Printf ("Apply CRDs from file: %s" , dir )
88- if err := applyCRDs (ctx , client .ApiextensionsV1 ().CustomResourceDefinitions (), dir ); err != nil {
84+ for _ , path := range pathsToApply {
85+ log .Printf ("Apply CRDs from file: %s" , path )
86+ if err := applyCRDs (ctx , client .ApiextensionsV1 ().CustomResourceDefinitions (), path ); err != nil {
8987 log .Fatalf ("Failed to apply CRDs: %v" , err )
9088 }
9189 }
9290}
9391
94- // walkCRDs walks the CRDs directory and applies each YAML file.
95- // TODO: add unit test for this function.
96- func walkCRDs (recursive bool , crdDirs []string ) ([]string , error ) {
97- var dirs []string
92+ // collectYamlPaths processes a list of paths and returns all YAML files.
93+ func collectYamlPaths (crdDirs []string ) ([]string , error ) {
94+ paths := map [string ]struct {}{}
9895 for _ , crdDir := range crdDirs {
9996 // We need the parent directory to check if we are in the top-level directory.
10097 // This is necessary for the recursive logic.
10198 // We can skip the errors as it has been checked in initFlags.
102- parentDir , _ := os .Stat (crdDir )
99+ parentDir , err := os .Stat (crdDir )
100+ if err != nil {
101+ return []string {}, fmt .Errorf ("stat the path %s: %w" , crdDir , err )
102+ }
103103 // Walk the directory recursively and apply each YAML file.
104- err : = filepath .Walk (crdDir , func (path string , info os.FileInfo , err error ) error {
104+ err = filepath .Walk (crdDir , func (path string , info os.FileInfo , err error ) error {
105105 if err != nil {
106106 return err
107107 }
@@ -113,20 +113,30 @@ func walkCRDs(recursive bool, crdDirs []string) ([]string, error) {
113113 if filepath .Ext (path ) != ".yaml" && filepath .Ext (path ) != ".yml" {
114114 return nil
115115 }
116- // If not recursive we want to only apply the CRDs in the top-level directory.
116+ // If we apply a dir we only want to apply the CRDs in the directory (i.e., not recursively) .
117117 // filepath.Dir() does not add a trailing slash, thus we need to trim it in the crdDir.
118- if ! recursive && parentDir .IsDir () && filepath .Dir (path ) != strings .TrimRight (crdDir , "/" ) {
118+ if parentDir .IsDir () && filepath .Dir (path ) != strings .TrimRight (crdDir , "/" ) {
119119 return nil
120120 }
121121
122- dirs = append ( dirs , path )
122+ paths [ path ] = struct {}{}
123123 return nil
124124 })
125125 if err != nil {
126126 return []string {}, fmt .Errorf ("walk the path %s: %w" , crdDirs , err )
127127 }
128128 }
129- return dirs , nil
129+ return mapToSlice (paths ), nil
130+ }
131+
132+ // mapToSlice converts a map to a slice.
133+ // The map is used to deduplicate the paths.
134+ func mapToSlice (m map [string ]struct {}) []string {
135+ s := []string {}
136+ for k := range m {
137+ s = append (s , k )
138+ }
139+ return s
130140}
131141
132142// applyCRDs reads a YAML file, splits it into documents, and applies each CRD to the cluster.
@@ -183,7 +193,7 @@ func applyCRD(
183193 log .Printf ("Create CRD %s" , crd .Name )
184194 _ , err = crdClient .Create (ctx , crd , metav1.CreateOptions {})
185195 if err != nil {
186- return fmt .Errorf ("create CRD %s : %w" , crd . Name , err )
196+ return fmt .Errorf ("create CRD: %w" , err )
187197 }
188198 return nil
189199 }
0 commit comments