...

Source file src/k8s.io/kubectl/pkg/cmd/create/create_service_test.go

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

     1  /*
     2  Copyright 2016 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 create
    18  
    19  import (
    20  	"testing"
    21  
    22  	restclient "k8s.io/client-go/rest"
    23  	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
    24  
    25  	v1 "k8s.io/api/core/v1"
    26  	apiequality "k8s.io/apimachinery/pkg/api/equality"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/util/intstr"
    29  	"k8s.io/cli-runtime/pkg/genericiooptions"
    30  )
    31  
    32  func TestCreateServices(t *testing.T) {
    33  
    34  	tests := []struct {
    35  		name         string
    36  		serviceType  v1.ServiceType
    37  		tcp          []string
    38  		clusterip    string
    39  		externalName string
    40  		nodeport     int
    41  		expected     *v1.Service
    42  		expectErr    bool
    43  	}{
    44  		{
    45  			name:        "clusterip-ok",
    46  			tcp:         []string{"456", "321:908"},
    47  			clusterip:   "",
    48  			serviceType: v1.ServiceTypeClusterIP,
    49  			expected: &v1.Service{
    50  				ObjectMeta: metav1.ObjectMeta{
    51  					Name:   "clusterip-ok",
    52  					Labels: map[string]string{"app": "clusterip-ok"},
    53  				},
    54  				Spec: v1.ServiceSpec{Type: "ClusterIP",
    55  					Ports: []v1.ServicePort{{Name: "456", Protocol: "TCP", Port: 456, TargetPort: intstr.IntOrString{Type: 0, IntVal: 456, StrVal: ""}, NodePort: 0},
    56  						{Name: "321-908", Protocol: "TCP", Port: 321, TargetPort: intstr.IntOrString{Type: 0, IntVal: 908, StrVal: ""}, NodePort: 0}},
    57  					Selector:  map[string]string{"app": "clusterip-ok"},
    58  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: ""},
    59  			},
    60  			expectErr: false,
    61  		},
    62  		{
    63  			name:        "clusterip-missing",
    64  			serviceType: v1.ServiceTypeClusterIP,
    65  			expectErr:   true,
    66  		},
    67  		{
    68  			name:        "clusterip-none-wrong-type",
    69  			tcp:         []string{},
    70  			clusterip:   "None",
    71  			serviceType: v1.ServiceTypeNodePort,
    72  			expectErr:   true,
    73  		},
    74  		{
    75  			name:        "clusterip-none-ok",
    76  			tcp:         []string{},
    77  			clusterip:   "None",
    78  			serviceType: v1.ServiceTypeClusterIP,
    79  			expected: &v1.Service{
    80  				ObjectMeta: metav1.ObjectMeta{
    81  					Name:   "clusterip-none-ok",
    82  					Labels: map[string]string{"app": "clusterip-none-ok"},
    83  				},
    84  				Spec: v1.ServiceSpec{Type: "ClusterIP",
    85  					Ports:     []v1.ServicePort{},
    86  					Selector:  map[string]string{"app": "clusterip-none-ok"},
    87  					ClusterIP: "None", ExternalIPs: []string(nil), LoadBalancerIP: ""},
    88  			},
    89  			expectErr: false,
    90  		},
    91  		{
    92  			name:        "clusterip-none-and-port-mapping",
    93  			tcp:         []string{"456:9898"},
    94  			clusterip:   "None",
    95  			serviceType: v1.ServiceTypeClusterIP,
    96  			expected: &v1.Service{
    97  				ObjectMeta: metav1.ObjectMeta{
    98  					Name:   "clusterip-none-and-port-mapping",
    99  					Labels: map[string]string{"app": "clusterip-none-and-port-mapping"},
   100  				},
   101  				Spec: v1.ServiceSpec{Type: "ClusterIP",
   102  					Ports:     []v1.ServicePort{{Name: "456-9898", Protocol: "TCP", Port: 456, TargetPort: intstr.IntOrString{Type: 0, IntVal: 9898, StrVal: ""}, NodePort: 0}},
   103  					Selector:  map[string]string{"app": "clusterip-none-and-port-mapping"},
   104  					ClusterIP: "None", ExternalIPs: []string(nil), LoadBalancerIP: ""},
   105  			},
   106  			expectErr: false,
   107  		},
   108  		{
   109  			name:        "loadbalancer-ok",
   110  			tcp:         []string{"456:9898"},
   111  			clusterip:   "",
   112  			serviceType: v1.ServiceTypeLoadBalancer,
   113  			expected: &v1.Service{
   114  				ObjectMeta: metav1.ObjectMeta{
   115  					Name:   "loadbalancer-ok",
   116  					Labels: map[string]string{"app": "loadbalancer-ok"},
   117  				},
   118  				Spec: v1.ServiceSpec{Type: "LoadBalancer",
   119  					Ports:     []v1.ServicePort{{Name: "456-9898", Protocol: "TCP", Port: 456, TargetPort: intstr.IntOrString{Type: 0, IntVal: 9898, StrVal: ""}, NodePort: 0}},
   120  					Selector:  map[string]string{"app": "loadbalancer-ok"},
   121  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: ""},
   122  			},
   123  			expectErr: false,
   124  		},
   125  		{
   126  			name:        "invalid-port",
   127  			tcp:         []string{"65536"},
   128  			clusterip:   "None",
   129  			serviceType: v1.ServiceTypeClusterIP,
   130  			expectErr:   true,
   131  		},
   132  		{
   133  			name:        "invalid-port-mapping",
   134  			tcp:         []string{"8080:-abc"},
   135  			clusterip:   "None",
   136  			serviceType: v1.ServiceTypeClusterIP,
   137  			expectErr:   true,
   138  		},
   139  		{
   140  			expectErr: true,
   141  		},
   142  		{
   143  			name:        "validate-ok",
   144  			serviceType: v1.ServiceTypeClusterIP,
   145  			tcp:         []string{"123", "234:1234"},
   146  			clusterip:   "",
   147  			expected: &v1.Service{
   148  				ObjectMeta: metav1.ObjectMeta{
   149  					Name:   "validate-ok",
   150  					Labels: map[string]string{"app": "validate-ok"},
   151  				},
   152  				Spec: v1.ServiceSpec{Type: "ClusterIP",
   153  					Ports: []v1.ServicePort{
   154  						{Name: "123", Protocol: "TCP", Port: 123, TargetPort: intstr.IntOrString{Type: 0, IntVal: 123, StrVal: ""}, NodePort: 0},
   155  						{Name: "234-1234", Protocol: "TCP", Port: 234, TargetPort: intstr.IntOrString{Type: 0, IntVal: 1234, StrVal: ""}, NodePort: 0},
   156  					},
   157  					Selector:  map[string]string{"app": "validate-ok"},
   158  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: ""},
   159  			},
   160  			expectErr: false,
   161  		},
   162  		{
   163  			name:        "invalid-ClusterIPNone",
   164  			serviceType: v1.ServiceTypeNodePort,
   165  			tcp:         []string{"123", "234:1234"},
   166  			clusterip:   v1.ClusterIPNone,
   167  			expectErr:   true,
   168  		},
   169  		{
   170  			name:        "TCP-none",
   171  			serviceType: v1.ServiceTypeClusterIP,
   172  			clusterip:   "",
   173  			expectErr:   true,
   174  		},
   175  		{
   176  			name:         "invalid-ExternalName",
   177  			serviceType:  v1.ServiceTypeExternalName,
   178  			tcp:          []string{"123", "234:1234"},
   179  			clusterip:    "",
   180  			externalName: "@oi:test",
   181  			expectErr:    true,
   182  		},
   183  		{
   184  			name:         "externalName-ok",
   185  			serviceType:  v1.ServiceTypeExternalName,
   186  			tcp:          []string{"123", "234:1234"},
   187  			clusterip:    "",
   188  			externalName: "www.externalname.com",
   189  			expected: &v1.Service{
   190  				ObjectMeta: metav1.ObjectMeta{
   191  					Name:   "externalName-ok",
   192  					Labels: map[string]string{"app": "externalName-ok"},
   193  				},
   194  				Spec: v1.ServiceSpec{Type: "ExternalName",
   195  					Ports: []v1.ServicePort{
   196  						{Name: "123", Protocol: "TCP", Port: 123, TargetPort: intstr.IntOrString{Type: 0, IntVal: 123, StrVal: ""}, NodePort: 0},
   197  						{Name: "234-1234", Protocol: "TCP", Port: 234, TargetPort: intstr.IntOrString{Type: 0, IntVal: 1234, StrVal: ""}, NodePort: 0},
   198  					},
   199  					Selector:  map[string]string{"app": "externalName-ok"},
   200  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: "", ExternalName: "www.externalname.com"},
   201  			},
   202  			expectErr: false,
   203  		},
   204  		{
   205  			name:        "my-node-port-service-ok",
   206  			serviceType: v1.ServiceTypeNodePort,
   207  			tcp:         []string{"443:https", "30000:8000"},
   208  			clusterip:   "",
   209  			expected: &v1.Service{
   210  				ObjectMeta: metav1.ObjectMeta{
   211  					Name:   "my-node-port-service-ok",
   212  					Labels: map[string]string{"app": "my-node-port-service-ok"},
   213  				},
   214  				Spec: v1.ServiceSpec{Type: "NodePort",
   215  					Ports: []v1.ServicePort{
   216  						{Name: "443-https", Protocol: "TCP", Port: 443, TargetPort: intstr.IntOrString{Type: 1, IntVal: 0, StrVal: "https"}, NodePort: 0},
   217  						{Name: "30000-8000", Protocol: "TCP", Port: 30000, TargetPort: intstr.IntOrString{Type: 0, IntVal: 8000, StrVal: ""}, NodePort: 0},
   218  					},
   219  					Selector:  map[string]string{"app": "my-node-port-service-ok"},
   220  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: ""},
   221  			},
   222  			expectErr: false,
   223  		},
   224  		{
   225  			name:        "my-node-port-service-ok2",
   226  			serviceType: v1.ServiceTypeNodePort,
   227  			tcp:         []string{"80:http"},
   228  			clusterip:   "",
   229  			nodeport:    4444,
   230  			expected: &v1.Service{
   231  				ObjectMeta: metav1.ObjectMeta{
   232  					Name:   "my-node-port-service-ok2",
   233  					Labels: map[string]string{"app": "my-node-port-service-ok2"},
   234  				},
   235  				Spec: v1.ServiceSpec{Type: "NodePort",
   236  					Ports: []v1.ServicePort{
   237  						{Name: "80-http", Protocol: "TCP", Port: 80, TargetPort: intstr.IntOrString{Type: 1, IntVal: 0, StrVal: "http"}, NodePort: 4444},
   238  					},
   239  					Selector:  map[string]string{"app": "my-node-port-service-ok2"},
   240  					ClusterIP: "", ExternalIPs: []string(nil), LoadBalancerIP: ""},
   241  			},
   242  			expectErr: false,
   243  		},
   244  	}
   245  	for _, tc := range tests {
   246  		t.Run(tc.name, func(t *testing.T) {
   247  			options := ServiceOptions{
   248  				Name:         tc.name,
   249  				Type:         tc.serviceType,
   250  				TCP:          tc.tcp,
   251  				ClusterIP:    tc.clusterip,
   252  				NodePort:     tc.nodeport,
   253  				ExternalName: tc.externalName,
   254  			}
   255  
   256  			var service *v1.Service
   257  
   258  			err := options.Validate()
   259  			if err == nil {
   260  				service, err = options.createService()
   261  			}
   262  			if tc.expectErr && err == nil {
   263  				t.Errorf("%s: expected an error, but createService passes.", tc.name)
   264  			}
   265  			if !tc.expectErr && err != nil {
   266  				t.Errorf("%s: unexpected error: %v", tc.name, err)
   267  			}
   268  			if !apiequality.Semantic.DeepEqual(service, tc.expected) {
   269  				t.Errorf("%s: expected:\n%#v\ngot:\n%#v", tc.name, tc.expected, service)
   270  			}
   271  		})
   272  	}
   273  }
   274  
   275  func TestCreateServiceWithNamespace(t *testing.T) {
   276  	svcName := "test-service"
   277  	ns := "test"
   278  	tf := cmdtesting.NewTestFactory().WithNamespace(ns)
   279  	defer tf.Cleanup()
   280  
   281  	tf.ClientConfigVal = &restclient.Config{}
   282  
   283  	ioStreams, _, buf, _ := genericiooptions.NewTestIOStreams()
   284  	cmd := NewCmdCreateServiceClusterIP(tf, ioStreams)
   285  	cmd.Flags().Set("dry-run", "client")
   286  	cmd.Flags().Set("output", "jsonpath={.metadata.namespace}")
   287  	cmd.Flags().Set("clusterip", "None")
   288  	cmd.Run(cmd, []string{svcName})
   289  	if buf.String() != ns {
   290  		t.Errorf("expected output: %s, but got: %s", ns, buf.String())
   291  	}
   292  }
   293  

View as plain text