diff --git a/api/internal/target/kusttarget.go b/api/internal/target/kusttarget.go index 766351951..a51299a4c 100644 --- a/api/internal/target/kusttarget.go +++ b/api/internal/target/kusttarget.go @@ -164,6 +164,10 @@ func (kt *KustTarget) accumulateTarget(ra *accumulator.ResAccumulator) ( if err != nil { return nil, errors.Wrap(err, "accumulating resources") } + ra, err = kt.accumulateComponents(ra, kt.kustomization.Components) + if err != nil { + return nil, errors.Wrap(err, "accumulating components") + } tConfig, err := builtinconfig.MakeTransformerConfig( kt.ldr, kt.kustomization.Configurations) if err != nil { @@ -273,7 +277,7 @@ func (kt *KustTarget) accumulateResources( return nil, fmt.Errorf("accumulateFile %q, loader.New %q", errF, errL) } var errD error - ra, errD = kt.accumulateDirectory(ra, ldr) + ra, errD = kt.accumulateDirectory(ra, ldr, false) if errD != nil { return nil, fmt.Errorf("accumulateFile %q, accumulateDirector: %q", errF, errD) } @@ -282,8 +286,27 @@ func (kt *KustTarget) accumulateResources( return ra, nil } +// accumulateResources fills the given resourceAccumulator +// with resources read from the given list of paths. +func (kt *KustTarget) accumulateComponents( + ra *accumulator.ResAccumulator, paths []string) (*accumulator.ResAccumulator, error) { + for _, path := range paths { + // Components always refer to directories + ldr, errL := kt.ldr.New(path) + if errL != nil { + return nil, fmt.Errorf("loader.New %q", errL) + } + var errD error + ra, errD = kt.accumulateDirectory(ra, ldr, true) + if errD != nil { + return nil, fmt.Errorf("accumulateDirectory: %q", errD) + } + } + return ra, nil +} + func (kt *KustTarget) accumulateDirectory( - ra *accumulator.ResAccumulator, ldr ifc.Loader) (*accumulator.ResAccumulator, error) { + ra *accumulator.ResAccumulator, ldr ifc.Loader, isComponent bool) (*accumulator.ResAccumulator, error) { defer ldr.Cleanup() subKt := NewKustTarget( ldr, kt.validator, kt.rFactory, kt.tFactory, kt.pLdr) @@ -292,6 +315,13 @@ func (kt *KustTarget) accumulateDirectory( return nil, errors.Wrapf( err, "couldn't make target for path '%s'", ldr.Root()) } + if isComponent && subKt.kustomization.Kind != types.ComponentKind { + return nil, fmt.Errorf( + "expected kind '%s' for path '%s' but got '%s'", types.ComponentKind, ldr.Root(), subKt.kustomization.Kind) + } else if !isComponent && subKt.kustomization.Kind == types.ComponentKind { + return nil, fmt.Errorf( + "expected kind != '%s' for path '%s'", types.ComponentKind, ldr.Root()) + } var subRa *accumulator.ResAccumulator if subKt.kustomization.Kind == types.ComponentKind { diff --git a/api/krusty/component_test.go b/api/krusty/component_test.go index 022f9f4aa..5ab861fe3 100644 --- a/api/krusty/component_test.go +++ b/api/krusty/component_test.go @@ -62,8 +62,10 @@ func writeComponentProd(th kusttest_test.Harness) { th.WriteK("/app/prod", ` resources: - ../base -- ../patch - db + +components: +- ../patch `) th.WriteF("/app/prod/db", ` apiVersion: v1 @@ -105,16 +107,16 @@ metadata: apiVersion: v1 kind: Deployment metadata: - name: patched-stub + name: patched-db spec: - replicas: 1 + type: Logical --- apiVersion: v1 kind: Deployment metadata: - name: db + name: patched-stub spec: - type: Logical + replicas: 1 `) } @@ -135,9 +137,11 @@ configMapGenerator: th.WriteK("/app/prod", ` resources: - ../base +- db + +components: - ../patch - ../additionalpatch -- db `) m := th.Run("/app/prod", th.MakeDefaultOptions()) th.AssertActualEqualsExpected(m, ` @@ -162,16 +166,16 @@ metadata: apiVersion: v1 kind: Deployment metadata: - name: patched-stub + name: patched-db spec: - replicas: 1 + type: Logical --- apiVersion: v1 kind: Deployment metadata: - name: db + name: patched-stub spec: - type: Logical + replicas: 1 `) } @@ -183,7 +187,7 @@ func TestNestedComponents(t *testing.T) { th.WriteF("/app/additionalpatch/kustomization.yaml", ` apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component -resources: +components: - ../patch configMapGenerator: - name: my-configmap @@ -194,8 +198,10 @@ configMapGenerator: th.WriteK("/app/prod", ` resources: - ../base -- ../additionalpatch - db + +components: +- ../additionalpatch `) m := th.Run("/app/prod", th.MakeDefaultOptions()) th.AssertActualEqualsExpected(m, ` @@ -220,16 +226,16 @@ metadata: apiVersion: v1 kind: Deployment metadata: - name: patched-stub + name: patched-db spec: - replicas: 1 + type: Logical --- apiVersion: v1 kind: Deployment metadata: - name: db + name: patched-stub spec: - type: Logical + replicas: 1 `) } @@ -283,16 +289,16 @@ metadata: apiVersion: v1 kind: Deployment metadata: - name: patched-stub + name: patched-db spec: - replicas: 1 + type: Logical --- apiVersion: v1 kind: Deployment metadata: - name: db + name: patched-stub spec: - type: Logical + replicas: 1 `) } @@ -334,6 +340,44 @@ metadata: `) } +func TestComponentsCannotBeAddedToResources(t *testing.T) { + th := kusttest_test.MakeHarness(t) + writeComponentBase(th) + writeComponentPatch(th) + th.WriteF("/app/custinres/kustomization.yaml", ` +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../base +- ../patch +`) + err := th.RunWithErr("/app/custinres", th.MakeDefaultOptions()) + if !strings.Contains( + err.Error(), + "expected kind != 'Component' for path '/app/patch'") { + t.Fatalf("unexpected error: %s", err) + } +} + +func TestResourcesCannotBeAddedToComponents(t *testing.T) { + th := kusttest_test.MakeHarness(t) + writeComponentBase(th) + writeComponentPatch(th) + th.WriteF("/app/resincust/kustomization.yaml", ` +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +components: +- ../base +- ../patch +`) + err := th.RunWithErr("/app/resincust", th.MakeDefaultOptions()) + if !strings.Contains( + err.Error(), + "accumulating components: accumulateDirectory: \"expected kind 'Component' for path '/app/base' but got 'Kustomization'") { + t.Fatalf("unexpected error: %s", err) + } +} + func TestMissingOptionalComponentApiVersion(t *testing.T) { th := kusttest_test.MakeHarness(t) writeComponentBase(th) diff --git a/api/types/kustomization.go b/api/types/kustomization.go index eb32d906a..f86edb4bf 100644 --- a/api/types/kustomization.go +++ b/api/types/kustomization.go @@ -75,10 +75,14 @@ type Kustomization struct { // // Resources specifies relative paths to files holding YAML representations - // of kubernetes API objects, or specifcations of other kustomizations + // of kubernetes API objects, or specifications of other kustomizations // via relative paths, absolute paths, or URLs. Resources []string `json:"resources,omitempty" yaml:"resources,omitempty"` + // Components specifies relative paths to specifications of other Components + // via relative paths, absolute paths, or URLs. + Components []string `json:"components,omitempty" yaml:"components,omitempty"` + // Crds specifies relative paths to Custom Resource Definition files. // This allows custom resources to be recognized as operands, making // it possible to add them to the Resources list.