blob: 07578a0abc7a02b58cd715739f66fa5ee6c81a36 [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 functions to convert between the different alternative representations of a set of Kubernetes resources: folders with manifests, lists of records (concatenated manifests), or ResourceLists.
19
20
21use ./concatenate.nu
22
23
24
25# Substitute environment variables in text from stdin.
26#
27# Environment variables can be listed either as a string in the format accepted by the `envsubst` command (e.g. `$VAR1,$VAR2`) or as a list of strings with the environment variable names that will be formatted by the function. In case the parameter is empty, it should invoke `envsubst` with no parameters, so that it replaces all the environment variables that are found.
28export def "replace environment variables" [vars_to_replace: any = ""]: [
29 string -> string
30] {
31 # Gather reference to stdin before it is lost
32 let text: string = $in
33
34 # Adapt the input as needed
35 let filter: string = (if ($vars_to_replace | describe) == "string" {
36 # If it is a string, it can be used directly as filter for envsubst
37 $vars_to_replace
38 } else if ($vars_to_replace | describe) == "list<string>" {
39 # If it is a list of strings, we can concatenate them in a single string with the right format for envsubst
40 ($vars_to_replace | each {|var| $"${($var)}" } | str join ',')
41 } else {
42 # Handle unexpected type for $vars_to_replace
43 error make {msg: $"Error: Expected a string or list of strings, but received ($vars_to_replace | describe)"}
44 })
45
46 # Proceed with the substitution
47 if ($filter | is-empty) {
48 $text | ^envsubst
49 } else {
50 $text | ^envsubst $filter
51 }
52}
53
54alias replace_env_vars = replace environment variables
55
56
57# Convert manifests in a source folder to a ResourceList
58export def "folder to resourcelist" [
59 --subst-env, # Set if environment variables should be replaced
60 folder: path,
61 env_filter?: any = ""
62]: [
63 record -> record
64 nothing -> record
65] {
66 # Gather the input and convert to record if empty
67 let in_list: record = if $in == null { {} } else { $in }
68
69 # Create a ResourceList from the source folder and substitute environment variables if needed
70 let source_list: record = (
71 kpt fn source $folder
72 | if $subst_env {
73 $in | replace environment variables $env_filter
74 } else {
75 $in
76 }
77 | from yaml
78 )
79
80 # Merge both resource lists carefully
81 $in_list | concatenate resourcelists $source_list
82}
83
84export alias "folder to rl" = folder to resourcelist
85export alias folder2list_generator = folder to resourcelist
86
87
88# Convert a manifest from stdin to a ResourceList
89## NOTE: It is an equivalent with type-checks to:
90## kustomize cfg cat --wrap-kind ResourceList
91export def "manifest to resourcelist" []: [
92 any -> record
93] {
94 # Gather the input and convert to list
95 let manifest_in: list<any> = (if $in == null { [] }
96 else if ($in | describe | str starts-with "record") { [ $in ] }
97 else if ($in | describe | str starts-with "list") or ($in | describe | str starts-with "table") { $in }
98 else { error make {msg: $"Error: Expected a record or a list of records, but received ($in | describe)."}})
99
100 {
101 apiVersion: "config.kubernetes.io/v1"
102 kind: "ResourceList"
103 items: $manifest_in
104 }
105}
106
107export alias manifest2list = manifest to resourcelist
108
109
110# Convert a ResourceList to file manifests in a target folder
111export def "resourcelist to folder" [
112 --sync, # If sync is true, replaces all contents in the folder, otherwise just copies over.
113 folder: path,
114 dry_run?: bool = false # If true, just prints the ResourceList but does not render any file
115]: [
116 record -> any
117] {
118
119 # Preserves the input value
120 let list_in: record = $in
121
122 # As optional parameter, defaults to $env.DRY_RUN when not set
123 let is_dry_run: bool = if $dry_run == null { $env.DRY_RUN | into bool } else { $dry_run }
124
125 # If it is a dry-run, just prints the input ResourceList and exits
126 if $is_dry_run {
127 return ($list_in | to yaml)
128 }
129
130 # First, render the manifests to a temporary folder
131 let tmp_folder: string = (mktemp -t -d)
132 let tmp_target: string = ($tmp_folder | path join manifests)
133 $list_in | to yaml | ^kpt fn sink $tmp_target
134
135 # Writes the contents to the target folder
136 if $sync {
137 # Sync actually removes any previous contents in the folder
138 rm -rf $folder
139 }
140 mkdir $folder
141 ls $tmp_target | get name | cp -r ...$in $folder
142
143 # Removes the temporary folder
144 rm -rf $tmp_folder
145}
146
147export alias list2folder = resourcelist to folder