blob: f0c7f646f8a96f3a8920ac10dd33090894cf8fe7 [file] [log] [blame]
garciadeblas83775ba2025-07-23 18:35:24 +02001#######################################################################################
2# Copyright ETSI Contributors and Others.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13# implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#######################################################################################
17
18# Module with custom functions to manage the transformations and generations associated to the different types of Building Blocks supported by OSM.
19#
20# Supported Brick types are:
21#
22# - `basic`. Basic transformation of the ResourceList. It performs a cleanup and regularization of the target Kustomization (enforce the right path in the repo, ensure that `wait` is enabled, etc.), unless specified otherwise. In addition, it also supports the commonest transformations for a Kustomization, such as addition of optional components, extra labels and/or annotations, hot replacement of image names and tags, etc. For more details, check out the help for the `brick transform basic` command.
23# - `helmreleaseset`. Transformations for a ResourceList with a set of HelmReleases, so that values injected into the specific HelmReleases. It is a superset of the `basic` Brick, and its transformations are applied right after the corresponding basic transformations. For more details, check out the help for the `brick transform helmreleaseset` command.
24# - `custom`. Transformation of the ResourceList with a custom (user-provided) "create" transformation after a `basic` regularization is applied. For more details, check out the help for the `custom create` command.
25# - `custom-hr`. Transformation of the ResourceList with a custom (user-provided) "create" transformation after a `helmreleaseset` transformation (including `basic` regularizations) is applied. For more details, check out the help for the `custom create` command.
26# - `custom-full`. Transformation of the ResourceList with a custom (user-provided) "create" transformation. **No `basic` regularization is applied**, so any regularization (if needed) should be implemented in the custom command. For more details, check out the help for the `custom create` command.
27
28
29use ../krm *
30use ./location.nu
31use custom
32
33
34# Apply the `basic` transformation to ResourceList received from stdin according to the specification of the Brick.
35# The `basic` Brick transformation just does a cleanup and regularization of the target Kustomization
36export def "transform basic" [
37 brick: record # Brick specification
38]: [
39 record -> record
40] {
41 let rl: record = $in
42
43 # Get the key parts
44 let brick_name: string = ($brick | get -i name | default "untitled-brick")
45 let kustomization_name: string = ($brick | get $.kustomization.name)
46 let kustomization_namespace: string = ($brick | get -i $.kustomization.namespace | default "flux-system")
47 let src: string = ($brick | get source | location from base path)
48 let options: record = ($brick | get -i options | default {})
49 ## Should it avoid path regularization?
50 let keep_path: bool = ($options | get -i keep-path | default false)
51 ## Should it avoid enforcing the wait?
52 let enforce_wait: bool = ($options | get -i enforce-wait | default true)
53 ## Should it avoid enforcing the prune?
54 let enforce_prune: bool = ($options | get -i enforce-prune | default true)
55 ## Should it enable (or append) some `components`?
56 let components: list = ($options | get -i components | default [])
57 ## Should it set or overwrite `targetNamespace`?
58 let targetNamespace: string = ($options | get -i targetNamespace | default "")
59 ## Should it overwrite `interval`?
60 let interval: string = ($options | get -i interval | default "")
61 ## Should it set or overwrite `retryInterval`?
62 let retryInterval: string = ($options | get -i retryInterval | default "")
63 ## Should it set or overwrite `serviceAccountName`?
64 let serviceAccountName: string = ($options | get -i serviceAccountName | default "")
65 ## Should it add custom `healthChecks`?
66 let healthChecks: list = ($options | get -i healthChecks | default [])
67 ## Should it add custom `healthCheckExprs`?
68 let healthCheckExprs: list = ($options | get -i healthCheckExprs | default [])
69 ## Should it set or overwrite a `namePrefix`?
70 let namePrefix: string = ($options | get -i namePrefix | default "")
71 ## Should it set or overwrite a `nameSuffix`?
72 let nameSuffix: string = ($options | get -i nameSuffix | default "")
73 ## Should it append additional `.metadata.labels` and `.spec.commonMetadata.labels`?
74 let new_labels: record = ($options | get -i new_labels | default {})
75 ## Should it append additional `.metadata.annotations` and `.spec.commonMetadata.annotations`?
76 let new_annotations: record = ($options | get -i new_annotations | default {})
77 ## Should it append additional `.spec.images` replacements?
78 let images: list = ($options | get -i images | default [])
79
80 # Transform as per the basic Brick model
81 $rl
82 # Path regularization, if applicable
83 | if $keep_path { $in } else {
84 $in
85 | (
86 patch resource update key
87 $.spec.path $src
88 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
89 )
90 }
91 # Enforce the wait, if applicable
92 | if $enforce_wait {
93 $in
94 | (
95 patch resource upsert key
96 $.spec.wait $enforce_wait
97 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
98 )
99 } else { $in }
100 # Enforce the prune, if applicable
101 | if $enforce_prune {
102 $in
103 | (
104 patch resource upsert key
105 $.spec.prune $enforce_prune
106 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
107 )
108 } else { $in }
109 # Enable (or append) some `components`, if applicable
110 | if ($components | is-not-empty) {
111 let tmp_rl: record = $in
112 let existing_components: list = (
113 $tmp_rl
114 | (
115 patch resource keep
116 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
117 )
118 | get -i $.items.0.spec.components
119 | default []
120 )
121 let all_components: list = ($existing_components ++ $components) | uniq
122
123 $tmp_rl
124 | (
125 patch resource upsert key
126 $.spec.components $all_components
127 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
128 )
129 } else { $in }
130 # Set or overwrite `targetNamespace`, if applicable
131 | if ($targetNamespace | is-not-empty) {
132 $in
133 | (
134 patch resource upsert key
135 $.spec.targetNamespace $targetNamespace
136 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
137 )
138 } else { $in }
139 # Overwrite `interval`, if applicable
140 | if ($interval | is-not-empty) {
141 $in
142 | (
143 patch resource update key
144 $.spec.interval $interval
145 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
146 )
147 } else { $in }
148 # Set or overwrite `retryInterval`, if applicable
149 | if ($retryInterval | is-not-empty) {
150 $in
151 | (
152 patch resource upsert key
153 $.spec.retryInterval $retryInterval
154 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
155 )
156 } else { $in }
157 # Set or overwrite `serviceAccountName`, if applicable
158 | if ($serviceAccountName | is-not-empty) {
159 $in
160 | (
161 patch resource upsert key
162 $.spec.serviceAccountName $serviceAccountName
163 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
164 )
165 } else { $in }
166 # Enable (or append) some `healthChecks`, if applicable
167 | if ($healthChecks | is-not-empty) {
168 let tmp_rl: record = $in
169 let existing_healthChecks: list = ($tmp_rl | get -i $.spec.healthChecks | default [])
170 let all_healthChecks: list = ($existing_healthChecks ++ $healthChecks) | uniq
171
172 $tmp_rl
173 | (
174 patch resource upsert key
175 $.spec.healthChecks $all_healthChecks
176 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
177 )
178 } else { $in }
179 # Enable (or append) some `healthCheckExprs`, if applicable
180 | if ($healthCheckExprs | is-not-empty) {
181 let tmp_rl: record = $in
182 let existing_healthCheckExprs: list = ($tmp_rl | get -i $.spec.healthCheckExprs | default [])
183 let all_healthCheckExprs: list = ($existing_healthCheckExprs ++ $healthCheckExprs) | uniq
184
185 $tmp_rl
186 | (
187 patch resource upsert key
188 $.spec.healthCheckExprs $all_healthCheckExprs
189 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
190 )
191 } else { $in }
192 # Set or overwrite `namePrefix`, if applicable
193 | if ($namePrefix | is-not-empty) {
194 $in
195 | (
196 patch resource upsert key
197 $.spec.namePrefix $namePrefix
198 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
199 )
200 } else { $in }
201 # Set or overwrite `nameSuffix`, if applicable
202 | if ($nameSuffix | is-not-empty) {
203 $in
204 | (
205 patch resource upsert key
206 $.spec.nameSuffix $nameSuffix
207 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
208 )
209 } else { $in }
210 # Enable (or append) some `.metadata.labels` and `.spec.commonMetadata.labels`, if applicable
211 | if ($new_labels | is-not-empty) {
212 let tmp_rl: record = $in
213 let existing_labels: list = ($tmp_rl | get -i $.metadata.labels | default [])
214 let existing_common_labels: list = ($tmp_rl | get -i $.spec.commonMetadata.labels | default [])
215 let all_labels: list = ($existing_labels | merge $new_labels)
216 let all_common_labels: list = ($existing_common_labels | merge $new_labels)
217
218 $tmp_rl
219 | (
220 patch resource upsert key
221 $.metadata.labels
222 $all_labels
223 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
224 )
225 | (
226 patch resource upsert key
227 $.spec.commonMetadata.labels
228 $all_common_labels
229 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
230 )
231 } else { $in }
232 # Enable (or append) some `.metadata.annotations` and `.spec.commonMetadata.annotations`, if applicable
233 | if ($new_annotations | is-not-empty) {
234 let tmp_rl: record = $in
235 let existing_annotations: list = ($tmp_rl | get -i $.metadata.annotations | default [])
236 let existing_common_annotations: list = ($tmp_rl | get -i $.spec.commonMetadata.annotations | default [])
237 let all_annotations: list = ($existing_annotations | merge $new_annotations)
238 let all_common_annotations: list = ($existing_common_annotations | merge $new_annotations)
239
240 $tmp_rl
241 | (
242 patch resource upsert key
243 $.metadata.annotations
244 $all_annotations
245 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
246 )
247 | (
248 patch resource upsert key
249 $.spec.commonMetadata.annotations
250 $all_common_annotations
251 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
252 )
253 } else { $in }
254 # Enable (or append) some `.spec.images` replacements, if applicable
255 | if ($images | is-not-empty) {
256 let tmp_rl: record = $in
257 let existing_images: list = ($tmp_rl | get -i $.spec.images | default [])
258 let all_images: list = ($existing_images ++ $images) | uniq
259
260 $tmp_rl
261 | (
262 patch resource upsert key
263 $.spec.images $all_images
264 "kustomize.toolkit.fluxcd.io/v1" Kustomization $kustomization_name $kustomization_namespace
265 )
266 } else { $in }
267}
268
269
270# Apply the `helmreleaseset` transformation to ResourceList received from stdin according to the specification of the Brick.
271# The `basic` Brick transformation just does a cleanup and regularization of the target Kustomization
272export def "transform helmreleaseset" [
273 brick: record # Brick specification
274]: [
275 record -> record
276] {
277 # Input ReleaseList after basic transformations
278 let rl: record = $in
279
280 # Get the key parts
281 let brick_name: string = ($brick | get -i name | default "untitled-brick")
282 let kustomization_name: string = ($brick | get $.kustomization.name)
283 let kustomization_namespace: string = ($brick | get -i $.kustomization.namespace | default "flux-system")
284 let hrset_values: list<record> = ($brick | get "hrset-values" | default [])
285 let public_age_key: string = ($brick | get -i $.public-age-key | default "")
286
287 # Apply HelmRelease-specific transformations
288 $hrset_values
289 | reduce --fold $rl {|elt, acc|
290 $acc
291 | (
292 overlaypatch helmrelease set values
293 # --ks-namespace: string
294 --ks-namespace $kustomization_namespace
295 # --hr-namespace: string
296 --hr-namespace ($elt | get $.HelmRelease.namespace)
297 # --operation: string = "add"
298 # --cm-key: string = "values.yaml"
299 --cm-key ($elt | get -i $.valuesFrom.configMapKeyRef.key | default "values.yaml")
300 # --cm-target-path: string
301 # --cm-optional
302 # --create-cm-with-values: record
303 --create-cm-with-values ($elt | get -i "create-cm" | default {})
304 # --secret-key: string = "values.yaml"
305 --secret-key ($elt | get -i $.valuesFrom.secretKeyRef.key | default "values.yaml")
306 # --secret-target-path: string
307 # --secret-optional
308 # --create-secret-with-values: record
309 --create-secret-with-values (
310 $env
311 | get -i ($elt | get -i $.create-secret.env-values-reference | default "")
312 | default {}
313 )
314 # --public-age-key: string
315 --public-age-key $public_age_key
316 # kustomization_name: string
317 $kustomization_name
318 # helmrelease_name: string
319 ($elt | get $.HelmRelease.name)
320 # inline_values?: record
321 ($elt | get -i "inline-values" | default {})
322 # cm_name?: string
323 ($elt | get -i $.valuesFrom.configMapKeyRef.name | default "")
324 # secret_name?: string
325 ($elt | get -i $.valuesFrom.secretKeyRef.name | default "")
326 )
327 }
328}
329
330
331# Transform the ResourceList received from stdin according to the specification of a Brick transformation.
332#
333export def transform [
334 brick: record # Brick specification
335 environment: record = {} # Record with environment variables to load
336]: [
337 record -> record
338] {
339 # Get input ResourceList
340 let rl: record = $in
341
342 # Get the brick name
343 let brick_name: string = ($brick | get -i name | default "untitled-brick")
344
345 # Update the environment to include the brick name
346 let updated_environment: record = (
347 $environment
348 | upsert $.BRICK_NAME $brick_name
349 )
350
351 # Update the brick record accordingly
352 let updated_brick: record = (
353 $brick
354 | replace vars $updated_environment
355 )
356
357 # Get other key parts
358 let brick_type: string = ($updated_brick | get -i type | default "basic" | str downcase)
359
360 # Apply transformation according to the brick type
361 with-env $updated_environment {
362 match $brick_type {
363 "basic" => {
364 # Basic transformation of the ResourceList (just cleanup and regularization)
365 $rl
366 | transform basic $updated_brick
367 },
368 "helmreleaseset" => {
369 # Transformation of the ResourceList with a set of HelmReleases
370 $rl
371 | transform basic $updated_brick
372 | transform helmreleaseset $updated_brick
373 },
374 "custom-full" => {
375 # Transformation of the ResourceList with a custom "create" transformation
376 $rl
377 | custom brick create $updated_brick $updated_environment
378 },
379 "custom" => {
380 # Transformation of the ResourceList with a custom "create" transformation, after a basic cleanup and regularization
381 $rl
382 | transform basic $updated_brick
383 | custom brick create $updated_brick $updated_environment
384 },
385 "custom-hr" => {
386 # Transformation of the ResourceList with a custom "create" transformation, after a `helmreleaseset` transformation
387 $rl
388 | transform basic $updated_brick
389 | transform helmreleaseset $updated_brick
390 | custom brick create $updated_brick $updated_environment
391 },
392 _ => {
393 # Unknown brick type, throw an error
394 error make { msg: $"Error: Unknown Brick type: ($updated_brick | get type)" }
395 }
396 }
397 }
398}