Make generation of the apply annotation optional

pull/6/head
Janet Kuo 2015-11-04 13:47:08 -08:00
parent 13e68d2a87
commit a6a64820d7
24 changed files with 158 additions and 41 deletions

View File

@ -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")
@ -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")
@ -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=()
@ -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")
@ -843,6 +847,7 @@ _kubectl_expose()
flags+=("--overrides=")
flags+=("--port=")
flags+=("--protocol=")
flags+=("--save-config")
flags+=("--selector=")
flags+=("--session-affinity=")
flags+=("--show-all")
@ -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=")

View File

@ -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.)

View File

@ -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'

View File

@ -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)

View File

@ -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.

View File

@ -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'

View File

@ -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

View File

@ -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].
@ -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)]()

View File

@ -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
```
@ -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)]()

View File

@ -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)
```
@ -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)]()

View File

@ -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.)
@ -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)]()

View File

@ -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
@ -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)]()

View File

@ -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.)
@ -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)]()

View File

@ -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 #

View File

@ -266,6 +266,7 @@ root-ca-file
root-dir
run-proxy
runtime-config
save-config
scheduler-config
schema-cache-dir
secure-port

View File

@ -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 original, err := GetOriginalConfiguration(info); err != nil || len(original) <= 0 {
return err
}
return CreateApplyAnnotation(info)
}
// 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
}
if len(original) > 0 {
modified, err := GetModifiedConfiguration(info, false)
if err != nil {
return err
}
if err := SetOriginalConfiguration(info, modified); err != nil {
return err
}
}
return nil
return SetOriginalConfiguration(info, modified)
}
// 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)
}

View File

@ -64,6 +64,7 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without creating it.")
usage := "Filename, directory, or URL to a file identifying the resource to get from a server."
kubectl.AddJsonFilenameFlag(cmd, &filenames, usage)
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -134,8 +135,7 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
return f.PrintObject(cmd, object, out)
}
// Serialize the configuration into an annotation.
if err := kubectl.UpdateApplyAnnotation(hpa); err != nil {
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), hpa); err != nil {
return err
}

View File

@ -67,6 +67,7 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -106,9 +107,7 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
if err != nil {
return err
}
// Update the annotation used by kubectl apply
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}

View File

@ -95,6 +95,7 @@ func NewCmdEdit(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringP("output", "o", "yaml", "Output format. One of: yaml|json.")
cmd.Flags().String("output-version", "", "Output the formatted object with the given version (default api-version).")
cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows", "Use Windows line-endings (default Unix line-endings)")
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -220,8 +221,12 @@ func RunEdit(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
return fmt.Errorf("The edited file had a syntax error: %v", err)
}
// annotate the edited object for kubectl apply
if err := kubectl.UpdateApplyAnnotation(updates); err != nil {
// put configuration annotation in "updates"
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), updates); err != nil {
return preservedFile(err, file, out)
}
// encode updates back to "edited" since we'll only generate patch from "edited"
if edited, err = updates.Mapping.Codec.Encode(updates.Object); err != nil {
return preservedFile(err, file, out)
}

View File

@ -93,6 +93,7 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "Filename, directory, or URL to a file identifying the resource to expose a service"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -201,8 +202,7 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
if cmdutil.GetFlagBool(cmd, "dry-run") {
return f.PrintObject(cmd, object, out)
}
// Serialize the configuration into an annotation.
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil {
return err
}

View File

@ -83,6 +83,7 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().Duration("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")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -128,9 +129,8 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
return err
}
// Serialize the configuration into an annotation.
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
return err
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil {
return cmdutil.AddSourceToErr("replacing", info.Source, err)
}
// Serialize the object with the annotation applied.
@ -216,8 +216,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
return err
}
// Serialize the configuration into an annotation.
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil {
return err
}

View File

@ -78,6 +78,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
}
cmdutil.AddPrinterFlags(cmd)
addRunFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
return cmd
}
@ -371,8 +372,7 @@ func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kub
return nil, "", nil, nil, err
}
// Serialize the configuration into an annotation.
if err := kubectl.UpdateApplyAnnotation(info); err != nil {
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), info); err != nil {
return nil, "", nil, nil, err
}

View File

@ -235,6 +235,7 @@ func TestGenerateService(t *testing.T) {
}
cmd := &cobra.Command{}
cmd.Flags().String("output", "", "")
cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "")
addRunFlags(cmd)
if !test.expectPOST {

View File

@ -28,7 +28,6 @@ import (
"strings"
"time"
"github.com/evanphx/json-patch"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/latest"
"k8s.io/kubernetes/pkg/api/unversioned"
@ -39,11 +38,16 @@ import (
"k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"github.com/evanphx/json-patch"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const (
ApplyAnnotationsFlag = "save-config"
)
type debugError interface {
DebugError() (msg string, args []interface{})
}
@ -283,6 +287,10 @@ func AddValidateFlags(cmd *cobra.Command) {
cmd.Flags().String("schema-cache-dir", fmt.Sprintf("~/%s/%s", clientcmd.RecommendedHomeDir, clientcmd.RecommendedSchemaName), fmt.Sprintf("If non-empty, load/store cached API schemas in this directory, default is '$HOME/%s/%s'", clientcmd.RecommendedHomeDir, clientcmd.RecommendedSchemaName))
}
func AddApplyAnnotationFlags(cmd *cobra.Command) {
cmd.Flags().Bool(ApplyAnnotationsFlag, 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.")
}
func ReadConfigDataFromReader(reader io.Reader, source string) ([]byte, error) {
data, err := ioutil.ReadAll(reader)
if err != nil {