Record kubectl commands

pull/6/head
Janet Kuo 2016-01-22 10:33:23 -08:00
parent 210bac10c9
commit 5088d0e147
38 changed files with 277 additions and 11 deletions

View File

@ -616,6 +616,7 @@ _kubectl_create()
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--record")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--validate")
@ -671,6 +672,7 @@ _kubectl_replace()
flags+=("--grace-period=")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--record")
flags+=("--save-config")
flags+=("--schema-cache-dir=")
flags+=("--timeout=")
@ -726,6 +728,7 @@ _kubectl_patch()
two_word_flags+=("-o")
flags+=("--patch=")
two_word_flags+=("-p")
flags+=("--record")
flags+=("--alsologtostderr")
flags+=("--api-version=")
flags+=("--certificate-authority=")
@ -852,6 +855,7 @@ _kubectl_edit()
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--record")
flags+=("--save-config")
flags+=("--windows-line-endings")
flags+=("--alsologtostderr")
@ -901,6 +905,7 @@ _kubectl_apply()
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--record")
flags+=("--schema-cache-dir=")
flags+=("--validate")
flags+=("--alsologtostderr")
@ -1110,6 +1115,7 @@ _kubectl_scale()
flags_completion+=("__handle_filename_extension_flag json|yaml|yml")
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--record")
flags+=("--replicas=")
flags+=("--resource-version=")
flags+=("--timeout=")
@ -1477,6 +1483,7 @@ _kubectl_run()
flags+=("--output-version=")
flags+=("--overrides=")
flags+=("--port=")
flags+=("--record")
flags+=("--replicas=")
two_word_flags+=("-r")
flags+=("--requests=")
@ -1555,6 +1562,7 @@ _kubectl_expose()
flags+=("--overrides=")
flags+=("--port=")
flags+=("--protocol=")
flags+=("--record")
flags+=("--save-config")
flags+=("--selector=")
flags+=("--session-affinity=")
@ -1620,6 +1628,7 @@ _kubectl_autoscale()
flags+=("--output=")
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--record")
flags+=("--save-config")
flags+=("--show-all")
flags+=("-a")
@ -1857,6 +1866,7 @@ _kubectl_label()
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--overwrite")
flags+=("--record")
flags+=("--resource-version=")
flags+=("--selector=")
two_word_flags+=("-l")
@ -1938,6 +1948,7 @@ _kubectl_annotate()
two_word_flags+=("-o")
flags+=("--output-version=")
flags+=("--overwrite")
flags+=("--record")
flags+=("--resource-version=")
flags+=("--selector=")
two_word_flags+=("-l")

View File

@ -55,6 +55,10 @@ horizontalpodautoscalers (hpa), resourcequotas (quota) or secrets.
\fB\-\-overwrite\fP=false
If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.
.PP
\fB\-\-record\fP=false
Record current kubectl command in the resource annotation.
.PP
\fB\-\-resource\-version\fP=""
If non\-empty, the annotation update will only succeed if this is the current resource\-version for the object. Only valid when specifying a single resource.

View File

@ -29,6 +29,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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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

@ -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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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.

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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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.

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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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.

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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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.

View File

@ -52,6 +52,10 @@ If \-\-resource\-version is specified, then updates will use this resource versi
\fB\-\-overwrite\fP=false
If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.
.PP
\fB\-\-record\fP=false
Record current kubectl command in the resource annotation.
.PP
\fB\-\-resource\-version\fP=""
If non\-empty, the labels update will only succeed if this is the current resource\-version for the object. Only valid when specifying a single resource.

View File

@ -36,6 +36,10 @@ Please refer to the models in
\fB\-p\fP, \fB\-\-patch\fP=""
The patch to be applied to the resource JSON file.
.PP
\fB\-\-record\fP=false
Record current kubectl command in the resource annotation.
.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP

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\-\-record\fP=false
Record current kubectl command in the resource annotation.
.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.

View File

@ -84,6 +84,10 @@ Creates a replication controller or job to manage the created container(s).
\fB\-\-port\fP=\-1
The port that this container exposes. If \-\-expose is true, this is also the port used by the service that is created.
.PP
\fB\-\-record\fP=false
Record current kubectl command in the resource annotation.
.PP
\fB\-r\fP, \fB\-\-replicas\fP=1
Number of replicas to create for this container. Default is 1.

View File

@ -35,6 +35,10 @@ scale is sent to the server.
\fB\-o\fP, \fB\-\-output\fP=""
Output mode. Use "\-o name" for shorter output (resource/name).
.PP
\fB\-\-record\fP=false
Record current kubectl command in the resource annotation.
.PP
\fB\-\-replicas\fP=\-1
The new desired number of replicas. Required.

View File

@ -88,6 +88,7 @@ $ kubectl annotate pods foo description-
-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).
--overwrite[=false]: If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.
--record[=false]: Record current kubectl command in the resource annotation.
--resource-version="": If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.
-l, --selector="": Selector (label query) to filter on
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
@ -127,7 +128,7 @@ $ kubectl annotate pods foo description-
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_annotate.md?pixel)]()

View File

@ -63,6 +63,7 @@ $ cat pod.json | kubectl apply -f -
```
-f, --filename=[]: Filename, directory, or URL to file that contains the configuration to apply
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
--record[=false]: Record current kubectl command in the resource annotation.
--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
```
@ -99,7 +100,7 @@ $ cat pod.json | kubectl apply -f -
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_apply.md?pixel)]()

View File

@ -71,6 +71,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).
--record[=false]: Record current kubectl command in the resource annotation.
--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.
@ -109,7 +110,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 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_autoscale.md?pixel)]()

View File

@ -62,6 +62,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).
--record[=false]: Record current kubectl command in the resource annotation.
--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
@ -101,7 +102,7 @@ $ cat pod.json | kubectl create -f -
* [kubectl create namespace](kubectl_create_namespace.md) - Create a namespace with the specified name.
* [kubectl create secret](kubectl_create_secret.md) - Create a secret using specified subcommand.
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create.md?pixel)]()

View File

@ -82,6 +82,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).
--record[=false]: Record current kubectl command in the resource annotation.
--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)
```
@ -118,7 +119,7 @@ kubectl edit (RESOURCE/NAME | -f FILENAME)
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_edit.md?pixel)]()

View File

@ -86,6 +86,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'.
--record[=false]: Record current kubectl command in the resource annotation.
--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'
@ -128,7 +129,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 on 10-Jan-2016
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_expose.md?pixel)]()

View File

@ -82,6 +82,7 @@ $ kubectl label pods foo bar-
-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).
--overwrite[=false]: If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.
--record[=false]: Record current kubectl command in the resource annotation.
--resource-version="": If non-empty, the labels update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.
-l, --selector="": Selector (label query) to filter on
-a, --show-all[=false]: When printing, show all resources (default hide terminated pods.)
@ -121,7 +122,7 @@ $ kubectl label pods foo bar-
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_label.md?pixel)]()

View File

@ -69,6 +69,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to update
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
-p, --patch="": The patch to be applied to the resource JSON file.
--record[=false]: Record current kubectl command in the resource annotation.
```
### Options inherited from parent commands
@ -103,7 +104,7 @@ kubectl patch pod valid-pod -p '{"spec":{"containers":[{"name":"kubernetes-serve
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_patch.md?pixel)]()

View File

@ -75,6 +75,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).
--record[=false]: Record current kubectl command in the resource annotation.
--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
@ -113,7 +114,7 @@ kubectl replace --force -f ./pod.json
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_replace.md?pixel)]()

View File

@ -99,6 +99,7 @@ $ kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'pri
--output-version="": Output the formatted object with the given version (default api-version).
--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=-1: The port that this container exposes. If --expose is true, this is also the port used by the service that is created.
--record[=false]: Record current kubectl command in the resource annotation.
-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, a job is created for this pod and --replicas must be 1. Default 'Always'
@ -145,7 +146,7 @@ $ kubectl run pi --image=perl --restart=OnFailure -- perl -Mbignum=bpi -wle 'pri
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 14-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_run.md?pixel)]()

View File

@ -75,6 +75,7 @@ $ kubectl scale --replicas=3 job/cron
--current-replicas=-1: Precondition for current size. Requires that the current size of the resource match this value in order to scale.
-f, --filename=[]: Filename, directory, or URL to a file identifying the resource to set a new size
-o, --output="": Output mode. Use "-o name" for shorter output (resource/name).
--record[=false]: Record current kubectl command in the resource annotation.
--replicas=-1: The new desired number of replicas. Required.
--resource-version="": Precondition for resource version. Requires that the current resource version match this value in order to scale.
--timeout=0: The length of time to wait before giving up on a scale operation, zero means don't wait.
@ -112,7 +113,7 @@ $ kubectl scale --replicas=3 job/cron
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
###### Auto generated by spf13/cobra on 8-Dec-2015
###### Auto generated by spf13/cobra on 22-Jan-2016
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_scale.md?pixel)]()

View File

@ -34,6 +34,7 @@ import (
unversioned_legacy "k8s.io/kubernetes/pkg/client/typed/generated/legacy/unversioned"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/framework"
"k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util"
deploymentutil "k8s.io/kubernetes/pkg/util/deployment"
@ -721,6 +722,12 @@ func (dc *DeploymentController) getNewRC(deployment extensions.Deployment, maxOl
Template: &newRCTemplate,
},
}
if _, ok := deployment.Annotations[kubectl.ChangeCauseAnnotation]; ok {
if newRC.Annotations == nil {
newRC.Annotations = make(map[string]string)
}
newRC.Annotations[kubectl.ChangeCauseAnnotation] = deployment.Annotations[kubectl.ChangeCauseAnnotation]
}
createdRC, err := dc.client.Legacy().ReplicationControllers(namespace).Create(&newRC)
if err != nil {
dc.rcExpectations.DeleteExpectations(dKey)

View File

@ -46,6 +46,9 @@ type AnnotateOptions struct {
all bool
resourceVersion string
changeCause string
recordFlag bool
f *cmdutil.Factory
out io.Writer
cmd *cobra.Command
@ -111,6 +114,7 @@ func NewCmdAnnotate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.resourceVersion, "resource-version", "", "If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")
usage := "Filename, directory, or URL to a file identifying the resource to update the annotation"
kubectl.AddJsonFilenameFlag(cmd, &options.filenames, usage)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -151,6 +155,9 @@ func (o *AnnotateOptions) Complete(f *cmdutil.Factory, out io.Writer, cmd *cobra
return err
}
o.recordFlag = cmdutil.GetRecordFlag(cmd)
o.changeCause = f.Command()
mapper, typer := f.Object()
o.builder = resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)).
ContinueOnError().
@ -199,6 +206,10 @@ func (o AnnotateOptions) RunAnnotate() error {
if err != nil {
return err
}
// If we should record change-cause, add it to new annotations
if cmdutil.ContainsChangeCause(info) || o.recordFlag {
o.newAnnotations[kubectl.ChangeCauseAnnotation] = o.changeCause
}
if err := o.updateAnnotations(obj); err != nil {
return err
}
@ -292,6 +303,10 @@ func validateAnnotations(removeAnnotations []string, newAnnotations map[string]s
func validateNoAnnotationOverwrites(meta *api.ObjectMeta, annotations map[string]string) error {
var buf bytes.Buffer
for key := range annotations {
// change-cause annotation can always be overwritten
if key == kubectl.ChangeCauseAnnotation {
continue
}
if value, found := meta.Annotations[key]; found {
if buf.Len() > 0 {
buf.WriteString("; ")

View File

@ -69,6 +69,7 @@ func NewCmdApply(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -132,6 +133,13 @@ func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *Ap
if err := kubectl.CreateApplyAnnotation(info, encoder); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
}
// Then create the resource and skip the three-way merge
if err := createAndRefresh(info); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
@ -166,6 +174,17 @@ func RunApply(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *Ap
return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err)
}
if cmdutil.ShouldRecord(cmd, info) {
patch, err = cmdutil.ChangeResourcePatch(info, f.Command())
if err != nil {
return err
}
_, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch)
if err != nil {
return cmdutil.AddSourceToErr(fmt.Sprintf("applying patch:\n%s\nto:\n%v\nfor:", patch, info), info.Source, err)
}
}
count++
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "configured")
return nil

View File

@ -64,6 +64,7 @@ func NewCmdAutoscale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "Filename, directory, or URL to a file identifying the resource to autoscale."
kubectl.AddJsonFilenameFlag(cmd, &filenames, usage)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -139,6 +140,12 @@ func RunAutoscale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
if err != nil {
return err
}
if cmdutil.ShouldRecord(cmd, hpa) {
if err := cmdutil.RecordChangeCause(hpa.Object, f.Command()); err != nil {
return err
}
object = hpa.Object
}
// TODO: extract this flag to a central location, when such a location exists.
if cmdutil.GetFlagBool(cmd, "dry-run") {
return f.PrintObject(cmd, object, out)

View File

@ -73,6 +73,7 @@ func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
// create subcommands
cmd.AddCommand(NewCmdCreateNamespace(f, out))
@ -120,6 +121,12 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
}
if err := createAndRefresh(info); err != nil {
return cmdutil.AddSourceToErr("creating", info.Source, err)
}

View File

@ -97,6 +97,7 @@ func NewCmdEdit(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().String("output-version", "", "Output the formatted object with the given version (default api-version).")
cmd.Flags().Bool("windows-line-endings", gruntime.GOOS == "windows", "Use Windows line-endings (default Unix line-endings)")
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -232,6 +233,12 @@ func RunEdit(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []strin
if err := kubectl.CreateOrUpdateAnnotation(cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag), updates, encoder); err != nil {
return preservedFile(err, file, out)
}
if cmdutil.ShouldRecord(cmd, updates) {
err = cmdutil.RecordChangeCause(updates.Object, f.Command())
if err != nil {
return err
}
}
// encode updates back to "edited" since we'll only generate patch from "edited"
if edited, err = runtime.Encode(encoder, updates.Object); err != nil {
return preservedFile(err, file, out)

View File

@ -95,6 +95,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)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -210,6 +211,12 @@ func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []str
if err != nil {
return err
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(object, f.Command()); err != nil {
return err
}
}
info.Refresh(object, true)
// TODO: extract this flag to a central location, when such a location exists.
if cmdutil.GetFlagBool(cmd, "dry-run") {
return f.PrintObject(cmd, object, out)

View File

@ -97,6 +97,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "Filename, directory, or URL to a file identifying the resource to update the labels"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
cmd.Flags().Bool("dry-run", false, "If true, only print the object that would be sent, without sending it.")
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -252,6 +253,11 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
if err := labelFunc(obj, overwrite, resourceVersion, lbls, remove); err != nil {
return err
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil {
return err
}
}
newData, err := json.Marshal(obj)
if err != nil {
return err

View File

@ -70,6 +70,7 @@ func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.")
cmd.MarkFlagRequired("patch")
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to update"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
@ -124,6 +125,16 @@ func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
if err != nil {
return err
}
if cmdutil.ShouldRecord(cmd, info) {
patchBytes, err = cmdutil.ChangeResourcePatch(info, f.Command())
if err != nil {
return err
}
_, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes)
if err != nil {
return err
}
}
cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched")
return nil
}

View File

@ -84,6 +84,7 @@ func NewCmdReplace(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.AddValidateFlags(cmd)
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -133,6 +134,12 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
return cmdutil.AddSourceToErr("replacing", info.Source, err)
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil {
return cmdutil.AddSourceToErr("replacing", info.Source, err)
}
}
// Serialize the object with the annotation applied.
obj, err := resource.NewHelper(info.Client, info.Mapping).Replace(info.Namespace, info.Name, true, info.Object)
if err != nil {
@ -220,6 +227,12 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
return err
}
if cmdutil.ShouldRecord(cmd, info) {
if err := cmdutil.RecordChangeCause(info.Object, f.Command()); err != nil {
return cmdutil.AddSourceToErr("replacing", info.Source, err)
}
}
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
if err != nil {
return err

View File

@ -83,6 +83,7 @@ func NewCmdRun(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *c
cmdutil.AddPrinterFlags(cmd)
addRunFlags(cmd)
cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
return cmd
}
@ -425,6 +426,15 @@ func createGeneratedObject(f *cmdutil.Factory, cmd *cobra.Command, generator kub
return nil, "", nil, nil, err
}
annotations, err := mapping.MetadataAccessor.Annotations(obj)
if err != nil {
return nil, "", nil, nil, err
}
if cmdutil.GetRecordFlag(cmd) || len(annotations[kubectl.ChangeCauseAnnotation]) > 0 {
if err := cmdutil.RecordChangeCause(obj, f.Command()); err != nil {
return nil, "", nil, nil, err
}
}
// TODO: extract this flag to a central location, when such a location exists.
if !cmdutil.GetFlagBool(cmd, "dry-run") {
resourceMapper := &resource.Mapper{

View File

@ -300,6 +300,7 @@ func TestGenerateService(t *testing.T) {
cmd := &cobra.Command{}
cmd.Flags().String("output", "", "")
cmd.Flags().Bool(cmdutil.ApplyAnnotationsFlag, false, "")
cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation.")
addRunFlags(cmd)
if !test.expectPOST {

View File

@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"
@ -82,6 +83,7 @@ func NewCmdScale(f *cmdutil.Factory, out io.Writer) *cobra.Command {
cmd.MarkFlagRequired("replicas")
cmd.Flags().Duration("timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait.")
cmdutil.AddOutputFlagsForMutation(cmd)
cmdutil.AddRecordFlag(cmd)
usage := "Filename, directory, or URL to a file identifying the resource to set a new size"
kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
@ -149,6 +151,24 @@ func RunScale(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
errs = append(errs, err)
continue
}
if cmdutil.ShouldRecord(cmd, info) {
patchBytes, err := cmdutil.ChangeResourcePatch(info, f.Command())
if err != nil {
errs = append(errs, err)
continue
}
mapping := info.ResourceMapping()
client, err := f.ClientForMapping(mapping)
if err != nil {
return err
}
helper := resource.NewHelper(client, mapping)
_, err = helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patchBytes)
if err != nil {
errs = append(errs, err)
continue
}
}
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "scaled")
}

View File

@ -27,6 +27,7 @@ import (
"os/user"
"path"
"strconv"
"strings"
"time"
"github.com/emicklei/go-restful/swagger"
@ -62,6 +63,7 @@ const (
type Factory struct {
clients *ClientCache
flags *pflag.FlagSet
cmd string
// Returns interfaces for dealing with arbitrary runtime.Objects.
Object func() (meta.RESTMapper, runtime.ObjectTyper)
@ -182,6 +184,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
return &Factory{
clients: clients,
flags: flags,
cmd: recordCommand(os.Args),
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
cfg, err := clientConfig.ClientConfig()
@ -472,6 +475,17 @@ func GetFirstPod(client *client.Client, namespace string, selector map[string]st
return pod, nil
}
func recordCommand(args []string) string {
if len(args) > 0 {
args[0] = "kubectl"
}
return strings.Join(args, " ")
}
func (f *Factory) Command() string {
return f.cmd
}
// BindFlags adds any flags that are common to all kubectl sub commands.
func (f *Factory) BindFlags(flags *pflag.FlagSet) {
// any flags defined by external projects (not part of pflags)

View File

@ -18,6 +18,7 @@ package util
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@ -27,6 +28,7 @@ import (
"strings"
"time"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
@ -34,6 +36,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/runtime"
utilerrors "k8s.io/kubernetes/pkg/util/errors"
"k8s.io/kubernetes/pkg/util/strategicpatch"
"github.com/evanphx/json-patch"
"github.com/golang/glog"
@ -434,3 +437,56 @@ func UpdateObject(info *resource.Info, codec runtime.Codec, updateFn func(runtim
return info.Object, nil
}
// AddCmdRecordFlag adds --record flag to command
func AddRecordFlag(cmd *cobra.Command) {
cmd.Flags().Bool("record", false, "Record current kubectl command in the resource annotation.")
}
func GetRecordFlag(cmd *cobra.Command) bool {
return GetFlagBool(cmd, "record")
}
// RecordChangeCause annotate change-cause to input runtime object.
func RecordChangeCause(obj runtime.Object, changeCause string) error {
meta, err := api.ObjectMetaFor(obj)
if err != nil {
return err
}
if meta.Annotations == nil {
meta.Annotations = make(map[string]string)
}
meta.Annotations[kubectl.ChangeCauseAnnotation] = changeCause
return nil
}
// ChangeResourcePatch creates a strategic merge patch between the origin input resource info
// and the annotated with change-cause input resource info.
func ChangeResourcePatch(info *resource.Info, changeCause string) ([]byte, error) {
oldData, err := json.Marshal(info.Object)
if err != nil {
return nil, err
}
if err := RecordChangeCause(info.Object, changeCause); err != nil {
return nil, err
}
newData, err := json.Marshal(info.Object)
if err != nil {
return nil, err
}
return strategicpatch.CreateTwoWayMergePatch(oldData, newData, info.Object)
}
// containsChangeCause checks if input resource info contains change-cause annotation.
func ContainsChangeCause(info *resource.Info) bool {
annotations, err := info.Mapping.MetadataAccessor.Annotations(info.Object)
if err != nil {
return false
}
return len(annotations[kubectl.ChangeCauseAnnotation]) > 0
}
// ShouldRecord checks if we should record current change cause
func ShouldRecord(cmd *cobra.Command, info *resource.Info) bool {
return GetRecordFlag(cmd) || ContainsChangeCause(info)
}