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  }