From 78f486d130575e01d6e99bceb806d2ebe68a3a7b Mon Sep 17 00:00:00 2001
From: petruki <31597636+petruki@users.noreply.github.com>
Date: Tue, 2 Apr 2024 21:19:30 -0700
Subject: [PATCH] Adding core handler
---
Makefile | 13 ++++
README.md | 11 +---
src/core/core_test.go | 59 +++++++++++++++++
src/core/handler.go | 35 +++++++++++
src/core/handler_test.go | 20 ++++++
src/repository/account.go | 21 +++++++
src/repository/account_test.go | 101 ++++++++++++++++++++++++++++++
src/repository/repository_test.go | 57 +++++++++++++++++
8 files changed, 307 insertions(+), 10 deletions(-)
create mode 100644 Makefile
create mode 100644 src/core/core_test.go
create mode 100644 src/core/handler.go
create mode 100644 src/core/handler_test.go
create mode 100644 src/repository/account_test.go
create mode 100644 src/repository/repository_test.go
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..806300a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,13 @@
+build:
+ go build -o ./bin/app ./src/cmd/app/main.go
+
+run:
+ GOOS=windows $env:GO_ENV="test"; go run ./src/cmd/app/main.go
+ GOOS=linux GO_ENV=test go run ./src/cmd/app/main.go
+
+test:
+ go test -p 1 -coverpkg=./... -v
+
+cover:
+ go test -p 1 -coverprofile="coverage.out" ./...
+ go tool cover -html="coverage.out"
diff --git a/README.md b/README.md
index 9a83ff8..66d9075 100644
--- a/README.md
+++ b/README.md
@@ -24,13 +24,4 @@ GitOps Domain Snapshot Orchestrator for Switcher API
# Features
- Manage Switchers in a GitOps manner
- Multiple and Independent Environments
-- Two-way Sync allow you to use the Switcher API Management, Slack App and GitOps at the same time
-
-## Run Project
-
-- Running
- Windows: `$env:GO_ENV="test"; go run ./src/cmd/app/main.go`
- Unit: `GO_ENV=test go run ./src/cmd/app/main.go`
-- Testing `go test -coverpkg=./... -v`
-- Coverage `go test -coverprofile="coverage.out" ./... && go tool cover -html="coverage.out"`
-- Building `go build -o ./bin/app ./src/cmd/app/main.go`
\ No newline at end of file
+- Two-way Sync allow you to use the Switcher API Management, Slack App and GitOps at the same time
\ No newline at end of file
diff --git a/src/core/core_test.go b/src/core/core_test.go
new file mode 100644
index 0000000..3b13276
--- /dev/null
+++ b/src/core/core_test.go
@@ -0,0 +1,59 @@
+package core
+
+import (
+ "context"
+ "os"
+ "testing"
+
+ "github.com/switcherapi/switcher-gitops/src/config"
+ "github.com/switcherapi/switcher-gitops/src/db"
+ "github.com/switcherapi/switcher-gitops/src/model"
+ "github.com/switcherapi/switcher-gitops/src/repository"
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+var mongoDb *mongo.Database
+var coreHandler *CoreHandler
+
+func TestMain(m *testing.M) {
+ setup()
+ code := m.Run()
+ shutdown()
+ os.Exit(code)
+}
+
+func setup() {
+ os.Setenv("GO_ENV", "test")
+ config.InitEnv()
+ mongoDb = db.InitDb()
+
+ accountRepository := repository.NewAccountRepositoryMongo(mongoDb)
+ coreHandler = NewCoreHandler(accountRepository)
+}
+
+func shutdown() {
+ mongoDb.Drop(context.Background())
+ mongoDb.Client().Disconnect(context.Background())
+}
+
+// Fixtures
+
+func givenAccount() model.Account {
+ return model.Account{
+ Repository: "switcherapi/switcher-gitops",
+ Branch: "master",
+ Domain: model.DomainDetails{
+ ID: "123",
+ Name: "Switcher GitOps",
+ Version: "123",
+ LastCommit: "123",
+ Status: "active",
+ Message: "Synced successfully",
+ },
+ Settings: model.Settings{
+ Active: true,
+ Window: "10m",
+ ForcePrune: false,
+ },
+ }
+}
diff --git a/src/core/handler.go b/src/core/handler.go
new file mode 100644
index 0000000..6936b63
--- /dev/null
+++ b/src/core/handler.go
@@ -0,0 +1,35 @@
+package core
+
+import (
+ "github.com/switcherapi/switcher-gitops/src/model"
+ "github.com/switcherapi/switcher-gitops/src/repository"
+)
+
+type CoreHandler struct {
+ AccountRepository repository.AccountRepository
+ status int
+}
+
+func NewCoreHandler(repo repository.AccountRepository) *CoreHandler {
+ return &CoreHandler{
+ AccountRepository: repo,
+ }
+}
+
+func (c *CoreHandler) InitCoreHandlerCoroutine() (int, error) {
+ // Load all accounts
+ accounts, _ := c.AccountRepository.FetchAllActiveAccounts()
+
+ // Iterate over accounts and start a new account handler
+ for _, account := range accounts {
+ c.startNewAccountHandler(account)
+ }
+
+ // Update core handler status
+ c.status = 1
+ return c.status, nil
+}
+
+func (c *CoreHandler) startNewAccountHandler(account model.Account) {
+ c.AccountRepository.FetchByDomainId(account.Domain.ID)
+}
diff --git a/src/core/handler_test.go b/src/core/handler_test.go
new file mode 100644
index 0000000..2e42044
--- /dev/null
+++ b/src/core/handler_test.go
@@ -0,0 +1,20 @@
+package core
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestInitCoreHandlerCoroutine(t *testing.T) {
+ // Given
+ account1 := givenAccount()
+ coreHandler.AccountRepository.Create(&account1)
+
+ // Test
+ status, err := coreHandler.InitCoreHandlerCoroutine()
+
+ // Assert
+ assert.Nil(t, err)
+ assert.Equal(t, 1, status)
+}
diff --git a/src/repository/account.go b/src/repository/account.go
index c4be9e3..7f760ea 100644
--- a/src/repository/account.go
+++ b/src/repository/account.go
@@ -15,6 +15,7 @@ import (
type AccountRepository interface {
Create(account *model.Account) (*model.Account, error)
FetchByDomainId(domainId string) (*model.Account, error)
+ FetchAllActiveAccounts() ([]model.Account, error)
Update(account *model.Account) (*model.Account, error)
DeleteByDomainId(domainId string) error
}
@@ -32,6 +33,7 @@ func (err ErrAccountNotFound) Error() string {
}
const domainIdFilter = "domain.id"
+const settingsActiveFilter = "settings.active"
func NewAccountRepositoryMongo(db *mongo.Database) *AccountRepositoryMongo {
registerAccountRepositoryValidators(db)
@@ -65,6 +67,25 @@ func (repo *AccountRepositoryMongo) FetchByDomainId(domainId string) (*model.Acc
return &account, nil
}
+func (repo *AccountRepositoryMongo) FetchAllActiveAccounts() ([]model.Account, error) {
+ collection, ctx, cancel := getDbContext(repo)
+ defer cancel()
+
+ filter := primitive.M{settingsActiveFilter: true}
+ cursor, _ := collection.Find(ctx, filter)
+
+ var accounts []model.Account
+ for cursor.Next(ctx) {
+ var account model.Account
+ err := cursor.Decode(&account)
+ if err == nil {
+ accounts = append(accounts, account)
+ }
+ }
+
+ return accounts, nil
+}
+
func (repo *AccountRepositoryMongo) Update(account *model.Account) (*model.Account, error) {
collection, ctx, cancel := getDbContext(repo)
defer cancel()
diff --git a/src/repository/account_test.go b/src/repository/account_test.go
new file mode 100644
index 0000000..a33b7c6
--- /dev/null
+++ b/src/repository/account_test.go
@@ -0,0 +1,101 @@
+package repository
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCreateAccount(t *testing.T) {
+ // Given
+ account := givenAccount(true)
+
+ // Test
+ createdAccount, err := accountRepository.Create(&account)
+
+ // Assert
+ assert.Nil(t, err)
+ assert.NotNil(t, createdAccount.ID)
+}
+
+func TestFetchAccountByDomainId(t *testing.T) {
+ // Given
+ account := givenAccount(true)
+ accountRepository.Create(&account)
+
+ // Test
+ fetchedAccount, err := accountRepository.FetchByDomainId(account.Domain.ID)
+
+ // Assert
+ assert.Nil(t, err)
+ assert.NotNil(t, fetchedAccount.ID)
+}
+
+func TestFetchAccountByDomainIdNotFound(t *testing.T) {
+ // Test
+ _, err := accountRepository.FetchByDomainId("non_existent_domain_id")
+
+ // Assert
+ assert.NotNil(t, err)
+}
+
+func TestFetchAllActiveAccounts(t *testing.T) {
+ // Given
+ account1 := givenAccount(true)
+ account2 := givenAccount(false)
+ accountRepository.Create(&account1)
+ accountRepository.Create(&account2)
+
+ // Test
+ accounts, err := accountRepository.FetchAllActiveAccounts()
+
+ // Assert
+ assert.Nil(t, err)
+ assert.Equal(t, 1, len(accounts))
+}
+
+func TestUpdateAccount(t *testing.T) {
+ // Given
+ account := givenAccount(true)
+ accountRepository.Create(&account)
+
+ // Test
+ account.Branch = "new_branch"
+ updatedAccount, err := accountRepository.Update(&account)
+
+ // Assert
+ assert.Nil(t, err)
+ assert.Equal(t, "new_branch", updatedAccount.Branch)
+}
+
+func TestUpdateAccountNotFound(t *testing.T) {
+ // Given
+ account := givenAccount(true)
+ account.Domain.ID = "non_existent_domain_id"
+
+ // Test
+ _, err := accountRepository.Update(&account)
+
+ // Assert
+ assert.NotNil(t, err)
+}
+
+func TestDeleteAccount(t *testing.T) {
+ // Given
+ account := givenAccount(true)
+ accountRepository.Create(&account)
+
+ // Test
+ err := accountRepository.DeleteByDomainId(account.Domain.ID)
+
+ // Assert
+ assert.Nil(t, err)
+}
+
+func TestDeleteAccountNotFound(t *testing.T) {
+ // Test
+ err := accountRepository.DeleteByDomainId("non_existent_domain_id")
+
+ // Assert
+ assert.NotNil(t, err)
+}
diff --git a/src/repository/repository_test.go b/src/repository/repository_test.go
new file mode 100644
index 0000000..f5fee84
--- /dev/null
+++ b/src/repository/repository_test.go
@@ -0,0 +1,57 @@
+package repository
+
+import (
+ "context"
+ "os"
+ "testing"
+
+ "github.com/switcherapi/switcher-gitops/src/config"
+ "github.com/switcherapi/switcher-gitops/src/db"
+ "github.com/switcherapi/switcher-gitops/src/model"
+ "go.mongodb.org/mongo-driver/mongo"
+)
+
+var mongoDb *mongo.Database
+var accountRepository *AccountRepositoryMongo
+
+func TestMain(m *testing.M) {
+ setup()
+ code := m.Run()
+ shutdown()
+ os.Exit(code)
+}
+
+func setup() {
+ os.Setenv("GO_ENV", "test")
+ config.InitEnv()
+ mongoDb = db.InitDb()
+
+ accountRepository = NewAccountRepositoryMongo(mongoDb)
+}
+
+func shutdown() {
+ mongoDb.Drop(context.Background())
+ mongoDb.Client().Disconnect(context.Background())
+}
+
+// Fixtures
+
+func givenAccount(active bool) model.Account {
+ return model.Account{
+ Repository: "switcherapi/switcher-gitops",
+ Branch: "master",
+ Domain: model.DomainDetails{
+ ID: "123",
+ Name: "Switcher GitOps",
+ Version: "123",
+ LastCommit: "123",
+ Status: "active",
+ Message: "Synced successfully",
+ },
+ Settings: model.Settings{
+ Active: active,
+ Window: "10m",
+ ForcePrune: false,
+ },
+ }
+}