diff --git a/context/context.go b/context/context.go index 49de7f469..314fc3584 100644 --- a/context/context.go +++ b/context/context.go @@ -28,6 +28,9 @@ type ResourceSet struct { // Values to include when interpolating resources from this resource set. Values map[string]interface{} `json:"values"` + // Args to pass on to kubectl for this resource set. + Args []string `json:"args"` + // Nested resource sets to include Include []ResourceSet `json:"include"` diff --git a/context/context_test.go b/context/context_test.go index 34c77cc9b..d7fdc11e5 100644 --- a/context/context_test.go +++ b/context/context_test.go @@ -54,6 +54,42 @@ func TestLoadFlatContextFromFile(t *testing.T) { } } +func TestLoadContextWithArgs(t *testing.T) { + ctx, err := LoadContext("testdata/flat-with-args-test.yaml", &noExplicitVars) + + if err != nil { + t.Error(err) + t.Fail() + } + + expected := Context{ + Name: "k8s.prod.mydomain.com", + ResourceSets: []ResourceSet{ + { + Name: "some-api", + Path: "some-api", + Values: make(map[string]interface{}, 0), + Args: []string{ + "--as=some-user", + "--as-group=hello:world", + "--as-banana", + "true", + }, + Include: nil, + Parent: "", + }, + }, + BaseDir: "testdata", + ImportedVars: make(map[string]interface{}, 0), + ExplicitVars: make(map[string]interface{}, 0), + } + + if !reflect.DeepEqual(*ctx, expected) { + t.Error("Loaded context and expected context did not match") + t.Fail() + } +} + func TestLoadContextWithResourceSetCollections(t *testing.T) { ctx, err := LoadContext("testdata/collections-test.yaml", &noExplicitVars) diff --git a/context/testdata/flat-with-args-test.yaml b/context/testdata/flat-with-args-test.yaml new file mode 100644 index 000000000..29d3334fb --- /dev/null +++ b/context/testdata/flat-with-args-test.yaml @@ -0,0 +1,9 @@ +--- +context: k8s.prod.mydomain.com +include: + - name: some-api + args: + - --as=some-user + - --as-group=hello:world + - --as-banana + - "true" diff --git a/docs/resource-sets.md b/docs/resource-sets.md index 94d402f9a..1444dd491 100644 --- a/docs/resource-sets.md +++ b/docs/resource-sets.md @@ -16,6 +16,7 @@ Technically a resource set is simply a folder with a few YAML and/or JSON templa - [`name`](#name) - [`path`](#path) - [`values`](#values) + - [`args`](#args) - [`include`](#include) - [Multiple includes](#multiple-includes) - [Nesting resource sets](#nesting-resource-sets) @@ -81,6 +82,12 @@ The `values` field specifies key/values pairs of variables that should be availa This field is **optional**. +### `args` + +The `args` field specifies a list of arguments that should be passed to `kubectl`. + +This field is **optional**. + ### `include` The `include` field specifies additional resource sets that should be included and that should inherit the diff --git a/main.go b/main.go index 6dacc5275..3d20adde3 100644 --- a/main.go +++ b/main.go @@ -199,7 +199,7 @@ func loadContextAndResources(file *string) (*context.Context, *[]templater.Rende } func runKubectlWithResources(c *context.Context, kubectlArgs *[]string, resourceSets *[]templater.RenderedResourceSet) error { - args := append(*kubectlArgs, fmt.Sprintf("--context=%s", c.Name)) + argsWithContext := append(*kubectlArgs, fmt.Sprintf("--context=%s", c.Name)) for _, rs := range *resourceSets { if len(rs.Resources) == 0 { @@ -207,7 +207,9 @@ func runKubectlWithResources(c *context.Context, kubectlArgs *[]string, resource continue } - kubectl := exec.Command(*kubectlBin, args...) + argsWithResourceSetArgs := append(argsWithContext, rs.Args...) + + kubectl := exec.Command(*kubectlBin, argsWithResourceSetArgs...) stdin, err := kubectl.StdinPipe() if err != nil { diff --git a/templater/templater.go b/templater/templater.go index ff4e0efde..e842daeba 100644 --- a/templater/templater.go +++ b/templater/templater.go @@ -35,6 +35,7 @@ type RenderedResource struct { type RenderedResourceSet struct { Name string Resources []RenderedResource + Args []string } func LoadAndApplyTemplates(include *[]string, exclude *[]string, c *context.Context) ([]RenderedResourceSet, error) { @@ -94,6 +95,7 @@ func processResourceSet(ctx *context.Context, rs *context.ResourceSet) (*Rendere return &RenderedResourceSet{ Name: rs.Name, Resources: resources, + Args: rs.Args, }, nil }