2222HR_VERSION = "v2"
2323HR_PLURAL = "helmreleases"
2424
25- # All of these are mandated by the ValidatingAdmissionPolicy on the management cluster
26- # and cannot be changed without updating both the VAP and the RBAC.
27- HR_NAME = "scs-kaas-certification"
28- HR_NAMESPACE = "scs-kaas-certification"
29- HR_KUBECONFIG_SECRET = "scs-kaas-certification-kubeconfig"
30- HR_CHART_REF = {
31- "kind" : "HelmChart" ,
32- "name" : "scs-kaas-certification" ,
33- "namespace" : "flux-system" ,
34- }
35- HR_VALUES_FIXED = {
36- "cloud" : "bfe2-prod" ,
37- "controlPlane" : {"hosted" : True },
38- "metadata" : {
39- "customerID" : 1111 ,
40- "customerName" : "teuto.net Netzdienste GmbH" ,
41- "friendlyName" : "scs-kaas-certification" ,
42- "serviceLevelAgreement" : "None" ,
43- },
44- "nodePools" : {
45- "pool-0" : {"flavor" : "standard.2.1905" , "replicas" : 2 },
46- },
47- }
48-
4925
5026class PluginT8s (KubernetesClusterPlugin ):
5127 """
@@ -62,13 +38,51 @@ class PluginT8s(KubernetesClusterPlugin):
6238 kubeconfig: t8s-kubeconfig.yaml (management cluster kubeconfig template)
6339 secrets:
6440 token: '{{ clouds_conf.teuto_mgmt_token }}'
41+ cloud: 'bfe2-prod' (optional, defaults to 'bfe2-prod')
42+ controlPlaneHosted: true (optional, defaults to true)
43+ nodePools: (optional, defaults to a single 'pool-0')
44+ pool-0:
45+ flavor: 'standard.2.1905'
46+ replicas: 2
47+ metadata: (optional; individual keys default as shown)
48+ customerID: 1111
49+ customerName: 'teuto.net Netzdienste GmbH'
50+ friendlyName: 'scs-kaas-certification'
51+ serviceLevelAgreement: 'None'
6552 """
6653
6754 def __init__ (self , config : dict [str , Any ], basepath : str = "." , cwd : str = "." ) -> None :
6855 self .basepath = basepath
6956 self .cwd = cwd
7057 self .env = Environment ()
7158
59+ # All of these are mandated by the ValidatingAdmissionPolicy on the management cluster
60+ # and cannot be changed without updating both the VAP and the RBAC. They are instance
61+ # (rather than module-level) attributes because, in principle, different certification
62+ # targets could be configured with different values here.
63+ self .hr_name = "scs-kaas-certification"
64+ self .hr_namespace = "scs-kaas-certification"
65+ self .hr_kubeconfig_secret = "scs-kaas-certification-kubeconfig"
66+ self .hr_chart_ref : dict [str , str ] = {
67+ "kind" : "HelmChart" ,
68+ "name" : "scs-kaas-certification" ,
69+ "namespace" : "flux-system" ,
70+ }
71+ metadata_config : dict [str , Any ] = config .get ("metadata" , {})
72+ self .hr_values_fixed : dict [str , Any ] = {
73+ "cloud" : config .get ("cloud" , "bfe2-prod" ),
74+ "controlPlane" : {"hosted" : config .get ("controlPlaneHosted" , True )},
75+ "metadata" : {
76+ "customerID" : metadata_config .get ("customerID" , 1111 ),
77+ "customerName" : metadata_config .get ("customerName" , "teuto.net Netzdienste GmbH" ),
78+ "friendlyName" : metadata_config .get ("friendlyName" , "scs-kaas-certification" ),
79+ "serviceLevelAgreement" : metadata_config .get ("serviceLevelAgreement" , "None" ),
80+ },
81+ "nodePools" : config .get ("nodePools" , {
82+ "pool-0" : {"flavor" : "standard.2.1905" , "replicas" : 2 },
83+ }),
84+ }
85+
7286 fn : str = config ["templates" ]["kubeconfig" ]
7387 with open (os .path .join (basepath , fn ), "r" ) as f :
7488 self .kubeconfig_template : Template = self .env .from_string (f .read ())
@@ -91,12 +105,12 @@ def _build_helmrelease(self) -> dict[str, Any]:
91105 return {
92106 "apiVersion" : f"{ HR_GROUP } /{ HR_VERSION } " ,
93107 "kind" : "HelmRelease" ,
94- "metadata" : {"name" : HR_NAME , "namespace" : HR_NAMESPACE },
108+ "metadata" : {"name" : self . hr_name , "namespace" : self . hr_namespace },
95109 "spec" : {
96- "chartRef" : HR_CHART_REF ,
110+ "chartRef" : self . hr_chart_ref ,
97111 "driftDetection" : {"mode" : "enabled" },
98112 "interval" : "1m" ,
99- "values" : {** HR_VALUES_FIXED , "version" : self .k8s_version },
113+ "values" : {** self . hr_values_fixed , "version" : self .k8s_version },
100114 },
101115 }
102116
@@ -105,17 +119,17 @@ def _delete_helmrelease(self, co_api: CustomObjectsApi) -> None:
105119 co_api .delete_namespaced_custom_object (
106120 HR_GROUP ,
107121 HR_VERSION ,
108- HR_NAMESPACE ,
122+ self . hr_namespace ,
109123 HR_PLURAL ,
110- HR_NAME ,
124+ self . hr_name ,
111125 )
112126 except ApiException as e :
113127 if e .status == 404 :
114- logger .debug (f"HelmRelease { HR_NAME } not present, nothing to delete" )
128+ logger .debug (f"HelmRelease { self . hr_name } not present, nothing to delete" )
115129 return
116130 raise
117131 # Give Flux time to begin deletion before we try to recreate
118- logger .debug (f"HelmRelease { HR_NAME } deletion requested; waiting 30s" )
132+ logger .debug (f"HelmRelease { self . hr_name } deletion requested; waiting 30s" )
119133 time .sleep (30 )
120134
121135 def _apply_helmrelease (self , api_client : ApiClient ) -> None :
@@ -132,9 +146,9 @@ def _apply_helmrelease(self, api_client: ApiClient) -> None:
132146 path_params = {
133147 'group' : HR_GROUP ,
134148 'version' : HR_VERSION ,
135- 'namespace' : HR_NAMESPACE ,
149+ 'namespace' : self . hr_namespace ,
136150 'plural' : HR_PLURAL ,
137- 'name' : HR_NAME ,
151+ 'name' : self . hr_name ,
138152 },
139153 query_params = [('fieldManager' , 'plugin_t8s' ), ('force' , 'true' )],
140154 header_params = {
@@ -148,15 +162,15 @@ def _apply_helmrelease(self, api_client: ApiClient) -> None:
148162 auth_settings = ['BearerToken' ],
149163 _return_http_data_only = True ,
150164 )
151- logger .debug (f"HelmRelease { HR_NAME } applied" )
165+ logger .debug (f"HelmRelease { self . hr_name } applied" )
152166
153167 def _get_kubeconfig_from_secret (self , core_api : CoreV1Api ) -> bytes :
154- secret = cast (V1Secret , core_api .read_namespaced_secret (HR_KUBECONFIG_SECRET , HR_NAMESPACE ))
168+ secret = cast (V1Secret , core_api .read_namespaced_secret (self . hr_kubeconfig_secret , self . hr_namespace ))
155169 data : dict [str , str ] = secret .data or {}
156170 if "value" in data :
157171 return base64 .standard_b64decode (data ["value" ].encode ())
158172 raise RuntimeError (
159- f"kubeconfig secret { HR_KUBECONFIG_SECRET } is missing key 'value'; has keys: { list (data )} "
173+ f"kubeconfig secret { self . hr_kubeconfig_secret } is missing key 'value'; has keys: { list (data )} "
160174 )
161175
162176 def _wait_for_kubeconfig_secret (self , core_api : CoreV1Api ) -> bytes :
@@ -170,10 +184,10 @@ def _wait_for_kubeconfig_secret(self, core_api: CoreV1Api) -> bytes:
170184 timeout = next (timeouts )
171185 if not timeout :
172186 raise RuntimeError (
173- f"Timeout waiting for kubeconfig secret { HR_KUBECONFIG_SECRET } "
187+ f"Timeout waiting for kubeconfig secret { self . hr_kubeconfig_secret } "
174188 )
175189 logger .debug (
176- f"waiting { timeout } s for kubeconfig secret { HR_KUBECONFIG_SECRET } "
190+ f"waiting { timeout } s for kubeconfig secret { self . hr_kubeconfig_secret } "
177191 )
178192 time .sleep (timeout )
179193
0 commit comments