From a15fb472d49fb44834765f5d3d63dd6cdf5cfc98 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Tue, 19 Sep 2023 16:59:02 +0200 Subject: [PATCH 01/10] feat: redesign artefacts --- momentum-core/.gitignore | 1 + momentum-core/README.md | 1 + momentum-core/artefacts/artefact-tree.go | 328 ++++++++++ momentum-core/artefacts/artefact-tree_test.go | 25 + momentum-core/artefacts/model.go | 41 ++ momentum-core/artefacts/routes.go | 126 ++++ momentum-core/clients/git-client.go | 192 ------ momentum-core/clients/git-client_test.go | 51 -- momentum-core/config/config.go | 46 +- momentum-core/{models => config}/error.go | 2 +- momentum-core/config/routes.go | 14 + momentum-core/dispatcher.go | 38 +- momentum-core/docs/docs.go | 595 ++++++++++++++++-- momentum-core/docs/swagger.json | 593 +++++++++++++++-- momentum-core/docs/swagger.yaml | 429 +++++++++++-- momentum-core/files/files.go | 28 + momentum-core/files/model.go | 52 ++ momentum-core/files/routes.go | 99 +++ momentum-core/main.go | 28 +- momentum-core/models/application.go | 66 -- momentum-core/models/deployment.go | 71 --- momentum-core/models/keyvalue.go | 122 ---- momentum-core/models/repository.go | 57 -- momentum-core/models/stage.go | 73 --- momentum-core/routers/application-router.go | 144 ----- momentum-core/routers/deployment-router.go | 124 ---- momentum-core/routers/repository-router.go | 238 ------- momentum-core/routers/stage-router.go | 124 ---- momentum-core/routers/template-router.go | 7 - momentum-core/routers/value-router.go | 153 ----- momentum-core/services/application-service.go | 125 ---- momentum-core/services/deployment-service.go | 206 ------ .../services/deployment-service_test.go | 11 - momentum-core/services/repository-service.go | 120 ---- momentum-core/services/stage-service.go | 165 ----- momentum-core/services/template-service.go | 298 --------- .../services/template-service_test.go | 99 --- momentum-core/services/tree-service.go | 126 ---- momentum-core/services/value-service.go | 120 ---- momentum-core/tree/momentum-tree.go | 18 +- 40 files changed, 2250 insertions(+), 2906 deletions(-) create mode 100644 momentum-core/artefacts/artefact-tree.go create mode 100644 momentum-core/artefacts/artefact-tree_test.go create mode 100644 momentum-core/artefacts/model.go create mode 100644 momentum-core/artefacts/routes.go delete mode 100644 momentum-core/clients/git-client_test.go rename momentum-core/{models => config}/error.go (97%) create mode 100644 momentum-core/config/routes.go create mode 100644 momentum-core/files/files.go create mode 100644 momentum-core/files/model.go create mode 100644 momentum-core/files/routes.go delete mode 100644 momentum-core/models/application.go delete mode 100644 momentum-core/models/deployment.go delete mode 100644 momentum-core/models/keyvalue.go delete mode 100644 momentum-core/models/repository.go delete mode 100644 momentum-core/models/stage.go delete mode 100644 momentum-core/routers/application-router.go delete mode 100644 momentum-core/routers/deployment-router.go delete mode 100644 momentum-core/routers/repository-router.go delete mode 100644 momentum-core/routers/stage-router.go delete mode 100644 momentum-core/routers/template-router.go delete mode 100644 momentum-core/routers/value-router.go delete mode 100644 momentum-core/services/application-service.go delete mode 100644 momentum-core/services/deployment-service.go delete mode 100644 momentum-core/services/deployment-service_test.go delete mode 100644 momentum-core/services/repository-service.go delete mode 100644 momentum-core/services/stage-service.go delete mode 100644 momentum-core/services/template-service.go delete mode 100644 momentum-core/services/template-service_test.go delete mode 100644 momentum-core/services/tree-service.go delete mode 100644 momentum-core/services/value-service.go diff --git a/momentum-core/.gitignore b/momentum-core/.gitignore index 3484ca2..353f72f 100644 --- a/momentum-core/.gitignore +++ b/momentum-core/.gitignore @@ -1,2 +1,3 @@ +.vscode/* ./dev-setup.sh momentum-core \ No newline at end of file diff --git a/momentum-core/README.md b/momentum-core/README.md index 17d5152..be63ac5 100644 --- a/momentum-core/README.md +++ b/momentum-core/README.md @@ -8,6 +8,7 @@ The core implements a REST-API empowering consumers to manage their repository i | Name | Description | Mandatory |--------------|-------------|----------- +| MOMENTUM_GIT_REPO_URL | The repository which shall be cloned on startup (if not already on disk) | yes | MOMENTUM_GIT_USER | Username for user who creates transactions | yes | MOMENTUM_GIT_EMAIL | Email for the user who creates the transactions | yes | MOMENTUM_GIT_TOKEN | Access token which belongs to the user who creates the transaction | yes diff --git a/momentum-core/artefacts/artefact-tree.go b/momentum-core/artefacts/artefact-tree.go new file mode 100644 index 0000000..a216146 --- /dev/null +++ b/momentum-core/artefacts/artefact-tree.go @@ -0,0 +1,328 @@ +package artefacts + +import ( + "errors" + "momentum-core/config" + "momentum-core/utils" + "os" + "path/filepath" + "strings" +) + +const META_PREFIX = "_" +const DEPLOYMENT_WRAP_FOLDER_NAME = "_deploy" + +const LOAD_ENTIRE_TREE = -1 + +func LoadArtefactTree() (*Artefact, error) { + + return LoadArtefactTreeFrom(filepath.Join(config.GLOBAL.RepoDir(), config.MOMENTUM_ROOT)) +} + +func LoadArtefactTreeFrom(root string) (*Artefact, error) { + + return loadArtefactTreeUntilDepth(root, nil, LOAD_ENTIRE_TREE) +} + +func WriteToString(artefact *Artefact) string { + + return writeToString(artefact, 0, "") +} + +func Root(artefact *Artefact) *Artefact { + + current := artefact + for current.Parent != nil { + current = current.Parent + } + + return current +} + +func NewArtefact(path string, parent *Artefact) (*Artefact, error) { + + f, err := os.Stat(path) + if os.IsNotExist(err) { + return nil, errors.New("path " + path + " does not exist") + } + + artefact := new(Artefact) + artefact.Id, err = utils.GenerateId(idGenerationPath(path)) + if err != nil { + return nil, err + } + + artefact.Name = f.Name() + artefact.Content = make([]*Artefact, 0) + + if parent != nil { + artefact.Parent = parent + artefact.ParentId = artefact.Parent.Id + artefact.Parent.Content = append(artefact.Parent.Content, artefact) + artefact.Parent.ContentIds = append(artefact.Parent.ContentIds, artefact.Id) + } + + if artefact.Parent == nil { + artefact.ArtefactType = ROOT + } else if f.Mode().IsRegular() { + artefact.ArtefactType = FILE + } else if strings.HasPrefix(f.Name(), META_PREFIX) { + artefact.ArtefactType = META + } else if IsApplication(artefact) { + artefact.ArtefactType = APPLICATION + } else if IsDeployment(artefact) { + artefact.ArtefactType = DEPLOYMENT + } else if IsStage(artefact) { + artefact.ArtefactType = STAGE + } else { + return nil, errors.New("unable to decide artefact type") + } + + return artefact, nil +} + +func Applications() []*Artefact { + + t, err := LoadArtefactTree() + if err != nil { + return make([]*Artefact, 0) + } + + applications := make([]*Artefact, 0) + for _, chld := range t.Content { + if chld.ArtefactType == APPLICATION { + applications = append(applications, chld) + } + } + + return applications +} + +func StagesByApplication(applicationOrStageId string) []*Artefact { + + t, err := LoadArtefactTree() + if err != nil { + return make([]*Artefact, 0) + } + + artefacts := FlatPreorder(t, make([]*Artefact, 0)) + stages := make([]*Artefact, 0) + for _, artefact := range artefacts { + if artefact.ArtefactType == STAGE && artefact.Parent.Id == applicationOrStageId { + stages = append(stages, artefact) + } + } + + return stages +} + +func DeploymentsByStage(stageId string) []*Artefact { + + t, err := LoadArtefactTree() + if err != nil { + return make([]*Artefact, 0) + } + + artefacts := FlatPreorder(t, make([]*Artefact, 0)) + deployments := make([]*Artefact, 0) + for _, artefact := range artefacts { + if artefact.ArtefactType == DEPLOYMENT && artefact.Parent.Id == stageId { + deployments = append(deployments, artefact) + } + } + + return deployments +} + +func FileById(id string) (*Artefact, error) { + + artefacts, err := LoadArtefactTree() // origin + + if err != nil { + return nil, err + } + + files := Files(artefacts) + for _, file := range files { + if file.Id == id { + return file, nil + } + } + + return nil, errors.New("no file with id " + id) +} + +func Files(origin *Artefact) []*Artefact { + + flattened := FlatPreorder(origin, make([]*Artefact, 0)) + files := make([]*Artefact, 0) + for _, artefact := range flattened { + if artefact.ArtefactType == FILE { + files = append(files, artefact) + } + } + + return files +} + +func IsApplication(artefact *Artefact) bool { + + if artefact != nil && artefact.Parent != nil { + if artefact.Parent.Name == config.MOMENTUM_ROOT { + return true + } + } + + return false +} + +func IsStage(artefact *Artefact) bool { + + if artefact.Parent != nil && + artefact.ArtefactType != FILE && + !IsApplication(artefact) && + !IsDeployment(artefact) { + + return true + } + + return false +} + +func IsDeployment(artefact *Artefact) bool { + + if artefact != nil && artefact.Parent != nil { + if artefact.Parent.Name == DEPLOYMENT_WRAP_FOLDER_NAME { + return true + } + } + + return false +} + +func FlatPreorder(root *Artefact, result []*Artefact) []*Artefact { + + if root == nil { + return result + } + + result = append(result, root) + + if len(root.Content) > 0 { + for _, child := range root.Content { + result = FlatPreorder(child, result) + } + } + + return result +} + +// checks wether the given artefact has a predecessor with given id +func hasAnyPredecessor(artefact *Artefact, predecessorId string) bool { + + current := artefact + for current != nil { + if current.Id == predecessorId { + return true + } + current = current.Parent + } + + return false +} + +func FullPath(artefact *Artefact) string { + + current := artefact + path := "" + for current != nil { + path = filepath.Join(current.Name, path) + current = current.Parent + } + + return filepath.Join(config.GLOBAL.RepoDir(), path) +} + +func loadArtefactTreeUntilDepth(path string, parent *Artefact, depth int) (*Artefact, error) { + + artefact, err := NewArtefact(path, parent) + if err != nil { + return nil, err + } + + if artefact.ArtefactType != FILE && (depth > 0 || depth <= LOAD_ENTIRE_TREE) { + + dir, err := utils.FileOpen(path, int(os.ModeDir.Perm())) + if err != nil { + return nil, err + } + + dirEntries, err := dir.ReadDir(-1) // reads all entries + for _, entry := range dirEntries { + if entry.Type().IsDir() || entry.Type().IsRegular() { + // we are only interested in "normal" files and directories + childPath := filepath.Join(path, entry.Name()) + _, err := loadArtefactTreeUntilDepth(childPath, artefact, depth-1) + if err != nil { + return nil, err + } + } + } + } + + return artefact, nil +} + +func idGenerationPath(path string) string { + relevantForId, _ := strings.CutPrefix(path, config.GLOBAL.RepoDir()) + return relevantForId +} + +func children(artefact *Artefact) ([]*Artefact, error) { + + childs := make([]*Artefact, 0) + path := FullPath(artefact) + dir, err := utils.FileOpen(path, int(os.ModeDir.Perm())) + if err != nil { + return make([]*Artefact, 0), err + } + + dirEntries, err := dir.ReadDir(-1) // reads all entries + for _, entry := range dirEntries { + if entry.Type().IsDir() || entry.Type().IsRegular() { + // we are only interested in "normal" files and directories + childPath := filepath.Join(path, entry.Name()) + chld, err := NewArtefact(childPath, artefact) + if err != nil { + return make([]*Artefact, 0), err + } + childs = append(childs, chld) + } + } + + return childs, nil +} + +func writeToString(artefact *Artefact, level int, representation string) string { + + internalIntendation := level + for internalIntendation > 0 { + representation += " " + internalIntendation-- + } + + representation += artefact.Name + if artefact.ArtefactType == FILE { + representation += " (FILE, ID: " + artefact.Id + ")" + } else { + representation += " (DIR, ID: " + artefact.Id + ")" + } + representation += "\n" + + for _, child := range artefact.Content { + + representation = writeToString(child, level+1, representation) + } + + return representation +} diff --git a/momentum-core/artefacts/artefact-tree_test.go b/momentum-core/artefacts/artefact-tree_test.go new file mode 100644 index 0000000..5cd833e --- /dev/null +++ b/momentum-core/artefacts/artefact-tree_test.go @@ -0,0 +1,25 @@ +package artefacts_test + +import ( + "fmt" + "momentum-core/artefacts" + "momentum-core/config" + "testing" +) + +func TestArtefactTree(t *testing.T) { + + _, err := config.InitializeMomentumCore() + if err != nil { + fmt.Println(err.Error()) + t.Fail() + } + + artfcts, err := artefacts.LoadArtefactTree() + if err != nil { + fmt.Println(err.Error()) + t.Fail() + } + + fmt.Println(artefacts.WriteToString(artfcts)) +} diff --git a/momentum-core/artefacts/model.go b/momentum-core/artefacts/model.go new file mode 100644 index 0000000..0c99476 --- /dev/null +++ b/momentum-core/artefacts/model.go @@ -0,0 +1,41 @@ +package artefacts + +import "momentum-core/tree" + +type ArtefactType int + +const ( + ROOT ArtefactType = 1 << iota + META + APPLICATION + STAGE + DEPLOYMENT + FILE +) + +type Artefact struct { + Id string `json:"id"` + Name string `json:"name"` + ArtefactType ArtefactType `json:"type"` + ContentIds []string `json:"contentIds"` // id's of children artefacts + Content []*Artefact `json:"-"` + ParentId string `json:"parentId"` // id of parent artefacts + Parent *Artefact `json:"-"` +} + +func toArtefact(n *tree.Node) *Artefact { + + if n == nil { + return nil + } + + artefact := new(Artefact) + artefact.Id = n.Id + artefact.Name = n.NormalizedPath() + + if n.Kind == tree.File { + artefact.ArtefactType = FILE + } + + return artefact +} diff --git a/momentum-core/artefacts/routes.go b/momentum-core/artefacts/routes.go new file mode 100644 index 0000000..9d3a6a1 --- /dev/null +++ b/momentum-core/artefacts/routes.go @@ -0,0 +1,126 @@ +package artefacts + +import ( + "errors" + "fmt" + "momentum-core/config" + "net/http" + + "github.com/gin-gonic/gin" +) + +func RegisterArtefactRoutes(engine *gin.Engine) { + engine.GET(config.API_ARTEFACT_BY_ID, GetArtefact) + engine.GET(config.API_APPLICATIONS, GetApplications) + engine.GET(config.API_STAGES, GetStages) + engine.GET(config.API_DEPLOYMENTS, GetDeployments) +} + +// GetArtefact godoc +// +// @Summary get an artefact by id (an artefact can be any of APPLICATION, STAGE or DEPLOYMENT) +// @Tags artefacts +// @Produce json +// @Param id path string true "artefact id" +// @Success 200 {object} Artefact +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/artefact/{id}/ [get] +func GetArtefact(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + + artefactId := c.Param("id") + if artefactId == "" { + c.JSON(http.StatusNotFound, config.NewApiError(errors.New("artefact id not specified"), http.StatusBadRequest, c, traceId)) + return + } + + t, err := LoadArtefactTree() + if err != nil { + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + fmt.Println(WriteToString(t)) + + flattened := FlatPreorder(t, make([]*Artefact, 0)) + for _, artefact := range flattened { + if artefact.Id == artefactId { + fmt.Println(artefact, "artefactId:", artefact.ParentId) + c.JSON(http.StatusOK, artefact) + return + } + } + + return +} + +// GetApplications godoc +// +// @Summary gets a list of all applications +// @Tags artefacts +// @Produce json +// @Success 200 {array} Artefact +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/applications [get] +func GetApplications(c *gin.Context) { + + c.JSON(http.StatusOK, Applications()) +} + +// GetStages godoc +// +// @Summary gets a list of all stages within an application or stage by id. +// @Tags artefacts +// @Produce json +// @Param parentId query string true "application or stage id" +// @Success 200 {object} Artefact +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/stages [get] +func GetStages(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + appOrStageId := c.Query("parentId") + + if appOrStageId == "" { + err := errors.New("request parameter parentId not set") + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + c.JSON(http.StatusOK, StagesByApplication(appOrStageId)) +} + +// GetDeployments godoc +// +// @Summary get a list of deployments for a given stage by id +// @Tags artefacts +// @Produce json +// @Param stageId query string true "stage id" +// @Success 200 {object} Artefact +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/deployments [get] +func GetDeployments(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + stageId := c.Query("stageId") + + if stageId == "" { + err := errors.New("request parameter stageId not set") + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + c.JSON(http.StatusOK, DeploymentsByStage(stageId)) +} diff --git a/momentum-core/clients/git-client.go b/momentum-core/clients/git-client.go index 8b24aa5..c6916b2 100644 --- a/momentum-core/clients/git-client.go +++ b/momentum-core/clients/git-client.go @@ -1,10 +1,7 @@ package clients import ( - "errors" - "fmt" "momentum-core/config" - "momentum-core/utils" "os" git "gopkg.in/src-d/go-git.v4" @@ -18,9 +15,7 @@ type GitClient struct { func NewGitClient(config *config.MomentumConfig) *GitClient { gitClient := new(GitClient) - gitClient.config = config - return gitClient } @@ -33,105 +28,6 @@ type GitTransaction struct { var transactions []*GitTransaction = make([]*GitTransaction, 0) -func InitGitTransaction(path string, name string) (string, error) { - - repo, err := repository(path) - if err != nil { - return "", err - } - - id, err := utils.GenerateId(path + name) - if err != nil { - return "", err - } - - transaction := new(GitTransaction) - - transaction.id = id - transaction.path = path - transaction.name = name - - headRef, err := repo.Head() - if err != nil { - return "", err - } - transaction.headRef = headRef - - transactions = append(transactions, transaction) - - return transaction.id, nil -} - -func GitTransactionWrite(path string, transactionId string) error { - - transaction, err := transaction(transactionId) - if err != nil { - return err - } - - worktree, err := worktree(transaction.path) - if err != nil { - return err - } - - err = add(path, worktree) - if err != nil { - return err - } - - err = commit(transaction.path, "feat: added "+utils.LastPartOfPath(path)+" (ID:"+transactionId+")") - if err != nil { - return err - } - - return nil -} - -func GitTransactionCommit(transactionId string) error { - - t, err := transaction(transactionId) - if err != nil { - return err - } - - err = push(t.path) - if err != nil { - return err - } - - return nil -} - -func GitTransactionRollback(transactionId string) error { - - t, err := transaction(transactionId) - if err != nil { - return err - } - - repo, err := worktree(t.path) - if err != nil { - return err - } - - repo.Reset(&git.ResetOptions{ - Commit: t.headRef.Hash(), - }) - - return nil -} - -func transaction(transactionId string) (*GitTransaction, error) { - - for _, t := range transactions { - if t.id == transactionId { - return t, nil - } - } - - return nil, errors.New("invalid transactionId=" + transactionId) -} - func CloneRepoTo(url string, username string, password string, location string) error { _, err := git.PlainClone(location, false, &git.CloneOptions{ URL: url, @@ -141,91 +37,3 @@ func CloneRepoTo(url string, username string, password string, location string) return err } - -func pullRepo(location string) error { - - repo, err := git.PlainOpen(location) - if err != nil { - return err - } - - worktree, err := repo.Worktree() - if err != nil { - return err - } - - err = worktree.Pull(&git.PullOptions{RemoteName: "origin"}) - if err != nil && err.Error() != "already up-to-date" { - // TODO is there a more elegant solution? - return err - } - return nil -} - -func repository(location string) (*git.Repository, error) { - - repo, err := git.PlainOpen(location) - if err != nil { - fmt.Println("opening git repo at", location, "failed:", err.Error()) - return nil, err - } - - return repo, nil -} - -func worktree(location string) (*git.Worktree, error) { - - repo, err := repository(location) - if err != nil { - return nil, err - } - - worktree, err := repo.Worktree() - if err != nil { - fmt.Println("reading worktree failed git repo failed:", err.Error()) - return nil, err - } - - return worktree, nil -} - -func add(location string, worktree *git.Worktree) error { - - _, err := worktree.Add(location) - if err != nil { - fmt.Println("adding changes in worktree failed failed:", err.Error()) - return err - } - return nil -} - -func commit(location string, commitMsg string) error { - - worktree, err := worktree(location) - if err != nil { - return err - } - - _, err = worktree.Commit(commitMsg, &git.CommitOptions{}) - if err != nil { - fmt.Println("committing git repo failed:", err.Error()) - return err - } - - return nil -} - -func push(location string) error { - - repo, err := repository(location) - if err != nil { - return err - } - - err = repo.Push(&git.PushOptions{}) - if err != nil { - return err - } - - return nil -} diff --git a/momentum-core/clients/git-client_test.go b/momentum-core/clients/git-client_test.go deleted file mode 100644 index 348dc4e..0000000 --- a/momentum-core/clients/git-client_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package clients_test - -import ( - "fmt" - "momentum-core/clients" - "momentum-core/utils" - "os" - "testing" -) - -const TEST_LOCATION = "testdata" -const TEST_REPO = "https://github.com/Joel-Haeberli/momentum-test-strcuture-2" - -func FILESYSTEMTEST_TestTransactionCycle(t *testing.T) { - - clients.CloneRepoTo(TEST_REPO, "", "", TEST_LOCATION) - - transactionId, err := clients.InitGitTransaction(TEST_LOCATION, "test transaction") - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - filePath := utils.BuildPath(TEST_LOCATION, "testtransactionfile.txt") - f, err := utils.FileOpen(filePath, os.O_CREATE|os.O_RDWR) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - _, err = f.WriteString("this is a test") - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - f.Close() - - err = clients.GitTransactionWrite(filePath, transactionId) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - err = clients.GitTransactionCommit(transactionId) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - utils.DirDelete(TEST_LOCATION) -} diff --git a/momentum-core/config/config.go b/momentum-core/config/config.go index bef810d..0120a7c 100644 --- a/momentum-core/config/config.go +++ b/momentum-core/config/config.go @@ -4,6 +4,9 @@ import ( "errors" "momentum-core/utils" "os" + "path/filepath" + + git "gopkg.in/src-d/go-git.v4" gittransaction "github.com/Joel-Haeberli/git-transaction" ) @@ -12,9 +15,12 @@ const MOMENTUM_ROOT = "momentum-root" const TRANSACTION_MODE = gittransaction.DEBUG -const MOMENTUM_GIT_USER = "MOMENTUM_GIT_USER" -const MOMENTUM_GIT_EMAIL = "MOMENTUM_GIT_EMAIL" -const MOMENTUM_GIT_TOKEN = "MOMENTUM_GIT_TOKEN" +const MOMENTUM_GIT_USER = "MOMENTUM_GIT_USER" // the git username associated with the repositories token +const MOMENTUM_GIT_EMAIL = "MOMENTUM_GIT_EMAIL" // the email belonging to the user associated with the repository token +const MOMENTUM_GIT_TOKEN = "MOMENTUM_GIT_TOKEN" // the access token associated with the repository token +const MOMENTUM_GIT_REPO_URL = "MOMENTUM_GIT_REPO_URL" // the HTTP url to the git repository the instance is working on + +var GLOBAL *MomentumConfig = nil // set on initialization, otherwise crash type ILoggerClient interface { LogTrace(msg string, traceId string) @@ -44,6 +50,10 @@ func (m *MomentumConfig) DataDir() string { return m.dataDir } +func (m *MomentumConfig) RepoDir() string { + return filepath.Join(m.dataDir, "repository") +} + func (m *MomentumConfig) ValidationTmpDir() string { return m.validationTmpDir } @@ -97,6 +107,24 @@ func (m *MomentumConfig) checkMandatoryTemplates() error { return nil } +func (m *MomentumConfig) initializeRepository() error { + + _, err := os.Stat(m.RepoDir()) + if !os.IsNotExist(err) { + LOGGER.LogInfo("will not clone repository because one present", "STARTUP") + return nil + } + + repoUrl := os.Getenv(MOMENTUM_GIT_REPO_URL) + if repoUrl == "" { + return errors.New("failed initializing momentum because " + MOMENTUM_GIT_REPO_URL + " was not set") + } + + cloneRepoTo(repoUrl, "", "", m.RepoDir()) + + return nil +} + func (m *MomentumConfig) initializeGitAccessToken() error { if TRANSACTION_MODE == gittransaction.DEBUG { @@ -162,6 +190,8 @@ func InitializeMomentumCore() (*MomentumConfig, error) { panic("failed initializing logger: " + err.Error()) } + GLOBAL = config + return config, err } @@ -174,3 +204,13 @@ func createPathIfNotPresent(path string, parentDir string) { utils.DirCreate(path) } } + +func cloneRepoTo(url string, username string, password string, location string) error { + _, err := git.PlainClone(location, false, &git.CloneOptions{ + URL: url, + Progress: os.Stdout, + // Auth: ..., TODO in case not public dir + }) + + return err +} diff --git a/momentum-core/models/error.go b/momentum-core/config/error.go similarity index 97% rename from momentum-core/models/error.go rename to momentum-core/config/error.go index ae59fad..9160d5f 100644 --- a/momentum-core/models/error.go +++ b/momentum-core/config/error.go @@ -1,4 +1,4 @@ -package models +package config import "github.com/gin-gonic/gin" diff --git a/momentum-core/config/routes.go b/momentum-core/config/routes.go new file mode 100644 index 0000000..5130319 --- /dev/null +++ b/momentum-core/config/routes.go @@ -0,0 +1,14 @@ +package config + +const API = "/api" +const API_VERSION_BETA = API + "/beta" + +const API_FILE_BY_ID = API_VERSION_BETA + "/file/:id" +const API_DIR_BY_ID = API_VERSION_BETA + "/dir/:id" +const API_FILE_LINE_OVERWRITTENBY = API_VERSION_BETA + "/file/:id/line/:lineNumber/overwritten-by" +const API_FILE_LINE_OVERWRITES = API_VERSION_BETA + "/file/:id/line/:lineNumber/overwrites" + +const API_ARTEFACT_BY_ID = API_VERSION_BETA + "/artefact/:id" +const API_APPLICATIONS = API_VERSION_BETA + "/applications" +const API_STAGES = API_VERSION_BETA + "/stages" +const API_DEPLOYMENTS = API_VERSION_BETA + "/deployments" diff --git a/momentum-core/dispatcher.go b/momentum-core/dispatcher.go index dbe2771..3ca8b61 100644 --- a/momentum-core/dispatcher.go +++ b/momentum-core/dispatcher.go @@ -1,8 +1,9 @@ package main import ( + "momentum-core/artefacts" "momentum-core/config" - "momentum-core/routers" + "momentum-core/files" "github.com/gin-gonic/gin" @@ -13,41 +14,18 @@ import ( ) type Dispatcher struct { - server *gin.Engine - config *config.MomentumConfig - repositoryRouter *routers.RepositoryRouter - applicationRouter *routers.ApplicationRouter - stageRouter *routers.StageRouter - deploymentRouter *routers.DeploymentRouter - valueRouter *routers.ValueRouter - templateRouter *routers.TemplateRouter + server *gin.Engine + config *config.MomentumConfig } -func NewDispatcher(config *config.MomentumConfig, - repositoryRouter *routers.RepositoryRouter, - applicationRouter *routers.ApplicationRouter, - stageRouter *routers.StageRouter, - deploymentRouter *routers.DeploymentRouter, - valueRouter *routers.ValueRouter, - templateRouter *routers.TemplateRouter) *Dispatcher { +func NewDispatcher(config *config.MomentumConfig) *Dispatcher { dispatcher := new(Dispatcher) - - dispatcher.server = gin.Default() - dispatcher.config = config + dispatcher.server = gin.Default() - dispatcher.repositoryRouter = repositoryRouter - dispatcher.applicationRouter = applicationRouter - dispatcher.stageRouter = stageRouter - dispatcher.deploymentRouter = deploymentRouter - dispatcher.valueRouter = valueRouter - - dispatcher.repositoryRouter.RegisterRepositoryRoutes(dispatcher.server) - dispatcher.applicationRouter.RegisterApplicationRoutes(dispatcher.server) - dispatcher.stageRouter.RegisterStageRoutes(dispatcher.server) - dispatcher.deploymentRouter.RegisterDeploymentRoutes(dispatcher.server) - dispatcher.valueRouter.RegisterValueRoutes(dispatcher.server) + files.RegisterFileRoutes(dispatcher.server) + artefacts.RegisterArtefactRoutes(dispatcher.server) dispatcher.server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) diff --git a/momentum-core/docs/docs.go b/momentum-core/docs/docs.go index 4e66efb..76078d1 100644 --- a/momentum-core/docs/docs.go +++ b/momentum-core/docs/docs.go @@ -1,5 +1,4 @@ -// Code generated by swaggo/swag. DO NOT EDIT. - +// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -20,6 +19,388 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/beta/applications": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "gets a list of all applications", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/artefacts.Artefact" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/artefact/{id}/": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "get an artefact by id (an artefact can be any of APPLICATION, STAGE or DEPLOYMENT)", + "parameters": [ + { + "type": "string", + "description": "artefact id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/deployments": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "get a list of deployments for a given stage by id", + "parameters": [ + { + "type": "string", + "description": "stage id", + "name": "stageId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/dir/{id}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets the content of a file", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/files.Dir" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets the content of a file", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/files.File" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}/line/{lineNumber}/overwrites": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets a list of child properties, which are overwritten by the given line.", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "line number in file", + "name": "lineNumber", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets a list of properties which overwrite the given line.", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "line number in file", + "name": "lineNumber", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/stages": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "gets a list of all stages within an application or stage by id.", + "parameters": [ + { + "type": "string", + "description": "application or stage id", + "name": "parentId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, "/application": { "post": { "consumes": [ @@ -53,19 +434,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -104,19 +485,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -145,19 +526,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -197,19 +578,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -243,19 +624,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -296,19 +677,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -349,19 +730,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -405,19 +786,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -457,19 +838,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -513,19 +894,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -562,19 +943,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -618,19 +999,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -667,19 +1048,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -720,19 +1101,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -773,19 +1154,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -824,19 +1205,19 @@ const docTemplate = `{ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -844,7 +1225,51 @@ const docTemplate = `{ } }, "definitions": { - "models.ApiError": { + "artefacts.Artefact": { + "type": "object", + "properties": { + "contentIds": { + "description": "id's of children artefacts", + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentId": { + "description": "id's of parent", + "type": "string" + }, + "type": { + "$ref": "#/definitions/artefacts.ArtefactType" + } + } + }, + "artefacts.ArtefactType": { + "type": "integer", + "enum": [ + 1, + 2, + 4, + 8, + 16, + 32 + ], + "x-enum-varnames": [ + "ROOT", + "META", + "APPLICATION", + "STAGE", + "DEPLOYMENT", + "FILE" + ] + }, + "config.ApiError": { "type": "object", "properties": { "detail": { @@ -865,6 +1290,72 @@ const docTemplate = `{ } } }, + "files.Dir": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "$ref": "#/definitions/files.File" + } + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "subDirs": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Dir" + } + } + } + }, + "files.File": { + "type": "object", + "properties": { + "body": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + } + } + }, + "files.Overwrite": { + "type": "object", + "properties": { + "originFileId": { + "type": "string" + }, + "originFileLine": { + "type": "integer" + }, + "originFilePath": { + "type": "string" + }, + "overwriteFileId": { + "type": "string" + }, + "overwriteFileLine": { + "type": "integer" + }, + "overwriteFilePath": { + "type": "string" + } + } + }, "models.Application": { "type": "object", "properties": { @@ -1064,7 +1555,7 @@ var SwaggerInfo = &swag.Spec{ Version: "early-alpha", Host: "localhost:8080", BasePath: "/", - Schemes: []string{"http,", "https"}, + Schemes: []string{"http"}, Title: "Momentum Core API", Description: "The momentum core api manages the core structure of momentum", InfoInstanceName: "swagger", diff --git a/momentum-core/docs/swagger.json b/momentum-core/docs/swagger.json index 7836826..3fae5b9 100644 --- a/momentum-core/docs/swagger.json +++ b/momentum-core/docs/swagger.json @@ -1,7 +1,6 @@ { "schemes": [ - "http,", - "https" + "http" ], "swagger": "2.0", "info": { @@ -17,6 +16,388 @@ "host": "localhost:8080", "basePath": "/", "paths": { + "/api/beta/applications": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "gets a list of all applications", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/artefacts.Artefact" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/artefact/{id}/": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "get an artefact by id (an artefact can be any of APPLICATION, STAGE or DEPLOYMENT)", + "parameters": [ + { + "type": "string", + "description": "artefact id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/deployments": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "get a list of deployments for a given stage by id", + "parameters": [ + { + "type": "string", + "description": "stage id", + "name": "stageId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/dir/{id}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets the content of a file", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/files.Dir" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets the content of a file", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/files.File" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}/line/{lineNumber}/overwrites": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets a list of child properties, which are overwritten by the given line.", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "line number in file", + "name": "lineNumber", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "files" + ], + "summary": "gets a list of properties which overwrite the given line.", + "parameters": [ + { + "type": "string", + "description": "file id", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "line number in file", + "name": "lineNumber", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, + "/api/beta/stages": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "artefacts" + ], + "summary": "gets a list of all stages within an application or stage by id.", + "parameters": [ + { + "type": "string", + "description": "application or stage id", + "name": "parentId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/artefacts.Artefact" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/config.ApiError" + } + } + } + } + }, "/application": { "post": { "consumes": [ @@ -50,19 +431,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -101,19 +482,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -142,19 +523,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -194,19 +575,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -240,19 +621,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -293,19 +674,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -346,19 +727,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -402,19 +783,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -454,19 +835,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -510,19 +891,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -559,19 +940,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -615,19 +996,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -664,19 +1045,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -717,19 +1098,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -770,19 +1151,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -821,19 +1202,19 @@ "400": { "description": "Bad Request", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "404": { "description": "Not Found", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } }, "500": { "description": "Internal Server Error", "schema": { - "$ref": "#/definitions/models.ApiError" + "$ref": "#/definitions/config.ApiError" } } } @@ -841,7 +1222,51 @@ } }, "definitions": { - "models.ApiError": { + "artefacts.Artefact": { + "type": "object", + "properties": { + "contentIds": { + "description": "id's of children artefacts", + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "parentId": { + "description": "id's of parent", + "type": "string" + }, + "type": { + "$ref": "#/definitions/artefacts.ArtefactType" + } + } + }, + "artefacts.ArtefactType": { + "type": "integer", + "enum": [ + 1, + 2, + 4, + 8, + 16, + 32 + ], + "x-enum-varnames": [ + "ROOT", + "META", + "APPLICATION", + "STAGE", + "DEPLOYMENT", + "FILE" + ] + }, + "config.ApiError": { "type": "object", "properties": { "detail": { @@ -862,6 +1287,72 @@ } } }, + "files.Dir": { + "type": "object", + "properties": { + "files": { + "type": "array", + "items": { + "$ref": "#/definitions/files.File" + } + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "subDirs": { + "type": "array", + "items": { + "$ref": "#/definitions/files.Dir" + } + } + } + }, + "files.File": { + "type": "object", + "properties": { + "body": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "path": { + "type": "string" + } + } + }, + "files.Overwrite": { + "type": "object", + "properties": { + "originFileId": { + "type": "string" + }, + "originFileLine": { + "type": "integer" + }, + "originFilePath": { + "type": "string" + }, + "overwriteFileId": { + "type": "string" + }, + "overwriteFileLine": { + "type": "integer" + }, + "overwriteFilePath": { + "type": "string" + } + } + }, "models.Application": { "type": "object", "properties": { diff --git a/momentum-core/docs/swagger.yaml b/momentum-core/docs/swagger.yaml index 04d9d25..fc59168 100644 --- a/momentum-core/docs/swagger.yaml +++ b/momentum-core/docs/swagger.yaml @@ -1,6 +1,39 @@ basePath: / definitions: - models.ApiError: + artefacts.Artefact: + properties: + contentIds: + description: id's of children artefacts + items: + type: string + type: array + id: + type: string + name: + type: string + parentId: + description: id's of parent + type: string + type: + $ref: '#/definitions/artefacts.ArtefactType' + type: object + artefacts.ArtefactType: + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + type: integer + x-enum-varnames: + - ROOT + - META + - APPLICATION + - STAGE + - DEPLOYMENT + - FILE + config.ApiError: properties: detail: type: string @@ -14,6 +47,49 @@ definitions: type: type: string type: object + files.Dir: + properties: + files: + items: + $ref: '#/definitions/files.File' + type: array + id: + type: string + name: + type: string + path: + type: string + subDirs: + items: + $ref: '#/definitions/files.Dir' + type: array + type: object + files.File: + properties: + body: + type: string + id: + type: string + name: + type: string + path: + type: string + type: object + files.Overwrite: + properties: + originFileId: + type: string + originFileLine: + type: integer + originFilePath: + type: string + overwriteFileId: + type: string + overwriteFileLine: + type: integer + overwriteFilePath: + type: string + type: object models.Application: properties: id: @@ -150,6 +226,258 @@ info: title: Momentum Core API version: early-alpha paths: + /api/beta/applications: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/artefacts.Artefact' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets a list of all applications + tags: + - artefacts + /api/beta/artefact/{id}/: + get: + parameters: + - description: artefact id + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/artefacts.Artefact' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: get an artefact by id (an artefact can be any of APPLICATION, STAGE + or DEPLOYMENT) + tags: + - artefacts + /api/beta/deployments: + get: + parameters: + - description: stage id + in: query + name: stageId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/artefacts.Artefact' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: get a list of deployments for a given stage by id + tags: + - artefacts + /api/beta/dir/{id}: + get: + parameters: + - description: file id + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/files.Dir' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets the content of a file + tags: + - files + /api/beta/file/{id}: + get: + parameters: + - description: file id + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/files.File' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets the content of a file + tags: + - files + /api/beta/file/{id}/line/{lineNumber}/overwrites: + get: + parameters: + - description: file id + in: path + name: id + required: true + type: string + - description: line number in file + in: path + name: lineNumber + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/files.Overwrite' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets a list of child properties, which are overwritten by the given + line. + tags: + - files + /api/beta/file/{id}/line/{lineNumber}/overwritten-by: + get: + parameters: + - description: file id + in: path + name: id + required: true + type: string + - description: line number in file + in: path + name: lineNumber + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/files.Overwrite' + type: array + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets a list of properties which overwrite the given line. + tags: + - files + /api/beta/stages: + get: + parameters: + - description: application or stage id + in: query + name: parentId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/artefacts.Artefact' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: gets a list of all stages within an application or stage by id. + tags: + - artefacts /application: post: consumes: @@ -171,15 +499,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: add an application tags: - applications @@ -204,15 +532,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get a deployment of a repository by id tags: - deployments @@ -231,15 +559,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: load repositories tags: - repositories @@ -265,15 +593,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: add a new repository tags: - repositories @@ -295,15 +623,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get a repository tags: - repositories @@ -330,15 +658,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get an application of a repository by id tags: - applications @@ -365,15 +693,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get a stage of a repository by id tags: - stages @@ -400,15 +728,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get a deployment of a repository by id tags: - deployments @@ -437,15 +765,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get all values of an application by the applications id tags: - values @@ -471,15 +799,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get all applications of a repository tags: - applications @@ -508,15 +836,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get all values of a deployment by the deployments id tags: - values @@ -540,15 +868,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get deployments tags: - deployments @@ -577,15 +905,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get all values of an stage by the stages id tags: - values @@ -609,15 +937,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get stages tags: - stages @@ -644,15 +972,15 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: get a value of a repository by id tags: - values @@ -677,19 +1005,18 @@ paths: "400": description: Bad Request schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "404": description: Not Found schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' "500": description: Internal Server Error schema: - $ref: '#/definitions/models.ApiError' + $ref: '#/definitions/config.ApiError' summary: add a new stage tags: - stages schemes: -- http, -- https +- http swagger: "2.0" diff --git a/momentum-core/files/files.go b/momentum-core/files/files.go new file mode 100644 index 0000000..e9eb2cc --- /dev/null +++ b/momentum-core/files/files.go @@ -0,0 +1,28 @@ +package files + +import ( + "encoding/base64" + "momentum-core/utils" +) + +func fileToBase64(path string) (string, error) { + + f, err := utils.FileOpen(path, utils.FILE_ALLOW_READ_WRITE_ALL) + if err != nil { + return "", err + } + + fileAsString := utils.FileAsString(f) + + return base64.RawStdEncoding.EncodeToString([]byte(fileAsString)), nil +} + +func fileToRaw(base64Encoded string) (string, error) { + + bytes, err := base64.RawStdEncoding.DecodeString(base64Encoded) + if err != nil { + return "", err + } + + return string(bytes), nil +} diff --git a/momentum-core/files/model.go b/momentum-core/files/model.go new file mode 100644 index 0000000..a81eaa5 --- /dev/null +++ b/momentum-core/files/model.go @@ -0,0 +1,52 @@ +package files + +type IFile interface { + Id() string + Name() string + Body() string // Base64 encoded +} + +type IDir interface { + Id() string + Name() string + SubDirs() []IDir + Files() []IFile +} + +type IOverwrite interface { + OriginFileId() string + OriginFileLine() int + OverwriteFileId() string + OverwriteFileLine() int +} + +type File struct { + Id string + Name string + Body string +} + +type Dir struct { + Id string + Name string + SubDirs []*Dir + Files []*File +} + +type Overwrite struct { + OriginFileId string + OriginFileLine int + OverwriteFileId string + OverwriteFileLine int +} + +func NewFile(id string, name string, encodedBody string) *File { + + f := new(File) + + f.Id = id + f.Name = name + f.Body = encodedBody + + return f +} diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go new file mode 100644 index 0000000..03733a1 --- /dev/null +++ b/momentum-core/files/routes.go @@ -0,0 +1,99 @@ +package files + +import ( + "momentum-core/artefacts" + "momentum-core/config" + "net/http" + + "github.com/gin-gonic/gin" +) + +func RegisterFileRoutes(engine *gin.Engine) { + engine.GET(config.API_FILE_BY_ID, GetFile) + engine.GET(config.API_DIR_BY_ID, GetDir) + engine.GET(config.API_FILE_LINE_OVERWRITTENBY, GetOverwrittenBy) + engine.GET(config.API_FILE_LINE_OVERWRITES, GetOverwrites) +} + +// GetFile godoc +// +// @Summary gets the content of a file +// @Tags files +// @Produce json +// @Param id path string true "file id" +// @Success 200 {object} File +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/file/{id} [get] +func GetFile(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + id := c.Param("id") + + artefact, err := artefacts.FileById(id) + if err != nil { + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + encodedFile, err := fileToBase64(artefacts.FullPath(artefact)) + file := NewFile(artefact.Id, artefact.Name, encodedFile) + + c.JSON(http.StatusOK, file) +} + +// GetDir godoc +// +// @Summary gets the content of a file +// @Tags files +// @Produce json +// @Param id path string true "file id" +// @Success 200 {object} Dir +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/dir/{id} [get] +func GetDir(c *gin.Context) { + + _ = c.Param("id") + + return +} + +// GetOverwrittenBy godoc +// +// @Summary gets a list of properties which overwrite the given line. +// @Tags files +// @Produce json +// @Param id path string true "file id" +// @Param lineNumber path int true "line number in file" +// @Success 200 {array} Overwrite +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/file/{id}/line/{lineNumber}/overwritten-by [get] +func GetOverwrittenBy(c *gin.Context) { + + _ = c.Param("id") + _ = c.Param("lineNumber") +} + +// GetOverwrites godoc +// +// @Summary gets a list of child properties, which are overwritten by the given line. +// @Tags files +// @Produce json +// @Param id path string true "file id" +// @Param lineNumber path int true "line number in file" +// @Success 200 {array} Overwrite +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/file/{id}/line/{lineNumber}/overwrites [get] +func GetOverwrites(c *gin.Context) { + + _ = c.Param("id") + _ = c.Param("lineNumber") +} diff --git a/momentum-core/main.go b/momentum-core/main.go index 28ca829..0a8b029 100644 --- a/momentum-core/main.go +++ b/momentum-core/main.go @@ -2,10 +2,7 @@ package main import ( "fmt" - "momentum-core/clients" "momentum-core/config" - "momentum-core/routers" - "momentum-core/services" _ "github.com/pdrum/swagger-automation/docs" // This line is necessary for go-swagger to find your docs! ) @@ -17,7 +14,7 @@ import ( // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // -// @schemes http, https +// @schemes http // @host localhost:8080 // @BasePath / func main() { @@ -29,25 +26,10 @@ func main() { panic("failed initializing momentum. problem: " + err.Error()) } - gitClient := clients.NewGitClient(config) - kustomizeClient := clients.NewKustomizationValidationClient(config) - - templateService := services.NewTemplateService() - treeService := services.NewTreeService(config) - repositoryService := services.NewRepositoryService(config, treeService, gitClient, kustomizeClient) - applicationService := services.NewApplicationService(config, treeService, templateService) - stageService := services.NewStageService(config, treeService, templateService) - deploymentService := services.NewDeploymentService(config, stageService, templateService, treeService) - valueService := services.NewValueService(treeService) - - templateRouter := routers.NewTemplateRouter() - valueRouter := routers.NewValueRouter(valueService) - deploymentRouter := routers.NewDeploymentRouter(deploymentService, repositoryService, config) - stageRouter := routers.NewStageRouter(stageService, repositoryService, config) - applicationRouter := routers.NewApplicationRouter(applicationService, repositoryService, config) - repositoryRouter := routers.NewRepositoryRouter(repositoryService, applicationService, stageService, deploymentService) - - dispatcher := NewDispatcher(config, repositoryRouter, applicationRouter, stageRouter, deploymentRouter, valueRouter, templateRouter) + // gitClient := clients.NewGitClient(config) + // kustomizeClient := clients.NewKustomizationValidationClient(config) + + dispatcher := NewDispatcher(config) dispatcher.Serve() } diff --git a/momentum-core/models/application.go b/momentum-core/models/application.go deleted file mode 100644 index a4e8f25..0000000 --- a/momentum-core/models/application.go +++ /dev/null @@ -1,66 +0,0 @@ -package models - -import ( - "errors" - "momentum-core/clients" - "momentum-core/tree" - "momentum-core/utils" - - "github.com/gin-gonic/gin" -) - -type ApplicationCreateRequest struct { - Name string `json:"name"` - ReconcileInterval string `json:"reconcileInterval"` - ChartVersion string `json:"chartVersion"` - RepositoryName string `json:"repositoryName"` -} - -type Application struct { - Id string `json:"id"` - Name string `json:"name"` - Path string `json:"-"` - RepositoryName string `json:"repositoryName"` -} - -func ExtractApplicationCreateRequest(c *gin.Context) (*ApplicationCreateRequest, error) { - return utils.Extract[ApplicationCreateRequest](c) -} - -func ExtractApplication(c *gin.Context) (*Application, error) { - return utils.Extract[Application](c) -} - -func ToApplicationFromNode(n *tree.Node, repositoryName string) (*Application, error) { - - if n == nil { - return nil, errors.New("nil node") - } - - app := new(Application) - - app.Id = n.Id - app.Name = n.Path - app.Path = n.FullPath() - app.RepositoryName = repositoryName - - return app, nil -} - -func ToApplication(data []byte) (*Application, error) { - - app, err := clients.UnmarshallJson[Application](data) - if err != nil { - return nil, err - } - return app, nil -} - -func (a *Application) ToJson() ([]byte, error) { - - data, err := clients.MarshallJson(a) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/momentum-core/models/deployment.go b/momentum-core/models/deployment.go deleted file mode 100644 index 968e132..0000000 --- a/momentum-core/models/deployment.go +++ /dev/null @@ -1,71 +0,0 @@ -package models - -import ( - "errors" - "momentum-core/clients" - "momentum-core/tree" - "momentum-core/utils" - "strings" - - "github.com/gin-gonic/gin" -) - -type DeploymentCreateRequest struct { - Name string `json:"name"` - ReconcileInterval string `json:"reconcileInterval"` - ChartVersion string `json:"chartVersion"` - ParentStageId string `json:"parentStageId"` - RepositoryName string `json:"repositoryName"` - ApplicationName string `json:"applicationName"` -} - -type Deployment struct { - Id string `json:"id"` - Name string `json:"name"` - Path string `json:"-"` - ParentStageId string `json:"parentStageId"` - RepositoryId string `json:"repositoryId"` -} - -func ExtractDeploymentCreateRequest(c *gin.Context) (*DeploymentCreateRequest, error) { - return utils.Extract[DeploymentCreateRequest](c) -} - -func ExtractDeployment(c *gin.Context) (*Deployment, error) { - return utils.Extract[Deployment](c) -} - -func ToDeploymentFromNode(n *tree.Node, repositoryId string) (*Deployment, error) { - - if n == nil || n.Parent == nil { - return nil, errors.New("nil node or parent") - } - - deployment := new(Deployment) - - deployment.Id = n.Id - deployment.Name = strings.Split(n.Path, "::")[0] - deployment.Path = n.FullPath() - deployment.RepositoryId = repositoryId - deployment.ParentStageId = n.Parent.Id - - return deployment, nil -} - -func ToDeplyoment(data []byte) (*Deployment, error) { - - deployment, err := clients.UnmarshallJson[Deployment](data) - if err != nil { - return nil, err - } - return deployment, nil -} - -func (d *Deployment) ToJson() ([]byte, error) { - - data, err := clients.MarshallJson(d) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/momentum-core/models/keyvalue.go b/momentum-core/models/keyvalue.go deleted file mode 100644 index 1f5a011..0000000 --- a/momentum-core/models/keyvalue.go +++ /dev/null @@ -1,122 +0,0 @@ -package models - -import ( - "errors" - "momentum-core/clients" - "momentum-core/tree" - "momentum-core/utils" - - "github.com/gin-gonic/gin" -) - -type ValueType int - -const ( - REPOSITORY ValueType = iota - APPLICATION - STAGE - DEPLOYMENT -) - -type KeyValueCreateRequest struct { - Key string `json:"key"` - Value string `json:"value"` - DisplayName string `json:"displayName"` - ParentStageId string `json:"parentStageId"` - ParentDeploymentId string `json:"parentDeploymentId"` - ParentKeyValueId string `json:"parentKeyValueId"` -} - -type Value struct { - Id string `json:"id"` - Key string `json:"key"` - Value string `json:"value"` - Path string `json:"-"` - DisplayName string `json:"displayName"` - ParentStageId string `json:"parentStageId"` - ParentDeploymentId string `json:"parentDeploymentId"` -} - -type ValueWrapper struct { - FileId string `json:"parentFileId"` - FileName string `json:"parentFileName"` - ValueType ValueType `json:"valueType"` - Values []*Value `json:"values"` -} - -func ExtractKeyValueCreateRequest(c *gin.Context) (*KeyValueCreateRequest, error) { - return utils.Extract[KeyValueCreateRequest](c) -} - -func ExtractKeyValue(c *gin.Context) (*Value, error) { - return utils.Extract[Value](c) -} - -func ToValueWrapperFromNode(n *tree.Node, valType ValueType) (*ValueWrapper, error) { - - if n.Kind != tree.File { - return nil, errors.New("only files can be converted to a value wrapper") - } - - valueWrapper := new(ValueWrapper) - - valueWrapper.FileId = n.Id - valueWrapper.FileName = n.NormalizedPath() - mappedValues := make([]*Value, 0) - for _, v := range n.Values() { - value, err := ToValueFromNode(v) - if err != nil { - return nil, errors.New("unable to map value from node") - } - mappedValues = append(mappedValues, value) - } - valueWrapper.Values = mappedValues - valueWrapper.ValueType = valType - - return valueWrapper, nil -} - -func ToValueFromNode(n *tree.Node) (*Value, error) { - - if n == nil { - return nil, errors.New("expected a tree node but was nil") - } - - keyValue := new(Value) - - keyValue.Id = n.Id - keyValue.Key = n.FullPath() - keyValue.Value = n.Value - - parentStage := n - - for !parentStage.IsStage() && parentStage.Parent != nil { - if parentStage.Kind == tree.File { - keyValue.ParentDeploymentId = parentStage.Id - } - parentStage = parentStage.Parent - } - keyValue.ParentStageId = parentStage.Id - - keyValue.DisplayName = n.Path - - return keyValue, nil -} - -func ToKeyValue(data []byte) (*Value, error) { - - keyValue, err := clients.UnmarshallJson[Value](data) - if err != nil { - return nil, err - } - return keyValue, nil -} - -func (kv *Value) ToJson() ([]byte, error) { - - data, err := clients.MarshallJson(kv) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/momentum-core/models/repository.go b/momentum-core/models/repository.go deleted file mode 100644 index 9a3f916..0000000 --- a/momentum-core/models/repository.go +++ /dev/null @@ -1,57 +0,0 @@ -package models - -import ( - "momentum-core/clients" - "momentum-core/tree" - "momentum-core/utils" - - "github.com/gin-gonic/gin" -) - -type RepositoryCreateRequest struct { - Name string `json:"name"` - Url string `json:"url"` -} - -type Repository struct { - Id string `json:"id"` - Name string `json:"name"` - Path string `json:"-"` -} - -func ExtractRepository(c *gin.Context) (*Repository, error) { - return utils.Extract[Repository](c) -} - -func ExtractRepositoryCreateRequest(c *gin.Context) (*RepositoryCreateRequest, error) { - return utils.Extract[RepositoryCreateRequest](c) -} - -func ToRepositoryFromNode(n *tree.Node) (*Repository, error) { - - repository := new(Repository) - - repository.Id = n.Id - repository.Name = n.Path - repository.Path = n.FullPath() - - return repository, nil -} - -func ToRepository(data []byte) (*Repository, error) { - - repository, err := clients.UnmarshallJson[Repository](data) - if err != nil { - return nil, err - } - return repository, nil -} - -func (r *Repository) ToJson() ([]byte, error) { - - data, err := clients.MarshallJson(r) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/momentum-core/models/stage.go b/momentum-core/models/stage.go deleted file mode 100644 index a00a8ae..0000000 --- a/momentum-core/models/stage.go +++ /dev/null @@ -1,73 +0,0 @@ -package models - -import ( - "errors" - "momentum-core/clients" - "momentum-core/tree" - "momentum-core/utils" - - "github.com/gin-gonic/gin" -) - -type StageCreateRequest struct { - Name string `json:"name"` - ReconcileInterval string `json:"reconcileInterval"` - ChartVersion string `json:"chartVersion"` - RepositoryName string `json:"repositoryName"` - ParentApplicationId string `json:"parentApplicationId"` - ParentStageId string `json:"parentStageId"` -} - -type Stage struct { - Id string `json:"id"` - Name string `json:"name"` - Path string `json:"-"` - ParentApplicationId string `json:"parentApplicationId"` - ParentStageId string `json:"parentStageId"` -} - -func ExtractStageCreateRequest(c *gin.Context) (*StageCreateRequest, error) { - return utils.Extract[StageCreateRequest](c) -} - -func ExtractStage(c *gin.Context) (*Stage, error) { - return utils.Extract[Stage](c) -} - -func ToStageFromNode(n *tree.Node, parentId string) (*Stage, error) { - - if n == nil { - return nil, errors.New("nil node") - } - - stage := new(Stage) - stage.Id = n.Id - stage.Name = n.Path - stage.Path = n.FullPath() - - if n.IsStage() { - stage.ParentStageId = parentId - } else { - stage.ParentApplicationId = parentId - } - - return stage, nil -} - -func ToStage(data []byte) (*Stage, error) { - - stage, err := clients.UnmarshallJson[Stage](data) - if err != nil { - return nil, err - } - return stage, nil -} - -func (a *Stage) ToJson() ([]byte, error) { - - data, err := clients.MarshallJson(a) - if err != nil { - return nil, err - } - return data, nil -} diff --git a/momentum-core/routers/application-router.go b/momentum-core/routers/application-router.go deleted file mode 100644 index bb5d37b..0000000 --- a/momentum-core/routers/application-router.go +++ /dev/null @@ -1,144 +0,0 @@ -package routers - -import ( - "momentum-core/config" - "momentum-core/models" - "momentum-core/services" - "net/http" - - gittransaction "github.com/Joel-Haeberli/git-transaction" - "github.com/gin-gonic/gin" -) - -const ROUTING_PATH_APPLICATION_BY_ID = VERSION + "/repository/:repositoryName/:applicationId" -const ROUTING_PATH_APPLICATION = VERSION + "/application" - -type ApplicationRouter struct { - applicationService *services.ApplicationService - repositoryService *services.RepositoryService - config *config.MomentumConfig -} - -func NewApplicationRouter(applicationService *services.ApplicationService, - repositoryService *services.RepositoryService, - config *config.MomentumConfig, -) *ApplicationRouter { - - router := new(ApplicationRouter) - - router.applicationService = applicationService - router.repositoryService = repositoryService - router.config = config - - return router -} - -func (a *ApplicationRouter) RegisterApplicationRoutes(server *gin.Engine) { - - server.GET(ROUTING_PATH_APPLICATION_BY_ID, a.getApplication) - server.POST(ROUTING_PATH_APPLICATION, a.addApplication) -} - -// getApplication godoc -// -// @Summary get an application of a repository by id -// @Tags applications -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param applicationId path string true "Application ID" -// @Success 200 {object} models.Application -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/{applicationId} [get] -func (a *ApplicationRouter) getApplication(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - // TODO: find out why binding doesnt work: - // type AppUrl struct { - // repositoryName string `uri:"repositoryName" binding:"required"` - // applicationId string `uri:"applicationId" binding:"required"` - // } - // var url AppUrl - // err := c.BindUri(&url) - - // fmt.Println(url.repositoryName, url.applicationId) - - // if err != nil { - // fmt.Println("error after binding:", err.Error()) - // c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - // return - // } - // fmt.Println("application-id:", url.applicationId, "/ by hand:", c.Request.RequestURI, url) - - repoName := c.Param("repositoryName") - appId := c.Param("applicationId") - - result, err := a.applicationService.GetApplication(repoName, appId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// addApplication godoc -// -// @Summary add an application -// @Tags applications -// @Accept json -// @Produce json -// @Param applicationCreateRequest body models.ApplicationCreateRequest true "Create Application" -// @Success 200 {object} models.Application -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /application [post] -func (a *ApplicationRouter) addApplication(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - request, err := models.ExtractApplicationCreateRequest(c) - if err != nil { - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - repo, err := a.repositoryService.GetRepository(request.RepositoryName, traceId) - if err != nil { - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - ctx, transaction, err := gittransaction.New(config.TRANSACTION_MODE, repo.Path, a.config.TransactionToken()) - - application, err := a.applicationService.AddApplication(request, traceId) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Write(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Commit(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.IndentedJSON(http.StatusOK, application) -} diff --git a/momentum-core/routers/deployment-router.go b/momentum-core/routers/deployment-router.go deleted file mode 100644 index 72637d0..0000000 --- a/momentum-core/routers/deployment-router.go +++ /dev/null @@ -1,124 +0,0 @@ -package routers - -import ( - "momentum-core/config" - "momentum-core/models" - "momentum-core/services" - "net/http" - - gittransaction "github.com/Joel-Haeberli/git-transaction" - "github.com/gin-gonic/gin" -) - -const ROUTING_PATH_DEPLOYMENT_BY_ID = VERSION + "/repository/:repositoryName/app/stage/deployment/:deploymentId" -const ROUTING_PATH_DEPLOYMENT = VERSION + "/deployment" - -type DeploymentRouter struct { - deploymentService *services.DeploymentService - repositoryService *services.RepositoryService - config *config.MomentumConfig -} - -func NewDeploymentRouter(deploymentService *services.DeploymentService, repositoryService *services.RepositoryService, config *config.MomentumConfig) *DeploymentRouter { - - router := new(DeploymentRouter) - - router.deploymentService = deploymentService - router.repositoryService = repositoryService - router.config = config - - return router -} - -func (d *DeploymentRouter) RegisterDeploymentRoutes(server *gin.Engine) { - - server.GET(ROUTING_PATH_DEPLOYMENT_BY_ID, d.getDeployment) - server.POST(ROUTING_PATH_DEPLOYMENT, d.addDeployment) -} - -// GetDeployment godoc -// -// @Summary get a deployment of a repository by id -// @Tags deployments -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param deploymentId path string true "Deployment ID" -// @Success 200 {object} models.Deployment -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/app/stage/deployment/{deploymentId} [get] -func (d *DeploymentRouter) getDeployment(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - deploymentId := c.Param("deploymentId") - - result, err := d.deploymentService.GetDeployment(repoName, deploymentId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// GetDeployment godoc -// -// @Summary get a deployment of a repository by id -// @Tags deployments -// @Accept json -// @Produce json -// @Param deploymentCreateRequest body models.DeploymentCreateRequest true "Create Deployment" -// @Success 200 {object} models.Deployment -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /deployment [post] -func (d *DeploymentRouter) addDeployment(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - request, err := models.ExtractDeploymentCreateRequest(c) - if err != nil { - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - repo, err := d.repositoryService.GetRepository(request.RepositoryName, traceId) - if err != nil { - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - ctx, transaction, err := gittransaction.New(config.TRANSACTION_MODE, repo.Path, d.config.TransactionToken()) - - deployment, err := d.deploymentService.AddDeployment(request, traceId) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Write(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Commit(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.IndentedJSON(http.StatusOK, deployment) -} diff --git a/momentum-core/routers/repository-router.go b/momentum-core/routers/repository-router.go deleted file mode 100644 index ea95879..0000000 --- a/momentum-core/routers/repository-router.go +++ /dev/null @@ -1,238 +0,0 @@ -package routers - -import ( - "momentum-core/config" - "momentum-core/models" - "momentum-core/services" - "net/http" - - "github.com/gin-gonic/gin" -) - -const VERSION = "" // for example "/v1" or "/beta" - -const ROUTING_PATH_REPOSITORIES = VERSION + "/repositories" -const ROUTING_PATH_REPOSITORY = VERSION + "/repository" - -const ROUTING_PATH_REPOSITORY_APPLICATIONS = VERSION + "/repository/:repositoryName/applications" -const ROUTING_PATH_REPOSITORY_STAGES = VERSION + "/repository/:repositoryName/stages" -const ROUTING_PATH_REPOSITORY_DEPLOYMENTS = VERSION + "/repository/:repositoryName/deployments" - -const ROUTING_PATH_REPOSITORY_BY_NAME = VERSION + "/repository/:repositoryName/" - -type RepositoryRouter struct { - repositoryService *services.RepositoryService - applicationService *services.ApplicationService - stageService *services.StageService - deploymentService *services.DeploymentService -} - -func NewRepositoryRouter(repositoryService *services.RepositoryService, - applicationService *services.ApplicationService, - stageService *services.StageService, - deploymentService *services.DeploymentService, -) *RepositoryRouter { - - router := new(RepositoryRouter) - - router.repositoryService = repositoryService - router.applicationService = applicationService - router.stageService = stageService - router.deploymentService = deploymentService - - return router -} - -func (r *RepositoryRouter) RegisterRepositoryRoutes(server *gin.Engine) { - - server.POST(ROUTING_PATH_REPOSITORY, r.addRepository) - server.GET(ROUTING_PATH_REPOSITORIES, r.getRepositories) - server.GET(ROUTING_PATH_REPOSITORY_BY_NAME, r.getRepository) - server.GET(ROUTING_PATH_REPOSITORY_APPLICATIONS, r.getApplications) - server.GET(ROUTING_PATH_REPOSITORY_STAGES, r.getStages) - server.GET(ROUTING_PATH_REPOSITORY_DEPLOYMENTS, r.getDeployments) -} - -// GetRepositories godoc -// -// @Summary load repositories -// @Description load all repositories managed by this instance -// @Tags repositories -// @Produce json -// @Success 200 {array} models.Repository -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repositories [get] -func (r *RepositoryRouter) getRepositories(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - repos := r.repositoryService.GetRepositories(traceId) - c.JSON(http.StatusOK, repos) -} - -// AddRepository godoc -// -// @Summary add a new repository -// @Description adds a new repository to the instance -// @Tags repositories -// @Accept json -// @Produce json -// @Param repositoryCreateRequest body models.RepositoryCreateRequest true "Create Repository" -// @Success 200 {object} models.Repository -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository [post] -func (r *RepositoryRouter) addRepository(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - request, err := models.ExtractRepositoryCreateRequest(c) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - repo, err := r.repositoryService.AddRepository(request, traceId) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, repo) -} - -type repoUrl struct { - repositoryName string `uri:"repositoryName" binding:"required"` -} - -// GetRepository godoc -// -// @Summary get a repository -// @Tags repositories -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Success 200 {object} models.Repository -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName} [get] -func (r *RepositoryRouter) getRepository(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - req := new(repoUrl) - err := c.BindUri(req) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - result, err := r.repositoryService.GetRepository(req.repositoryName, traceId) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// GetApplications godoc -// -// @Summary get all applications of a repository -// @Tags applications -// @Accept json -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Success 200 {array} models.Application -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/applications [get] -func (r *RepositoryRouter) getApplications(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - req := new(repoUrl) - err := c.BindUri(req) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - result, err := r.applicationService.GetApplications(req.repositoryName, traceId) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// GetStages godoc -// -// @Summary get stages -// @Tags stages -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Success 200 {array} models.Stage -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/stages [get] -func (r *RepositoryRouter) getStages(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - req := new(repoUrl) - err := c.BindUri(req) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - result, err := r.stageService.GetStages(req.repositoryName, traceId) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// GetDeployments godoc -// -// @Summary get deployments -// @Tags deployments -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Success 200 {array} models.Deployment -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/deployments [get] -func (r *RepositoryRouter) getDeployments(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - req := new(repoUrl) - err := c.BindUri(req) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - result, err := r.deploymentService.GetDeployments(req.repositoryName, traceId) - if err != nil { - c.JSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} diff --git a/momentum-core/routers/stage-router.go b/momentum-core/routers/stage-router.go deleted file mode 100644 index d978e89..0000000 --- a/momentum-core/routers/stage-router.go +++ /dev/null @@ -1,124 +0,0 @@ -package routers - -import ( - "momentum-core/config" - "momentum-core/models" - "momentum-core/services" - "net/http" - - gittransaction "github.com/Joel-Haeberli/git-transaction" - "github.com/gin-gonic/gin" -) - -const ROUTING_PATH_STAGE_BY_ID = VERSION + "/repository/:repositoryName/app/stage/:stageId" -const ROUTING_PATH_STAGE = VERSION + "/stage" - -type StageRouter struct { - stageService *services.StageService - repositoryService *services.RepositoryService - config *config.MomentumConfig -} - -func NewStageRouter(stageService *services.StageService, repositoryService *services.RepositoryService, config *config.MomentumConfig) *StageRouter { - - router := new(StageRouter) - - router.stageService = stageService - router.repositoryService = repositoryService - router.config = config - - return router -} - -func (s *StageRouter) RegisterStageRoutes(server *gin.Engine) { - - server.GET(ROUTING_PATH_STAGE_BY_ID, s.getStage) - server.POST(ROUTING_PATH_STAGE, s.addStage) -} - -// GetStage godoc -// -// @Summary get a stage of a repository by id -// @Tags stages -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param stageId path string true "Stage ID" -// @Success 200 {object} models.Deployment -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/app/stage/{stageId} [get] -func (s *StageRouter) getStage(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - stageId := c.Param("stageId") - - result, err := s.stageService.GetStage(repoName, stageId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// AddStage godoc -// -// @Summary add a new stage -// @Tags stages -// @Accept json -// @Produce json -// @Param stageCreateRequest body models.StageCreateRequest true "Create Stage" -// @Success 200 {object} models.Stage -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /stage [post] -func (sr *StageRouter) addStage(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - request, err := models.ExtractStageCreateRequest(c) - if err != nil { - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - repo, err := sr.repositoryService.GetRepository(request.RepositoryName, traceId) - if err != nil { - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - ctx, transaction, err := gittransaction.New(config.TRANSACTION_MODE, repo.Path, sr.config.TransactionToken()) - - stage, err := sr.stageService.AddStage(request, traceId) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusBadRequest, models.NewApiError(err, http.StatusBadRequest, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Write(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - err = transaction.Commit(ctx) - if err != nil { - transaction.Rollback(ctx) - c.IndentedJSON(http.StatusInternalServerError, models.NewApiError(err, http.StatusInternalServerError, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.IndentedJSON(http.StatusOK, stage) -} diff --git a/momentum-core/routers/template-router.go b/momentum-core/routers/template-router.go deleted file mode 100644 index 0d59aa3..0000000 --- a/momentum-core/routers/template-router.go +++ /dev/null @@ -1,7 +0,0 @@ -package routers - -type TemplateRouter struct{} - -func NewTemplateRouter() *TemplateRouter { - return new(TemplateRouter) -} diff --git a/momentum-core/routers/value-router.go b/momentum-core/routers/value-router.go deleted file mode 100644 index 9fd8446..0000000 --- a/momentum-core/routers/value-router.go +++ /dev/null @@ -1,153 +0,0 @@ -package routers - -import ( - "momentum-core/config" - "momentum-core/models" - "momentum-core/services" - "net/http" - - "github.com/gin-gonic/gin" -) - -const ROUTING_PATH_VALUE_BY_ID = VERSION + "/repository/:repositoryName/value/:valueId" -const ROUTING_PATH_VALUE = VERSION + "/value" -const ROUTING_PATH_VALUE_BY_APPLICATION = VERSION + "/repository/:repositoryName/application/values/:applicationId" -const ROUTING_PATH_VALUE_BY_STAGE = VERSION + "/repository/:repositoryName/stage/values/:stageId" -const ROUTING_PATH_VALUE_BY_DEPLOYMENT = VERSION + "/repository/:repositoryName/deployment/values/:deploymentId" - -type ValueRouter struct { - valueService *services.ValueService -} - -func NewValueRouter(valueService *services.ValueService) *ValueRouter { - - vs := new(ValueRouter) - - vs.valueService = valueService - - return vs -} - -func (vr *ValueRouter) RegisterValueRoutes(server *gin.Engine) { - - server.GET(ROUTING_PATH_VALUE_BY_ID, vr.valueById) - server.GET(ROUTING_PATH_VALUE_BY_APPLICATION, vr.valuesByApplication) - server.GET(ROUTING_PATH_VALUE_BY_STAGE, vr.valuesByStage) - server.GET(ROUTING_PATH_VALUE_BY_DEPLOYMENT, vr.valuesByDeployment) -} - -// valueById godoc -// -// @Summary get a value of a repository by id -// @Tags values -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param valueId path string true "Value ID" -// @Success 200 {object} models.Value -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/value/{valueId} [get] -func (vr *ValueRouter) valueById(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - valueId := c.Param("valueId") - - result, err := vr.valueService.ValueById(repoName, valueId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// valuesByApplication godoc -// -// @Summary get all values of an application by the applications id -// @Tags values -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param applicationId path string true "Application ID" -// @Success 200 {array} models.ValueWrapper -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/application/values/{applicationId} [get] -func (vr *ValueRouter) valuesByApplication(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - applicationId := c.Param("applicationId") - - result, err := vr.valueService.ValuesByApplication(repoName, applicationId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// valuesByStage godoc -// -// @Summary get all values of an stage by the stages id -// @Tags values -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param stageId path string true "Stage ID" -// @Success 200 {array} models.ValueWrapper -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/stage/values/{stageId} [get] -func (vr *ValueRouter) valuesByStage(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - stageId := c.Param("stageId") - - result, err := vr.valueService.ValuesByStage(repoName, stageId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} - -// valuesByDeployment godoc -// -// @Summary get all values of a deployment by the deployments id -// @Tags values -// @Produce json -// @Param repositoryName path string true "Repository Name" -// @Param deploymentId path string true "Deployment ID" -// @Success 200 {array} models.ValueWrapper -// @Failure 400 {object} models.ApiError -// @Failure 404 {object} models.ApiError -// @Failure 500 {object} models.ApiError -// @Router /repository/{repositoryName}/deployment/values/{deploymentId} [get] -func (vr *ValueRouter) valuesByDeployment(c *gin.Context) { - - traceId := config.LOGGER.TraceId() - - repoName := c.Param("repositoryName") - deploymentId := c.Param("deploymentId") - - result, err := vr.valueService.ValuesByDeployment(repoName, deploymentId, traceId) - if err != nil { - c.JSON(http.StatusNotFound, models.NewApiError(err, http.StatusNotFound, c, traceId)) - config.LOGGER.LogError(err.Error(), err, traceId) - return - } - - c.JSON(http.StatusOK, result) -} diff --git a/momentum-core/services/application-service.go b/momentum-core/services/application-service.go deleted file mode 100644 index 77e28e5..0000000 --- a/momentum-core/services/application-service.go +++ /dev/null @@ -1,125 +0,0 @@ -package services - -import ( - "errors" - "momentum-core/config" - "momentum-core/models" - "momentum-core/utils" -) - -type ApplicationService struct { - config *config.MomentumConfig - treeService *TreeService - templateService *TemplateService -} - -func NewApplicationService(config *config.MomentumConfig, treeService *TreeService, templateService *TemplateService) *ApplicationService { - - appService := new(ApplicationService) - - appService.config = config - appService.treeService = treeService - appService.templateService = templateService - - return appService -} - -func (as *ApplicationService) GetApplications(repositoryName string, traceId string) ([]*models.Application, error) { - - repo, err := as.treeService.repository(repositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("no repository found", err, traceId) - return nil, err - } - - apps := repo.Apps() - mappedApps := make([]*models.Application, 0) - for _, app := range apps { - mapped, err := models.ToApplicationFromNode(app, repositoryName) - if err != nil { - config.LOGGER.LogWarning("failed mapping application from node", err, traceId) - return nil, err - } - mappedApps = append(mappedApps, mapped) - } - - return mappedApps, nil -} - -func (as *ApplicationService) GetApplication(repositoryName string, applicationId string, traceId string) (*models.Application, error) { - - result, err := as.treeService.application(repositoryName, applicationId, traceId) - if err != nil { - config.LOGGER.LogWarning("no application found", err, traceId) - return nil, err - } - - return models.ToApplicationFromNode(result, repositoryName) -} - -func (as *ApplicationService) AddApplication(request *models.ApplicationCreateRequest, traceId string) (*models.Application, error) { - - repo, err := as.treeService.repository(request.RepositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("no repository found", err, traceId) - return nil, err - } - - apps := repo.Apps() - for _, app := range apps { - if app.Path == request.Name { - return nil, errors.New("application with this name already exists") - } - } - - appMountPath := utils.BuildPath(repo.MomentumRoot().FullPath(), request.Name) - appBasePath := utils.BuildPath(appMountPath, "_base") - - _, err = utils.DirCopy(as.config.ApplicationTemplateFolderPath(), appMountPath) - if err != nil { - config.LOGGER.LogWarning("failed copying from "+as.config.ApplicationTemplateFolderPath()+" to "+appMountPath, err, traceId) - return nil, err - } - - appRepositoryPath := utils.BuildPath(appMountPath, "repository.yaml") - appNamespacePath := utils.BuildPath(appMountPath, "ns.yaml") - appBaseKustomizationPath := utils.BuildPath(appBasePath, KUSTOMIZATION_FILE_NAME) - appBaseReleasePath := utils.BuildPath(appBasePath, "release.yaml") - - template := as.templateService.NewApplicationTemplate(appRepositoryPath, appNamespacePath, appBaseKustomizationPath, appBaseReleasePath, request.Name, request.ReconcileInterval, request.ChartVersion) - err = as.templateService.ApplyApplicationTemplate(template) - if err != nil { - config.LOGGER.LogWarning("failed applying application template", err, traceId) - return nil, err - } - - repositoryKustomizationResources, err := as.treeService.find(traceId, request.RepositoryName, config.MOMENTUM_ROOT, KUSTOMIZATION_FILE_NAME, "resources") - if repositoryKustomizationResources == nil || err != nil { - return nil, errors.New("unable to find kustomization resources for repository of new application") - } - - err = repositoryKustomizationResources.AddYamlValue(request.Name, 0) - if err != nil { - config.LOGGER.LogWarning("failed adding application to resources", err, traceId) - return nil, err - } - - err = repositoryKustomizationResources.Write(true) - if err != nil { - config.LOGGER.LogWarning("failed writing application to resources", err, traceId) - return nil, err - } - - application, err := as.treeService.find(traceId, request.RepositoryName, appMountPath) - if err != nil { - config.LOGGER.LogWarning("unable to find application in "+appMountPath, err, traceId) - return nil, err - } - - app, err := models.ToApplicationFromNode(application, request.RepositoryName) - if err != nil { - config.LOGGER.LogWarning("failed mapping application from node", err, traceId) - return nil, err - } - return app, nil -} diff --git a/momentum-core/services/deployment-service.go b/momentum-core/services/deployment-service.go deleted file mode 100644 index ad5d373..0000000 --- a/momentum-core/services/deployment-service.go +++ /dev/null @@ -1,206 +0,0 @@ -package services - -import ( - "errors" - "momentum-core/config" - "momentum-core/models" - "momentum-core/utils" - "strings" -) - -type DeploymentService struct { - config *config.MomentumConfig - stageService *StageService - templateService *TemplateService - treeService *TreeService -} - -func NewDeploymentService(config *config.MomentumConfig, stageService *StageService, templateService *TemplateService, treeService *TreeService) *DeploymentService { - - deploymentService := new(DeploymentService) - - deploymentService.config = config - deploymentService.stageService = stageService - deploymentService.templateService = templateService - deploymentService.treeService = treeService - - return deploymentService -} - -func (ds *DeploymentService) GetDeployments(repositoryName string, traceId string) ([]*models.Deployment, error) { - - repo, err := ds.treeService.repository(repositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("no repository found", err, traceId) - return nil, err - } - - deployments := repo.AllDeployments() - - mappedDeployments := make([]*models.Deployment, 0) - for _, deployment := range deployments { - mapped, err := models.ToDeploymentFromNode(deployment, repo.Id) - if err != nil { - config.LOGGER.LogWarning("failed mapping deployment from node", err, traceId) - return nil, err - } - mappedDeployments = append(mappedDeployments, mapped) - } - - return mappedDeployments, nil -} - -func (ds *DeploymentService) GetDeployment(repositoryName string, deploymentId string, traceId string) (*models.Deployment, error) { - - deployment, err := ds.treeService.deployment(repositoryName, deploymentId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find deployment "+deploymentId, err, traceId) - return nil, err - } - if deployment == nil { - return nil, errors.New("no deployment with id " + deploymentId) - } - - return models.ToDeploymentFromNode(deployment, deployment.Root().Id) -} - -func (ds *DeploymentService) AddDeployment(request *models.DeploymentCreateRequest, traceId string) (*models.Deployment, error) { - - stage, err := ds.stageService.FindStageById(request.ParentStageId, request.RepositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find stage with id "+request.ParentStageId, err, traceId) - return nil, err - } - - if ds.deploymentExists(request.Name, stage.Id, request.RepositoryName, traceId) { - return nil, errors.New("unable to create deployment because name already in use") - } - - deploymentYamlDestinationName := request.Name + ".yaml" - deploymentFolderDestinationPath := utils.BuildPath(stage.Path, "_deploy", request.Name) - deploymentFileDestinationPath := utils.BuildPath(stage.Path, deploymentYamlDestinationName) - - deploymentFolderDestinationPath, err = utils.DirCopy(ds.config.DeploymentTemplateFolderPath(), deploymentFolderDestinationPath) - if err != nil { - config.LOGGER.LogWarning("failed copying deployment template from "+ds.config.DeploymentTemplateFolderPath()+" to "+deploymentFolderDestinationPath, err, traceId) - return nil, err - } - - fileCopySuccess := utils.FileCopy(ds.config.DeploymentTemplateFilePath(), deploymentFileDestinationPath) - if !fileCopySuccess { - return nil, errors.New("failed copying deployment file") - } - - releaseYamlPath := utils.BuildPath(deploymentFolderDestinationPath, "release.yaml") - deploymentKustomizationYamlPath := utils.BuildPath(deploymentFolderDestinationPath, KUSTOMIZATION_FILE_NAME) - pathFromMomentumRoot := strings.Split(deploymentFolderDestinationPath, config.MOMENTUM_ROOT)[1] - pathFromMomentumRoot = utils.BuildPath(config.MOMENTUM_ROOT, pathFromMomentumRoot) - - template := ds.templateService.NewDeploymentTemplate( - deploymentKustomizationYamlPath, - deploymentFileDestinationPath, - releaseYamlPath, - deploymentYamlDestinationName, - pathFromMomentumRoot, - request.ReconcileInterval, - request.ChartVersion, - request.ApplicationName, - request.RepositoryName, - ) - - err = ds.templateService.ApplyDeploymentTemplate(template) - if err != nil { - config.LOGGER.LogWarning("failed applying deployment template", err, traceId) - return nil, err - } - - parentStageKustomizationResources, err := ds.treeService.find(traceId, request.RepositoryName, stage.Path, KUSTOMIZATION_FILE_NAME, "resources") - if err != nil { - config.LOGGER.LogError("failed searching for parent stage kustomization yaml", err, traceId) - return nil, err - } - - if parentStageKustomizationResources != nil { - err = parentStageKustomizationResources.AddYamlValue(deploymentYamlDestinationName, 0) - if err != nil { - config.LOGGER.LogWarning("failed adding deployment to resources", err, traceId) - return nil, err - } - - err = parentStageKustomizationResources.Write(true) - if err != nil { - config.LOGGER.LogError("failed writing deployment to resources", err, traceId) - return nil, err - } - } else { - parentStageKustomization, err := ds.treeService.find(traceId, request.RepositoryName, stage.Path, KUSTOMIZATION_FILE_NAME) - if err != nil { - config.LOGGER.LogError("unable to add resources sequence beacuse not found parents stage kustomization", err, traceId) - return nil, err - } - - err = parentStageKustomization.AddYamlSequence("resources", []string{deploymentYamlDestinationName}, 0) - if err != nil { - config.LOGGER.LogError("unable to add resources sequence to parents stage kustomization", err, traceId) - return nil, err - } - - err = parentStageKustomization.Write(true) - if err != nil { - config.LOGGER.LogError("failed writing deployment to resources", err, traceId) - return nil, err - } - } - - deployment, err := ds.treeService.find(traceId, request.RepositoryName, deploymentFileDestinationPath) - if err != nil { - config.LOGGER.LogWarning("unable to find deployment", err, traceId) - return nil, err - } - - depl, err := models.ToDeploymentFromNode(deployment, request.RepositoryName) - if err != nil { - config.LOGGER.LogWarning("failed mapping deployment from node", err, traceId) - return nil, err - } - return depl, nil -} - -func (ds *DeploymentService) deploymentExists(deploymentName string, stageId string, repositoryName string, traceId string) bool { - - deployments, err := ds.findDeploymentsByStage(stageId, repositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find deployments of stage "+stageId, err, traceId) - return true - } - - for _, depl := range deployments { - if depl.Name == deploymentName { - return true - } - } - - return false -} - -func (ds *DeploymentService) findDeploymentsByStage(stageId string, repositoryName string, traceId string) ([]*models.Deployment, error) { - - stage, err := ds.treeService.stage(repositoryName, stageId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find stage "+stageId, err, traceId) - return nil, err - } - deployments := stage.Deployments() - - depls := make([]*models.Deployment, 0) - for _, deployment := range deployments { - depl, err := models.ToDeploymentFromNode(deployment, repositoryName) - if err != nil { - config.LOGGER.LogWarning("failed mapping deployment from node", err, traceId) - return nil, err - } - depls = append(depls, depl) - } - - return depls, nil -} diff --git a/momentum-core/services/deployment-service_test.go b/momentum-core/services/deployment-service_test.go deleted file mode 100644 index 3d653b1..0000000 --- a/momentum-core/services/deployment-service_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package services_test - -import ( - "testing" -) - -func TestGetDeployment(t *testing.T) { - - // repo := "testrepo1" - // deploymentId = "a7ffc6f8bf1ed766" -} diff --git a/momentum-core/services/repository-service.go b/momentum-core/services/repository-service.go deleted file mode 100644 index 2230369..0000000 --- a/momentum-core/services/repository-service.go +++ /dev/null @@ -1,120 +0,0 @@ -package services - -import ( - "errors" - "fmt" - "momentum-core/clients" - "momentum-core/config" - "momentum-core/models" - "momentum-core/tree" - "momentum-core/utils" - "os" -) - -type RepositoryService struct { - config *config.MomentumConfig - treeService *TreeService - gitClient *clients.GitClient - kustomizeClient *clients.KustomizationValidationClient -} - -func NewRepositoryService(config *config.MomentumConfig, treeService *TreeService, gitClient *clients.GitClient, kustomizeClient *clients.KustomizationValidationClient) *RepositoryService { - - repositoryService := new(RepositoryService) - - repositoryService.config = config - repositoryService.treeService = treeService - repositoryService.gitClient = gitClient - repositoryService.kustomizeClient = kustomizeClient - - return repositoryService -} - -func (r *RepositoryService) AddRepository(createRequest *models.RepositoryCreateRequest, traceId string) (*models.Repository, error) { - - repoPath := utils.BuildPath(r.config.DataDir(), createRequest.Name) - - if utils.FileExists(repoPath) { - return nil, errors.New("repository with name " + createRequest.Name + " already exists") - } - - err := clients.CloneRepoTo(createRequest.Url, "", "", repoPath) - if err != nil { - config.LOGGER.LogWarning("failed cloning repository", err, traceId) - return nil, err - } - - repo, err := tree.Parse(repoPath) - if err != nil { - config.LOGGER.LogWarning("failed parsing momentum tree", err, traceId) - return nil, err - } - - if len(repo.Directories()) != 1 { - return nil, errors.New("only one directory allowed in repository root") - } - - err = r.kustomizeClient.Validate(createRequest.Name) - if err != nil { - config.LOGGER.LogWarning("failed validating repository with kustomize", err, traceId) - return nil, err - } - - // TODO: GIT PUSH - - repository := new(models.Repository) - repository.Name = createRequest.Name - repository.Id = repo.Id - return repository, nil -} - -func (r *RepositoryService) GetRepositories(traceId string) []string { - - dir, err := utils.FileOpen(r.config.DataDir(), os.O_RDONLY) - if err != nil { - config.LOGGER.LogError("failed reading data directory", err, traceId) - return make([]string, 0) - } - - entries, err := dir.ReadDir(-1) // -1 reads all - if err != nil { - config.LOGGER.LogError("failed reading data directory", err, traceId) - return make([]string, 0) - } - - repos := make([]string, 0) - for _, entry := range entries { - if entry.IsDir() { - repos = append(repos, entry.Name()) - } - } - - return repos -} - -func (r *RepositoryService) GetRepository(name string, traceId string) (*models.Repository, error) { - - fmt.Println("Logger instance:", config.LOGGER) - config.LOGGER.LogInfo("getting repository with name "+name, "") - - repoPath := utils.BuildPath(r.config.DataDir(), name) - fmt.Println("Repo path:", repoPath) - if !utils.FileExists(repoPath) { - return nil, errors.New("repository does not exist") - } - - n, err := r.treeService.repository(name, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find repositories", err, traceId) - return nil, err - } - - result, err := models.ToRepositoryFromNode(n) - fmt.Println(result) - if err != nil { - config.LOGGER.LogWarning("failed mapping repository from node", err, traceId) - return nil, err - } - - return result, nil -} diff --git a/momentum-core/services/stage-service.go b/momentum-core/services/stage-service.go deleted file mode 100644 index b4b0f41..0000000 --- a/momentum-core/services/stage-service.go +++ /dev/null @@ -1,165 +0,0 @@ -package services - -import ( - "errors" - "momentum-core/config" - "momentum-core/models" - "momentum-core/tree" - "momentum-core/utils" -) - -type StageService struct { - config *config.MomentumConfig - treeService *TreeService - templateService *TemplateService -} - -func NewStageService(config *config.MomentumConfig, treeService *TreeService, templateService *TemplateService) *StageService { - - stageService := new(StageService) - - stageService.config = config - stageService.treeService = treeService - stageService.templateService = templateService - - return stageService -} - -func (as *StageService) GetStages(repositoryName string, traceId string) ([]*models.Stage, error) { - - repo, err := as.treeService.repository(repositoryName, traceId) - if err != nil { - config.LOGGER.LogWarning("failed adding deployment to resources", err, traceId) - return nil, err - } - - stages := repo.AllStages() - - mappedStages := make([]*models.Stage, 0) - for _, stage := range stages { - mapped, err := models.ToStageFromNode(stage, stage.Parent.Id) - if err != nil { - return nil, err - } - mappedStages = append(mappedStages, mapped) - } - - return mappedStages, nil -} - -func (as *StageService) GetStage(repositoryName string, stageId string, traceId string) (*models.Stage, error) { - - result, err := as.treeService.stage(repositoryName, stageId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find stage "+stageId, err, traceId) - return nil, err - } - - return models.ToStageFromNode(result, result.Parent.Id) -} - -func (s *StageService) FindStageById(stageId string, repositoryName string, traceId string) (*models.Stage, error) { - - stageNode, err := s.treeService.stage(repositoryName, stageId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find stage "+stageId, err, traceId) - return nil, err - } - - return models.ToStageFromNode(stageNode, stageNode.Parent.Id) -} - -func (s *StageService) AddStage(request *models.StageCreateRequest, traceId string) (*models.Stage, error) { - - parentAppNode, err := s.treeService.application(request.RepositoryName, request.ParentApplicationId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find application "+request.ParentApplicationId, err, traceId) - return nil, err - } - - var stageMountNode *tree.Node - if request.ParentStageId == "" { - stageMountNode = parentAppNode - } else { - stageMountNode, err = s.treeService.stage(request.RepositoryName, request.ParentStageId, traceId) - if err != nil { - return nil, err - } - } - - dirs := stageMountNode.Directories() - for _, dir := range dirs { - if dir.Path == request.Name { - return nil, errors.New("stage with this name already exists") - } - } - - stageMountPath := utils.BuildPath(stageMountNode.FullPath(), request.Name) - stageBasePath := utils.BuildPath(stageMountPath, "_base") - - _, err = utils.DirCopy(s.config.StageTemplateFolderPath(), stageMountPath) - if err != nil { - return nil, err - } - - stageBaseKustomizationPath := utils.BuildPath(stageBasePath, KUSTOMIZATION_FILE_NAME) - stageBaseReleasePath := utils.BuildPath(stageBasePath, "release.yaml") - - template := s.templateService.NewStageTemplate(stageBaseKustomizationPath, stageBaseReleasePath, request.Name, parentAppNode.Path, request.ReconcileInterval, request.ChartVersion) - err = s.templateService.ApplyStageTemplate(template) - if err != nil { - return nil, err - } - - parentKustomizationResources, err := s.treeService.find(traceId, request.RepositoryName, stageMountNode.FullPath(), KUSTOMIZATION_FILE_NAME, "resources") - if err != nil { - config.LOGGER.LogError(err.Error(), err, traceId) - return nil, err - } - - if parentKustomizationResources == nil { - config.LOGGER.LogTrace("unable to find kustomization resources for parent stage or application of new stage", traceId) - kustomizationFileNode, err := s.treeService.find(traceId, request.RepositoryName, stageMountNode.FullPath(), KUSTOMIZATION_FILE_NAME) - if err != nil { - config.LOGGER.LogError(err.Error(), err, traceId) - return nil, err - } - - err = kustomizationFileNode.AddYamlSequence("resources", []string{request.Name}, 0) - if err != nil { - config.LOGGER.LogError(err.Error(), err, traceId) - return nil, err - } - - err = kustomizationFileNode.Write(true) - if err != nil { - config.LOGGER.LogWarning("failed writing stage to resources", err, traceId) - return nil, err - } - } else { - err = parentKustomizationResources.AddYamlValue(request.Name, 0) - if err != nil { - config.LOGGER.LogWarning("failed adding stage to resources", err, traceId) - return nil, err - } - - err = parentKustomizationResources.Write(true) - if err != nil { - config.LOGGER.LogWarning("failed writing stage to resources", err, traceId) - return nil, err - } - } - - stage, err := s.treeService.find(traceId, request.RepositoryName, stageMountPath) - if err != nil { - config.LOGGER.LogWarning("unable to find "+stageMountPath, err, traceId) - return nil, err - } - - stg, err := models.ToStageFromNode(stage, stageMountNode.Id) - if err != nil { - config.LOGGER.LogWarning("failed mapping stage from node", err, traceId) - return nil, err - } - return stg, nil -} diff --git a/momentum-core/services/template-service.go b/momentum-core/services/template-service.go deleted file mode 100644 index 6ebc79e..0000000 --- a/momentum-core/services/template-service.go +++ /dev/null @@ -1,298 +0,0 @@ -package services - -import ( - "fmt" - "momentum-core/config" - "momentum-core/utils" - "os" - "strings" - "text/template" -) - -const KUSTOMIZATION_FILE_NAME = "kustomization.yaml" - -type ApplicationTemplate struct { - applicationRepositoryPath string - applicationNamespacePath string - applicationBaseKustomizationTemplatePath string - applicationBaseReleaseTemplatePath string - applicationKustomizationTemplate *ApplicationKustomizationTemplate - applicationReleaseTemplate *ApplicationReleaseTemplate -} - -type ApplicationKustomizationTemplate struct { - ApplicationName string -} - -type ApplicationReleaseTemplate struct { - ApplicationName string - ReconcileInterval string - ChartVersion string -} - -type StageTemplate struct { - stageBaseKustomizationPath string - stageBaseReleasePath string - stageKustomizationTemplate *StageKustomizationTemplate - stageReleaseTemplate *StageReleaseTemplate -} - -type StageKustomizationTemplate struct { - ApplicationName string - StageName string -} - -type StageReleaseTemplate struct { - StageName string - ApplicationName string - ReconcileInterval string - ChartVersion string -} - -type DeploymentTemplate struct { - deploymentKustomizationTemplatePath string - deploymentStageDeploymentDescriptionTemplatePath string - deploymentReleaseTemplatePath string - deploymentKustomizationTemplate *DeploymentKustomizationTemplate - deploymentStageDeploymentDescriptionTemplate *DeploymentStageDeploymentDescriptionTemplate - deploymentReleaseTemplate *DeploymentReleaseTemplate -} - -type DeploymentKustomizationTemplate struct { - DeploymentNameWithoutEnding string -} - -type DeploymentStageDeploymentDescriptionTemplate struct { - DeploymentNameWithoutEnding string - DeploymentName string - PathFromMomentumRoot string - RepositoryName string -} - -type DeploymentReleaseTemplate struct { - ApplicationName string - ReconcileInterval string - ChartVersion string -} - -type TemplateService struct{} - -func NewTemplateService() *TemplateService { - return new(TemplateService) -} - -func (ts *TemplateService) NewApplicationTemplate( - applicationRepositoryPath string, - applicationNamespacePath string, - applicationBaseKustomizationPath string, - applicationBaseReleasePath string, - applicationName string, - reconcileInterval string, - chartVersion string, -) *ApplicationTemplate { - - template := new(ApplicationTemplate) - - template.applicationRepositoryPath = applicationRepositoryPath - template.applicationNamespacePath = applicationNamespacePath - template.applicationBaseKustomizationTemplatePath = applicationBaseKustomizationPath - template.applicationBaseReleaseTemplatePath = applicationBaseReleasePath - - applicationKustomizationTemplate := new(ApplicationKustomizationTemplate) - applicationKustomizationTemplate.ApplicationName = applicationName - - applicationReleaseTemplate := new(ApplicationReleaseTemplate) - applicationReleaseTemplate.ApplicationName = applicationName - applicationReleaseTemplate.ReconcileInterval = reconcileInterval - applicationReleaseTemplate.ChartVersion = chartVersion - - template.applicationKustomizationTemplate = applicationKustomizationTemplate - template.applicationReleaseTemplate = applicationReleaseTemplate - - return template -} - -func (ts *TemplateService) NewStageTemplate( - stageBaseKustomizationPath string, - stageBaseReleasePath string, - stageName string, - applicationName string, - stageReconcileInterval string, - stageChartVersion string, -) *StageTemplate { - - template := new(StageTemplate) - - template.stageBaseKustomizationPath = stageBaseKustomizationPath - template.stageBaseReleasePath = stageBaseReleasePath - - stageBaseKustomization := new(StageKustomizationTemplate) - stageBaseKustomization.StageName = stageName - stageBaseKustomization.ApplicationName = applicationName - - stageBaseRelease := new(StageReleaseTemplate) - stageBaseRelease.StageName = stageName - stageBaseRelease.ApplicationName = applicationName - stageBaseRelease.ReconcileInterval = stageReconcileInterval - stageBaseRelease.ChartVersion = stageChartVersion - - template.stageKustomizationTemplate = stageBaseKustomization - template.stageReleaseTemplate = stageBaseRelease - - return template -} - -func (ts *TemplateService) NewDeploymentTemplate( - deploymentKustomizationTemplatePath string, - deploymentStageDeploymentDescriptionTemplatePath string, - deploymentReleaseTemplatePath string, - deploymentFileName string, - pathFromMomentumRoot string, - reconcileInterval string, - chartVersion string, - applicationName string, - repositoryName string) *DeploymentTemplate { - - template := new(DeploymentTemplate) - - template.deploymentKustomizationTemplatePath = deploymentKustomizationTemplatePath - template.deploymentStageDeploymentDescriptionTemplatePath = deploymentStageDeploymentDescriptionTemplatePath - template.deploymentReleaseTemplatePath = deploymentReleaseTemplatePath - - deploymentNameWithoutEnding, _ := strings.CutSuffix(deploymentFileName, ".yml") - deploymentNameWithoutEnding, _ = strings.CutSuffix(deploymentNameWithoutEnding, ".yaml") - - templateStageDeployment := new(DeploymentStageDeploymentDescriptionTemplate) - templateStageDeployment.DeploymentName = deploymentFileName - templateStageDeployment.DeploymentNameWithoutEnding = deploymentNameWithoutEnding - templateStageDeployment.PathFromMomentumRoot = "./" + pathFromMomentumRoot - templateStageDeployment.RepositoryName = repositoryName - - deploymentKustomizationTemplate := new(DeploymentKustomizationTemplate) - deploymentKustomizationTemplate.DeploymentNameWithoutEnding = deploymentNameWithoutEnding - - deploymentReleaseTemplate := new(DeploymentReleaseTemplate) - deploymentReleaseTemplate.ApplicationName = applicationName - deploymentReleaseTemplate.ReconcileInterval = reconcileInterval - deploymentReleaseTemplate.ChartVersion = chartVersion - - template.deploymentKustomizationTemplate = deploymentKustomizationTemplate - template.deploymentStageDeploymentDescriptionTemplate = templateStageDeployment - template.deploymentReleaseTemplate = deploymentReleaseTemplate - - return template -} - -func (ts *TemplateService) ApplyApplicationTemplate(template *ApplicationTemplate) error { - - err := ts.ParseReplaceWrite(template.applicationBaseKustomizationTemplatePath, template.applicationKustomizationTemplate) - if err != nil { - config.LOGGER.LogError("failed applying base kustomization template", err, "") - return err - } - - err = ts.ParseReplaceWrite(template.applicationBaseReleaseTemplatePath, template.applicationReleaseTemplate) - if err != nil { - config.LOGGER.LogError("failed applying base release template", err, "") - return err - } - - err = ts.ParseReplaceWrite(template.applicationRepositoryPath, template.applicationKustomizationTemplate) - if err != nil { - config.LOGGER.LogError("failed applying release template", err, "") - return err - } - - err = ts.ParseReplaceWrite(template.applicationNamespacePath, template.applicationKustomizationTemplate) - if err != nil { - config.LOGGER.LogError("failed applying namespace template", err, "") - return err - } - - return nil -} - -func (ts *TemplateService) ApplyStageTemplate(template *StageTemplate) error { - - err := ts.ParseReplaceWrite(template.stageBaseKustomizationPath, template.stageKustomizationTemplate) - if err != nil { - return err - } - - err = ts.ParseReplaceWrite(template.stageBaseReleasePath, template.stageReleaseTemplate) - if err != nil { - return err - } - - return nil -} - -func (ts *TemplateService) ApplyDeploymentTemplate(template *DeploymentTemplate) error { - - err := ts.ParseReplaceWrite(template.deploymentStageDeploymentDescriptionTemplatePath, template.deploymentStageDeploymentDescriptionTemplate) - if err != nil { - return err - } - - err = ts.ParseReplaceWrite(template.deploymentKustomizationTemplatePath, template.deploymentKustomizationTemplate) - if err != nil { - return err - } - - err = ts.ParseReplaceWrite(template.deploymentReleaseTemplatePath, template.deploymentReleaseTemplate) - if err != nil { - return err - } - - return nil -} - -func (ts *TemplateService) ParseReplaceWrite(path string, data any) error { - - parsed, err := ts.parse(path) - if err != nil { - fmt.Println("failed parsing template:", err.Error()) - return err - } - - err = ts.replace(path, parsed, data) - if err != nil { - fmt.Println("failed replacing template strings:", err.Error()) - return err - } - - return nil -} - -func (ts *TemplateService) parse(path string) (*template.Template, error) { - - reader, err := utils.FileOpen(path, utils.FILE_ALLOW_READ_WRITE_ALL) - if err != nil { - fmt.Println("failed opening template:", err.Error()) - return nil, err - } - defer reader.Close() - templateAsString := utils.FileAsString(reader) - - temp, err := template.New(path).Parse(templateAsString) - if err != nil { - fmt.Println("failed parsing path:", err.Error()) - return nil, err - } - - return temp, nil -} - -func (ts *TemplateService) replace(path string, t *template.Template, data any) error { - - utils.FileDelete(path) - - writer, err := utils.FileOpen(path, utils.FILE_ALLOW_READ_WRITE_ALL|os.O_CREATE) - if err != nil { - fmt.Println("failed opening template:", err.Error()) - return err - } - defer writer.Close() - err = t.Execute(writer, data) - return err -} diff --git a/momentum-core/services/template-service_test.go b/momentum-core/services/template-service_test.go deleted file mode 100644 index 024450a..0000000 --- a/momentum-core/services/template-service_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package services_test - -import ( - "fmt" - "momentum-core/services" - "momentum-core/utils" - "os" - "testing" -) - -func FILESYSTEMTEST_TestApplyDeploymentReleaseTemplate(t *testing.T) { - - var wd, _ = os.Getwd() - var TEMPLATE_TEST_FILE_PATH = utils.BuildPath(wd, "template_test.yaml") - var templateService = services.NewTemplateService() - - template := "Hello my name is {{ .ApplicationName }}" - writeTestFile(t, TEMPLATE_TEST_FILE_PATH, []string{template}) - - appName := "{CoolApp}" - - err := templateService.ParseReplaceWrite(TEMPLATE_TEST_FILE_PATH, &services.DeploymentReleaseTemplate{appName, "", ""}) - if err != nil { - fmt.Println("applying template failed:", err.Error()) - t.FailNow() - } - - f, err := utils.FileOpen(TEMPLATE_TEST_FILE_PATH, utils.FILE_ALLOW_READ_WRITE_ALL) - if err != nil { - fmt.Println("failed opening file:", err.Error()) - } - - lines := utils.FileAsLines(f) - - check := lines[0] - fmt.Println(check) - if check != "Hello my name is {CoolApp}" { - fmt.Println(check, "does not satisfies assumptions") - } - - cleanup(t, TEMPLATE_TEST_FILE_PATH) -} - -func FILESYSTEMTEST_TestApplyDeploymentStageDeploymentDescriptionTemplate(t *testing.T) { - - var wd, _ = os.Getwd() - var TEMPLATE_TEST_FILE_PATH = utils.BuildPath(wd, "template_test.yaml") - var templateService = services.NewTemplateService() - - template := "Hello my name is '{{ .DeploymentName }}' ('{{ .DeploymentNameWithoutEnding }}') and im living in {{ .RepositoryName }}" - writeTestFile(t, TEMPLATE_TEST_FILE_PATH, []string{template}) - - deploymentName := "CoolDeployment" - repositoryName := "CoolRepository" - - err := templateService.ParseReplaceWrite(TEMPLATE_TEST_FILE_PATH, &services.DeploymentStageDeploymentDescriptionTemplate{deploymentName, deploymentName, "myrootdir", repositoryName}) - if err != nil { - fmt.Println("applying template failed:", err.Error()) - t.FailNow() - } - - cleanup(t, TEMPLATE_TEST_FILE_PATH) -} - -func FILESYSTEMTEST_TestApplyDeploymentKustomizationTemplate(t *testing.T) { - - var wd, _ = os.Getwd() - var TEMPLATE_TEST_FILE_PATH = utils.BuildPath(wd, "template_test.yaml") - var templateService = services.NewTemplateService() - - template := "Hello my name is {{ .DeploymentName }}" - writeTestFile(t, TEMPLATE_TEST_FILE_PATH, []string{template}) - - deploymentName := "CoolDeployment" - - err := templateService.ParseReplaceWrite(TEMPLATE_TEST_FILE_PATH, &services.DeploymentKustomizationTemplate{deploymentName}) - if err != nil { - fmt.Println("applying template failed:", err.Error()) - t.FailNow() - } - - cleanup(t, TEMPLATE_TEST_FILE_PATH) -} - -func writeTestFile(t *testing.T, p string, lines []string) { - if !utils.FileWriteLines(p, lines) { - fmt.Println("failed writing test file") - t.FailNow() - } -} - -func cleanup(t *testing.T, p string) { - err := os.Remove(p) - - if err != nil { - fmt.Println("unable to clean up after test") - t.FailNow() - } -} diff --git a/momentum-core/services/tree-service.go b/momentum-core/services/tree-service.go deleted file mode 100644 index e088262..0000000 --- a/momentum-core/services/tree-service.go +++ /dev/null @@ -1,126 +0,0 @@ -package services - -import ( - "errors" - "momentum-core/config" - "momentum-core/tree" - "momentum-core/utils" -) - -type TreeService struct { - config *config.MomentumConfig -} - -func NewTreeService(config *config.MomentumConfig) *TreeService { - - service := new(TreeService) - - service.config = config - - return service -} - -func (ts *TreeService) repository(repositoryName string, traceId string) (*tree.Node, error) { - - repoPath := utils.BuildPath(ts.config.DataDir(), repositoryName) - root, err := tree.Parse(repoPath) - if err != nil { - config.LOGGER.LogWarning("failed adding stage to resources", err, traceId) - return nil, err - } - return root.Repo(), nil -} - -func (ts *TreeService) application(repositoryName string, applicationId string, traceId string) (*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - apps := repo.Apps() - for _, app := range apps { - if app.Id == applicationId { - return app, nil - } - } - return nil, errors.New("no application with id " + applicationId) -} - -func (ts *TreeService) stage(repositoryName string, stageId string, traceId string) (*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - stages := repo.AllStages() - for _, stage := range stages { - if stage.Id == stageId { - return stage, nil - } - } - return nil, errors.New("no stage with id " + stageId) -} - -func (ts *TreeService) deployment(repositoryName string, deploymentId string, traceId string) (*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - deployments := repo.AllDeployments() - for _, deployment := range deployments { - if deployment.Id == deploymentId { - return deployment, nil - } - } - return nil, errors.New("no deployment with id " + deploymentId) -} - -func (ts *TreeService) value(repositoryName string, valueId string, traceId string) (*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - values := repo.AllValues() - for _, value := range values { - if value.Id == valueId { - return value, nil - } - } - return nil, errors.New("no value with id " + valueId) -} - -func (ts *TreeService) find(traceId string, repositoryName string, terms ...string) (*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - searchTerm := tree.ToMatchableSearchTerm(utils.BuildPath(terms...)) - - config.LOGGER.LogTrace("searching for: "+searchTerm, traceId) - - result, _ := repo.FindFirst(searchTerm) - - return result, nil -} - -func (ts *TreeService) findAll(traceId string, repositoryName string, terms ...string) ([]*tree.Node, error) { - - repo, err := ts.repository(repositoryName, traceId) - if err != nil { - return nil, err - } - - searchTerm := tree.ToMatchableSearchTerm(utils.BuildPath(terms...)) - - result := repo.Search(searchTerm) - - return result, nil -} diff --git a/momentum-core/services/value-service.go b/momentum-core/services/value-service.go deleted file mode 100644 index b7ed484..0000000 --- a/momentum-core/services/value-service.go +++ /dev/null @@ -1,120 +0,0 @@ -package services - -import ( - "errors" - "fmt" - "momentum-core/config" - "momentum-core/models" - "strings" -) - -type ValueService struct { - treeService *TreeService -} - -func NewValueService(treeService *TreeService) *ValueService { - - valueService := new(ValueService) - - valueService.treeService = treeService - - return valueService -} - -func (vs *ValueService) ValueById(repositoryName string, valueId string, traceId string) (*models.Value, error) { - - value, err := vs.treeService.value(repositoryName, valueId, traceId) - if err != nil { - config.LOGGER.LogWarning("unable to find value "+valueId, err, traceId) - return nil, err - } - if value == nil { - return nil, errors.New("no value with id " + valueId) - } - - return models.ToValueFromNode(value) -} - -func (vs *ValueService) ValuesByApplication(repositoryName string, applicationId string, traceId string) ([]*models.ValueWrapper, error) { - - application, err := vs.treeService.application(repositoryName, applicationId, traceId) - if err != nil { - return nil, err - } - - wrappedValues := make([]*models.ValueWrapper, 0) - files := application.Files() - for _, f := range files { - fmt.Println("File:", f.NormalizedPath()) - if strings.EqualFold(f.NormalizedPath(), KUSTOMIZATION_FILE_NAME) { - wrappedKustomization, err := models.ToValueWrapperFromNode(f, models.APPLICATION) - if err != nil { - return nil, err - } - wrappedValues = append(wrappedValues, wrappedKustomization) - } - if strings.EqualFold(f.PathWithoutEnding(), "ns") { - wrappedNamespace, err := models.ToValueWrapperFromNode(f, models.APPLICATION) - if err != nil { - return nil, err - } - wrappedValues = append(wrappedValues, wrappedNamespace) - } - if strings.EqualFold(f.PathWithoutEnding(), "repository") { - wrappedRepository, err := models.ToValueWrapperFromNode(f, models.APPLICATION) - if err != nil { - return nil, err - } - wrappedValues = append(wrappedValues, wrappedRepository) - } - } - - return wrappedValues, nil -} - -func (vs *ValueService) ValuesByStage(repositoryName string, stageId string, traceId string) ([]*models.ValueWrapper, error) { - - stage, err := vs.treeService.stage(repositoryName, stageId, traceId) - if err != nil { - return nil, err - } - - files := stage.Files() - for _, f := range files { - if strings.EqualFold(f.NormalizedPath(), KUSTOMIZATION_FILE_NAME) { - wrappedKustomization, err := models.ToValueWrapperFromNode(f, models.STAGE) - if err != nil { - return nil, err - } - return []*models.ValueWrapper{wrappedKustomization}, nil - } - } - - return make([]*models.ValueWrapper, 0), nil -} - -func (vs *ValueService) ValuesByDeployment(repositoryName string, deploymentId string, traceId string) ([]*models.ValueWrapper, error) { - - deployment, err := vs.treeService.deployment(repositoryName, deploymentId, traceId) - if err != nil { - return nil, err - } - - wrappers := make([]*models.ValueWrapper, 0) - - wrappedDeploymentFile, err := models.ToValueWrapperFromNode(deployment, models.DEPLOYMENT) - if err != nil { - return nil, err - } - wrappers = append(wrappers, wrappedDeploymentFile) - - for _, f := range deployment.DeploymentFolderFiles() { - wrappedFile, err := models.ToValueWrapperFromNode(f, models.DEPLOYMENT) - if err != nil { - return nil, err - } - wrappers = append(wrappers, wrappedFile) - } - - return wrappers, nil -} diff --git a/momentum-core/tree/momentum-tree.go b/momentum-core/tree/momentum-tree.go index cd67149..be3465f 100644 --- a/momentum-core/tree/momentum-tree.go +++ b/momentum-core/tree/momentum-tree.go @@ -5,6 +5,18 @@ import ( "strings" ) +func (n *Node) ChildById(id string, parent *Node) *Node { + + flattened := parent.FlatPreorder(make([]*Node, 0)) + for _, n := range flattened { + if n.Id == id { + return n + } + } + + return nil +} + func (n *Node) Repo() *Node { return n.Root() @@ -156,10 +168,10 @@ func (n *Node) Values() []*Node { return make([]*Node, 0) } - return n.flatPreorder(make([]*Node, 0)) + return n.FlatPreorder(make([]*Node, 0)) } -func (n *Node) flatPreorder(result []*Node) []*Node { +func (n *Node) FlatPreorder(result []*Node) []*Node { if n == nil { return result @@ -169,7 +181,7 @@ func (n *Node) flatPreorder(result []*Node) []*Node { if len(n.Children) > 0 { for _, child := range n.Children { - result = child.flatPreorder(result) + result = child.FlatPreorder(result) } } From d5c0cee48be4ffda2c3f9e13ba0a355eebe1b808 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Tue, 19 Sep 2023 20:26:38 +0200 Subject: [PATCH 02/10] feat: add file to parent --- momentum-core/.gitignore | 3 +- momentum-core/artefacts/artefact-tree.go | 38 +- momentum-core/config/config.go | 6 + momentum-core/config/routes.go | 1 + momentum-core/docs/docs.go | 1079 +--------------------- momentum-core/docs/swagger.json | 1079 +--------------------- momentum-core/docs/swagger.yaml | 701 +------------- momentum-core/files/model.go | 28 +- momentum-core/files/routes.go | 78 ++ momentum-core/utils/filehandler.go | 8 + 10 files changed, 265 insertions(+), 2756 deletions(-) diff --git a/momentum-core/.gitignore b/momentum-core/.gitignore index 353f72f..c0f8a91 100644 --- a/momentum-core/.gitignore +++ b/momentum-core/.gitignore @@ -1,3 +1,4 @@ .vscode/* ./dev-setup.sh -momentum-core \ No newline at end of file +momentum-core +__debug* \ No newline at end of file diff --git a/momentum-core/artefacts/artefact-tree.go b/momentum-core/artefacts/artefact-tree.go index a216146..23bf286 100644 --- a/momentum-core/artefacts/artefact-tree.go +++ b/momentum-core/artefacts/artefact-tree.go @@ -47,7 +47,7 @@ func NewArtefact(path string, parent *Artefact) (*Artefact, error) { } artefact := new(Artefact) - artefact.Id, err = utils.GenerateId(idGenerationPath(path)) + artefact.Id, err = utils.GenerateId(config.IdGenerationPath(path)) if err != nil { return nil, err } @@ -152,6 +152,37 @@ func FileById(id string) (*Artefact, error) { return nil, errors.New("no file with id " + id) } +func DirectoryById(id string) (*Artefact, error) { + + artefacts, err := LoadArtefactTree() // origin + + if err != nil { + return nil, err + } + + directories := Directories(artefacts) + for _, dir := range directories { + if dir.Id == id { + return dir, nil + } + } + + return nil, errors.New("no file with id " + id) +} + +func Directories(origin *Artefact) []*Artefact { + + flattened := FlatPreorder(origin, make([]*Artefact, 0)) + directories := make([]*Artefact, 0) + for _, artefact := range flattened { + if artefact.ArtefactType != FILE && artefact.ArtefactType != META { + directories = append(directories, artefact) + } + } + + return directories +} + func Files(origin *Artefact) []*Artefact { flattened := FlatPreorder(origin, make([]*Artefact, 0)) @@ -273,11 +304,6 @@ func loadArtefactTreeUntilDepth(path string, parent *Artefact, depth int) (*Arte return artefact, nil } -func idGenerationPath(path string) string { - relevantForId, _ := strings.CutPrefix(path, config.GLOBAL.RepoDir()) - return relevantForId -} - func children(artefact *Artefact) ([]*Artefact, error) { childs := make([]*Artefact, 0) diff --git a/momentum-core/config/config.go b/momentum-core/config/config.go index 0120a7c..8a147f4 100644 --- a/momentum-core/config/config.go +++ b/momentum-core/config/config.go @@ -5,6 +5,7 @@ import ( "momentum-core/utils" "os" "path/filepath" + "strings" git "gopkg.in/src-d/go-git.v4" @@ -205,6 +206,11 @@ func createPathIfNotPresent(path string, parentDir string) { } } +func IdGenerationPath(path string) string { + relevantForId, _ := strings.CutPrefix(path, GLOBAL.RepoDir()) + return relevantForId +} + func cloneRepoTo(url string, username string, password string, location string) error { _, err := git.PlainClone(location, false, &git.CloneOptions{ URL: url, diff --git a/momentum-core/config/routes.go b/momentum-core/config/routes.go index 5130319..cb9e89b 100644 --- a/momentum-core/config/routes.go +++ b/momentum-core/config/routes.go @@ -4,6 +4,7 @@ const API = "/api" const API_VERSION_BETA = API + "/beta" const API_FILE_BY_ID = API_VERSION_BETA + "/file/:id" +const API_FILE_ADD = API_VERSION_BETA + "/file" const API_DIR_BY_ID = API_VERSION_BETA + "/dir/:id" const API_FILE_LINE_OVERWRITTENBY = API_VERSION_BETA + "/file/:id/line/:lineNumber/overwritten-by" const API_FILE_LINE_OVERWRITES = API_VERSION_BETA + "/file/:id/line/:lineNumber/overwrites" diff --git a/momentum-core/docs/docs.go b/momentum-core/docs/docs.go index 76078d1..1648007 100644 --- a/momentum-core/docs/docs.go +++ b/momentum-core/docs/docs.go @@ -197,803 +197,23 @@ const docTemplate = `{ } } }, - "/api/beta/file/{id}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets the content of a file", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/files.File" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/file/{id}/line/{lineNumber}/overwrites": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of child properties, which are overwritten by the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of properties which overwrite the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/stages": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "artefacts" - ], - "summary": "gets a list of all stages within an application or stage by id.", - "parameters": [ - { - "type": "string", - "description": "application or stage id", - "name": "parentId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/artefacts.Artefact" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/application": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "applications" - ], - "summary": "add an application", - "parameters": [ - { - "description": "Create Application", - "name": "applicationCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.ApplicationCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Application" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/deployment": { + "/api/beta/file": { "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get a deployment of a repository by id", - "parameters": [ - { - "description": "Create Deployment", - "name": "deploymentCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.DeploymentCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repositories": { - "get": { - "description": "load all repositories managed by this instance", - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "load repositories", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Repository" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository": { - "post": { - "description": "adds a new repository to the instance", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "add a new repository", - "parameters": [ - { - "description": "Create Repository", - "name": "repositoryCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.RepositoryCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Repository" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "get a repository", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Repository" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/app/stage/deployment/{deploymentId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get a deployment of a repository by id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Deployment ID", - "name": "deploymentId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/app/stage/{stageId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "stages" - ], - "summary": "get a stage of a repository by id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stage ID", - "name": "stageId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/application/values/{applicationId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "values" - ], - "summary": "get all values of an application by the applications id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Application ID", - "name": "applicationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/applications": { - "get": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "applications" - ], - "summary": "get all applications of a repository", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Application" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/deployment/values/{deploymentId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "values" - ], - "summary": "get all values of a deployment by the deployments id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Deployment ID", - "name": "deploymentId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/deployments": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get deployments", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } + "consumes": [ + "application/json" ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Deployment" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/stage/values/{stageId}": { - "get": { "produces": [ "application/json" ], "tags": [ - "values" - ], - "summary": "get all values of an stage by the stages id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stage ID", - "name": "stageId", - "in": "path", - "required": true - } + "files" ], + "summary": "adds a new file to a given parent", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } + "$ref": "#/definitions/files.File" } }, "400": { @@ -1017,20 +237,20 @@ const docTemplate = `{ } } }, - "/repository/{repositoryName}/stages": { + "/api/beta/file/{id}": { "get": { "produces": [ "application/json" ], "tags": [ - "stages" + "files" ], - "summary": "get stages", + "summary": "gets the content of a file", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true } @@ -1039,10 +259,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Stage" - } + "$ref": "#/definitions/files.File" } }, "400": { @@ -1066,27 +283,27 @@ const docTemplate = `{ } } }, - "/repository/{repositoryName}/value/{valueId}": { + "/api/beta/file/{id}/line/{lineNumber}/overwrites": { "get": { "produces": [ "application/json" ], "tags": [ - "values" + "files" ], - "summary": "get a value of a repository by id", + "summary": "gets a list of child properties, which are overwritten by the given line.", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Value ID", - "name": "valueId", + "type": "integer", + "description": "line number in file", + "name": "lineNumber", "in": "path", "required": true } @@ -1095,7 +312,10 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Value" + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } } }, "400": { @@ -1119,27 +339,27 @@ const docTemplate = `{ } } }, - "/repository/{repositoryName}/{applicationId}": { + "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { "get": { "produces": [ "application/json" ], "tags": [ - "applications" + "files" ], - "summary": "get an application of a repository by id", + "summary": "gets a list of properties which overwrite the given line.", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Application ID", - "name": "applicationId", + "type": "integer", + "description": "line number in file", + "name": "lineNumber", "in": "path", "required": true } @@ -1148,7 +368,10 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } } }, "400": { @@ -1172,34 +395,29 @@ const docTemplate = `{ } } }, - "/stage": { - "post": { - "consumes": [ - "application/json" - ], + "/api/beta/stages": { + "get": { "produces": [ "application/json" ], "tags": [ - "stages" + "artefacts" ], - "summary": "add a new stage", + "summary": "gets a list of all stages within an application or stage by id.", "parameters": [ { - "description": "Create Stage", - "name": "stageCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.StageCreateRequest" - } + "type": "string", + "description": "application or stage id", + "name": "parentId", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Stage" + "$ref": "#/definitions/artefacts.Artefact" } }, "400": { @@ -1242,7 +460,7 @@ const docTemplate = `{ "type": "string" }, "parentId": { - "description": "id's of parent", + "description": "id of parent artefacts", "type": "string" }, "type": { @@ -1305,9 +523,6 @@ const docTemplate = `{ "name": { "type": "string" }, - "path": { - "type": "string" - }, "subDirs": { "type": "array", "items": { @@ -1327,9 +542,6 @@ const docTemplate = `{ }, "name": { "type": "string" - }, - "path": { - "type": "string" } } }, @@ -1342,208 +554,11 @@ const docTemplate = `{ "originFileLine": { "type": "integer" }, - "originFilePath": { - "type": "string" - }, "overwriteFileId": { "type": "string" }, "overwriteFileLine": { "type": "integer" - }, - "overwriteFilePath": { - "type": "string" - } - } - }, - "models.Application": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.ApplicationCreateRequest": { - "type": "object", - "properties": { - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Deployment": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "repositoryId": { - "type": "string" - } - } - }, - "models.DeploymentCreateRequest": { - "type": "object", - "properties": { - "applicationName": { - "type": "string" - }, - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Repository": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "models.RepositoryCreateRequest": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "models.Stage": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentApplicationId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - } - } - }, - "models.StageCreateRequest": { - "type": "object", - "properties": { - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentApplicationId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Value": { - "type": "object", - "properties": { - "displayName": { - "type": "string" - }, - "id": { - "type": "string" - }, - "key": { - "type": "string" - }, - "parentDeploymentId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "models.ValueType": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3 - ], - "x-enum-varnames": [ - "REPOSITORY", - "APPLICATION", - "STAGE", - "DEPLOYMENT" - ] - }, - "models.ValueWrapper": { - "type": "object", - "properties": { - "parentFileId": { - "type": "string" - }, - "parentFileName": { - "type": "string" - }, - "valueType": { - "$ref": "#/definitions/models.ValueType" - }, - "values": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Value" - } } } } diff --git a/momentum-core/docs/swagger.json b/momentum-core/docs/swagger.json index 3fae5b9..ac319d1 100644 --- a/momentum-core/docs/swagger.json +++ b/momentum-core/docs/swagger.json @@ -194,803 +194,23 @@ } } }, - "/api/beta/file/{id}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets the content of a file", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/files.File" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/file/{id}/line/{lineNumber}/overwrites": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of child properties, which are overwritten by the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of properties which overwrite the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/api/beta/stages": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "artefacts" - ], - "summary": "gets a list of all stages within an application or stage by id.", - "parameters": [ - { - "type": "string", - "description": "application or stage id", - "name": "parentId", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/artefacts.Artefact" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/application": { - "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "applications" - ], - "summary": "add an application", - "parameters": [ - { - "description": "Create Application", - "name": "applicationCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.ApplicationCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Application" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/deployment": { + "/api/beta/file": { "post": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get a deployment of a repository by id", - "parameters": [ - { - "description": "Create Deployment", - "name": "deploymentCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.DeploymentCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repositories": { - "get": { - "description": "load all repositories managed by this instance", - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "load repositories", - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Repository" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository": { - "post": { - "description": "adds a new repository to the instance", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "add a new repository", - "parameters": [ - { - "description": "Create Repository", - "name": "repositoryCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.RepositoryCreateRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Repository" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "repositories" - ], - "summary": "get a repository", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Repository" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/app/stage/deployment/{deploymentId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get a deployment of a repository by id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Deployment ID", - "name": "deploymentId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/app/stage/{stageId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "stages" - ], - "summary": "get a stage of a repository by id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stage ID", - "name": "stageId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/models.Deployment" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/application/values/{applicationId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "values" - ], - "summary": "get all values of an application by the applications id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Application ID", - "name": "applicationId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/applications": { - "get": { - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "applications" - ], - "summary": "get all applications of a repository", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Application" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/deployment/values/{deploymentId}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "values" - ], - "summary": "get all values of a deployment by the deployments id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Deployment ID", - "name": "deploymentId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/deployments": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "deployments" - ], - "summary": "get deployments", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - } + "consumes": [ + "application/json" ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Deployment" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, - "/repository/{repositoryName}/stage/values/{stageId}": { - "get": { "produces": [ "application/json" ], "tags": [ - "values" - ], - "summary": "get all values of an stage by the stages id", - "parameters": [ - { - "type": "string", - "description": "Repository Name", - "name": "repositoryName", - "in": "path", - "required": true - }, - { - "type": "string", - "description": "Stage ID", - "name": "stageId", - "in": "path", - "required": true - } + "files" ], + "summary": "adds a new file to a given parent", "responses": { "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.ValueWrapper" - } + "$ref": "#/definitions/files.File" } }, "400": { @@ -1014,20 +234,20 @@ } } }, - "/repository/{repositoryName}/stages": { + "/api/beta/file/{id}": { "get": { "produces": [ "application/json" ], "tags": [ - "stages" + "files" ], - "summary": "get stages", + "summary": "gets the content of a file", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true } @@ -1036,10 +256,7 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Stage" - } + "$ref": "#/definitions/files.File" } }, "400": { @@ -1063,27 +280,27 @@ } } }, - "/repository/{repositoryName}/value/{valueId}": { + "/api/beta/file/{id}/line/{lineNumber}/overwrites": { "get": { "produces": [ "application/json" ], "tags": [ - "values" + "files" ], - "summary": "get a value of a repository by id", + "summary": "gets a list of child properties, which are overwritten by the given line.", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Value ID", - "name": "valueId", + "type": "integer", + "description": "line number in file", + "name": "lineNumber", "in": "path", "required": true } @@ -1092,7 +309,10 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Value" + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } } }, "400": { @@ -1116,27 +336,27 @@ } } }, - "/repository/{repositoryName}/{applicationId}": { + "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { "get": { "produces": [ "application/json" ], "tags": [ - "applications" + "files" ], - "summary": "get an application of a repository by id", + "summary": "gets a list of properties which overwrite the given line.", "parameters": [ { "type": "string", - "description": "Repository Name", - "name": "repositoryName", + "description": "file id", + "name": "id", "in": "path", "required": true }, { - "type": "string", - "description": "Application ID", - "name": "applicationId", + "type": "integer", + "description": "line number in file", + "name": "lineNumber", "in": "path", "required": true } @@ -1145,7 +365,10 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Application" + "type": "array", + "items": { + "$ref": "#/definitions/files.Overwrite" + } } }, "400": { @@ -1169,34 +392,29 @@ } } }, - "/stage": { - "post": { - "consumes": [ - "application/json" - ], + "/api/beta/stages": { + "get": { "produces": [ "application/json" ], "tags": [ - "stages" + "artefacts" ], - "summary": "add a new stage", + "summary": "gets a list of all stages within an application or stage by id.", "parameters": [ { - "description": "Create Stage", - "name": "stageCreateRequest", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/models.StageCreateRequest" - } + "type": "string", + "description": "application or stage id", + "name": "parentId", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Stage" + "$ref": "#/definitions/artefacts.Artefact" } }, "400": { @@ -1239,7 +457,7 @@ "type": "string" }, "parentId": { - "description": "id's of parent", + "description": "id of parent artefacts", "type": "string" }, "type": { @@ -1302,9 +520,6 @@ "name": { "type": "string" }, - "path": { - "type": "string" - }, "subDirs": { "type": "array", "items": { @@ -1324,9 +539,6 @@ }, "name": { "type": "string" - }, - "path": { - "type": "string" } } }, @@ -1339,208 +551,11 @@ "originFileLine": { "type": "integer" }, - "originFilePath": { - "type": "string" - }, "overwriteFileId": { "type": "string" }, "overwriteFileLine": { "type": "integer" - }, - "overwriteFilePath": { - "type": "string" - } - } - }, - "models.Application": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.ApplicationCreateRequest": { - "type": "object", - "properties": { - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Deployment": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "repositoryId": { - "type": "string" - } - } - }, - "models.DeploymentCreateRequest": { - "type": "object", - "properties": { - "applicationName": { - "type": "string" - }, - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Repository": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - }, - "models.RepositoryCreateRequest": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - } - } - }, - "models.Stage": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentApplicationId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - } - } - }, - "models.StageCreateRequest": { - "type": "object", - "properties": { - "chartVersion": { - "type": "string" - }, - "name": { - "type": "string" - }, - "parentApplicationId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "reconcileInterval": { - "type": "string" - }, - "repositoryName": { - "type": "string" - } - } - }, - "models.Value": { - "type": "object", - "properties": { - "displayName": { - "type": "string" - }, - "id": { - "type": "string" - }, - "key": { - "type": "string" - }, - "parentDeploymentId": { - "type": "string" - }, - "parentStageId": { - "type": "string" - }, - "value": { - "type": "string" - } - } - }, - "models.ValueType": { - "type": "integer", - "enum": [ - 0, - 1, - 2, - 3 - ], - "x-enum-varnames": [ - "REPOSITORY", - "APPLICATION", - "STAGE", - "DEPLOYMENT" - ] - }, - "models.ValueWrapper": { - "type": "object", - "properties": { - "parentFileId": { - "type": "string" - }, - "parentFileName": { - "type": "string" - }, - "valueType": { - "$ref": "#/definitions/models.ValueType" - }, - "values": { - "type": "array", - "items": { - "$ref": "#/definitions/models.Value" - } } } } diff --git a/momentum-core/docs/swagger.yaml b/momentum-core/docs/swagger.yaml index fc59168..158819b 100644 --- a/momentum-core/docs/swagger.yaml +++ b/momentum-core/docs/swagger.yaml @@ -12,7 +12,7 @@ definitions: name: type: string parentId: - description: id's of parent + description: id of parent artefacts type: string type: $ref: '#/definitions/artefacts.ArtefactType' @@ -57,8 +57,6 @@ definitions: type: string name: type: string - path: - type: string subDirs: items: $ref: '#/definitions/files.Dir' @@ -72,8 +70,6 @@ definitions: type: string name: type: string - path: - type: string type: object files.Overwrite: properties: @@ -81,140 +77,10 @@ definitions: type: string originFileLine: type: integer - originFilePath: - type: string overwriteFileId: type: string overwriteFileLine: type: integer - overwriteFilePath: - type: string - type: object - models.Application: - properties: - id: - type: string - name: - type: string - repositoryName: - type: string - type: object - models.ApplicationCreateRequest: - properties: - chartVersion: - type: string - name: - type: string - reconcileInterval: - type: string - repositoryName: - type: string - type: object - models.Deployment: - properties: - id: - type: string - name: - type: string - parentStageId: - type: string - repositoryId: - type: string - type: object - models.DeploymentCreateRequest: - properties: - applicationName: - type: string - chartVersion: - type: string - name: - type: string - parentStageId: - type: string - reconcileInterval: - type: string - repositoryName: - type: string - type: object - models.Repository: - properties: - id: - type: string - name: - type: string - type: object - models.RepositoryCreateRequest: - properties: - name: - type: string - url: - type: string - type: object - models.Stage: - properties: - id: - type: string - name: - type: string - parentApplicationId: - type: string - parentStageId: - type: string - type: object - models.StageCreateRequest: - properties: - chartVersion: - type: string - name: - type: string - parentApplicationId: - type: string - parentStageId: - type: string - reconcileInterval: - type: string - repositoryName: - type: string - type: object - models.Value: - properties: - displayName: - type: string - id: - type: string - key: - type: string - parentDeploymentId: - type: string - parentStageId: - type: string - value: - type: string - type: object - models.ValueType: - enum: - - 0 - - 1 - - 2 - - 3 - type: integer - x-enum-varnames: - - REPOSITORY - - APPLICATION - - STAGE - - DEPLOYMENT - models.ValueWrapper: - properties: - parentFileId: - type: string - parentFileName: - type: string - valueType: - $ref: '#/definitions/models.ValueType' - values: - items: - $ref: '#/definitions/models.Value' - type: array type: object host: localhost:8080 info: @@ -343,6 +209,32 @@ paths: summary: gets the content of a file tags: - files + /api/beta/file: + post: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/files.File' + "400": + description: Bad Request + schema: + $ref: '#/definitions/config.ApiError' + "404": + description: Not Found + schema: + $ref: '#/definitions/config.ApiError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/config.ApiError' + summary: adds a new file to a given parent + tags: + - files /api/beta/file/{id}: get: parameters: @@ -478,545 +370,6 @@ paths: summary: gets a list of all stages within an application or stage by id. tags: - artefacts - /application: - post: - consumes: - - application/json - parameters: - - description: Create Application - in: body - name: applicationCreateRequest - required: true - schema: - $ref: '#/definitions/models.ApplicationCreateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Application' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: add an application - tags: - - applications - /deployment: - post: - consumes: - - application/json - parameters: - - description: Create Deployment - in: body - name: deploymentCreateRequest - required: true - schema: - $ref: '#/definitions/models.DeploymentCreateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Deployment' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get a deployment of a repository by id - tags: - - deployments - /repositories: - get: - description: load all repositories managed by this instance - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.Repository' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: load repositories - tags: - - repositories - /repository: - post: - consumes: - - application/json - description: adds a new repository to the instance - parameters: - - description: Create Repository - in: body - name: repositoryCreateRequest - required: true - schema: - $ref: '#/definitions/models.RepositoryCreateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Repository' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: add a new repository - tags: - - repositories - /repository/{repositoryName}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Repository' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get a repository - tags: - - repositories - /repository/{repositoryName}/{applicationId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Application ID - in: path - name: applicationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Application' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get an application of a repository by id - tags: - - applications - /repository/{repositoryName}/app/stage/{stageId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Stage ID - in: path - name: stageId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Deployment' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get a stage of a repository by id - tags: - - stages - /repository/{repositoryName}/app/stage/deployment/{deploymentId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Deployment ID - in: path - name: deploymentId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Deployment' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get a deployment of a repository by id - tags: - - deployments - /repository/{repositoryName}/application/values/{applicationId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Application ID - in: path - name: applicationId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.ValueWrapper' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get all values of an application by the applications id - tags: - - values - /repository/{repositoryName}/applications: - get: - consumes: - - application/json - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.Application' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get all applications of a repository - tags: - - applications - /repository/{repositoryName}/deployment/values/{deploymentId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Deployment ID - in: path - name: deploymentId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.ValueWrapper' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get all values of a deployment by the deployments id - tags: - - values - /repository/{repositoryName}/deployments: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.Deployment' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get deployments - tags: - - deployments - /repository/{repositoryName}/stage/values/{stageId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Stage ID - in: path - name: stageId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.ValueWrapper' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get all values of an stage by the stages id - tags: - - values - /repository/{repositoryName}/stages: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/models.Stage' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get stages - tags: - - stages - /repository/{repositoryName}/value/{valueId}: - get: - parameters: - - description: Repository Name - in: path - name: repositoryName - required: true - type: string - - description: Value ID - in: path - name: valueId - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Value' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: get a value of a repository by id - tags: - - values - /stage: - post: - consumes: - - application/json - parameters: - - description: Create Stage - in: body - name: stageCreateRequest - required: true - schema: - $ref: '#/definitions/models.StageCreateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/models.Stage' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: add a new stage - tags: - - stages schemes: - http swagger: "2.0" diff --git a/momentum-core/files/model.go b/momentum-core/files/model.go index a81eaa5..006e4df 100644 --- a/momentum-core/files/model.go +++ b/momentum-core/files/model.go @@ -21,23 +21,29 @@ type IOverwrite interface { } type File struct { - Id string - Name string - Body string + Id string `json:"id"` + Name string `json:"name"` + Body string `json:"body"` +} + +type CreateFileRequest struct { + ParentId string `json:"parentId"` + Name string `json:"name"` + Body string `json:"body"` } type Dir struct { - Id string - Name string - SubDirs []*Dir - Files []*File + Id string `json:"id"` + Name string `json:"name"` + SubDirs []*Dir `json:"subDirs"` + Files []*File `json:"files"` } type Overwrite struct { - OriginFileId string - OriginFileLine int - OverwriteFileId string - OverwriteFileLine int + OriginFileId string `json:"originFileId"` + OriginFileLine int `json:"originFileLine"` + OverwriteFileId string `json:"overwriteFileId"` + OverwriteFileLine int `json:"overwriteFileLine"` } func NewFile(id string, name string, encodedBody string) *File { diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go index 03733a1..3a15e6a 100644 --- a/momentum-core/files/routes.go +++ b/momentum-core/files/routes.go @@ -1,15 +1,19 @@ package files import ( + "errors" "momentum-core/artefacts" "momentum-core/config" + "momentum-core/utils" "net/http" + "path/filepath" "github.com/gin-gonic/gin" ) func RegisterFileRoutes(engine *gin.Engine) { engine.GET(config.API_FILE_BY_ID, GetFile) + engine.POST(config.API_FILE_ADD, AddFile) engine.GET(config.API_DIR_BY_ID, GetDir) engine.GET(config.API_FILE_LINE_OVERWRITTENBY, GetOverwrittenBy) engine.GET(config.API_FILE_LINE_OVERWRITES, GetOverwrites) @@ -44,6 +48,80 @@ func GetFile(c *gin.Context) { c.JSON(http.StatusOK, file) } +// AddFile godoc +// +// @Summary adds a new file to a given parent +// @Tags files +// @Accept json +// @Produce json +// @Body CreateFileRequest +// @Success 200 {object} File +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/file [post] +func AddFile(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + + createFileReq := new(CreateFileRequest) + + err := c.BindJSON(createFileReq) + if err != nil { + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + dir, err := artefacts.DirectoryById(createFileReq.ParentId) + if err != nil { + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + filePath := filepath.Join(artefacts.FullPath(dir), createFileReq.Name) + if utils.FileExists(filePath) { + err = errors.New("file with given name already exists") + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + fileContentDecoded, err := fileToRaw(createFileReq.Body) + if err != nil { + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + writeSuccess := utils.FileWrite(filePath, fileContentDecoded) + if !writeSuccess { + err = errors.New("writing file failed") + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + encodedFile, err := fileToBase64(filePath) + newFileId, err := utils.GenerateId(config.IdGenerationPath(filePath)) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + fileArtefact, err := artefacts.FileById(newFileId) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + file := NewFile(fileArtefact.Id, fileArtefact.Name, encodedFile) + + c.JSON(http.StatusOK, file) +} + // GetDir godoc // // @Summary gets the content of a file diff --git a/momentum-core/utils/filehandler.go b/momentum-core/utils/filehandler.go index 9bacca5..308bd6f 100644 --- a/momentum-core/utils/filehandler.go +++ b/momentum-core/utils/filehandler.go @@ -114,6 +114,14 @@ func dirCopyRecursive(rootOrigin string, rootDestination string, relativeToParen return errors.Join(errs...) } +func FileWrite(path string, content string) bool { + + buf := make([]byte, 0) + buf = append(buf, bytes.NewBufferString(content).Bytes()...) + + return write(path, int64(len(buf)), buf) +} + func FileWriteLines(path string, lines []string) bool { buf := make([]byte, 0) From ec9a53c081db78245626912f7c0c5a03e7c81622 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 25 Sep 2023 22:33:18 +0200 Subject: [PATCH 03/10] feat: property backtracking implementation --- momentum-core/artefacts/model.go | 19 -- momentum-core/backtracking/backtrack.go | 144 +++++++++ momentum-core/backtracking/backtrack_test.go | 32 ++ .../backtracking/property-backtracker.go | 85 ++++++ momentum-core/backtracking/test.yaml | 9 + momentum-core/backtracking/yaml-parser.go | 54 ++++ momentum-core/clients/kustomization-client.go | 15 +- momentum-core/dispatcher.go | 37 --- momentum-core/files/routes.go | 2 + momentum-core/main.go | 27 +- momentum-core/templates/model.go | 32 ++ momentum-core/templates/routes.go | 1 + .../templates/template-config-parser.go | 1 + momentum-core/tree/bfs.go | 79 ----- momentum-core/tree/bfs_test.go | 69 ----- momentum-core/tree/momentum-tree.go | 242 ---------------- momentum-core/tree/momentum-tree_test.go | 80 ----- momentum-core/tree/parser.go | 131 --------- momentum-core/tree/parser_test.go | 111 ------- .../tree/testdata/kustomization.yaml | 7 - .../testdata_sub/_base/kustomization.yaml | 18 -- .../tree/testdata/testdata_sub/_base/ns.yaml | 4 - .../testdata/testdata_sub/_base/release.yaml | 26 -- .../testdata/testdata_sub/_base/values.yaml | 3 - .../_deploy/deployment3/kustomization.yaml | 15 - .../_deploy/deployment3/release.yaml | 4 - .../_deploy/deployment3/values.yaml | 2 - .../testdata/testdata_sub/deployment2.yaml | 11 - .../testdata/testdata_sub/deployment3.yaml | 11 - .../testdata/testdata_sub/kustomization.yaml | 7 - momentum-core/tree/tree.go | 228 --------------- momentum-core/tree/tree_test.go | 24 -- momentum-core/tree/utils.go | 45 --- momentum-core/tree/writer.go | 102 ------- momentum-core/tree/yaml-node-factory.go | 189 ------------ momentum-core/tree/yaml-node-factory_test.go | 274 ------------------ momentum-core/yaml/tree.go | 162 +++++++++++ .../printer.go => yaml/view-node-printer.go} | 26 +- momentum-core/{tree => yaml}/yaml_mapper.go | 81 ++++-- 39 files changed, 603 insertions(+), 1806 deletions(-) create mode 100644 momentum-core/backtracking/backtrack.go create mode 100644 momentum-core/backtracking/backtrack_test.go create mode 100644 momentum-core/backtracking/property-backtracker.go create mode 100644 momentum-core/backtracking/test.yaml create mode 100644 momentum-core/backtracking/yaml-parser.go delete mode 100644 momentum-core/dispatcher.go create mode 100644 momentum-core/templates/model.go create mode 100644 momentum-core/templates/routes.go create mode 100644 momentum-core/templates/template-config-parser.go delete mode 100644 momentum-core/tree/bfs.go delete mode 100644 momentum-core/tree/bfs_test.go delete mode 100644 momentum-core/tree/momentum-tree.go delete mode 100644 momentum-core/tree/momentum-tree_test.go delete mode 100644 momentum-core/tree/parser.go delete mode 100644 momentum-core/tree/parser_test.go delete mode 100644 momentum-core/tree/testdata/kustomization.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_base/kustomization.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_base/ns.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_base/release.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_base/values.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/kustomization.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/release.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/values.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/deployment2.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/deployment3.yaml delete mode 100644 momentum-core/tree/testdata/testdata_sub/kustomization.yaml delete mode 100644 momentum-core/tree/tree.go delete mode 100644 momentum-core/tree/tree_test.go delete mode 100644 momentum-core/tree/utils.go delete mode 100644 momentum-core/tree/writer.go delete mode 100644 momentum-core/tree/yaml-node-factory.go delete mode 100644 momentum-core/tree/yaml-node-factory_test.go create mode 100644 momentum-core/yaml/tree.go rename momentum-core/{tree/printer.go => yaml/view-node-printer.go} (70%) rename momentum-core/{tree => yaml}/yaml_mapper.go (74%) diff --git a/momentum-core/artefacts/model.go b/momentum-core/artefacts/model.go index 0c99476..84f0faa 100644 --- a/momentum-core/artefacts/model.go +++ b/momentum-core/artefacts/model.go @@ -1,7 +1,5 @@ package artefacts -import "momentum-core/tree" - type ArtefactType int const ( @@ -22,20 +20,3 @@ type Artefact struct { ParentId string `json:"parentId"` // id of parent artefacts Parent *Artefact `json:"-"` } - -func toArtefact(n *tree.Node) *Artefact { - - if n == nil { - return nil - } - - artefact := new(Artefact) - artefact.Id = n.Id - artefact.Name = n.NormalizedPath() - - if n.Kind == tree.File { - artefact.ArtefactType = FILE - } - - return artefact -} diff --git a/momentum-core/backtracking/backtrack.go b/momentum-core/backtracking/backtrack.go new file mode 100644 index 0000000..a96371c --- /dev/null +++ b/momentum-core/backtracking/backtrack.go @@ -0,0 +1,144 @@ +package backtracking + +type Backtracker[T any, P any] interface { + // The function executes the backtrack algorithm as configured and returns the result + RunBacktrack() []*Match[T, P] +} + +type Input[I any, T any, P any] interface { + // GetInput shall return the input of a configured source, such that the Parse function can parse the input into the Node structure + GetInput() I + // Parse shall map the input source into the node structure + Parse(I) *Node[T, P] + // GetSearch shall return the instance of the search + GetSearch() Search[T, P] +} + +type Search[T any, P any] interface { + // The predicate is the fragment, the backtracking algorithm searches for + Predicate() *T + // The Comparable shall process a node and generate an object comparable to the predicate + Comparable(*Node[T, P]) *T + // IsMatch compares the predicate with a given compare value and returns true if they match and false if they do not + IsMatch(*T, *T) bool + // StopEarly shall return true if the algorithm must backtrack and reject the current branch. + // False if the algorithm shall process further even if no full match has been reached. + StopEarly(*T, *T) bool +} + +// Node is the structure used inside the backtrack algorithm and describes a tree structure. +type Node[T any, P any] struct { + value *T + pointer *P // pointer to the actual element which belongs to the node + parent *Node[T, P] + children []*Node[T, P] +} + +type Match[T any, P any] struct { + Input *T + Match *T + MatchNode *Node[T, P] +} + +// Implementation of a backtracking algorithm to find matches on path as described on Wikipedia: https://en.wikipedia.org/wiki/Backtracking +func Backtrack[I any, T any, P any](inp Input[I, T, P]) []*Match[T, P] { + + result := make([]*Match[T, P], 0) + return backtrack(inp.GetSearch(), root(inp.Parse(inp.GetInput())), result) +} + +func backtrack[T any, P any](problem Search[T, P], n *Node[T, P], result []*Match[T, P]) []*Match[T, P] { + + if n == nil { + return result + } + + // Currently no rejection makes sense + // if reject(problem, n) { + // return backtrack(problem, next(problem, n), result) + // } + + if accept(problem, n) { + result = appendOutput(problem, n, result) + } + + return backtrack(problem, next(problem, n), result) +} + +func root[T any, P any](n *Node[T, P]) *Node[T, P] { + + current := n + for current.parent != nil { + current = current.parent + } + + return current +} + +func reject[T any, P any](search Search[T, P], n *Node[T, P]) bool { + + // can be dangerous, because results are ommited possibly ommitted + return search.StopEarly(search.Predicate(), search.Comparable(n)) +} + +func accept[T any, P any](search Search[T, P], n *Node[T, P]) bool { + + return search.IsMatch(search.Predicate(), search.Comparable(n)) +} + +func first[T any, P any](search Search[T, P], n *Node[T, P]) *Node[T, P] { + + return n.children[0] +} + +func next[T any, P any](search Search[T, P], n *Node[T, P]) *Node[T, P] { + + if n == nil { + return nil + } + + if len(n.children) == 0 { + // backtrack + return walkUp(n.parent, n) + } + + return first(search, n) +} + +func walkUp[T any, P any](parent *Node[T, P], current *Node[T, P]) *Node[T, P] { + + found := false + if parent != nil && current != nil && current.parent == parent { + for _, chld := range parent.children { + if found { + return chld + } else if chld == current { + found = true + } + } + } + + if found && parent.parent != nil { + // this indicates that the current node was the last of level, thus we need to walk up further + // if the parent is nil, this indicates we are at root and traversed the whole tree + if parent.parent == nil { + return nil + } + + return walkUp(parent.parent, parent) + } + + return nil +} + +func appendOutput[T any, P any](search Search[T, P], n *Node[T, P], matches []*Match[T, P]) []*Match[T, P] { + + match := new(Match[T, P]) + match.Input = search.Predicate() + match.Match = n.value + match.MatchNode = n + + matches = append(matches, match) + + return matches +} diff --git a/momentum-core/backtracking/backtrack_test.go b/momentum-core/backtracking/backtrack_test.go new file mode 100644 index 0000000..5bedc86 --- /dev/null +++ b/momentum-core/backtracking/backtrack_test.go @@ -0,0 +1,32 @@ +package backtracking_test + +import ( + "fmt" + "momentum-core/backtracking" + "os" + "path/filepath" + "testing" +) + +func TestBacktracker(t *testing.T) { + + wd, err := os.Getwd() + if err != nil { + fmt.Println(err) + t.FailNow() + } + + testFilePath := filepath.Join(wd, "test.yaml") + + backtracker := backtracking.NewPropertyBacktracker("test.for", testFilePath, backtracking.NewYamlPropertyParser()) + result := backtracker.RunBacktrack() + + if len(result) != 1 { + fmt.Println("expected one result") + t.FailNow() + } + + for _, res := range result { + fmt.Println(res) + } +} diff --git a/momentum-core/backtracking/property-backtracker.go b/momentum-core/backtracking/property-backtracker.go new file mode 100644 index 0000000..fef7cd9 --- /dev/null +++ b/momentum-core/backtracking/property-backtracker.go @@ -0,0 +1,85 @@ +package backtracking + +import ( + "momentum-core/yaml" + "strings" +) + +const PROPERTY_SEPARATOR = "." + +type PropertyParser interface { + ParseProperties(string) *Node[string, yaml.ViewNode] +} + +// The property backtracker finds matches within a property structure. +// A property search is concepted as hierarchical string separated by dots, +// where each level of the +type PropertyBacktracker struct { + Backtracker[string, yaml.ViewNode] + Input[string, string, yaml.ViewNode] + Search[string, yaml.ViewNode] + + inputParser PropertyParser + predicate string + path string // path to the yaml file which shall be processed +} + +func NewPropertyBacktracker(predicate string, path string, parser PropertyParser) *PropertyBacktracker { + + backtracker := new(PropertyBacktracker) + backtracker.predicate = predicate + backtracker.inputParser = parser + backtracker.path = path + + return backtracker +} + +func (backtracker *PropertyBacktracker) RunBacktrack() []*Match[string, yaml.ViewNode] { + + return Backtrack[string, string, yaml.ViewNode](backtracker) +} + +func (backtracker *PropertyBacktracker) GetInput() string { + + return backtracker.path +} + +func (backtracker *PropertyBacktracker) Parse(input string) *Node[string, yaml.ViewNode] { + + return backtracker.inputParser.ParseProperties(backtracker.path) +} + +func (backtracker *PropertyBacktracker) GetSearch() Search[string, yaml.ViewNode] { + + return backtracker +} + +func (backtracker *PropertyBacktracker) Predicate() *string { + + return &backtracker.predicate +} + +func (backtracker *PropertyBacktracker) Comparable(n *Node[string, yaml.ViewNode]) *string { + + propertyString := "" + current := n + for current != nil { + propertyString = strings.Join([]string{*current.value, propertyString}, PROPERTY_SEPARATOR) + current = current.parent + } + + cutted, _ := strings.CutPrefix(propertyString, PROPERTY_SEPARATOR) + cutted, _ = strings.CutSuffix(cutted, PROPERTY_SEPARATOR) + //fmt.Println("cutted propertyString:", propertyString) + return &cutted +} + +func (backtracker *PropertyBacktracker) IsMatch(predicate *string, argument *string) bool { + + return strings.EqualFold(*predicate, *argument) +} + +func (backtracker *PropertyBacktracker) StopEarly(predicate *string, argument *string) bool { + + return !strings.HasPrefix(*predicate, *argument) +} diff --git a/momentum-core/backtracking/test.yaml b/momentum-core/backtracking/test.yaml new file mode 100644 index 0000000..a8ff1fc --- /dev/null +++ b/momentum-core/backtracking/test.yaml @@ -0,0 +1,9 @@ +test: + for: + backtracker: test + not-for: + backtracker: test + go-never: to +trees: + are: + your: friends \ No newline at end of file diff --git a/momentum-core/backtracking/yaml-parser.go b/momentum-core/backtracking/yaml-parser.go new file mode 100644 index 0000000..367cac8 --- /dev/null +++ b/momentum-core/backtracking/yaml-parser.go @@ -0,0 +1,54 @@ +package backtracking + +import ( + "fmt" + "momentum-core/utils" + "momentum-core/yaml" +) + +type YamlPropertyParser struct { + PropertyParser +} + +func NewYamlPropertyParser() *YamlPropertyParser { + + parser := new(YamlPropertyParser) + + return parser +} + +func (parser *YamlPropertyParser) ParseProperties(path string) *Node[string, yaml.ViewNode] { + + if !utils.FileExists(path) { + return nil + } + + root, err := yaml.ParseFile(path) + if err != nil { + fmt.Println(err) + return nil + } + + if root.Children[0].Kind == yaml.Mapping { + + return viewNodeToNode(root.Children[0], nil) + } + + return nil +} + +func viewNodeToNode(n *yaml.ViewNode, parent *Node[string, yaml.ViewNode]) *Node[string, yaml.ViewNode] { + + r := new(Node[string, yaml.ViewNode]) + r.parent = parent + r.value = &n.Path + r.pointer = n + + children := make([]*Node[string, yaml.ViewNode], 0) + for _, child := range n.Children { + children = append(children, viewNodeToNode(child, r)) + } + r.children = children + + return r +} diff --git a/momentum-core/clients/kustomization-client.go b/momentum-core/clients/kustomization-client.go index df65ece..dbba17a 100644 --- a/momentum-core/clients/kustomization-client.go +++ b/momentum-core/clients/kustomization-client.go @@ -3,7 +3,6 @@ package clients import ( "fmt" "momentum-core/config" - "momentum-core/tree" "momentum-core/utils" "sigs.k8s.io/kustomize/api/krusty" @@ -36,13 +35,14 @@ func (kustomizationService *KustomizationValidationClient) Validate(repoName str return err } - repoTree, err := tree.Parse(path) - if err != nil { - fmt.Println("failed parsing validation directory") - return err - } + // TODO -> fix kustomization validator + // repoTree, err := yaml.Parse(path) + // if err != nil { + // fmt.Println("failed parsing validation directory") + // return err + // } - err = kustomizationService.check(repoTree.MomentumRoot().FullPath()) + // err = kustomizationService.check(repoTree.MomentumRoot().FullPath()) if err != nil { fmt.Println("error while validating kustomize structure (check):", err.Error()) kustomizationService.validationCleanup(path) @@ -68,7 +68,6 @@ func (kustomizationService *KustomizationValidationClient) check(path string) er fs := filesys.MakeFsOnDisk() - // TODO -> OpenAI ApiSchemes for FluxCD -> Kubeconform kustomizer := krusty.MakeKustomizer(krusty.MakeDefaultOptions()) _, err := kustomizer.Run(fs, path) diff --git a/momentum-core/dispatcher.go b/momentum-core/dispatcher.go deleted file mode 100644 index 3ca8b61..0000000 --- a/momentum-core/dispatcher.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "momentum-core/artefacts" - "momentum-core/config" - "momentum-core/files" - - "github.com/gin-gonic/gin" - - swaggerFiles "github.com/swaggo/files" - ginSwagger "github.com/swaggo/gin-swagger" - - _ "momentum-core/docs" -) - -type Dispatcher struct { - server *gin.Engine - config *config.MomentumConfig -} - -func NewDispatcher(config *config.MomentumConfig) *Dispatcher { - - dispatcher := new(Dispatcher) - dispatcher.config = config - dispatcher.server = gin.Default() - - files.RegisterFileRoutes(dispatcher.server) - artefacts.RegisterArtefactRoutes(dispatcher.server) - - dispatcher.server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) - - return dispatcher -} - -func (d *Dispatcher) Serve() { - d.server.Run("localhost:8080") -} diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go index 3a15e6a..65669f9 100644 --- a/momentum-core/files/routes.go +++ b/momentum-core/files/routes.go @@ -135,6 +135,8 @@ func AddFile(c *gin.Context) { // @Router /api/beta/dir/{id} [get] func GetDir(c *gin.Context) { + // TODO is this needed? + _ = c.Param("id") return diff --git a/momentum-core/main.go b/momentum-core/main.go index 0a8b029..b45e1d6 100644 --- a/momentum-core/main.go +++ b/momentum-core/main.go @@ -2,11 +2,21 @@ package main import ( "fmt" + "momentum-core/artefacts" "momentum-core/config" + "momentum-core/files" - _ "github.com/pdrum/swagger-automation/docs" // This line is necessary for go-swagger to find your docs! + "github.com/gin-gonic/gin" + + // do not change order of the three following imports. It would break stuff. + _ "momentum-core/docs" // This line is necessary for swagger to find your docs! + + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" ) +const momentumCoreAsciiArt = "███╗ ███╗ ██████╗ ███╗ ███╗███████╗███╗ ██╗████████╗██╗ ██╗███╗ ███╗ ██████╗ ██████╗ ██████╗ ███████╗\n████╗ ████║██╔═══██╗████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██║ ██║████╗ ████║ ██╔════╝██╔═══██╗██╔══██╗██╔════╝\n██╔████╔██║██║ ██║██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ██║ ██║██╔████╔██║ ██║ ██║ ██║██████╔╝█████╗ \n██║╚██╔╝██║██║ ██║██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██║██║╚██╔╝██║ ██║ ██║ ██║██╔══██╗██╔══╝ \n██║ ╚═╝ ██║╚██████╔╝██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ╚██████╔╝██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██║ ██║███████╗\n╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝" + // @title Momentum Core API // @version early-alpha // @description The momentum core api manages the core structure of momentum @@ -19,17 +29,22 @@ import ( // @BasePath / func main() { - fmt.Println("Starting momentum-core") - - config, err := config.InitializeMomentumCore() + _, err := config.InitializeMomentumCore() if err != nil { panic("failed initializing momentum. problem: " + err.Error()) } + fmt.Println(momentumCoreAsciiArt) + // gitClient := clients.NewGitClient(config) // kustomizeClient := clients.NewKustomizationValidationClient(config) - dispatcher := NewDispatcher(config) + server := gin.Default() + + files.RegisterFileRoutes(server) + artefacts.RegisterArtefactRoutes(server) + + server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) - dispatcher.Serve() + server.Run("localhost:8080") } diff --git a/momentum-core/templates/model.go b/momentum-core/templates/model.go new file mode 100644 index 0000000..e6e5d6a --- /dev/null +++ b/momentum-core/templates/model.go @@ -0,0 +1,32 @@ +package templates + +type TemplateStructureType int + +const ( + DIR TemplateStructureType = 1 << iota + FILE +) + +type CreateTemplateRequest struct { + Name string `json:"name"` + ParentId string `json:"parentId"` // must be an artefact of type APPLICATION or STAGE + TemplateStructure []*CreateTemplateStructureArtefact `json:"templateStructure"` +} + +type CreateTemplateStructureArtefact struct { + Name string `json:"name"` + Path string `json:"path"` // the path is to be given relative to the templates root + TemplateStructureType TemplateStructureType `json:"templateStructureType"` + ParentId string `json:"parentId"` // if not set, it will live inside the templates root +} + +type Template struct { + Id string `json:"id"` + Name string `json:"name"` + TemplateArtefact []*TemplateArtefact `json:"templateArtefacts"` +} + +type TemplateArtefact struct { + Id string `json:"id"` + Name string `json:"name"` +} diff --git a/momentum-core/templates/routes.go b/momentum-core/templates/routes.go new file mode 100644 index 0000000..dac8432 --- /dev/null +++ b/momentum-core/templates/routes.go @@ -0,0 +1 @@ +package templates diff --git a/momentum-core/templates/template-config-parser.go b/momentum-core/templates/template-config-parser.go new file mode 100644 index 0000000..dac8432 --- /dev/null +++ b/momentum-core/templates/template-config-parser.go @@ -0,0 +1 @@ +package templates diff --git a/momentum-core/tree/bfs.go b/momentum-core/tree/bfs.go deleted file mode 100644 index 28efa16..0000000 --- a/momentum-core/tree/bfs.go +++ /dev/null @@ -1,79 +0,0 @@ -package tree - -import ( - "strings" -) - -func ToMatchableSearchTerm(fullPath string) string { - - return strings.ReplaceAll(strings.ReplaceAll(fullPath, ".", "::"), "/", ".") -} - -func BreathFirstSearch(term string, startNode *Node) []*Node { - - if strings.Contains(term, HIERARCHY_SEPARATOR) { - - return bfsMultilevelPathMatch(SortedTermsPathList(term), startNode, make([]*Node, 0)) - } else { - - return bfsPathMatch(term, startNode, make([]*Node, 0)) - } -} - -/* -* Finds all nodes which paths match the search term. - */ -func bfsPathMatch(term string, n *Node, result []*Node) []*Node { - - if n == nil { - return result - } - - if !n.IsWrapping && n.Path == term { - result = append(result, n) - } - - if n.Children != nil || len(n.Children) > 0 { - - for _, child := range n.Children { - result = bfsPathMatch(term, child, result) - } - } - - return result -} - -/* -* Finds all nodes which pathes correspond to the given hierarchy relative to given start node. - */ -func bfsMultilevelPathMatch(sortedTerms []string, startNode *Node, result []*Node) []*Node { - - term := BuildSortedTermsPath(sortedTerms...) - - return bfsMultilevelPathMatchByTerm(term, startNode, result) -} - -func bfsMultilevelPathMatchByTerm(term string, n *Node, result []*Node) []*Node { - - // fmt.Println("Searching in", ToMatchableSearchTerm(n.FullPath()), "for", term) - - if strings.Contains(ToMatchableSearchTerm(n.FullPath()), term) { - - if len(result) > 1 { - for _, res := range result { - - if strings.LastIndex(ToMatchableSearchTerm(n.FullPath()), term) != strings.LastIndex(ToMatchableSearchTerm(res.FullPath()), term) { - result = append(result, n) - } - } - } else { - result = append(result, n) - } - } - - for _, child := range n.Children { - result = bfsMultilevelPathMatchByTerm(term, child, result) - } - - return result -} diff --git a/momentum-core/tree/bfs_test.go b/momentum-core/tree/bfs_test.go deleted file mode 100644 index b835e3a..0000000 --- a/momentum-core/tree/bfs_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package tree_test - -import ( - "momentum-core/tree" - "momentum-core/utils" - "strings" - "testing" -) - -const testdataDir = "./testdata" -const baseKustomization = "kustomization.yaml" - -func TestTreeBfs(t *testing.T) { - - testPath := utils.BuildPath(testdataDir, baseKustomization) - searchTerm := "kind" - - ftree, err := tree.Parse(testPath) - if err != nil { - t.Error(err, err.Error()) - } - - tree.Print(ftree) - - result := ftree.Search(searchTerm) - - if len(result) > 1 { - t.Error("Too many results. Expected only one.") - t.FailNow() - } - - if len(result) < 1 { - t.Error("Expected a result.") - t.FailNow() - } - - if result[0].Path != searchTerm || result[0].Value != "Kustomization" { - t.Error("Expected other result.") - } -} - -func TestMultiLevelPathBfs(t *testing.T) { - - testPath := "testdata" - searchTerm := "testdata.testdata_sub.kustomization::yaml.kind" - - ftree, err := tree.Parse(testPath) - if err != nil { - t.Error(err, err.Error()) - } - - tree.Print(ftree) - - result := ftree.Search(searchTerm) - - if len(result) > 1 { - t.Error("Too many results. Expected only one.") - t.FailNow() - } - - if len(result) < 1 { - t.Error("Expected a result.") - t.FailNow() - } - - if strings.Contains(result[0].FullPath(), searchTerm) || result[0].Value != "Kustomization" { - t.Error("Expected other result.") - } -} diff --git a/momentum-core/tree/momentum-tree.go b/momentum-core/tree/momentum-tree.go deleted file mode 100644 index be3465f..0000000 --- a/momentum-core/tree/momentum-tree.go +++ /dev/null @@ -1,242 +0,0 @@ -package tree - -import ( - "momentum-core/config" - "strings" -) - -func (n *Node) ChildById(id string, parent *Node) *Node { - - flattened := parent.FlatPreorder(make([]*Node, 0)) - for _, n := range flattened { - if n.Id == id { - return n - } - } - - return nil -} - -func (n *Node) Repo() *Node { - - return n.Root() -} - -func (n *Node) MomentumRoot() *Node { - - momentumRoot, found := n.Repo().FindFirst(config.MOMENTUM_ROOT) - if !found { - return nil - } - return momentumRoot -} - -func (n *Node) Apps() []*Node { - - root := n.MomentumRoot() - apps := make([]*Node, 0) - for _, app := range root.Directories() { - apps = append(apps, app) - } - return apps -} - -func (n *Node) AllStages() []*Node { - - apps := n.Apps() - stgs := make([]*Node, 0) - for _, app := range apps { - stgs = append(stgs, app.stages()...) - } - return stgs -} - -func (n *Node) stages() []*Node { - - nodesStages := make([]*Node, 0) - for _, possibleStage := range n.Directories() { - if possibleStage.Kind == Directory && !strings.HasPrefix(possibleStage.Path, META_PREFIX) { - childStages := possibleStage.stages() - nodesStages = append([]*Node{possibleStage}, childStages...) - } - } - - return nodesStages -} - -func (n *Node) IsStage() bool { - - stages := n.AllStages() - for _, stage := range stages { - if n.FullPath() == stage.FullPath() { - return true - } - } - return false -} - -func (n *Node) FindStage(path string) (bool, *Node) { - - stages := n.AllStages() - for _, stage := range stages { - if stage.FullPath() == path { - return true, stage - } - } - return false, nil -} - -func (n *Node) AllDeployments() []*Node { - - stgsAndApps := n.AllStages() - stgsAndApps = append(stgsAndApps, n.Apps()...) - depls := make([]*Node, 0) - - for _, stage := range stgsAndApps { - depls = append(depls, deployments(stage)...) - } - - return depls -} - -func (n *Node) Deployments() []*Node { - return deployments(n) -} - -func (n *Node) Deployment(deploymentId string) *Node { - - for _, deployment := range deployments(n) { - if deployment.Id == deploymentId { - return deployment - } - } - - return nil -} - -func (n *Node) DeploymentFolderFiles() []*Node { - - deploymentFolders := childrenWithName(n.Parent, "_deploy") - for _, depl := range deploymentFolders { - - if strings.EqualFold(n.PathWithoutEnding(), depl.PathWithoutEnding()) { - return depl.Files() - } - } - - return make([]*Node, 0) -} - -func (n *Node) AllValues() []*Node { - - depls := deployments(n) - stgs := n.stages() - apps := n.Apps() - - deplFiles := make([]*Node, 0) - for _, dep := range depls { - deplFiles = append(deplFiles, dep.Files()...) - deplFiles = append(deplFiles, dep.DeploymentFolderFiles()...) - } - - stgsFiles := make([]*Node, 0) - for _, stgFile := range stgs { - stgsFiles = append(stgsFiles, stgFile.Files()...) - } - - appFiles := make([]*Node, 0) - for _, appFile := range apps { - appFiles = append(appFiles, appFile.Files()...) - } - - files := make([]*Node, 0) - files = append(files, appFiles...) - files = append(files, stgsFiles...) - files = append(files, deplFiles...) - - values := make([]*Node, 0) - for _, f := range files { - values = append(values, f.Values()...) - } - - return values -} - -func (n *Node) Values() []*Node { - - if n == nil || n.Kind != File { - return make([]*Node, 0) - } - - return n.FlatPreorder(make([]*Node, 0)) -} - -func (n *Node) FlatPreorder(result []*Node) []*Node { - - if n == nil { - return result - } - - result = append(result, n) - - if len(n.Children) > 0 { - for _, child := range n.Children { - result = child.FlatPreorder(result) - } - } - - return result -} - -func deployments(stage *Node) []*Node { - - files := stage.Files() - deployFolders := stage.Search("_deploy") - if len(deployFolders) < 1 { - return make([]*Node, 0) - } - deployFolder := deployFolders[0] - deployFolders = deployFolder.Directories() - exclusions := []string{"kustomization.yml", "kustomization.yaml"} - - depls := make([]*Node, 0) - for _, f := range files { - - fileIsDeployment := true - if !strings.HasSuffix(f.NormalizedPath(), ".yml") && !strings.HasSuffix(f.NormalizedPath(), ".yaml") { - continue - } - - for _, excl := range exclusions { - - if strings.EqualFold(f.NormalizedPath(), excl) { - - fileIsDeployment = false - } - } - - if fileIsDeployment { - - for _, dir := range deployFolders { - - if strings.EqualFold(dir.Path, f.PathWithoutEnding()) { - depls = append(depls, f) - } - } - } - } - - return depls -} - -func childrenWithName(n *Node, name string) []*Node { - - matches := make([]*Node, 0) - for _, child := range n.Children { - if strings.EqualFold(child.Path, name) { - matches = append(matches, child) - } - } - - return matches -} diff --git a/momentum-core/tree/momentum-tree_test.go b/momentum-core/tree/momentum-tree_test.go deleted file mode 100644 index 8a42365..0000000 --- a/momentum-core/tree/momentum-tree_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package tree_test - -import ( - "fmt" - "momentum-core/tree" - "testing" -) - -const basePath = "testdata" - -func FILESYSTEMTEST_TestAllApps(t *testing.T) { - - n, err := tree.Parse(basePath) - if err != nil { - fmt.Println("unable to parse tree:", err.Error()) - t.FailNow() - } - - apps := n.Apps() - if len(apps) != 1 { - fmt.Println("expected exactly one app") - t.FailNow() - } - - if apps[0].Path != "testdata_sub" { - fmt.Println("expected app to be 'testdata_sub', but was", apps[0].Path) - t.FailNow() - } -} - -func FILESYSTEMTEST_TestAllStages(t *testing.T) { - - n, err := tree.Parse(basePath) - if err != nil { - fmt.Println("unable to parse tree:", err.Error()) - t.FailNow() - } - - stages := n.AllStages() - if len(stages) != 3 { - fmt.Println("expected exactly three stages") - t.FailNow() - } - - expectOneToBe(stages, "bronze", t) - expectOneToBe(stages, "silver", t) - expectOneToBe(stages, "gold", t) -} - -func FILESYSTEMTEST_TestAllDeployments(t *testing.T) { - - n, err := tree.Parse(basePath) - if err != nil { - fmt.Println("unable to parse tree:", err.Error()) - t.FailNow() - } - - deployments := n.AllDeployments() - if len(deployments) != 2 { - fmt.Println("expected exactly two deployments but were", len(deployments)) - t.FailNow() - } - - expectOneToBe(deployments, "deployment2.yaml", t) - expectOneToBe(deployments, "deployment3.yaml", t) -} - -func expectOneToBe(n []*tree.Node, expected string, t *testing.T) { - - for _, e := range n { - - fmt.Println("checking if", e.NormalizedPath(), "matches expectation", expected) - if e.NormalizedPath() == expected { - return - } - } - - fmt.Println("expected", expected, "but could not find in", n) - t.FailNow() -} diff --git a/momentum-core/tree/parser.go b/momentum-core/tree/parser.go deleted file mode 100644 index 3387df2..0000000 --- a/momentum-core/tree/parser.go +++ /dev/null @@ -1,131 +0,0 @@ -package tree - -import ( - "errors" - "fmt" - "momentum-core/utils" - "momentum-core/yaml" - "os" - "strings" -) - -func Parse(path string) (*Node, error) { - - return ParseWithExclusions(path, []string{".git"}) -} - -func ParseWithExclusions(path string, excludes []string) (*Node, error) { - - dir, err := os.Open(path) - if err != nil { - fmt.Println(err.Error()) - return nil, err - } - - stat, err := dir.Stat() - if err != nil { - fmt.Println(err.Error()) - return nil, err - } - - if !stat.IsDir() { - rootFile, err := parseFile(path) - if err != nil { - return nil, err - } - rootFile.Path = path // overwrite root with absolute path - return rootFile, nil - } - - rootDir, err := parseDir(path, excludes) - if err != nil { - return nil, err - } - rootDir.Path = path // overwrite root with absolute path - return rootDir, nil -} - -func parseDir(path string, excludes []string) (*Node, error) { - - dir, err := os.Open(path) - if err != nil { - fmt.Println(err.Error()) - return nil, err - } - - stat, err := dir.Stat() - if err != nil { - fmt.Println(err.Error()) - return nil, err - } - - if !stat.IsDir() { - e := errors.New("path must be directory") - fmt.Println(e.Error()) - return nil, e - } - - entries, err := dir.ReadDir(-1) - if err != nil { - fmt.Println(err.Error()) - return nil, err - } - - dirNode := NewNode(Directory, utils.LastPartOfPath(path), "", nil, nil, nil) - - for _, entry := range entries { - - if contains(excludes, entry.Name()) { - continue - } - - entryPath := utils.BuildPath(dir.Name(), entry.Name()) - if entry.IsDir() { - parsed, err := parseDir(entryPath, excludes) - if err != nil { - return nil, err - } - dirNode.AddChild(parsed) - } else { - - if strings.HasSuffix(entryPath, ".yml") || strings.HasSuffix(entryPath, ".yaml") { - fileNode, err := parseFile(entryPath) - if err != nil { - return nil, err - } - if fileNode != nil { - dirNode.AddChild(fileNode) - } - } - } - } - - return dirNode, nil -} - -// fileNode == nil indicates empty file. -func parseFile(path string) (*Node, error) { - - if strings.HasSuffix(path, ".yml") || strings.HasSuffix(path, ".yaml") { - if utils.FileEmpty(path) { - return nil, nil - } - parseTree := yaml.DecodeToTree(path) - mappedTree, err := MomentumTreeFromYaml(parseTree, path) - if err != nil { - return nil, err - } - return mappedTree, nil - } - return nil, errors.New("unsupported file type") -} - -func contains(col []string, s string) bool { - - for _, c := range col { - if s == c { - return true - } - } - return false -} diff --git a/momentum-core/tree/parser_test.go b/momentum-core/tree/parser_test.go deleted file mode 100644 index 3fabeea..0000000 --- a/momentum-core/tree/parser_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package tree_test - -import ( - "fmt" - "momentum-core/tree" - "momentum-core/utils" - "os" - "testing" -) - -func TestNewTree(t *testing.T) { - - path, err := os.Getwd() - path = utils.BuildPath(path, "testdata") - if err != nil { - t.Errorf(err.Error()) - } - - n, err := tree.Parse(path) - if err != nil { - t.Errorf(err.Error()) - } - - tree.Print(n) -} - -func TestParseFile(t *testing.T) { - - currentDir, err := os.Getwd() - if err != nil { - fmt.Println(err.Error()) - t.Fail() - } - - testfile := utils.BuildPath(currentDir, "testdata", "kustomization.yaml") - - parsed, err := tree.Parse(testfile) - if err != nil { - fmt.Println(err.Error()) - t.Fail() - } - - tree.Print(parsed) - - if len(parsed.Children) != 1 { - fmt.Println("expected root to have exactly 1 child") - t.FailNow() - } - - if parsed.Path != testfile { - fmt.Println("expected root to have exactly path", testfile) - t.FailNow() - } - - if parsed.Children[0].Kind != tree.Mapping || !parsed.Children[0].IsWrapping { - fmt.Println("expected root to have kind mapping and be wrapping") - t.FailNow() - } - - if len(parsed.Children[0].Children) != 4 { - fmt.Println("expected root mapping to have exactly four children") - t.FailNow() - } - - parsed = parsed.Children[0] - - if parsed.Children[0].Kind != tree.Property || parsed.Children[1].Kind != tree.Property { - fmt.Println("expected child one and two to be of kind property") - t.FailNow() - } - - if parsed.Children[0].Path != "apiVersion" || parsed.Children[1].Path != "kind" { - fmt.Println("paths didn't match expectations") - t.FailNow() - } - - if parsed.Children[0].Value != "kustomize.config.k8s.io/v1beta1" || parsed.Children[1].Value != "Kustomization" { - fmt.Println("values didn't match expectations") - t.FailNow() - } - - if parsed.Children[2].Kind != tree.Sequence { - fmt.Println("expected third child to be of kind sequence") - t.FailNow() - } - - if parsed.Children[2].Path != "resources" { - fmt.Println("expected third child to have path resources") - t.FailNow() - } - - if len(parsed.Children[2].Children) != 1 { - fmt.Println("expected third child to have exactly one child") - t.FailNow() - } - - if parsed.Children[2].Children[0].Kind != tree.Value { - fmt.Println("expected first child of third child to have kind value") - t.FailNow() - } - - if parsed.Children[2].Children[0].Value != "./mywebserver" { - fmt.Println("value didn't match expectation") - t.FailNow() - } - - if parsed.Children[2].Children[0].Value != "./mywebserver" { - fmt.Println("value didn't match expectation") - t.FailNow() - } -} diff --git a/momentum-core/tree/testdata/kustomization.yaml b/momentum-core/tree/testdata/kustomization.yaml deleted file mode 100644 index 1a06f55..0000000 --- a/momentum-core/tree/testdata/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - - ./mywebserver -mappingResources: - - name: A mapped sequence - description: some description \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_base/kustomization.yaml b/momentum-core/tree/testdata/testdata_sub/_base/kustomization.yaml deleted file mode 100644 index c6eabb3..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_base/kustomization.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -commonLabels: - gitops.natron.io/application: "mywebserver" -resources: -- ns.yaml -- release.yaml -configMapGenerator: -- name: base-values - files: - - ../../_base/values.yaml - options: - disableNameSuffixHash: true -- name: hetzner-prod-1-values - files: - - values.yaml - options: - disableNameSuffixHash: true diff --git a/momentum-core/tree/testdata/testdata_sub/_base/ns.yaml b/momentum-core/tree/testdata/testdata_sub/_base/ns.yaml deleted file mode 100644 index 01e4139..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_base/ns.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: Namespace -metadata: - name: patch \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_base/release.yaml b/momentum-core/tree/testdata/testdata_sub/_base/release.yaml deleted file mode 100644 index 45926e5..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_base/release.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - name: mywebserver -spec: - interval: 10m - chart: - spec: - chart: nginx - sourceRef: - kind: HelmRepository - name: bitnami-charts - namespace: flux-public - install: - remediation: - remediateLastFailure: true - upgrade: - remediation: - remediateLastFailure: true - valuesFrom: - - kind: ConfigMap - name: base-values - - kind: ConfigMap - name: hetzner-prod-1-values - - kind: ConfigMap - name: deploy-values \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_base/values.yaml b/momentum-core/tree/testdata/testdata_sub/_base/values.yaml deleted file mode 100644 index 707ef07..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_base/values.yaml +++ /dev/null @@ -1,3 +0,0 @@ -ingress: - enabled: true - ingressClassName: "nginx" \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/kustomization.yaml b/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/kustomization.yaml deleted file mode 100644 index ca1b29d..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/kustomization.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -namespace: deployment3 -commonLabels: - gitops.natron.io/stage: "hetzner-prod-1" -resources: -- ../../_base/ -patchesStrategicMerge: -- release.yaml -configMapGenerator: -- name: deploy-values - files: - - values.yaml - options: - disableNameSuffixHash: true \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/release.yaml b/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/release.yaml deleted file mode 100644 index 171ea5a..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/release.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - name: mywebserver \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/values.yaml b/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/values.yaml deleted file mode 100644 index 0911ef2..0000000 --- a/momentum-core/tree/testdata/testdata_sub/_deploy/deployment3/values.yaml +++ /dev/null @@ -1,2 +0,0 @@ -ingress: - hostName: deployment3.natron.io \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/deployment2.yaml b/momentum-core/tree/testdata/testdata_sub/deployment2.yaml deleted file mode 100644 index bba6a25..0000000 --- a/momentum-core/tree/testdata/testdata_sub/deployment2.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 -kind: Kustomization -metadata: - name: deployment2 -spec: - interval: 5m0s - path: ./_deploy/deployment2/ - prune: true - sourceRef: - kind: GitRepository - name: natrium \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/deployment3.yaml b/momentum-core/tree/testdata/testdata_sub/deployment3.yaml deleted file mode 100644 index 446ce30..0000000 --- a/momentum-core/tree/testdata/testdata_sub/deployment3.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 -kind: Kustomization -metadata: - name: deployment3 -spec: - interval: 5m0s - path: ./_deploy/deployment3/ - prune: true - sourceRef: - kind: GitRepository - name: natrium \ No newline at end of file diff --git a/momentum-core/tree/testdata/testdata_sub/kustomization.yaml b/momentum-core/tree/testdata/testdata_sub/kustomization.yaml deleted file mode 100644 index 29d66d1..0000000 --- a/momentum-core/tree/testdata/testdata_sub/kustomization.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -resources: - # @natrium: deployments - - ./deployment2.yaml - # @natrium: stages - # - gold/ \ No newline at end of file diff --git a/momentum-core/tree/tree.go b/momentum-core/tree/tree.go deleted file mode 100644 index f58a2b3..0000000 --- a/momentum-core/tree/tree.go +++ /dev/null @@ -1,228 +0,0 @@ -package tree - -import ( - "errors" - "fmt" - "strings" - - "momentum-core/utils" - "momentum-core/yaml" -) - -type NodeKind int - -const ( - Directory NodeKind = 1 << iota - File - Property - Mapping - Sequence - Value -) - -const FILE_ENDING_SEPARATOR_REPLACEMENT = "::" - -type Node struct { - Id string - Kind NodeKind - // indicates wether the node is wrapping or not - // (a wrapping node has an empty path and must be ignored while searching) - IsWrapping bool - Path string - Value string // Value only set for Kind == Value - Parent *Node - Children []*Node - // only sub-trees of (Yaml-)File nodes have YamlNode. otherwise nil. - // facilitates writing to writable yaml tree. - YamlNode *yaml.Node -} - -func NewNode(kind NodeKind, path string, value string, parent *Node, children []*Node, yamlNode *yaml.Node) *Node { - - n := new(Node) - - n.Kind = kind - n.Path = strings.ReplaceAll(utils.LastPartOfPath(path), ".", FILE_ENDING_SEPARATOR_REPLACEMENT) - n.Value = value - n.Parent = parent - n.YamlNode = yamlNode - - if children == nil || len(children) < 1 { - n.Children = make([]*Node, 0) - } else { - n.Children = children - } - - if kind == Sequence || kind == Mapping { - // when setting nodes path, this must be changed - n.IsWrapping = true - } - - id, err := utils.GenerateId(n.FullPath()) - if err != nil { - fmt.Println("generating id failed:", err.Error()) - } - n.Id = id - - return n -} - -func (n *Node) Remove() { - - if n.Parent == nil || len(n.Parent.Children) < 1 { - return - } - - newChilds := make([]*Node, 0) - for _, child := range n.Parent.Children { - if child != n { - newChilds = append(newChilds, child) - } - } - n.Parent.Children = newChilds - - n.Parent.RemoveYamlChild(n.Path) - - n.Parent = nil -} - -func (n *Node) AddChild(child *Node) { - - if child == nil { - return - } - - if child.Parent != nil { - child.Remove() - } - - child.Parent = n - - n.Children = append(n.Children, child) -} - -func (n *Node) SetValue(v string) { - - n.Value = v - - if n.YamlNode != nil { - n.YamlNode.Value = v - } -} - -// Returns full path from root to this node. -func (n *Node) FullPath() string { - path := "" - current := n - if current == nil { - return path - } - for current.Parent != nil { - path = utils.BuildPath(current.Path, path) - current = current.Parent - } - path = utils.BuildPath(current.Path, path) - return strings.ReplaceAll(path, FILE_ENDING_SEPARATOR_REPLACEMENT, ".") -} - -// Returns path for use in filesystem interactions. -func (n *Node) NormalizedPath() string { - return strings.ReplaceAll(n.Path, FILE_ENDING_SEPARATOR_REPLACEMENT, ".") -} - -// If path has special ending '::[anything]' its cut otherwise just n.Path -func (n *Node) PathWithoutEnding() string { - return strings.Split(n.Path, FILE_ENDING_SEPARATOR_REPLACEMENT)[0] -} - -func (n *Node) Write(allowOverwrite bool) error { - - _, err := WriteNode(n, allowOverwrite) - if err != nil { - return err - } - return nil -} - -func (n *Node) IsRoot() bool { - return n.Parent == nil || n == n.Parent // if nodes parent is reference to itself its the parent. -} - -func (n *Node) Root() *Node { - - current := n - for !current.IsRoot() { - current = current.Parent - } - return current -} - -func (n *Node) Files() []*Node { - - if n == nil || n.Kind != Directory { - return make([]*Node, 0) - } - - files := make([]*Node, 0) - for _, child := range n.Children { - if child.Kind == File { - files = append(files, child) - } - } - return files -} - -func (n *Node) Directories() []*Node { - - if n == nil || n.Kind != Directory { - return make([]*Node, 0) - } - - directories := make([]*Node, 0) - for _, child := range n.Children { - if child.Kind == Directory { - directories = append(directories, child) - } - } - return directories -} - -func (n *Node) Search(term string) []*Node { - - return BreathFirstSearch(term, n) -} - -func (n *Node) FindFirst(term string) (*Node, bool) { - - results := n.Search(term) - if results == nil || len(results) < 1 { - return nil, false - } - return results[0], true -} - -func (n *Node) FileMapping() (*Node, error) { - - if n.Kind != File || n.YamlNode.Kind != yaml.DocumentNode { - return nil, errors.New("cannot read file mapping from non file node") - } - - for _, child := range n.Children { - - if child.Kind == Mapping && child.Path == "" && child.Value == "" { - return child, nil - } - } - - return nil, errors.New("file has no mapping node") -} - -func idMatch(expect string, n *Node) bool { - - id, err := utils.GenerateId(n.FullPath()) - if err != nil { - return false - } - - return id == expect -} diff --git a/momentum-core/tree/tree_test.go b/momentum-core/tree/tree_test.go deleted file mode 100644 index 13a7f71..0000000 --- a/momentum-core/tree/tree_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package tree_test - -import ( - "momentum-core/tree" - "testing" -) - -func FILESYSTEMTEST_TestTreeCreation(test *testing.T) { - - tDir := tree.NewNode(tree.Directory, "/testpath", "", nil, nil, nil) - tFile := tree.NewNode(tree.File, "testfile.yaml", "", tDir, nil, nil) - tMapping := tree.NewNode(tree.Mapping, "mapping", "", tFile, nil, nil) - tSequence := tree.NewNode(tree.Sequence, "sequence", "", tFile, nil, nil) - tProperty := tree.NewNode(tree.Property, "property", "", tMapping, nil, nil) - tValue := tree.NewNode(tree.Value, "", "value", tSequence, nil, nil) - - if tProperty.FullPath() != "testpath/testfile.yaml/mapping/property" { - test.FailNow() - } - - if tValue.FullPath() != "testpath/testfile.yaml/sequence" { - test.FailNow() - } -} diff --git a/momentum-core/tree/utils.go b/momentum-core/tree/utils.go deleted file mode 100644 index dec5ed2..0000000 --- a/momentum-core/tree/utils.go +++ /dev/null @@ -1,45 +0,0 @@ -package tree - -import "strings" - -const META_PREFIX = "_" -const HIERARCHY_SEPARATOR = "." - -func BuildSortedTermsPath(parts ...string) string { - - p := "" - for _, part := range parts { - p += part + HIERARCHY_SEPARATOR - } - p, _ = strings.CutSuffix(p, HIERARCHY_SEPARATOR) - - return p -} - -func SortedTermsPathList(term string) []string { - return strings.Split(term, HIERARCHY_SEPARATOR) -} - -/* -* Builds a match tree from a given term which separates nodes with the HIERARCHY_SEPARATOR - */ -func BuildMatchTree(term string) *Node { - - parts := strings.Split(term, HIERARCHY_SEPARATOR) - - root := new(Node) - root.Path = parts[0] - - current := root - if len(parts) > 1 { - for i := 1; i < len(parts); i++ { - - newNode := new(Node) - newNode.Path = parts[i] - current.Children = append(current.Children, newNode) - current = newNode - } - } - - return root -} diff --git a/momentum-core/tree/writer.go b/momentum-core/tree/writer.go deleted file mode 100644 index 7f4bed9..0000000 --- a/momentum-core/tree/writer.go +++ /dev/null @@ -1,102 +0,0 @@ -package tree - -import ( - "errors" - "fmt" - "momentum-core/utils" - "momentum-core/yaml" - "strings" -) - -/* -* BE AWARE: Write will overwrite everything without asking if allowOverwrite=true is set. -* You have to check first, that you don't overwrite stuff -* which shall not be overwritten. -* -* If the given node is not of Kind File or Directory, it will -* look for any parent which matches the criteria and write the parent - */ -func WriteNode(n *Node, allowOverwrite bool) (string, error) { - - writableNode, err := writableParent(n) - if err != nil { - return "", err - } - - if writableNode.Kind == Directory { - return writeDir(writableNode, allowOverwrite) - } else if writableNode.Kind == File { - return writeFile(writableNode, allowOverwrite) - } - - return "", errors.New("unknown writable node kind") -} - -func writeDir(n *Node, allowOverwrite bool) (string, error) { - - if n.Kind != Directory { - return "", errors.New("kind directory expected") - } - - err := utils.DirCreate(n.FullPath()) - if err != nil { - return "", err - } - - for _, child := range n.Children { - if isWritable(child) { - WriteNode(child, allowOverwrite) - } - } - - return n.Path, nil -} - -func writeFile(n *Node, allowOverwrite bool) (string, error) { - - defer func() { - if r := recover(); r != nil { - fmt.Println("failed writing file:", r) - } - }() - - if n.Kind != File { - return "", errors.New("kind file expected") - } - - if n.YamlNode == nil { - return "", errors.New("file has no yaml node. cannot write file") - } - - if strings.HasSuffix(n.NormalizedPath(), ".yml") || strings.HasSuffix(n.NormalizedPath(), ".yaml") { - _, err := yaml.EncodeToFile(n.YamlNode, n.FullPath(), allowOverwrite) - if err != nil { - return "", err - } - } else { - return "", errors.New("only files which end with .yml or .yaml can be written") - } - - return n.Path, nil -} - -func writableParent(n *Node) (*Node, error) { - - if n == nil { - return nil, errors.New("node supplied was nil") - } - - if isWritable(n) { - return n, nil - } - - if n.Parent == nil { - return nil, errors.New("no writable node inside tree") - } - - return writableParent(n.Parent) -} - -func isWritable(n *Node) bool { - return n.Kind == Directory || n.Kind == File -} diff --git a/momentum-core/tree/yaml-node-factory.go b/momentum-core/tree/yaml-node-factory.go deleted file mode 100644 index 6521830..0000000 --- a/momentum-core/tree/yaml-node-factory.go +++ /dev/null @@ -1,189 +0,0 @@ -package tree - -import ( - "errors" - "momentum-core/utils" - "momentum-core/yaml" -) - -// copied from yaml, because module private there -const ( - nullTag = "!!null" - boolTag = "!!bool" - StrTag = "!!str" - intTag = "!!int" - floatTag = "!!float" - timestampTag = "!!timestamp" - seqTag = "!!seq" - mapTag = "!!map" - binaryTag = "!!binary" - mergeTag = "!!merge" -) - -func (n *Node) RemoveYamlChildren() error { - - errs := make([]error, 0) - for _, chld := range n.Children { - errs = append(errs, chld.RemoveYamlChild(chld.Path)) - } - - return errors.Join(errs...) -} - -func (n *Node) RemoveYamlChild(path string) error { - - updated := make([]*Node, 0) - for _, child := range n.Children { - if child.Path != path { - updated = append(updated, child) - } - - updatedYaml := make([]*yaml.Node, 0) - if child.Path == path { - if child.Parent != nil && child.Parent.YamlNode != nil { - if child.Parent.YamlNode != nil { - for _, yamlChild := range child.Parent.YamlNode.Content { - if yamlChild.Value != utils.LastPartOfPath(path) { - updatedYaml = append(updatedYaml, yamlChild) - } - } - child.Parent.YamlNode.Content = updatedYaml - } - } - } - - return nil - } - - n.Children = updated - - return nil -} - -func (n *Node) AddYamlSequence(key string, values []string, style yaml.Style) error { - - if len(values) < 1 { - return errors.New("sequence must have at least one value") - } - - var err error = nil - var anchor *Node = n - if n.Kind == File { - anchor, err = n.FileMapping() - if err != nil { - return errors.New("failed retrieving file mapping of file node") - } - } - - yamlSequenceName := CreateScalarNode(key, StrTag, 0) - yamlSequenceNode := CreateSequenceNode(style) - anchor.YamlNode.Content = append(anchor.YamlNode.Content, yamlSequenceName, yamlSequenceNode) - - sequenceNode := NewNode(Sequence, key, "", nil, nil, yamlSequenceNode) - anchor.AddChild(sequenceNode) - - for _, val := range values { - err := sequenceNode.AddYamlValue(val, 0) - if err != nil { - return err - } - } - - return nil -} - -func (n *Node) AddYamlMapping(key string, style yaml.Style) (*Node, error) { - - var err error = nil - var anchor *Node = n - if n.Kind == File { - anchor, err = n.FileMapping() - if err != nil { - return nil, err - } - } - - yamlMappingName := CreateScalarNode(key, StrTag, 0) - yamlMappingNode := CreateMappingNode(key, style) - - anchor.YamlNode.Content = append(anchor.YamlNode.Content, yamlMappingName, yamlMappingNode) - - mappingNode := NewNode(Mapping, key, "", nil, nil, yamlMappingNode) - anchor.AddChild(mappingNode) - - return mappingNode, nil -} - -func (n *Node) AddYamlProperty(key string, value string, valueTag string, style yaml.Style) error { - - if n.Kind != Mapping || n.YamlNode.Kind != yaml.MappingNode { - return errors.New("properties can only be added to mapping nodes") - } - - yamlKeyNode, yamlValueNode := CreatePropertyNodes(key, value, valueTag, style) - - mappingNode := NewNode(Property, key, value, n, nil, yamlValueNode) - - n.YamlNode.Content = append(n.YamlNode.Content, yamlKeyNode, yamlValueNode) - n.AddChild(mappingNode) - - return nil -} - -func (n *Node) AddYamlValue(value string, style yaml.Style) error { - - if n.Kind != Sequence || n.YamlNode.Kind != yaml.SequenceNode { - return errors.New("can only add sequence value to node of type sequence") - } - - sequenceValue := CreateScalarNode(value, StrTag, style) - n.YamlNode.Content = append(n.YamlNode.Content, sequenceValue) - momentumNode := NewNode(Value, "", value, n, nil, sequenceValue) - n.AddChild(momentumNode) - - return nil -} - -func CreatePropertyNodes(key string, value string, valueTag string, style yaml.Style) (*yaml.Node, *yaml.Node) { - - keyNode := CreateScalarNode(key, StrTag, style) - valueNode := CreateScalarNode(value, valueTag, style) - - return keyNode, valueNode -} - -func CreateSequenceNode(style yaml.Style) *yaml.Node { - - n := new(yaml.Node) - - n.Kind = yaml.SequenceNode - n.Tag = seqTag - n.Value = "" - n.Style = style - - return n -} - -func CreateMappingNode(key string, style yaml.Style) *yaml.Node { - - n := new(yaml.Node) - - n.Kind = yaml.MappingNode - n.Tag = mapTag - n.Value = "" - n.Style = style - - return n -} - -func CreateScalarNode(value string, tag string, style yaml.Style) *yaml.Node { - - n := new(yaml.Node) - - n.Kind = yaml.ScalarNode - n.Tag = tag - n.Value = value - n.Style = style - - return n -} diff --git a/momentum-core/tree/yaml-node-factory_test.go b/momentum-core/tree/yaml-node-factory_test.go deleted file mode 100644 index 3fd4ced..0000000 --- a/momentum-core/tree/yaml-node-factory_test.go +++ /dev/null @@ -1,274 +0,0 @@ -package tree_test - -import ( - "fmt" - "momentum-core/tree" - "momentum-core/utils" - "os" - "strings" - "testing" -) - -func FILESYSTEMTEST_TestAddSequenceValue(t *testing.T) { - - wdir, err := os.Getwd() - if err != nil { - fmt.Println("cannot read workdir") - t.FailNow() - } - - TEST_FILE_PATH := utils.BuildPath(wdir, "testdata/node_manipulations.yaml") - - success := writeTestFile(TEST_FILE_PATH) - if !success { - fmt.Println("unable to instantiate testfile") - t.FailNow() - } - - parsed, err := tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse testfile") - t.FailNow() - } - - utils.FileDelete(TEST_FILE_PATH) - - resourcesSequence, found := parsed.FindFirst("resources") - if !found { - fmt.Println("unable to find resources sequence in testfile") - t.FailNow() - } - - tree.Print(parsed) - - resourcesSequence.Children[0].SetValue("Ciao") - err = resourcesSequence.AddYamlValue("World", 0) - if err != nil { - fmt.Println(err.Error()) - t.FailNow() - } - - tree.Print(resourcesSequence) - - err = resourcesSequence.Write(true) - if err != nil { - fmt.Println("writing new resources failed:", err.Error()) - t.FailNow() - } - - afterWriteTree, err := tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("parsing tree failed after adding resources") - t.FailNow() - } - - resourcesSequence, found = afterWriteTree.FindFirst("resources") - if !found { - fmt.Println("unable to find resources sequence in testfile after update") - t.FailNow() - } - - tree.Print(afterWriteTree) - - if len(resourcesSequence.Children) != 2 { - fmt.Println("expected two children in resources") - t.FailNow() - } - - if resourcesSequence.Children[0].Value != "Ciao" { - fmt.Println("expected first child to be 'Hello'") - t.FailNow() - } - - if resourcesSequence.Children[1].Value != "World" { - fmt.Println("expected first child to be 'World'") - t.FailNow() - } - - cleanup(t, TEST_FILE_PATH) -} - -func FILESYSTEMTEST_TestAddSequence(t *testing.T) { - - wdir, err := os.Getwd() - if err != nil { - fmt.Println("cannot read workdir") - t.FailNow() - } - - TEST_FILE_PATH := utils.BuildPath(wdir, "testdata/node_manipulations.yaml") - - success := writeTestFile(TEST_FILE_PATH) - if !success { - fmt.Println("unable to instantiate testfile") - t.FailNow() - } - defer utils.FileDelete(TEST_FILE_PATH) - - parsed, err := tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse testfile") - t.FailNow() - } - - utils.FileDelete(TEST_FILE_PATH) - - err = parsed.AddYamlSequence("sequence", []string{"value"}, 0) - if err != nil { - fmt.Println("failed to write sequence:", err.Error()) - t.FailNow() - } - - tree.Print(parsed) - - err = parsed.Write(true) - if err != nil { - fmt.Println("failed to write manipulated testfile:", err.Error()) - t.FailNow() - } - - parsed, err = tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse manipulated testfile", err.Error()) - t.FailNow() - } - - _, found := parsed.FindFirst("sequence") - if !found { - fmt.Println("unable to find new sequence in testfile after update") - t.FailNow() - } - - tree.Print(parsed) -} - -func FILESYSTEMTEST_TestAddMapping(t *testing.T) { - - wdir, err := os.Getwd() - if err != nil { - fmt.Println("cannot read workdir") - t.FailNow() - } - - TEST_FILE_PATH := utils.BuildPath(wdir, "testdata/node_manipulations.yaml") - - success := writeTestFile(TEST_FILE_PATH) - if !success { - fmt.Println("unable to instantiate testfile") - t.FailNow() - } - defer utils.FileDelete(TEST_FILE_PATH) - - parsed, err := tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse testfile") - t.FailNow() - } - - fileMapping, err := parsed.FileMapping() - if err != nil { - fmt.Println("unable to find file mapping", err.Error()) - t.FailNow() - } - - fmt.Println("FILEMAP:", fileMapping) - - mappingNode, err := fileMapping.AddYamlMapping("mapping-key", 0) - if err != nil { - fmt.Println("creating mapping node failed:", err.Error()) - t.FailNow() - } - - err = mappingNode.AddYamlProperty("subprob", "subpropvalue", tree.StrTag, 0) - if err != nil { - fmt.Println("creating mappings property node failed:", err.Error()) - t.FailNow() - } - - tree.Print(parsed) - - err = parsed.Write(true) - if err != nil { - fmt.Println("failed to write manipulated testfile:", err.Error()) - t.FailNow() - } - - parsed, err = tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse manipulated testfile", err.Error()) - t.FailNow() - } - - tree.Print(parsed) - - _, found := parsed.FindFirst("mapping-key") - if !found { - fmt.Println("mapping was not added as expected") - t.FailNow() - } -} - -func FILESYSTEMTEST_TestAddProperty(t *testing.T) { - - wdir, err := os.Getwd() - if err != nil { - fmt.Println("cannot read workdir") - t.FailNow() - } - - TEST_FILE_PATH := utils.BuildPath(wdir, "testdata/node_manipulations.yaml") - - success := writeTestFile(TEST_FILE_PATH) - if !success { - fmt.Println("unable to instantiate testfile") - t.FailNow() - } - defer utils.FileDelete(TEST_FILE_PATH) - - parsed, err := tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse testfile") - t.FailNow() - } - - fileMapping, err := parsed.FileMapping() - if err != nil { - fmt.Println("unable to find file mapping", err.Error()) - t.FailNow() - } - - fileMapping.AddYamlProperty("property-key", "property-value", tree.StrTag, 0) - - err = parsed.Write(true) - if err != nil { - fmt.Println("failed to write manipulated testfile:", err.Error()) - t.FailNow() - } - - parsed, err = tree.Parse(TEST_FILE_PATH) - if err != nil { - fmt.Println("failed to parse manipulated testfile", err.Error()) - t.FailNow() - } - - tree.Print(parsed) - - _, found := parsed.FindFirst("property-key") - if !found { - fmt.Println("mapping was not added as expected") - t.FailNow() - } -} - -func writeTestFile(p string) bool { - return utils.FileWriteLines(p, strings.Split("kind: Test\nresources:\n- \"Hello\"\nprop: \"value\"", "\n")) -} - -func cleanup(t *testing.T, p string) { - err := os.Remove(p) - - if err != nil { - fmt.Println("unable to clean up after test") - t.FailNow() - } -} diff --git a/momentum-core/yaml/tree.go b/momentum-core/yaml/tree.go new file mode 100644 index 0000000..d17ce1d --- /dev/null +++ b/momentum-core/yaml/tree.go @@ -0,0 +1,162 @@ +package yaml + +import ( + "errors" + "fmt" + "momentum-core/utils" + "strings" +) + +type NodeKind int + +const ( + Directory NodeKind = 1 << iota + File + Property + Mapping + Sequence + Value +) + +const FILE_ENDING_SEPARATOR_REPLACEMENT = "::" + +type ViewNode struct { + Id string + Kind NodeKind + // indicates wether the node is wrapping or not + // (a wrapping node has an empty path and must be ignored while searching) + IsWrapping bool + Path string + Value string // Value only set for Kind == Value + Parent *ViewNode + Children []*ViewNode + // only sub-trees of (Yaml-)File nodes have YamlNode. otherwise nil. + // facilitates writing to writable yaml tree. + YamlNode *Node +} + +func NewNode(kind NodeKind, path string, value string, parent *ViewNode, children []*ViewNode, yamlNode *Node) *ViewNode { + + n := new(ViewNode) + + n.Kind = kind + n.Path = strings.ReplaceAll(utils.LastPartOfPath(path), ".", FILE_ENDING_SEPARATOR_REPLACEMENT) + n.Value = value + n.Parent = parent + n.YamlNode = yamlNode + + if children == nil || len(children) < 1 { + n.Children = make([]*ViewNode, 0) + } else { + n.Children = children + } + + if kind == Sequence || kind == Mapping { + // when setting nodes path, this must be changed + n.IsWrapping = true + } + + id, err := utils.GenerateId(n.FullPath()) + if err != nil { + fmt.Println("generating id failed:", err.Error()) + } + n.Id = id + + return n +} + +// fileNode == nil indicates empty file. +func ParseFile(path string) (*ViewNode, error) { + + if strings.HasSuffix(path, ".yml") || strings.HasSuffix(path, ".yaml") { + if utils.FileEmpty(path) { + return nil, nil + } + parseTree := DecodeToTree(path) + mappedTree, err := MomentumTreeFromYaml(parseTree, path) + if err != nil { + return nil, err + } + return mappedTree, nil + } + return nil, errors.New("unsupported file type") +} + +// Returns full path from root to this node. +func (n *ViewNode) FullPath() string { + path := "" + current := n + if current == nil { + return path + } + for current.Parent != nil { + path = utils.BuildPath(current.Path, path) + current = current.Parent + } + path = utils.BuildPath(current.Path, path) + return strings.ReplaceAll(path, FILE_ENDING_SEPARATOR_REPLACEMENT, ".") +} + +func (n *ViewNode) Remove() { + + if n.Parent == nil || len(n.Parent.Children) < 1 { + return + } + + newChilds := make([]*ViewNode, 0) + for _, child := range n.Parent.Children { + if child != n { + newChilds = append(newChilds, child) + } + } + n.Parent.Children = newChilds + + n.Parent.RemoveYamlChild(n.Path) + + n.Parent = nil +} + +func (n *ViewNode) AddChild(child *ViewNode) { + + if child == nil { + return + } + + if child.Parent != nil { + child.Remove() + } + + child.Parent = n + + n.Children = append(n.Children, child) +} + +func (n *ViewNode) RemoveYamlChild(path string) error { + + updated := make([]*ViewNode, 0) + for _, child := range n.Children { + if child.Path != path { + updated = append(updated, child) + } + + updatedYaml := make([]*Node, 0) + if child.Path == path { + if child.Parent != nil && child.Parent.YamlNode != nil { + if child.Parent.YamlNode != nil { + for _, yamlChild := range child.Parent.YamlNode.Content { + if yamlChild.Value != utils.LastPartOfPath(path) { + updatedYaml = append(updatedYaml, yamlChild) + } + } + child.Parent.YamlNode.Content = updatedYaml + } + } + } + + return nil + } + + n.Children = updated + + return nil +} diff --git a/momentum-core/tree/printer.go b/momentum-core/yaml/view-node-printer.go similarity index 70% rename from momentum-core/tree/printer.go rename to momentum-core/yaml/view-node-printer.go index e2ea5c6..bcd704b 100644 --- a/momentum-core/tree/printer.go +++ b/momentum-core/yaml/view-node-printer.go @@ -1,35 +1,15 @@ -package tree +package yaml import ( "fmt" ) -func Print(n *Node) { +func Print(n *ViewNode) { print(n, 0) } -func ToHumanReadableKind(k NodeKind) string { - - switch k { - case Directory: - return "Directory" - case File: - return "File" - case Mapping: - return "Mapping" - case Sequence: - return "Sequence" - case Property: - return "Property" - case Value: - return "Value" - default: - return "UNKNOWN" - } -} - -func print(n *Node, level int) { +func print(n *ViewNode, level int) { if n == nil { return diff --git a/momentum-core/tree/yaml_mapper.go b/momentum-core/yaml/yaml_mapper.go similarity index 74% rename from momentum-core/tree/yaml_mapper.go rename to momentum-core/yaml/yaml_mapper.go index 1d50737..cf6305c 100644 --- a/momentum-core/tree/yaml_mapper.go +++ b/momentum-core/yaml/yaml_mapper.go @@ -1,22 +1,21 @@ -package tree +package yaml import ( "errors" "momentum-core/utils" - "momentum-core/yaml" "strings" ) const EMPTY_SCALAR = "" -func MomentumTreeFromYaml(n *yaml.Node, filePath string) (*Node, error) { +func MomentumTreeFromYaml(n *Node, filePath string) (*ViewNode, error) { if n == nil { - return nil, errors.New("yaml node is nil") + return nil, errors.New("yaml ViewNode is nil") } - if n.Kind != yaml.DocumentNode { + if n.Kind != DocumentNode { return nil, errors.New("only yaml nodes of kind documentnode can be loaded into the tree") } @@ -35,16 +34,16 @@ func MomentumTreeFromYaml(n *yaml.Node, filePath string) (*Node, error) { return fileNode, nil } -func momentumFileTree(yamlNode *yaml.Node, parent *Node) (*Node, error) { +func momentumFileTree(yamlNode *Node, parent *ViewNode) (*ViewNode, error) { if yamlNode == nil { - return nil, errors.New("yaml node is nil") + return nil, errors.New("yaml ViewNode is nil") } if parent == nil { - return nil, errors.New("parent node is nil") + return nil, errors.New("parent ViewNode is nil") } mapped, parent, doAddChild, err := mapYamlNode(yamlNode, parent) @@ -70,7 +69,7 @@ func momentumFileTree(yamlNode *yaml.Node, parent *Node) (*Node, error) { return parent, nil } -func mapYamlNode(n *yaml.Node, parent *Node) (*Node, *Node, bool, error) { +func mapYamlNode(n *Node, parent *ViewNode) (*ViewNode, *ViewNode, bool, error) { if n == nil { @@ -84,7 +83,7 @@ func mapYamlNode(n *yaml.Node, parent *Node) (*Node, *Node, bool, error) { } doAddChild := true - var momentumNode *Node + var momentumNode *ViewNode switch momentumKind { @@ -120,7 +119,7 @@ func mapYamlNode(n *yaml.Node, parent *Node) (*Node, *Node, bool, error) { return momentumNode, parent, doAddChild, nil } -func YamlTree(n *Node) (*yaml.Node, error) { +func YamlTree(n *ViewNode) (*Node, error) { if n.Kind == Directory { @@ -135,11 +134,11 @@ func YamlTree(n *Node) (*yaml.Node, error) { return n.YamlNode, nil } -func handleValueEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { +func handleValueEntries(n *Node, parent *ViewNode) (*ViewNode, bool, error) { - if n.Kind != yaml.ScalarNode { + if n.Kind != ScalarNode { - return nil, false, errors.New("expecting scalar node") + return nil, false, errors.New("expecting scalar ViewNode") } if parent.Kind == Sequence { @@ -158,14 +157,14 @@ func handleValueEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { return parent.Children[lastChildIndex], false, nil } - return nil, false, errors.New("unallowed combination of kind value and node parents kind (parent kind: " + ToHumanReadableKind(parent.Kind) + ")") + return nil, false, errors.New("unallowed combination of kind value and ViewNode parents kind (parent kind: " + ToHumanReadableKind(parent.Kind) + ")") } -func handlePropertyEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { +func handlePropertyEntries(n *Node, parent *ViewNode) (*ViewNode, bool, error) { - if n.Kind != yaml.ScalarNode { + if n.Kind != ScalarNode { - return nil, false, errors.New("expecting scalar node") + return nil, false, errors.New("expecting scalar ViewNode") } return NewNode(Property, n.Value, EMPTY_SCALAR, nil, nil, nil), true, nil @@ -175,11 +174,11 @@ func handlePropertyEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { * Most of the Sequence and Mapping entries are relevant to the parser, but not to us. * This function handles edge cases for sequences. */ -func handleSequenceEntries(n *yaml.Node, parent *Node) (*Node, error) { +func handleSequenceEntries(n *Node, parent *ViewNode) (*ViewNode, error) { - if n.Kind != yaml.SequenceNode { + if n.Kind != SequenceNode { - return nil, errors.New("expecting sequence node") + return nil, errors.New("expecting sequence ViewNode") } lastChildIndex := len(parent.Children) - 1 @@ -204,11 +203,11 @@ func handleSequenceEntries(n *yaml.Node, parent *Node) (*Node, error) { * Most of the Sequence and Mapping entries are relevant to the parser, but not to us. * This function handles edge cases for maps. */ -func handleMapEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { +func handleMapEntries(n *Node, parent *ViewNode) (*ViewNode, bool, error) { - if n.Kind != yaml.MappingNode { + if n.Kind != MappingNode { - return nil, false, errors.New("expecting mapping node") + return nil, false, errors.New("expecting mapping ViewNode") } lastChildIndex := len(parent.Children) - 1 @@ -241,7 +240,7 @@ func handleMapEntries(n *yaml.Node, parent *Node) (*Node, bool, error) { return newNode, true, nil } -func yamlNodeIsMapValue(parent *Node) bool { +func yamlNodeIsMapValue(parent *ViewNode) bool { if parent == nil || parent.Kind != Mapping { return false @@ -256,23 +255,23 @@ func yamlNodeIsMapValue(parent *Node) bool { return parent.Children[lastChildIndex].Kind == Property && parent.Children[lastChildIndex].Value == EMPTY_SCALAR } -func momentumKind(n *yaml.Node, parent *Node) (NodeKind, error) { +func momentumKind(n *Node, parent *ViewNode) (NodeKind, error) { switch n.Kind { - case yaml.DocumentNode: + case DocumentNode: return File, nil - case yaml.MappingNode: + case MappingNode: return Mapping, nil - case yaml.SequenceNode: + case SequenceNode: return Sequence, nil - case yaml.AliasNode: + case AliasNode: return -1, errors.New("kind alias currently not supported by momentum") - case yaml.ScalarNode: + case ScalarNode: if yamlNodeIsMapValue(parent) { return Value, nil @@ -286,3 +285,23 @@ func momentumKind(n *yaml.Node, parent *Node) (NodeKind, error) { return -1, errors.New("unknown yaml kind") } } + +func ToHumanReadableKind(k NodeKind) string { + + switch k { + case Directory: + return "Directory" + case File: + return "File" + case Mapping: + return "Mapping" + case Sequence: + return "Sequence" + case Property: + return "Property" + case Value: + return "Value" + default: + return "UNKNOWN" + } +} From 3eebb949c3b5046f01f06e1ad17b9c97cc9f9255 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 08:23:26 +0200 Subject: [PATCH 04/10] feat: get overwrites API --- momentum-core/artefacts/artefact-tree.go | 60 +++++++++ momentum-core/artefacts/override.go | 31 +++++ momentum-core/artefacts/routes.go | 5 +- momentum-core/backtracking/backtrack.go | 5 +- .../backtracking/property-backtracker.go | 2 + momentum-core/backtracking/yaml-parser.go | 2 +- momentum-core/docs/docs.go | 125 ------------------ momentum-core/docs/swagger.json | 125 ------------------ momentum-core/docs/swagger.yaml | 83 ------------ momentum-core/files/routes.go | 111 ++++++++++------ momentum-core/templates/model.go | 40 +++--- momentum-core/utils/filehandler.go | 3 +- momentum-core/yaml/tree.go | 27 +++- 13 files changed, 223 insertions(+), 396 deletions(-) create mode 100644 momentum-core/artefacts/override.go diff --git a/momentum-core/artefacts/artefact-tree.go b/momentum-core/artefacts/artefact-tree.go index 23bf286..7e2b7d1 100644 --- a/momentum-core/artefacts/artefact-tree.go +++ b/momentum-core/artefacts/artefact-tree.go @@ -262,6 +262,66 @@ func hasAnyPredecessor(artefact *Artefact, predecessorId string) bool { return false } +// selects all predecessors of an artefact, which have the same name +func predecessorsByName(artefact *Artefact) []*Artefact { + + predecessors := make([]*Artefact, 0) + if artefact == nil || artefact.Parent == nil { + return predecessors + } + + current := artefact.Parent + for current != nil { + + if strings.EqualFold(current.Name, artefact.Name) { + predecessors = append(predecessors, current) + } + + for _, currentChild := range current.Content { + + if strings.EqualFold(currentChild.Name, artefact.Name) { + predecessors = append(predecessors, currentChild) + } + } + + current = current.Parent + } + + return predecessors +} + +func FindArtefactByPath(path string) *Artefact { + + artefactTree, err := LoadArtefactTree() + if err != nil { + config.LOGGER.LogError(err.Error(), err, "NO-TRACEID") + return nil + } + + return findArtefactByPath(artefactTree, path) +} + +func findArtefactByPath(artefact *Artefact, path string) *Artefact { + + if artefact == nil { + return nil + } + + if strings.EqualFold(FullPath(artefact), path) { + return artefact + } + + for _, next := range artefact.Content { + + match := findArtefactByPath(next, path) + if match != nil { + return match + } + } + + return nil +} + func FullPath(artefact *Artefact) string { current := artefact diff --git a/momentum-core/artefacts/override.go b/momentum-core/artefacts/override.go new file mode 100644 index 0000000..243cbdc --- /dev/null +++ b/momentum-core/artefacts/override.go @@ -0,0 +1,31 @@ +package artefacts + +import ( + "strings" +) + +// gets all files which are higher up in the structure with the same name as the given file path. +func OverwritesByPriorityAsc(path string) []*Artefact { + + overwritable := FindArtefactByPath(path) + if overwritable != nil { + + overwritesOrderedByPriorityAsc := make([]*Artefact, 0) + current := overwritable + for current != nil { + + for _, child := range current.Content { + + if strings.EqualFold(overwritable.Name, child.Name) && !strings.EqualFold(overwritable.Id, child.Id) { + overwritesOrderedByPriorityAsc = append(overwritesOrderedByPriorityAsc, child) + } + } + + current = current.Parent + } + + return overwritesOrderedByPriorityAsc + } + + return make([]*Artefact, 0) +} diff --git a/momentum-core/artefacts/routes.go b/momentum-core/artefacts/routes.go index 9d3a6a1..6f4f526 100644 --- a/momentum-core/artefacts/routes.go +++ b/momentum-core/artefacts/routes.go @@ -2,7 +2,6 @@ package artefacts import ( "errors" - "fmt" "momentum-core/config" "net/http" @@ -44,12 +43,12 @@ func GetArtefact(c *gin.Context) { return } - fmt.Println(WriteToString(t)) + // fmt.Println(WriteToString(t)) flattened := FlatPreorder(t, make([]*Artefact, 0)) for _, artefact := range flattened { if artefact.Id == artefactId { - fmt.Println(artefact, "artefactId:", artefact.ParentId) + // fmt.Println(artefact, "artefactId:", artefact.ParentId) c.JSON(http.StatusOK, artefact) return } diff --git a/momentum-core/backtracking/backtrack.go b/momentum-core/backtracking/backtrack.go index a96371c..7d2cf83 100644 --- a/momentum-core/backtracking/backtrack.go +++ b/momentum-core/backtracking/backtrack.go @@ -23,13 +23,14 @@ type Search[T any, P any] interface { IsMatch(*T, *T) bool // StopEarly shall return true if the algorithm must backtrack and reject the current branch. // False if the algorithm shall process further even if no full match has been reached. + // Be aware that a slightly wrong implementation can lead to ommitted results. StopEarly(*T, *T) bool } // Node is the structure used inside the backtrack algorithm and describes a tree structure. type Node[T any, P any] struct { value *T - pointer *P // pointer to the actual element which belongs to the node + Pointer *P // pointer to the actual element which belongs to the node parent *Node[T, P] children []*Node[T, P] } @@ -119,7 +120,7 @@ func walkUp[T any, P any](parent *Node[T, P], current *Node[T, P]) *Node[T, P] { } if found && parent.parent != nil { - // this indicates that the current node was the last of level, thus we need to walk up further + // this indicates that the current node was the last of this level, thus we need to walk up further // if the parent is nil, this indicates we are at root and traversed the whole tree if parent.parent == nil { return nil diff --git a/momentum-core/backtracking/property-backtracker.go b/momentum-core/backtracking/property-backtracker.go index fef7cd9..6324d2f 100644 --- a/momentum-core/backtracking/property-backtracker.go +++ b/momentum-core/backtracking/property-backtracker.go @@ -1,6 +1,7 @@ package backtracking import ( + "fmt" "momentum-core/yaml" "strings" ) @@ -76,6 +77,7 @@ func (backtracker *PropertyBacktracker) Comparable(n *Node[string, yaml.ViewNode func (backtracker *PropertyBacktracker) IsMatch(predicate *string, argument *string) bool { + fmt.Println("trying to match:", *predicate, "=?", *argument) return strings.EqualFold(*predicate, *argument) } diff --git a/momentum-core/backtracking/yaml-parser.go b/momentum-core/backtracking/yaml-parser.go index 367cac8..cf12fba 100644 --- a/momentum-core/backtracking/yaml-parser.go +++ b/momentum-core/backtracking/yaml-parser.go @@ -42,7 +42,7 @@ func viewNodeToNode(n *yaml.ViewNode, parent *Node[string, yaml.ViewNode]) *Node r := new(Node[string, yaml.ViewNode]) r.parent = parent r.value = &n.Path - r.pointer = n + r.Pointer = n children := make([]*Node[string, yaml.ViewNode], 0) for _, child := range n.Children { diff --git a/momentum-core/docs/docs.go b/momentum-core/docs/docs.go index 1648007..6e70d86 100644 --- a/momentum-core/docs/docs.go +++ b/momentum-core/docs/docs.go @@ -151,52 +151,6 @@ const docTemplate = `{ } } }, - "/api/beta/dir/{id}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets the content of a file", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/files.Dir" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, "/api/beta/file": { "post": { "consumes": [ @@ -283,62 +237,6 @@ const docTemplate = `{ } } }, - "/api/beta/file/{id}/line/{lineNumber}/overwrites": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of child properties, which are overwritten by the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { "get": { "produces": [ @@ -508,29 +406,6 @@ const docTemplate = `{ } } }, - "files.Dir": { - "type": "object", - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/files.File" - } - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "subDirs": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Dir" - } - } - } - }, "files.File": { "type": "object", "properties": { diff --git a/momentum-core/docs/swagger.json b/momentum-core/docs/swagger.json index ac319d1..25c7054 100644 --- a/momentum-core/docs/swagger.json +++ b/momentum-core/docs/swagger.json @@ -148,52 +148,6 @@ } } }, - "/api/beta/dir/{id}": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets the content of a file", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/files.Dir" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, "/api/beta/file": { "post": { "consumes": [ @@ -280,62 +234,6 @@ } } }, - "/api/beta/file/{id}/line/{lineNumber}/overwrites": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "files" - ], - "summary": "gets a list of child properties, which are overwritten by the given line.", - "parameters": [ - { - "type": "string", - "description": "file id", - "name": "id", - "in": "path", - "required": true - }, - { - "type": "integer", - "description": "line number in file", - "name": "lineNumber", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Overwrite" - } - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/config.ApiError" - } - } - } - } - }, "/api/beta/file/{id}/line/{lineNumber}/overwritten-by": { "get": { "produces": [ @@ -505,29 +403,6 @@ } } }, - "files.Dir": { - "type": "object", - "properties": { - "files": { - "type": "array", - "items": { - "$ref": "#/definitions/files.File" - } - }, - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "subDirs": { - "type": "array", - "items": { - "$ref": "#/definitions/files.Dir" - } - } - } - }, "files.File": { "type": "object", "properties": { diff --git a/momentum-core/docs/swagger.yaml b/momentum-core/docs/swagger.yaml index 158819b..fd732c5 100644 --- a/momentum-core/docs/swagger.yaml +++ b/momentum-core/docs/swagger.yaml @@ -47,21 +47,6 @@ definitions: type: type: string type: object - files.Dir: - properties: - files: - items: - $ref: '#/definitions/files.File' - type: array - id: - type: string - name: - type: string - subDirs: - items: - $ref: '#/definitions/files.Dir' - type: array - type: object files.File: properties: body: @@ -179,36 +164,6 @@ paths: summary: get a list of deployments for a given stage by id tags: - artefacts - /api/beta/dir/{id}: - get: - parameters: - - description: file id - in: path - name: id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/files.Dir' - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: gets the content of a file - tags: - - files /api/beta/file: post: consumes: @@ -265,44 +220,6 @@ paths: summary: gets the content of a file tags: - files - /api/beta/file/{id}/line/{lineNumber}/overwrites: - get: - parameters: - - description: file id - in: path - name: id - required: true - type: string - - description: line number in file - in: path - name: lineNumber - required: true - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - items: - $ref: '#/definitions/files.Overwrite' - type: array - "400": - description: Bad Request - schema: - $ref: '#/definitions/config.ApiError' - "404": - description: Not Found - schema: - $ref: '#/definitions/config.ApiError' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/config.ApiError' - summary: gets a list of child properties, which are overwritten by the given - line. - tags: - - files /api/beta/file/{id}/line/{lineNumber}/overwritten-by: get: parameters: diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go index 65669f9..f96a5cf 100644 --- a/momentum-core/files/routes.go +++ b/momentum-core/files/routes.go @@ -2,11 +2,16 @@ package files import ( "errors" + "fmt" "momentum-core/artefacts" + "momentum-core/backtracking" "momentum-core/config" "momentum-core/utils" + "momentum-core/yaml" "net/http" "path/filepath" + "strconv" + "strings" "github.com/gin-gonic/gin" ) @@ -14,9 +19,7 @@ import ( func RegisterFileRoutes(engine *gin.Engine) { engine.GET(config.API_FILE_BY_ID, GetFile) engine.POST(config.API_FILE_ADD, AddFile) - engine.GET(config.API_DIR_BY_ID, GetDir) engine.GET(config.API_FILE_LINE_OVERWRITTENBY, GetOverwrittenBy) - engine.GET(config.API_FILE_LINE_OVERWRITES, GetOverwrites) } // GetFile godoc @@ -122,26 +125,6 @@ func AddFile(c *gin.Context) { c.JSON(http.StatusOK, file) } -// GetDir godoc -// -// @Summary gets the content of a file -// @Tags files -// @Produce json -// @Param id path string true "file id" -// @Success 200 {object} Dir -// @Failure 400 {object} config.ApiError -// @Failure 404 {object} config.ApiError -// @Failure 500 {object} config.ApiError -// @Router /api/beta/dir/{id} [get] -func GetDir(c *gin.Context) { - - // TODO is this needed? - - _ = c.Param("id") - - return -} - // GetOverwrittenBy godoc // // @Summary gets a list of properties which overwrite the given line. @@ -156,24 +139,72 @@ func GetDir(c *gin.Context) { // @Router /api/beta/file/{id}/line/{lineNumber}/overwritten-by [get] func GetOverwrittenBy(c *gin.Context) { - _ = c.Param("id") - _ = c.Param("lineNumber") -} + traceId := config.LOGGER.TraceId() -// GetOverwrites godoc -// -// @Summary gets a list of child properties, which are overwritten by the given line. -// @Tags files -// @Produce json -// @Param id path string true "file id" -// @Param lineNumber path int true "line number in file" -// @Success 200 {array} Overwrite -// @Failure 400 {object} config.ApiError -// @Failure 404 {object} config.ApiError -// @Failure 500 {object} config.ApiError -// @Router /api/beta/file/{id}/line/{lineNumber}/overwrites [get] -func GetOverwrites(c *gin.Context) { + overwritableId := c.Param("id") + overwritableLine, err := strconv.Atoi(c.Param("lineNumber")) + if err != nil { + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + overwritable, err := artefacts.FileById(overwritableId) + if err != nil { + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + fileNode, err := yaml.ParseFile(artefacts.FullPath(overwritable)) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + lineNode := yaml.FindNodeByLine(fileNode, overwritableLine) + if lineNode == nil { + err := errors.New("could not find line " + strconv.Itoa(overwritableLine) + " in file " + artefacts.FullPath(overwritable)) + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + fmt.Println("Line of predicate:", lineNode) + + overwritingFiles := artefacts.OverwritesByPriorityAsc(artefacts.FullPath(overwritable)) + + fmt.Println("files possibly overwriting current", overwritingFiles) + + if len(overwritingFiles) > 0 { + + predicate := yaml.ToMatchableSearchTerm(lineNode.FullPath()) + predicate = strings.Join(strings.Split(predicate, ".")[1:], ".") // remove filename prefix + + overwrites := make([]*Overwrite, 0) + for _, overwriting := range overwritingFiles { + + fmt.Println("loading overwrite:", overwriting) + + backtracker := backtracking.NewPropertyBacktracker(predicate, artefacts.FullPath(overwriting), backtracking.NewYamlPropertyParser()) + var result []*backtracking.Match[string, yaml.ViewNode] = backtracker.RunBacktrack() + + for _, match := range result { + + overwrite := new(Overwrite) + overwrite.OriginFileId = overwritableId + overwrite.OriginFileLine = overwritableLine + overwrite.OverwriteFileLine = match.MatchNode.Pointer.YamlNode.Line + overwrite.OverwriteFileId = overwriting.Id + + overwrites = append(overwrites, overwrite) + } + } + + c.JSON(http.StatusOK, overwrites) + return + } - _ = c.Param("id") - _ = c.Param("lineNumber") + c.JSON(http.StatusOK, make([]*Overwrite, 0)) } diff --git a/momentum-core/templates/model.go b/momentum-core/templates/model.go index e6e5d6a..7b166bb 100644 --- a/momentum-core/templates/model.go +++ b/momentum-core/templates/model.go @@ -1,32 +1,42 @@ package templates +import "momentum-core/files" + type TemplateStructureType int +type TemplateKind int + +const ( + APPLICATION TemplateKind = 1 << iota + STAGE + DEPLOYMENT +) + const ( DIR TemplateStructureType = 1 << iota FILE ) type CreateTemplateRequest struct { - Name string `json:"name"` - ParentId string `json:"parentId"` // must be an artefact of type APPLICATION or STAGE - TemplateStructure []*CreateTemplateStructureArtefact `json:"templateStructure"` + TemplateKind TemplateKind `json:"templateKind"` + Template *files.Dir `json:"template"` } -type CreateTemplateStructureArtefact struct { - Name string `json:"name"` - Path string `json:"path"` // the path is to be given relative to the templates root - TemplateStructureType TemplateStructureType `json:"templateStructureType"` - ParentId string `json:"parentId"` // if not set, it will live inside the templates root +type Template struct { + TemplateKind TemplateKind `json:"templateKind"` + Template *files.Dir `json:"template"` } -type Template struct { - Id string `json:"id"` - Name string `json:"name"` - TemplateArtefact []*TemplateArtefact `json:"templateArtefacts"` +type TemplateStore struct { + Templates []*Template `json:"templates"` } -type TemplateArtefact struct { - Id string `json:"id"` - Name string `json:"name"` +// next steps: +// 1. define templates +// 2. define implement overwrite detection by file +// 3. implement backtracking with detected files for line matching endpoints + +// this shall define which files overwrite each other. +// shall support wildcards and filenames. +type OverwriteConfiguration struct { } diff --git a/momentum-core/utils/filehandler.go b/momentum-core/utils/filehandler.go index 308bd6f..08e04b7 100644 --- a/momentum-core/utils/filehandler.go +++ b/momentum-core/utils/filehandler.go @@ -18,7 +18,8 @@ func IsDirectory(path string) bool { stat, err := os.Stat(path) if err != nil { - panic("Failed opening stat of file " + path) + fmt.Println("Failed opening stat of file " + path) + return false } return stat.IsDir() } diff --git a/momentum-core/yaml/tree.go b/momentum-core/yaml/tree.go index d17ce1d..5d6f7f7 100644 --- a/momentum-core/yaml/tree.go +++ b/momentum-core/yaml/tree.go @@ -65,7 +65,6 @@ func NewNode(kind NodeKind, path string, value string, parent *ViewNode, childre return n } -// fileNode == nil indicates empty file. func ParseFile(path string) (*ViewNode, error) { if strings.HasSuffix(path, ".yml") || strings.HasSuffix(path, ".yaml") { @@ -82,6 +81,27 @@ func ParseFile(path string) (*ViewNode, error) { return nil, errors.New("unsupported file type") } +func FindNodeByLine(n *ViewNode, line int) *ViewNode { + + if n.Kind == Directory { + fmt.Println("cannot find node of type directory") + return nil + } + + if n.YamlNode.Line == line { + return n + } + + for _, child := range n.Children { + result := FindNodeByLine(child, line) + if result != nil { + return result + } + } + + return nil +} + // Returns full path from root to this node. func (n *ViewNode) FullPath() string { path := "" @@ -97,6 +117,11 @@ func (n *ViewNode) FullPath() string { return strings.ReplaceAll(path, FILE_ENDING_SEPARATOR_REPLACEMENT, ".") } +func ToMatchableSearchTerm(fullPath string) string { + + return strings.ReplaceAll(strings.ReplaceAll(fullPath, ".", "::"), "/", ".") +} + func (n *ViewNode) Remove() { if n.Parent == nil || len(n.Parent.Children) < 1 { From 8cb6ff53994535d8901d9fe430d59a8787039b95 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 08:41:21 +0200 Subject: [PATCH 05/10] fix: make overwrites more flexibel --- momentum-core/artefacts/override.go | 7 ++++++- momentum-core/backtracking/property-backtracker.go | 3 +-- momentum-core/files/routes.go | 14 +++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/momentum-core/artefacts/override.go b/momentum-core/artefacts/override.go index 243cbdc..9f3d6b7 100644 --- a/momentum-core/artefacts/override.go +++ b/momentum-core/artefacts/override.go @@ -4,8 +4,13 @@ import ( "strings" ) +type OverwriteAdvice func(string) []*Artefact + +// extend this list to add more overwriting rules +var ActiveOverwriteAdvices []OverwriteAdvice = []OverwriteAdvice{overwritesByFilenamePriorityAsc} + // gets all files which are higher up in the structure with the same name as the given file path. -func OverwritesByPriorityAsc(path string) []*Artefact { +func overwritesByFilenamePriorityAsc(path string) []*Artefact { overwritable := FindArtefactByPath(path) if overwritable != nil { diff --git a/momentum-core/backtracking/property-backtracker.go b/momentum-core/backtracking/property-backtracker.go index 6324d2f..aaa44ef 100644 --- a/momentum-core/backtracking/property-backtracker.go +++ b/momentum-core/backtracking/property-backtracker.go @@ -1,7 +1,6 @@ package backtracking import ( - "fmt" "momentum-core/yaml" "strings" ) @@ -77,7 +76,7 @@ func (backtracker *PropertyBacktracker) Comparable(n *Node[string, yaml.ViewNode func (backtracker *PropertyBacktracker) IsMatch(predicate *string, argument *string) bool { - fmt.Println("trying to match:", *predicate, "=?", *argument) + // fmt.Println("trying to match:", *predicate, "=?", *argument) return strings.EqualFold(*predicate, *argument) } diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go index f96a5cf..f0e53dd 100644 --- a/momentum-core/files/routes.go +++ b/momentum-core/files/routes.go @@ -2,7 +2,6 @@ package files import ( "errors" - "fmt" "momentum-core/artefacts" "momentum-core/backtracking" "momentum-core/config" @@ -127,7 +126,7 @@ func AddFile(c *gin.Context) { // GetOverwrittenBy godoc // -// @Summary gets a list of properties which overwrite the given line. +// @Summary gets a list of overwrites which overwrite the given line. // @Tags files // @Produce json // @Param id path string true "file id" @@ -171,11 +170,10 @@ func GetOverwrittenBy(c *gin.Context) { return } - fmt.Println("Line of predicate:", lineNode) - - overwritingFiles := artefacts.OverwritesByPriorityAsc(artefacts.FullPath(overwritable)) - - fmt.Println("files possibly overwriting current", overwritingFiles) + overwritingFiles := make([]*artefacts.Artefact, 0) + for _, advice := range artefacts.ActiveOverwriteAdvices { + overwritingFiles = append(overwritingFiles, advice(artefacts.FullPath(overwritable))...) + } if len(overwritingFiles) > 0 { @@ -185,8 +183,6 @@ func GetOverwrittenBy(c *gin.Context) { overwrites := make([]*Overwrite, 0) for _, overwriting := range overwritingFiles { - fmt.Println("loading overwrite:", overwriting) - backtracker := backtracking.NewPropertyBacktracker(predicate, artefacts.FullPath(overwriting), backtracking.NewYamlPropertyParser()) var result []*backtracking.Match[string, yaml.ViewNode] = backtracker.RunBacktrack() From 3580f7e58ae1df1cdd5697593d9b45428681f5b6 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 09:43:37 +0200 Subject: [PATCH 06/10] feat: update file & integrate git transactions --- momentum-core/files/routes.go | 109 +++++++++++++++++++++++++++++++++- momentum-core/go.mod | 6 -- momentum-core/go.sum | 25 -------- 3 files changed, 108 insertions(+), 32 deletions(-) diff --git a/momentum-core/files/routes.go b/momentum-core/files/routes.go index f0e53dd..5d9ed5d 100644 --- a/momentum-core/files/routes.go +++ b/momentum-core/files/routes.go @@ -12,6 +12,7 @@ import ( "strconv" "strings" + gittransaction "github.com/Joel-Haeberli/git-transaction" "github.com/gin-gonic/gin" ) @@ -52,7 +53,7 @@ func GetFile(c *gin.Context) { // AddFile godoc // -// @Summary adds a new file to a given parent +// @Summary adds a new file to a given parent (triggers transaction) // @Tags files // @Accept json // @Produce json @@ -97,23 +98,49 @@ func AddFile(c *gin.Context) { return } + ctx, transaction, err := gittransaction.New(config.TRANSACTION_MODE, config.GLOBAL.RepoDir(), config.GLOBAL.TransactionToken()) + if err != nil { + transaction.Rollback(ctx) + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + writeSuccess := utils.FileWrite(filePath, fileContentDecoded) if !writeSuccess { + transaction.Rollback(ctx) err = errors.New("writing file failed") c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) config.LOGGER.LogError(err.Error(), err, traceId) return } + err = transaction.Write(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + err = transaction.Commit(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + encodedFile, err := fileToBase64(filePath) newFileId, err := utils.GenerateId(config.IdGenerationPath(filePath)) if err != nil { + transaction.Rollback(ctx) c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) config.LOGGER.LogError(err.Error(), err, traceId) return } + fileArtefact, err := artefacts.FileById(newFileId) if err != nil { + transaction.Rollback(ctx) c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) config.LOGGER.LogError(err.Error(), err, traceId) return @@ -124,6 +151,86 @@ func AddFile(c *gin.Context) { c.JSON(http.StatusOK, file) } +// UpdateFile godoc +// +// @Summary updates the given file (triggers transaction) +// @Tags files +// @Accept json +// @Produce json +// @Body File +// @Success 200 {object} File +// @Failure 400 {object} config.ApiError +// @Failure 404 {object} config.ApiError +// @Failure 500 {object} config.ApiError +// @Router /api/beta/file/{id} [put] +func UpdateFile(c *gin.Context) { + + traceId := config.LOGGER.TraceId() + + requestedFile := new(File) + err := c.BindJSON(requestedFile) + if err != nil { + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + decodedBody, err := fileToRaw(requestedFile.Body) + if err != nil { + c.JSON(http.StatusBadRequest, config.NewApiError(err, http.StatusBadRequest, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + file, err := artefacts.FileById(requestedFile.Id) + if err != nil { + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + filePath := artefacts.FullPath(file) + if !utils.FileExists(filePath) { + err = errors.New("file does not exist") + c.JSON(http.StatusNotFound, config.NewApiError(err, http.StatusNotFound, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + ctx, transaction, err := gittransaction.New(config.TRANSACTION_MODE, config.GLOBAL.RepoDir(), config.GLOBAL.TransactionToken()) + if err != nil { + transaction.Rollback(ctx) + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + utils.FileDelete(filePath) + success := utils.FileWrite(filePath, decodedBody) + if !success { + err = errors.New("failed to write file") + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + err = transaction.Write(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + err = transaction.Commit(ctx) + if err != nil { + c.JSON(http.StatusInternalServerError, config.NewApiError(err, http.StatusInternalServerError, c, traceId)) + config.LOGGER.LogError(err.Error(), err, traceId) + return + } + + c.JSON(http.StatusOK, requestedFile) +} + // GetOverwrittenBy godoc // // @Summary gets a list of overwrites which overwrite the given line. diff --git a/momentum-core/go.mod b/momentum-core/go.mod index 1a56dab..c948831 100644 --- a/momentum-core/go.mod +++ b/momentum-core/go.mod @@ -27,14 +27,9 @@ require ( github.com/go-openapi/spec v0.20.9 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/kr/pretty v0.3.1 // indirect - github.com/labstack/echo v3.3.10+incompatible // indirect - github.com/labstack/gommon v0.2.9 // indirect - github.com/mattn/go-colorable v0.1.2 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/skeema/knownhosts v1.1.1 // indirect github.com/stretchr/testify v1.8.4 // indirect - github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.0.1 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/tools v0.11.0 // indirect ) @@ -72,7 +67,6 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect - github.com/pdrum/swagger-automation v0.0.0-20190629163613-c8c7c80ba858 github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sergi/go-diff v1.3.1 // indirect diff --git a/momentum-core/go.sum b/momentum-core/go.sum index 8f88a63..5b4c27a 100644 --- a/momentum-core/go.sum +++ b/momentum-core/go.sum @@ -1,9 +1,3 @@ -github.com/Joel-Haeberli/git-transaction v0.1.1 h1:DsmVZAx5cEsUq8VqNkJZ8a5JRRk1ahGHb9yo3nTxQRI= -github.com/Joel-Haeberli/git-transaction v0.1.1/go.mod h1:cd98lb1P64RZtEpTQXXclpG7+OSp9eDNQjiMFkkxFpA= -github.com/Joel-Haeberli/git-transaction v0.1.2 h1:xXIgHFKfaZw8Dko29+/sNPQTkDKYOczv0Xk1Kh/kauQ= -github.com/Joel-Haeberli/git-transaction v0.1.2/go.mod h1:cd98lb1P64RZtEpTQXXclpG7+OSp9eDNQjiMFkkxFpA= -github.com/Joel-Haeberli/git-transaction v0.1.3 h1:aXdQkM7WUCBWeAVHhLF4HIWBSrAy28AqKALZswrk9k4= -github.com/Joel-Haeberli/git-transaction v0.1.3/go.mod h1:cd98lb1P64RZtEpTQXXclpG7+OSp9eDNQjiMFkkxFpA= github.com/Joel-Haeberli/git-transaction v0.1.4 h1:EXi+rf4LZTxseh1cfAgNWK+DDk7/2vcT+vrKiUzZLDc= github.com/Joel-Haeberli/git-transaction v0.1.4/go.mod h1:cd98lb1P64RZtEpTQXXclpG7+OSp9eDNQjiMFkkxFpA= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= @@ -13,8 +7,6 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903 h1:ZK3C5DtzV2nVAQTx5S5jQvMeDqWtD1By5mOoyY/xJek= github.com/ProtonMail/go-crypto v0.0.0-20230518184743-7afd39499903/go.mod h1:8TI4H3IbrackdNgv+92dI+rhpCaLqM0IfpgCgenFvRE= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= @@ -41,7 +33,6 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -132,10 +123,6 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= -github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= -github.com/labstack/gommon v0.2.9 h1:heVeuAYtevIQVYkGj6A41dtfT91LrvFG220lavpWhrU= -github.com/labstack/gommon v0.2.9/go.mod h1:E8ZTmW9vw5az5/ZyHWCp0Lw4OH2ecsaBP1C/NKavGG4= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -145,9 +132,6 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -160,8 +144,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pdrum/swagger-automation v0.0.0-20190629163613-c8c7c80ba858 h1:lgbJiJQx8bXo+eM88AFdd0VxUvaTLzCBXpK+H9poJ+Y= -github.com/pdrum/swagger-automation v0.0.0-20190629163613-c8c7c80ba858/go.mod h1:y02HeaN0visd95W6cEX2NXDv5sCwyqfzucWTdDGEwYY= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= @@ -210,10 +192,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= @@ -227,7 +205,6 @@ golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -255,9 +232,7 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 3f4224c02191fb8933cd35ac6be048bf91f74be6 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 18 Sep 2023 10:03:56 +0200 Subject: [PATCH 07/10] fix: new structure according to argocd --- .../{application}/_base/application.yaml | 26 ++++++++++++++ .../{application}/_base/kustomization.yaml | 13 +++++++ .../{application}/_base/values.yaml | 0 .../{stage}/_argo/kustomization.yaml | 8 +++++ .../{application}/{stage}/_argo/project.yaml | 20 +++++++++++ .../{stage}/_base/application.yaml | 6 ++++ .../{stage}/_base/kustomization.yaml | 15 ++++++++ .../{application}/{stage}/_base/values.yaml | 8 +++++ .../_deploy/{deployment}/application.yaml | 5 +++ .../_deploy/{deployment}/kustomization.yaml | 36 +++++++++++++++++++ .../{stage}/_deploy/{deployment}/secrets.yaml | 0 .../{stage}/_deploy/{deployment}/values.yaml | 0 .../{application}/{stage}/kustomization.yaml | 5 +++ 13 files changed, 142 insertions(+) create mode 100644 momentum-structure/momentum-root-argocd/{application}/_base/application.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/_base/kustomization.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/_base/values.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/kustomization.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/project.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_base/application.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_base/kustomization.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_base/values.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/application.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml create mode 100644 momentum-structure/momentum-root-argocd/{application}/{stage}/kustomization.yaml diff --git a/momentum-structure/momentum-root-argocd/{application}/_base/application.yaml b/momentum-structure/momentum-root-argocd/{application}/_base/application.yaml new file mode 100644 index 0000000..3fefcf0 --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/_base/application.yaml @@ -0,0 +1,26 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched + namespace: argocd + annotations: + pref.argocd.argoproj.io/default-view: network + pref.argocd.argoproj.io/default-pod-sort: parentResource +spec: + source: + chart: {{ .HelmChartName }} + repoURL: {{ .HelmRepoUrl }} + targetRevision: {{ .HelmChartVersion }} + helm: + releaseName: {{ .ApplicationName }} + valuesObject: + destination: + server: "https://kubernetes.default.svc" + namespace: to-be-patched + syncPolicy: + automated: + allowEmpty: true + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/momentum-structure/momentum-root-argocd/{application}/_base/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/_base/kustomization.yaml new file mode 100644 index 0000000..555e23c --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/_base/kustomization.yaml @@ -0,0 +1,13 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- application.yaml +labels: +- includeSelectors: true + pairs: + gitops.natron.io/application: '{{ .ApplicationName }}' +patches: + - path: values.yaml + target: + kind: Application + diff --git a/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml b/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/kustomization.yaml new file mode 100644 index 0000000..408c81e --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- project.yaml +labels: +- includeSelectors: true + pairs: + gitops.natron.io/app: "{{ .ApplicationName }}" \ No newline at end of file diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/project.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/project.yaml new file mode 100644 index 0000000..9b612f9 --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_argo/project.yaml @@ -0,0 +1,20 @@ +apiVersion: argoproj.io/v1alpha1 +kind: AppProject +metadata: + name: {{ .ApplicationName }}-{{ .StageNames }} + namespace: argocd +spec: + clusterResourceWhitelist: + - group: '*' + kind: '*' + description: This is the Project for {{ .ApplicationName }} + destinations: + - name: in-cluster + namespace: {{ .ApplicationName }}-{{ .StageNames }}-* + server: https://kubernetes.default.svc + namespaceResourceWhitelist: + - group: '*' + kind: '*' + # sourceRepos: + orphanedResources: + warn: false \ No newline at end of file diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/application.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/application.yaml new file mode 100644 index 0000000..209af0f --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/application.yaml @@ -0,0 +1,6 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched +spec: + project: {{ .ApplicationName }}-{{ .StageNames }} diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/kustomization.yaml new file mode 100644 index 0000000..d3a1521 --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../../_base/ +labels: +- includeSelectors: true + pairs: + gitops.natron.io/app: "{{ .ApplicationName }}" +patches: + - path: application.yaml + target: + kind: Application + - path: values.yaml + target: + kind: Application \ No newline at end of file diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/values.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/values.yaml new file mode 100644 index 0000000..b98908a --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_base/values.yaml @@ -0,0 +1,8 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched +spec: + source: + helm: + valuesObject: \ No newline at end of file diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/application.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/application.yaml new file mode 100644 index 0000000..2f404b7 --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/application.yaml @@ -0,0 +1,5 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +spec: + destination: + namespace: {{ .ApplicationName }}-{{ .StageNames }} diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml new file mode 100644 index 0000000..a04893b --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml @@ -0,0 +1,36 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../../_base/ # applications _base +labels: +- includeSelectors: true + pairs: + # Patched on stage above // wont work if addtionall resources are added on this level + #gitops.natron.io/app: "" + gitops.natron.io/stage: "{{ .StageName }}" +patches: + - path: application.yaml + target: + kind: Application + - target: + kind: Application + name: .* + patch: |- + - op: replace + path: /metadata/name + # {{ .ApplicationName }}-{{ .StageNames }} + value: {{ .MetadataName }} + - target: + group: image.toolkit.fluxcd.io + name: .* + patch: |- + - op: replace + path: /metadata/namespace + value: {{ .MetadataName }} + - target: + group: notification.toolkit.fluxcd.io + name: .* + patch: |- + - op: replace + path: /metadata/namespace + value: {{ .MetadataName }} \ No newline at end of file diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml new file mode 100644 index 0000000..e69de29 diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml new file mode 100644 index 0000000..e69de29 diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/kustomization.yaml new file mode 100644 index 0000000..116db63 --- /dev/null +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ./_deploy/prod/ +#- ./_deploy/dev/ From 24036325216d7a4df4595a0c2e0ed35718a1aaa6 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 10:03:52 +0200 Subject: [PATCH 08/10] ignore: .vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 211f8d1..26e7031 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ dist/ _temp/ ./momentum-core/momentum-core +./momentum-core/.vscode/* From 2107ca0da49b90132f23099c512d8327ed292892 Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 10:04:38 +0200 Subject: [PATCH 09/10] ignore: .vscode --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 26e7031..71b50f8 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,4 @@ dist/ _temp/ ./momentum-core/momentum-core -./momentum-core/.vscode/* +./momentum-core/.vscode/ From 9dbbfc9e97a143fd49088cb26489cf4aa388bc2b Mon Sep 17 00:00:00 2001 From: Joel-Haeberli Date: Mon, 2 Oct 2023 10:05:55 +0200 Subject: [PATCH 10/10] fix: merge request comments --- .../momentum-root-argocd/{application}/_base/values.yaml | 9 +++++++++ .../{stage}/_deploy/{deployment}/kustomization.yaml | 8 +++++++- .../{stage}/_deploy/{deployment}/secrets.yaml | 9 +++++++++ .../{stage}/_deploy/{deployment}/values.yaml | 9 +++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml b/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml index e69de29..b72e7a7 100644 --- a/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml +++ b/momentum-structure/momentum-root-argocd/{application}/_base/values.yaml @@ -0,0 +1,9 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched +spec: + source: + helm: + valuesObject: + diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml index a04893b..656c238 100644 --- a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/kustomization.yaml @@ -12,6 +12,12 @@ patches: - path: application.yaml target: kind: Application + - path: values.yaml + target: + kind: Application + - path: secrets.yaml + target: + kind: Application - target: kind: Application name: .* @@ -33,4 +39,4 @@ patches: patch: |- - op: replace path: /metadata/namespace - value: {{ .MetadataName }} \ No newline at end of file + value: {{ .MetadataName }} diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml index e69de29..b72e7a7 100644 --- a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/secrets.yaml @@ -0,0 +1,9 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched +spec: + source: + helm: + valuesObject: + diff --git a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml index e69de29..b72e7a7 100644 --- a/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml +++ b/momentum-structure/momentum-root-argocd/{application}/{stage}/_deploy/{deployment}/values.yaml @@ -0,0 +1,9 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: to-be-patched +spec: + source: + helm: + valuesObject: +