Skip to content

kpt pkg get: revisit "container directory" behaviour for explicit destinations #4702

Description

@aravindtga

Background

When kpt pkg get REPO dest is called and dest already exists as a directory, getDest() in pkg/lib/util/parse/parse.go silently appends the package name as a subdirectory (e.g.dest/nginx). This was an intentional design from v0.1.0 mimicking cp semantics, but it creates confusing behaviour:

  • If dest doesn't exist: package is written directly to dest
  • If dest exists: package is written to dest/<pkg-name>

Same command, same explicit argument, different interpretation depending on filesystem state at invocation time.

Steps

# Setup
mkdir -p /tmp/kpt-container-test && cd /tmp/kpt-container-test
git init

# Case 1: destination does NOT exist
# Package is written directly to "my-package"
kpt pkg get https://github.com/kptdev/kpt.git/package-examples/nginx@main my-package
ls my-package/
# Output: Kptfile  deployment.yaml  svc.yaml

# Cleanup
rm -rf my-package

# Case 2: destination DOES exist (empty directory)
# Package is NOT written to "my-package" — instead it goes to "my-package/nginx"
mkdir my-package
kpt pkg get https://github.com/kptdev/kpt.git/package-examples/nginx@main my-package
ls my-package/
# Output: nginx/
ls my-package/nginx/
# Output: Kptfile  deployment.yaml  svc.yaml

The user typed the same destination (my-package) in both cases, but got different results based on whether the directory existed beforehand.

Problems

  1. User intent is ambiguous. When a user explicitly types dest, they most likely mean "put the package here", not "use this as a parent directory". The meaning shouldn't change based on whether they ran mkdir first.
  2. Undocumented. The original v0.1.0 docs explained the three cases clearly, but the current documentation at reference/cli/pkg/get/_index.md only says "The local directory to write the package to" - the container behaviour is not mentioned.
  3. Source of bugs. Issue kpt pkg get duplicates a package as a subdirectory when attempting to override the local directory name #2656 was caused by this inconsistency, a first fetch with a non-existing path takes the "direct" route, then a repeat fetch finds the directory exists and switches to container logic, silently creating a nested duplicate.

Proposal

Consider deprecating the container pattern for explicit destinations:

  • If the user provides a destination and it already exists (non-empty), error unconditionally
  • If the user provides a destination and it doesn't exist, create it and fetch into it (current behaviour)
  • If no destination is provided, default to ./ in the current directory (current behaviour)

This would align pkg get with the rest of kpt and with git clone semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions