Merge pull request #33990 from asalkeld/local-option-label

Automatic merge from submit-queue

Add local option to the label command

**What this PR does / why we need it**:
Add the --local option to be both consistent with other commands and so it can be used with  "set selector" and "create service".

**Which issue this PR fixes** 
Related: #7296

**Special notes for your reviewer**:
None

**Release note**:
```release-note
Add a new option "--local" to the `kubectl label`
```
This commit is contained in:
Kubernetes Submit Queue 2016-10-05 06:32:13 -07:00 committed by GitHub
commit 776af8e7f6
3 changed files with 47 additions and 5 deletions

View File

@ -808,6 +808,16 @@ __EOF__
[ "$(EDITOR=cat kubectl edit --windows-line-endings pod/valid-pod | file - | grep CRLF)" ] [ "$(EDITOR=cat kubectl edit --windows-line-endings pod/valid-pod | file - | grep CRLF)" ]
[ ! "$(EDITOR=cat kubectl edit --windows-line-endings=false pod/valid-pod | file - | grep CRLF)" ] [ ! "$(EDITOR=cat kubectl edit --windows-line-endings=false pod/valid-pod | file - | grep CRLF)" ]
### Label POD YAML file locally without effecting the live pod.
# Pre-condition: name is valid-pod
kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
# Command
output_message=$(kubectl label --local --overwrite -f hack/testdata/pod.yaml name=localonlyvalue -o yaml "${kube_flags[@]}")
echo $output_message
# Post-condition: name is still valid-pod in the live pod, but command output is the new value
kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
kube::test::if_has_string "${output_message}" "localonlyvalue"
### Overwriting an existing label is not permitted ### Overwriting an existing label is not permitted
# Pre-condition: name is valid-pod # Pre-condition: name is valid-pod
kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod' kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'

View File

@ -93,6 +93,7 @@ func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
} }
cmdutil.AddPrinterFlags(cmd) cmdutil.AddPrinterFlags(cmd)
cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.") cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.")
cmd.Flags().Bool("local", false, "If true, label will NOT contact api-server but run locally.")
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types") cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types")
cmd.Flags().String("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.") cmd.Flags().String("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.")
@ -188,6 +189,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
all := cmdutil.GetFlagBool(cmd, "all") all := cmdutil.GetFlagBool(cmd, "all")
overwrite := cmdutil.GetFlagBool(cmd, "overwrite") overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version") resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
local := cmdutil.GetFlagBool(cmd, "local")
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
@ -203,11 +205,13 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
ContinueOnError(). ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace(). NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, options). FilenameParam(enforceNamespace, options).
SelectorParam(selector). Flatten()
ResourceTypeOrNameArgs(all, resources...).
Flatten().
Latest()
if !local {
b = b.SelectorParam(selector).
ResourceTypeOrNameArgs(all, resources...).
Latest()
}
one := false one := false
r := b.Do().IntoSingular(&one) r := b.Do().IntoSingular(&one)
if err := r.Err(); err != nil { if err := r.Err(); err != nil {
@ -227,7 +231,7 @@ func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
var outputObj runtime.Object var outputObj runtime.Object
dataChangeMsg := "not labeled" dataChangeMsg := "not labeled"
if cmdutil.GetDryRunFlag(cmd) { if cmdutil.GetDryRunFlag(cmd) || local {
err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove) err = labelFunc(info.Object, overwrite, resourceVersion, lbls, remove)
if err != nil { if err != nil {
return err return err

View File

@ -383,6 +383,34 @@ func TestLabelForResourceFromFile(t *testing.T) {
} }
} }
func TestLabelLocal(t *testing.T) {
f, tf, _, ns := NewAPIFactory()
tf.Client = &fake.RESTClient{
NegotiatedSerializer: ns,
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
t.Fatalf("unexpected request: %s %#v\n%#v", req.Method, req.URL, req)
return nil, nil
}),
}
tf.Namespace = "test"
tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}
buf := bytes.NewBuffer([]byte{})
cmd := NewCmdLabel(f, buf)
cmd.Flags().Set("local", "true")
options := &resource.FilenameOptions{
Filenames: []string{"../../../examples/storage/cassandra/cassandra-controller.yaml"},
}
err := RunLabel(f, buf, cmd, []string{"a=b"}, options)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !strings.Contains(buf.String(), "labeled") {
t.Errorf("did not set labels: %s", buf.String())
}
}
func TestLabelMultipleObjects(t *testing.T) { func TestLabelMultipleObjects(t *testing.T) {
pods, _, _ := testData() pods, _, _ := testData()
f, tf, codec, ns := NewAPIFactory() f, tf, codec, ns := NewAPIFactory()