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 """
@@ -69,6 +45,32 @@ def __init__(self, config: dict[str, Any], basepath: str = ".", cwd: str = ".")
6945 self .cwd = cwd
7046 self .env = Environment ()
7147
48+ # All of these are mandated by the ValidatingAdmissionPolicy on the management cluster
49+ # and cannot be changed without updating both the VAP and the RBAC. They are instance
50+ # (rather than module-level) attributes because, in principle, different certification
51+ # targets could be configured with different values here.
52+ self .hr_name = "scs-kaas-certification"
53+ self .hr_namespace = "scs-kaas-certification"
54+ self .hr_kubeconfig_secret = "scs-kaas-certification-kubeconfig"
55+ self .hr_chart_ref : dict [str , str ] = {
56+ "kind" : "HelmChart" ,
57+ "name" : "scs-kaas-certification" ,
58+ "namespace" : "flux-system" ,
59+ }
60+ self .hr_values_fixed : dict [str , Any ] = {
61+ "cloud" : "bfe2-prod" ,
62+ "controlPlane" : {"hosted" : True },
63+ "metadata" : {
64+ "customerID" : 1111 ,
65+ "customerName" : "teuto.net Netzdienste GmbH" ,
66+ "friendlyName" : "scs-kaas-certification" ,
67+ "serviceLevelAgreement" : "None" ,
68+ },
69+ "nodePools" : {
70+ "pool-0" : {"flavor" : "standard.2.1905" , "replicas" : 2 },
71+ },
72+ }
73+
7274 fn : str = config ["templates" ]["kubeconfig" ]
7375 with open (os .path .join (basepath , fn ), "r" ) as f :
7476 self .kubeconfig_template : Template = self .env .from_string (f .read ())
@@ -91,12 +93,12 @@ def _build_helmrelease(self) -> dict[str, Any]:
9193 return {
9294 "apiVersion" : f"{ HR_GROUP } /{ HR_VERSION } " ,
9395 "kind" : "HelmRelease" ,
94- "metadata" : {"name" : HR_NAME , "namespace" : HR_NAMESPACE },
96+ "metadata" : {"name" : self . hr_name , "namespace" : self . hr_namespace },
9597 "spec" : {
96- "chartRef" : HR_CHART_REF ,
98+ "chartRef" : self . hr_chart_ref ,
9799 "driftDetection" : {"mode" : "enabled" },
98100 "interval" : "1m" ,
99- "values" : {** HR_VALUES_FIXED , "version" : self .k8s_version },
101+ "values" : {** self . hr_values_fixed , "version" : self .k8s_version },
100102 },
101103 }
102104
@@ -105,17 +107,17 @@ def _delete_helmrelease(self, co_api: CustomObjectsApi) -> None:
105107 co_api .delete_namespaced_custom_object (
106108 HR_GROUP ,
107109 HR_VERSION ,
108- HR_NAMESPACE ,
110+ self . hr_namespace ,
109111 HR_PLURAL ,
110- HR_NAME ,
112+ self . hr_name ,
111113 )
112114 except ApiException as e :
113115 if e .status == 404 :
114- logger .debug (f"HelmRelease { HR_NAME } not present, nothing to delete" )
116+ logger .debug (f"HelmRelease { self . hr_name } not present, nothing to delete" )
115117 return
116118 raise
117119 # Give Flux time to begin deletion before we try to recreate
118- logger .debug (f"HelmRelease { HR_NAME } deletion requested; waiting 30s" )
120+ logger .debug (f"HelmRelease { self . hr_name } deletion requested; waiting 30s" )
119121 time .sleep (30 )
120122
121123 def _apply_helmrelease (self , api_client : ApiClient ) -> None :
@@ -132,9 +134,9 @@ def _apply_helmrelease(self, api_client: ApiClient) -> None:
132134 path_params = {
133135 'group' : HR_GROUP ,
134136 'version' : HR_VERSION ,
135- 'namespace' : HR_NAMESPACE ,
137+ 'namespace' : self . hr_namespace ,
136138 'plural' : HR_PLURAL ,
137- 'name' : HR_NAME ,
139+ 'name' : self . hr_name ,
138140 },
139141 query_params = [('fieldManager' , 'plugin_t8s' ), ('force' , 'true' )],
140142 header_params = {
@@ -148,15 +150,15 @@ def _apply_helmrelease(self, api_client: ApiClient) -> None:
148150 auth_settings = ['BearerToken' ],
149151 _return_http_data_only = True ,
150152 )
151- logger .debug (f"HelmRelease { HR_NAME } applied" )
153+ logger .debug (f"HelmRelease { self . hr_name } applied" )
152154
153155 def _get_kubeconfig_from_secret (self , core_api : CoreV1Api ) -> bytes :
154- secret = cast (V1Secret , core_api .read_namespaced_secret (HR_KUBECONFIG_SECRET , HR_NAMESPACE ))
156+ secret = cast (V1Secret , core_api .read_namespaced_secret (self . hr_kubeconfig_secret , self . hr_namespace ))
155157 data : dict [str , str ] = secret .data or {}
156158 if "value" in data :
157159 return base64 .standard_b64decode (data ["value" ].encode ())
158160 raise RuntimeError (
159- f"kubeconfig secret { HR_KUBECONFIG_SECRET } is missing key 'value'; has keys: { list (data )} "
161+ f"kubeconfig secret { self . hr_kubeconfig_secret } is missing key 'value'; has keys: { list (data )} "
160162 )
161163
162164 def _wait_for_kubeconfig_secret (self , core_api : CoreV1Api ) -> bytes :
@@ -170,10 +172,10 @@ def _wait_for_kubeconfig_secret(self, core_api: CoreV1Api) -> bytes:
170172 timeout = next (timeouts )
171173 if not timeout :
172174 raise RuntimeError (
173- f"Timeout waiting for kubeconfig secret { HR_KUBECONFIG_SECRET } "
175+ f"Timeout waiting for kubeconfig secret { self . hr_kubeconfig_secret } "
174176 )
175177 logger .debug (
176- f"waiting { timeout } s for kubeconfig secret { HR_KUBECONFIG_SECRET } "
178+ f"waiting { timeout } s for kubeconfig secret { self . hr_kubeconfig_secret } "
177179 )
178180 time .sleep (timeout )
179181
0 commit comments