Skip to content

kubectl parses environment files differently than POSIX shell environments #1753

Open
@pveierland

Description

@pveierland

What happened:

❯ cat test.env
TEST_STRING_1=hello
TEST_STRING_2="hello world"
TEST_STRING_3='hello world'

❯ kubectl create configmap test --from-env-file test.env
configmap/test created

❯ k get cm test -o yaml
apiVersion: v1
data:
  TEST_STRING_1: hello
  TEST_STRING_2: '"hello world"'
  TEST_STRING_3: '''hello world'''
kind: ConfigMap
metadata:
  creationTimestamp: "2025-06-20T05:47:06Z"
  name: test
  namespace: default
  resourceVersion: "210905"
  uid: 254eced4-4dd9-4abc-8567-90b647f4186b

❯ source test.env
❯ echo $TEST_STRING_1
hello
❯ echo $TEST_STRING_2
hello world
❯ echo $TEST_STRING_3
hello world

❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_1}'
hello
❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_2}'
"hello world"
❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_3}'
'hello world'

What you expected to happen:

The expected behavior for environment files is that they would allow quotation handling in the same manner as POSIX shell environments, i.e. such that the resulting values in the evaluated config map would instead be:

❯ k get cm test -o yaml
apiVersion: v1
data:
  TEST_STRING_1: hello
  TEST_STRING_2: hello world
  TEST_STRING_3: hello world
kind: ConfigMap
metadata:
  creationTimestamp: "2025-06-20T05:47:06Z"
  name: test
  namespace: default
  resourceVersion: "210905"
  uid: 254eced4-4dd9-4abc-8567-90b647f4186b

❯ source test.env
❯ echo $TEST_STRING_1
hello
❯ echo $TEST_STRING_2
hello world
❯ echo $TEST_STRING_3
hello world

❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_1}'
hello
❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_2}'
hello world
❯ kubectl get cm test -o jsonpath='{.data.TEST_STRING_3}'
hello world

The current behavior means that quotations required within a POSIX shell environment are interpreted literally by the kubectl tool, which means that it is not possible to use the same environment files within both the context of a POSIX shell environment and with the kubectl tool. This both breaks the expected feature set of environment files for the user, and will require separate files or special handling by the user, instead of being able to re-use existing files.

How to reproduce it (as minimally and precisely as possible):

See above.

Anything else we need to know?:

There is a related issue for the kustomize tool, ideally both tools should be fixed in the same manner to ensure consistent behavior using a more complete environment file parser.

kubernetes-sigs/kustomize#4525

Note that a parser such as https://github.com/joho/godotenv will correctly parse quoted strings, see:

Environment:

  • Kubernetes client and server versions (use kubectl version):
❯ kubectl version
Client Version: v1.33.0
Kustomize Version: v5.6.0
Server Version: v1.31.0
  • Cloud provider or hardware configuration: local
  • OS (e.g: cat /etc/os-release):
❯ cat /etc/os-release
ANSI_COLOR="0;38;2;126;186;228"
BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
BUILD_ID="25.05.20250522.55d1f92"
CPE_NAME="cpe:/o:nixos:nixos:25.05"
DEFAULT_HOSTNAME=nixos
DOCUMENTATION_URL="https://nixos.org/learn.html"
HOME_URL="https://nixos.org/"
ID=nixos
ID_LIKE=""
IMAGE_ID=""
IMAGE_VERSION=""
LOGO="nix-snowflake"
NAME=NixOS
PRETTY_NAME="NixOS 25.05 (Warbler)"
SUPPORT_END="2025-12-31"
SUPPORT_URL="https://nixos.org/community.html"
VARIANT=""
VARIANT_ID=""
VENDOR_NAME=NixOS
VENDOR_URL="https://nixos.org/"
VERSION="25.05 (Warbler)"
VERSION_CODENAME=warbler
VERSION_ID="25.05"

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.needs-triageIndicates an issue or PR lacks a `triage/foo` label and requires one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions