github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/internal/destinationfetchersvc/service_test.go (about)

     1  package destinationfetchersvc_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/http"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  
    12  	"github.com/stretchr/testify/require"
    13  	"k8s.io/apimachinery/pkg/util/json"
    14  
    15  	"github.com/kyma-incubator/compass/components/director/internal/destinationfetchersvc"
    16  	"github.com/kyma-incubator/compass/components/director/internal/destinationfetchersvc/automock"
    17  	"github.com/kyma-incubator/compass/components/director/internal/model"
    18  	"github.com/pkg/errors"
    19  
    20  	"github.com/kyma-incubator/compass/components/director/pkg/apperrors"
    21  	"github.com/kyma-incubator/compass/components/director/pkg/config"
    22  	persistenceAutomock "github.com/kyma-incubator/compass/components/director/pkg/persistence/automock"
    23  	"github.com/kyma-incubator/compass/components/director/pkg/persistence/txtest"
    24  	"github.com/kyma-incubator/compass/components/director/pkg/resource"
    25  	"github.com/stretchr/testify/mock"
    26  )
    27  
    28  const (
    29  	tenantID            = "f09ba084-0e82-49ab-ab2e-b7ecc988312d"
    30  	runtimeID           = "d09ba084-0e82-49ab-ab2e-b7ecc988312d"
    31  	tenantLabelKey      = "subaccount"
    32  	regionLabelKey      = "region"
    33  	region              = "region1"
    34  	UUID                = "9b26a428-d526-469c-a5ef-2856f3ce0430"
    35  	subdomainLabelValue = "127" // will be replaced in 127.0.0.1 when fetching token for destination service
    36  )
    37  
    38  var (
    39  	testErr = errors.New("test error")
    40  )
    41  
    42  func TestService_SyncTenantDestinations(t *testing.T) {
    43  	//GIVEN
    44  	destinationServer := newDestinationServer(t)
    45  	destinationServer.server.Start()
    46  	defer destinationServer.server.Close()
    47  
    48  	txGen := txtest.NewTransactionContextGenerator(testErr)
    49  	destAPIConfig := defaultAPIConfig()
    50  	destConfig := defaultDestinationConfig(t, destinationServer.server.URL)
    51  
    52  	testCases := []struct {
    53  		Name                string
    54  		LabelRepo           func() *automock.LabelRepo
    55  		DestRepo            func() *automock.DestinationRepo
    56  		Transactioner       func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner)
    57  		BundleRepo          func() *automock.BundleRepo
    58  		UUIDService         func() *automock.UUIDService
    59  		ExpectedErrorOutput string
    60  		DestServiceHandler  func(w http.ResponseWriter, r *http.Request)
    61  	}{
    62  		{
    63  			Name: "Sync tenant destinations",
    64  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
    65  				return txGen.ThatSucceedsMultipleTimes(5)
    66  			},
    67  			LabelRepo:   successfulLabelRegionAndSubdomainRequest,
    68  			BundleRepo:  successfulBundleRepo("bundleID"),
    69  			DestRepo:    successfulDestinationRepo("bundleID"),
    70  			UUIDService: successfulUUIDService,
    71  		},
    72  		{
    73  			Name: "Successful sync of destinations but failing to delete old should not return error",
    74  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
    75  				return txGen.ThatSucceedsMultipleTimes(5)
    76  			},
    77  			LabelRepo:   successfulLabelRegionAndSubdomainRequest,
    78  			BundleRepo:  successfulBundleRepo("bundleID"),
    79  			DestRepo:    successfulInsertFailingDeleteDestinationRepo("bundleID"),
    80  			UUIDService: successfulUUIDService,
    81  		},
    82  		{
    83  			Name: "When getting bundles fails should stop processing destinations",
    84  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
    85  				return txGen.ThatSucceedsMultipleTimes(3)
    86  			},
    87  			LabelRepo:           successfulLabelRegionAndSubdomainRequest,
    88  			BundleRepo:          failingBundleRepo,
    89  			DestRepo:            unusedDestinationsRepo,
    90  			UUIDService:         successfulUUIDService,
    91  			ExpectedErrorOutput: testErr.Error(),
    92  		},
    93  		{
    94  			Name: "When no bundles are returned should continue to process destinations",
    95  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
    96  				return txGen.ThatSucceedsMultipleTimes(5)
    97  			},
    98  			LabelRepo:   successfulLabelRegionAndSubdomainRequest,
    99  			BundleRepo:  bundleRepoWithNoBundles,
   100  			DestRepo:    successfulDeleteDestinationRepo,
   101  			UUIDService: successfulUUIDService,
   102  		},
   103  		{
   104  			Name: "When destination upsert or delete fails should stop processing destinations",
   105  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   106  				return txGen.ThatSucceedsMultipleTimes(3)
   107  			},
   108  			LabelRepo:           successfulLabelRegionAndSubdomainRequest,
   109  			BundleRepo:          successfulBundleRepo("bundleID"),
   110  			DestRepo:            failingDestinationRepo,
   111  			UUIDService:         successfulUUIDService,
   112  			ExpectedErrorOutput: testErr.Error(),
   113  		},
   114  		{
   115  			Name:                "Failed to begin transaction to database",
   116  			Transactioner:       txGen.ThatFailsOnBegin,
   117  			LabelRepo:           unusedLabelRepo,
   118  			BundleRepo:          unusedBundleRepo,
   119  			DestRepo:            unusedDestinationsRepo,
   120  			UUIDService:         unusedUUIDService,
   121  			ExpectedErrorOutput: testErr.Error(),
   122  		},
   123  		{
   124  			Name:          "Failed to find subdomain label",
   125  			Transactioner: txGen.ThatSucceeds,
   126  			LabelRepo: func() *automock.LabelRepo {
   127  				repo := &automock.LabelRepo{}
   128  				repo.On("GetSubdomainLabelForSubscribedRuntime", mock.Anything, tenantID).
   129  					Return(nil, apperrors.NewNotFoundError(resource.Label, "id"))
   130  				return repo
   131  			},
   132  			BundleRepo:          unusedBundleRepo,
   133  			DestRepo:            unusedDestinationsRepo,
   134  			UUIDService:         unusedUUIDService,
   135  			ExpectedErrorOutput: fmt.Sprintf("tenant %s not found", tenantID),
   136  		},
   137  		{
   138  			Name:          "Error while getting subdomain label",
   139  			Transactioner: txGen.ThatSucceeds,
   140  			LabelRepo: func() *automock.LabelRepo {
   141  				repo := &automock.LabelRepo{}
   142  				repo.On("GetSubdomainLabelForSubscribedRuntime", mock.Anything, tenantID).
   143  					Return(nil, testErr)
   144  				return repo
   145  			},
   146  			BundleRepo:          unusedBundleRepo,
   147  			DestRepo:            unusedDestinationsRepo,
   148  			UUIDService:         unusedUUIDService,
   149  			ExpectedErrorOutput: testErr.Error(),
   150  		},
   151  		{
   152  			Name:                "Failed to commit transaction",
   153  			Transactioner:       txGen.ThatFailsOnCommit,
   154  			LabelRepo:           successfulLabelSubdomainRequest,
   155  			BundleRepo:          unusedBundleRepo,
   156  			DestRepo:            unusedDestinationsRepo,
   157  			UUIDService:         unusedUUIDService,
   158  			ExpectedErrorOutput: testErr.Error(),
   159  		},
   160  		{
   161  			Name: "Failed getting region",
   162  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   163  				return txGen.ThatSucceedsMultipleTimes(2)
   164  			},
   165  			LabelRepo:           failedLabelRegionAndSuccessfulSubdomainRequest,
   166  			BundleRepo:          unusedBundleRepo,
   167  			DestRepo:            unusedDestinationsRepo,
   168  			UUIDService:         unusedUUIDService,
   169  			ExpectedErrorOutput: testErr.Error(),
   170  		},
   171  		{
   172  			Name: "When destination service returns only invalid destinations - do not store them and remove old ones",
   173  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   174  				return txGen.ThatSucceedsMultipleTimes(4)
   175  			},
   176  			LabelRepo:   successfulLabelRegionAndSubdomainRequest,
   177  			BundleRepo:  unusedBundleRepo,
   178  			DestRepo:    successfulDeleteDestinationRepo,
   179  			UUIDService: successfulUUIDService,
   180  			DestServiceHandler: func(w http.ResponseWriter, r *http.Request) {
   181  				w.Header().Set("Content-Type", "application/json")
   182  				w.Header().Set("Page-Count", "1")
   183  
   184  				var (
   185  					invalidDest1 = `{
   186  						"Name": "badS4URL",
   187  						"URL": "invalid",
   188  						"XFSystemName": "Test S4HANA system",
   189  						"product.name": "SAP S/4HANA Cloud",
   190  						"communicationScenarioId": "SAP_COM_0108"
   191  					}`
   192  					invalidDest2 = `{
   193  						"Name": "no URL",
   194  						"XFSystemName": "Test S4HANA system",
   195  						"product.name": "SAP S/4HANA Cloud",
   196  						"x-correlation-id": "correlation-id"
   197  					}`
   198  					invalidDest3 = `{
   199  						"Name": "bad URL",
   200  						"URL": ":invalidURL",
   201  						"x-system-name": "Test S4HANA system",
   202  						"x-system-type": "SAP S/4HANA Cloud",
   203  						"x-correlation-id": "correlation-id"
   204  					}`
   205  					invalidDest4 = `{
   206  						"Name": "no correlation id",
   207  						"x-system-type": "systemType",
   208  						"x-system-id": "systemId"
   209  					}`
   210  				)
   211  				_, err := w.Write([]byte(fmt.Sprintf("[%s, %s, %s, %s]",
   212  					invalidDest1, invalidDest2, invalidDest3, invalidDest4)))
   213  				assert.NoError(t, err)
   214  			},
   215  		},
   216  		{
   217  			Name: "When destination service returns zero pages - just remove old ones",
   218  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   219  				return txGen.ThatSucceedsMultipleTimes(3)
   220  			},
   221  			LabelRepo:   successfulLabelRegionAndSubdomainRequest,
   222  			BundleRepo:  unusedBundleRepo,
   223  			DestRepo:    successfulDeleteDestinationRepo,
   224  			UUIDService: successfulUUIDService,
   225  			DestServiceHandler: func(w http.ResponseWriter, r *http.Request) {
   226  				w.Header().Set("Content-Type", "application/json")
   227  				w.Header().Set("Page-Count", "0")
   228  
   229  				_, err := w.Write([]byte("[]"))
   230  				assert.NoError(t, err)
   231  			},
   232  		},
   233  	}
   234  	for _, testCase := range testCases {
   235  		t.Run(testCase.Name, func(t *testing.T) {
   236  			destinationServer.handler.customTenantDestinationHandler = testCase.DestServiceHandler
   237  			defer func() {
   238  				destinationServer.handler.customTenantDestinationHandler = nil
   239  			}()
   240  			_, tx := testCase.Transactioner()
   241  			destRepo := testCase.DestRepo()
   242  			labelRepo := testCase.LabelRepo()
   243  			bundleRepo := testCase.BundleRepo()
   244  			uuidService := testCase.UUIDService()
   245  			tenantRepo := unusedTenantRepo()
   246  			defer mock.AssertExpectationsForObjects(t, tx, destRepo, labelRepo, uuidService, bundleRepo, tenantRepo)
   247  
   248  			destSvc := destinationfetchersvc.DestinationService{
   249  				Transactioner:      tx,
   250  				UUIDSvc:            uuidService,
   251  				DestinationRepo:    destRepo,
   252  				BundleRepo:         bundleRepo,
   253  				LabelRepo:          labelRepo,
   254  				TenantRepo:         tenantRepo,
   255  				DestinationsConfig: destConfig,
   256  				APIConfig:          destAPIConfig,
   257  			}
   258  
   259  			ctx := context.Background()
   260  			// WHEN
   261  			err := destSvc.SyncTenantDestinations(ctx, tenantID)
   262  
   263  			// THEN
   264  			if len(testCase.ExpectedErrorOutput) > 0 {
   265  				require.Error(t, err)
   266  				require.Contains(t, err.Error(), testCase.ExpectedErrorOutput)
   267  			} else {
   268  				require.NoError(t, err)
   269  			}
   270  		})
   271  	}
   272  }
   273  
   274  func TestService_FetchDestinationsSensitiveData(t *testing.T) {
   275  	//GIVEN
   276  	destinationServer := newDestinationServer(t)
   277  	destinationServer.server.Start()
   278  	defer destinationServer.server.Close()
   279  
   280  	txGen := txtest.NewTransactionContextGenerator(testErr)
   281  	destAPIConfig := defaultAPIConfig()
   282  	destConfig := defaultDestinationConfig(t, destinationServer.server.URL)
   283  
   284  	testCases := []struct {
   285  		Name                string
   286  		DestinationNames    []string
   287  		TenantID            string
   288  		LabelRepo           func() *automock.LabelRepo
   289  		Transactioner       func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner)
   290  		ExpectedErrorOutput string
   291  	}{
   292  		{
   293  			Name:             "Fetch with empty destination list",
   294  			DestinationNames: []string{},
   295  			TenantID:         tenantID,
   296  			LabelRepo:        successfulLabelRegionAndSubdomainRequest,
   297  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   298  				return txGen.ThatSucceedsMultipleTimes(2)
   299  			},
   300  		},
   301  		{
   302  			Name:             "Fetch with existing destinations list",
   303  			DestinationNames: []string{"dest1", "dest2"},
   304  			TenantID:         tenantID,
   305  			LabelRepo:        successfulLabelRegionAndSubdomainRequest,
   306  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   307  				return txGen.ThatSucceedsMultipleTimes(2)
   308  			},
   309  		},
   310  		{
   311  			Name:             "Fetch with one non-existing destination",
   312  			DestinationNames: []string{"dest1", "missing"},
   313  			TenantID:         tenantID,
   314  			LabelRepo:        successfulLabelRegionAndSubdomainRequest,
   315  			Transactioner: func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner) {
   316  				return txGen.ThatSucceedsMultipleTimes(2)
   317  			},
   318  			ExpectedErrorOutput: "Object not found",
   319  		},
   320  	}
   321  	for _, testCase := range testCases {
   322  		t.Run(testCase.Name, func(t *testing.T) {
   323  			_, tx := testCase.Transactioner()
   324  			destRepo := unusedDestinationsRepo()
   325  			labelRepo := testCase.LabelRepo()
   326  			uuidService := unusedUUIDService()
   327  			bundleRepo := unusedBundleRepo()
   328  			tenantRepo := unusedTenantRepo()
   329  
   330  			defer mock.AssertExpectationsForObjects(t, tx, destRepo, labelRepo, uuidService, bundleRepo, tenantRepo)
   331  
   332  			destSvc := destinationfetchersvc.DestinationService{
   333  				Transactioner:      tx,
   334  				UUIDSvc:            uuidService,
   335  				DestinationRepo:    destRepo,
   336  				BundleRepo:         bundleRepo,
   337  				TenantRepo:         tenantRepo,
   338  				LabelRepo:          labelRepo,
   339  				DestinationsConfig: destConfig,
   340  				APIConfig:          destAPIConfig,
   341  			}
   342  
   343  			ctx := context.Background()
   344  			// WHEN
   345  			resp, err := destSvc.FetchDestinationsSensitiveData(ctx, testCase.TenantID, testCase.DestinationNames)
   346  
   347  			// THEN
   348  			if len(testCase.ExpectedErrorOutput) > 0 {
   349  				require.Error(t, err)
   350  				require.Contains(t, err.Error(), testCase.ExpectedErrorOutput)
   351  			} else {
   352  				require.NoError(t, err)
   353  				var parsedResponse map[string]map[string]interface{}
   354  				require.NoError(t, json.Unmarshal(resp, &parsedResponse))
   355  				destinations := parsedResponse["destinations"]
   356  				require.NotNil(t, destinations)
   357  				for _, expectedDestinationName := range testCase.DestinationNames {
   358  					require.Contains(t, destinations, expectedDestinationName)
   359  				}
   360  			}
   361  		})
   362  	}
   363  }
   364  
   365  func TestService_GetSubscribedTenantIDs(t *testing.T) {
   366  	//GIVEN
   367  	txGen := txtest.NewTransactionContextGenerator(testErr)
   368  	destAPIConfig := defaultAPIConfig()
   369  	destConfig := defaultDestinationConfig(t, "invalid")
   370  
   371  	testCases := []struct {
   372  		Name                string
   373  		ExpectedTenantIDs   []string
   374  		TenantRepo          func() *automock.TenantRepo
   375  		Transactioner       func() (*persistenceAutomock.PersistenceTx, *persistenceAutomock.Transactioner)
   376  		ExpectedErrorOutput string
   377  	}{
   378  		{
   379  			Name:              "Fetch subscribed tenants",
   380  			ExpectedTenantIDs: []string{"a", "b"},
   381  			TenantRepo:        successfulTenantRepo([]string{"b", "a"}),
   382  			Transactioner:     txGen.ThatSucceeds,
   383  		},
   384  		{
   385  			Name:                "Tenant repo returns error",
   386  			TenantRepo:          failingTenantRepo,
   387  			Transactioner:       txGen.ThatSucceeds,
   388  			ExpectedErrorOutput: testErr.Error(),
   389  		},
   390  		{
   391  			Name:                "Tenant repo returns error on Begin",
   392  			TenantRepo:          unusedTenantRepo,
   393  			Transactioner:       txGen.ThatFailsOnBegin,
   394  			ExpectedErrorOutput: testErr.Error(),
   395  		},
   396  		{
   397  			Name:                "Tenant repo returns error on Commit",
   398  			TenantRepo:          successfulTenantRepo([]string{}),
   399  			Transactioner:       txGen.ThatFailsOnCommit,
   400  			ExpectedErrorOutput: testErr.Error(),
   401  		},
   402  		{
   403  			Name:              "Tenant repo returns no tenants",
   404  			ExpectedTenantIDs: []string{},
   405  			TenantRepo:        successfulTenantRepo([]string{}),
   406  			Transactioner:     txGen.ThatSucceeds,
   407  		},
   408  	}
   409  	for _, testCase := range testCases {
   410  		t.Run(testCase.Name, func(t *testing.T) {
   411  			_, tx := testCase.Transactioner()
   412  			destRepo := unusedDestinationsRepo()
   413  			labelRepo := unusedLabelRepo()
   414  			uuidService := unusedUUIDService()
   415  			bundleRepo := unusedBundleRepo()
   416  			tenantRepo := testCase.TenantRepo()
   417  
   418  			defer mock.AssertExpectationsForObjects(t, tx, destRepo, labelRepo, uuidService, bundleRepo, tenantRepo)
   419  
   420  			destSvc := destinationfetchersvc.DestinationService{
   421  				Transactioner:      tx,
   422  				UUIDSvc:            uuidService,
   423  				DestinationRepo:    destRepo,
   424  				BundleRepo:         bundleRepo,
   425  				TenantRepo:         tenantRepo,
   426  				LabelRepo:          labelRepo,
   427  				DestinationsConfig: destConfig,
   428  				APIConfig:          destAPIConfig,
   429  			}
   430  
   431  			ctx := context.Background()
   432  			// WHEN
   433  			tenantIDs, err := destSvc.GetSubscribedTenantIDs(ctx)
   434  
   435  			// THEN
   436  			if len(testCase.ExpectedErrorOutput) > 0 {
   437  				require.Error(t, err)
   438  				require.Contains(t, err.Error(), testCase.ExpectedErrorOutput)
   439  			} else {
   440  				require.NoError(t, err)
   441  				for _, expectedTenantID := range testCase.ExpectedTenantIDs {
   442  					require.Contains(t, tenantIDs, expectedTenantID)
   443  				}
   444  			}
   445  		})
   446  	}
   447  }
   448  
   449  func unusedLabelRepo() *automock.LabelRepo              { return &automock.LabelRepo{} }
   450  func unusedDestinationsRepo() *automock.DestinationRepo { return &automock.DestinationRepo{} }
   451  func unusedBundleRepo() *automock.BundleRepo            { return &automock.BundleRepo{} }
   452  func unusedTenantRepo() *automock.TenantRepo            { return &automock.TenantRepo{} }
   453  func unusedUUIDService() *automock.UUIDService          { return &automock.UUIDService{} }
   454  
   455  func successfulUUIDService() *automock.UUIDService {
   456  	uuidService := &automock.UUIDService{}
   457  	uuidService.On("Generate").Return(UUID)
   458  	return uuidService
   459  }
   460  
   461  func successfulLabelSubdomainRequest() *automock.LabelRepo {
   462  	repo := &automock.LabelRepo{}
   463  	label := model.NewLabelForRuntime(runtimeID, tenantID, tenantLabelKey, subdomainLabelValue)
   464  	tid := tenantID
   465  	label.Tenant = &tid
   466  	repo.On("GetSubdomainLabelForSubscribedRuntime", mock.Anything, tenantID).Return(label, nil)
   467  	return repo
   468  }
   469  
   470  func failedLabelRegionAndSuccessfulSubdomainRequest() *automock.LabelRepo {
   471  	repo := &automock.LabelRepo{}
   472  	label := model.NewLabelForRuntime(runtimeID, tenantID, tenantLabelKey, subdomainLabelValue)
   473  	tid := tenantID
   474  	label.Tenant = &tid
   475  	repo.On("GetSubdomainLabelForSubscribedRuntime", mock.Anything, tenantID).Return(label, nil)
   476  	repo.On("GetByKey", mock.Anything, tenantID, model.TenantLabelableObject, tenantID, regionLabelKey).
   477  		Return(nil, testErr)
   478  	return repo
   479  }
   480  
   481  func successfulLabelRegionAndSubdomainRequest() *automock.LabelRepo {
   482  	repo := &automock.LabelRepo{}
   483  	label := model.NewLabelForRuntime(runtimeID, tenantID, tenantLabelKey, subdomainLabelValue)
   484  	tid := tenantID
   485  	label.Tenant = &tid
   486  	repo.On("GetSubdomainLabelForSubscribedRuntime", mock.Anything, tenantID).Return(label, nil)
   487  	label = model.NewLabelForRuntime(runtimeID, tenantID, regionLabelKey, region)
   488  	label.Tenant = &tid
   489  	repo.On("GetByKey", mock.Anything, tenantID, model.TenantLabelableObject, tenantID, regionLabelKey).
   490  		Return(label, nil)
   491  	return repo
   492  }
   493  
   494  func successfulBundleRepo(bundleID string) func() *automock.BundleRepo {
   495  	return func() *automock.BundleRepo {
   496  		bundleRepo := unusedBundleRepo()
   497  		bundleRepo.On("ListByDestination",
   498  			mock.Anything, mock.Anything, mock.Anything).Return(
   499  			[]*model.Bundle{{
   500  				BaseEntity: &model.BaseEntity{
   501  					ID: bundleID,
   502  				},
   503  			}}, nil)
   504  		return bundleRepo
   505  	}
   506  }
   507  
   508  func failingBundleRepo() *automock.BundleRepo {
   509  	bundleRepo := unusedBundleRepo()
   510  	bundleRepo.On("ListByDestination",
   511  		mock.Anything, mock.Anything, mock.Anything).Return(nil, testErr)
   512  	return bundleRepo
   513  }
   514  
   515  func bundleRepoWithNoBundles() *automock.BundleRepo {
   516  	bundleRepo := unusedBundleRepo()
   517  	bundleRepo.On("ListByDestination",
   518  		mock.Anything, mock.Anything, mock.Anything).Return([]*model.Bundle{}, nil)
   519  	return bundleRepo
   520  }
   521  
   522  func successfulDeleteDestinationRepo() *automock.DestinationRepo {
   523  	destinationRepo := unusedDestinationsRepo()
   524  	destinationRepo.On("DeleteOld",
   525  		mock.Anything, UUID, tenantID).Return(nil)
   526  	return destinationRepo
   527  }
   528  
   529  func successfulDestinationRepo(bundleID string) func() *automock.DestinationRepo {
   530  	return func() *automock.DestinationRepo {
   531  		destinationRepo := unusedDestinationsRepo()
   532  		destinationRepo.On("Upsert",
   533  			mock.Anything, mock.Anything, mock.Anything, mock.Anything, bundleID, mock.Anything).Return(nil)
   534  		destinationRepo.On("DeleteOld",
   535  			mock.Anything, UUID, tenantID).Return(nil)
   536  		return destinationRepo
   537  	}
   538  }
   539  
   540  func successfulInsertFailingDeleteDestinationRepo(bundleID string) func() *automock.DestinationRepo {
   541  	return func() *automock.DestinationRepo {
   542  		destinationRepo := unusedDestinationsRepo()
   543  		destinationRepo.On("Upsert",
   544  			mock.Anything, mock.Anything, mock.Anything, mock.Anything, bundleID, mock.Anything).Return(nil)
   545  		destinationRepo.On("DeleteOld",
   546  			mock.Anything, UUID, tenantID).Return(testErr)
   547  		return destinationRepo
   548  	}
   549  }
   550  
   551  func failingDestinationRepo() *automock.DestinationRepo {
   552  	destinationRepo := unusedDestinationsRepo()
   553  	destinationRepo.On("Upsert",
   554  		mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(testErr)
   555  	return destinationRepo
   556  }
   557  
   558  func successfulTenantRepo(tenantIDs []string) func() *automock.TenantRepo {
   559  	return func() *automock.TenantRepo {
   560  		tenantRepo := unusedTenantRepo()
   561  		tenants := make([]*model.BusinessTenantMapping, 0, len(tenantIDs))
   562  		for _, tenantID := range tenantIDs {
   563  			tenants = append(tenants, &model.BusinessTenantMapping{
   564  				ID: tenantID,
   565  			})
   566  		}
   567  		tenantRepo.On("ListBySubscribedRuntimes", mock.Anything).Return(tenants, nil)
   568  		return tenantRepo
   569  	}
   570  }
   571  
   572  func failingTenantRepo() *automock.TenantRepo {
   573  	tenantRepo := unusedTenantRepo()
   574  	tenantRepo.On("ListBySubscribedRuntimes", mock.Anything).Return(nil, testErr)
   575  	return tenantRepo
   576  }
   577  
   578  func defaultAPIConfig() destinationfetchersvc.DestinationServiceAPIConfig {
   579  	return destinationfetchersvc.DestinationServiceAPIConfig{
   580  		GoroutineLimit:                2,
   581  		RetryInterval:                 0,
   582  		RetryAttempts:                 2,
   583  		EndpointGetTenantDestinations: "/subaccountDestinations",
   584  		EndpointFindDestination:       "/destinations",
   585  		Timeout:                       time.Second * 10,
   586  		PageSize:                      1,
   587  		PagingPageParam:               "$page",
   588  		PagingSizeParam:               "$pageSize",
   589  		PagingCountParam:              "$pageCount",
   590  		PagingCountHeader:             "Page-Count",
   591  		OAuthTokenPath:                "/oauth/token",
   592  	}
   593  }
   594  
   595  func defaultDestinationConfig(t *testing.T, destinationServerURL string) config.DestinationsConfig {
   596  	cert, key := generateTestCertAndKey(t, "test")
   597  	instanceConfig := config.InstanceConfig{
   598  		ClientID:     tenantID,
   599  		ClientSecret: "secret",
   600  		URL:          destinationServerURL,
   601  		TokenURL:     destinationServerURL,
   602  		Cert:         string(cert),
   603  		Key:          string(key),
   604  	}
   605  	return config.DestinationsConfig{
   606  		RegionToInstanceConfig: map[string]config.InstanceConfig{
   607  			region: instanceConfig,
   608  		},
   609  	}
   610  }