Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make generation of the apply annotation optional #16809

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions contrib/completions/bash/kubectl
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ _kubectl_create()
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--validate")

Expand Down Expand Up @@ -391,6 +392,7 @@ _kubectl_replace()
flags+=("--grace-period=")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--timeout=")
flags+=("--validate")
Expand Down Expand Up @@ -498,6 +500,7 @@ _kubectl_edit()
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--windows-line-endings")

must_have_one_flag=()
Expand Down Expand Up @@ -766,6 +769,7 @@ _kubectl_run()
two_word_flags+=("-r")
flags+=("--requests=")
flags+=("--restart=")
flags+=("--save-config")
flags+=("--service-generator=")
flags+=("--service-overrides=")
flags+=("--show-all")
Expand Down Expand Up @@ -843,6 +847,7 @@ _kubectl_expose()
flags+=("--overrides=")
flags+=("--port=")
flags+=("--protocol=")
flags+=("--save-config")
flags+=("--selector=")
flags+=("--session-affinity=")
flags+=("--show-all")
Expand Down Expand Up @@ -883,6 +888,7 @@ _kubectl_autoscale()
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--save-config")
flags+=("--show-all")
flags+=("-a")
flags+=("--sort-by=")
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-autoscale.1
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ An autoscaler can automatically increase or decrease number of pods deployed wit
\fB\-\-output\-version\fP=""
Output the formatted object with the given version (default api\-version).

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-a\fP, \fB\-\-show\-all\fP=false
When printing, show all resources (default hide terminated pods.)
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-create.1
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ JSON and YAML formats are accepted.
\fB\-o\fP, \fB\-\-output\fP=""
Output mode. Use "\-o name" for shorter output (resource/name).

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-edit.1
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ saved copy to include the latest resource version.
\fB\-\-output\-version\fP=""
Output the formatted object with the given version (default api\-version).

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-\-windows\-line\-endings\fP=false
Use Windows line\-endings (default Unix line\-endings)
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-expose.1
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ the new service will re\-use the labels from the resource it exposes.
\fB\-\-protocol\fP="TCP"
The network protocol for the service to be created. Default is 'tcp'.

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-\-selector\fP=""
A label selector to use for this service. If empty (the default) infer the selector from the replication controller.
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-replace.1
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Please refer to the models in
\fB\-o\fP, \fB\-\-output\fP=""
Output mode. Use "\-o name" for shorter output (resource/name).

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-\-schema\-cache\-dir\fP="\~/.kube/schema"
If non\-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/kubectl-run.1
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ Creates a replication controller to manage the created container(s).
\fB\-\-restart\fP="Always"
The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and \-\-replicas must be 1. Default 'Always'

.PP
\fB\-\-save\-config\fP=false
If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.

.PP
\fB\-\-service\-generator\fP="service/v2"
The name of the generator to use for creating a service. Only used if \-\-expose is true
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_autoscale.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ $ kubectl autoscale rc foo --max=5 --cpu-percent=80
--no-headers[=false]: When using the default output, don't print headers.
-o, --output="": Output format. One of: json|yaml|wide|name|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://releases.k8s.io/HEAD/docs/user-guide/jsonpath.md].
--output-version="": Output the formatted object with the given version (default api-version).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
--sort-by="": If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. 'ObjectMeta.Name'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
--template="": Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
Expand Down Expand Up @@ -107,7 +108,7 @@ $ kubectl autoscale rc foo --max=5 --cpu-percent=80

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra on 16-Oct-2015
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_autoscale.md?pixel)]()
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ $ cat pod.json | kubectl create -f -
```
-f, --filename=[]: Filename, directory, or URL to file to use to create the resource
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--validate[=true]: If true, use a schema to validate the input before sending it
```
Expand Down Expand Up @@ -97,7 +98,7 @@ $ cat pod.json | kubectl create -f -

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra on 9-Oct-2015
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create.md?pixel)]()
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_edit.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ kubectl edit (RESOURCE/NAME | -f FILENAME)
-f, --filename=[]: Filename, directory, or URL to file to use to edit the resource
-o, --output="yaml": Output format. One of: yaml|json.
--output-version="": Output the formatted object with the given version (default api-version).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--windows-line-endings[=false]: Use Windows line-endings (default Unix line-endings)
```

Expand Down Expand Up @@ -116,7 +117,7 @@ kubectl edit (RESOURCE/NAME | -f FILENAME)

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra on 23-Oct-2015
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_edit.md?pixel)]()
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_expose.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ $ kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream
--overrides="": An inline JSON override for the generated object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field.
--port="": The port that the service should serve on. Copied from the resource being exposed, if unspecified
--protocol="TCP": The network protocol for the service to be created. Default is 'tcp'.
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--selector="": A label selector to use for this service. If empty (the default) infer the selector from the replication controller.
--session-affinity="": If non-empty, set the session affinity for the service to this; legal values: 'None', 'ClientIP'
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
Expand Down Expand Up @@ -126,7 +127,7 @@ $ kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra at 2015-10-14 10:34:09.969832007 +0000 UTC
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_expose.md?pixel)]()
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_replace.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ kubectl replace --force -f ./pod.json
--force[=false]: Delete and re-create the specified resource
--grace-period=-1: Only relevant during a force replace. Period of time in seconds given to the old resource to terminate gracefully. Ignored if negative.
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir="~/.kube/schema": If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--timeout=0: Only relevant during a force replace. The length of time to wait before giving up on a delete of the old resource, zero means determine a timeout from the size of the object
--validate[=true]: If true, use a schema to validate the input before sending it
Expand Down Expand Up @@ -111,7 +112,7 @@ kubectl replace --force -f ./pod.json

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra on 9-Oct-2015
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_replace.md?pixel)]()
Expand Down
3 changes: 2 additions & 1 deletion docs/user-guide/kubectl/kubectl_run.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ $ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>
-r, --replicas=1: Number of replicas to create for this container. Default is 1.
--requests="": The resource requirement requests for this container. For example, 'cpu=100m,memory=256Mi'
--restart="Always": The restart policy for this Pod. Legal values [Always, OnFailure, Never]. If set to 'Always' a replication controller is created for this pod, if set to OnFailure or Never, only the Pod is created and --replicas must be 1. Default 'Always'
--save-config[=false]: If true, the configuration of current object will be saved in its annotation. This is useful when you want to perform kubectl apply on this object in the future.
--service-generator="service/v2": The name of the generator to use for creating a service. Only used if --expose is true
--service-overrides="": An inline JSON override for the generated service object. If this is non-empty, it is used to override the generated object. Requires that the object supply a valid apiVersion field. Only used if --expose is true.
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
Expand Down Expand Up @@ -139,7 +140,7 @@ $ kubectl run nginx --image=nginx --command -- <cmd> <arg1> ... <argN>

* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager

###### Auto generated by spf13/cobra on 30-Oct-2015
###### Auto generated by spf13/cobra on 6-Nov-2015

<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_run.md?pixel)]()
Expand Down
64 changes: 64 additions & 0 deletions hack/test-cmd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,70 @@ runTests() {
! [[ $(diff -q "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced > /dev/null) ]]
# Clean up
rm "${KUBE_TEMP}"/test-pod-replace.yaml "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced
kubectl delete pods test-pod "${kube_flags[@]}"

## Configuration annotations should be set when --save-config is enabled
## 1. kubectl create --save-config should generate configuration annotation
# Pre-Condition: no POD is running
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
# Command: create a pod "test-pod"
kubectl create -f hack/testdata/pod.yaml --save-config "${kube_flags[@]}"
# Post-Condition: pod "test-pod" has configuration annotation
[[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Clean up
kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
## 2. kubectl edit --save-config should generate configuration annotation
# Pre-Condition: no POD is running, then create pod "test-pod", which shouldn't have configuration annotation
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Command: edit the pod "test-pod"
temp_editor="${KUBE_TEMP}/tmp-editor.sh"
echo -e '#!/bin/bash\nsed -i "s/test-pod-label/test-pod-label-edited/g" $@' > "${temp_editor}"
chmod +x "${temp_editor}"
EDITOR=${temp_editor} kubectl edit pod test-pod --save-config "${kube_flags[@]}"
# Post-Condition: pod "test-pod" has configuration annotation
[[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Clean up
kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
## 3. kubectl replace --save-config should generate configuration annotation
# Pre-Condition: no POD is running, then create pod "test-pod", which shouldn't have configuration annotation
kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Command: replace the pod "test-pod"
kubectl replace -f hack/testdata/pod.yaml --save-config "${kube_flags[@]}"
# Post-Condition: pod "test-pod" has configuration annotation
[[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Clean up
kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
## 4. kubectl run --save-config should generate configuration annotation
# Pre-Condition: no RC is running
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
# Command: create the rc "nginx" with image nginx
kubectl run nginx --image=nginx --save-config "${kube_flags[@]}"
# Post-Condition: rc "nginx" has configuration annotation
[[ "$(kubectl get rc nginx -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
## 5. kubectl expose --save-config should generate configuration annotation
# Pre-Condition: no service is running
kube::test::get_object_assert svc "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
# Command: expose the rc "nginx"
kubectl expose rc nginx --save-config --port=80 --target-port=8000 "${kube_flags[@]}"
# Post-Condition: service "nginx" has configuration annotation
[[ "$(kubectl get svc nginx -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Clean up
kubectl delete rc,svc nginx
## 6. kubectl autoscale --save-config should generate configuration annotation
# Pre-Condition: no RC is running, then create the rc "frontend", which shouldn't have configuration annotation
kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
kubectl create -f examples/guestbook/frontend-controller.yaml "${kube_flags[@]}"
! [[ "$(kubectl get rc frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Command: autoscale rc "frontend"
kubectl autoscale -f examples/guestbook/frontend-controller.yaml --save-config "${kube_flags[@]}" --max=2
# Post-Condition: hpa "frontend" has configuration annotation
[[ "$(kubectl get hpa frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
# Clean up
kubectl delete rc,hpa frontend

##############
# Namespaces #
Expand Down
1 change: 1 addition & 0 deletions hack/verify-flags/known-flags.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ root-ca-file
root-dir
run-proxy
runtime-config
save-config
scheduler-config
schema-cache-dir
secure-port
Expand Down
36 changes: 20 additions & 16 deletions pkg/kubectl/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,26 +163,30 @@ func GetModifiedConfiguration(info *resource.Info, annotate bool) ([]byte, error
return modified, nil
}

// If the last applied configuration annotation is already present, then
// UpdateApplyAnnotation gets the modified configuration of the object,
// without embedding it again, and then sets it on the object as the annotation.
// Otherwise, it does nothing.
// UpdateApplyAnnotation calls CreateApplyAnnotation if the last applied
// configuration annotation is already present. Otherwise, it does nothing.
func UpdateApplyAnnotation(info *resource.Info) error {
original, err := GetOriginalConfiguration(info)
if err != nil {
if original, err := GetOriginalConfiguration(info); err != nil || len(original) <= 0 {
return err
}
return CreateApplyAnnotation(info)
}

if len(original) > 0 {
modified, err := GetModifiedConfiguration(info, false)
if err != nil {
return err
}

if err := SetOriginalConfiguration(info, modified); err != nil {
return err
}
// CreateApplyAnnotation gets the modified configuration of the object,
// without embedding it again, and then sets it on the object as the annotation.
func CreateApplyAnnotation(info *resource.Info) error {
modified, err := GetModifiedConfiguration(info, false)
if err != nil {
return err
}
return SetOriginalConfiguration(info, modified)
}

return nil
// Create the annotation used by kubectl apply only when createAnnotation is true
// Otherwise, only update the annotation when it already exists
func CreateOrUpdateAnnotation(createAnnotation bool, info *resource.Info) error {
if createAnnotation {
return CreateApplyAnnotation(info)
}
return UpdateApplyAnnotation(info)
}