Skip to content

Failed to create three way merge patch when container environment variable specified multiple times #86163

Closed
@distorhead

Description

@distorhead

What happened:

Kubectl apply has failed with error The order in patch list ... doesn't match $setElementOrder list when container environment variable has been specified multiple times.

How to reproduce:

  1. Create deployment with two environment variables TESTVAR="1":
$ cat mydeploy.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeploy
  labels:
    component: mydeploy
spec:
  replicas: 1
  selector:
    matchLabels:
      component: mydeploy
  template:
    metadata:
      labels:
        component: mydeploy
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: main
        image: ubuntu:18.04
        command: [ "/bin/bash", "-c", "while true; do date; sleep 1; done" ]
        env:
        - name: TESTVAR
          value: "1"
        - name: TESTVAR2
          value: "one"
        - name: TESTVAR
          value: "1"
$ kubectl apply -f mydeploy.yaml 
deployment.apps/mydeploy created
  1. Check that kubernetes has been created deployment with double variable definition:
$ kubectl get deploy mydeploy -oyaml
...
    spec:
      containers:
      - command:
        - /bin/bash
        - -c
        - while true; do date; sleep 1; done
        env:
        - name: TESTVAR
          value: "1"
        - name: TESTVAR2
          value: one
        - name: TESTVAR
          value: "1"
...
  1. Change mydeploy manifest so that TESTVAR="2" and TESTVAR2="two":
$ cat mydeploy.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydeploy
  labels:
    component: mydeploy
spec:
  replicas: 1
  selector:
    matchLabels:
      component: mydeploy
  template:
    metadata:
      labels:
        component: mydeploy
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: main
        image: ubuntu:18.04
        command: [ "/bin/bash", "-c", "while true; do date; sleep 1; done" ]
        env:
        - name: TESTVAR
          value: "2"
        - name: TESTVAR2
          value: "two"
        - name: TESTVAR
          value: "2"
  1. Applying new manifest gives an error from the patch creation procedure:
$ kubectl apply -f mydeploy.yaml 
Error from server: error when applying patch:
{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"component\":\"mydeploy\"},\"name\":\"mydeploy\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"component\":\"mydeploy\"}},\"template\":{\"metadata\":{\"labels\":{\"component\":\"mydeploy\"}},\"spec\":{\"containers\":[{\"command\":[\"/bin/bash\",\"-c\",\"while true; do date; sleep 1; done\"],\"env\":[{\"name\":\"TESTVAR\",\"value\":\"2\"},{\"name\":\"TESTVAR2\",\"value\":\"two\"},{\"name\":\"TESTVAR\",\"value\":\"2\"}],\"image\":\"ubuntu:18.04\",\"name\":\"main\"}],\"terminationGracePeriodSeconds\":10}}}}\n"}},"spec":{"template":{"spec":{"$setElementOrder/containers":[{"name":"main"}],"containers":[{"$setElementOrder/env":[{"name":"TESTVAR"},{"name":"TESTVAR2"},{"name":"TESTVAR"}],"env":[{"name":"TESTVAR","value":"2"},{"name":"TESTVAR","value":"2"},{"name":"TESTVAR2","value":"two"}],"name":"main"}]}}}}
to:
Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment"
Name: "mydeploy", Namespace: "default"
Object: &{map["kind":"Deployment" "apiVersion":"apps/v1" "metadata":map["resourceVersion":"310445" "generation":'\x01' "creationTimestamp":"2019-12-11T14:37:11Z" "annotations":map["deployment.kubernetes.io/revision":"1" "kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"labels\":{\"component\":\"mydeploy\"},\"name\":\"mydeploy\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"component\":\"mydeploy\"}},\"template\":{\"metadata\":{\"labels\":{\"component\":\"mydeploy\"}},\"spec\":{\"containers\":[{\"command\":[\"/bin/bash\",\"-c\",\"while true; do date; sleep 1; done\"],\"env\":[{\"name\":\"TESTVAR\",\"value\":\"1\"},{\"name\":\"TESTVAR2\",\"value\":\"one\"},{\"name\":\"TESTVAR\",\"value\":\"1\"}],\"image\":\"ubuntu:18.04\",\"name\":\"main\"}],\"terminationGracePeriodSeconds\":10}}}}\n"] "name":"mydeploy" "namespace":"default" "uid":"0c95c99f-4653-4b3d-b46c-650f52a34550" "selfLink":"/apis/apps/v1/namespaces/default/deployments/mydeploy" "labels":map["component":"mydeploy"]] "spec":map["replicas":'\x01' "selector":map["matchLabels":map["component":"mydeploy"]] "template":map["metadata":map["creationTimestamp":<nil> "labels":map["component":"mydeploy"]] "spec":map["containers":[map["command":["/bin/bash" "-c" "while true; do date; sleep 1; done"] "env":[map["name":"TESTVAR" "value":"1"] map["name":"TESTVAR2" "value":"one"] map["name":"TESTVAR" "value":"1"]] "resources":map[] "terminationMessagePath":"/dev/termination-log" "terminationMessagePolicy":"File" "imagePullPolicy":"IfNotPresent" "name":"main" "image":"ubuntu:18.04"]] "restartPolicy":"Always" "terminationGracePeriodSeconds":'\n' "dnsPolicy":"ClusterFirst" "securityContext":map[] "schedulerName":"default-scheduler"]] "strategy":map["type":"RollingUpdate" "rollingUpdate":map["maxUnavailable":"25%" "maxSurge":"25%"]] "revisionHistoryLimit":'\n' "progressDeadlineSeconds":'\u0258'] "status":map["observedGeneration":'\x01' "replicas":'\x01' "updatedReplicas":'\x01' "readyReplicas":'\x01' "availableReplicas":'\x01' "conditions":[map["lastUpdateTime":"2019-12-11T14:37:13Z" "lastTransitionTime":"2019-12-11T14:37:13Z" "reason":"MinimumReplicasAvailable" "message":"Deployment has minimum availability." "type":"Available" "status":"True"] map["message":"ReplicaSet \"mydeploy-ddf954467\" has successfully progressed." "type":"Progressing" "status":"True" "lastUpdateTime":"2019-12-11T14:37:13Z" "lastTransitionTime":"2019-12-11T14:37:11Z" "reason":"NewReplicaSetAvailable"]]]]}
for: "mydeploy.yaml": The order in patch list:
[map[name:TESTVAR value:2] map[name:TESTVAR value:2] map[name:TESTVAR2 value:two]]
 doesn't match $setElementOrder list:
[map[name:TESTVAR] map[name:TESTVAR2] map[name:TESTVAR]]

What you expected to happen:

Apiserver I suppose should not create Deployment object in the cluster with the double environment variable definition.

Environment:

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"13", GitVersion:"v1.13.3", GitCommit:"721bfa751924da8d1680787490c54b9179b1fed0", GitTreeState:"clean", BuildDate:"2019-02-01T20:08:12Z", GoVersion:"go1.11.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"16", GitVersion:"v1.16.0", GitCommit:"2bd9643cee5b3b3a5ecbd3af49d09018f0773c77", GitTreeState:"clean", BuildDate:"2019-09-18T14:27:17Z", GoVersion:"go1.12.9", Compiler:"gc", Platform:"linux/amd64"}

Also reproduces using following version:

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:32:14Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"linux/amd64"}
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic
$ uname -a
Linux werf 5.0.0-36-generic #39~18.04.1-Ubuntu SMP Tue Nov 12 11:09:50 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugCategorizes issue or PR as related to a bug.lifecycle/rottenDenotes an issue or PR that has aged beyond stale and will be auto-closed.needs-sigIndicates an issue or PR lacks a `sig/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