diff --git a/momentum-backend/main.go b/momentum-backend/main.go index db6ca4d..c4f5be9 100644 --- a/momentum-backend/main.go +++ b/momentum-backend/main.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "log" "os" "path/filepath" @@ -13,6 +14,7 @@ import ( "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" + "github.com/pocketbase/pocketbase/daos" "github.com/pocketbase/pocketbase/plugins/jsvm" "github.com/pocketbase/pocketbase/plugins/migratecmd" ) @@ -69,6 +71,9 @@ func main() { }) app.OnAfterBootstrap().Add(func(e *core.BootstrapEvent) error { + + testCleanUp(app.Dao().Clone()) + dispatcher := momentumcore.NewDispatcher(momentumConfig, app) // momentum core features must run before executing DB statements. @@ -84,3 +89,32 @@ func main() { log.Fatal(err) } } + +func testCleanUp(dao *daos.Dao) { + + keyvalues, err := dao.FindRecordsByExpr("keyValues") + depls, err := dao.FindRecordsByExpr("deployments") + stages, err := dao.FindRecordsByExpr("stages") + apps, err := dao.FindRecordsByExpr("applications") + reps, err := dao.FindRecordsByExpr("repositories") + + if err != nil { + fmt.Println("TEST CLEAN FAILED:", err.Error()) + } + + for _, e := range keyvalues { + dao.DeleteRecord(e) + } + for _, e := range depls { + dao.DeleteRecord(e) + } + for _, e := range stages { + dao.DeleteRecord(e) + } + for _, e := range apps { + dao.DeleteRecord(e) + } + for _, e := range reps { + dao.DeleteRecord(e) + } +} diff --git a/momentum-backend/momentum-core/momentum-config/db-consts.go b/momentum-backend/momentum-core/momentum-config/db-consts.go index edc3a84..654d046 100644 --- a/momentum-backend/momentum-core/momentum-config/db-consts.go +++ b/momentum-backend/momentum-core/momentum-config/db-consts.go @@ -6,23 +6,28 @@ const TABLE_REPOSITORIES_NAME = "repositories" const TABLE_REPOSITORIES_FIELD_ID = "id" const TABLE_REPOSITORIES_FIELD_NAME = "name" const TABLE_REPOSITORIES_FIELD_URL = "url" +const TABLE_REPOSITORIES_FIELD_APPLICATIONS = "applications" const TABLE_APPLICATIONS_NAME = "applications" const TABLE_APPLICATIONS_FIELD_ID = "id" const TABLE_APPLICATIONS_FIELD_NAME = "name" const TABLE_APPLICATIONS_FIELD_STAGES = "stages" const TABLE_APPLICATIONS_FIELD_HELMREPO = "helmRepository" +const TABLE_APPLICATIONS_FIELD_PARENTREPOSITORY = "parentRepository" const TABLE_DEPLOYMENTS_NAME = "deployments" const TABLE_DEPLOYMENTS_FIELD_ID = "id" const TABLE_DEPLOYMENTS_FIELD_NAME = "name" const TABLE_DEPLOYMENTS_FIELD_DESCRIPTION = "description" const TABLE_DEPLOYMENTS_FIELD_REPOSITORIES = "repositories" +const TABLE_DEPLOYMENTS_FIELD_PARENTSTAGE = "parentStage" const TABLE_STAGES_NAME = "stages" const TABLE_STAGES_FIELD_ID = "id" const TABLE_STAGES_FIELD_NAME = "name" const TABLE_STAGES_FIELD_DEPLOYMENTS = "deployments" +const TABLE_STAGES_FIELD_PARENTSTAGE = "parentStage" +const TABLE_STAGES_FIELD_PARENTAPPLICATION = "parentApplication" const TABLE_TEMPLATES_NAME = "templates" const TABLE_TEMPLATES_FIELD_ID = "id" @@ -40,5 +45,7 @@ const TABLE_KEYVALUE_NAME = "keyValues" const TABLE_KEYVALUE_FIELD_ID = "id" const TABLE_KEYVALUE_FIELD_KEY = "key" const TABLE_KEYVALUE_FIELD_VALUE = "value" +const TABLE_KEYVALUE_FIELD_PARENTSTAGE = "parentStage" +const TABLE_KEYVALUE_FIELD_PARENTDEPLOYMENT = "parentDeployment" const TABLE_SECRETKEYVALUE_NAME = "secretKeyValues" diff --git a/momentum-backend/momentum-core/momentum-controllers/application-controller.go b/momentum-backend/momentum-core/momentum-controllers/application-controller.go index 72af3bc..048d398 100644 --- a/momentum-backend/momentum-core/momentum-controllers/application-controller.go +++ b/momentum-backend/momentum-core/momentum-controllers/application-controller.go @@ -8,17 +8,29 @@ import ( ) type ApplicationController struct { - appService *services.ApplicationService + appService *services.ApplicationService + repositoryService *services.RepositoryService } -func NewApplicationController(appService *services.ApplicationService) *ApplicationController { +func NewApplicationController(appService *services.ApplicationService, repoService *services.RepositoryService) *ApplicationController { appController := new(ApplicationController) appController.appService = appService + appController.repositoryService = repoService return appController } +func (ac *ApplicationController) AddRepositoryToApplications(repoAddedEvent *RepositoryAddedEvent) error { + + repositoryRecord, err := ac.repositoryService.FindForName(repoAddedEvent.RepositoryName) + if err != nil { + return err + } + + return ac.appService.AddRepository(repositoryRecord, repoAddedEvent.Applications) +} + func (ac *ApplicationController) AddApplication(record *models.Record, conf *config.MomentumConfig) error { return nil diff --git a/momentum-backend/momentum-core/momentum-controllers/repository-controller.go b/momentum-backend/momentum-core/momentum-controllers/repository-controller.go index 4e4365d..6988ea9 100644 --- a/momentum-backend/momentum-core/momentum-controllers/repository-controller.go +++ b/momentum-backend/momentum-core/momentum-controllers/repository-controller.go @@ -16,6 +16,7 @@ import ( type RepositoryAddedEvent struct { RepositoryName string + Applications []*models.Record Deployments []*models.Record } @@ -60,7 +61,7 @@ func (rc *RepositoryController) AddRepository(record *models.Record, conf *confi return err } - _, deployments, err := rc.repositoryService.SyncRepositoryFromDisk(repo, record) + _, apps, deployments, err := rc.repositoryService.SyncRepositoryFromDisk(repo, record) if err != nil { fmt.Println("ERROR:", err.Error()) utils.DirDelete(path) @@ -69,6 +70,7 @@ func (rc *RepositoryController) AddRepository(record *models.Record, conf *confi repoAddedEvent := new(RepositoryAddedEvent) repoAddedEvent.RepositoryName = repoName + repoAddedEvent.Applications = apps repoAddedEvent.Deployments = deployments rc.repositoryAddedEventChannel <- repoAddedEvent diff --git a/momentum-backend/momentum-core/momentum-dispatcher.go b/momentum-backend/momentum-core/momentum-dispatcher.go index 4979836..5ccae75 100644 --- a/momentum-backend/momentum-core/momentum-dispatcher.go +++ b/momentum-backend/momentum-core/momentum-dispatcher.go @@ -46,7 +46,7 @@ func NewDispatcher(config *conf.MomentumConfig, pb *pocketbase.PocketBase) *Mome repoService := services.NewRepositoryService(pb.Dao(), appService) dispatcher.RepositoryController = controllers.NewRepositoryController(repoService, deploymentService, REPOSITORY_ADDED_EVENT_CHANNEL) - dispatcher.ApplicationsController = controllers.NewApplicationController(appService) + dispatcher.ApplicationsController = controllers.NewApplicationController(appService, repoService) dispatcher.StagesController = controllers.NewStageController(stageService) dispatcher.DeploymentController = controllers.NewDeploymentController(deploymentService, repoService) @@ -136,7 +136,13 @@ func (d *MomentumDispatcher) setupRepositoryAddedEventChannelObserver() { err := d.DeploymentController.AddRepositoryToDeployments(event) if err != nil { - fmt.Println("failed adding relationship to deployments for repository after reciving RepositoryAddedEvent:", event, err, err.Error()) + fmt.Println("failed adding relationship to deployments for repository after receiving RepositoryAddedEvent:", event, err, err.Error()) + return err + } + + err = d.ApplicationsController.AddRepositoryToApplications(event) + if err != nil { + fmt.Println("failed adding relationship to applications for repository after receiving RepositoryAddedEvent:", event, err, err.Error()) return err } diff --git a/momentum-backend/momentum-core/momentum-services/application-service.go b/momentum-backend/momentum-core/momentum-services/application-service.go index a2e4aca..912c107 100644 --- a/momentum-backend/momentum-core/momentum-services/application-service.go +++ b/momentum-backend/momentum-core/momentum-services/application-service.go @@ -1,6 +1,8 @@ package momentumservices import ( + "errors" + "fmt" consts "momentum/momentum-core/momentum-config" tree "momentum/momentum-core/momentum-tree" @@ -26,10 +28,13 @@ func NewApplicationService(dao *daos.Dao, stageService *StageService) *Applicati return appService } -func (as *ApplicationService) SyncApplicationsFromDisk(n *tree.Node, record *models.Record) ([]string, error) { +func (as *ApplicationService) SyncApplicationsFromDisk(n *tree.Node, record *models.Record) ([]*models.Record, error) { - recs := make([]string, 0) + recs := make([]*models.Record, 0) apps := n.Apps() + for _, a := range apps { + fmt.Println(a) + } for _, app := range apps { stages, err := as.stageService.SyncStagesFromDisk(app) @@ -37,32 +42,60 @@ func (as *ApplicationService) SyncApplicationsFromDisk(n *tree.Node, record *mod return nil, err } - rec, err := as.createWithoutEvent(app.NormalizedPath(), stages) + stageIds := make([]string, 0) + for _, stage := range stages { + stageIds = append(stageIds, stage.Id) + } + + rec, err := as.createWithoutEvent(app.NormalizedPath(), stageIds) if err != nil { return nil, err } + + err = as.stageService.AddParentApplication(stageIds, rec) + recs = append(recs, rec) } return recs, nil } +func (as *ApplicationService) AddRepository(repositoryRecord *models.Record, applications []*models.Record) error { + + if repositoryRecord.Collection().Name != consts.TABLE_REPOSITORIES_NAME { + return errors.New("repositoryRecord is not record of repositories collection") + } + + for _, app := range applications { + + app.Set(consts.TABLE_APPLICATIONS_FIELD_PARENTREPOSITORY, repositoryRecord.Id) + err := as.saveWithoutEvent(app) + if err != nil { + return err + } + } + + return nil +} + func (as *ApplicationService) GetApplicationCollection() (*models.Collection, error) { return as.dao.FindCollectionByNameOrId(consts.TABLE_APPLICATIONS_NAME) } -func (as *ApplicationService) createWithoutEvent(name string, stageIds []string) (string, error) { +func (as *ApplicationService) createWithoutEvent(name string, stageIds []string) (*models.Record, error) { appCollection, err := as.GetApplicationCollection() if err != nil { - return "", err + return nil, err } appRecord := models.NewRecord(appCollection) appRecord.Set(consts.TABLE_APPLICATIONS_FIELD_NAME, name) appRecord.Set(consts.TABLE_APPLICATIONS_FIELD_STAGES, stageIds) - err = as.dao.Clone().SaveRecord(appRecord) + return appRecord, as.saveWithoutEvent(appRecord) +} - return appRecord.Id, err +func (as *ApplicationService) saveWithoutEvent(record *models.Record) error { + return as.dao.Clone().SaveRecord(record) } diff --git a/momentum-backend/momentum-core/momentum-services/deployment-service.go b/momentum-backend/momentum-core/momentum-services/deployment-service.go index 9ae1fc2..f66f8ee 100644 --- a/momentum-backend/momentum-core/momentum-services/deployment-service.go +++ b/momentum-backend/momentum-core/momentum-services/deployment-service.go @@ -2,7 +2,6 @@ package momentumservices import ( "errors" - "fmt" consts "momentum/momentum-core/momentum-config" tree "momentum/momentum-core/momentum-tree" @@ -29,43 +28,59 @@ func NewDeploymentService(dao *daos.Dao, keyValueService *KeyValueService) *Depl return deplyomentService } -func (ds *DeploymentService) SyncDeploymentsFromDisk(n *tree.Node) ([]string, error) { +func (ds *DeploymentService) SyncDeploymentsFromDisk(n *tree.Node) ([]*models.Record, error) { deployments := n.AllDeployments() - deploymentIds := make([]string, 0) + deploymentIds := make([]*models.Record, 0) for _, deployment := range deployments { - deploymentId, deploymentRecord, err := ds.createWithoutEvent(deployment.NormalizedPath()) + deploymentRecord, err := ds.createWithoutEvent(deployment.NormalizedPath()) if err != nil { return nil, err } if deployment.Kind == tree.File { - err = ds.keyValueService.SyncFile(deployment, deploymentRecord) + + err := ds.keyValueService.SyncFile(deployment, deploymentRecord) if err != nil { return nil, err } } - deploymentIds = append(deploymentIds, deploymentId) + deploymentIds = append(deploymentIds, deploymentRecord) } return deploymentIds, nil } +func (ds *DeploymentService) AddParentStage(stage *models.Record, deployments []*models.Record) error { + + if stage.Collection().Name != consts.TABLE_STAGES_NAME { + return errors.New("stage is not record of stages collection") + } + + for _, deployment := range deployments { + deployment.Set(consts.TABLE_DEPLOYMENTS_FIELD_PARENTSTAGE, stage.Id) + err := ds.saveWithoutEvent(deployment) + if err != nil { + return err + } + } + + return nil +} + func (ds *DeploymentService) AddRepository(repositoryRecord *models.Record, deployments []*models.Record) error { if repositoryRecord.Collection().Name != consts.TABLE_REPOSITORIES_NAME { return errors.New("repositoryRecord is not record of repositories collection") } - fmt.Println("adding repository", repositoryRecord.Id, "to deplyoments", deployments) - for _, depl := range deployments { depl.Set(consts.TABLE_DEPLOYMENTS_FIELD_REPOSITORIES, append(depl.Get(consts.TABLE_DEPLOYMENTS_FIELD_REPOSITORIES).([]string), repositoryRecord.Id)) - err := ds.dao.SaveRecord(depl) + err := ds.saveWithoutEvent(depl) if err != nil { return err } @@ -84,17 +99,22 @@ func (ds *DeploymentService) GetDeploymentsCollection() (*models.Collection, err return coll, nil } -func (ds *DeploymentService) createWithoutEvent(name string) (string, *models.Record, error) { +func (ds *DeploymentService) createWithoutEvent(name string) (*models.Record, error) { deploymentCollection, err := ds.GetDeploymentsCollection() if err != nil { - return "", nil, err + return nil, err } deploymentRecord := models.NewRecord(deploymentCollection) deploymentRecord.Set(consts.TABLE_DEPLOYMENTS_FIELD_NAME, name) - err = ds.dao.Clone().SaveRecord(deploymentRecord) + err = ds.saveWithoutEvent(deploymentRecord) + + return deploymentRecord, nil +} + +func (ds *DeploymentService) saveWithoutEvent(record *models.Record) error { - return deploymentRecord.Id, deploymentRecord, nil + return ds.dao.Clone().SaveRecord(record) } diff --git a/momentum-backend/momentum-core/momentum-services/keyvalue-service.go b/momentum-backend/momentum-core/momentum-services/keyvalue-service.go index 989a465..7a92d18 100644 --- a/momentum-backend/momentum-core/momentum-services/keyvalue-service.go +++ b/momentum-backend/momentum-core/momentum-services/keyvalue-service.go @@ -34,9 +34,7 @@ func (kvs *KeyValueService) SyncFile(n *tree.Node, parentArtifact *models.Record return errors.New("can only sync nodes of type file") } - kvs.syncChildren(n.Children, parentArtifact, n.NormalizedPath()) - - return nil + return kvs.syncChildren(n.Children, parentArtifact, n.NormalizedPath()) } func (kvs *KeyValueService) GetKeyValueCollection() (*models.Collection, error) { @@ -76,7 +74,12 @@ func (kvs *KeyValueService) syncChildren(children []*tree.Node, parentArtifact * childRecord.Set(consts.TABLE_KEYVALUE_FIELD_KEY, propertyPath) childRecord.Set(consts.TABLE_KEYVALUE_FIELD_VALUE, child.Value) - err = kvs.dao.Clone().SaveRecord(childRecord) + err = kvs.saveWithoutEvent(childRecord) + if err != nil { + break + } + + err = kvs.addParentArtifact(parentArtifact, childRecord) if err != nil { break } @@ -87,7 +90,7 @@ func (kvs *KeyValueService) syncChildren(children []*tree.Node, parentArtifact * } else { parentArtifact.Set(consts.GENERIC_FIELD_KEYVALUES, childRecord.Id) } - err = kvs.dao.Clone().SaveRecord(parentArtifact) + err = kvs.saveWithoutEvent(parentArtifact) if err != nil { break } @@ -96,3 +99,63 @@ func (kvs *KeyValueService) syncChildren(children []*tree.Node, parentArtifact * return err } + +func (kvs *KeyValueService) addParentArtifact(parentArtifact *models.Record, keyValues *models.Record) error { + + switch parentArtifact.Collection().Name { + case consts.TABLE_STAGES_NAME: + return kvs.addParentStage(parentArtifact, []*models.Record{keyValues}) + case consts.TABLE_DEPLOYMENTS_NAME: + return kvs.addParentDeployment(parentArtifact, []*models.Record{keyValues}) + default: + return errors.New("invalid parent record type") + } +} + +func (kvs *KeyValueService) addParentStage(stage *models.Record, keyValues []*models.Record) error { + + if stage.Collection().Name != consts.TABLE_STAGES_NAME { + return errors.New("parent stage must be record of collection stages") + } + + for _, kv := range keyValues { + + if kv.Collection().Name != consts.TABLE_KEYVALUE_NAME { + return errors.New("expected keyvalues record type to add parent stage") + } + + kv.Set(consts.TABLE_KEYVALUE_FIELD_PARENTSTAGE, stage.Id) + err := kvs.saveWithoutEvent(kv) + if err != nil { + return err + } + } + + return nil +} + +func (kvs *KeyValueService) addParentDeployment(deployment *models.Record, keyValues []*models.Record) error { + + if deployment.Collection().Name != consts.TABLE_DEPLOYMENTS_NAME { + return errors.New("parent deployment must be record of collection deploments") + } + + for _, kv := range keyValues { + + if kv.Collection().Name != consts.TABLE_KEYVALUE_NAME { + return errors.New("expected keyvalues record type to add parent deployment") + } + + kv.Set(consts.TABLE_KEYVALUE_FIELD_PARENTDEPLOYMENT, deployment.Id) + err := kvs.saveWithoutEvent(kv) + if err != nil { + return err + } + } + + return nil +} + +func (kvs *KeyValueService) saveWithoutEvent(record *models.Record) error { + return kvs.dao.Clone().SaveRecord(record) +} diff --git a/momentum-backend/momentum-core/momentum-services/repository-service.go b/momentum-backend/momentum-core/momentum-services/repository-service.go index aae737c..a5bbc73 100644 --- a/momentum-backend/momentum-core/momentum-services/repository-service.go +++ b/momentum-backend/momentum-core/momentum-services/repository-service.go @@ -31,22 +31,28 @@ func NewRepositoryService(dao *daos.Dao, appService *ApplicationService) *Reposi return repositoryService } -func (rs *RepositoryService) SyncRepositoryFromDisk(n *tree.Node, record *models.Record) (*models.Record, []*models.Record, error) { +func (rs *RepositoryService) SyncRepositoryFromDisk(n *tree.Node, record *models.Record) (*models.Record, []*models.Record, []*models.Record, error) { - appRecordIds, err := rs.applicationService.SyncApplicationsFromDisk(n, record) + appRecords, err := rs.applicationService.SyncApplicationsFromDisk(n, record) if err != nil { - return nil, nil, apis.NewApiError(500, err.Error(), nil) + return nil, nil, nil, apis.NewApiError(500, err.Error(), nil) } + appRecIds := make([]string, 0) + for _, appRec := range appRecords { + appRecIds = append(appRecIds, appRec.Id) + } + record.Set(consts.TABLE_REPOSITORIES_FIELD_APPLICATIONS, appRecIds) + // this complex loop is necessary because we need to know which deployments must add the repository // which is currently created, when the creation of the repository is finished. // TODO for a future refactoring: extract logic to specific services. deployments := make([]*models.Record, 0) - for _, applicationRecordId := range appRecordIds { + for _, applicationRecord := range appRecords { - appRecord, err := rs.dao.FindRecordById(consts.TABLE_APPLICATIONS_NAME, applicationRecordId) + appRecord, err := rs.dao.FindRecordById(consts.TABLE_APPLICATIONS_NAME, applicationRecord.Id) if err != nil { - return nil, nil, err + return nil, nil, nil, err } stagesIds := appRecord.Get(consts.TABLE_APPLICATIONS_FIELD_STAGES).([]string) @@ -54,7 +60,7 @@ func (rs *RepositoryService) SyncRepositoryFromDisk(n *tree.Node, record *models stageRec, err := rs.dao.FindRecordById(consts.TABLE_STAGES_NAME, stageId) if err != nil { - return nil, nil, err + return nil, nil, nil, err } deploymentIds := stageRec.Get(consts.TABLE_STAGES_FIELD_DEPLOYMENTS).([]string) @@ -62,7 +68,7 @@ func (rs *RepositoryService) SyncRepositoryFromDisk(n *tree.Node, record *models deploymentRec, err := rs.dao.FindRecordById(consts.TABLE_DEPLOYMENTS_NAME, deploymentId) if err != nil { - return nil, nil, err + return nil, nil, nil, err } deployments = append(deployments, deploymentRec) @@ -70,7 +76,7 @@ func (rs *RepositoryService) SyncRepositoryFromDisk(n *tree.Node, record *models } } - return record, deployments, nil + return record, appRecords, deployments, nil } func (rs *RepositoryService) FindForName(name string) (*models.Record, error) { diff --git a/momentum-backend/momentum-core/momentum-services/stage-service.go b/momentum-backend/momentum-core/momentum-services/stage-service.go index 88709d7..72dbd10 100644 --- a/momentum-backend/momentum-core/momentum-services/stage-service.go +++ b/momentum-backend/momentum-core/momentum-services/stage-service.go @@ -1,6 +1,7 @@ package momentumservices import ( + "errors" consts "momentum/momentum-core/momentum-config" tree "momentum/momentum-core/momentum-tree" @@ -28,18 +29,20 @@ func NewStageService(dao *daos.Dao, deploymentService *DeploymentService, keyVal return stageService } -func (ss *StageService) SyncStagesFromDisk(n *tree.Node) ([]string, error) { +func (ss *StageService) SyncStagesFromDisk(n *tree.Node) ([]*models.Record, error) { stages := n.AllStages() - stageIds := make([]string, 0) + stageRecords := make([]*models.Record, 0) + var lastStageNode *tree.Node = nil + var lastStage *models.Record = nil for _, stage := range stages { - deploymentIds, err := ss.deploymentService.SyncDeploymentsFromDisk(n) + deployments, err := ss.deploymentService.SyncDeploymentsFromDisk(n) if err != nil { return nil, err } - stageId, stageRecord, err := ss.createWithoutEvent(stage.NormalizedPath(), deploymentIds) + stageRecord, err := ss.createWithoutEvent(stage.NormalizedPath(), deployments) if err != nil { return nil, err } @@ -47,17 +50,65 @@ func (ss *StageService) SyncStagesFromDisk(n *tree.Node) ([]string, error) { if stage.Kind == tree.Directory { stageFiles := stage.Files() for _, f := range stageFiles { - err = ss.keyValueService.SyncFile(f, stageRecord) + + err := ss.keyValueService.SyncFile(f, stageRecord) if err != nil { return nil, err } } } - stageIds = append(stageIds, stageId) + err = ss.deploymentService.AddParentStage(stageRecord, deployments) + if err != nil { + return nil, err + } + + if lastStage != nil && lastStageNode != nil && stage.Parent != nil && stage.Parent.IsStage() && lastStageNode.FullPath() == stage.Parent.FullPath() { + err = ss.addParentStage(lastStage, stageRecord) + if err != nil { + return nil, err + } + } + + stageRecords = append(stageRecords, stageRecord) + lastStage = stageRecord + lastStageNode = stage } - return stageIds, nil + return stageRecords, nil +} + +func (ss *StageService) AddParentApplication(stageIds []string, app *models.Record) error { + + if app.Collection().Name != consts.TABLE_APPLICATIONS_NAME { + return errors.New("can only process records of applications collection") + } + + for _, stageId := range stageIds { + + stage, err := ss.dao.FindRecordById(consts.TABLE_STAGES_NAME, stageId) + if err != nil { + return err + } + + stage.Set(consts.TABLE_STAGES_FIELD_PARENTAPPLICATION, app.Id) + err = ss.saveWithoutEvent(stage) + if err != nil { + return err + } + } + + return nil +} + +func (ss *StageService) addParentStage(parent *models.Record, child *models.Record) error { + + if parent.Collection().Name != consts.TABLE_STAGES_NAME || child.Collection().Name != consts.TABLE_STAGES_NAME { + return errors.New("can only process records of stages collection") + } + + child.Set(consts.TABLE_STAGES_FIELD_PARENTSTAGE, parent.Id) + return ss.saveWithoutEvent(child) } func (ss *StageService) GetStagesCollection() (*models.Collection, error) { @@ -65,18 +116,23 @@ func (ss *StageService) GetStagesCollection() (*models.Collection, error) { return ss.dao.FindCollectionByNameOrId(consts.TABLE_STAGES_NAME) } -func (ss *StageService) createWithoutEvent(name string, deploymentIds []string) (string, *models.Record, error) { +func (ss *StageService) createWithoutEvent(name string, deploymentIds []*models.Record) (*models.Record, error) { stageCollection, err := ss.GetStagesCollection() if err != nil { - return "", nil, err + return nil, err } stageRecord := models.NewRecord(stageCollection) stageRecord.Set(consts.TABLE_STAGES_FIELD_NAME, name) stageRecord.Set(consts.TABLE_STAGES_FIELD_DEPLOYMENTS, deploymentIds) - err = ss.dao.Clone().SaveRecord(stageRecord) + err = ss.saveWithoutEvent(stageRecord) + + return stageRecord, err +} + +func (ss *StageService) saveWithoutEvent(stage *models.Record) error { - return stageRecord.Id, stageRecord, err + return ss.dao.Clone().SaveRecord(stage) } diff --git a/momentum-backend/momentum-core/momentum-tree/momentum-tree.go b/momentum-backend/momentum-core/momentum-tree/momentum-tree.go index 6523eb3..7b9cd64 100644 --- a/momentum-backend/momentum-core/momentum-tree/momentum-tree.go +++ b/momentum-backend/momentum-core/momentum-tree/momentum-tree.go @@ -26,6 +26,28 @@ func (n *Node) AllStages() []*Node { return stgs } +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() diff --git a/momentum-backend/momentum-core/momentum-tree/tree.go b/momentum-backend/momentum-core/momentum-tree/tree.go index 6b93f17..7138f3c 100644 --- a/momentum-backend/momentum-core/momentum-tree/tree.go +++ b/momentum-backend/momentum-core/momentum-tree/tree.go @@ -139,14 +139,14 @@ func (n *Node) Write() error { } func (n *Node) IsRoot() bool { - return n.Parent == nil + 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 = n.Parent + current = current.Parent } return current } diff --git a/momentum-backend/pb_migrations/1686725242_updated_deployments.js b/momentum-backend/pb_migrations/1686725242_updated_deployments.js new file mode 100644 index 0000000..4bd4166 --- /dev/null +++ b/momentum-backend/pb_migrations/1686725242_updated_deployments.js @@ -0,0 +1,51 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("ka4cvffqmuxczw7") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "eb0jvo3o", + "name": "status", + "type": "select", + "required": false, + "unique": false, + "options": { + "maxSelect": 1, + "values": [ + "RUNNING", + "FAILED", + "PENDING", + "UNKNOWN" + ] + } + })) + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "x8gggfpu", + "name": "namespace", + "type": "text", + "required": false, + "unique": false, + "options": { + "min": null, + "max": null, + "pattern": "" + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("ka4cvffqmuxczw7") + + // remove + collection.schema.removeField("eb0jvo3o") + + // remove + collection.schema.removeField("x8gggfpu") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686895367_updated_deployments.js b/momentum-backend/pb_migrations/1686895367_updated_deployments.js new file mode 100644 index 0000000..14364d5 --- /dev/null +++ b/momentum-backend/pb_migrations/1686895367_updated_deployments.js @@ -0,0 +1,31 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("ka4cvffqmuxczw7") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "juvm3tmo", + "name": "parentStage", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "f8w5oambwthngxo", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": [] + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("ka4cvffqmuxczw7") + + // remove + collection.schema.removeField("juvm3tmo") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686895477_updated_stages.js b/momentum-backend/pb_migrations/1686895477_updated_stages.js new file mode 100644 index 0000000..5a832a5 --- /dev/null +++ b/momentum-backend/pb_migrations/1686895477_updated_stages.js @@ -0,0 +1,31 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("f8w5oambwthngxo") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "0zk57ok0", + "name": "parentApplication", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "wf40hpyi2wvpb7y", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": [] + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("f8w5oambwthngxo") + + // remove + collection.schema.removeField("0zk57ok0") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686895504_updated_applications.js b/momentum-backend/pb_migrations/1686895504_updated_applications.js new file mode 100644 index 0000000..771ea9e --- /dev/null +++ b/momentum-backend/pb_migrations/1686895504_updated_applications.js @@ -0,0 +1,31 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("wf40hpyi2wvpb7y") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "cc62mdka", + "name": "parentRepository", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "os5ld33mgj3dj7b", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": [] + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("wf40hpyi2wvpb7y") + + // remove + collection.schema.removeField("cc62mdka") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686896254_updated_keyValues.js b/momentum-backend/pb_migrations/1686896254_updated_keyValues.js new file mode 100644 index 0000000..4823f98 --- /dev/null +++ b/momentum-backend/pb_migrations/1686896254_updated_keyValues.js @@ -0,0 +1,51 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("zp90bz3osxtcevq") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "tmctz4dv", + "name": "parentStage", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "f8w5oambwthngxo", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": [] + } + })) + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "alxyew1k", + "name": "parentDeployment", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "ka4cvffqmuxczw7", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": [] + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("zp90bz3osxtcevq") + + // remove + collection.schema.removeField("tmctz4dv") + + // remove + collection.schema.removeField("alxyew1k") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686915608_updated_repositories.js b/momentum-backend/pb_migrations/1686915608_updated_repositories.js new file mode 100644 index 0000000..5393cc7 --- /dev/null +++ b/momentum-backend/pb_migrations/1686915608_updated_repositories.js @@ -0,0 +1,31 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("os5ld33mgj3dj7b") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "nmmegt3m", + "name": "applications", + "type": "relation", + "required": false, + "unique": false, + "options": { + "collectionId": "wf40hpyi2wvpb7y", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": null, + "displayFields": [] + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("os5ld33mgj3dj7b") + + // remove + collection.schema.removeField("nmmegt3m") + + return dao.saveCollection(collection) +}) diff --git a/momentum-backend/pb_migrations/1686919800_updated_repositories.js b/momentum-backend/pb_migrations/1686919800_updated_repositories.js new file mode 100644 index 0000000..bedda1d --- /dev/null +++ b/momentum-backend/pb_migrations/1686919800_updated_repositories.js @@ -0,0 +1,33 @@ +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("os5ld33mgj3dj7b") + + // remove + collection.schema.removeField("r3jb5rhz") + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("os5ld33mgj3dj7b") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "r3jb5rhz", + "name": "status", + "type": "select", + "required": true, + "unique": false, + "options": { + "maxSelect": 1, + "values": [ + "PENDING", + "SYNCING", + "UP-TO-DATE", + "ERROR" + ] + } + })) + + return dao.saveCollection(collection) +})