k8s.io/client-go@v0.31.1/tools/auth/exec/exec_test.go (about) 1 /* 2 Copyright 2020 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 exec 18 19 import ( 20 "strings" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/runtime" 26 "k8s.io/apimachinery/pkg/runtime/schema" 27 clientauthenticationv1 "k8s.io/client-go/pkg/apis/clientauthentication/v1" 28 clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1" 29 "k8s.io/client-go/rest" 30 ) 31 32 // restInfo holds the rest.Client fields that we care about for test assertions. 33 type restInfo struct { 34 host string 35 tlsClientConfig rest.TLSClientConfig 36 proxyURL string 37 } 38 39 func TestLoadExecCredential(t *testing.T) { 40 t.Parallel() 41 42 tests := []struct { 43 name string 44 data []byte 45 wantExecCredential runtime.Object 46 wantRESTInfo restInfo 47 wantErrorPrefix string 48 }{ 49 { 50 name: "v1 happy path", 51 data: marshal(t, clientauthenticationv1.SchemeGroupVersion, &clientauthenticationv1.ExecCredential{ 52 Spec: clientauthenticationv1.ExecCredentialSpec{ 53 Cluster: &clientauthenticationv1.Cluster{ 54 Server: "https://some-server/some/path", 55 TLSServerName: "some-server-name", 56 InsecureSkipTLSVerify: true, 57 CertificateAuthorityData: []byte("some-ca-data"), 58 ProxyURL: "https://some-proxy-url:12345", 59 Config: runtime.RawExtension{ 60 Raw: []byte(`{"apiVersion":"group/v1","kind":"PluginConfig","spec":{"names":["marshmallow","zelda"]}}`), 61 }, 62 }, 63 }, 64 }), 65 wantExecCredential: &clientauthenticationv1.ExecCredential{ 66 TypeMeta: metav1.TypeMeta{ 67 Kind: "ExecCredential", 68 APIVersion: clientauthenticationv1.SchemeGroupVersion.String(), 69 }, 70 Spec: clientauthenticationv1.ExecCredentialSpec{ 71 Cluster: &clientauthenticationv1.Cluster{ 72 Server: "https://some-server/some/path", 73 TLSServerName: "some-server-name", 74 InsecureSkipTLSVerify: true, 75 CertificateAuthorityData: []byte("some-ca-data"), 76 ProxyURL: "https://some-proxy-url:12345", 77 Config: runtime.RawExtension{ 78 Raw: []byte(`{"apiVersion":"group/v1","kind":"PluginConfig","spec":{"names":["marshmallow","zelda"]}}`), 79 }, 80 }, 81 }, 82 }, 83 wantRESTInfo: restInfo{ 84 host: "https://some-server/some/path", 85 tlsClientConfig: rest.TLSClientConfig{ 86 Insecure: true, 87 ServerName: "some-server-name", 88 CAData: []byte("some-ca-data"), 89 }, 90 proxyURL: "https://some-proxy-url:12345", 91 }, 92 }, 93 { 94 name: "v1beta1 happy path", 95 data: marshal(t, clientauthenticationv1beta1.SchemeGroupVersion, &clientauthenticationv1beta1.ExecCredential{ 96 Spec: clientauthenticationv1beta1.ExecCredentialSpec{ 97 Cluster: &clientauthenticationv1beta1.Cluster{ 98 Server: "https://some-server/some/path", 99 TLSServerName: "some-server-name", 100 InsecureSkipTLSVerify: true, 101 CertificateAuthorityData: []byte("some-ca-data"), 102 ProxyURL: "https://some-proxy-url:12345", 103 Config: runtime.RawExtension{ 104 Raw: []byte(`{"apiVersion":"group/v1","kind":"PluginConfig","spec":{"names":["marshmallow","zelda"]}}`), 105 }, 106 }, 107 }, 108 }), 109 wantExecCredential: &clientauthenticationv1beta1.ExecCredential{ 110 TypeMeta: metav1.TypeMeta{ 111 Kind: "ExecCredential", 112 APIVersion: clientauthenticationv1beta1.SchemeGroupVersion.String(), 113 }, 114 Spec: clientauthenticationv1beta1.ExecCredentialSpec{ 115 Cluster: &clientauthenticationv1beta1.Cluster{ 116 Server: "https://some-server/some/path", 117 TLSServerName: "some-server-name", 118 InsecureSkipTLSVerify: true, 119 CertificateAuthorityData: []byte("some-ca-data"), 120 ProxyURL: "https://some-proxy-url:12345", 121 Config: runtime.RawExtension{ 122 Raw: []byte(`{"apiVersion":"group/v1","kind":"PluginConfig","spec":{"names":["marshmallow","zelda"]}}`), 123 }, 124 }, 125 }, 126 }, 127 wantRESTInfo: restInfo{ 128 host: "https://some-server/some/path", 129 tlsClientConfig: rest.TLSClientConfig{ 130 Insecure: true, 131 ServerName: "some-server-name", 132 CAData: []byte("some-ca-data"), 133 }, 134 proxyURL: "https://some-proxy-url:12345", 135 }, 136 }, 137 { 138 name: "v1 nil config", 139 data: marshal(t, clientauthenticationv1.SchemeGroupVersion, &clientauthenticationv1.ExecCredential{ 140 Spec: clientauthenticationv1.ExecCredentialSpec{ 141 Cluster: &clientauthenticationv1.Cluster{ 142 Server: "https://some-server/some/path", 143 TLSServerName: "some-server-name", 144 InsecureSkipTLSVerify: true, 145 CertificateAuthorityData: []byte("some-ca-data"), 146 ProxyURL: "https://some-proxy-url:12345", 147 }, 148 }, 149 }), 150 wantExecCredential: &clientauthenticationv1.ExecCredential{ 151 TypeMeta: metav1.TypeMeta{ 152 Kind: "ExecCredential", 153 APIVersion: clientauthenticationv1.SchemeGroupVersion.String(), 154 }, 155 Spec: clientauthenticationv1.ExecCredentialSpec{ 156 Cluster: &clientauthenticationv1.Cluster{ 157 Server: "https://some-server/some/path", 158 TLSServerName: "some-server-name", 159 InsecureSkipTLSVerify: true, 160 CertificateAuthorityData: []byte("some-ca-data"), 161 ProxyURL: "https://some-proxy-url:12345", 162 }, 163 }, 164 }, 165 wantRESTInfo: restInfo{ 166 host: "https://some-server/some/path", 167 tlsClientConfig: rest.TLSClientConfig{ 168 Insecure: true, 169 ServerName: "some-server-name", 170 CAData: []byte("some-ca-data"), 171 }, 172 proxyURL: "https://some-proxy-url:12345", 173 }, 174 }, 175 { 176 name: "v1beta1 nil config", 177 data: marshal(t, clientauthenticationv1beta1.SchemeGroupVersion, &clientauthenticationv1beta1.ExecCredential{ 178 Spec: clientauthenticationv1beta1.ExecCredentialSpec{ 179 Cluster: &clientauthenticationv1beta1.Cluster{ 180 Server: "https://some-server/some/path", 181 TLSServerName: "some-server-name", 182 InsecureSkipTLSVerify: true, 183 CertificateAuthorityData: []byte("some-ca-data"), 184 ProxyURL: "https://some-proxy-url:12345", 185 }, 186 }, 187 }), 188 wantExecCredential: &clientauthenticationv1beta1.ExecCredential{ 189 TypeMeta: metav1.TypeMeta{ 190 Kind: "ExecCredential", 191 APIVersion: clientauthenticationv1beta1.SchemeGroupVersion.String(), 192 }, 193 Spec: clientauthenticationv1beta1.ExecCredentialSpec{ 194 Cluster: &clientauthenticationv1beta1.Cluster{ 195 Server: "https://some-server/some/path", 196 TLSServerName: "some-server-name", 197 InsecureSkipTLSVerify: true, 198 CertificateAuthorityData: []byte("some-ca-data"), 199 ProxyURL: "https://some-proxy-url:12345", 200 }, 201 }, 202 }, 203 wantRESTInfo: restInfo{ 204 host: "https://some-server/some/path", 205 tlsClientConfig: rest.TLSClientConfig{ 206 Insecure: true, 207 ServerName: "some-server-name", 208 CAData: []byte("some-ca-data"), 209 }, 210 proxyURL: "https://some-proxy-url:12345", 211 }, 212 }, 213 { 214 name: "v1 invalid cluster", 215 data: marshal(t, clientauthenticationv1.SchemeGroupVersion, &clientauthenticationv1.ExecCredential{ 216 Spec: clientauthenticationv1.ExecCredentialSpec{ 217 Cluster: &clientauthenticationv1.Cluster{ 218 ProxyURL: "invalid- url\n", 219 }, 220 }, 221 }), 222 wantErrorPrefix: "cannot create rest.Config", 223 }, 224 { 225 name: "v1beta1 invalid cluster", 226 data: marshal(t, clientauthenticationv1beta1.SchemeGroupVersion, &clientauthenticationv1beta1.ExecCredential{ 227 Spec: clientauthenticationv1beta1.ExecCredentialSpec{ 228 Cluster: &clientauthenticationv1beta1.Cluster{ 229 ProxyURL: "invalid- url\n", 230 }, 231 }, 232 }), 233 wantErrorPrefix: "cannot create rest.Config", 234 }, 235 { 236 name: "v1 nil cluster", 237 data: marshal(t, clientauthenticationv1.SchemeGroupVersion, &clientauthenticationv1.ExecCredential{}), 238 wantErrorPrefix: "ExecCredential does not contain cluster information", 239 }, 240 { 241 name: "v1beta1 nil cluster", 242 data: marshal(t, clientauthenticationv1beta1.SchemeGroupVersion, &clientauthenticationv1beta1.ExecCredential{}), 243 wantErrorPrefix: "ExecCredential does not contain cluster information", 244 }, 245 { 246 name: "invalid object kind", 247 data: marshal(t, metav1.SchemeGroupVersion, &metav1.Status{}), 248 wantErrorPrefix: "invalid group/kind: wanted ExecCredential.client.authentication.k8s.io, got Status", 249 }, 250 { 251 name: "bad data", 252 data: []byte("bad data"), 253 wantErrorPrefix: "decode: ", 254 }, 255 } 256 for _, test := range tests { 257 test := test 258 t.Run(test.name, func(t *testing.T) { 259 t.Parallel() 260 261 execCredential, restConfig, err := LoadExecCredential(test.data) 262 if test.wantErrorPrefix != "" { 263 if err == nil { 264 t.Error("wanted error, got success") 265 } else if !strings.HasPrefix(err.Error(), test.wantErrorPrefix) { 266 t.Errorf("wanted '%s', got '%s'", test.wantErrorPrefix, err.Error()) 267 } 268 } else if err != nil { 269 t.Error(err) 270 } else { 271 if diff := cmp.Diff(test.wantExecCredential, execCredential); diff != "" { 272 t.Error(diff) 273 } 274 275 if diff := cmp.Diff(test.wantRESTInfo.host, restConfig.Host); diff != "" { 276 t.Error(diff) 277 } 278 if diff := cmp.Diff(test.wantRESTInfo.tlsClientConfig, restConfig.TLSClientConfig); diff != "" { 279 t.Error(diff) 280 } 281 282 proxyURL, err := restConfig.Proxy(nil) 283 if err != nil { 284 t.Fatal(err) 285 } 286 if diff := cmp.Diff(test.wantRESTInfo.proxyURL, proxyURL.String()); diff != "" { 287 t.Error(diff) 288 } 289 } 290 }) 291 } 292 } 293 294 func marshal(t *testing.T, gv schema.GroupVersion, obj runtime.Object) []byte { 295 t.Helper() 296 297 data, err := runtime.Encode(codecs.LegacyCodec(gv), obj) 298 if err != nil { 299 t.Fatal(err) 300 } 301 302 return data 303 }