Repository: grafana/tanka (go)

Issue:
Server side apply
Some CRDs inside `kube-prometheus-stack` fails to apply due to large size.

> The CustomResourceDefinition "prometheuses.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes

The proposed way for installation is using the `--server-side` flag for `kubectl apply`.
Is there a way to support that with tanka?
Currently, I'm using this as a workaround.

```bash
#!/usr/bin/env bash

rm -rf manifests
tk export manifests/ environments/prod -t 'CustomResourceDefinition.*'
find manifests -type f ! -name '*.yaml' -delete
kubectl apply --server-side -f manifests
tk apply environments/prod -t '!CustomResourceDefinition.*'
```

Pull request description:
feat: support apply --server-side
Fixes #694.

Support `tk apply --server-side ...`, passed down to `kubectl apply --server-side ...`.


Patch:
diff --git a/cmd/tk/workflow.go b/cmd/tk/workflow.go
index bc19a06e..733e8cc4 100644
--- a/cmd/tk/workflow.go
+++ b/cmd/tk/workflow.go
@@ -41,6 +41,7 @@ func applyCmd() *cli.Command {
 	cmd.Flags().BoolVar(&opts.Validate, "validate", true, "validation of resources (kubectl --validate=false)")
 	cmd.Flags().BoolVar(&opts.AutoApprove, "dangerous-auto-approve", false, "skip interactive approval. Only for automation!")
 	cmd.Flags().StringVar(&opts.DryRun, "dry-run", "", `--dry-run parameter to pass down to kubectl, must be "none", "server", or "client"`)
+	cmd.Flags().BoolVar(&opts.ServerSide, "server-side", false, `pass --server-side flag down to kubectl`)
 
 	vars := workflowFlags(cmd.Flags())
 	getJsonnetOpts := jsonnetFlags(cmd.Flags())
diff --git a/pkg/kubernetes/client/apply.go b/pkg/kubernetes/client/apply.go
index 83a40cb2..421aed01 100644
--- a/pkg/kubernetes/client/apply.go
+++ b/pkg/kubernetes/client/apply.go
@@ -25,6 +25,10 @@ func (k Kubectl) applyCtl(data manifest.List, opts ApplyOpts) *exec.Cmd {
 		argv = append(argv, dryRun)
 	}
 
+	if opts.ServerSide {
+		argv = append(argv, "--server-side")
+	}
+
 	return k.ctl("apply", argv...)
 }
 
diff --git a/pkg/kubernetes/client/client.go b/pkg/kubernetes/client/client.go
index 7b88cef6..9c8be1eb 100644
--- a/pkg/kubernetes/client/client.go
+++ b/pkg/kubernetes/client/client.go
@@ -53,6 +53,9 @@ type ApplyOpts struct {
 
 	// DryRun string passed to kubectl as --dry-run=<DryRun>
 	DryRun string
+
+	// ServerSide flag passed to kubectl as --server-side
+	ServerSide bool
 }
 
 // DeleteOpts allow to specify additional parameters for delete operations
diff --git a/pkg/tanka/workflow.go b/pkg/tanka/workflow.go
index 6d6e3fa3..8795ba8a 100644
--- a/pkg/tanka/workflow.go
+++ b/pkg/tanka/workflow.go
@@ -27,6 +27,8 @@ type ApplyOpts struct {
 	Validate bool
 	// DryRun string passed to kubectl as --dry-run=<DryRun>
 	DryRun string
+	// ServerSide bool passed to kubectl as --server-side
+	ServerSide bool
 }
 
 // Apply parses the environment at the given directory (a `baseDir`) and applies
@@ -67,9 +69,10 @@ func Apply(baseDir string, opts ApplyOpts) error {
 	}
 
 	return kube.Apply(l.Resources, kubernetes.ApplyOpts{
-		Force:    opts.Force,
-		Validate: opts.Validate,
-		DryRun:   opts.DryRun,
+		Force:      opts.Force,
+		Validate:   opts.Validate,
+		DryRun:     opts.DryRun,
+		ServerSide: opts.ServerSide,
 	})
 }
 


Test patch:
diff --git a/pkg/kubernetes/client/apply_test.go b/pkg/kubernetes/client/apply_test.go
index 193075b7..6436ac01 100644
--- a/pkg/kubernetes/client/apply_test.go
+++ b/pkg/kubernetes/client/apply_test.go
@@ -58,6 +58,13 @@ func TestKubectl_applyCtl(t *testing.T) {
 			expectedArgs:   []string{"--dry-run=server"},
 			unExpectedArgs: []string{"--validate=false"},
 		},
+		{
+			name: "test server-side",
+			args: args{
+				opts: ApplyOpts{ServerSide: true},
+			},
+			expectedArgs: []string{"--server-side"},
+		},
 	}
 
 	for _, tt := range tests {