1package haip 2 3import ( 4 "github.com/stretchr/testify/assert" 5 "github.com/stretchr/testify/require" 6 "github.com/transip/gotransip/v6" 7 "github.com/transip/gotransip/v6/repository" 8 "io/ioutil" 9 "net" 10 "net/http" 11 "net/http/httptest" 12 "testing" 13) 14 15// mockServer struct is used to test the how the client sends a request 16// and responds to a servers response 17type mockServer struct { 18 t *testing.T 19 expectedURL string 20 expectedMethod string 21 statusCode int 22 expectedRequest string 23 response string 24 skipRequestBody bool 25} 26 27func (m *mockServer) getHTTPServer() *httptest.Server { 28 return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { 29 assert.Equal(m.t, m.expectedURL, req.URL.String()) // check if right expectedURL is called 30 31 if m.skipRequestBody == false && req.ContentLength != 0 { 32 // get the request body 33 // and check if the body matches the expected request body 34 body, err := ioutil.ReadAll(req.Body) 35 require.NoError(m.t, err) 36 assert.Equal(m.t, m.expectedRequest, string(body)) 37 } 38 39 assert.Equal(m.t, m.expectedMethod, req.Method) // check if the right expectedRequest expectedMethod is used 40 rw.WriteHeader(m.statusCode) // respond with given status code 41 42 if m.response != "" { 43 _, err := rw.Write([]byte(m.response)) 44 require.NoError(m.t, err, "error when writing mock response") 45 } 46 })) 47} 48 49func (m *mockServer) getClient() (*repository.Client, func()) { 50 httpServer := m.getHTTPServer() 51 config := gotransip.DemoClientConfiguration 52 config.URL = httpServer.URL 53 client, err := gotransip.NewClient(config) 54 require.NoError(m.t, err) 55 56 // return tearDown method with which will close the test server after the test 57 tearDown := func() { 58 httpServer.Close() 59 } 60 61 return &client, tearDown 62} 63 64func TestRepository_GetAll(t *testing.T) { 65 const apiResponse = `{ "haips": [ { "name": "example-haip", "description": "frontend cluster", "status": "active", "isLoadBalancingEnabled": true, "loadBalancingMode": "cookie", "stickyCookieName": "PHPSESSID", "healthCheckInterval": 3000, "httpHealthCheckPath": "/status.php", "httpHealthCheckPort": 443, "httpHealthCheckSsl": true, "ipv4Address": "37.97.254.7", "ipv6Address": "2a01:7c8:3:1337::1", "ipSetup": "ipv6to4", "ptrRecord": "frontend.example.com", "ipAddresses": [ "10.3.37.1", "10.3.38.1" ], "tlsMode": "tls12", "isLocked": false } ] } ` 66 server := mockServer{t: t, expectedURL: "/haips", expectedMethod: "GET", statusCode: 200, response: apiResponse} 67 client, tearDown := server.getClient() 68 defer tearDown() 69 repo := Repository{Client: *client} 70 71 all, err := repo.GetAll() 72 require.NoError(t, err) 73 require.Equal(t, 1, len(all)) 74 75 assert.Equal(t, "example-haip", all[0].Name) 76 assert.Equal(t, "frontend cluster", all[0].Description) 77 assert.EqualValues(t, "active", all[0].Status) 78 assert.Equal(t, true, all[0].IsLoadBalancingEnabled) 79 assert.EqualValues(t, "cookie", all[0].LoadBalancingMode) 80 assert.Equal(t, "PHPSESSID", all[0].StickyCookieName) 81 assert.EqualValues(t, 3000, all[0].HealthCheckInterval) 82 assert.Equal(t, "/status.php", all[0].HTTPHealthCheckPath) 83 assert.Equal(t, 443, all[0].HTTPHealthCheckPort) 84 assert.Equal(t, true, all[0].HTTPHealthCheckSsl) 85 assert.Equal(t, "37.97.254.7", all[0].IPv4Address.String()) 86 assert.Equal(t, "2a01:7c8:3:1337::1", all[0].IPv6Address.String()) 87 assert.EqualValues(t, "ipv6to4", all[0].IPSetup) 88 assert.Equal(t, "frontend.example.com", all[0].PtrRecord) 89 require.Equal(t, 2, len(all[0].IPAddresses)) 90 assert.Equal(t, "10.3.37.1", all[0].IPAddresses[0].String()) 91 assert.Equal(t, "10.3.38.1", all[0].IPAddresses[1].String()) 92 assert.EqualValues(t, "tls12", all[0].TLSMode) 93 assert.Equal(t, false, all[0].IsLocked) 94} 95 96func TestRepository_GetSelection(t *testing.T) { 97 const apiResponse = `{ "haips": [ { "name": "example-haip", "description": "frontend cluster", "status": "active", "isLoadBalancingEnabled": true, "loadBalancingMode": "cookie", "stickyCookieName": "PHPSESSID", "healthCheckInterval": 3000, "httpHealthCheckPath": "/status.php", "httpHealthCheckPort": 443, "httpHealthCheckSsl": true, "ipv4Address": "37.97.254.7", "ipv6Address": "2a01:7c8:3:1337::1", "ipSetup": "ipv4to6", "ptrRecord": "frontend.example.com", "ipAddresses": [ "10.3.37.1", "10.3.38.1" ], "tlsMode": "tls12", "isLocked": true } ] } ` 98 server := mockServer{t: t, expectedURL: "/haips?page=1&pageSize=25", expectedMethod: "GET", statusCode: 200, response: apiResponse} 99 client, tearDown := server.getClient() 100 defer tearDown() 101 repo := Repository{Client: *client} 102 103 all, err := repo.GetSelection(1, 25) 104 require.NoError(t, err) 105 require.Equal(t, 1, len(all)) 106 107 assert.Equal(t, "example-haip", all[0].Name) 108 assert.Equal(t, "frontend cluster", all[0].Description) 109 assert.EqualValues(t, "active", all[0].Status) 110 assert.Equal(t, true, all[0].IsLoadBalancingEnabled) 111 assert.EqualValues(t, "cookie", all[0].LoadBalancingMode) 112 assert.Equal(t, "PHPSESSID", all[0].StickyCookieName) 113 assert.EqualValues(t, 3000, all[0].HealthCheckInterval) 114 assert.Equal(t, "/status.php", all[0].HTTPHealthCheckPath) 115 assert.Equal(t, 443, all[0].HTTPHealthCheckPort) 116 assert.Equal(t, true, all[0].HTTPHealthCheckSsl) 117 assert.Equal(t, "37.97.254.7", all[0].IPv4Address.String()) 118 assert.Equal(t, "2a01:7c8:3:1337::1", all[0].IPv6Address.String()) 119 assert.EqualValues(t, "ipv4to6", all[0].IPSetup) 120 assert.Equal(t, "frontend.example.com", all[0].PtrRecord) 121 require.Equal(t, 2, len(all[0].IPAddresses)) 122 assert.Equal(t, "10.3.37.1", all[0].IPAddresses[0].String()) 123 assert.Equal(t, "10.3.38.1", all[0].IPAddresses[1].String()) 124 assert.EqualValues(t, "tls12", all[0].TLSMode) 125 assert.Equal(t, true, all[0].IsLocked) 126} 127 128func TestRepository_GetByName(t *testing.T) { 129 const apiResponse = `{ "haip": { "name": "example-haip", "description": "frontend cluster", "status": "active", "isLoadBalancingEnabled": true, "loadBalancingMode": "cookie", "stickyCookieName": "PHPSESSID", "healthCheckInterval": 3000, "httpHealthCheckPath": "/status.php", "httpHealthCheckPort": 443, "httpHealthCheckSsl": true, "ipv4Address": "37.97.254.7", "ipv6Address": "2a01:7c8:3:1337::1", "ipSetup": "ipv6to4", "ptrRecord": "frontend.example.com", "ipAddresses": [ "10.3.37.1", "10.3.38.1" ], "tlsMode": "tls12", "isLocked": false } }` 130 server := mockServer{t: t, expectedURL: "/haips/example-haip", expectedMethod: "GET", statusCode: 200, response: apiResponse} 131 client, tearDown := server.getClient() 132 defer tearDown() 133 repo := Repository{Client: *client} 134 135 haip, err := repo.GetByName("example-haip") 136 require.NoError(t, err) 137 138 assert.Equal(t, "example-haip", haip.Name) 139 assert.Equal(t, "frontend cluster", haip.Description) 140 assert.EqualValues(t, "active", haip.Status) 141 assert.Equal(t, true, haip.IsLoadBalancingEnabled) 142 assert.EqualValues(t, "cookie", haip.LoadBalancingMode) 143 assert.Equal(t, "PHPSESSID", haip.StickyCookieName) 144 assert.EqualValues(t, 3000, haip.HealthCheckInterval) 145 assert.Equal(t, "/status.php", haip.HTTPHealthCheckPath) 146 assert.Equal(t, 443, haip.HTTPHealthCheckPort) 147 assert.Equal(t, true, haip.HTTPHealthCheckSsl) 148 assert.Equal(t, "37.97.254.7", haip.IPv4Address.String()) 149 assert.Equal(t, "2a01:7c8:3:1337::1", haip.IPv6Address.String()) 150 assert.EqualValues(t, "ipv6to4", haip.IPSetup) 151 assert.Equal(t, "frontend.example.com", haip.PtrRecord) 152 require.Equal(t, 2, len(haip.IPAddresses)) 153 assert.Equal(t, "10.3.37.1", haip.IPAddresses[0].String()) 154 assert.Equal(t, "10.3.38.1", haip.IPAddresses[1].String()) 155 assert.EqualValues(t, "tls12", haip.TLSMode) 156 assert.Equal(t, false, haip.IsLocked) 157} 158 159func TestRepository_Order(t *testing.T) { 160 const expectedRequestBody = `{"productName":"haip-pro-contract","description":"myhaip01"}` 161 server := mockServer{t: t, expectedURL: "/haips", expectedMethod: "POST", statusCode: 201, expectedRequest: expectedRequestBody} 162 client, tearDown := server.getClient() 163 defer tearDown() 164 repo := Repository{Client: *client} 165 166 err := repo.Order("haip-pro-contract", "myhaip01") 167 require.NoError(t, err) 168} 169 170func TestRepository_Update(t *testing.T) { 171 const expectedRequestBody = `{"haip":{"name":"example-haip","description":"frontend cluster","status":"active","isLoadBalancingEnabled":true,"loadBalancingMode":"cookie","stickyCookieName":"PHPSESSID","healthCheckInterval":3000,"httpHealthCheckPath":"/status.php","httpHealthCheckPort":443,"httpHealthCheckSsl":true,"ipv4Address":"37.97.254.7","ipv6Address":"2a01:7c8:3:1337::1","ipSetup":"ipv6to4","ptrRecord":"frontend.example.com","ipAddresses":["10.3.37.1","10.3.38.1"],"tlsMode":"tls10_11_12"}}` 172 server := mockServer{t: t, expectedURL: "/haips/example-haip", expectedMethod: "PUT", statusCode: 204, expectedRequest: expectedRequestBody} 173 client, tearDown := server.getClient() 174 defer tearDown() 175 repo := Repository{Client: *client} 176 177 haip := Haip{ 178 Name: "example-haip", 179 Description: "frontend cluster", 180 Status: "active", 181 IsLoadBalancingEnabled: true, 182 LoadBalancingMode: "cookie", 183 StickyCookieName: "PHPSESSID", 184 HealthCheckInterval: 3000, 185 HTTPHealthCheckPath: "/status.php", 186 HTTPHealthCheckPort: 443, 187 HTTPHealthCheckSsl: true, 188 IPv4Address: net.ParseIP("37.97.254.7"), 189 IPv6Address: net.ParseIP("2a01:7c8:3:1337::1"), 190 IPSetup: "ipv6to4", 191 PtrRecord: "frontend.example.com", 192 IPAddresses: []net.IP{net.ParseIP("10.3.37.1"), net.ParseIP("10.3.38.1")}, 193 TLSMode: TLSModeMinTLS10, 194 } 195 196 err := repo.Update(haip) 197 require.NoError(t, err) 198} 199 200func TestRepository_Cancel(t *testing.T) { 201 const expectedRequestBody = `{"endTime":"immediately"}` 202 server := mockServer{t: t, expectedURL: "/haips/example-haip", expectedMethod: "DELETE", statusCode: 204, expectedRequest: expectedRequestBody} 203 client, tearDown := server.getClient() 204 defer tearDown() 205 repo := Repository{Client: *client} 206 207 err := repo.Cancel("example-haip", gotransip.CancellationTimeImmediately) 208 require.NoError(t, err) 209} 210 211func TestRepository_GetAllCertificates(t *testing.T) { 212 const apiResponse = `{ "certificates": [ { "id": 25478, "commonName": "example.com", "expirationDate": "2019-11-23" } ] }` 213 server := mockServer{t: t, expectedURL: "/haips/example-haip/certificates", expectedMethod: "GET", statusCode: 200, response: apiResponse} 214 client, tearDown := server.getClient() 215 defer tearDown() 216 repo := Repository{Client: *client} 217 218 all, err := repo.GetAllCertificates("example-haip") 219 require.NoError(t, err) 220 require.Equal(t, 1, len(all)) 221 222 assert.EqualValues(t, 25478, all[0].ID) 223 assert.Equal(t, "example.com", all[0].CommonName) 224 assert.Equal(t, "2019-11-23", all[0].ExpirationDate) 225} 226 227func TestRepository_AddCertificate(t *testing.T) { 228 const expectedRequestBody = `{"sslCertificateId":1337}` 229 server := mockServer{t: t, expectedURL: "/haips/example-haip/certificates", expectedMethod: "POST", statusCode: 201, expectedRequest: expectedRequestBody} 230 client, tearDown := server.getClient() 231 defer tearDown() 232 repo := Repository{Client: *client} 233 234 err := repo.AddCertificate("example-haip", 1337) 235 require.NoError(t, err) 236} 237 238func TestRepository_AddLetsEncryptCertificate(t *testing.T) { 239 const expectedRequestBody = `{"commonName":"foobar.example.com"}` 240 server := mockServer{t: t, expectedURL: "/haips/example-haip/certificates", expectedMethod: "POST", statusCode: 201, expectedRequest: expectedRequestBody} 241 client, tearDown := server.getClient() 242 defer tearDown() 243 repo := Repository{Client: *client} 244 245 err := repo.AddLetsEncryptCertificate("example-haip", "foobar.example.com") 246 require.NoError(t, err) 247} 248 249func TestRepository_DetachCertificate(t *testing.T) { 250 server := mockServer{t: t, expectedURL: "/haips/example-haip/certificates/1337", expectedMethod: "DELETE", statusCode: 204} 251 client, tearDown := server.getClient() 252 defer tearDown() 253 repo := Repository{Client: *client} 254 255 err := repo.DetachCertificate("example-haip", 1337) 256 require.NoError(t, err) 257} 258 259func TestRepository_GetAttachedIPAddresses(t *testing.T) { 260 const apiResponse = `{ "ipAddresses": [ "149.13.3.7", "149.31.33.7" ] }` 261 server := mockServer{t: t, expectedURL: "/haips/example-haip/ip-addresses", expectedMethod: "GET", statusCode: 200, response: apiResponse} 262 client, tearDown := server.getClient() 263 defer tearDown() 264 repo := Repository{Client: *client} 265 266 all, err := repo.GetAttachedIPAddresses("example-haip") 267 require.NoError(t, err) 268 require.Equal(t, 2, len(all)) 269 270 assert.Equal(t, "149.13.3.7", all[0].String()) 271 assert.Equal(t, "149.31.33.7", all[1].String()) 272} 273 274func TestRepository_SetAttachedIPAddresses(t *testing.T) { 275 const expectedRequestBody = `{"ipAddresses":["10.3.37.1","10.3.37.2"]}` 276 server := mockServer{t: t, expectedURL: "/haips/example-haip/ip-addresses", expectedMethod: "PUT", statusCode: 204, expectedRequest: expectedRequestBody} 277 client, tearDown := server.getClient() 278 defer tearDown() 279 repo := Repository{Client: *client} 280 281 ips := []net.IP{net.ParseIP("10.3.37.1"), net.ParseIP("10.3.37.2")} 282 283 err := repo.SetAttachedIPAddresses("example-haip", ips) 284 require.NoError(t, err) 285} 286 287func TestRepository_DetachIPAddresses(t *testing.T) { 288 server := mockServer{t: t, expectedURL: "/haips/example-haip/ip-addresses", expectedMethod: "DELETE", statusCode: 204} 289 client, tearDown := server.getClient() 290 defer tearDown() 291 repo := Repository{Client: *client} 292 293 err := repo.DetachIPAddresses("example-haip") 294 require.NoError(t, err) 295} 296 297func TestRepository_GetPortConfigurations(t *testing.T) { 298 const apiResponse = `{ "portConfigurations": [ { "id": 9865, "name": "Website Traffic", "sourcePort": 80, "targetPort": 80, "mode": "http", "endpointSslMode": "off" } ] } ` 299 server := mockServer{t: t, expectedURL: "/haips/example-haip/port-configurations", expectedMethod: "GET", statusCode: 200, response: apiResponse} 300 client, tearDown := server.getClient() 301 defer tearDown() 302 repo := Repository{Client: *client} 303 304 all, err := repo.GetPortConfigurations("example-haip") 305 require.NoError(t, err) 306 require.Equal(t, 1, len(all)) 307 308 assert.EqualValues(t, 9865, all[0].ID) 309 assert.Equal(t, "Website Traffic", all[0].Name) 310 assert.Equal(t, 80, all[0].SourcePort) 311 assert.Equal(t, 80, all[0].TargetPort) 312 assert.EqualValues(t, "http", all[0].Mode) 313 assert.Equal(t, "off", all[0].EndpointSslMode) 314} 315 316func TestRepository_GetPortConfiguration(t *testing.T) { 317 const apiResponse = `{ "portConfiguration": { "id": 9865, "name": "Website Traffic", "sourcePort": 80, "targetPort": 80, "mode": "http", "endpointSslMode": "off" } } ` 318 server := mockServer{t: t, expectedURL: "/haips/example-haip/port-configurations/9865", expectedMethod: "GET", statusCode: 200, response: apiResponse} 319 client, tearDown := server.getClient() 320 defer tearDown() 321 repo := Repository{Client: *client} 322 323 configuration, err := repo.GetPortConfiguration("example-haip", 9865) 324 require.NoError(t, err) 325 326 assert.EqualValues(t, 9865, configuration.ID) 327 assert.Equal(t, "Website Traffic", configuration.Name) 328 assert.Equal(t, 80, configuration.SourcePort) 329 assert.Equal(t, 80, configuration.TargetPort) 330 assert.EqualValues(t, "http", configuration.Mode) 331 assert.Equal(t, "off", configuration.EndpointSslMode) 332} 333 334func TestRepository_AddPortConfiguration(t *testing.T) { 335 const expectedRequestBody = `{"name":"Website Traffic","sourcePort":443,"targetPort":443,"mode":"https","endpointSslMode":"on"}` 336 server := mockServer{t: t, expectedURL: "/haips/example-haip/port-configurations", expectedMethod: "POST", statusCode: 201, expectedRequest: expectedRequestBody} 337 client, tearDown := server.getClient() 338 defer tearDown() 339 repo := Repository{Client: *client} 340 341 configuration := PortConfiguration{ 342 Name: "Website Traffic", 343 SourcePort: 443, 344 TargetPort: 443, 345 Mode: "https", 346 EndpointSslMode: "on", 347 } 348 err := repo.AddPortConfiguration("example-haip", configuration) 349 require.NoError(t, err) 350} 351 352func TestRepository_UpdatePortConfiguration(t *testing.T) { 353 const expectedRequestBody = `{"portConfiguration":{"id":9865,"name":"Website Traffic","sourcePort":443,"targetPort":443,"mode":"https","endpointSslMode":"on"}}` 354 server := mockServer{t: t, expectedURL: "/haips/example-haip/port-configurations/9865", expectedMethod: "PUT", statusCode: 204, expectedRequest: expectedRequestBody} 355 client, tearDown := server.getClient() 356 defer tearDown() 357 repo := Repository{Client: *client} 358 359 configuration := PortConfiguration{ 360 ID: 9865, 361 Name: "Website Traffic", 362 SourcePort: 443, 363 TargetPort: 443, 364 Mode: "https", 365 EndpointSslMode: "on", 366 } 367 err := repo.UpdatePortConfiguration("example-haip", configuration) 368 require.NoError(t, err) 369} 370 371func TestRepository_RemovePortConfiguration(t *testing.T) { 372 server := mockServer{t: t, expectedURL: "/haips/example-haip/port-configurations/1337", expectedMethod: "DELETE", statusCode: 204} 373 client, tearDown := server.getClient() 374 defer tearDown() 375 repo := Repository{Client: *client} 376 377 err := repo.RemovePortConfiguration("example-haip", 1337) 378 require.NoError(t, err) 379} 380 381func TestRepository_GetStatusReport(t *testing.T) { 382 const apiResponse = `{ "statusReport": [ { "ipAddress": "136.10.14.1", "port": 80, "ipVersion": 4, "loadBalancerName": "lb0", "loadBalancerIp": "136.144.151.255", "state": "up", "lastChange": "2019-09-29 16:51:18" } ] }` 383 server := mockServer{t: t, expectedURL: "/haips/example-haip/status-reports", expectedMethod: "GET", statusCode: 200, response: apiResponse} 384 client, tearDown := server.getClient() 385 defer tearDown() 386 repo := Repository{Client: *client} 387 388 all, err := repo.GetStatusReport("example-haip") 389 require.NoError(t, err) 390 require.Equal(t, 1, len(all)) 391 392 assert.Equal(t, "136.10.14.1", all[0].IPAddress.String()) 393 assert.Equal(t, 80, all[0].Port) 394 assert.Equal(t, 4, all[0].IPVersion) 395 assert.Equal(t, "lb0", all[0].LoadBalancerName) 396 assert.Equal(t, "136.144.151.255", all[0].LoadBalancerIP.String()) 397 assert.Equal(t, "up", all[0].State) 398 assert.Equal(t, "2019-09-29 16:51:18", all[0].LastChange.Format("2006-01-02 15:04:05")) 399} 400