Skip to content

Commit f623f0e

Browse files
committed
Add support for Kustomize components
Fix #753 Signed-off-by: Kristian Klausen <[email protected]>
1 parent 1e8dc84 commit f623f0e

File tree

8 files changed

+123
-0
lines changed

8 files changed

+123
-0
lines changed

api/v1beta2/kustomization_types.go

+4
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ type KustomizationSpec struct {
153153
// +kubebuilder:validation:Enum=none;client;server
154154
// +optional
155155
Validation string `json:"validation,omitempty"`
156+
157+
// Components specifies relative paths to specifications of other Components
158+
// +optional
159+
Components []string `json:"components,omitempty"`
156160
}
157161

158162
// Decryption defines how decryption is handled for Kubernetes manifests.

api/v1beta2/zz_generated.deepcopy.go

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/kustomize.toolkit.fluxcd.io_kustomizations.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,12 @@ spec:
585585
description: KustomizationSpec defines the configuration to calculate
586586
the desired state from a Source using Kustomize.
587587
properties:
588+
components:
589+
description: Components specifies relative paths to specifications
590+
of other Components
591+
items:
592+
type: string
593+
type: array
588594
decryption:
589595
description: Decrypt Kubernetes secrets before applying them on the
590596
cluster.

docs/spec/v1beta2/kustomization.md

+22
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ offering support for the following Kustomize directives:
556556
- [namespace](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/namespace/)
557557
- [patches](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patches/)
558558
- [images](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/images/)
559+
- [components](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/components/)
559560

560561
### Target namespace
561562

@@ -654,6 +655,27 @@ spec:
654655
digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
655656
```
656657

658+
### Components
659+
660+
To add [Kustomize `components` entries](https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/components/)
661+
to the configuration, and use reusable pieces of configuration logic that can
662+
be included from multiple overlays, `spec.components` can be defined:
663+
664+
```yaml
665+
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
666+
kind: Kustomization
667+
metadata:
668+
name: podinfo
669+
namespace: flux-system
670+
spec:
671+
# ...omitted for brevity
672+
components:
673+
- ingress
674+
- tls
675+
```
676+
677+
**Note:** The component paths must be local and relative.
678+
657679
## Variable substitution
658680

659681
With `spec.postBuild.substitute` you can provide a map of key/value pairs holding the

internal/generator/generator.go

+25
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ func (kg *KustomizeGenerator) WriteFile(dirPath string) (string, error) {
7979
})
8080
}
8181

82+
for _, m := range kg.kustomization.Spec.Components {
83+
if !isLocalRelativePath(m) {
84+
return "", fmt.Errorf("component path '%s' must be local and relative", m)
85+
}
86+
kus.Components = append(kus.Components, m)
87+
}
88+
8289
for _, m := range kg.kustomization.Spec.PatchesStrategicMerge {
8390
kus.PatchesStrategicMerge = append(kus.PatchesStrategicMerge, kustypes.PatchStrategicMerge(m.Raw))
8491
}
@@ -234,3 +241,21 @@ func adaptSelector(selector *kustomize.Selector) (output *kustypes.Selector) {
234241
}
235242
return
236243
}
244+
245+
func isLocalRelativePath(path string) bool {
246+
// From: https://github.com/kubernetes-sigs/kustomize/blob/84bd402cc0662c5df3f109c4f80c22611243c5f9/api/internal/git/repospec.go#L231-L239
247+
// with "file://" removed/
248+
for _, p := range []string{
249+
// Order matters here.
250+
"git::", "gh:", "ssh://", "https://", "http://",
251+
"git@", "github.com:", "github.com/"} {
252+
if len(p) < len(path) && strings.ToLower(path[:len(p)]) == p {
253+
return false
254+
}
255+
}
256+
257+
if filepath.IsAbs(path) || filepath.IsAbs(strings.TrimPrefix(strings.ToLower(path), "file://")) {
258+
return false
259+
}
260+
return true
261+
}

internal/generator/generator_test.go

+49
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,52 @@ func TestGenerator_WriteFile(t *testing.T) {
9393
})
9494
}
9595
}
96+
97+
func TestGenerator_Components(t *testing.T) {
98+
tests := []struct {
99+
name string
100+
dir string
101+
fluxComponents []string
102+
expectedComponents []string
103+
}{
104+
{
105+
name: "test kustomization.yaml with components and Flux Kustomization without components",
106+
dir: "components",
107+
fluxComponents: []string{},
108+
expectedComponents: []string{"componentA"},
109+
},
110+
{
111+
name: "test kustomization.yaml without components and Flux Kustomization with components",
112+
dir: "zero-components",
113+
fluxComponents: []string{"componentB", "componentC"},
114+
expectedComponents: []string{"componentB", "componentC"},
115+
},
116+
{
117+
name: "test kustomization.yaml with components and Flux Kustomization with components",
118+
dir: "components",
119+
fluxComponents: []string{"componentB", "componentC"},
120+
expectedComponents: []string{"componentA", "componentB", "componentC"},
121+
},
122+
}
123+
124+
for _, tt := range tests {
125+
t.Run(tt.name, func(t *testing.T) {
126+
g := NewWithT(t)
127+
tmpDir := t.TempDir()
128+
g.Expect(copy.Copy("./testdata/components", tmpDir)).To(Succeed())
129+
ks := v1beta2.Kustomization{
130+
Spec: v1beta2.KustomizationSpec{
131+
Components: tt.fluxComponents,
132+
},
133+
}
134+
kfile, err := NewGenerator(filepath.Join(tmpDir, tt.dir), &ks).WriteFile(filepath.Join(tmpDir, tt.dir))
135+
g.Expect(err).ToNot(HaveOccurred())
136+
137+
kfileYAML, err := os.ReadFile(kfile)
138+
g.Expect(err).ToNot(HaveOccurred())
139+
var k kustypes.Kustomization
140+
g.Expect(k.Unmarshal(kfileYAML)).To(Succeed())
141+
g.Expect(k.Components).Should(Equal(tt.expectedComponents))
142+
})
143+
}
144+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
apiVersion: kustomize.config.k8s.io/v1beta1
3+
kind: Kustomization
4+
resources:
5+
- configmap.yaml
6+
components:
7+
- componentA
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
apiVersion: kustomize.config.k8s.io/v1beta1
3+
kind: Kustomization
4+
resources:
5+
- configmap.yaml

0 commit comments

Comments
 (0)