Change:
/kind bug What happened: Applied ingress with annotations and the annotations are ignored. What you expected to happen: The annotations to be applied and visible when describing the ingress. How to reproduce it (as minimally and precisely as possible): Apply this; Describe the ingress; $ kubectl describe ingress ydos-ingress -n ydos Name: ydos-ingress Namespace: ydos Address: 130.61.9.241 Default backend: default-http-backend:80 (&lt;none) TLS: wildcard-yellowdog-tech-secret terminates Rules: Host Path Backends ---- ---- -------- /ydos ydos-svc:80 (&lt;none) Annotations: Events: &lt;none Anything else we need to know?: This is being deployed into a kubernetes ingress-nginx environment. The nginx controller is being updated but no annotations are being applied by kubernetes so affinity is not being configured in the nginx pod. Environment: Kubernetes version (use ): Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1+2.1.5.el7", GitCommit:"", GitTreeState:"archive", BuildDate:"2018-03-23T02:54:15Z", GoVersion:"go1.9.2", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.1-2+", GitCommit:"", GitTreeState:"clean", BuildDate:"2018-07-24T14:24:53Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"} Cloud provider or hardware configuration: NAME STATUS ROLES AGE VERSION EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME Ready node 8d v1.11.1 130.61.33.85 Oracle Linux Server 7.5 4.1.12-124.18.5.el7uek.x8664 docker://18.3.1 Ready node 8d v1.11.1 130.61.74.1 Oracle Linux Server 7.5 4.1.12-124.18.5.el7uek.x8664 docker://18.3.1 Ready node 8d v1.11.1 130.61.95.73 Oracle Linux Server 7.5 4.1.12-124.18.5.el7uek.x86_64 docker://18.3.1 OS (e.g. from /etc/os-release): Kernel (e.g. ): Install tools: Others:
/sig cli
I'm not able to reproduce this. Creating the ingress object and then describing it shows the annotations successfully. Can you capture the network request/response of the initial creation by adding (and removing any credential headers before posting the results)?
As requested, I deleted the existing ingress then applied, there's a describe at the end an no annotations. :-(
Also, this is the from /docs/example/affinity/cookie and it also doe snot apply the annotations... <
the posted object: and the created object returned from the server: both show the annotations it appears something else is modifying the object after the fact and dropping the annotations
The following get output would appear to partially agree. But why would the describe not show the annotations and the kubernetes ingress-nginx does not appear to be reading the annotations? As an aside why can't I seem to format my code properly with ` or &lt;, I always get random bullets.!? ;-) [opc cookie]$ kubectl get ingress ydos-ingress -n ydos -o yaml apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: cookie "false" ydos/wildcard-yellowdog-tech-secret "on" "1" 1M / sha1 YDOS-SESSION-EX creationTimestamp: 2018-08-29T08:08:35Z generation: 1 name: ydos-ingress namespace: ydos resourceVersion: "" selfLink: /apis/extensions/v1beta1/namespaces/ydos/ingresses/ydos-ingress uid: -ab62-11e8-86a3- spec: rules: host: http: paths: backend: serviceName: ydos-svc servicePort: 80 path: /ydos tls: hosts: secretName: wildcard-yellowdog-tech-secret status: loadBalancer: ingress: ip: 130.61.9.241 `
use "" to delimit your code looks like older versions of only showed some annotations. fixed in to be clear, that only affects display by kubectl, not use of those annotations by any other components /close
For anyone ending up here via google for this very issue of annotations not going through, my error was ultimately that I had ... This was a value of 10 as a yaml integer, where as annotation values can only be strings, so modifying this line to , all annotations went through OK. Would've been nice to get some errors about this =)
fyi, fix in progress in for this
You saved me a lot of time
Another note for the future: our problem was not quoting , it should, apparently, be or it will drop all annotations. That cost me about a day ...

Discussion:
"helper.go", "interfaces.go", "mapper.go", <ins> "metadata_decoder.go", </ins> "result.go", "scheme.go", "selector.go",

"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", <ins> "//staging/src/k8s.io/apimachinery/pkg/runtime/serializer/json:go_default_library", </ins> "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",

localFn:      b.isLocal, restMapperFn: b.restMapperFn, clientFn:     b.getClient, <del> decoder:      unstructured.UnstructuredJSONScheme, </del> <ins> decoder:      &metadataValidatingDecoder{unstructured.UnstructuredJSONScheme}, </ins> } return b

} } ` <ins> var aPodBadAnnotations string = ` { "kind": "Pod", "apiVersion": "` + corev1GV.String() + `", "metadata": { "name": "busybox{id}", "labels": { "name": "busybox{id}" }, "annotations": { "name": 0 } }, "spec": { "containers": [ { "name": "busybox", "image": "busybox", "command": [ "sleep", "3600" ], "imagePullPolicy": "IfNotPresent" } ], "restartPolicy": "Always" } } ` </ins> var aRC string = ` {

WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...) } <ins> func newUnstructuredDefaultBuilder() *Builder { return newUnstructuredDefaultBuilderWith(fakeClient()) } func newUnstructuredDefaultBuilderWith(fakeClientFn FakeClientFunc) *Builder { return NewFakeBuilder( fakeClientFn, func() (meta.RESTMapper, error) { return testrestmapper.TestOnlyStaticRESTMapper(scheme.Scheme), nil }, func() (restmapper.CategoryExpander, error) { return FakeCategoryExpander, nil }). Unstructured() } </ins> type errorRestMapper struct { meta.RESTMapper err error

}) } } <ins> func TestUnstructured(t *testing.T) { // create test dirs tmpDir, err := utiltesting.MkTmpdir("unstructured_test") if err != nil { t.Fatalf("error creating temp dir: %v", err) } defer os.RemoveAll(tmpDir) // create test files writeTestFile(t, fmt.Sprintf("%s/pod.json", tmpDir), aPod) writeTestFile(t, fmt.Sprintf("%s/badpod.json", tmpDir), aPodBadAnnotations) tests := []struct { name          string file          string expectedError string }{ { name:          "pod", file:          "pod.json", expectedError: "", }, { name:          "badpod", file:          "badpod.json", expectedError: "v1.ObjectMeta.Annotations", }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result := newUnstructuredDefaultBuilder(). ContinueOnError(). FilenameParam(false, &FilenameOptions{Recursive: false, Filenames: []string{fmt.Sprintf("%s/%s", tmpDir, tc.file)}}). Flatten(). Do() err := result.Err() if err == nil { _, err = result.Infos() } if len(tc.expectedError) == 0 { if err != nil { t.Errorf("unexpected error: %v", err) } } else { if err == nil { t.Errorf("expected error, got none") } else if !strings.Contains(err.Error(), tc.expectedError) { t.Errorf("expected error with '%s', got: %v", tc.expectedError, err) } } }) } } </ins>

<ins> /* Copyright 2019 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package resource import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer/json" ) // hold a single instance of the case-sensitive decoder var caseSensitiveJsonIterator = json.CaseSensitiveJsonIterator() // metadataValidatingDecoder wraps a decoder and additionally ensures metadata schema fields decode before returning an unstructured object type metadataValidatingDecoder struct { decoder runtime.Decoder } func (m *metadataValidatingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) { obj, gvk, err := m.decoder.Decode(data, defaults, into) // if we already errored, return if err != nil { return obj, gvk, err } // if we're not unstructured, return if _, isUnstructured := obj.(runtime.Unstructured); !isUnstructured { return obj, gvk, err } // make sure the data can decode into ObjectMeta before we return, // so we don't silently truncate schema errors in metadata later with accesser get/set calls v := &metadataOnlyObject{} if typedErr := caseSensitiveJsonIterator.Unmarshal(data, v); typedErr != nil { return obj, gvk, typedErr } return obj, gvk, err } type metadataOnlyObject struct { metav1.TypeMeta   `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` } </ins>