686 lines
19 KiB
Go
686 lines
19 KiB
Go
package gitops
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/dgrijalva/jwt-go"
|
|
"github.com/ghodss/yaml"
|
|
"github.com/go-git/go-git/v5"
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
"github.com/go-git/go-git/v5/plumbing/object"
|
|
"github.com/go-git/go-git/v5/plumbing/transport"
|
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
|
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/tidwall/gjson"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
ssh2 "golang.org/x/crypto/ssh"
|
|
|
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/graph/model"
|
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/authorization"
|
|
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/chaos-workflow/ops"
|
|
store "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/data-store"
|
|
dbOperationsGitOps "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/gitops"
|
|
dbSchemaGitOps "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/gitops"
|
|
dbOperationsWorkflow "github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/database/mongodb/workflow"
|
|
)
|
|
|
|
// GitConfig structure for the GitOps settings
|
|
type GitConfig struct {
|
|
ProjectID string
|
|
RepositoryURL string
|
|
LocalPath string
|
|
RemoteName string
|
|
Branch string
|
|
LatestCommit string
|
|
UserName *string
|
|
Password *string
|
|
AuthType model.AuthType
|
|
Token *string
|
|
SSHPrivateKey *string
|
|
}
|
|
|
|
type GitUser struct {
|
|
username string
|
|
email string
|
|
}
|
|
|
|
const (
|
|
DefaultPath = "/tmp/gitops/"
|
|
ProjectDataPath = "litmus"
|
|
)
|
|
|
|
func GitUserFromContext(ctx context.Context) GitUser {
|
|
defaultUser := GitUser{
|
|
username: "gitops@litmus-chaos",
|
|
email: "gitops@litmus.chaos",
|
|
}
|
|
if ctx == nil {
|
|
return defaultUser
|
|
}
|
|
userClaims := ctx.Value(authorization.UserClaim)
|
|
if userClaims == nil {
|
|
return defaultUser
|
|
}
|
|
if _, ok := userClaims.(jwt.MapClaims)["email"]; !ok {
|
|
return GitUser{
|
|
username: userClaims.(jwt.MapClaims)["username"].(string) + "@litmus-chaos",
|
|
email: userClaims.(jwt.MapClaims)["username"].(string) + "@litmus-chaos",
|
|
}
|
|
}
|
|
return GitUser{
|
|
username: userClaims.(jwt.MapClaims)["username"].(string) + "@litmus-chaos",
|
|
email: userClaims.(jwt.MapClaims)["email"].(string),
|
|
}
|
|
}
|
|
|
|
// GetGitOpsConfig is used for constructing the GitConfig from dbSchemaGitOps.GitConfigDB
|
|
func GetGitOpsConfig(repoData dbSchemaGitOps.GitConfigDB) GitConfig {
|
|
gitConfig := GitConfig{
|
|
ProjectID: repoData.ProjectID,
|
|
RepositoryURL: repoData.RepositoryURL,
|
|
RemoteName: "origin",
|
|
Branch: repoData.Branch,
|
|
LocalPath: DefaultPath + repoData.ProjectID,
|
|
LatestCommit: repoData.LatestCommit,
|
|
UserName: repoData.UserName,
|
|
Password: repoData.Password,
|
|
AuthType: repoData.AuthType,
|
|
Token: repoData.Token,
|
|
SSHPrivateKey: repoData.SSHPrivateKey,
|
|
}
|
|
|
|
return gitConfig
|
|
}
|
|
|
|
// setupGitRepo helps clones and sets up the repo for gitops
|
|
func (c GitConfig) setupGitRepo(user GitUser) error {
|
|
projectPath := c.LocalPath + "/" + ProjectDataPath + "/" + c.ProjectID
|
|
|
|
// clone repo
|
|
_, err := c.GitClone()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// check if project dir already present in repo
|
|
exists, err := PathExists(projectPath + "/.info")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
gitInfo := map[string]string{"projectID": c.ProjectID, "revision": "1"}
|
|
if exists {
|
|
data, err := ioutil.ReadFile(projectPath + "/.info")
|
|
if err != nil {
|
|
return errors.New("can't read existing git info file " + err.Error())
|
|
}
|
|
err = json.Unmarshal(data, &gitInfo)
|
|
if err != nil {
|
|
return errors.New("can't read existing git info file " + err.Error())
|
|
}
|
|
newRev, err := strconv.Atoi(gitInfo["revision"])
|
|
if err != nil {
|
|
return errors.New("can't read existing git info file[failed to parse revision] " + err.Error())
|
|
}
|
|
gitInfo["revision"] = strconv.Itoa(newRev + 1)
|
|
} else {
|
|
// create project dir and add config if not already present
|
|
err = os.MkdirAll(projectPath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
data, err := json.Marshal(gitInfo)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = ioutil.WriteFile(projectPath+"/.info", data, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// commit and push
|
|
_, err = c.GitCommit(user, "Setup Litmus Chaos GitOps for Project :"+c.ProjectID, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return c.GitPush()
|
|
}
|
|
|
|
// GitClone clones the repo
|
|
func (c GitConfig) GitClone() (*git.Repository, error) {
|
|
// clean the local path
|
|
err := os.RemoveAll(c.LocalPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
auth, err := c.getAuthMethod()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return git.PlainClone(c.LocalPath, false, &git.CloneOptions{
|
|
Auth: auth,
|
|
URL: c.RepositoryURL,
|
|
Progress: os.Stdout,
|
|
ReferenceName: plumbing.NewBranchReferenceName(c.Branch),
|
|
SingleBranch: true,
|
|
})
|
|
}
|
|
|
|
// getAuthMethod returns the AuthMethod instance required for the current repo access [read/writes]
|
|
func (c GitConfig) getAuthMethod() (transport.AuthMethod, error) {
|
|
|
|
switch c.AuthType {
|
|
|
|
case model.AuthTypeToken:
|
|
return &http.BasicAuth{
|
|
Username: "litmus", // this can be anything except an empty string
|
|
Password: *c.Token,
|
|
}, nil
|
|
|
|
case model.AuthTypeBasic:
|
|
return &http.BasicAuth{
|
|
Username: *c.UserName,
|
|
Password: *c.Password,
|
|
}, nil
|
|
|
|
case model.AuthTypeSSH:
|
|
publicKey, err := ssh.NewPublicKeys("git", []byte(*c.SSHPrivateKey), "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
publicKey.HostKeyCallback = ssh2.InsecureIgnoreHostKey()
|
|
return publicKey, nil
|
|
|
|
case model.AuthTypeNone:
|
|
return nil, nil
|
|
|
|
default:
|
|
return nil, errors.New("No Matching Auth Type Found")
|
|
}
|
|
}
|
|
|
|
// UnsafeGitPull executes git pull after a hard reset when uncommited changes are present in repo. Not safe.
|
|
func (c GitConfig) UnsafeGitPull() error {
|
|
cleanStatus, err := c.GitGetStatus()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
log.WithFields(log.Fields{"CleanStatus": cleanStatus}).Info("Executed GitGetStatus()... ")
|
|
if !cleanStatus {
|
|
log.Print("Resetting Repo...: " + c.ProjectID)
|
|
return c.handlerForDirtyStatus()
|
|
}
|
|
return c.GitPull()
|
|
}
|
|
|
|
// GitGetStatus executes "git get status --porcelain" for the provided Repository Path,
|
|
// returns true if the repository is clean
|
|
// and false if the repository is dirty
|
|
func (c GitConfig) GitGetStatus() (bool, error) {
|
|
_, workTree, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return true, err
|
|
}
|
|
status, err := workTree.Status()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return status.IsClean(), nil
|
|
}
|
|
|
|
// getRepositoryWorktreeReference returns the git.Repository and git.Worktree instanes for the repo
|
|
func (c GitConfig) getRepositoryWorktreeReference() (*git.Repository, *git.Worktree, error) {
|
|
repo, err := git.PlainOpen(c.LocalPath)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
workTree, err := repo.Worktree()
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return repo, workTree, nil
|
|
}
|
|
|
|
// handlerForDirtyStatus calls relative functions if the GitGetStatus gives a clean status as a result
|
|
func (c GitConfig) handlerForDirtyStatus() error {
|
|
if err := c.GitHardReset(); err != nil {
|
|
return err
|
|
}
|
|
return c.GitPull()
|
|
}
|
|
|
|
// GitHardReset executes "git reset --hard HEAD" in provided Repository Path
|
|
func (c GitConfig) GitHardReset() error {
|
|
_, workTree, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if workTree.Reset(&git.ResetOptions{Mode: git.HardReset}) != nil {
|
|
return fmt.Errorf("error in executing Reset: %s", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GitPull updates the repository in provided Path
|
|
func (c GitConfig) GitPull() error {
|
|
_, workTree, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
auth, err := c.getAuthMethod()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = workTree.Pull(&git.PullOptions{
|
|
Auth: auth,
|
|
RemoteName: c.RemoteName,
|
|
ReferenceName: plumbing.NewBranchReferenceName(c.Branch),
|
|
SingleBranch: true,
|
|
})
|
|
if err != nil && err != git.NoErrAlreadyUpToDate {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GitCheckout changes the current active branch to specified branch in GitConfig
|
|
func (c GitConfig) GitCheckout() error {
|
|
r, w, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = r.Storer.Reference(plumbing.NewBranchReferenceName(c.Branch))
|
|
create := true
|
|
log.Print(err)
|
|
if err == nil {
|
|
create = false
|
|
}
|
|
return w.Checkout(&git.CheckoutOptions{
|
|
Branch: plumbing.NewBranchReferenceName(c.Branch),
|
|
Create: create,
|
|
})
|
|
}
|
|
|
|
// GitPush pushes the current changes to remote set in GitConfig, always needs auth credentials
|
|
func (c GitConfig) GitPush() error {
|
|
if c.AuthType == model.AuthTypeNone {
|
|
return errors.New("cannot write/push without credentials, auth type = none")
|
|
}
|
|
|
|
r, _, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
auth, err := c.getAuthMethod()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = r.Push(&git.PushOptions{
|
|
RemoteName: c.RemoteName,
|
|
Auth: auth,
|
|
Progress: os.Stdout,
|
|
})
|
|
if err == git.NoErrAlreadyUpToDate {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
// GitCommit saves the changes in the repo and commits them with the message provided
|
|
func (c GitConfig) GitCommit(user GitUser, message string, deleteFile *string) (string, error) {
|
|
_, w, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if deleteFile == nil {
|
|
_, err = w.Add("./litmus/" + c.ProjectID + "/")
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
} else {
|
|
_, err := w.Remove(*deleteFile)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
hash, err := w.Commit(message, &git.CommitOptions{
|
|
Author: &object.Signature{
|
|
Name: user.username,
|
|
Email: user.email,
|
|
When: time.Now(),
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return hash.String(), nil
|
|
}
|
|
|
|
// GetChanges returns the LatestCommit and list of files changed(since previous LatestCommit) in the project directory mentioned in GitConfig
|
|
func (c GitConfig) GetChanges() (string, map[string]int, error) {
|
|
path := ProjectDataPath + "/" + c.ProjectID + "/"
|
|
|
|
r, _, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
var knownCommit *object.Commit = nil
|
|
if c.LatestCommit != "" {
|
|
knownCommit, err = r.CommitObject(plumbing.NewHash(c.LatestCommit))
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
}
|
|
visited := map[string]int{}
|
|
lastFile := ""
|
|
|
|
commitIter, err := r.Log(&git.LogOptions{
|
|
PathFilter: func(file string) bool {
|
|
if (strings.HasSuffix(path, "/") && strings.HasPrefix(file, path)) || (path == file) {
|
|
visited[file] += 1
|
|
lastFile = file
|
|
return true
|
|
}
|
|
return false
|
|
},
|
|
Order: git.LogOrderCommitterTime,
|
|
})
|
|
if err != nil {
|
|
return "", nil, errors.New("Failed to get commit Iterator :" + err.Error())
|
|
}
|
|
|
|
commit, err := commitIter.Next()
|
|
if err != nil && err != io.EOF {
|
|
return "", nil, err
|
|
}
|
|
if commit != nil {
|
|
c.LatestCommit = commit.Hash.String()
|
|
}
|
|
|
|
for err != io.EOF && commit != nil {
|
|
if knownCommit != nil {
|
|
ancestor, er := commit.IsAncestor(knownCommit)
|
|
if er != nil {
|
|
return "", nil, er
|
|
}
|
|
if knownCommit.Hash == commit.Hash || ancestor {
|
|
break
|
|
}
|
|
}
|
|
commit, err = commitIter.Next()
|
|
if err != nil && err != io.EOF {
|
|
return "", nil, err
|
|
}
|
|
}
|
|
if err != io.EOF && visited[lastFile] == 1 {
|
|
delete(visited, lastFile)
|
|
}
|
|
return c.LatestCommit, visited, nil
|
|
}
|
|
|
|
// GetLatestCommitHash returns the latest commit hash in the local repo for the project directory
|
|
func (c GitConfig) GetLatestCommitHash() (string, error) {
|
|
path := ProjectDataPath + "/" + c.ProjectID + "/"
|
|
r, _, err := c.getRepositoryWorktreeReference()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
commitIter, err := r.Log(&git.LogOptions{
|
|
PathFilter: func(file string) bool {
|
|
return (strings.HasSuffix(path, "/") && strings.HasPrefix(file, path)) || (path == file)
|
|
},
|
|
Order: git.LogOrderCommitterTime,
|
|
})
|
|
if err != nil {
|
|
return "", errors.New("Failed to get latest commit hash :" + err.Error())
|
|
}
|
|
commit, err := commitIter.Next()
|
|
|
|
if err != nil {
|
|
return "", errors.New("Failed to get latest commit hash:" + err.Error())
|
|
}
|
|
return commit.Hash.String(), nil
|
|
}
|
|
|
|
// SetupGitOps clones and sets up the repo for gitops and returns the LatestCommit
|
|
func SetupGitOps(user GitUser, gitConfig GitConfig) (string, error) {
|
|
err := gitConfig.setupGitRepo(user)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
commitHash, err := gitConfig.GetLatestCommitHash()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return commitHash, err
|
|
}
|
|
|
|
// SyncDBToGit syncs the DB with the GitRepo for the project
|
|
func SyncDBToGit(ctx context.Context, config GitConfig) error {
|
|
repositoryExists, err := PathExists(config.LocalPath)
|
|
if err != nil {
|
|
return fmt.Errorf("Error while checking repo exists, err: %s", err)
|
|
}
|
|
if !repositoryExists {
|
|
err = config.setupGitRepo(GitUserFromContext(ctx))
|
|
} else {
|
|
err = config.GitPull()
|
|
if err != nil {
|
|
return errors.New("Error syncing DB : " + err.Error())
|
|
}
|
|
}
|
|
latestCommit, files, err := config.GetChanges()
|
|
if err != nil {
|
|
return errors.New("Error Getting File Changes : " + err.Error())
|
|
}
|
|
if latestCommit == config.LatestCommit {
|
|
return nil
|
|
}
|
|
log.Print(latestCommit, " ", config.LatestCommit, "File Changes: ", files)
|
|
newWorkflows := false
|
|
for file := range files {
|
|
if !strings.HasSuffix(file, ".yaml") {
|
|
continue
|
|
}
|
|
// check if file was deleted or not
|
|
exists, err := PathExists(config.LocalPath + "/" + file)
|
|
if err != nil {
|
|
return errors.New("Error checking file in local repo : " + file + " | " + err.Error())
|
|
}
|
|
if !exists {
|
|
err = deleteWorkflow(file, config)
|
|
if err != nil {
|
|
log.Print("Error while deleting workflow db entry : " + file + " | " + err.Error())
|
|
continue
|
|
}
|
|
continue
|
|
}
|
|
// read changes [new additions/updates]
|
|
data, err := ioutil.ReadFile(config.LocalPath + "/" + file)
|
|
if err != nil {
|
|
log.Print("Error reading data from git file : " + file + " | " + err.Error())
|
|
continue
|
|
}
|
|
data, err = yaml.YAMLToJSON(data)
|
|
if err != nil {
|
|
log.Print("Error unmarshalling data from git file : " + file + " | " + err.Error())
|
|
continue
|
|
}
|
|
wfID := gjson.Get(string(data), "metadata.labels.workflow_id").String()
|
|
kind := strings.ToLower(gjson.Get(string(data), "kind").String())
|
|
if kind != "cronworkflow" && kind != "workflow" && kind != "chaosengine" {
|
|
continue
|
|
}
|
|
|
|
log.Print("WFID in changed File :", wfID)
|
|
if wfID == "" {
|
|
log.Print("New Workflow pushed to git : " + file)
|
|
flag, err := createWorkflow(string(data), file, config)
|
|
if err != nil {
|
|
log.Print("Error while creating new workflow db entry : " + file + " | " + err.Error())
|
|
continue
|
|
}
|
|
if flag {
|
|
newWorkflows = true
|
|
}
|
|
} else {
|
|
err = updateWorkflow(string(data), wfID, file, config)
|
|
if err != nil {
|
|
log.Print("Error while creating new workflow db entry : " + file + " | " + err.Error())
|
|
continue
|
|
}
|
|
}
|
|
|
|
}
|
|
// push workflows with workflow_id added
|
|
if newWorkflows {
|
|
latestCommit, err = config.GitCommit(GitUserFromContext(ctx), "Updated New Workflows", nil)
|
|
if err != nil {
|
|
return errors.New("Cannot commit workflows to git : " + err.Error())
|
|
}
|
|
err = config.GitPush()
|
|
if err != nil {
|
|
return errors.New("Cannot push workflows to git : " + err.Error())
|
|
}
|
|
}
|
|
|
|
query := bson.D{{"project_id", config.ProjectID}}
|
|
update := bson.D{{"$set", bson.D{{"latest_commit", latestCommit}}}}
|
|
|
|
if ctx == nil {
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
defer cancel()
|
|
err = dbOperationsGitOps.UpdateGitConfig(ctx, query, update)
|
|
} else {
|
|
err = dbOperationsGitOps.UpdateGitConfig(ctx, query, update)
|
|
}
|
|
|
|
if err != nil {
|
|
return errors.New("Failed to update git config : " + err.Error())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// createWorkflow helps in creating a new workflow during the SyncDBToGit operation
|
|
func createWorkflow(data, file string, config GitConfig) (bool, error) {
|
|
_, fileName := filepath.Split(file)
|
|
fileName = strings.Replace(fileName, ".yaml", "", -1)
|
|
wfName := gjson.Get(data, "metadata.name").String()
|
|
clusterID := gjson.Get(data, "metadata.labels.cluster_id").String()
|
|
log.Print("Workflow Details | wf_name: ", wfName, " cluster_id: ", clusterID)
|
|
if wfName == "" || clusterID == "" {
|
|
return false, nil
|
|
}
|
|
if fileName != wfName {
|
|
return false, errors.New("file name doesn't match workflow name")
|
|
}
|
|
workflow := model.ChaosWorkFlowInput{
|
|
WorkflowID: nil,
|
|
WorkflowManifest: data,
|
|
CronSyntax: "",
|
|
WorkflowName: wfName,
|
|
WorkflowDescription: "",
|
|
Weightages: nil,
|
|
IsCustomWorkflow: true,
|
|
ProjectID: config.ProjectID,
|
|
ClusterID: clusterID,
|
|
}
|
|
input, wfType, err := ops.ProcessWorkflow(&workflow)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
err = ops.ProcessWorkflowCreation(input, wfType, store.Store)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
workflowPath := config.LocalPath + "/" + file
|
|
|
|
yamlData, err := yaml.JSONToYAML([]byte(input.WorkflowManifest))
|
|
if err != nil {
|
|
return false, errors.New("Cannot convert manifest to yaml : " + err.Error())
|
|
}
|
|
|
|
err = ioutil.WriteFile(workflowPath, yamlData, 0644)
|
|
if err != nil {
|
|
return false, errors.New("Cannot write workflow to git : " + err.Error())
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// updateWorkflow helps in updating a existing workflow during the SyncDBToGit operation
|
|
func updateWorkflow(data, wfID, file string, config GitConfig) error {
|
|
_, fileName := filepath.Split(file)
|
|
fileName = strings.Replace(fileName, ".yaml", "", -1)
|
|
wfName := gjson.Get(data, "metadata.name").String()
|
|
clusterID := gjson.Get(data, "metadata.labels.cluster_id").String()
|
|
log.Print("Workflow Details | wf_name: ", wfName, " cluster_id: ", clusterID)
|
|
if wfName == "" || clusterID == "" {
|
|
log.Print("Cannot Update workflow missing workflow name or cluster id")
|
|
return nil
|
|
}
|
|
|
|
if fileName != wfName {
|
|
return errors.New("file name doesn't match workflow name")
|
|
}
|
|
|
|
workflow, err := dbOperationsWorkflow.GetWorkflows(bson.D{{"workflow_id", wfID}, {"project_id", config.ProjectID}, {"isRemoved", false}})
|
|
if len(workflow) == 0 {
|
|
return errors.New("No such workflow found : " + wfID)
|
|
}
|
|
|
|
if clusterID != workflow[0].ClusterID {
|
|
log.Print("Cannot change cluster id for existing workflow")
|
|
return nil
|
|
}
|
|
|
|
workflowData := model.ChaosWorkFlowInput{
|
|
WorkflowID: &workflow[0].WorkflowID,
|
|
WorkflowManifest: data,
|
|
CronSyntax: workflow[0].CronSyntax,
|
|
WorkflowName: wfName,
|
|
WorkflowDescription: workflow[0].WorkflowDescription,
|
|
Weightages: nil,
|
|
IsCustomWorkflow: workflow[0].IsCustomWorkflow,
|
|
ProjectID: config.ProjectID,
|
|
ClusterID: workflow[0].ClusterID,
|
|
}
|
|
|
|
input, wfType, err := ops.ProcessWorkflow(&workflowData)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return ops.ProcessWorkflowUpdate(input, wfType, store.Store)
|
|
|
|
}
|
|
|
|
// deleteWorkflow helps in deleting a workflow from DB during the SyncDBToGit operation
|
|
func deleteWorkflow(file string, config GitConfig) error {
|
|
_, fileName := filepath.Split(file)
|
|
fileName = strings.Replace(fileName, ".yaml", "", -1)
|
|
|
|
query := bson.D{{"workflow_name", fileName}, {"project_id", config.ProjectID}}
|
|
workflow, err := dbOperationsWorkflow.GetWorkflow(query)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return ops.ProcessWorkflowDelete(query, workflow, store.Store)
|
|
}
|