mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-13 11:25:19 +00:00
Add "fieldManager" to flag to PATCH/CREATE/UPDATE
And add a corresponding flag in kubectl (for apply), even though the value is defaulted in kubectl with "kubectl". The flag is required for Apply patch-type, and optional for other PATCH, CREATE and UPDATE (in which case we fallback on the user-agent).
This commit is contained in:
@@ -249,12 +249,12 @@ run_kubectl_apply_tests() {
|
||||
set -o errexit
|
||||
|
||||
create_and_use_new_namespace
|
||||
kube::log::status "Testing kubectl apply --server-side"
|
||||
kube::log::status "Testing kubectl apply --experimental-server-side"
|
||||
## kubectl apply should create the resource that doesn't exist yet
|
||||
# Pre-Condition: no POD exists
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# Command: apply a pod "test-pod" (doesn't exist) should create this pod
|
||||
kubectl apply --server-side -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
kubectl apply --experimental-server-side -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
# Post-Condition: pod "test-pod" is created
|
||||
kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label'
|
||||
# Clean up
|
||||
@@ -265,13 +265,13 @@ run_kubectl_apply_tests() {
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
|
||||
# apply dry-run
|
||||
kubectl apply --server-side --server-dry-run -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
kubectl apply --experimental-server-side --server-dry-run -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
# No pod exists
|
||||
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||
# apply non dry-run creates the pod
|
||||
kubectl apply --server-side -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
kubectl apply --experimental-server-side -f hack/testdata/pod.yaml "${kube_flags[@]}"
|
||||
# apply changes
|
||||
kubectl apply --server-side --server-dry-run -f hack/testdata/pod-apply.yaml "${kube_flags[@]}"
|
||||
kubectl apply --experimental-server-side --server-dry-run -f hack/testdata/pod-apply.yaml "${kube_flags[@]}"
|
||||
# Post-Condition: label still has initial value
|
||||
kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label'
|
||||
|
||||
@@ -302,7 +302,7 @@ run_kubectl_apply_tests() {
|
||||
__EOF__
|
||||
|
||||
# Dry-run create the CR
|
||||
kubectl "${kube_flags[@]}" apply --server-side --server-dry-run -f hack/testdata/CRD/resource.yaml "${kube_flags[@]}"
|
||||
kubectl "${kube_flags[@]}" apply --experimental-server-side --server-dry-run -f hack/testdata/CRD/resource.yaml "${kube_flags[@]}"
|
||||
# Make sure that the CR doesn't exist
|
||||
! kubectl "${kube_flags[@]}" get resource/myobj
|
||||
|
||||
|
||||
@@ -2,10 +2,15 @@ load("@io_bazel_rules_go//go:def.bzl", "go_test")
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "large",
|
||||
srcs = [
|
||||
"apply_test.go",
|
||||
"main_test.go",
|
||||
],
|
||||
tags = [
|
||||
"etcd",
|
||||
"integration",
|
||||
],
|
||||
deps = [
|
||||
"//pkg/master:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
|
||||
@@ -106,6 +106,7 @@ func TestApplyAlsoCreates(t *testing.T) {
|
||||
Namespace("default").
|
||||
Resource(tc.resource).
|
||||
Name(tc.name).
|
||||
Param("fieldManager", "apply_test").
|
||||
Body([]byte(tc.body)).
|
||||
Do().
|
||||
Get()
|
||||
@@ -132,6 +133,7 @@ func TestCreateOnApplyFailsWithUID(t *testing.T) {
|
||||
Namespace("default").
|
||||
Resource("pods").
|
||||
Name("test-pod-uid").
|
||||
Param("fieldManager", "apply_test").
|
||||
Body([]byte(`{
|
||||
"apiVersion": "v1",
|
||||
"kind": "Pod",
|
||||
@@ -194,6 +196,7 @@ func TestApplyUpdateApplyConflictForced(t *testing.T) {
|
||||
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)
|
||||
@@ -214,6 +217,7 @@ func TestApplyUpdateApplyConflictForced(t *testing.T) {
|
||||
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")
|
||||
@@ -232,6 +236,7 @@ func TestApplyUpdateApplyConflictForced(t *testing.T) {
|
||||
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)
|
||||
@@ -249,6 +254,7 @@ func TestApplyManagedFields(t *testing.T) {
|
||||
Namespace("default").
|
||||
Resource("configmaps").
|
||||
Name("test-cm").
|
||||
Param("fieldManager", "apply_test").
|
||||
Body([]byte(`{
|
||||
"apiVersion": "v1",
|
||||
"kind": "ConfigMap",
|
||||
@@ -273,6 +279,7 @@ func TestApplyManagedFields(t *testing.T) {
|
||||
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)
|
||||
@@ -306,7 +313,7 @@ func TestApplyManagedFields(t *testing.T) {
|
||||
},
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "apply",
|
||||
"manager": "apply_test",
|
||||
"operation": "Apply",
|
||||
"apiVersion": "v1",
|
||||
"fields": {
|
||||
@@ -318,7 +325,7 @@ func TestApplyManagedFields(t *testing.T) {
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "` + accessor.GetManagedFields()[1].Manager + `",
|
||||
"manager": "updater",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "` + accessor.GetManagedFields()[1].Time.UTC().Format(time.RFC3339) + `",
|
||||
@@ -360,6 +367,7 @@ func TestApplyRemovesEmptyManagedFields(t *testing.T) {
|
||||
Namespace("default").
|
||||
Resource("configmaps").
|
||||
Name("test-cm").
|
||||
Param("fieldManager", "apply_test").
|
||||
Body(obj).
|
||||
Do().
|
||||
Get()
|
||||
@@ -371,6 +379,7 @@ func TestApplyRemovesEmptyManagedFields(t *testing.T) {
|
||||
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)
|
||||
@@ -390,3 +399,42 @@ func TestApplyRemovesEmptyManagedFields(t *testing.T) {
|
||||
t.Fatalf("Object contains unexpected managedFields: %v", managed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyRequiresFieldManager(t *testing.T) {
|
||||
defer utilfeaturetesting.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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,6 +567,9 @@ func TestRBAC(t *testing.T) {
|
||||
if r.verb == "PATCH" {
|
||||
// For patch operations, use the apply content type
|
||||
req.Header.Add("Content-Type", string(types.ApplyPatchType))
|
||||
q := req.URL.Query()
|
||||
q.Add("fieldManager", "rbac_test")
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user