github.com/Axway/agent-sdk@v1.1.101/pkg/apic/client_test.go (about) 1 package apic 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "strings" 7 "testing" 8 "time" 9 10 cache2 "github.com/Axway/agent-sdk/pkg/agent/cache" 11 "github.com/Axway/agent-sdk/pkg/api" 12 apiv1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1" 13 v1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1" 14 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 15 "github.com/Axway/agent-sdk/pkg/apic/auth" 16 defs "github.com/Axway/agent-sdk/pkg/apic/definitions" 17 corecfg "github.com/Axway/agent-sdk/pkg/config" 18 "github.com/Axway/agent-sdk/pkg/util/healthcheck" 19 "github.com/stretchr/testify/assert" 20 ) 21 22 func TestNewClient(t *testing.T) { 23 cfg := corecfg.NewCentralConfig(corecfg.DiscoveryAgent) 24 client := New(cfg, MockTokenGetter, cache2.NewAgentCacheManager(cfg, false)) 25 assert.NotNil(t, client) 26 } 27 28 func TestGetEnvironment(t *testing.T) { 29 svcClient, mockHTTPClient := GetTestServiceClient() 30 cfg := GetTestServiceClientCentralConfiguration(svcClient) 31 cfg.Environment = "Environment" 32 mockHTTPClient.SetResponse("./testdata/apiserver-environment.json", http.StatusOK) 33 34 env, err := svcClient.GetEnvironment() 35 assert.NotNil(t, env) 36 assert.Nil(t, err, "An unexpected error was returned from the health check with traceability agent in publishToEnvironment mode") 37 assert.NotNil(t, env) 38 } 39 40 func arrContains(arr []string, s string) bool { 41 for _, n := range arr { 42 if n == s { 43 return true 44 } 45 } 46 return false 47 } 48 49 func TestMapTagsToArray(t *testing.T) { 50 svcClient, _ := GetTestServiceClient() 51 tag4Value := "value4" 52 tags := map[string]interface{}{"tag1": "value1", "tag2": "", "tag3": "value3", "tag4": &tag4Value} 53 result := mapToTagsArray(tags, svcClient.cfg.GetTagsToPublish()) 54 assert.Equal(t, 4, len(result)) 55 assert.True(t, arrContains(result, "tag1_value1")) 56 assert.True(t, arrContains(result, "tag2")) 57 assert.False(t, arrContains(result, "bar")) 58 59 cfg := GetTestServiceClientCentralConfiguration(svcClient) 60 cfg.TagsToPublish = "bar" 61 result = mapToTagsArray(tags, cfg.GetTagsToPublish()) 62 assert.Equal(t, 5, len(result)) 63 assert.True(t, arrContains(result, "tag1_value1")) 64 assert.True(t, arrContains(result, "tag2")) 65 assert.True(t, arrContains(result, "bar")) 66 } 67 68 func TestGetUserEmailAddress(t *testing.T) { 69 svcClient, mockHTTPClient := GetTestServiceClient() 70 71 cfg := GetTestServiceClientCentralConfiguration(svcClient) 72 cfg.Environment = "Environment" 73 cfg.PlatformURL = "http://foo.bar:4080" 74 75 // Test DiscoveryAgent, PublishToEnvironment 76 mockHTTPClient.SetResponses([]api.MockResponse{ 77 { 78 FileName: "./testdata/userinfo.json", 79 RespCode: http.StatusOK, 80 }, 81 }) 82 83 addr, err := svcClient.GetUserEmailAddress("b0433b7f-ac38-4d29-8a64-cf645c99b99f") 84 assert.Nil(t, err) 85 assert.Equal(t, "joe@axway.com", addr) 86 87 // test a failure 88 mockHTTPClient.SetResponses([]api.MockResponse{ 89 {FileName: "./testdata/userinfoerror.json", 90 RespCode: http.StatusNotFound, 91 ErrString: "Resource Not Found", 92 }, 93 }) 94 95 addr, err = svcClient.GetUserEmailAddress("b0433b7f-ac38-4d29-8a64-cf645c99b99g") 96 assert.NotNil(t, err) 97 assert.Equal(t, "", addr) 98 } 99 100 func TestGetUserName(t *testing.T) { 101 svcClient, mockHTTPClient := GetTestServiceClient() 102 103 cfg := GetTestServiceClientCentralConfiguration(svcClient) 104 cfg.Environment = "Environment" 105 cfg.PlatformURL = "http://foo.bar:4080" 106 107 // Test DiscoveryAgent, PublishToEnvironment 108 mockHTTPClient.SetResponses([]api.MockResponse{ 109 { 110 FileName: "./testdata/userinfo.json", 111 RespCode: http.StatusOK, 112 }, 113 }) 114 115 userName, err := svcClient.GetUserName("b0433b7f-ac38-4d29-8a64-cf645c99b99f") 116 assert.Nil(t, err) 117 assert.Equal(t, "Dale Feldick", userName) 118 119 // test a failure 120 mockHTTPClient.SetResponses([]api.MockResponse{ 121 {FileName: "./testdata/userinfoerror.json", 122 RespCode: http.StatusNotFound, 123 ErrString: "Resource Not Found", 124 }, 125 }) 126 127 userName, err = svcClient.GetUserName("b0433b7f-ac38-4d29-8a64-cf645c99b99g") 128 assert.NotNil(t, err) 129 assert.Equal(t, "", userName) 130 } 131 132 func TestHealthCheck(t *testing.T) { 133 svcClient, mockHTTPClient := GetTestServiceClient() 134 requester := svcClient.tokenRequester 135 136 // swap out mock for a real tokenRequester 137 svcClient.tokenRequester = auth.NewPlatformTokenGetter("", "", "", "", "", "", "", 1*time.Second) 138 139 // failure 140 status := svcClient.Healthcheck("Client Test") 141 assert.Equal(t, status.Result, healthcheck.FAIL) 142 assert.True(t, strings.Contains(status.Details, "error getting authentication token")) 143 144 svcClient.tokenRequester = requester 145 146 // failure 147 status = svcClient.Healthcheck("Client Test") 148 assert.Equal(t, status.Result, healthcheck.FAIL) 149 assert.True(t, strings.Contains(status.Details, "unexpected end")) 150 151 // success 152 responses := []api.MockResponse{ 153 {FileName: "./testdata/apiserver-environment.json", RespCode: http.StatusOK}, 154 } 155 mockHTTPClient.SetResponses(responses) 156 status = svcClient.Healthcheck("Client Test") 157 assert.Equal(t, status.Result, healthcheck.OK) 158 } 159 160 func TestCreateSubResource(t *testing.T) { 161 svcClient, mockHTTPClient := GetTestServiceClient() 162 cfg := GetTestServiceClientCentralConfiguration(svcClient) 163 cfg.Environment = "mockenv" 164 cfg.PlatformURL = "http://foo.bar:4080" 165 166 // There should be one request for each sub resource of the ResourceInstance 167 mockHTTPClient.SetResponses([]api.MockResponse{ 168 { 169 FileName: "./testdata/agent-details-sr.json", 170 RespCode: http.StatusOK, 171 }, 172 { 173 FileName: "./testdata/agent-details-sr.json", 174 RespCode: http.StatusOK, 175 }, 176 }) 177 178 ri := &apiv1.ResourceInstance{ 179 ResourceMeta: apiv1.ResourceMeta{ 180 Name: "test-resource", 181 GroupVersionKind: management.APIServiceGVK(), 182 SubResources: map[string]interface{}{ 183 defs.XAgentDetails: map[string]interface{}{ 184 "externalAPIID": "12345", 185 "externalAPIName": "daleapi", 186 "createdBy": "", 187 }, 188 "abc": map[string]interface{}{ 189 "123": "132", 190 }, 191 }, 192 }, 193 } 194 195 err := svcClient.CreateSubResource(ri.ResourceMeta, ri.SubResources) 196 assert.Nil(t, err) 197 } 198 199 func TestUpdateSpecORCreateResourceInstance(t *testing.T) { 200 tests := []struct { 201 name string 202 gvk apiv1.GroupVersionKind 203 oldHash string 204 newHash string 205 apiResponses []api.MockResponse 206 expectedTagVal string 207 expectErr bool 208 }{ 209 { 210 name: "should error with bad response from api call", 211 gvk: management.AccessRequestDefinitionGVK(), 212 oldHash: "1234", 213 newHash: "1235", 214 apiResponses: []api.MockResponse{ 215 { 216 RespCode: http.StatusUnauthorized, 217 }, 218 }, 219 expectedTagVal: "existing", 220 expectErr: true, 221 }, 222 { 223 name: "should not update ARD as hash is unchanged", 224 gvk: management.AccessRequestDefinitionGVK(), 225 oldHash: "1234", 226 newHash: "1234", 227 apiResponses: []api.MockResponse{}, 228 expectedTagVal: "existing", 229 expectErr: false, 230 }, 231 { 232 name: "should not update CRD as hash is unchanged", 233 gvk: management.CredentialRequestDefinitionGVK(), 234 oldHash: "1234", 235 newHash: "1234", 236 apiResponses: []api.MockResponse{}, 237 expectedTagVal: "existing", 238 expectErr: false, 239 }, 240 { 241 name: "should update ARD as hash has changed", 242 gvk: management.AccessRequestDefinitionGVK(), 243 oldHash: "1234", 244 newHash: "5234", 245 apiResponses: []api.MockResponse{ 246 { 247 FileName: "./testdata/apiservice.json", 248 RespCode: http.StatusOK, 249 }, 250 { 251 FileName: "./testdata/apiservice.json", 252 RespCode: http.StatusOK, 253 }, 254 }, 255 expectedTagVal: "prod", 256 expectErr: false, 257 }, 258 { 259 name: "should update CRD as hash has changed", 260 gvk: management.CredentialRequestDefinitionGVK(), 261 oldHash: "1234", 262 newHash: "5234", 263 apiResponses: []api.MockResponse{ 264 { 265 FileName: "./testdata/apiservice.json", 266 RespCode: http.StatusOK, 267 }, 268 { 269 FileName: "./testdata/apiservice.json", 270 RespCode: http.StatusOK, 271 }, 272 }, 273 expectedTagVal: "prod", 274 expectErr: false, 275 }, 276 } 277 for _, tt := range tests { 278 t.Run(tt.name, func(t *testing.T) { 279 svcClient, mockHTTPClient := GetTestServiceClient() 280 cfg := GetTestServiceClientCentralConfiguration(svcClient) 281 cfg.Environment = "mockenv" 282 cfg.PlatformURL = "http://foo.bar:4080" 283 284 // There should be one request for each sub resource of the ResourceInstance 285 mockHTTPClient.SetResponses(tt.apiResponses) 286 287 res := apiv1.ResourceInstance{ 288 ResourceMeta: apiv1.ResourceMeta{ 289 Name: tt.name, 290 GroupVersionKind: tt.gvk, 291 SubResources: map[string]interface{}{ 292 defs.XAgentDetails: map[string]interface{}{ 293 defs.AttrSpecHash: tt.oldHash, 294 }, 295 }, 296 Tags: []string{"existing"}, 297 }, 298 Spec: map[string]interface{}{}, 299 } 300 301 // setup the cachedResources 302 switch tt.gvk.Kind { 303 case management.AccessRequestDefinitionGVK().Kind: 304 svcClient.caches.AddAccessRequestDefinition(&res) 305 case management.CredentialRequestDefinitionGVK().Kind: 306 svcClient.caches.AddCredentialRequestDefinition(&res) 307 } 308 309 newRes := res 310 newRes.Tags = []string{} 311 newRes.SubResources = map[string]interface{}{defs.XAgentDetails: map[string]interface{}{defs.AttrSpecHash: tt.newHash}} 312 313 ri, err := svcClient.updateSpecORCreateResourceInstance(&newRes) 314 if tt.expectErr { 315 assert.NotNil(t, err) 316 } else { 317 assert.Nil(t, err) 318 assert.Equal(t, tt.expectedTagVal, ri.Tags[0]) 319 } 320 321 }) 322 } 323 } 324 325 func TestPatchRequest(t *testing.T) { 326 createInstance := func(name string) *v1.ResourceInstance { 327 inst := createAPIServiceInstance(name, name, "", "", false) 328 ri, _ := inst.AsInstance() 329 return ri 330 } 331 332 tests := []struct { 333 name string 334 res *v1.ResourceInstance 335 patchSubResource string 336 patches []map[string]interface{} 337 apiResponses []api.MockResponse 338 expectErr bool 339 }{ 340 { 341 name: "no self link", 342 res: &v1.ResourceInstance{}, 343 apiResponses: []api.MockResponse{}, 344 expectErr: true, 345 }, 346 { 347 name: "no patches", 348 res: createInstance("test"), 349 expectErr: false, 350 }, 351 { 352 name: "send patch", 353 res: createInstance("test"), 354 apiResponses: []api.MockResponse{ 355 { 356 FileName: "./testdata/serviceinstance.json", 357 RespCode: http.StatusOK, 358 }, 359 }, 360 patchSubResource: "source", 361 patches: []map[string]interface{}{ 362 { 363 PatchOperation: PatchOpAdd, 364 PatchPath: "/source/compliance", 365 PatchValue: map[string]interface{}{}, 366 }, 367 }, 368 expectErr: false, 369 }, 370 } 371 for _, tt := range tests { 372 t.Run(tt.name, func(t *testing.T) { 373 svcClient, mockHTTPClient := GetTestServiceClient() 374 cfg := GetTestServiceClientCentralConfiguration(svcClient) 375 cfg.Environment = "mockenv" 376 cfg.PlatformURL = "http://foo.bar:4080" 377 378 mockHTTPClient.SetResponses(tt.apiResponses) 379 380 ri, err := svcClient.PatchSubResource(tt.res, tt.patchSubResource, tt.patches) 381 if tt.expectErr { 382 if tt.patches != nil { 383 assert.NotNil(t, err) 384 } 385 } else { 386 assert.Nil(t, err) 387 assert.NotNil(t, ri) 388 if len(tt.patches) > 0 { 389 assert.NotEmpty(t, mockHTTPClient.Requests) 390 p := make([]map[string]interface{}, 0) 391 json.Unmarshal(mockHTTPClient.Requests[0].Body, &p) 392 assert.NotEmpty(t, p) 393 assert.Equal(t, len(tt.patches)+1, len(p)) 394 buildObjectTreePatchFound := false 395 for _, patch := range p { 396 operation := patch[PatchOperation] 397 if operation == PatchOpBuildObjectTree { 398 buildObjectTreePatchFound = true 399 assert.Equal(t, "/"+tt.patchSubResource, patch[PatchPath]) 400 } else { 401 path := patch[PatchPath] 402 assert.Equal(t, path, tt.patches[0][PatchPath]) 403 } 404 } 405 assert.True(t, buildObjectTreePatchFound) 406 } 407 } 408 }) 409 } 410 }