Repository: GoogleContainerTools/skaffold
Pull request #7422 (2022-05-18 19:00:50)

chore: rename folder testdata/gcb-with-location


<!-- Include if applicable: -->
rename typo from #7411, not sure why the integration test passed though with incorrect path.


codecov[bot]: # [Codecov](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools) Report
> Merging [#7422](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools) (6bc9112) into [main](https://codecov.io/gh/GoogleContainerTools/skaffold/commit/290280e8c6c19231e9ed5b5c027f2c01d22f75be?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools) (290280e) will **decrease** coverage by `4.04%`.
> The diff coverage is `55.07%`.

```diff
@@            Coverage Diff             @@
##             main    #7422      +/-   ##
==========================================
- Coverage   70.48%   66.43%   -4.05%     
==========================================
  Files         515      570      +55     
  Lines       23150    27533    +4383     
==========================================
+ Hits        16317    18292    +1975     
- Misses       5776     7901    +2125     
- Partials     1057     1340     +283     
```


| [Impacted Files](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools) | Coverage Δ | |
|---|---|---|
| [cmd/skaffold/app/cmd/credits/export.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvY3JlZGl0cy9leHBvcnQuZ28=) | `0.00% <0.00%> (ø)` | |
| [cmd/skaffold/app/cmd/deploy.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvZGVwbG95Lmdv) | `50.00% <0.00%> (-3.85%)` | :arrow_down: |
| [cmd/skaffold/app/cmd/test.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvdGVzdC5nbw==) | `44.44% <0.00%> (ø)` | |
| [cmd/skaffold/skaffold.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL3NrYWZmb2xkLmdv) | `0.00% <0.00%> (ø)` | |
| [cmd/skaffold/app/cmd/render.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvcmVuZGVyLmdv) | `34.37% <10.00%> (-7.01%)` | :arrow_down: |
| [cmd/skaffold/app/cmd/inspect\_tests.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvaW5zcGVjdF90ZXN0cy5nbw==) | `62.50% <14.28%> (-1.14%)` | :arrow_down: |
| [cmd/skaffold/app/cmd/lsp.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvbHNwLmdv) | `28.12% <28.12%> (ø)` | |
| [cmd/skaffold/app/cmd/fix.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvZml4Lmdv) | `55.93% <38.88%> (-20.54%)` | :arrow_down: |
| [cmd/skaffold/app/cmd/verify.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvdmVyaWZ5Lmdv) | `41.17% <41.17%> (ø)` | |
| [cmd/skaffold/app/cmd/lint.go](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools#diff-Y21kL3NrYWZmb2xkL2FwcC9jbWQvbGludC5nbw==) | `42.85% <42.85%> (ø)` | |
| ... and [300 more](https://codecov.io/gh/GoogleContainerTools/skaffold/pull/7422/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools) | |

:mega: Codecov can now indicate which changes are the most critical in Pull Requests. [Learn more](https://about.codecov.io/product/feature/runtime-insights/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=GoogleContainerTools)


Patch:
diff --git a/cmd/skaffold/app/cmd/deploy.go b/cmd/skaffold/app/cmd/deploy.go
index e5b17c79e..bbfa050a4 100644
--- a/cmd/skaffold/app/cmd/deploy.go
+++ b/cmd/skaffold/app/cmd/deploy.go
@@ -56,7 +56,7 @@ func doDeploy(ctx context.Context, out io.Writer) error {
 			return err
 		}
 		// Render
-		manifests, errR := r.Render(ctx, out, buildArtifacts, true, opts.RenderOutput)
+		manifests, errR := r.Render(ctx, out, buildArtifacts, true)
 		if errR != nil {
 			return errR
 		}
diff --git a/cmd/skaffold/app/cmd/render.go b/cmd/skaffold/app/cmd/render.go
index 656aaa6af..119bc293f 100644
--- a/cmd/skaffold/app/cmd/render.go
+++ b/cmd/skaffold/app/cmd/render.go
@@ -75,11 +75,10 @@ func doRender(ctx context.Context, out io.Writer) error {
 			}
 		}
 
-		manifests, errR := r.Render(ctx, out, bRes, offline, opts.RenderOutput)
-		if errR != nil {
-			return fmt.Errorf("rendering manifests: %w", errR)
+		manifests, err := r.Render(ctx, out, bRes, offline)
+		if err != nil {
+			return fmt.Errorf("rendering manifests: %w", err)
 		}
-		manifest.Write(manifests.String(), opts.RenderOutput, out)
-		return nil
+		return manifest.Write(manifests.String(), opts.RenderOutput, out)
 	})
 }
diff --git a/cmd/skaffold/app/cmd/run.go b/cmd/skaffold/app/cmd/run.go
index af23c7876..8a898ecec 100644
--- a/cmd/skaffold/app/cmd/run.go
+++ b/cmd/skaffold/app/cmd/run.go
@@ -55,7 +55,7 @@ func doRun(ctx context.Context, out io.Writer) error {
 		}
 
 		// Render
-		manifestList, err := r.Render(ctx, out, bRes, true, opts.RenderOutput)
+		manifestList, err := r.Render(ctx, out, bRes, true)
 		if err != nil {
 			return err
 		}
diff --git a/integration/examples/getting-started/artifacts.json b/integration/examples/getting-started/artifacts.json
deleted file mode 100644
index d558a6b27..000000000
--- a/integration/examples/getting-started/artifacts.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"builds":null}
\ No newline at end of file
diff --git a/integration/examples/getting-started/images.json b/integration/examples/getting-started/images.json
deleted file mode 100644
index d558a6b27..000000000
--- a/integration/examples/getting-started/images.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"builds":null}
\ No newline at end of file
diff --git a/integration/examples/getting-started/skaffold.yaml b/integration/examples/getting-started/skaffold.yaml
index adea0d850..a3b2a231a 100644
--- a/integration/examples/getting-started/skaffold.yaml
+++ b/integration/examples/getting-started/skaffold.yaml
@@ -5,4 +5,4 @@ build:
   - image: skaffold-example
 manifests:
   rawYaml:
-  - k8s-*
+  - k8s-pod.yaml
diff --git a/pkg/skaffold/deploy/kubectl/kubectl.go b/pkg/skaffold/deploy/kubectl/kubectl.go
index 1f148f3dc..3e0a79cbb 100644
--- a/pkg/skaffold/deploy/kubectl/kubectl.go
+++ b/pkg/skaffold/deploy/kubectl/kubectl.go
@@ -80,7 +80,6 @@ type Deployer struct {
 	insecureRegistries map[string]bool
 	labeller           *label.DefaultLabeller
 	skipRender         bool
-	hydrationDir       string
 	namespaces         *[]string
 
 	transformableAllowlist map[apimachinery.GroupKind]latest.ResourceFilter
@@ -89,7 +88,7 @@ type Deployer struct {
 
 // NewDeployer returns a new Deployer for a DeployConfig filled
 // with the needed configuration for `kubectl apply`
-func NewDeployer(cfg Config, labeller *label.DefaultLabeller, d *latest.KubectlDeploy, hydrationDir string) (*Deployer, error) {
+func NewDeployer(cfg Config, labeller *label.DefaultLabeller, d *latest.KubectlDeploy) (*Deployer, error) {
 	defaultNamespace := ""
 	if d.DefaultNamespace != nil {
 		var err error
@@ -132,7 +131,6 @@ func NewDeployer(cfg Config, labeller *label.DefaultLabeller, d *latest.KubectlD
 		// hydratedManifests refers to the DIR in the `skaffold apply DIR`. Used in both v1 and v2.
 		hydratedManifests: cfg.HydratedManifests(),
 		// hydrationDir refers to the path where the hydrated manifests are stored, this is introduced in v2.
-		hydrationDir: hydrationDir,
 
 		transformableAllowlist: transformableAllowlist,
 		transformableDenylist:  transformableDenylist,
diff --git a/pkg/skaffold/render/generate/generate.go b/pkg/skaffold/render/generate/generate.go
index 3c53ab14b..1f1fec19c 100644
--- a/pkg/skaffold/render/generate/generate.go
+++ b/pkg/skaffold/render/generate/generate.go
@@ -91,34 +91,18 @@ func (g Generator) Generate(ctx context.Context, out io.Writer) (manifest.Manife
 	var manifests manifest.ManifestList
 
 	// Generate kustomize Manifests
-	_, endTrace := instrumentation.StartTrace(ctx, "Render_expandGlobKustomizeManifests")
-	kustomizePaths, err := resolveRemoteAndLocal(g.config.Kustomize, g.workingDir)
-	if err != nil {
-		event.DeployInfoEvent(fmt.Errorf("could not expand the glob kustomize manifests: %w", err))
-		return nil, err
-	}
-	endTrace()
-	kustomizePathMap := make(map[string]bool)
-	for _, path := range kustomizePaths {
-		if dir, ok := isKustomizeDir(path); ok {
-			kustomizePathMap[dir] = true
-		}
-	}
-	for kPath := range kustomizePathMap {
-		// TODO: kustomize kpt-fn not available yet. See https://github.com/GoogleContainerTools/kpt/issues/1447
-		cmd := exec.CommandContext(ctx, "kustomize", "build", kPath)
-		out, err := util.RunCmdOut(ctx, cmd)
+	if g.config.Kustomize != nil && len(g.config.Kustomize.Paths) != 0 {
+		kustomizeManifests, err := g.generateKustomizeManifests(ctx)
 		if err != nil {
 			return nil, err
 		}
-		if len(out) == 0 {
-			continue
+		for _, m := range kustomizeManifests {
+			manifests.Append(m)
 		}
-		manifests.Append(out)
 	}
 
 	// Generate in-place hydrated kpt Manifests
-	_, endTrace = instrumentation.StartTrace(ctx, "Render_expandGlobKptManifests")
+	_, endTrace := instrumentation.StartTrace(ctx, "Render_expandGlobKptManifests")
 	kptPaths, err := resolveRemoteAndLocal(g.config.Kpt, g.workingDir)
 	if err != nil {
 		event.DeployInfoEvent(fmt.Errorf("could not expand the glob kpt manifests: %w", err))
@@ -174,6 +158,38 @@ func (g Generator) Generate(ctx context.Context, out io.Writer) (manifest.Manife
 	return manifests, nil
 }
 
+func (g Generator) generateKustomizeManifests(ctx context.Context) ([][]byte, error) {
+	var manifests [][]byte
+
+	_, endTrace := instrumentation.StartTrace(ctx, "Render_expandGlobKustomizeManifests")
+	kustomizePaths, err := resolveRemoteAndLocal(g.config.Kustomize.Paths, g.workingDir)
+	if err != nil {
+		event.DeployInfoEvent(fmt.Errorf("could not expand the glob kustomize manifests: %w", err))
+		return nil, err
+	}
+	endTrace()
+	kustomizePathMap := make(map[string]bool)
+	for _, path := range kustomizePaths {
+		if dir, ok := isKustomizeDir(path); ok {
+			kustomizePathMap[dir] = true
+		}
+	}
+	for kPath := range kustomizePathMap {
+		// TODO: kustomize kpt-fn not available yet. See https://github.com/GoogleContainerTools/kpt/issues/1447
+		cmd := exec.CommandContext(ctx, "kustomize", append([]string{"build"}, kustomizeBuildArgs(g.config.Kustomize.BuildArgs, kPath)...)...)
+		out, err := util.RunCmdOut(ctx, cmd)
+		if err != nil {
+			return nil, err
+		}
+		if len(out) == 0 {
+			continue
+		}
+		manifests = append(manifests, out)
+	}
+
+	return manifests, nil
+}
+
 // isKustomizeDir checks if the path is managed by kustomize. A more reliable approach is parsing the kustomize content
 // resources, bases, overlays. However, this switches the manifests parsing from kustomize/kpt to skaffold. To avoid
 // skaffold render.generate mis-use, we expect the users do not place non-kustomize manifests under the kustomization.yaml directory, so as the kpt manifests.
@@ -200,6 +216,24 @@ func isKustomizeDir(path string) (string, bool) {
 	return "", false
 }
 
+// kustomizeBuildArgs returns a list of build args to be passed to kustomize build.
+func kustomizeBuildArgs(buildArgs []string, kustomizePath string) []string {
+	var args []string
+
+	if len(buildArgs) > 0 {
+		for _, v := range buildArgs {
+			parts := strings.Split(v, " ")
+			args = append(args, parts...)
+		}
+	}
+
+	if len(kustomizePath) > 0 {
+		args = append(args, kustomizePath)
+	}
+
+	return args
+}
+
 func isKptDir(path string) (string, bool) {
 	fileInfo, err := os.Stat(path)
 	if err != nil {
@@ -220,16 +254,19 @@ func isKptDir(path string) (string, bool) {
 
 // walkManifests finds out all the manifests from the `.manifests.generate`, so they can be registered in the file watcher.
 // Note: the logic about manifest dependencies shall separate from the "Generate" function, which requires "context" and
-// only be called when a renderig action is needed (normally happens after the file watcher registration).
+// only be called when a rendering action is needed (normally happens after the file watcher registration).
 func (g Generator) walkManifests() ([]string, error) {
 	var dependencyPaths []string
+
 	// Generate kustomize Manifests
-	kustomizePaths, err := resolveRemoteAndLocal(g.config.Kustomize, g.workingDir)
-	if err != nil {
-		event.DeployInfoEvent(fmt.Errorf("could not expand the glob kustomize manifests: %w", err))
-		return nil, err
+	if g.config.Kustomize != nil {
+		kustomizePaths, err := resolveRemoteAndLocal(g.config.Kustomize.Paths, g.workingDir)
+		if err != nil {
+			event.DeployInfoEvent(fmt.Errorf("could not expand the glob kustomize manifests: %w", err))
+			return nil, err
+		}
+		dependencyPaths = append(dependencyPaths, kustomizePaths...)
 	}
-	dependencyPaths = append(dependencyPaths, kustomizePaths...)
 
 	// Generate in-place hydrated kpt Manifests
 	kptPaths, err := resolveRemoteAndLocal(g.config.Kpt, g.workingDir)
diff --git a/pkg/skaffold/render/renderer/kpt/kpt.go b/pkg/skaffold/render/renderer/kpt/kpt.go
index e8ff2f3ca..fb4fc725b 100644
--- a/pkg/skaffold/render/renderer/kpt/kpt.go
+++ b/pkg/skaffold/render/renderer/kpt/kpt.go
@@ -97,7 +97,7 @@ func New(cfg render.Config, rCfg latest.RenderConfig, hydrationDir string, label
 	}, nil
 }
 
-func (r *Kpt) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, _ bool, output string) (manifest.ManifestList, error) {
+func (r *Kpt) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, _ bool) (manifest.ManifestList, error) {
 	kptfilePath := filepath.Join(r.hydrationDir, kptfile.KptFileName)
 	kfConfig := &kptfile.KptFile{}
 
@@ -153,7 +153,7 @@ func (r *Kpt) Render(ctx context.Context, out io.Writer, builds []graph.Artifact
 	if err := os.MkdirAll(r.hydrationDir, os.ModePerm); err != nil {
 		return nil, err
 	}
-	if err := manifest.Write(manifests.String(), dryConfigPath, out); err != nil {
+	if err := manifest.Write(manifests.String(), dryConfigPath, io.Discard); err != nil {
 		return nil, err
 	}
 	endTrace()
@@ -183,15 +183,12 @@ func (r *Kpt) Render(ctx context.Context, out io.Writer, builds []graph.Artifact
 		// TODO(yuwenma): How to guide users when they face kpt error (may due to bad user config)?
 		return nil, err
 	}
-
-	if output != "" {
-		r.writeManifestsToFile(ctx, out, output)
-	}
-	return manifests, nil
+	return r.unwrapManifests(ctx, out)
 }
 
-// writeManifestsToFile converts the structured manifest to a flatten format and store them in the given `output` file.
-func (r *Kpt) writeManifestsToFile(ctx context.Context, out io.Writer, output string) error {
+// unwrapManifests converts the structured manifest to a flatten format
+func (r *Kpt) unwrapManifests(ctx context.Context, out io.Writer) (manifest.ManifestList, error) {
+	var m manifest.ManifestList
 	rCtx, endTrace := instrumentation.StartTrace(ctx, "Render_outputManifests")
 	cmd := exec.CommandContext(rCtx, "kpt", "fn", "source", r.hydrationDir, "-o", "unwrap")
 	var buf []byte
@@ -199,7 +196,8 @@ func (r *Kpt) writeManifestsToFile(ctx context.Context, out io.Writer, output st
 	buf, err := util.RunCmdOut(ctx, cmd)
 	if err != nil {
 		endTrace(instrumentation.TraceEndError(err))
-		return err
+		return m, err
 	}
-	return ioutil.WriteFile(output, buf, os.ModePerm)
+	m = append(m, buf)
+	return m, nil
 }
diff --git a/pkg/skaffold/render/renderer/kubectl/kubectl.go b/pkg/skaffold/render/renderer/kubectl/kubectl.go
index 7ce5637cb..f8e10eac3 100644
--- a/pkg/skaffold/render/renderer/kubectl/kubectl.go
+++ b/pkg/skaffold/render/renderer/kubectl/kubectl.go
@@ -55,7 +55,7 @@ func New(cfg render.Config, rCfg latest.RenderConfig, labels map[string]string)
 	}, nil
 }
 
-func (r Kubectl) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, _ bool, _ string) (manifest.ManifestList, error) {
+func (r Kubectl) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, _ bool) (manifest.ManifestList, error) {
 	_, endTrace := instrumentation.StartTrace(ctx, "Render_KubectlManifests")
 	log.Entry(ctx).Infof("rendering using kubectl")
 	instrumentation.AddAttributesToCurrentSpanFromContext(ctx, map[string]string{
diff --git a/pkg/skaffold/render/renderer/noop/noop.go b/pkg/skaffold/render/renderer/noop/noop.go
index ac975e434..cf5b10827 100644
--- a/pkg/skaffold/render/renderer/noop/noop.go
+++ b/pkg/skaffold/render/renderer/noop/noop.go
@@ -34,7 +34,7 @@ func New(_ latest.RenderConfig, _, _ string, _ map[string]string) (Noop, error)
 	return Noop{}, nil
 }
 
-func (r Noop) Render(_ context.Context, _ io.Writer, _ []graph.Artifact, _ bool, _ string) (manifest.ManifestList, error) {
+func (r Noop) Render(_ context.Context, _ io.Writer, _ []graph.Artifact, _ bool) (manifest.ManifestList, error) {
 	return manifest.ManifestList{}, nil
 }
 
diff --git a/pkg/skaffold/render/renderer/render_mux.go b/pkg/skaffold/render/renderer/render_mux.go
index 05f45826e..b5a80d4d9 100644
--- a/pkg/skaffold/render/renderer/render_mux.go
+++ b/pkg/skaffold/render/renderer/render_mux.go
@@ -41,13 +41,13 @@ func NewRenderMux(renderers []Renderer) Renderer {
 	return RenderMux{renderers: renderers}
 }
 
-func (r RenderMux) Render(ctx context.Context, out io.Writer, artifacts []graph.Artifact, offline bool, outputPath string) (manifest.ManifestList, error) {
+func (r RenderMux) Render(ctx context.Context, out io.Writer, artifacts []graph.Artifact, offline bool) (manifest.ManifestList, error) {
 	allManifests := manifest.ManifestList{}
 	for i, renderer := range r.renderers {
 		eventV2.RendererInProgress(i)
 		w, ctx := output.WithEventContext(ctx, out, constants.Render, strconv.Itoa(i))
 		ctx, endTrace := instrumentation.StartTrace(ctx, "Render")
-		ms, err := renderer.Render(ctx, w, artifacts, offline, "" /* never write to files */)
+		ms, err := renderer.Render(ctx, w, artifacts, offline)
 		if err != nil {
 			eventV2.RendererFailed(i, err)
 			endTrace(instrumentation.TraceEndError(err))
diff --git a/pkg/skaffold/render/renderer/renderer.go b/pkg/skaffold/render/renderer/renderer.go
index c59ea4a97..2aab295d4 100644
--- a/pkg/skaffold/render/renderer/renderer.go
+++ b/pkg/skaffold/render/renderer/renderer.go
@@ -31,7 +31,7 @@ import (
 )
 
 type Renderer interface {
-	Render(ctx context.Context, out io.Writer, artifacts []graph.Artifact, offline bool, output string) (manifest.ManifestList, error)
+	Render(ctx context.Context, out io.Writer, artifacts []graph.Artifact, offline bool) (manifest.ManifestList, error)
 	// ManifestDeps returns the user kubernetes manifests to file watcher. In dev mode, a "redeploy" will be triggered
 	// if any of the "Dependencies" manifest is changed.
 	ManifestDeps() ([]string, error)
diff --git a/pkg/skaffold/runner/deployer.go b/pkg/skaffold/runner/deployer.go
index 7e4c80a4b..8bc903a7c 100644
--- a/pkg/skaffold/runner/deployer.go
+++ b/pkg/skaffold/runner/deployer.go
@@ -115,7 +115,7 @@ func GetDeployer(ctx context.Context, runCtx *runcontext.RunContext, labeller *l
 			}
 		}
 
-		return getDefaultDeployer(runCtx, labeller, hydrationDir)
+		return getDefaultDeployer(runCtx, labeller)
 	}
 
 	var deployers []deploy.Deployer
@@ -158,7 +158,7 @@ func GetDeployer(ctx context.Context, runCtx *runcontext.RunContext, labeller *l
 		}
 
 		if d.KubectlDeploy != nil {
-			deployer, err := kubectl.NewDeployer(dCtx, labeller, d.KubectlDeploy, hydrationDir)
+			deployer, err := kubectl.NewDeployer(dCtx, labeller, d.KubectlDeploy)
 			if err != nil {
 				return nil, err
 			}
@@ -213,7 +213,7 @@ The default deployer will honor a select set of deploy configuration from an exi
 For a multi-config project, we do not currently support resolving conflicts between differing sets of this deploy configuration.
 Therefore, in this function we do implicit validation of the provided configuration, and fail if any conflict cannot be resolved.
 */
-func getDefaultDeployer(runCtx *runcontext.RunContext, labeller *label.DefaultLabeller, hydrationDir string) (deploy.Deployer, error) {
+func getDefaultDeployer(runCtx *runcontext.RunContext, labeller *label.DefaultLabeller) (deploy.Deployer, error) {
 	deployCfgs := runCtx.DeployConfigs()
 
 	var kFlags *latest.KubectlFlags
@@ -280,7 +280,7 @@ func getDefaultDeployer(runCtx *runcontext.RunContext, labeller *label.DefaultLa
 		DefaultNamespace: defaultNamespace,
 	}
 	dCtx := &deployerCtx{runCtx, latest.DeployConfig{StatusCheck: statusCheck, KubeContext: kubeContext, DeployType: latest.DeployType{KubectlDeploy: k}}}
-	defaultDeployer, err := kubectl.NewDeployer(dCtx, labeller, k, hydrationDir)
+	defaultDeployer, err := kubectl.NewDeployer(dCtx, labeller, k)
 	if err != nil {
 		return nil, fmt.Errorf("instantiating default kubectl deployer: %w", err)
 	}
diff --git a/pkg/skaffold/runner/runner.go b/pkg/skaffold/runner/runner.go
index c773c8264..dbc08aaff 100644
--- a/pkg/skaffold/runner/runner.go
+++ b/pkg/skaffold/runner/runner.go
@@ -45,8 +45,7 @@ type Runner interface {
 	HasDeployed() bool
 	Prune(context.Context, io.Writer) error
 
-	// "output" arg is only used in Render v1.
-	Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool, output string) (manifest.ManifestList, error)
+	Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool) (manifest.ManifestList, error)
 	Test(context.Context, io.Writer, []graph.Artifact) error
 	Verify(context.Context, io.Writer, []graph.Artifact) error
 	VerifyAndLog(context.Context, io.Writer, []graph.Artifact) error
diff --git a/pkg/skaffold/runner/timings.go b/pkg/skaffold/runner/timings.go
index 06996ddd0..20989fb4c 100644
--- a/pkg/skaffold/runner/timings.go
+++ b/pkg/skaffold/runner/timings.go
@@ -83,11 +83,11 @@ func (w withTimings) Test(ctx context.Context, out io.Writer, builds []graph.Art
 	return nil
 }
 
-func (w withTimings) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool, filepath string) (manifest.ManifestList, error) {
+func (w withTimings) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool) (manifest.ManifestList, error) {
 	start := time.Now()
 	log.Entry(ctx).Infoln("Starting render...")
 
-	manifestsLists, err := w.Renderer.Render(ctx, out, builds, offline, filepath)
+	manifestsLists, err := w.Renderer.Render(ctx, out, builds, offline)
 	if err != nil {
 		return nil, err
 	}
diff --git a/pkg/skaffold/runner/v2/dev.go b/pkg/skaffold/runner/v2/dev.go
index 1ad9c86d5..9fa2e26ac 100644
--- a/pkg/skaffold/runner/v2/dev.go
+++ b/pkg/skaffold/runner/v2/dev.go
@@ -178,7 +178,7 @@ func (r *SkaffoldRunner) doDev(ctx context.Context, out io.Writer) error {
 		if !meterUpdated {
 			instrumentation.AddDevIteration("deploy")
 		}
-		manifests, err := r.Render(childCtx, out, r.Builds, false, "")
+		manifests, err := r.Render(childCtx, out, r.Builds, false)
 		if err != nil {
 			log.Entry(ctx).Warn("Skipping render due to error:", err)
 			event.DevLoopFailedInPhase(r.devIteration, constants.Render, err)
@@ -347,7 +347,7 @@ func (r *SkaffoldRunner) Dev(ctx context.Context, out io.Writer, artifacts []*la
 	r.deployer.GetLogger().SetSince(time.Now())
 
 	// First render
-	manifests, err := r.Render(ctx, out, r.Builds, true, "")
+	manifests, err := r.Render(ctx, out, r.Builds, true)
 	if err != nil {
 		event.DevLoopFailedInPhase(r.devIteration, constants.Render, err)
 		eventV2.TaskFailed(constants.DevLoop, err)
diff --git a/pkg/skaffold/runner/v2/render.go b/pkg/skaffold/runner/v2/render.go
index 3b643894d..f3e0e6fdf 100644
--- a/pkg/skaffold/runner/v2/render.go
+++ b/pkg/skaffold/runner/v2/render.go
@@ -29,7 +29,7 @@ import (
 	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output"
 )
 
-func (r *SkaffoldRunner) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool, renderOutputFile string) (manifest.ManifestList, error) {
+func (r *SkaffoldRunner) Render(ctx context.Context, out io.Writer, builds []graph.Artifact, offline bool) (manifest.ManifestList, error) {
 	if r.runCtx.RenderOnly() {
 		// Fetch the digest and append it to the tag with the format of "tag@digest"
 		if r.runCtx.DigestSource() == constants.RemoteDigestSource {
@@ -48,11 +48,12 @@ func (r *SkaffoldRunner) Render(ctx context.Context, out io.Writer, builds []gra
 	}
 
 	ctx, endTrace := instrumentation.StartTrace(ctx, "Render")
-	manifestList, errR := r.renderer.Render(ctx, out, builds, offline, renderOutputFile)
-	if errR != nil {
-		endTrace(instrumentation.TraceEndError(errR))
-		return nil, errR
+	manifestList, err := r.renderer.Render(ctx, out, builds, offline)
+	if err != nil {
+		endTrace(instrumentation.TraceEndError(err))
+		return nil, err
 	}
+
 	endTrace()
 	return manifestList, nil
 }
diff --git a/pkg/skaffold/schema/defaults/defaults.go b/pkg/skaffold/schema/defaults/defaults.go
index 43fa1e074..b79ea6df5 100644
--- a/pkg/skaffold/schema/defaults/defaults.go
+++ b/pkg/skaffold/schema/defaults/defaults.go
@@ -121,7 +121,7 @@ func SetDefaultRenderer(c *latest.SkaffoldConfig) {
 	if len(c.Render.Generate.RawK8s) > 0 {
 		return
 	}
-	if len(c.Render.Generate.Kustomize) > 0 {
+	if c.Render.Generate.Kustomize != nil {
 		return
 	}
 	if c.Render.Generate.Helm != nil {
diff --git a/pkg/skaffold/schema/v2beta28/upgrade.go b/pkg/skaffold/schema/v2beta28/upgrade.go
index 6e46daa67..51a05c370 100644
--- a/pkg/skaffold/schema/v2beta28/upgrade.go
+++ b/pkg/skaffold/schema/v2beta28/upgrade.go
@@ -48,10 +48,15 @@ func upgradeOnePipeline(oldPipeline, newPipeline interface{}) error {
 		newPL.Deploy.KubectlDeploy.Manifests = nil
 	}
 
-	// TODO(marlongamez): port over buildArgs config and copy that
 	// Copy kustomize deploy config to render config
 	if oldPL.Deploy.KustomizeDeploy != nil {
-		newPL.Render.Kustomize = oldPL.Deploy.KustomizeDeploy.KustomizePaths
+		newPL.Render.Kustomize = &next.Kustomize{
+			Paths:     oldPL.Deploy.KustomizeDeploy.KustomizePaths,
+			BuildArgs: oldPL.Deploy.KustomizeDeploy.BuildArgs,
+		}
+		if len(newPL.Render.Kustomize.Paths) == 0 {
+			newPL.Render.Kustomize.Paths = append(newPL.Render.Kustomize.Paths, ".")
+		}
 		// nil out kustomize deployer as it shouldn't be a thing anymore
 		newPL.Deploy.KustomizeDeploy = nil
 


Test patch:
diff --git a/cmd/skaffold/app/cmd/run_test.go b/cmd/skaffold/app/cmd/run_test.go
index c4373f373..2b9d645f7 100644
--- a/cmd/skaffold/app/cmd/run_test.go
+++ b/cmd/skaffold/app/cmd/run_test.go
@@ -78,7 +78,7 @@ func (r *mockRunRunner) DeployAndLog(context.Context, io.Writer, []graph.Artifac
 	return nil
 }
 
-func (r *mockRunRunner) Render(context.Context, io.Writer, []graph.Artifact, bool, string) (manifest.ManifestList, error) {
+func (r *mockRunRunner) Render(context.Context, io.Writer, []graph.Artifact, bool) (manifest.ManifestList, error) {
 	r.renderRan = true
 	return manifest.ManifestList{}, nil
 }
diff --git a/integration/render_test.go b/integration/render_test.go
index 3c045ad96..3f27fb3ee 100644
--- a/integration/render_test.go
+++ b/integration/render_test.go
@@ -43,7 +43,6 @@ func TestKubectlRenderOutput(t *testing.T) {
 	test := struct {
 		description string
 		builds      []graph.Artifact
-		renderPath  string
 		input       string
 		expectedOut string
 	}{
@@ -54,7 +53,6 @@ func TestKubectlRenderOutput(t *testing.T) {
 				Tag:       "gcr.io/k8s-skaffold/skaffold:test",
 			},
 		},
-		renderPath: "./test-output",
 		input: `apiVersion: v1
 kind: Pod
 spec:
@@ -81,7 +79,7 @@ spec:
 		r, err := kubectl.New(mockCfg, rc, map[string]string{})
 		t.RequireNoError(err)
 		var b bytes.Buffer
-		l, err := r.Render(context.Background(), &b, test.builds, false, test.renderPath)
+		l, err := r.Render(context.Background(), &b, test.builds, false)
 
 		t.CheckNoError(err)
 
@@ -220,7 +218,7 @@ spec:
 			r, err := kubectl.New(mockCfg, rc, map[string]string{})
 			t.RequireNoError(err)
 			var b bytes.Buffer
-			l, err := r.Render(context.Background(), &b, test.builds, false, "")
+			l, err := r.Render(context.Background(), &b, test.builds, false)
 
 			t.CheckNoError(err)
 			t.CheckDeepEqual(test.expectedOut, l.String())
diff --git a/integration/testdata/debug/skaffold.yaml b/integration/testdata/debug/skaffold.yaml
index d24a4b8ca..ee7714633 100644
--- a/integration/testdata/debug/skaffold.yaml
+++ b/integration/testdata/debug/skaffold.yaml
@@ -29,8 +29,11 @@ manifests:
 profiles:
 - name: kustomize
   patches:
+  - op: remove
+    path: /manifests/rawYaml
   manifests:
     kustomize:
+      paths:
       - "."
 # use GCP Buildpacks to build the individual projects
 - name: buildpacks
@@ -62,6 +65,8 @@ profiles:
     #    builder: "gcr.io/buildpacks/builder:v1"
 - name: docker
   patches:
+  - op: remove
+    path: /manifests/rawYaml
   build:
     artifacts:
     - image: skaffold-debug-nodejs
diff --git a/integration/testdata/gcp-with-location/Dockerfile b/integration/testdata/gcb-with-location/Dockerfile
similarity index 100%
rename from integration/testdata/gcp-with-location/Dockerfile
rename to integration/testdata/gcb-with-location/Dockerfile
diff --git a/integration/testdata/gcp-with-location/go.mod b/integration/testdata/gcb-with-location/go.mod
similarity index 100%
rename from integration/testdata/gcp-with-location/go.mod
rename to integration/testdata/gcb-with-location/go.mod
diff --git a/integration/testdata/gcp-with-location/k8s-pod.yaml b/integration/testdata/gcb-with-location/k8s-pod.yaml
similarity index 62%
rename from integration/testdata/gcp-with-location/k8s-pod.yaml
rename to integration/testdata/gcb-with-location/k8s-pod.yaml
index 5e86139c9..e8e559450 100644
--- a/integration/testdata/gcp-with-location/k8s-pod.yaml
+++ b/integration/testdata/gcb-with-location/k8s-pod.yaml
@@ -5,4 +5,4 @@ metadata:
 spec:
   containers:
   - name: getting-started
-    image: skaffold-example-with-location
+    image: gcr.io/k8s-skaffold/skaffold-example-with-location
diff --git a/integration/testdata/gcp-with-location/main.go b/integration/testdata/gcb-with-location/main.go
similarity index 100%
rename from integration/testdata/gcp-with-location/main.go
rename to integration/testdata/gcb-with-location/main.go
diff --git a/integration/testdata/gcp-with-location/skaffold.yaml b/integration/testdata/gcb-with-location/skaffold.yaml
similarity index 54%
rename from integration/testdata/gcp-with-location/skaffold.yaml
rename to integration/testdata/gcb-with-location/skaffold.yaml
index 9cbb88d49..cfba17007 100644
--- a/integration/testdata/gcp-with-location/skaffold.yaml
+++ b/integration/testdata/gcb-with-location/skaffold.yaml
@@ -1,12 +1,11 @@
 apiVersion: skaffold/v3alpha1
 kind: Config
 build:
+  artifacts:
+    - image: gcr.io/k8s-skaffold/skaffold-example-with-location
   googleCloudBuild:
     projectId: k8s-skaffold
     region: asia-east1
-  artifacts:
-  - image: gcr.io/k8s-skaffold/skaffold-example-with-location
-deploy:
-  kubectl:
-    manifests:
-      - k8s-*
+manifests:
+  rawYaml:
+    - k8s-*
\ No newline at end of file
diff --git a/integration/testdata/gcp-with-location/README.md b/integration/testdata/gcp-with-location/README.md
deleted file mode 100644
index 2e4105950..000000000
--- a/integration/testdata/gcp-with-location/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-### Example: Getting started with a simple go app
-
-[![Open in Cloud Shell](https://gstatic.com/cloudssh/images/open-btn.svg)](https://ssh.cloud.google.com/cloudshell/editor?cloudshell_git_repo=https://github.com/GoogleContainerTools/skaffold&cloudshell_open_in_editor=README.md&cloudshell_workspace=examples/google-cloud-build)
-
-This is a simple example based on:
-
-* **building** a single Go file app and with a multistage `Dockerfile` using Google Cloud Build
-* **tagging** using the default tagPolicy (`gitCommit`)
-* **deploying** a single container pod using `kubectl`
diff --git a/pkg/skaffold/deploy/kubectl/kubectl_test.go b/pkg/skaffold/deploy/kubectl/kubectl_test.go
index 2df04c4e4..d624e67cc 100644
--- a/pkg/skaffold/deploy/kubectl/kubectl_test.go
+++ b/pkg/skaffold/deploy/kubectl/kubectl_test.go
@@ -28,7 +28,6 @@ import (
 	"time"
 
 	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/config"
-	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/constants"
 	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/label"
 	deployutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/deploy/util"
 	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/graph"
@@ -235,7 +234,7 @@ func TestKubectlV1RenderDeploy(t *testing.T) {
 				},
 				RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{
 					Namespace: skaffoldNamespaceOption}},
-			}, &label.DefaultLabeller{}, &test.kubectl, filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+			}, &label.DefaultLabeller{}, &test.kubectl)
 			t.RequireNoError(err)
 
 			rc := latest.RenderConfig{Generate: test.generate}
@@ -250,7 +249,7 @@ func TestKubectlV1RenderDeploy(t *testing.T) {
 			t.CheckNoError(err)
 			var b bytes.Buffer
 			m, errR := r.Render(context.Background(), &b, []graph.Artifact{{ImageName: "leeroy-web", Tag: "leeroy-web:v1"}},
-				true, "")
+				true)
 			t.CheckNoError(errR)
 			err = k.Deploy(context.Background(), ioutil.Discard, test.builds, m)
 
@@ -327,7 +326,7 @@ func TestKubectlCleanup(t *testing.T) {
 			k, err := NewDeployer(&kubectlConfig{
 				workingDir: ".",
 				RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}},
-			}, &label.DefaultLabeller{}, &test.kubectl, filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+			}, &label.DefaultLabeller{}, &test.kubectl)
 			t.RequireNoError(err)
 			rc := latest.RenderConfig{Generate: test.generate}
 			mockCfg := &kubectlConfig{
@@ -341,7 +340,7 @@ func TestKubectlCleanup(t *testing.T) {
 			t.CheckNoError(err)
 			var b bytes.Buffer
 			m, errR := r.Render(context.Background(), &b, []graph.Artifact{{ImageName: "leeroy-web", Tag: "leeroy-web:v1"}},
-				true, "")
+				true)
 			t.CheckNoError(errR)
 
 			err = k.Cleanup(context.Background(), ioutil.Discard, test.dryRun, m)
@@ -387,7 +386,7 @@ func TestKubectlDeployerRemoteCleanup(t *testing.T) {
 			k, err := NewDeployer(&kubectlConfig{
 				workingDir: ".",
 				RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}},
-			}, &label.DefaultLabeller{}, &test.kubectl, filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+			}, &label.DefaultLabeller{}, &test.kubectl)
 			t.RequireNoError(err)
 
 			err = k.Cleanup(context.Background(), ioutil.Discard, false, nil)
@@ -416,8 +415,7 @@ func TestKubectlRedeploy(t *testing.T) {
 				Enabled: true,
 				Delay:   0 * time.Millisecond,
 				Max:     10 * time.Second},
-		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-app.yaml"), tmpDir.Path("deployment-web.yaml")}},
-			filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-app.yaml"), tmpDir.Path("deployment-web.yaml")}})
 		t.RequireNoError(err)
 
 		// Deploy both manifests
@@ -485,8 +483,7 @@ func TestKubectlWaitForDeletions(t *testing.T) {
 				Delay:   0 * time.Millisecond,
 				Max:     10 * time.Second,
 			},
-		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-web.yaml")}},
-			filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-web.yaml")}})
 		t.RequireNoError(err)
 
 		var out bytes.Buffer
@@ -524,8 +521,7 @@ func TestKubectlWaitForDeletionsFails(t *testing.T) {
 				Delay:   10 * time.Second,
 				Max:     100 * time.Millisecond,
 			},
-		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-web.yaml")}},
-			filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+		}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: []string{tmpDir.Path("deployment-web.yaml")}})
 		t.RequireNoError(err)
 
 		m, err := manifest.Load(bytes.NewReader([]byte(DeploymentWebYAMLv1)))
@@ -588,8 +584,7 @@ func TestDependencies(t *testing.T) {
 				Touch("00/b.yaml", "00/a.yaml").
 				Chdir()
 
-			k, err := NewDeployer(&kubectlConfig{}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: test.manifests},
-				filepath.Join(tmpDir.Root(), constants.DefaultHydrationDir))
+			k, err := NewDeployer(&kubectlConfig{}, &label.DefaultLabeller{}, &latest.KubectlDeploy{Manifests: test.manifests})
 			t.RequireNoError(err)
 
 			dependencies, err := k.Dependencies()
@@ -638,14 +633,14 @@ func TestGCSManifests(t *testing.T) {
 			t.CheckNoError(err)
 			var b bytes.Buffer
 			m, errR := r.Render(context.Background(), &b, []graph.Artifact{{ImageName: "leeroy-web", Tag: "leeroy-web:v1"}},
-				true, "")
+				true)
 			t.CheckNoError(errR)
 
 			k, err := NewDeployer(&kubectlConfig{
 				workingDir: ".",
 				skipRender: test.skipRender,
 				RunContext: runcontext.RunContext{Opts: config.SkaffoldOptions{Namespace: TestNamespace}},
-			}, &label.DefaultLabeller{}, &latest.KubectlDeploy{}, filepath.Join("", constants.DefaultHydrationDir))
+			}, &label.DefaultLabeller{}, &latest.KubectlDeploy{})
 			t.RequireNoError(err)
 
 			err = k.Deploy(context.Background(), ioutil.Discard, nil, m)
@@ -682,7 +677,7 @@ func TestHasRunnableHooks(t *testing.T) {
 	}
 	for _, test := range tests {
 		testutil.Run(t, test.description, func(t *testutil.T) {
-			k, err := NewDeployer(&kubectlConfig{}, &label.DefaultLabeller{}, &test.cfg, "")
+			k, err := NewDeployer(&kubectlConfig{}, &label.DefaultLabeller{}, &test.cfg)
 			t.RequireNoError(err)
 			actual := k.HasRunnableHooks()
 			t.CheckDeepEqual(test.expected, actual)
diff --git a/pkg/skaffold/render/generate/generate_test.go b/pkg/skaffold/render/generate/generate_test.go
index 83227c147..bd89bc4cf 100644
--- a/pkg/skaffold/render/generate/generate_test.go
+++ b/pkg/skaffold/render/generate/generate_test.go
@@ -201,7 +201,9 @@ func TestManifestDeps(t *testing.T) {
 		{
 			description: "kustomize dir",
 			generateConfig: latest.Generate{
-				Kustomize: []string{"kustomize-sample"},
+				Kustomize: &latest.Kustomize{
+					Paths: []string{"kustomize-sample"},
+				},
 			},
 			expected: []string{"kustomize-sample/kustomization.yaml", "kustomize-sample/patch.yaml"},
 		},
@@ -215,9 +217,11 @@ func TestManifestDeps(t *testing.T) {
 		{
 			description: "multi manifest, mixed dir and file",
 			generateConfig: latest.Generate{
-				RawK8s:    []string{"rawYaml-sample"},
-				Kustomize: []string{"kustomize-sample"},
-				Kpt:       []string{"kpt-sample"},
+				RawK8s: []string{"rawYaml-sample"},
+				Kustomize: &latest.Kustomize{
+					Paths: []string{"kustomize-sample"},
+				},
+				Kpt: []string{"kpt-sample"},
 			},
 			expected: []string{
 				"kpt-sample/Kptfile",
diff --git a/pkg/skaffold/render/renderer/kpt/kpt_test.go b/pkg/skaffold/render/renderer/kpt/kpt_test.go
index 4a17bb354..829d1468c 100644
--- a/pkg/skaffold/render/renderer/kpt/kpt_test.go
+++ b/pkg/skaffold/render/renderer/kpt/kpt_test.go
@@ -177,10 +177,12 @@ pipeline:
 			t.CheckNoError(err)
 			t.Override(&util.DefaultExecCommand,
 				testutil.CmdRun(fmt.Sprintf("kpt fn render %v",
-					filepath.Join(tmpDirObj.Root(), ".kpt-pipeline"))))
+					filepath.Join(tmpDirObj.Root(), ".kpt-pipeline"))).
+					AndRunOut(fmt.Sprintf("kpt fn source %v -o unwrap",
+						filepath.Join(tmpDirObj.Root(), ".kpt-pipeline")), ""))
 			var b bytes.Buffer
 			_, err = r.Render(context.Background(), &b, []graph.Artifact{{ImageName: "leeroy-web", Tag: "leeroy-web:v1"}},
-				true, "")
+				true)
 			t.CheckNoError(err)
 			t.CheckFileExistAndContent(filepath.Join(tmpDirObj.Root(), constants.DefaultHydrationDir, DryFileName), []byte(labeledPodYaml))
 			t.CheckFileExistAndContent(filepath.Join(tmpDirObj.Root(), constants.DefaultHydrationDir, kptfile.KptFileName), []byte(test.updatedKptfile))
@@ -246,10 +248,12 @@ inventory:
 			t.CheckNoError(err)
 			t.Override(&util.DefaultExecCommand,
 				testutil.CmdRun(fmt.Sprintf("kpt fn render %v",
-					filepath.Join(tmpDirObj.Root(), ".kpt-pipeline"))))
+					filepath.Join(tmpDirObj.Root(), ".kpt-pipeline"))).
+					AndRunOut(fmt.Sprintf("kpt fn source %v -o unwrap",
+						filepath.Join(tmpDirObj.Root(), ".kpt-pipeline")), ""))
 			var b bytes.Buffer
 			_, err = r.Render(context.Background(), &b, []graph.Artifact{},
-				true, "")
+				true)
 			t.CheckNoError(err)
 			t.CheckFileExistAndContent(filepath.Join(tmpDirObj.Root(), constants.DefaultHydrationDir, kptfile.KptFileName),
 				[]byte(test.updatedKptfile))
diff --git a/pkg/skaffold/render/renderer/kubectl/kubectl_test.go b/pkg/skaffold/render/renderer/kubectl/kubectl_test.go
index 35b850a94..1ac697ac8 100644
--- a/pkg/skaffold/render/renderer/kubectl/kubectl_test.go
+++ b/pkg/skaffold/render/renderer/kubectl/kubectl_test.go
@@ -91,7 +91,7 @@ func TestRender(t *testing.T) {
 			t.CheckNoError(err)
 			var b bytes.Buffer
 			manifestList, errR := r.Render(context.Background(), &b, []graph.Artifact{{ImageName: "leeroy-web", Tag: "leeroy-web:v1"}},
-				true, "")
+				true)
 			t.CheckNoError(errR)
 			t.CheckDeepEqual(test.expected, manifestList.String())
 		})
diff --git a/pkg/skaffold/render/renderer/render_mux_test.go b/pkg/skaffold/render/renderer/render_mux_test.go
index 32bde4088..c18af1670 100644
--- a/pkg/skaffold/render/renderer/render_mux_test.go
+++ b/pkg/skaffold/render/renderer/render_mux_test.go
@@ -74,7 +74,7 @@ func TestRenderMux_Render(t *testing.T) {
 				}}})
 			mux := NewRenderMux(tc.renderers)
 			buf := &bytes.Buffer{}
-			actual, err := mux.Render(context.Background(), buf, nil, true, "")
+			actual, err := mux.Render(context.Background(), buf, nil, true)
 			t.CheckErrorAndDeepEqual(tc.shouldErr, err, tc.expected, actual.String())
 			actualDeps, errD := mux.ManifestDeps()
 			t.CheckNoError(errD)
@@ -93,7 +93,7 @@ func (m mock) ManifestDeps() ([]string, error) {
 	return m.deps, nil
 }
 
-func (m mock) Render(context.Context, io.Writer, []graph.Artifact, bool, string) (manifest.ManifestList, error) {
+func (m mock) Render(context.Context, io.Writer, []graph.Artifact, bool) (manifest.ManifestList, error) {
 	if m.shouldErr {
 		return nil, fmt.Errorf("render error")
 	}
diff --git a/pkg/skaffold/runner/deployer_test.go b/pkg/skaffold/runner/deployer_test.go
index f5ba47de6..ce5158354 100644
--- a/pkg/skaffold/runner/deployer_test.go
+++ b/pkg/skaffold/runner/deployer_test.go
@@ -95,7 +95,7 @@ func TestGetDeployer(tOuter *testing.T) {
 						Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 					}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 						Flags: latest.KubectlFlags{},
-					}, "")).(deploy.Deployer),
+					})).(deploy.Deployer),
 				}, false),
 			},
 			{
@@ -135,7 +135,7 @@ func TestGetDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(deploy.Deployer),
+				})).(deploy.Deployer),
 			},
 			{
 				description: "apply forces creation of kubectl deployer with helm config",
@@ -152,7 +152,7 @@ func TestGetDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(deploy.Deployer),
+				})).(deploy.Deployer),
 			},
 			{
 				description: "multiple deployers",
@@ -229,7 +229,7 @@ func TestGetDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(deploy.Deployer),
+				})).(deploy.Deployer),
 			},
 			{
 				description: "apply works with Cloud Run",
@@ -324,7 +324,7 @@ func TestGetDefaultDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(*kubectl.Deployer),
+				})).(*kubectl.Deployer),
 			},
 			{
 				name: "one config with kubectl deploy, with flags",
@@ -343,7 +343,7 @@ func TestGetDefaultDeployer(tOuter *testing.T) {
 						Apply:  []string{"--foo"},
 						Global: []string{"--bar"},
 					},
-				}, "")).(*kubectl.Deployer),
+				})).(*kubectl.Deployer),
 			},
 			{
 				name: "two kubectl configs with mismatched flags should fail",
@@ -374,7 +374,7 @@ func TestGetDefaultDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(*kubectl.Deployer),
+				})).(*kubectl.Deployer),
 			},
 			{
 				name: "one config with kustomize deploy",
@@ -385,7 +385,7 @@ func TestGetDefaultDeployer(tOuter *testing.T) {
 					Pipelines: runcontext.NewPipelines([]latest.Pipeline{{}}),
 				}, &label.DefaultLabeller{}, &latest.KubectlDeploy{
 					Flags: latest.KubectlFlags{},
-				}, "")).(*kubectl.Deployer),
+				})).(*kubectl.Deployer),
 			},
 		}
 
@@ -401,7 +401,7 @@ func TestGetDefaultDeployer(tOuter *testing.T) {
 				}
 				deployer, err := getDefaultDeployer(&runcontext.RunContext{
 					Pipelines: runcontext.NewPipelines(pipelines),
-				}, &label.DefaultLabeller{}, "")
+				}, &label.DefaultLabeller{})
 
 				t.CheckErrorAndFailNow(test.shouldErr, err)
 
diff --git a/pkg/skaffold/runner/timings_test.go b/pkg/skaffold/runner/timings_test.go
index 0f41fd02f..c7f1e8bcc 100644
--- a/pkg/skaffold/runner/timings_test.go
+++ b/pkg/skaffold/runner/timings_test.go
@@ -74,7 +74,7 @@ type mockRenderer struct {
 	err bool
 }
 
-func (m *mockRenderer) Render(context.Context, io.Writer, []graph.Artifact, bool, string) (manifest.ManifestList, error) {
+func (m *mockRenderer) Render(context.Context, io.Writer, []graph.Artifact, bool) (manifest.ManifestList, error) {
 	if m.err {
 		return nil, errors.New("Unable to render")
 	}
@@ -246,7 +246,7 @@ func TestTimingsRender(t *testing.T) {
 			_, _, render, _ := WithTimings(nil, nil, r, nil, false)
 
 			var out bytes.Buffer
-			_, err := render.Render(context.Background(), &out, nil, false, "")
+			_, err := render.Render(context.Background(), &out, nil, false)
 
 			t.CheckError(test.shouldErr, err)
 			t.CheckMatches(test.shouldOutput, out.String())
diff --git a/pkg/skaffold/runner/v2/runner_test.go b/pkg/skaffold/runner/v2/runner_test.go
index 6c990172e..ae8133395 100644
--- a/pkg/skaffold/runner/v2/runner_test.go
+++ b/pkg/skaffold/runner/v2/runner_test.go
@@ -215,7 +215,7 @@ func (t *TestBench) Deploy(_ context.Context, _ io.Writer, artifacts []graph.Art
 	return nil
 }
 
-func (t *TestBench) Render(_ context.Context, _ io.Writer, artifacts []graph.Artifact, _ bool, _ string) (manifest.ManifestList, error) {
+func (t *TestBench) Render(_ context.Context, _ io.Writer, artifacts []graph.Artifact, _ bool) (manifest.ManifestList, error) {
 	if len(t.renderErrors) > 0 {
 		err := t.renderErrors[0]
 		t.renderErrors = t.renderErrors[1:]
diff --git a/pkg/skaffold/schema/defaults/defaults_test.go b/pkg/skaffold/schema/defaults/defaults_test.go
index 9b8cadf62..607a8ae01 100644
--- a/pkg/skaffold/schema/defaults/defaults_test.go
+++ b/pkg/skaffold/schema/defaults/defaults_test.go
@@ -450,12 +450,12 @@ func TestSetDefaultRenderer(t *testing.T) {
 			description: "kustomize manifests",
 			input: latest.RenderConfig{
 				Generate: latest.Generate{
-					Kustomize: []string{"/kmanifests"},
+					Kustomize: &latest.Kustomize{Paths: []string{"/kmanifests"}},
 				},
 			},
 			expected: latest.RenderConfig{
 				Generate: latest.Generate{
-					Kustomize: []string{"/kmanifests"},
+					Kustomize: &latest.Kustomize{Paths: []string{"/kmanifests"}},
 				},
 			},
 		},
@@ -490,14 +490,14 @@ func TestSetDefaultRenderer(t *testing.T) {
 			input: latest.RenderConfig{
 				Generate: latest.Generate{
 					Kpt:       []string{"/kmanifests1"},
-					Kustomize: []string{"/kmanifests2"},
+					Kustomize: &latest.Kustomize{Paths: []string{"/kmanifests2"}},
 					Helm:      &latest.Helm{Releases: []latest.HelmRelease{{Name: "test"}}},
 				},
 			},
 			expected: latest.RenderConfig{
 				Generate: latest.Generate{
 					Kpt:       []string{"/kmanifests1"},
-					Kustomize: []string{"/kmanifests2"},
+					Kustomize: &latest.Kustomize{Paths: []string{"/kmanifests2"}},
 					Helm:      &latest.Helm{Releases: []latest.HelmRelease{{Name: "test"}}},
 				},
 			},
diff --git a/pkg/skaffold/schema/latest/config.go b/pkg/skaffold/schema/latest/config.go
index 9db15e8c1..e739e5e0f 100644
--- a/pkg/skaffold/schema/latest/config.go
+++ b/pkg/skaffold/schema/latest/config.go
@@ -569,8 +569,9 @@ type Generate struct {
 	// RawK8s TODO: add description.
 	RawK8s []string `yaml:"rawYaml,omitempty" skaffold:"filepath"`
 
-	// Kustomize TODO: add description.
-	Kustomize []string `yaml:"kustomize,omitempty" skaffold:"filepath"`
+	// Kustomize defines the paths to be modified with kustomize, along with extra
+	// flags to be passed to kustomize
+	Kustomize *Kustomize `yaml:"kustomize,omitempty"`
 
 	// Helm TODO: add description.
 	Helm *Helm `yaml:"helm,omitempty"`
@@ -579,6 +580,17 @@ type Generate struct {
 	Kpt []string `yaml:"kpt,omitempty" skaffold:"filepath"`
 }
 
+// Kustomize defines the paths to be modified with kustomize, along with
+// extra flags to be passed to kustomize
+type Kustomize struct {
+	// Paths is the path to Kustomization files.
+	// Defaults to `["."]`.
+	Paths []string `yaml:"paths,omitempty" skaffold:"filepath"`
+
+	// BuildArgs are additional args passed to `kustomize build`.
+	BuildArgs []string `yaml:"buildArgs,omitempty"`
+}
+
 // Helm defines the manifests from helm releases.
 type Helm struct {
 	// Flags are additional option flags that are passed on the command
diff --git a/pkg/skaffold/schema/v2beta28/upgrade_test.go b/pkg/skaffold/schema/v2beta28/upgrade_test.go
index 7cb8f0757..2e0eb3283 100644
--- a/pkg/skaffold/schema/v2beta28/upgrade_test.go
+++ b/pkg/skaffold/schema/v2beta28/upgrade_test.go
@@ -149,6 +149,7 @@ manifests:
   rawYaml:
     - k8s-*
   kustomize:
+    paths:
     - kustomization-main
   helm:
     releases:
@@ -181,7 +182,8 @@ profiles:
       rawYaml:
       - k8s-*
       kustomize:
-      - kustomization-test
+        paths:
+        - kustomization-test
     deploy:
       kubectl: {}
   - name: test local
@@ -195,6 +197,9 @@ profiles:
     manifests:
       rawYaml:
       - k8s-*
+      kustomize:
+        paths:
+        - "."
     deploy:
       kubectl: {}
 `