Skip to content

Commit

Permalink
feat(generate): support k8s manifest overriding (#88)
Browse files Browse the repository at this point in the history
Signed-off-by: Ben Meier <ben.meier@humanitec.com>
  • Loading branch information
astromechza authored Nov 21, 2024
1 parent 70df937 commit 641d0df
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
27 changes: 27 additions & 0 deletions internal/command/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ manifests. All resources and links between Workloads will be resolved and provis
if p, ok := internal.FindFirstUnresolvedSecretRef("", manifest); ok {
return errors.Errorf("unresolved secret ref in manifest: %s", p)
}
mSig := buildManifestSignature(manifest)
outputManifests = slices.DeleteFunc(outputManifests, func(other map[string]interface{}) bool {
if buildManifestSignature(other) == mSig {
slog.Info(fmt.Sprintf("Overriding duplicate resource manifest %s", mSig))
return true
}
return false
})
outputManifests = append(outputManifests, manifest)
}
slog.Info(fmt.Sprintf("Wrote %d resource manifests to manifests buffer for resource '%s'", len(res.Extras.Manifests), id))
Expand All @@ -217,6 +225,14 @@ manifests. All resources and links between Workloads will be resolved and provis
if p, ok := internal.FindFirstUnresolvedSecretRef("", intermediate); ok {
return errors.Errorf("unresolved secret ref in manifest: %s", p)
}
mSig := buildManifestSignature(intermediate)
outputManifests = slices.DeleteFunc(outputManifests, func(other map[string]interface{}) bool {
if buildManifestSignature(other) == mSig {
slog.Info(fmt.Sprintf("Overriding duplicate resource manifest %s", mSig))
return true
}
return false
})
outputManifests = append(outputManifests, intermediate)
}
slog.Info(fmt.Sprintf("Wrote %d manifests to manifests buffer for workload '%s'", len(manifests), workloadName))
Expand Down Expand Up @@ -335,6 +351,17 @@ func parseAndApplyManifestPatches(entry string, flagName string, manifests []map
return outManifests, nil
}

// buildManifestSignature builds a unique manifest signature for each manifest coming out of a resource. This is used
// to deduplicate resource manifests when they share state.
func buildManifestSignature(n map[string]interface{}) string {
apiVersion, _ := n["apiVersion"].(string)
kind, _ := n["kind"].(string)
metadata, _ := n["metadata"].(map[string]interface{})
namespace, _ := metadata["namespace"].(string)
name, _ := metadata["name"].(string)
return fmt.Sprintf("%s/%s/%s/%s", apiVersion, kind, namespace, name)
}

func init() {
generateCmd.Flags().StringP(generateCmdOutputFlag, "o", "manifests.yaml", "The output manifests file to write the manifests to")
generateCmd.Flags().String(generateCmdOverridesFileFlag, "", "An optional file of Score overrides to merge in")
Expand Down
37 changes: 37 additions & 0 deletions internal/command/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"os"
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -236,3 +237,39 @@ containers:
assert.EqualError(t, err, "cannot use --override-property, --overrides-file, or --image when 0 or more than 1 score files are provided")
assert.Equal(t, "", stdout)
}

func TestDeduplicateResourceManifests(t *testing.T) {
td := changeToTempDir(t)
assert.NoError(t, os.WriteFile(filepath.Join(td, "score.yaml"), []byte(`
apiVersion: score.dev/v1b1
metadata:
name: example-a
containers:
hello:
image: foo
resources:
d1:
type: dummy
d2:
type: dummy
`), 0644))
_, _, err := executeAndResetCommand(context.Background(), rootCmd, []string{"init"})
require.NoError(t, err)
assert.NoError(t, os.WriteFile(filepath.Join(td, ".score-k8s", "00.provisioners.yaml"), []byte(`
- uri: template://dummy
type: dummy
manifests: |
- apiVersion: v1
kind: Secret
metadata:
name: my-secret
data:
fruit: {{ b64enc "banana" }}
`), 0644))
_, stderr, err := executeAndResetCommand(context.Background(), rootCmd, []string{"generate", "score.yaml"})
t.Log(string(stderr))
require.NoError(t, err)
rawManifests, err := os.ReadFile(filepath.Join(td, "manifests.yaml"))
require.NoError(t, err)
assert.Equal(t, strings.Count(string(rawManifests), "kind: Secret"), 1, "failed to find in", string(rawManifests))
}

0 comments on commit 641d0df

Please sign in to comment.