| garciadeblas | 83775ba | 2025-07-23 18:35:24 +0200 | [diff] [blame] | 1 | ####################################################################################### |
| 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 | |
| 29 | use ../krm * |
| 30 | use ./location.nu |
| 31 | use 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 |
| 36 | export 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 |
| 272 | export 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 | # |
| 333 | export 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 | } |