1/* 2Copyright 2017 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package openstack 18 19import ( 20 "math/rand" 21 "net/http" 22 "testing" 23 "time" 24) 25 26// testTokenGetter is a simple random token getter. 27type testTokenGetter struct{} 28 29const LetterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 30 31func RandStringBytes(n int) string { 32 b := make([]byte, n) 33 for i := range b { 34 b[i] = LetterBytes[rand.Intn(len(LetterBytes))] 35 } 36 return string(b) 37} 38 39func (*testTokenGetter) Token() (string, error) { 40 return RandStringBytes(32), nil 41} 42 43// testRoundTripper is mocked roundtripper which responds with unauthorized when 44// there is no authorization header, otherwise returns status ok. 45type testRoundTripper struct{} 46 47func (trt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { 48 authHeader := req.Header.Get("Authorization") 49 if authHeader == "" || authHeader == "Bearer " { 50 return &http.Response{ 51 StatusCode: http.StatusUnauthorized, 52 }, nil 53 } 54 return &http.Response{StatusCode: http.StatusOK}, nil 55} 56 57func TestOpenstackAuthProvider(t *testing.T) { 58 trt := &tokenRoundTripper{ 59 RoundTripper: &testRoundTripper{}, 60 } 61 62 tests := []struct { 63 name string 64 ttl time.Duration 65 interval time.Duration 66 same bool 67 }{ 68 { 69 name: "normal", 70 ttl: 2 * time.Second, 71 interval: 1 * time.Second, 72 same: true, 73 }, 74 { 75 name: "expire", 76 ttl: 1 * time.Second, 77 interval: 2 * time.Second, 78 same: false, 79 }, 80 } 81 82 for _, test := range tests { 83 trt.tokenGetter = &cachedGetter{ 84 tokenGetter: &testTokenGetter{}, 85 ttl: test.ttl, 86 } 87 88 req, err := http.NewRequest(http.MethodPost, "https://test-api-server.com", nil) 89 if err != nil { 90 t.Errorf("failed to new request: %s", err) 91 } 92 trt.RoundTrip(req) 93 header := req.Header.Get("Authorization") 94 if header == "" { 95 t.Errorf("expect to see token in header, but is absent") 96 } 97 98 time.Sleep(test.interval) 99 100 req, err = http.NewRequest(http.MethodPost, "https://test-api-server.com", nil) 101 if err != nil { 102 t.Errorf("failed to new request: %s", err) 103 } 104 trt.RoundTrip(req) 105 newHeader := req.Header.Get("Authorization") 106 if newHeader == "" { 107 t.Errorf("expect to see token in header, but is absent") 108 } 109 110 same := newHeader == header 111 if same != test.same { 112 t.Errorf("expect to get %t when compare header, but saw %t", test.same, same) 113 } 114 } 115 116} 117 118type fakePersister struct{} 119 120func (i *fakePersister) Persist(map[string]string) error { 121 return nil 122} 123 124func TestNewOpenstackAuthProvider(t *testing.T) { 125 tests := []struct { 126 name string 127 config map[string]string 128 expectError bool 129 }{ 130 { 131 name: "normal config without openstack configurations", 132 config: map[string]string{ 133 "ttl": "1s", 134 "foo": "bar", 135 }, 136 }, 137 { 138 name: "openstack auth provider: missing identityEndpoint", 139 config: map[string]string{ 140 "ttl": "1s", 141 "foo": "bar", 142 "username": "xyz", 143 "password": "123", 144 "tenantName": "admin", 145 }, 146 expectError: true, 147 }, 148 { 149 name: "openstack auth provider", 150 config: map[string]string{ 151 "ttl": "1s", 152 "foo": "bar", 153 "identityEndpoint": "http://controller:35357/v3", 154 "username": "xyz", 155 "password": "123", 156 "tenantName": "admin", 157 }, 158 }, 159 } 160 161 for _, test := range tests { 162 _, err := newOpenstackAuthProvider("test", test.config, &fakePersister{}) 163 if err != nil { 164 if !test.expectError { 165 t.Errorf("unexpected error: %v", err) 166 } 167 } else { 168 if test.expectError { 169 t.Error("expect error, but nil") 170 } 171 } 172 } 173} 174