123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889 |
- /*
- Copyright 2018 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 apiserver
- import (
- "encoding/json"
- "net/http"
- "net/http/httptest"
- "reflect"
- "testing"
- "time"
- "k8s.io/apimachinery/pkg/api/errors"
- "k8s.io/apimachinery/pkg/api/meta"
- metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/apimachinery/pkg/runtime/schema"
- "k8s.io/apimachinery/pkg/types"
- genericfeatures "k8s.io/apiserver/pkg/features"
- utilfeature "k8s.io/apiserver/pkg/util/feature"
- clientset "k8s.io/client-go/kubernetes"
- restclient "k8s.io/client-go/rest"
- featuregatetesting "k8s.io/component-base/featuregate/testing"
- "k8s.io/kubernetes/pkg/master"
- "k8s.io/kubernetes/test/integration/framework"
- )
- func setup(t *testing.T, groupVersions ...schema.GroupVersion) (*httptest.Server, clientset.Interface, framework.CloseFunc) {
- masterConfig := framework.NewIntegrationTestMasterConfig()
- if len(groupVersions) > 0 {
- resourceConfig := master.DefaultAPIResourceConfigSource()
- resourceConfig.EnableVersions(groupVersions...)
- masterConfig.ExtraConfig.APIResourceConfigSource = resourceConfig
- }
- masterConfig.GenericConfig.OpenAPIConfig = framework.DefaultOpenAPIConfig()
- _, s, closeFn := framework.RunAMaster(masterConfig)
- clientSet, err := clientset.NewForConfig(&restclient.Config{Host: s.URL})
- if err != nil {
- t.Fatalf("Error in create clientset: %v", err)
- }
- return s, clientSet, closeFn
- }
- // TestApplyAlsoCreates makes sure that PATCH requests with the apply content type
- // will create the object if it doesn't already exist
- // TODO: make a set of test cases in an easy-to-consume place (separate package?) so it's easy to test in both integration and e2e.
- func TestApplyAlsoCreates(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- testCases := []struct {
- resource string
- name string
- body string
- }{
- {
- resource: "pods",
- name: "test-pod",
- body: `{
- "apiVersion": "v1",
- "kind": "Pod",
- "metadata": {
- "name": "test-pod"
- },
- "spec": {
- "containers": [{
- "name": "test-container",
- "image": "test-image"
- }]
- }
- }`,
- }, {
- resource: "services",
- name: "test-svc",
- body: `{
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "name": "test-svc"
- },
- "spec": {
- "ports": [{
- "port": 8080,
- "protocol": "UDP"
- }]
- }
- }`,
- },
- }
- for _, tc := range testCases {
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource(tc.resource).
- Name(tc.name).
- Param("fieldManager", "apply_test").
- Body([]byte(tc.body)).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Get().Namespace("default").Resource(tc.resource).Name(tc.name).Do().Get()
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- // Test that we can re apply with a different field manager and don't get conflicts
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource(tc.resource).
- Name(tc.name).
- Param("fieldManager", "apply_test_2").
- Body([]byte(tc.body)).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Failed to re-apply object using Apply patch: %v", err)
- }
- }
- }
- // TestCreateOnApplyFailsWithUID makes sure that PATCH requests with the apply content type
- // will not create the object if it doesn't already exist and it specifies a UID
- func TestCreateOnApplyFailsWithUID(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("pods").
- Name("test-pod-uid").
- Param("fieldManager", "apply_test").
- Body([]byte(`{
- "apiVersion": "v1",
- "kind": "Pod",
- "metadata": {
- "name": "test-pod-uid",
- "uid": "88e00824-7f0e-11e8-94a1-c8d3ffb15800"
- },
- "spec": {
- "containers": [{
- "name": "test-container",
- "image": "test-image"
- }]
- }
- }`)).
- Do().
- Get()
- if !errors.IsConflict(err) {
- t.Fatalf("Expected conflict error but got: %v", err)
- }
- }
- func TestApplyUpdateApplyConflictForced(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"}
- },
- "spec": {
- "replicas": 3,
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest"
- }]
- }
- }
- }
- }`)
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.MergePatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Body([]byte(`{"spec":{"replicas": 5}}`)).Do().Get()
- if err != nil {
- t.Fatalf("Failed to patch object: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body([]byte(obj)).Do().Get()
- if err == nil {
- t.Fatalf("Expecting to get conflicts when applying object")
- }
- status, ok := err.(*errors.StatusError)
- if !ok {
- t.Fatalf("Expecting to get conflicts as API error")
- }
- if len(status.Status().Details.Causes) < 1 {
- t.Fatalf("Expecting to get at least one conflict when applying object, got: %v", status.Status().Details.Causes)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("force", "true").
- Param("fieldManager", "apply_test").
- Body([]byte(obj)).Do().Get()
- if err != nil {
- t.Fatalf("Failed to apply object with force: %v", err)
- }
- }
- // TestApplyManagedFields makes sure that managedFields api does not change
- func TestApplyManagedFields(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "apply_test").
- Body([]byte(`{
- "apiVersion": "v1",
- "kind": "ConfigMap",
- "metadata": {
- "name": "test-cm",
- "namespace": "default",
- "labels": {
- "test-label": "test"
- }
- },
- "data": {
- "key": "value"
- }
- }`)).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.MergePatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "updater").
- Body([]byte(`{"data":{"key": "new value"}}`)).Do().Get()
- if err != nil {
- t.Fatalf("Failed to patch object: %v", err)
- }
- object, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource("configmaps").Name("test-cm").Do().Get()
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- accessor, err := meta.Accessor(object)
- if err != nil {
- t.Fatalf("Failed to get meta accessor: %v", err)
- }
- actual, err := json.MarshalIndent(object, "\t", "\t")
- if err != nil {
- t.Fatalf("Failed to marshal object: %v", err)
- }
- expected := []byte(`{
- "metadata": {
- "name": "test-cm",
- "namespace": "default",
- "selfLink": "` + accessor.GetSelfLink() + `",
- "uid": "` + string(accessor.GetUID()) + `",
- "resourceVersion": "` + accessor.GetResourceVersion() + `",
- "creationTimestamp": "` + accessor.GetCreationTimestamp().UTC().Format(time.RFC3339) + `",
- "labels": {
- "test-label": "test"
- },
- "managedFields": [
- {
- "manager": "apply_test",
- "operation": "Apply",
- "apiVersion": "v1",
- "fields": {
- "f:metadata": {
- "f:labels": {
- "f:test-label": {}
- }
- }
- }
- },
- {
- "manager": "updater",
- "operation": "Update",
- "apiVersion": "v1",
- "time": "` + accessor.GetManagedFields()[1].Time.UTC().Format(time.RFC3339) + `",
- "fields": {
- "f:data": {
- "f:key": {}
- }
- }
- }
- ]
- },
- "data": {
- "key": "new value"
- }
- }`)
- if string(expected) != string(actual) {
- t.Fatalf("Expected:\n%v\nGot:\n%v", string(expected), string(actual))
- }
- }
- // TestApplyRemovesEmptyManagedFields there are no empty managers in managedFields
- func TestApplyRemovesEmptyManagedFields(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "v1",
- "kind": "ConfigMap",
- "metadata": {
- "name": "test-cm",
- "namespace": "default"
- }
- }`)
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "apply_test").
- Body(obj).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "apply_test").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to patch object: %v", err)
- }
- object, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource("configmaps").Name("test-cm").Do().Get()
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- accessor, err := meta.Accessor(object)
- if err != nil {
- t.Fatalf("Failed to get meta accessor: %v", err)
- }
- if managed := accessor.GetManagedFields(); managed != nil {
- t.Fatalf("Object contains unexpected managedFields: %v", managed)
- }
- }
- func TestApplyRequiresFieldManager(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "v1",
- "kind": "ConfigMap",
- "metadata": {
- "name": "test-cm",
- "namespace": "default"
- }
- }`)
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Body(obj).
- Do().
- Get()
- if err == nil {
- t.Fatalf("Apply should fail to create without fieldManager")
- }
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "apply_test").
- Body(obj).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Apply failed to create with fieldManager: %v", err)
- }
- }
- // TestApplyRemoveContainerPort removes a container port from a deployment
- func TestApplyRemoveContainerPort(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"}
- },
- "spec": {
- "replicas": 3,
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest",
- "ports": [{
- "containerPort": 80,
- "protocol": "TCP"
- }]
- }]
- }
- }
- }
- }`)
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- obj = []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"}
- },
- "spec": {
- "replicas": 3,
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest"
- }]
- }
- }
- }
- }`)
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to remove container port using Apply patch: %v", err)
- }
- deployment, err := client.AppsV1().Deployments("default").Get("deployment", metav1.GetOptions{})
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- if len(deployment.Spec.Template.Spec.Containers[0].Ports) > 0 {
- t.Fatalf("Expected no container ports but got: %v", deployment.Spec.Template.Spec.Containers[0].Ports)
- }
- }
- // TestApplyFailsWithVersionMismatch ensures that a version mismatch between the
- // patch object and the live object will error
- func TestApplyFailsWithVersionMismatch(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"}
- },
- "spec": {
- "replicas": 3,
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest"
- }]
- }
- }
- }
- }`)
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- obj = []byte(`{
- "apiVersion": "extensions/v1beta",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"}
- },
- "spec": {
- "replicas": 100,
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest"
- }]
- }
- }
- }
- }`)
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "apply_test").
- Body([]byte(obj)).Do().Get()
- if err == nil {
- t.Fatalf("Expecting to get version mismatch when applying object")
- }
- status, ok := err.(*errors.StatusError)
- if !ok {
- t.Fatalf("Expecting to get version mismatch as API error")
- }
- if status.Status().Code != http.StatusBadRequest {
- t.Fatalf("expected status code to be %d but was %d", http.StatusBadRequest, status.Status().Code)
- }
- }
- // TestApplyConvertsManagedFieldsVersion checks that the apply
- // converts the API group-version in the field manager
- func TestApplyConvertsManagedFieldsVersion(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- obj := []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"app": "nginx"},
- "managedFields": [
- {
- "manager": "sidecar_controller",
- "operation": "Apply",
- "apiVersion": "extensions/v1beta1",
- "fields": {
- "f:metadata": {
- "f:labels": {
- "f:sidecar_version": {}
- }
- },
- "f:spec": {
- "f:template": {
- "f: spec": {
- "f:containers": {
- "k:{\"name\":\"sidecar\"}": {
- ".": {},
- "f:image": {}
- }
- }
- }
- }
- }
- }
- }
- ]
- },
- "spec": {
- "selector": {
- "matchLabels": {
- "app": "nginx"
- }
- },
- "template": {
- "metadata": {
- "labels": {
- "app": "nginx"
- }
- },
- "spec": {
- "containers": [{
- "name": "nginx",
- "image": "nginx:latest"
- }]
- }
- }
- }
- }`)
- _, err := client.CoreV1().RESTClient().Post().
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Body(obj).Do().Get()
- if err != nil {
- t.Fatalf("Failed to create object: %v", err)
- }
- obj = []byte(`{
- "apiVersion": "apps/v1",
- "kind": "Deployment",
- "metadata": {
- "name": "deployment",
- "labels": {"sidecar_version": "release"}
- },
- "spec": {
- "template": {
- "spec": {
- "containers": [{
- "name": "sidecar",
- "image": "sidecar:latest"
- }]
- }
- }
- }
- }`)
- _, err = client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- AbsPath("/apis/apps/v1").
- Namespace("default").
- Resource("deployments").
- Name("deployment").
- Param("fieldManager", "sidecar_controller").
- Body([]byte(obj)).Do().Get()
- if err != nil {
- t.Fatalf("Failed to apply object: %v", err)
- }
- object, err := client.AppsV1().Deployments("default").Get("deployment", metav1.GetOptions{})
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- accessor, err := meta.Accessor(object)
- if err != nil {
- t.Fatalf("Failed to get meta accessor: %v", err)
- }
- managed := accessor.GetManagedFields()
- if len(managed) != 2 {
- t.Fatalf("Expected 2 field managers, but got managed fields: %v", managed)
- }
- var actual *metav1.ManagedFieldsEntry
- for i := range managed {
- entry := &managed[i]
- if entry.Manager == "sidecar_controller" && entry.APIVersion == "apps/v1" {
- actual = entry
- }
- }
- if actual == nil {
- t.Fatalf("Expected managed fields to contain entry with manager '%v' with converted api version '%v', but got managed fields:\n%v", "sidecar_controller", "apps/v1", managed)
- }
- expected := &metav1.ManagedFieldsEntry{
- Manager: "sidecar_controller",
- Operation: metav1.ManagedFieldsOperationApply,
- APIVersion: "apps/v1",
- Time: actual.Time,
- Fields: &metav1.Fields{
- Map: map[string]metav1.Fields{
- "f:metadata": {
- Map: map[string]metav1.Fields{
- "f:labels": {
- Map: map[string]metav1.Fields{
- "f:sidecar_version": {Map: map[string]metav1.Fields{}},
- },
- },
- },
- },
- "f:spec": {
- Map: map[string]metav1.Fields{
- "f:template": {
- Map: map[string]metav1.Fields{
- "f:spec": {
- Map: map[string]metav1.Fields{
- "f:containers": {
- Map: map[string]metav1.Fields{
- "k:{\"name\":\"sidecar\"}": {
- Map: map[string]metav1.Fields{
- ".": {Map: map[string]metav1.Fields{}},
- "f:image": {Map: map[string]metav1.Fields{}},
- "f:name": {Map: map[string]metav1.Fields{}},
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- }
- if !reflect.DeepEqual(actual, expected) {
- t.Fatalf("expected:\n%v\nbut got:\n%v", expected, actual)
- }
- }
- // TestClearManagedFields verifies it's possible to clear the managedFields
- func TestClearManagedFields(t *testing.T) {
- defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.ServerSideApply, true)()
- _, client, closeFn := setup(t)
- defer closeFn()
- _, err := client.CoreV1().RESTClient().Patch(types.ApplyPatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Param("fieldManager", "apply_test").
- Body([]byte(`{
- "apiVersion": "v1",
- "kind": "ConfigMap",
- "metadata": {
- "name": "test-cm",
- "namespace": "default",
- "labels": {
- "test-label": "test"
- }
- },
- "data": {
- "key": "value"
- }
- }`)).
- Do().
- Get()
- if err != nil {
- t.Fatalf("Failed to create object using Apply patch: %v", err)
- }
- _, err = client.CoreV1().RESTClient().Patch(types.MergePatchType).
- Namespace("default").
- Resource("configmaps").
- Name("test-cm").
- Body([]byte(`{"metadata":{"managedFields": [{}]}}`)).Do().Get()
- if err != nil {
- t.Fatalf("Failed to patch object: %v", err)
- }
- object, err := client.CoreV1().RESTClient().Get().Namespace("default").Resource("configmaps").Name("test-cm").Do().Get()
- if err != nil {
- t.Fatalf("Failed to retrieve object: %v", err)
- }
- accessor, err := meta.Accessor(object)
- if err != nil {
- t.Fatalf("Failed to get meta accessor: %v", err)
- }
- if managedFields := accessor.GetManagedFields(); len(managedFields) != 0 {
- t.Fatalf("Failed to clear managedFields, got: %v", managedFields)
- }
- }
|