...

Source file src/k8s.io/kubectl/pkg/cmd/replace/replace_test.go

Documentation: k8s.io/kubectl/pkg/cmd/replace

     1  /*
     2  Copyright 2015 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package replace
    18  
    19  import (
    20  	"net/http"
    21  	"strings"
    22  	"testing"
    23  
    24  	corev1 "k8s.io/api/core/v1"
    25  	"k8s.io/cli-runtime/pkg/genericiooptions"
    26  	"k8s.io/cli-runtime/pkg/resource"
    27  	"k8s.io/client-go/rest/fake"
    28  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    29  	"k8s.io/kubectl/pkg/scheme"
    30  )
    31  
    32  func TestReplaceObject(t *testing.T) {
    33  	_, _, rc := cmdtesting.TestData()
    34  
    35  	tf := cmdtesting.NewTestFactory().WithNamespace("test")
    36  	defer tf.Cleanup()
    37  	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
    38  
    39  	deleted := false
    40  	tf.UnstructuredClient = &fake.RESTClient{
    41  		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
    42  		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
    43  			switch p, m := req.URL.Path, req.Method; {
    44  			case p == "/api/v1/namespaces/test" && m == http.MethodGet:
    45  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
    46  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
    47  				deleted = true
    48  				fallthrough
    49  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
    50  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
    51  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
    52  				statusCode := http.StatusOK
    53  				if deleted {
    54  					statusCode = http.StatusNotFound
    55  				}
    56  				return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
    57  			case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
    58  				return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
    59  			default:
    60  				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
    61  				return nil, nil
    62  			}
    63  		}),
    64  	}
    65  	streams, _, buf, _ := genericiooptions.NewTestIOStreams()
    66  
    67  	cmd := NewCmdReplace(tf, streams)
    68  	cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
    69  	cmd.Flags().Set("output", "name")
    70  	cmd.Run(cmd, []string{})
    71  
    72  	// uses the name from the file, not the response
    73  	if buf.String() != "replicationcontroller/rc1\n" {
    74  		t.Errorf("unexpected output: %s", buf.String())
    75  	}
    76  
    77  	buf.Reset()
    78  	cmd.Flags().Set("force", "true")
    79  	cmd.Flags().Set("cascade", "false")
    80  	cmd.Flags().Set("output", "name")
    81  	cmd.Run(cmd, []string{})
    82  
    83  	if buf.String() != "replicationcontroller/redis-master\nreplicationcontroller/rc1\n" {
    84  		t.Errorf("unexpected output: %s", buf.String())
    85  	}
    86  }
    87  
    88  func TestReplaceMultipleObject(t *testing.T) {
    89  	_, svc, rc := cmdtesting.TestData()
    90  
    91  	tf := cmdtesting.NewTestFactory().WithNamespace("test")
    92  	defer tf.Cleanup()
    93  	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
    94  
    95  	redisMasterDeleted := false
    96  	frontendDeleted := false
    97  	tf.UnstructuredClient = &fake.RESTClient{
    98  		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
    99  		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
   100  			switch p, m := req.URL.Path, req.Method; {
   101  			case p == "/api/v1/namespaces/test" && m == http.MethodGet:
   102  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
   103  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
   104  				redisMasterDeleted = true
   105  				fallthrough
   106  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
   107  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   108  			case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
   109  				statusCode := http.StatusOK
   110  				if redisMasterDeleted {
   111  					statusCode = http.StatusNotFound
   112  				}
   113  				return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   114  			case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
   115  				return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   116  			case p == "/namespaces/test/services/frontend" && m == http.MethodDelete:
   117  				frontendDeleted = true
   118  				fallthrough
   119  			case p == "/namespaces/test/services/frontend" && m == http.MethodPut:
   120  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
   121  			case p == "/namespaces/test/services/frontend" && m == http.MethodGet:
   122  				statusCode := http.StatusOK
   123  				if frontendDeleted {
   124  					statusCode = http.StatusNotFound
   125  				}
   126  				return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
   127  			case p == "/namespaces/test/services" && m == http.MethodPost:
   128  				return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
   129  			default:
   130  				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
   131  				return nil, nil
   132  			}
   133  		}),
   134  	}
   135  	streams, _, buf, _ := genericiooptions.NewTestIOStreams()
   136  
   137  	cmd := NewCmdReplace(tf, streams)
   138  	cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
   139  	cmd.Flags().Set("filename", "../../../testdata/frontend-service.yaml")
   140  	cmd.Flags().Set("output", "name")
   141  	cmd.Run(cmd, []string{})
   142  
   143  	if buf.String() != "replicationcontroller/rc1\nservice/baz\n" {
   144  		t.Errorf("unexpected output: %s", buf.String())
   145  	}
   146  
   147  	buf.Reset()
   148  	cmd.Flags().Set("force", "true")
   149  	cmd.Flags().Set("cascade", "false")
   150  	cmd.Flags().Set("output", "name")
   151  	cmd.Run(cmd, []string{})
   152  
   153  	if buf.String() != "replicationcontroller/redis-master\nservice/frontend\nreplicationcontroller/rc1\nservice/baz\n" {
   154  		t.Errorf("unexpected output: %s", buf.String())
   155  	}
   156  }
   157  
   158  func TestReplaceDirectory(t *testing.T) {
   159  	_, _, rc := cmdtesting.TestData()
   160  
   161  	tf := cmdtesting.NewTestFactory().WithNamespace("test")
   162  	defer tf.Cleanup()
   163  	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
   164  
   165  	created := map[string]bool{}
   166  	tf.UnstructuredClient = &fake.RESTClient{
   167  		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
   168  		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
   169  			switch p, m := req.URL.Path, req.Method; {
   170  			case p == "/api/v1/namespaces/test" && m == http.MethodGet:
   171  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
   172  			case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodPut:
   173  				created[p] = true
   174  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   175  			case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodGet:
   176  				statusCode := http.StatusNotFound
   177  				if created[p] {
   178  					statusCode = http.StatusOK
   179  				}
   180  				return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   181  			case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodDelete:
   182  				delete(created, p)
   183  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   184  			case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers") && m == http.MethodPost:
   185  				return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   186  			default:
   187  				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
   188  				return nil, nil
   189  			}
   190  		}),
   191  	}
   192  	streams, _, buf, _ := genericiooptions.NewTestIOStreams()
   193  
   194  	cmd := NewCmdReplace(tf, streams)
   195  	cmd.Flags().Set("filename", "../../../testdata/replace/legacy")
   196  	cmd.Flags().Set("namespace", "test")
   197  	cmd.Flags().Set("output", "name")
   198  	cmd.Run(cmd, []string{})
   199  
   200  	if buf.String() != "replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" {
   201  		t.Errorf("unexpected output: %s", buf.String())
   202  	}
   203  
   204  	buf.Reset()
   205  	cmd.Flags().Set("force", "true")
   206  	cmd.Flags().Set("cascade", "false")
   207  	cmd.Run(cmd, []string{})
   208  
   209  	if buf.String() != "replicationcontroller/frontend\nreplicationcontroller/redis-master\nreplicationcontroller/redis-slave\n"+
   210  		"replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" {
   211  		t.Errorf("unexpected output: %s", buf.String())
   212  	}
   213  }
   214  
   215  func TestForceReplaceObjectNotFound(t *testing.T) {
   216  	_, _, rc := cmdtesting.TestData()
   217  
   218  	tf := cmdtesting.NewTestFactory().WithNamespace("test")
   219  	defer tf.Cleanup()
   220  	codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
   221  
   222  	tf.UnstructuredClient = &fake.RESTClient{
   223  		NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
   224  		Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
   225  			switch p, m := req.URL.Path, req.Method; {
   226  			case p == "/api/v1/namespaces/test" && m == http.MethodGet:
   227  				return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
   228  			case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == http.MethodGet || m == http.MethodDelete):
   229  				return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
   230  			case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
   231  				return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
   232  			default:
   233  				t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
   234  				return nil, nil
   235  			}
   236  		}),
   237  	}
   238  	streams, _, buf, _ := genericiooptions.NewTestIOStreams()
   239  
   240  	cmd := NewCmdReplace(tf, streams)
   241  	cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
   242  	cmd.Flags().Set("force", "true")
   243  	cmd.Flags().Set("cascade", "false")
   244  	cmd.Flags().Set("output", "name")
   245  	cmd.Run(cmd, []string{})
   246  
   247  	if buf.String() != "replicationcontroller/rc1\n" {
   248  		t.Errorf("unexpected output: %s", buf.String())
   249  	}
   250  }
   251  

View as plain text