@@ -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