github.com/Axway/agent-sdk@v1.1.101/pkg/apic/apiserviceinstance_test.go (about) 1 package apic 2 3 import ( 4 "net/http" 5 "testing" 6 7 "github.com/Axway/agent-sdk/pkg/api" 8 apiv1 "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/api/v1" 9 management "github.com/Axway/agent-sdk/pkg/apic/apiserver/models/management/v1alpha1" 10 defs "github.com/Axway/agent-sdk/pkg/apic/definitions" 11 "github.com/Axway/agent-sdk/pkg/util" 12 "github.com/stretchr/testify/assert" 13 ) 14 15 func TestServiceClient_buildAPIServiceInstance(t *testing.T) { 16 body := &ServiceBody{ 17 Description: "description", 18 ImageContentType: "content-type", 19 Image: "image-data", 20 NameToPush: "nametopush", 21 APIName: "apiname", 22 RestAPIID: "restapiid", 23 PrimaryKey: "primarykey", 24 Stage: "staging", 25 Version: "v1", 26 Tags: map[string]interface{}{ 27 "tag1": "value1", 28 "tag2": "value2", 29 }, 30 CreatedBy: "createdby", 31 ServiceAttributes: map[string]string{"service_attribute": "value"}, 32 RevisionAttributes: map[string]string{"revision_attribute": "value"}, 33 InstanceAttributes: map[string]string{"instance_attribute": "value"}, 34 ServiceAgentDetails: map[string]interface{}{ 35 "subresource_svc_key": "value", 36 }, 37 InstanceAgentDetails: map[string]interface{}{ 38 "subresource_instance_key": "value", 39 }, 40 RevisionAgentDetails: map[string]interface{}{ 41 "subresource_revision_key": "value", 42 }, 43 } 44 45 tags := []string{"tag1_value1", "tag2_value2"} 46 47 client, _ := GetTestServiceClient() 48 ep := []management.ApiServiceInstanceSpecEndpoint{ 49 { 50 Host: "abc.com", 51 Port: 80, 52 Protocol: "http", 53 Routing: management.ApiServiceInstanceSpecRouting{ 54 BasePath: "/base", 55 }, 56 }, 57 { 58 Host: "123.com", 59 Port: 443, 60 Protocol: "https", 61 Routing: management.ApiServiceInstanceSpecRouting{ 62 BasePath: "/path", 63 }, 64 }, 65 } 66 inst := client.buildAPIServiceInstance(body, "name", ep) 67 68 assert.Equal(t, management.APIServiceInstanceGVK(), inst.GroupVersionKind) 69 assert.Equal(t, "name", inst.Name) 70 assert.Equal(t, body.NameToPush, inst.Title) 71 72 assert.Contains(t, inst.Tags, tags[0]) 73 assert.Contains(t, inst.Tags, tags[1]) 74 75 assert.Contains(t, inst.Attributes, "instance_attribute") 76 assert.NotContains(t, inst.Attributes, "service_attribute") 77 assert.NotContains(t, inst.Attributes, "revision_attribute") 78 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIStage) 79 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIPrimaryKey) 80 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIID) 81 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIName) 82 assert.NotContains(t, inst.Attributes, defs.AttrCreatedBy) 83 84 assert.Equal(t, inst.Spec.Endpoint, ep) 85 86 sub := util.GetAgentDetails(inst) 87 assert.Equal(t, body.Stage, sub[defs.AttrExternalAPIStage]) 88 assert.Equal(t, body.PrimaryKey, sub[defs.AttrExternalAPIPrimaryKey]) 89 assert.Equal(t, body.RestAPIID, sub[defs.AttrExternalAPIID]) 90 assert.Equal(t, body.APIName, sub[defs.AttrExternalAPIName]) 91 assert.Equal(t, body.CreatedBy, sub[defs.AttrCreatedBy]) 92 assert.Contains(t, sub, "subresource_svc_key") 93 assert.Contains(t, sub, "subresource_instance_key") 94 assert.NotContains(t, sub, "subresource_revision_key") 95 assert.NotContains(t, sub, "revision_attribute") 96 } 97 98 func TestServiceClient_updateAPIServiceInstance(t *testing.T) { 99 body := &ServiceBody{ 100 Description: "description", 101 ImageContentType: "content-type", 102 Image: "image-data", 103 NameToPush: "nametopush", 104 APIName: "apiname", 105 RestAPIID: "restapiid", 106 PrimaryKey: "primarykey", 107 Stage: "staging", 108 Version: "v1", 109 Tags: map[string]interface{}{ 110 "tag1": "value1", 111 "tag2": "value2", 112 }, 113 CreatedBy: "createdby", 114 ServiceAttributes: map[string]string{"service_attribute": "value"}, 115 RevisionAttributes: map[string]string{"revision_attribute": "value"}, 116 InstanceAttributes: map[string]string{"instance_attribute": "value"}, 117 ServiceAgentDetails: map[string]interface{}{ 118 "subresource_svc_key": "value", 119 }, 120 InstanceAgentDetails: map[string]interface{}{ 121 "subresource_instance_key": "value", 122 }, 123 RevisionAgentDetails: map[string]interface{}{ 124 "subresource_revision_key": "value", 125 }, 126 } 127 128 tags := []string{"tag1_value1", "tag2_value2"} 129 130 client, _ := GetTestServiceClient() 131 ep := []management.ApiServiceInstanceSpecEndpoint{ 132 { 133 Host: "abc.com", 134 Port: 80, 135 Protocol: "http", 136 Routing: management.ApiServiceInstanceSpecRouting{ 137 BasePath: "/base", 138 }, 139 }, 140 { 141 Host: "123.com", 142 Port: 443, 143 Protocol: "https", 144 Routing: management.ApiServiceInstanceSpecRouting{ 145 BasePath: "/path", 146 }, 147 }, 148 } 149 inst := &management.APIServiceInstance{ 150 ResourceMeta: apiv1.ResourceMeta{ 151 Title: "oldname", 152 Attributes: map[string]string{ 153 "old_attr": "value", 154 }, 155 Name: "name", 156 Tags: []string{"old_tag"}, 157 Metadata: apiv1.Metadata{ResourceVersion: ""}, 158 }, 159 } 160 inst = client.updateAPIServiceInstance(body, inst, ep) 161 162 assert.Equal(t, management.APIServiceInstanceGVK(), inst.GroupVersionKind) 163 assert.Empty(t, inst.Metadata.ResourceVersion) 164 assert.Equal(t, "name", inst.Name) 165 assert.Equal(t, body.NameToPush, inst.Title) 166 167 assert.Contains(t, inst.Tags, tags[0]) 168 assert.Contains(t, inst.Tags, tags[1]) 169 assert.NotContains(t, inst.Tags, "old_tag") 170 171 assert.Equal(t, inst.Spec.Endpoint, ep) 172 173 assert.Contains(t, inst.Attributes, "instance_attribute") 174 assert.NotContains(t, inst.Attributes, "service_attribute") 175 assert.NotContains(t, inst.Attributes, "revision_attribute") 176 assert.NotContains(t, inst.Attributes, "old_attr") 177 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIStage) 178 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIPrimaryKey) 179 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIID) 180 assert.NotContains(t, inst.Attributes, defs.AttrExternalAPIName) 181 assert.NotContains(t, inst.Attributes, defs.AttrCreatedBy) 182 183 sub := util.GetAgentDetails(inst) 184 assert.Equal(t, body.Stage, sub[defs.AttrExternalAPIStage]) 185 assert.Equal(t, body.PrimaryKey, sub[defs.AttrExternalAPIPrimaryKey]) 186 assert.Equal(t, body.RestAPIID, sub[defs.AttrExternalAPIID]) 187 assert.Equal(t, body.APIName, sub[defs.AttrExternalAPIName]) 188 assert.Equal(t, body.CreatedBy, sub[defs.AttrCreatedBy]) 189 assert.Contains(t, sub, "subresource_svc_key") 190 assert.Contains(t, sub, "subresource_instance_key") 191 assert.NotContains(t, sub, "subresource_revision_key") 192 assert.NotContains(t, sub, "revision_attribute") 193 } 194 195 func Test_buildAPIServiceInstanceNilAttributes(t *testing.T) { 196 client, _ := GetTestServiceClient() 197 body := &ServiceBody{} 198 ep := []management.ApiServiceInstanceSpecEndpoint{} 199 inst := client.buildAPIServiceInstance(body, "name", ep) 200 assert.NotNil(t, inst.Attributes) 201 202 inst.Attributes = nil 203 204 inst = client.updateAPIServiceInstance(body, inst, ep) 205 assert.NotNil(t, inst.Attributes) 206 } 207 208 func createAPIServiceInstance(name, id string, refInstance string, dpType string, isDesign bool) *management.APIServiceInstance { 209 instance := &management.APIServiceInstance{ 210 ResourceMeta: apiv1.ResourceMeta{ 211 Name: name, 212 Title: name, 213 SubResources: map[string]interface{}{ 214 defs.XAgentDetails: map[string]interface{}{ 215 defs.AttrExternalAPIID: id, 216 defs.AttrExternalAPIName: name, 217 }, 218 }, 219 }, 220 Spec: management.ApiServiceInstanceSpec{}, 221 } 222 if refInstance != "" || dpType != "" { 223 instance.Source = &management.ApiServiceInstanceSource{ 224 References: &management.ApiServiceInstanceSourceReferences{ 225 ApiServiceInstance: refInstance, 226 }, 227 } 228 instance.Source.DataplaneType = &management.ApiServiceInstanceSourceDataplaneType{} 229 if isDesign { 230 instance.Source.DataplaneType.Design = dpType 231 } else { 232 instance.Source.DataplaneType.Managed = dpType 233 } 234 } 235 return instance 236 } 237 238 func TestInstanceSourceUpdates(t *testing.T) { 239 // case 1 - new instance, source managed dataplane, sub resource updated 240 // case 2 - new instance, source design dataplane, sub resource updated 241 // case 3 - new instance, source unmanaged dataplane with reference, sub resource updated 242 // case 4 - existing instance, no source, source updated 243 // case 5 - existing instance, existing source, different dataplane type, source updated 244 // case 6 - existing instance, existing source, different reference, source updated 245 // case 7 - existing instance, existing source, same dataplane type and same reference, no source updated 246 testCases := []struct { 247 name string 248 instanceName string 249 managedDataplane DataplaneType 250 designDataplane DataplaneType 251 existingInstance *management.APIServiceInstance 252 referenceInstance string 253 apiserverResponses []api.MockResponse 254 }{ 255 { 256 name: "new instance for managed dataplane", 257 instanceName: "newInstManaged", 258 managedDataplane: AWS, 259 apiserverResponses: []api.MockResponse{ 260 { 261 FileName: "./testdata/serviceinstance.json", // call to create the instance 262 RespCode: http.StatusCreated, 263 }, 264 { 265 FileName: "./testdata/serviceinstance.json", // call to update source subresource 266 RespCode: http.StatusOK, 267 }, 268 { 269 FileName: "./testdata/serviceinstance.json", // call to update source subresource 270 RespCode: http.StatusOK, 271 }, 272 }, 273 }, 274 { 275 name: "new instance for design dataplane", 276 instanceName: "newInstDesign", 277 designDataplane: GitLab, 278 apiserverResponses: []api.MockResponse{ 279 { 280 FileName: "./testdata/serviceinstance.json", // call to create the instance 281 RespCode: http.StatusCreated, 282 }, 283 { 284 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 285 RespCode: http.StatusOK, 286 }, 287 { 288 FileName: "./testdata/serviceinstance.json", // call to update source subresource 289 RespCode: http.StatusOK, 290 }, 291 }, 292 }, 293 { 294 name: "new instance for unmanaged dataplane with referenced instance", 295 instanceName: "newInstUnmanaged", 296 managedDataplane: Unclassified, 297 referenceInstance: "refInst", 298 apiserverResponses: []api.MockResponse{ 299 { 300 FileName: "./testdata/serviceinstance.json", // call to create the instance 301 RespCode: http.StatusCreated, 302 }, 303 { 304 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 305 RespCode: http.StatusOK, 306 }, 307 { 308 FileName: "./testdata/serviceinstance.json", // call to update source subresource 309 RespCode: http.StatusOK, 310 }, 311 }, 312 }, 313 { 314 name: "existing instance with no source", 315 instanceName: "daleapi", 316 managedDataplane: AWS, 317 existingInstance: createAPIServiceInstance("daleapi", "2f5f92f0-f5e4-44fb-bc84-599c27b3497a", "", "", false), 318 apiserverResponses: []api.MockResponse{ 319 { 320 FileName: "./testdata/serviceinstance.json", // call to get the instance 321 RespCode: http.StatusOK, 322 }, 323 { 324 FileName: "./testdata/serviceinstance.json", // call to update the instance 325 RespCode: http.StatusOK, 326 }, 327 { 328 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 329 RespCode: http.StatusOK, 330 }, 331 { 332 FileName: "./testdata/serviceinstance.json", // call to update source subresource 333 RespCode: http.StatusOK, 334 }, 335 }, 336 }, 337 { 338 name: "existing instance with different dataplane type", 339 instanceName: "existingInstance", 340 managedDataplane: AWS, 341 existingInstance: createAPIServiceInstance("existingInstance", "existingInstance", "", Unclassified.String(), false), 342 apiserverResponses: []api.MockResponse{ 343 { 344 FileName: "./testdata/existingserviceinstances.json", // call to get the instance 345 RespCode: http.StatusOK, 346 }, 347 { 348 FileName: "./testdata/serviceinstance.json", // call to update the instance 349 RespCode: http.StatusOK, 350 }, 351 { 352 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 353 RespCode: http.StatusOK, 354 }, 355 { 356 FileName: "./testdata/serviceinstance.json", // call to update source subresource 357 RespCode: http.StatusOK, 358 }, 359 }, 360 }, 361 { 362 name: "existing instance with different referenced instance", 363 instanceName: "existingInstance", 364 managedDataplane: Unclassified, 365 existingInstance: createAPIServiceInstance("existingInstance", "existingInstance", "refInstance", Unclassified.String(), false), 366 referenceInstance: "newRefInstance", 367 apiserverResponses: []api.MockResponse{ 368 { 369 FileName: "./testdata/existingserviceinstances.json", // call to get the instance 370 RespCode: http.StatusOK, 371 }, 372 { 373 FileName: "./testdata/serviceinstance.json", // call to update the instance 374 RespCode: http.StatusOK, 375 }, 376 { 377 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 378 RespCode: http.StatusOK, 379 }, 380 { 381 FileName: "./testdata/serviceinstance.json", // call to update source subresource 382 RespCode: http.StatusOK, 383 }, 384 }, 385 }, 386 { 387 name: "existing instance with same source", 388 instanceName: "existingInstance", 389 managedDataplane: Unclassified, 390 existingInstance: createAPIServiceInstance("existingInstance", "existingInstance", "refInstance", Unclassified.String(), false), 391 referenceInstance: "refInstance", 392 apiserverResponses: []api.MockResponse{ 393 { 394 FileName: "./testdata/existingserviceinstances.json", // call to get the instance 395 RespCode: http.StatusOK, 396 }, 397 { 398 FileName: "./testdata/serviceinstance.json", // call to update the instance 399 RespCode: http.StatusOK, 400 }, 401 { 402 FileName: "./testdata/serviceinstance.json", // call to update x-agent-details subresource 403 RespCode: http.StatusOK, 404 }, 405 // no source subresource update 406 }, 407 }, 408 } 409 for _, test := range testCases { 410 t.Run(test.name, func(t *testing.T) { 411 client, httpClient := GetTestServiceClient() 412 body := &ServiceBody{ 413 RestAPIID: test.instanceName, 414 } 415 416 if test.existingInstance != nil { 417 ri, _ := test.existingInstance.AsInstance() 418 client.caches.AddAPIServiceInstance(ri) 419 body.serviceContext.serviceAction = updateAPI 420 body.serviceContext.revisionCount = 1 421 } 422 423 if test.managedDataplane != "" { 424 body.dataplaneType = test.managedDataplane 425 } 426 if test.designDataplane != "" { 427 body.dataplaneType = test.designDataplane 428 body.isDesignDataplane = true 429 } 430 body.referencedInstanceName = test.referenceInstance 431 httpClient.SetResponses(test.apiserverResponses) 432 433 err := client.processInstance(body) 434 assert.Nil(t, err) 435 assert.Equal(t, len(test.apiserverResponses), httpClient.RespCount) 436 }) 437 } 438 }