From 96f8698ebee80717f9cd1578a6148bb8e95927b1 Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:19:19 -0700 Subject: [PATCH] Integrated handler with API to push changes --- src/core/api.go | 12 +- src/core/api_test.go | 10 +- src/core/handler.go | 83 ++++++------ src/core/handler_test.go | 269 +++++++++++++++++++++++++-------------- 4 files changed, 222 insertions(+), 152 deletions(-) diff --git a/src/core/api.go b/src/core/api.go index 93e5a50..1c0e289 100644 --- a/src/core/api.go +++ b/src/core/api.go @@ -16,7 +16,7 @@ type GraphQLRequest struct { Query string `json:"query"` } -type ApplyChangeResponse struct { +type PushChangeResponse struct { Message string `json:"message"` Version int `json:"version"` } @@ -24,7 +24,7 @@ type ApplyChangeResponse struct { type IAPIService interface { FetchSnapshotVersion(domainId string, environment string) (string, error) FetchSnapshot(domainId string, environment string) (string, error) - ApplyChangesToAPI(domainId string, environment string, diff model.DiffResult) (ApplyChangeResponse, error) + PushChanges(domainId string, environment string, diff model.DiffResult) (PushChangeResponse, error) NewDataFromJson(jsonData []byte) model.Data } @@ -68,15 +68,15 @@ func (a *ApiService) FetchSnapshot(domainId string, environment string) (string, return responseBody, nil } -func (a *ApiService) ApplyChangesToAPI(domainId string, environment string, diff model.DiffResult) (ApplyChangeResponse, error) { +func (a *ApiService) PushChanges(domainId string, environment string, diff model.DiffResult) (PushChangeResponse, error) { reqBody, _ := json.Marshal(diff) - responseBody, err := a.doPostRequest(a.apiUrl+"/gitops/apply", domainId, reqBody) + responseBody, err := a.doPostRequest(a.apiUrl+"/gitops/push", domainId, reqBody) if err != nil { - return ApplyChangeResponse{}, err + return PushChangeResponse{}, err } - var response ApplyChangeResponse + var response PushChangeResponse json.Unmarshal([]byte(responseBody), &response) return response, nil } diff --git a/src/core/api_test.go b/src/core/api_test.go index 2fe53c8..2879dc5 100644 --- a/src/core/api_test.go +++ b/src/core/api_test.go @@ -113,8 +113,8 @@ func TestFetchSnapshot(t *testing.T) { }) } -func TestApplyChangesToAPI(t *testing.T) { - t.Run("Should apply changes to API", func(t *testing.T) { +func TestPushChangesToAPI(t *testing.T) { + t.Run("Should push changes to API", func(t *testing.T) { // Given diff := givenDiffResult() fakeApiServer := givenApiResponse(http.StatusOK, `{ @@ -126,7 +126,7 @@ func TestApplyChangesToAPI(t *testing.T) { apiService := NewApiService(SWITCHER_API_JWT_SECRET, fakeApiServer.URL) // Test - response, _ := apiService.ApplyChangesToAPI("domainId", "default", diff) + response, _ := apiService.PushChanges("domainId", "default", diff) // Assert assert.NotNil(t, response) @@ -143,7 +143,7 @@ func TestApplyChangesToAPI(t *testing.T) { apiService := NewApiService("[INVALID_KEY]", fakeApiServer.URL) // Test - response, _ := apiService.ApplyChangesToAPI("domainId", "default", diff) + response, _ := apiService.PushChanges("domainId", "default", diff) // Assert assert.NotNil(t, response) @@ -156,7 +156,7 @@ func TestApplyChangesToAPI(t *testing.T) { apiService := NewApiService("[SWITCHER_API_JWT_SECRET]", "http://localhost:8080") // Test - _, err := apiService.ApplyChangesToAPI("domainId", "default", diff) + _, err := apiService.PushChanges("domainId", "default", diff) // Assert assert.NotNil(t, err) diff --git a/src/core/handler.go b/src/core/handler.go index 497a475..59ef804 100644 --- a/src/core/handler.go +++ b/src/core/handler.go @@ -1,7 +1,6 @@ package core import ( - "fmt" "time" "github.com/switcherapi/switcher-gitops/src/config" @@ -24,7 +23,8 @@ type CoreHandler struct { Status int } -func NewCoreHandler(accountRepository repository.AccountRepository, apiService IAPIService, comparatorService IComparatorService) *CoreHandler { +func NewCoreHandler(accountRepository repository.AccountRepository, apiService IAPIService, + comparatorService IComparatorService) *CoreHandler { timeWindow, unitWindow := utils.GetTimeWindow(config.GetEnv("HANDLER_WAITING_TIME")) waitingTime := time.Duration(timeWindow) * unitWindow @@ -78,10 +78,8 @@ func (c *CoreHandler) StartAccountHandler(accountId string, gitService IGitServi // Wait for account to be active if !account.Settings.Active { - utils.LogInfo("[%s - %s (%s)] Account is not active, waiting for activation", - accountId, account.Domain.Name, account.Environment) - - c.updateDomainStatus(*account, model.StatusPending, "Account was deactivated") + c.updateDomainStatus(*account, model.StatusPending, "Account was deactivated", + utils.LogLevelInfo) time.Sleep(time.Duration(c.waitingTime)) continue } @@ -93,10 +91,8 @@ func (c *CoreHandler) StartAccountHandler(accountId string, gitService IGitServi repositoryData, err := gitService.GetRepositoryData(account.Environment) if err != nil { - utils.LogError("[%s - %s (%s)] Failed to fetch repository data - %s", - accountId, account.Domain.Name, account.Environment, err.Error()) - - c.updateDomainStatus(*account, model.StatusError, "Failed to fetch repository data - "+err.Error()) + c.updateDomainStatus(*account, model.StatusError, "Failed to fetch repository data - "+err.Error(), + utils.LogLevelError) time.Sleep(time.Duration(c.waitingTime)) continue } @@ -105,10 +101,8 @@ func (c *CoreHandler) StartAccountHandler(accountId string, gitService IGitServi snapshotVersionPayload, err := c.apiService.FetchSnapshotVersion(account.Domain.ID, account.Environment) if err != nil { - utils.LogError("[%s - %s (%s)] Failed to fetch snapshot version - %s", - accountId, account.Domain.Name, account.Environment, err.Error()) - - c.updateDomainStatus(*account, model.StatusError, "Failed to fetch snapshot version - "+err.Error()) + c.updateDomainStatus(*account, model.StatusError, "Failed to fetch snapshot version - "+err.Error(), + utils.LogLevelError) time.Sleep(time.Duration(c.waitingTime)) continue } @@ -125,37 +119,31 @@ func (c *CoreHandler) StartAccountHandler(accountId string, gitService IGitServi } func (c *CoreHandler) syncUp(account model.Account, repositoryData *model.RepositoryData, gitService IGitService) { - utils.LogInfo("[%s - %s (%s)] Syncing up", account.ID.Hex(), account.Domain.Name, account.Environment) - // Update account status: Out of sync account.Domain.LastCommit = repositoryData.CommitHash account.Domain.LastDate = repositoryData.CommitDate - c.updateDomainStatus(account, model.StatusOutSync, model.MessageSyncingUp) + c.updateDomainStatus(account, model.StatusOutSync, model.MessageSyncingUp, utils.LogLevelInfo) // Check for changes diff, snapshotApi, err := c.checkForChanges(account, repositoryData.Content) if err != nil { - utils.LogError("[%s - %s (%s)] Failed to check for changes - %s", - account.ID.Hex(), account.Domain.Name, account.Environment, err.Error()) - - c.updateDomainStatus(account, model.StatusError, "Failed to check for changes - "+err.Error()) + c.updateDomainStatus(account, model.StatusError, "Failed to check for changes - "+err.Error(), + utils.LogLevelError) return } - // Apply changes - changeSource, account, err := c.applyChanges(snapshotApi, account, repositoryData, diff, gitService) + // Push changes + changeSource, account, err := c.pushChanges(snapshotApi, account, repositoryData, diff, gitService) if err != nil { - utils.LogError("[%s - %s (%s)] Failed to apply changes [%s] - %s", - account.ID.Hex(), account.Domain.Name, account.Environment, changeSource, err.Error()) - - c.updateDomainStatus(account, model.StatusError, "Failed to apply changes ["+changeSource+"] - "+err.Error()) + c.updateDomainStatus(account, model.StatusError, "Failed to push changes ["+changeSource+"] - "+err.Error(), + utils.LogLevelError) return } // Update account status: Synced - c.updateDomainStatus(account, model.StatusSynced, model.MessageSynced) + c.updateDomainStatus(account, model.StatusSynced, model.MessageSynced, utils.LogLevelInfo) } func (c *CoreHandler) checkForChanges(account model.Account, content string) (model.DiffResult, model.Snapshot, error) { @@ -182,18 +170,15 @@ func (c *CoreHandler) checkForChanges(account model.Account, content string) (mo return c.comparatorService.MergeResults([]model.DiffResult{diffNew, diffChanged, diffDeleted}), snapshotApi.Snapshot, nil } -func (c *CoreHandler) applyChanges(snapshotApi model.Snapshot, account model.Account, +func (c *CoreHandler) pushChanges(snapshotApi model.Snapshot, account model.Account, repositoryData *model.RepositoryData, diff model.DiffResult, gitService IGitService) (string, model.Account, error) { - utils.LogDebug("[%s - %s (%s)] SnapshotAPI version: %s - SnapshotRepo version: %s", - account.ID.Hex(), account.Domain.Name, account.Environment, fmt.Sprint(snapshotApi.Domain.Version), fmt.Sprint(account.Domain.Version)) - err := error(nil) changeSource := "" if snapshotApi.Domain.Version > account.Domain.Version { changeSource = "Repository" if c.isRepositoryOutSync(repositoryData, diff) { - account, err = c.applyChangesToRepository(account, snapshotApi, gitService) + account, err = c.pushChangesToRepository(account, snapshotApi, gitService) } else { utils.LogInfo("[%s - %s (%s)] Repository is up to date", account.ID.Hex(), account.Domain.Name, account.Environment) @@ -202,36 +187,45 @@ func (c *CoreHandler) applyChanges(snapshotApi model.Snapshot, account model.Acc } } else if len(diff.Changes) > 0 { changeSource = "API" - account = c.applyChangesToAPI(account, repositoryData, diff) + account, err = c.pushChangesToAPI(account, repositoryData, diff) } return changeSource, account, err } -func (c *CoreHandler) applyChangesToAPI(account model.Account, repositoryData *model.RepositoryData, diff model.DiffResult) model.Account { - utils.LogInfo("[%s - %s (%s)] Pushing changes to API", account.ID.Hex(), account.Domain.Name, account.Environment) +func (c *CoreHandler) pushChangesToAPI(account model.Account, + repositoryData *model.RepositoryData, diff model.DiffResult) (model.Account, error) { + utils.LogInfo("[%s - %s (%s)] Pushing changes to API (prune: %t)", account.ID.Hex(), account.Domain.Name, + account.Environment, account.Settings.ForcePrune) // Removed deleted if force prune is disabled if !account.Settings.ForcePrune { - c.comparatorService.RemoveDeleted(diff) + diff = c.comparatorService.RemoveDeleted(diff) } // Push changes to API + apiResponse, err := c.apiService.PushChanges(account.Domain.ID, account.Environment, diff) + + if err != nil { + return account, err + } // Update domain - account.Domain.Version = 2 + account.Domain.Version = apiResponse.Version account.Domain.LastCommit = repositoryData.CommitHash - return account + return account, nil } -func (c *CoreHandler) applyChangesToRepository(account model.Account, snapshot model.Snapshot, gitService IGitService) (model.Account, error) { +func (c *CoreHandler) pushChangesToRepository(account model.Account, snapshot model.Snapshot, + gitService IGitService) (model.Account, error) { utils.LogInfo("[%s - %s (%s)] Pushing changes to repository", account.ID.Hex(), account.Domain.Name, account.Environment) // Remove version from domain snapshotContent := snapshot snapshotContent.Domain.Version = 0 + // Push changes to repository lastCommit, err := gitService.PushChanges(account.Environment, utils.ToJsonFromObject(snapshotContent)) if err != nil { @@ -248,8 +242,9 @@ func (c *CoreHandler) applyChangesToRepository(account model.Account, snapshot m func (c *CoreHandler) isOutSync(account model.Account, lastCommit string, snapshotVersionPayload string) bool { snapshotVersion := c.apiService.NewDataFromJson([]byte(snapshotVersionPayload)).Snapshot.Domain.Version - utils.LogDebug("[%s - %s (%s)] Checking account - Last commit: %s - Domain Version: %d - Snapshot Version: %d", - account.ID.Hex(), account.Domain.Name, account.Environment, account.Domain.LastCommit, account.Domain.Version, snapshotVersion) + utils.LogDebug("[%s - %s (%s)] Checking account - Last commit: %s - GitOps Version: %d - API Version: %d", + account.ID.Hex(), account.Domain.Name, account.Environment, account.Domain.LastCommit, + account.Domain.Version, snapshotVersion) return account.Domain.LastCommit == "" || // First sync account.Domain.LastCommit != lastCommit || // Repository out of sync @@ -261,7 +256,9 @@ func (c *CoreHandler) isRepositoryOutSync(repositoryData *model.RepositoryData, len(diff.Changes) > 0 // Changes detected } -func (c *CoreHandler) updateDomainStatus(account model.Account, status string, message string) { +func (c *CoreHandler) updateDomainStatus(account model.Account, status string, message string, logLevel string) { + utils.Log(logLevel, "[%s - %s (%s)] %s", account.ID.Hex(), account.Domain.Name, account.Environment, message) + account.Domain.Status = status account.Domain.Message = message account.Domain.LastDate = time.Now().Format(time.ANSIC) diff --git a/src/core/handler_test.go b/src/core/handler_test.go index 447b591..8f31c63 100644 --- a/src/core/handler_test.go +++ b/src/core/handler_test.go @@ -60,100 +60,32 @@ func TestInitCoreHandlerGoroutine(t *testing.T) { }) } -func TestStartAccountHandler(t *testing.T) { - t.Run("Should not sync when account is not active", func(t *testing.T) { - // Given - fakeGitService := NewFakeGitService() - - account := givenAccount() - account.Domain.ID = "123-not-active" - account.Settings.Active = false - accountCreated, _ := coreHandler.accountRepository.Create(&account) - - // Test - go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) - - time.Sleep(1 * time.Second) - - // Assert - accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) - assert.Equal(t, model.StatusPending, accountFromDb.Domain.Status) - assert.Equal(t, "Account was deactivated", accountFromDb.Domain.Message) - assert.Equal(t, "", accountFromDb.Domain.LastCommit) - - tearDown() - }) - - t.Run("Should not sync when fetch repository data returns an error", func(t *testing.T) { +func TestAccountHandlerSyncRepository(t *testing.T) { + t.Run("Should sync successfully when API has a newer version", func(t *testing.T) { // Given fakeGitService := NewFakeGitService() - fakeGitService.errorGetRepoData = "something went wrong" - - account := givenAccount() - account.Domain.ID = "123-error-get-repo-data" - accountCreated, _ := coreHandler.accountRepository.Create(&account) - - // Test - go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) - - time.Sleep(1 * time.Second) - - // Assert - accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) - assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) - assert.Contains(t, accountFromDb.Domain.Message, "Failed to fetch repository data") - assert.Equal(t, "", accountFromDb.Domain.LastCommit) - - tearDown() - }) + fakeGitService.lastCommit = "111" - t.Run("Should not sync when fetch snapshot version returns an error", func(t *testing.T) { - // Given - fakeGitService := NewFakeGitService() fakeApiService := NewFakeApiService() - fakeApiService.throwErrorVersion = true - coreHandler = NewCoreHandler(coreHandler.accountRepository, fakeApiService, NewComparatorService()) account := givenAccount() - account.Domain.ID = "123-error-fetch-snapshot-version" - accountCreated, _ := coreHandler.accountRepository.Create(&account) - - // Test - go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) - - time.Sleep(1 * time.Second) - - // Assert - accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) - assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) - assert.Contains(t, accountFromDb.Domain.Message, "Failed to fetch snapshot version") - assert.Equal(t, "", accountFromDb.Domain.LastCommit) - - tearDown() - }) - - t.Run("Should not sync after account is deleted", func(t *testing.T) { - // Given - fakeGitService := NewFakeGitService() - - account := givenAccount() - account.Domain.ID = "123-deleted" + account.Domain.ID = "123-newer-version" accountCreated, _ := coreHandler.accountRepository.Create(&account) // Test go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) - numGoroutinesBefore := runtime.NumGoroutine() - // Terminate the goroutine - coreHandler.accountRepository.DeleteByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + // Wait for goroutine to process time.Sleep(1 * time.Second) - numGoroutinesAfter := runtime.NumGoroutine() // Assert - _, err := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) - assert.LessOrEqual(t, numGoroutinesAfter, numGoroutinesBefore) - assert.NotNil(t, err) + accountFromDb, _ := coreHandler.accountRepository.FetchByAccountId(string(accountCreated.ID.Hex())) + assert.Equal(t, model.StatusSynced, accountFromDb.Domain.Status) + assert.Contains(t, accountFromDb.Domain.Message, model.MessageSynced) + assert.Equal(t, "111", accountFromDb.Domain.LastCommit) + assert.Equal(t, 1, accountFromDb.Domain.Version) + assert.NotEqual(t, "", accountFromDb.Domain.LastDate) tearDown() }) @@ -229,8 +161,39 @@ func TestStartAccountHandler(t *testing.T) { tearDown() }) +} - t.Run("Should sync and prune successfully when repository is out of sync", func(t *testing.T) { +func TestAccountHandlerSyncAPI(t *testing.T) { + t.Run("Should sync API when repository has new changes", func(t *testing.T) { + // Given + fakeGitService := NewFakeGitService() + fakeApiService := NewFakeApiService() + + coreHandler = NewCoreHandler(coreHandler.accountRepository, fakeApiService, NewComparatorService()) + + account := givenAccount() + account.Domain.ID = "123-sync-api" + account.Domain.Version = 1 + accountCreated, _ := coreHandler.accountRepository.Create(&account) + + // Test + go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) + + // Wait for goroutine to process + time.Sleep(1 * time.Second) + + // Assert + accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.Equal(t, model.StatusSynced, accountFromDb.Domain.Status) + assert.Contains(t, accountFromDb.Domain.Message, model.MessageSynced) + assert.Equal(t, "123", accountFromDb.Domain.LastCommit) + assert.Equal(t, 100, accountFromDb.Domain.Version) + assert.NotEqual(t, "", accountFromDb.Domain.LastDate) + + tearDown() + }) + + t.Run("Should sync and prune successfully when API is out of sync", func(t *testing.T) { // Given fakeGitService := NewFakeGitService() fakeGitService.content = `{ @@ -258,13 +221,13 @@ func TestStartAccountHandler(t *testing.T) { assert.Equal(t, model.StatusSynced, accountFromDb.Domain.Status) assert.Contains(t, accountFromDb.Domain.Message, model.MessageSynced) assert.Equal(t, "123", accountFromDb.Domain.LastCommit) - assert.Equal(t, 2, accountFromDb.Domain.Version) + assert.Equal(t, 100, accountFromDb.Domain.Version) assert.NotEqual(t, "", accountFromDb.Domain.LastDate) tearDown() }) - t.Run("Should sync and not prune when repository is out of sync", func(t *testing.T) { + t.Run("Should sync and not prune when API is out of sync", func(t *testing.T) { // Given fakeGitService := NewFakeGitService() fakeGitService.content = `{ @@ -292,37 +255,107 @@ func TestStartAccountHandler(t *testing.T) { assert.Equal(t, model.StatusSynced, accountFromDb.Domain.Status) assert.Contains(t, accountFromDb.Domain.Message, model.MessageSynced) assert.Equal(t, "123", accountFromDb.Domain.LastCommit) - assert.Equal(t, 2, accountFromDb.Domain.Version) + assert.Equal(t, 100, accountFromDb.Domain.Version) assert.NotEqual(t, "", accountFromDb.Domain.LastDate) tearDown() }) +} - t.Run("Should sync successfully when API has a newer version", func(t *testing.T) { +func TestAccountHandlerNotSync(t *testing.T) { + t.Run("Should not sync when account is not active", func(t *testing.T) { // Given fakeGitService := NewFakeGitService() - fakeGitService.lastCommit = "111" + account := givenAccount() + account.Domain.ID = "123-not-active" + account.Settings.Active = false + accountCreated, _ := coreHandler.accountRepository.Create(&account) + + // Test + go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) + + time.Sleep(1 * time.Second) + + // Assert + accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.Equal(t, model.StatusPending, accountFromDb.Domain.Status) + assert.Equal(t, "Account was deactivated", accountFromDb.Domain.Message) + assert.Equal(t, "", accountFromDb.Domain.LastCommit) + + tearDown() + }) + + t.Run("Should not sync when fetch repository data returns an error", func(t *testing.T) { + // Given + fakeGitService := NewFakeGitService() + fakeGitService.errorGetRepoData = "something went wrong" + + account := givenAccount() + account.Domain.ID = "123-error-get-repo-data" + accountCreated, _ := coreHandler.accountRepository.Create(&account) + + // Test + go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) + + time.Sleep(1 * time.Second) + + // Assert + accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) + assert.Contains(t, accountFromDb.Domain.Message, "Failed to fetch repository data") + assert.Equal(t, "", accountFromDb.Domain.LastCommit) + + tearDown() + }) + + t.Run("Should not sync when fetch snapshot version returns an error", func(t *testing.T) { + // Given + fakeGitService := NewFakeGitService() fakeApiService := NewFakeApiService() + fakeApiService.throwErrorVersion = true + coreHandler = NewCoreHandler(coreHandler.accountRepository, fakeApiService, NewComparatorService()) account := givenAccount() - account.Domain.ID = "123-newer-version" + account.Domain.ID = "123-error-fetch-snapshot-version" accountCreated, _ := coreHandler.accountRepository.Create(&account) // Test go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) - // Wait for goroutine to process time.Sleep(1 * time.Second) // Assert - accountFromDb, _ := coreHandler.accountRepository.FetchByAccountId(string(accountCreated.ID.Hex())) - assert.Equal(t, model.StatusSynced, accountFromDb.Domain.Status) - assert.Contains(t, accountFromDb.Domain.Message, model.MessageSynced) - assert.Equal(t, "111", accountFromDb.Domain.LastCommit) - assert.Equal(t, 1, accountFromDb.Domain.Version) - assert.NotEqual(t, "", accountFromDb.Domain.LastDate) + accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) + assert.Contains(t, accountFromDb.Domain.Message, "Failed to fetch snapshot version") + assert.Equal(t, "", accountFromDb.Domain.LastCommit) + + tearDown() + }) + + t.Run("Should not sync after account is deleted", func(t *testing.T) { + // Given + fakeGitService := NewFakeGitService() + + account := givenAccount() + account.Domain.ID = "123-deleted" + accountCreated, _ := coreHandler.accountRepository.Create(&account) + + // Test + go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) + numGoroutinesBefore := runtime.NumGoroutine() + + // Terminate the goroutine + coreHandler.accountRepository.DeleteByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + time.Sleep(1 * time.Second) + numGoroutinesAfter := runtime.NumGoroutine() + + // Assert + _, err := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.LessOrEqual(t, numGoroutinesAfter, numGoroutinesBefore) + assert.NotNil(t, err) tearDown() }) @@ -377,7 +410,36 @@ func TestStartAccountHandler(t *testing.T) { accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) assert.Contains(t, accountFromDb.Domain.Message, "authorization failed") - assert.Contains(t, accountFromDb.Domain.Message, "Failed to apply changes [Repository]") + assert.Contains(t, accountFromDb.Domain.Message, "Failed to push changes [Repository]") + assert.Equal(t, "123", accountFromDb.Domain.LastCommit) + assert.NotEqual(t, "", accountFromDb.Domain.LastDate) + + tearDown() + }) + + t.Run("Should not sync when API returns an error while pushing changes", func(t *testing.T) { + // Given + fakeGitService := NewFakeGitService() + fakeApiService := NewFakeApiService() + fakeApiService.throwErrorPush = true + + coreHandler = NewCoreHandler(coreHandler.accountRepository, fakeApiService, NewComparatorService()) + + account := givenAccount() + account.Domain.ID = "123-api-error-push" + account.Domain.Version = 1 + accountCreated, _ := coreHandler.accountRepository.Create(&account) + + // Test + go coreHandler.StartAccountHandler(accountCreated.ID.Hex(), fakeGitService) + + // Wait for goroutine to process + time.Sleep(1 * time.Second) + + // Assert + accountFromDb, _ := coreHandler.accountRepository.FetchByDomainIdEnvironment(accountCreated.Domain.ID, accountCreated.Environment) + assert.Equal(t, model.StatusError, accountFromDb.Domain.Status) + assert.Contains(t, accountFromDb.Domain.Message, "Failed to push changes") assert.Equal(t, "123", accountFromDb.Domain.LastCommit) assert.NotEqual(t, "", accountFromDb.Domain.LastDate) @@ -456,14 +518,21 @@ func (f *FakeGitService) UpdateRepositorySettings(repository string, token strin type FakeApiService struct { throwErrorVersion bool throwErrorSnapshot bool + throwErrorPush bool responseVersion string responseSnapshot string + pushChanges PushChangeResponse } func NewFakeApiService() *FakeApiService { return &FakeApiService{ throwErrorVersion: false, throwErrorSnapshot: false, + throwErrorPush: false, + pushChanges: PushChangeResponse{ + Message: "Changes applied successfully", + Version: 100, + }, responseVersion: `{ "data": { "domain": { @@ -498,7 +567,7 @@ func NewFakeApiService() *FakeApiService { func (f *FakeApiService) FetchSnapshotVersion(domainId string, environment string) (string, error) { if f.throwErrorVersion { - return "", errors.New("Something went wrong") + return "", errors.New("something went wrong") } return f.responseVersion, nil @@ -506,14 +575,18 @@ func (f *FakeApiService) FetchSnapshotVersion(domainId string, environment strin func (f *FakeApiService) FetchSnapshot(domainId string, environment string) (string, error) { if f.throwErrorSnapshot { - return "", errors.New("Something went wrong") + return "", errors.New("something went wrong") } return f.responseSnapshot, nil } -func (f *FakeApiService) ApplyChangesToAPI(domainId string, environment string, diff model.DiffResult) (ApplyChangeResponse, error) { - return ApplyChangeResponse{}, nil +func (f *FakeApiService) PushChanges(domainId string, environment string, diff model.DiffResult) (PushChangeResponse, error) { + if f.throwErrorPush { + return PushChangeResponse{}, errors.New("something went wrong") + } + + return f.pushChanges, nil } func (f *FakeApiService) NewDataFromJson(jsonData []byte) model.Data {