44Generate version-specific hierarchy of the cluster-stacks repo.
55
66This is a helper script to generate a version-specific folder structure
7- of the base cluster-stacks implementation. The source directory is in
8- `cluster-stacks/providers/openstack/scs` and supported versions are maintained
9- in a file `versions.yaml` within the source directory. The source directory is a
10- valid variant of this repo, pinned to the smallest supported version.
7+ of the base cluster-stacks implementation. The source directory is provider
8+ and stack specific (e.g., providers/openstack/scs2). Supported versions are
9+ maintained in a file `versions.yaml` within the source directory.
1110"""
1211
1312
1413import argparse
1514import logging
15+ import os
1616import shutil
1717import subprocess
1818import sys
19- from pathlib import Path , PosixPath
19+ from pathlib import Path
2020
2121import yaml
2222import requests
2323
2424BASE_PATH = Path (__file__ ).parent .parent
25- SOURCE_PATH = BASE_PATH .joinpath ("providers" , "openstack" , "scs" )
26- DEFAULT_TARGET_PATH = BASE_PATH .joinpath ("providers" , "openstack" , "out" )
25+
26+ # These will be set by command-line arguments in __main__
27+ SOURCE_PATH : Path
28+ DEFAULT_TARGET_PATH : Path
29+ PROVIDER : str
30+ STACK : str
2731
2832logger = logging .getLogger (__name__ )
2933
@@ -61,7 +65,7 @@ def get_dash_version(version: str) -> str:
6165 return "-" .join (version .split ("." )[0 :2 ])
6266
6367
64- def create_output_dir (version : str ) -> PosixPath :
68+ def create_output_dir (version : str ) -> Path :
6569 """
6670 Prepare output directory by creating it and copying the source files over.
6771 This overwrites files existing inside the output directory, as those
@@ -94,7 +98,7 @@ def create_output_dir(version: str) -> PosixPath:
9498 return out_dir
9599
96100
97- def readfile (path : PosixPath ):
101+ def readfile (path : Path ):
98102 """
99103 Helper function to read yaml configuration files.
100104
@@ -104,18 +108,19 @@ def readfile(path: PosixPath):
104108 Returns:
105109 Content of the yaml configuration file.
106110 """
107- # TODO: yaml.safe_load either returns a list or dict,
108- # depending on the structure of the yaml file. This can be improved / refactored.
111+ # TODO: yaml.safe_load either returns a list or dict,
112+ # depending on the structure of yaml file. This can be improved / refactored.
109113 with open (path , encoding = "utf-8" ) as stream :
110114 try :
111115 content = yaml .safe_load (stream )
112116 except yaml .YAMLError as exc :
113117 print (exc )
118+ return content
114119
115120 return content
116121
117122
118- def writefile (path : PosixPath , content ):
123+ def writefile (path : Path , content ):
119124 """
120125 Helper function to write content to a yaml configuration file.
121126
@@ -131,7 +136,7 @@ def writefile(path: PosixPath, content):
131136
132137
133138def update_cluster_addon (
134- target : PosixPath , build : bool , build_verbose : bool , ** versions
139+ target : Path , build : bool , build_verbose : bool , ** versions
135140):
136141 """
137142 Update relevant files inside the cluster-stacks/<path>/cluster-addon subdirectory
@@ -148,16 +153,22 @@ def update_cluster_addon(
148153 logger .info ("Updating %s" , target )
149154 content = readfile (target )
150155
151- for dep in content ["dependencies" ]:
152- if dep ["name" ] == "openstack-cinder-csi" :
153- dep ["version" ] = versions ["cinder_csi" ]
154-
155- if dep ["name" ] == "openstack-cloud-controller-manager" :
156- dep ["version" ] = versions ["occm" ]
157-
158- content ["name" ] = (
159- f"openstack-scs-{ get_dash_version (versions ['kubernetes' ])} -cluster-addon"
160- )
156+ # Update provider-specific dependencies
157+ if PROVIDER == "openstack" :
158+ for dep in content ["dependencies" ]:
159+ if dep ["name" ] == "openstack-cinder-csi" :
160+ dep ["version" ] = versions .get ("cinder_csi" , dep ["version" ])
161+ if dep ["name" ] == "openstack-cloud-controller-manager" :
162+ dep ["version" ] = versions .get ("occm" , dep ["version" ])
163+ # Add other provider-specific logic here as needed
164+
165+ # Update chart name with provider/stack info
166+ k8s_ver = get_dash_version (versions ['kubernetes' ])
167+ content ["name" ] = f"{ PROVIDER } -{ STACK } -{ k8s_ver } -cluster-addon"
168+
169+ # Update chart name with provider/stack info
170+ k8s_ver = get_dash_version (versions ['kubernetes' ])
171+ content ["name" ] = f"{ PROVIDER } -{ STACK } -{ k8s_ver } -cluster-addon"
161172
162173 writefile (target , content )
163174
@@ -172,7 +183,7 @@ def update_cluster_addon(
172183 )
173184
174185
175- def update_csctl_conf (target : PosixPath , ** versions ):
186+ def update_csctl_conf (target : Path , ** versions ):
176187 """
177188 Function to update csctl configuration file.
178189
@@ -191,7 +202,7 @@ def update_csctl_conf(target: PosixPath, **versions):
191202 writefile (target , content )
192203
193204
194- def update_cluster_class (target : PosixPath , ** kwargs ):
205+ def update_cluster_class (target : Path , ** kwargs ):
195206 """
196207 Update relevant files inside the cluster-stacks/<path>/cluster-class subdirectory.
197208
@@ -208,22 +219,26 @@ def update_cluster_class(target: PosixPath, **kwargs):
208219 logger .info ("Updating %s" , chart_file )
209220 content = readfile (chart_file )
210221 version = get_dash_version (kwargs ["kubernetes" ])
211- content ["name" ] = f"openstack-scs -{ version } -cluster-class"
222+ content ["name" ] = f"{ PROVIDER } - { STACK } -{ version } -cluster-class"
212223
213224 writefile (chart_file , content )
214225
215- logger .info ("Updating %s" , values_file )
216- content = readfile (values_file )
217-
218- content ["images" ]["controlPlane" ][
219- "name"
220- ] = f"ubuntu-capi-image-v{ kwargs ['kubernetes' ]} "
221- content ["images" ]["worker" ]["name" ] = f"ubuntu-capi-image-v{ kwargs ['kubernetes' ]} "
222-
223- writefile (values_file , content )
224-
225-
226- def update_node_images (target : PosixPath , ** kwargs ):
226+ # Update values.yaml (provider-specific)
227+ if values_file .exists ():
228+ logger .info ("Updating %s" , values_file )
229+ content = readfile (values_file )
230+
231+ # OpenStack-specific image updates (only if content exists and has images)
232+ if content and PROVIDER == "openstack" and "images" in content :
233+ if "controlPlane" in content ["images" ]:
234+ content ["images" ]["controlPlane" ]["name" ] = f"ubuntu-capi-image-v{ kwargs ['kubernetes' ]} "
235+ if "worker" in content ["images" ]:
236+ content ["images" ]["worker" ]["name" ] = f"ubuntu-capi-image-v{ kwargs ['kubernetes' ]} "
237+
238+ writefile (values_file , content )
239+
240+
241+ def update_node_images (target : Path , ** kwargs ):
227242 """
228243 Update relevant files inside the cluster-stacks/<path>/node-images subdirectory.
229244
@@ -258,8 +273,26 @@ def update_node_images(target: PosixPath, **kwargs):
258273if __name__ == "__main__" :
259274 LOGFORMAT = "%(asctime)s - %(levelname)s: %(message)s"
260275 logging .basicConfig (level = logging .INFO , encoding = "utf-8" , format = LOGFORMAT )
276+
261277 # Initialize arg parser
262- parser = argparse .ArgumentParser ()
278+ parser = argparse .ArgumentParser (
279+ description = "Generate version-specific cluster stack manifests"
280+ )
281+ parser .add_argument (
282+ "--provider" ,
283+ type = str ,
284+ default = os .environ .get ("PROVIDER" , "openstack" ),
285+ help = "Provider name (e.g., openstack, docker). Can be set via PROVIDER env var." ,
286+ )
287+ parser .add_argument (
288+ "--cluster-stack" ,
289+ "--cs-name" ,
290+ "--stack" , # Keep --stack for backwards compatibility
291+ dest = "stack" ,
292+ type = str ,
293+ default = os .environ .get ("CLUSTER_STACK" , os .environ .get ("STACK" , "scs2" )),
294+ help = "Cluster stack name (e.g., scs2, scs, ferrol). Can be set via CLUSTER_STACK or STACK env var." ,
295+ )
263296 parser .add_argument (
264297 "-t" ,
265298 "--target-version" ,
@@ -274,6 +307,23 @@ def update_node_images(target: PosixPath, **kwargs):
274307 "--build-verbose" , action = "store_false" , help = "Show output of helm build"
275308 )
276309 args = parser .parse_args ()
310+
311+ # Set global provider/stack paths
312+ PROVIDER = args .provider
313+ STACK = args .stack
314+ SOURCE_PATH = BASE_PATH / "providers" / PROVIDER / STACK
315+ DEFAULT_TARGET_PATH = BASE_PATH / "providers" / PROVIDER / "out"
316+
317+ # Validate source path exists
318+ if not SOURCE_PATH .exists ():
319+ print (f"❌ Source directory not found: { SOURCE_PATH } " )
320+ print (f" Available stacks for { PROVIDER } :" )
321+ provider_path = BASE_PATH .joinpath ("providers" , PROVIDER )
322+ if provider_path .exists ():
323+ for stack_dir in provider_path .iterdir ():
324+ if stack_dir .is_dir () and stack_dir .name != "out" :
325+ print (f" - { stack_dir .name } " )
326+ sys .exit (1 )
277327
278328 # Load supported target versions
279329 sup_versions = load_supported_versions ()
@@ -304,6 +354,8 @@ def update_node_images(target: PosixPath, **kwargs):
304354 )
305355 update_csctl_conf (output_dir .joinpath ("csctl.yaml" ), ** tv )
306356 update_cluster_class (output_dir .joinpath ("cluster-class" ), ** tv )
307- update_node_images (
308- output_dir .joinpath ("cluster-class" , "templates" , "image.yaml" ), ** tv
309- )
357+
358+ # Update node images only if image.yaml exists (OpenStack-specific)
359+ image_yaml = output_dir .joinpath ("cluster-class" , "templates" , "image.yaml" )
360+ if image_yaml .exists ():
361+ update_node_images (image_yaml , ** tv )
0 commit comments