1
1
package packager
2
2
3
3
import (
4
- "strings "
4
+ "path/filepath "
5
5
6
6
"github.com/defenseunicorns/zarf/src/config"
7
7
"github.com/defenseunicorns/zarf/src/internal/message"
@@ -10,111 +10,166 @@ import (
10
10
"github.com/defenseunicorns/zarf/src/types"
11
11
)
12
12
13
- func GetComposedComponents () (components []types.ZarfComponent ) {
13
+ func GetComponents () (components []types.ZarfComponent ) {
14
14
for _ , component := range config .GetComponents () {
15
- // Check for standard component.
16
15
if component .Import .Path == "" {
17
- // Append standard component to list.
18
16
components = append (components , component )
19
17
} else {
20
- validateOrBail (& component )
21
-
22
- // Expand and add components from imported package.
23
- importedComponent := getImportedComponent (component )
24
- // Merge in parent component changes.
25
- mergeComponentOverrides (& importedComponent , component )
26
- // Add to the list of components for the package.
27
- components = append (components , importedComponent )
18
+ components = append (components , GetComposedComponent (component ))
28
19
}
29
20
}
30
21
31
22
// Update the parent package config with the expanded sub components.
32
23
// This is important when the deploy package is created.
33
24
config .SetComponents (components )
25
+
34
26
return components
35
27
}
36
28
37
- // Validates the sub component, exits program if validation fails.
38
- func validateOrBail (component * types.ZarfComponent ) {
39
- if err := validate .ValidateImportPackage (component ); err != nil {
40
- message .Fatalf (err , "Invalid import definition in the %s component: %s" , component .Name , err )
41
- }
42
- }
29
+ func GetComposedComponent (childComponent types.ZarfComponent ) types.ZarfComponent {
30
+ // Make sure the component we're trying to import cant be accessed
31
+ validateOrBail (& childComponent )
43
32
44
- // Sets Name, Default, Required and Description to the original components values
45
- func mergeComponentOverrides (target * types.ZarfComponent , src types.ZarfComponent ) {
46
- target .Name = src .Name
47
- target .Default = src .Default
48
- target .Required = src .Required
33
+ // Keep track of the composed components import path to build nestedily composed components
34
+ everGrowingComposePath := ""
49
35
50
- if src .Description != "" {
51
- target .Description = src .Description
52
- }
36
+ // Get the component that we are trying to import
37
+ // NOTE: This function is recursive and will continue getting the parents until there are no more 'imported' components left
38
+ parentComponent := getParentComponent (childComponent , everGrowingComposePath )
39
+
40
+ // Merge the overrides from the parent that we just received with the child we were provided
41
+ mergeComponentOverrides (& parentComponent , childComponent )
42
+
43
+ return parentComponent
53
44
}
54
45
55
- // Get expanded components from imported component.
56
- func getImportedComponent (importComponent types.ZarfComponent ) (component types.ZarfComponent ) {
57
- // Read the imported package.
58
- importedPackage := getSubPackage (& importComponent )
46
+ func getParentComponent (childComponent types.ZarfComponent , everGrowingComposePath string ) (parentComponent types.ZarfComponent ) {
47
+ importedPackage , err := getSubPackage (filepath .Join (everGrowingComposePath , childComponent .Import .Path ))
48
+ if err != nil {
49
+ message .Fatal (err , "Unable to get the package that we're importing a component from" )
50
+ }
59
51
60
- componentName := importComponent .Import .ComponentName
61
- // Default to the component name if a custom one was not provided
62
- if componentName == "" {
63
- componentName = importComponent .Name
52
+ // Figure out which component we are actually importing
53
+ // NOTE: Default to the component name if a custom one was not provided
54
+ parentComponentName := childComponent .Import .ComponentName
55
+ if parentComponentName == "" {
56
+ parentComponentName = childComponent .Name
64
57
}
65
58
66
- // Loop over package components looking for a match the componentName
67
- for _ , componentToCompose := range importedPackage .Components {
68
- if componentToCompose .Name == componentName {
69
- return * prepComponentToCompose (& componentToCompose , importComponent )
59
+ // Find the parent component from the imported package that matches our arch
60
+ for _ , importedComponent := range importedPackage .Components {
61
+ if importedComponent .Name == parentComponentName {
62
+ parentComponent = importedComponent
63
+ break
70
64
}
71
65
}
72
66
73
- return component
74
- }
67
+ // Check if we need to get more of the parents!!!
68
+ if parentComponent .Import .Path != "" {
69
+ // Set a temporary composePath so we can get future parents/grandparents from our current location
70
+ tempEverGrowingComposePath := filepath .Join (everGrowingComposePath , childComponent .Import .Path )
75
71
76
- // Reads the locally imported zarf.yaml
77
- func getSubPackage (component * types.ZarfComponent ) (importedPackage types.ZarfPackage ) {
78
- utils .ReadYaml (component .Import .Path + "zarf.yaml" , & importedPackage )
79
- return importedPackage
80
- }
72
+ // Recursively call this function to get the next layer of parents
73
+ grandparentComponent := getParentComponent (parentComponent , tempEverGrowingComposePath )
81
74
82
- // Updates the name and sets all local asset paths relative to the importing component.
83
- func prepComponentToCompose ( child * types. ZarfComponent , parent types. ZarfComponent ) * types. ZarfComponent {
75
+ // Merge the grandparents values into the parent
76
+ mergeComponentOverrides ( & grandparentComponent , parentComponent )
84
77
85
- if child .Import .Path != "" {
86
- // The component we are trying to compose is a composed component itself!
87
- nestedComponent := getImportedComponent (* child )
88
- child = prepComponentToCompose (& nestedComponent , * child )
78
+ // Set the grandparent as the parent component now that we're done with recursively importing
79
+ parentComponent = grandparentComponent
89
80
}
90
81
82
+ // Fix the filePaths of imported components to be accessible from our current location
83
+ parentComponent = fixComposedFilepaths (parentComponent , childComponent )
84
+
85
+ return
86
+ }
87
+
88
+ func fixComposedFilepaths (parentComponent , childComponent types.ZarfComponent ) types.ZarfComponent {
91
89
// Prefix composed component file paths.
92
- for fileIdx , file := range child .Files {
93
- child .Files [fileIdx ].Source = getComposedFilePath (file .Source , parent .Import .Path )
90
+ for fileIdx , file := range parentComponent .Files {
91
+ parentComponent .Files [fileIdx ].Source = getComposedFilePath (file .Source , childComponent .Import .Path )
94
92
}
95
93
96
94
// Prefix non-url composed component chart values files.
97
- for chartIdx , chart := range child .Charts {
95
+ for chartIdx , chart := range parentComponent .Charts {
98
96
for valuesIdx , valuesFile := range chart .ValuesFiles {
99
- child .Charts [chartIdx ].ValuesFiles [valuesIdx ] = getComposedFilePath (valuesFile , parent .Import .Path )
97
+ parentComponent .Charts [chartIdx ].ValuesFiles [valuesIdx ] = getComposedFilePath (valuesFile , childComponent .Import .Path )
100
98
}
101
99
}
102
100
103
101
// Prefix non-url composed manifest files and kustomizations.
104
- for manifestIdx , manifest := range child .Manifests {
102
+ for manifestIdx , manifest := range parentComponent .Manifests {
105
103
for fileIdx , file := range manifest .Files {
106
- child .Manifests [manifestIdx ].Files [fileIdx ] = getComposedFilePath (file , parent .Import .Path )
104
+ parentComponent .Manifests [manifestIdx ].Files [fileIdx ] = getComposedFilePath (file , childComponent .Import .Path )
107
105
}
108
106
for kustomIdx , kustomization := range manifest .Kustomizations {
109
- child .Manifests [manifestIdx ].Kustomizations [kustomIdx ] = getComposedFilePath (kustomization , parent .Import .Path )
107
+ parentComponent .Manifests [manifestIdx ].Kustomizations [kustomIdx ] = getComposedFilePath (kustomization , childComponent .Import .Path )
110
108
}
111
109
}
112
110
113
- if child .CosignKeyPath != "" {
114
- child .CosignKeyPath = getComposedFilePath (child .CosignKeyPath , parent .Import .Path )
111
+ if parentComponent .CosignKeyPath != "" {
112
+ parentComponent .CosignKeyPath = getComposedFilePath (parentComponent .CosignKeyPath , childComponent .Import .Path )
115
113
}
116
114
117
- return child
115
+ return parentComponent
116
+ }
117
+
118
+ // Validates the sub component, exits program if validation fails.
119
+ func validateOrBail (component * types.ZarfComponent ) {
120
+ if err := validate .ValidateImportPackage (component ); err != nil {
121
+ message .Fatalf (err , "Invalid import definition in the %s component: %s" , component .Name , err )
122
+ }
123
+ }
124
+
125
+ // Sets Name, Default, Required and Description to the original components values
126
+ func mergeComponentOverrides (target * types.ZarfComponent , override types.ZarfComponent ) {
127
+ target .Name = override .Name
128
+ target .Default = override .Default
129
+ target .Required = override .Required
130
+ target .Group = override .Group
131
+
132
+ // Override description if it was provided.
133
+ if override .Description != "" {
134
+ target .Description = override .Description
135
+ }
136
+
137
+ // Override cosign key path if it was provided.
138
+ if override .CosignKeyPath != "" {
139
+ target .CosignKeyPath = override .CosignKeyPath
140
+ }
141
+
142
+ // Append slices where they exist.
143
+ target .Charts = append (target .Charts , override .Charts ... )
144
+ target .DataInjections = append (target .DataInjections , override .DataInjections ... )
145
+ target .Files = append (target .Files , override .Files ... )
146
+ target .Images = append (target .Images , override .Images ... )
147
+ target .Manifests = append (target .Manifests , override .Manifests ... )
148
+ target .Repos = append (target .Repos , override .Repos ... )
149
+
150
+ // Merge variables.
151
+ for key , variable := range override .Variables {
152
+ target .Variables [key ] = variable
153
+ }
154
+
155
+ // Merge scripts.
156
+ target .Scripts .Before = append (target .Scripts .Before , override .Scripts .Before ... )
157
+ target .Scripts .After = append (target .Scripts .After , override .Scripts .After ... )
158
+ target .Scripts .ShowOutput = override .Scripts .ShowOutput
159
+ if override .Scripts .Retry {
160
+ target .Scripts .Retry = override .Scripts .Retry
161
+ }
162
+
163
+ if override .Scripts .TimeoutSeconds > 0 {
164
+ target .Scripts .TimeoutSeconds = override .Scripts .TimeoutSeconds
165
+ }
166
+ }
167
+
168
+ // Reads the locally imported zarf.yaml
169
+ func getSubPackage (packagePath string ) (importedPackage types.ZarfPackage , err error ) {
170
+ path := filepath .Join (packagePath , config .ZarfYAML )
171
+ err = utils .ReadYaml (path , & importedPackage )
172
+ return importedPackage , err
118
173
}
119
174
120
175
// Prefix file path with importPath if original file path is not a url.
@@ -123,32 +178,7 @@ func getComposedFilePath(originalPath string, pathPrefix string) string {
123
178
if utils .IsUrl (originalPath ) {
124
179
return originalPath
125
180
}
126
- // Add prefix for local files.
127
- return fixRelativePathBacktracking (pathPrefix + originalPath )
128
- }
129
181
130
- func fixRelativePathBacktracking (path string ) string {
131
- var newPathBuilder []string
132
- var hitRealPath = false // We might need to go back several directories at the begining
133
-
134
- // Turn paths like `../../this/is/a/very/../silly/../path` into `../../this/is/a/path`
135
- splitString := strings .Split (path , "/" )
136
- for _ , dir := range splitString {
137
- if dir == ".." {
138
- if hitRealPath {
139
- // Instead of going back a directory, just don't get here in the first place
140
- newPathBuilder = newPathBuilder [:len (newPathBuilder )- 1 ]
141
- } else {
142
- // We are still going back directories for the first time, keep going back
143
- newPathBuilder = append (newPathBuilder , dir )
144
- }
145
- } else {
146
- // This is a regular directory we want to travel through
147
- hitRealPath = true
148
- newPathBuilder = append (newPathBuilder , dir )
149
- }
150
- }
151
-
152
- // NOTE: This assumes a relative path
153
- return strings .Join (newPathBuilder , "/" )
182
+ // Add prefix for local files.
183
+ return filepath .Join (pathPrefix , originalPath )
154
184
}
0 commit comments