diff --git a/core/cautils/kustomizedirectory.go b/core/cautils/kustomizedirectory.go index 31b449e3..0dcbfb13 100644 --- a/core/cautils/kustomizedirectory.go +++ b/core/cautils/kustomizedirectory.go @@ -9,6 +9,7 @@ import ( "github.com/kubescape/k8s-interface/workloadinterface" "github.com/kubescape/opa-utils/objectsenvelopes/localworkload" "sigs.k8s.io/kustomize/api/krusty" + "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/kustomize/kyaml/filesys" ) @@ -75,7 +76,11 @@ func getKustomizeDirectoryName(path string) string { func (kd *KustomizeDirectory) GetWorkloads(kustomizeDirectoryPath string) (map[string][]workloadinterface.IMetadata, []error) { fSys := filesys.MakeFsOnDisk() - kustomizer := krusty.MakeKustomizer(krusty.MakeDefaultOptions()) + // Use LoadRestrictionsNone to allow loading resources from outside the kustomize directory. + // This is necessary for overlays that reference base configurations in parent directories. + opts := krusty.MakeDefaultOptions() + opts.LoadRestrictions = types.LoadRestrictionsNone + kustomizer := krusty.MakeKustomizer(opts) resmap, err := kustomizer.Run(fSys, kustomizeDirectoryPath) if err != nil { diff --git a/core/cautils/kustomizedirectory_test.go b/core/cautils/kustomizedirectory_test.go index b569a0b5..3acb31de 100644 --- a/core/cautils/kustomizedirectory_test.go +++ b/core/cautils/kustomizedirectory_test.go @@ -4,6 +4,8 @@ import ( "os" "path/filepath" "testing" + + "github.com/stretchr/testify/assert" ) func TestGetKustomizeDirectoryName(t *testing.T) { @@ -61,3 +63,83 @@ func TestGetKustomizeDirectoryName(t *testing.T) { }) } } + +func kustomizeTestdataPath() string { + o, _ := os.Getwd() + return filepath.Join(o, "testdata", "kustomize") +} + +// TestKustomizeOverlayWithBase tests that kustomize overlays can properly load +// resources from base directories. This is the main fix for issue #1617. +func TestKustomizeOverlayWithBase(t *testing.T) { + overlayPath := filepath.Join(kustomizeTestdataPath(), "overlays", "prod") + + // Verify it's detected as a kustomize directory + assert.True(t, isKustomizeDirectory(overlayPath), "overlay should be detected as kustomize directory") + + // Create kustomize directory and get workloads + kd := NewKustomizeDirectory(overlayPath) + workloads, errs := kd.GetWorkloads(overlayPath) + + // Should not have errors - this was failing before the fix because + // overlays couldn't load resources from parent base directories + assert.Empty(t, errs, "should not have errors loading overlay with base reference") + + // Should have workloads from the rendered overlay + assert.NotEmpty(t, workloads, "should have workloads from rendered kustomize overlay") + + // The overlay should have produced exactly one deployment with the merged configuration + var deploymentFound bool + for _, wls := range workloads { + for _, wl := range wls { + if wl.GetKind() == "Deployment" && wl.GetName() == "test-app" { + deploymentFound = true + + // Verify the deployment has the resource limits from the base + obj := wl.GetObject() + spec, ok := obj["spec"].(map[string]interface{}) + assert.True(t, ok, "deployment should have spec") + + template, ok := spec["template"].(map[string]interface{}) + assert.True(t, ok, "deployment should have template") + + templateSpec, ok := template["spec"].(map[string]interface{}) + assert.True(t, ok, "template should have spec") + + containers, ok := templateSpec["containers"].([]interface{}) + assert.True(t, ok, "template spec should have containers") + assert.NotEmpty(t, containers, "should have at least one container") + + container, ok := containers[0].(map[string]interface{}) + assert.True(t, ok, "container should be a map") + + resources, ok := container["resources"].(map[string]interface{}) + assert.True(t, ok, "container should have resources (from base)") + + limits, ok := resources["limits"].(map[string]interface{}) + assert.True(t, ok, "resources should have limits") + assert.Equal(t, "500m", limits["cpu"], "cpu limit should be from base") + assert.Equal(t, "256Mi", limits["memory"], "memory limit should be from base") + + // Verify overlay modifications were applied + replicas, ok := spec["replicas"].(int) + assert.True(t, ok, "replicas should be an int") + assert.Equal(t, 3, replicas, "replicas should be modified by overlay") + } + } + } + assert.True(t, deploymentFound, "deployment should be found in rendered output") +} + +// TestKustomizeBaseDirectory tests that base directories work on their own +func TestKustomizeBaseDirectory(t *testing.T) { + basePath := filepath.Join(kustomizeTestdataPath(), "base") + + assert.True(t, isKustomizeDirectory(basePath), "base should be detected as kustomize directory") + + kd := NewKustomizeDirectory(basePath) + workloads, errs := kd.GetWorkloads(basePath) + + assert.Empty(t, errs, "should not have errors loading base directory") + assert.NotEmpty(t, workloads, "should have workloads from base directory") +} diff --git a/core/cautils/testdata/kustomize/base/deployment.yaml b/core/cautils/testdata/kustomize/base/deployment.yaml new file mode 100644 index 00000000..373e861d --- /dev/null +++ b/core/cautils/testdata/kustomize/base/deployment.yaml @@ -0,0 +1,28 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-app + labels: + app: test-app +spec: + replicas: 1 + selector: + matchLabels: + app: test-app + template: + metadata: + labels: + app: test-app + spec: + containers: + - name: test-container + image: nginx:1.19 + resources: + limits: + cpu: "500m" + memory: "256Mi" + requests: + cpu: "100m" + memory: "128Mi" + ports: + - containerPort: 80 diff --git a/core/cautils/testdata/kustomize/base/kustomization.yaml b/core/cautils/testdata/kustomize/base/kustomization.yaml new file mode 100644 index 00000000..88a04b54 --- /dev/null +++ b/core/cautils/testdata/kustomize/base/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - deployment.yaml diff --git a/core/cautils/testdata/kustomize/overlays/prod/kustomization.yaml b/core/cautils/testdata/kustomize/overlays/prod/kustomization.yaml new file mode 100644 index 00000000..611e4ae8 --- /dev/null +++ b/core/cautils/testdata/kustomize/overlays/prod/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - ../../base + +images: + - name: nginx + newTag: "1.21" + +replicas: + - name: test-app + count: 3