Merge pull request #2497 from gdsoumya/gitops-updates

Added edit gitops config feature and fixed auth server bug
This commit is contained in:
Soumya Ghosh Dastidar 2021-03-04 14:48:07 +05:30 committed by GitHub
commit 2d2ea63899
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 201 additions and 35 deletions

View File

@ -15,4 +15,4 @@ require (
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
)
)

View File

@ -45,6 +45,7 @@ const (
var DefaultUser = &UserCredentials{
UserName: types.DefaultUserName,
Password: types.DefaultUserPassword,
Role: RoleAdmin,
}
//PublicUserInfo displays the information of the user that is publicly available

View File

@ -600,7 +600,6 @@ github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z
github.com/litmuschaos/chaos-operator v0.0.0-20210126054859-85bb0ad85bfa h1:lBEvg10ZPndmBUMtVaMRVCqeKnKYmjtRSg2SF4iTQ7o=
github.com/litmuschaos/chaos-operator v0.0.0-20210126054859-85bb0ad85bfa/go.mod h1:Z2GpYjqXwFd8bx+kv58YEQFxynx1v9PMGCGTQFRVnFQ=
github.com/litmuschaos/elves v0.0.0-20201107015738-552d74669e3c/go.mod h1:DsbHGNUq/78NZozWVVI9Q6eBei4I+JjlkkD5aibJ3MQ=
github.com/litmuschaos/litmus v0.0.0-20210302122130-471654357d2b h1:BlwWoDHEvYh8RvBBWOmPrA6RgAs+d6ujxie8RU5ZgPk=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lpabon/godbc v0.1.1/go.mod h1:Jo9QV0cf3U6jZABgiJ2skINAXb9j8m51r07g4KI92ZA=
github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04=

View File

@ -218,6 +218,7 @@ type ComplexityRoot struct {
UpdateChaosWorkflow func(childComplexity int, input *model.ChaosWorkFlowInput) int
UpdateDashboard func(childComplexity int, dashboard *model.UpdataDBInput) int
UpdateDataSource func(childComplexity int, datasource model.DSInput) int
UpdateGitOps func(childComplexity int, config model.GitConfig) int
UpdateMyHub func(childComplexity int, myhubInput model.UpdateMyHub, projectID string) int
UpdatePanel func(childComplexity int, panelInput []*model.Panel) int
UpdateUser func(childComplexity int, user model.UpdateUserInput) int
@ -501,6 +502,7 @@ type MutationResolver interface {
GitopsNotifer(ctx context.Context, clusterInfo model.ClusterIdentity, workflowID string) (string, error)
EnableGitOps(ctx context.Context, config model.GitConfig) (bool, error)
DisableGitOps(ctx context.Context, projectID string) (bool, error)
UpdateGitOps(ctx context.Context, config model.GitConfig) (bool, error)
CreateDataSource(ctx context.Context, datasource *model.DSInput) (*model.DSResponse, error)
CreateDashBoard(ctx context.Context, dashboard *model.CreateDBInput) (string, error)
UpdateDataSource(ctx context.Context, datasource model.DSInput) (*model.DSResponse, error)
@ -1543,6 +1545,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return e.complexity.Mutation.UpdateDataSource(childComplexity, args["datasource"].(model.DSInput)), true
case "Mutation.updateGitOps":
if e.complexity.Mutation.UpdateGitOps == nil {
break
}
args, err := ec.field_Mutation_updateGitOps_args(context.TODO(), rawArgs)
if err != nil {
return 0, false
}
return e.complexity.Mutation.UpdateGitOps(childComplexity, args["config"].(model.GitConfig)), true
case "Mutation.updateMyHub":
if e.complexity.Mutation.UpdateMyHub == nil {
break
@ -3664,8 +3678,7 @@ type Mutation {
userClusterReg(clusterInput: ClusterInput!): clusterRegResponse! @authorized
#It is used to create chaosworkflow
createChaosWorkFlow(input: ChaosWorkFlowInput!): ChaosWorkFlowResponse!
@authorized
createChaosWorkFlow(input: ChaosWorkFlowInput!): ChaosWorkFlowResponse! @authorized
reRunChaosWorkFlow(workflowID: String!): String! @authorized
@ -3706,8 +3719,7 @@ type Mutation {
syncHub(id: ID!): [MyHubStatus!]! @authorized
updateChaosWorkflow(input: ChaosWorkFlowInput): ChaosWorkFlowResponse!
@authorized
updateChaosWorkflow(input: ChaosWorkFlowInput): ChaosWorkFlowResponse! @authorized
deleteClusterReg(cluster_id: String!): String! @authorized
@ -3725,6 +3737,8 @@ type Mutation {
disableGitOps(project_id: String!): Boolean! @authorized
updateGitOps(config: GitConfig!): Boolean! @authorized
# Analytics
createDataSource(datasource: DSInput): DSResponse @authorized
@ -4207,6 +4221,20 @@ func (ec *executionContext) field_Mutation_updateDataSource_args(ctx context.Con
return args, nil
}
func (ec *executionContext) field_Mutation_updateGitOps_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
var arg0 model.GitConfig
if tmp, ok := rawArgs["config"]; ok {
arg0, err = ec.unmarshalNGitConfig2githubᚗcomᚋlitmuschaosᚋlitmusᚋlitmusᚑportalᚋgraphqlᚑserverᚋgraphᚋmodelᚐGitConfig(ctx, tmp)
if err != nil {
return nil, err
}
}
args["config"] = arg0
return args, nil
}
func (ec *executionContext) field_Mutation_updateMyHub_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
var err error
args := map[string]interface{}{}
@ -9145,6 +9173,67 @@ func (ec *executionContext) _Mutation_disableGitOps(ctx context.Context, field g
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_updateGitOps(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
ec.Error(ctx, ec.Recover(ctx, r))
ret = graphql.Null
}
}()
fc := &graphql.FieldContext{
Object: "Mutation",
Field: field,
Args: nil,
IsMethod: true,
}
ctx = graphql.WithFieldContext(ctx, fc)
rawArgs := field.ArgumentMap(ec.Variables)
args, err := ec.field_Mutation_updateGitOps_args(ctx, rawArgs)
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
fc.Args = args
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
return ec.resolvers.Mutation().UpdateGitOps(rctx, args["config"].(model.GitConfig))
}
directive1 := func(ctx context.Context) (interface{}, error) {
if ec.directives.Authorized == nil {
return nil, errors.New("directive authorized is not implemented")
}
return ec.directives.Authorized(ctx, nil, directive0)
}
tmp, err := directive1(rctx)
if err != nil {
return nil, err
}
if tmp == nil {
return nil, nil
}
if data, ok := tmp.(bool); ok {
return data, nil
}
return nil, fmt.Errorf(`unexpected type %T from directive, should be bool`, tmp)
})
if err != nil {
ec.Error(ctx, err)
return graphql.Null
}
if resTmp == nil {
if !graphql.HasFieldError(ctx, fc) {
ec.Errorf(ctx, "must not be null")
}
return graphql.Null
}
res := resTmp.(bool)
fc.Result = res
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
}
func (ec *executionContext) _Mutation_createDataSource(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
defer func() {
if r := recover(); r != nil {
@ -19323,6 +19412,11 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
if out.Values[i] == graphql.Null {
invalids++
}
case "updateGitOps":
out.Values[i] = ec._Mutation_updateGitOps(ctx, field)
if out.Values[i] == graphql.Null {
invalids++
}
case "createDataSource":
out.Values[i] = ec._Mutation_createDataSource(ctx, field)
case "createDashBoard":

View File

@ -279,8 +279,7 @@ type Mutation {
userClusterReg(clusterInput: ClusterInput!): clusterRegResponse! @authorized
#It is used to create chaosworkflow
createChaosWorkFlow(input: ChaosWorkFlowInput!): ChaosWorkFlowResponse!
@authorized
createChaosWorkFlow(input: ChaosWorkFlowInput!): ChaosWorkFlowResponse! @authorized
reRunChaosWorkFlow(workflowID: String!): String! @authorized
@ -321,8 +320,7 @@ type Mutation {
syncHub(id: ID!): [MyHubStatus!]! @authorized
updateChaosWorkflow(input: ChaosWorkFlowInput): ChaosWorkFlowResponse!
@authorized
updateChaosWorkflow(input: ChaosWorkFlowInput): ChaosWorkFlowResponse! @authorized
deleteClusterReg(cluster_id: String!): String! @authorized
@ -340,6 +338,8 @@ type Mutation {
disableGitOps(project_id: String!): Boolean! @authorized
updateGitOps(config: GitConfig!): Boolean! @authorized
# Analytics
createDataSource(datasource: DSInput): DSResponse @authorized

View File

@ -146,6 +146,10 @@ func (r *mutationResolver) DisableGitOps(ctx context.Context, projectID string)
return gitOpsHandler.DisableGitOpsHandler(ctx, projectID)
}
func (r *mutationResolver) UpdateGitOps(ctx context.Context, config model.GitConfig) (bool, error) {
return gitOpsHandler.UpdateGitOpsDetailsHandler(ctx, config)
}
func (r *mutationResolver) CreateDataSource(ctx context.Context, datasource *model.DSInput) (*model.DSResponse, error) {
return analyticsHandler.CreateDataSource(datasource)
}

View File

@ -37,8 +37,6 @@ func init() {
// AddGitConfig inserts new git config for project
func AddGitConfig(ctx context.Context, config *GitConfigDB) error {
ctx, cancel := context.WithTimeout(backgroundContext, timeout)
defer cancel()
_, err := gitOpsCollection.InsertOne(ctx, config)
if err != nil {
return err
@ -48,8 +46,6 @@ func AddGitConfig(ctx context.Context, config *GitConfigDB) error {
// GetGitConfig retrieves git config using project id
func GetGitConfig(ctx context.Context, projectID string) (*GitConfigDB, error) {
ctx, cancel := context.WithTimeout(backgroundContext, timeout)
defer cancel()
query := bson.M{"project_id": projectID}
var res GitConfigDB
err := gitOpsCollection.FindOne(ctx, query).Decode(&res)
@ -65,8 +61,6 @@ func GetGitConfig(ctx context.Context, projectID string) (*GitConfigDB, error) {
// GetAllGitConfig retrieves all git configs from db
func GetAllGitConfig(ctx context.Context) ([]GitConfigDB, error) {
ctx, cancel := context.WithTimeout(backgroundContext, timeout)
defer cancel()
query := bson.D{{}}
cursor, err := gitOpsCollection.Find(ctx, query)
if err != nil {
@ -80,10 +74,22 @@ func GetAllGitConfig(ctx context.Context) ([]GitConfigDB, error) {
return configs, nil
}
// ReplaceGitConfig updates git config matching the query
func ReplaceGitConfig(ctx context.Context, query bson.D, update *GitConfigDB) error {
updateResult, err := gitOpsCollection.ReplaceOne(ctx, query, update)
if err != nil {
return err
}
if updateResult.MatchedCount == 0 {
return errors.New("No matching git config found")
}
return nil
}
// UpdateGitConfig update git config matching the query
func UpdateGitConfig(ctx context.Context, query bson.D, update bson.D) error {
ctx, cancel := context.WithTimeout(backgroundContext, timeout)
defer cancel()
updateResult, err := gitOpsCollection.UpdateOne(ctx, query, update)
if err != nil {
return err
@ -98,8 +104,6 @@ func UpdateGitConfig(ctx context.Context, query bson.D, update bson.D) error {
// DeleteGitConfig removes git config corresponding to the given project id
func DeleteGitConfig(ctx context.Context, projectID string) error {
ctx, cancel := context.WithTimeout(backgroundContext, timeout)
defer cancel()
_, err := gitOpsCollection.DeleteOne(ctx, bson.M{"project_id": projectID})
if err != nil {

View File

@ -9,6 +9,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"time"
@ -117,16 +118,30 @@ func (c GitConfig) setupGitRepo(user GitUser) error {
if err != nil {
return err
}
if exists {
return nil
}
// create project dir and add config if not already present
err = os.MkdirAll(projectPath, 0755)
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(map[string]string{"projectID": c.ProjectID})
data, err := json.Marshal(gitInfo)
if err != nil {
return err
}
@ -146,8 +161,10 @@ func (c GitConfig) setupGitRepo(user GitUser) error {
// GitClone clones the repo
func (c GitConfig) GitClone() (*git.Repository, error) {
// clean the local path
os.RemoveAll(c.LocalPath)
err := os.RemoveAll(c.LocalPath)
if err != nil {
return nil, err
}
auth, err := c.getAuthMethod()
if err != nil {
return nil, err
@ -441,8 +458,7 @@ func (c GitConfig) GetLatestCommitHash() (string, error) {
}
// SetupGitOps clones and sets up the repo for gitops and returns the LatestCommit
func SetupGitOps(user GitUser, config dbSchemaGitOps.GitConfigDB) (string, error) {
gitConfig := GetGitOpsConfig(config)
func SetupGitOps(user GitUser, gitConfig GitConfig) (string, error) {
err := gitConfig.setupGitRepo(user)
if err != nil {
return "", err

View File

@ -30,7 +30,10 @@ import (
"github.com/litmuschaos/litmus/litmus-portal/graphql-server/pkg/gitops"
)
const timeout = time.Second * 5
const (
timeout = time.Second * 5
tempPath = "/tmp/gitops_test/"
)
var (
gitLock = gitops.NewGitLock()
@ -54,7 +57,7 @@ func EnableGitOpsHandler(ctx context.Context, config model.GitConfig) (bool, err
log.Print("Enabling Gitops")
gitDB := dbSchemaGitOps.GetGitConfigDB(config)
commit, err := gitops.SetupGitOps(gitops.GitUserFromContext(ctx), gitDB)
commit, err := gitops.SetupGitOps(gitops.GitUserFromContext(ctx), gitops.GetGitOpsConfig(gitDB))
if err != nil {
return false, errors.New("Failed to setup GitOps : " + err.Error())
}
@ -87,7 +90,7 @@ func DisableGitOpsHandler(ctx context.Context, projectID string) (bool, error) {
return true, nil
}
// GetGitOpsDetailsHandler
// GetGitOpsDetailsHandler returns the current gitops config for the requested project
func GetGitOpsDetailsHandler(ctx context.Context, projectID string) (*model.GitConfigResponse, error) {
gitLock.Lock(projectID, nil)
defer gitLock.Unlock(projectID, nil)
@ -123,6 +126,51 @@ func GetGitOpsDetailsHandler(ctx context.Context, projectID string) (*model.GitC
return &resp, nil
}
// UpdateGitOpsDetailsHandler updates an exiting gitops config for a project
func UpdateGitOpsDetailsHandler(ctx context.Context, config model.GitConfig) (bool, error) {
gitLock.Lock(config.ProjectID, nil)
defer gitLock.Unlock(config.ProjectID, nil)
gitLock.Lock(config.RepoURL, &config.Branch)
defer gitLock.Unlock(config.RepoURL, &config.Branch)
existingConfig, err := dbOperationsGitOps.GetGitConfig(ctx, config.ProjectID)
if err != nil {
return false, errors.New("Cannot get Git Config from DB : " + err.Error())
}
if existingConfig == nil {
return false, errors.New("GitOps Disabled ")
}
log.Print("Enabling Gitops")
gitDB := dbSchemaGitOps.GetGitConfigDB(config)
gitConfig := gitops.GetGitOpsConfig(gitDB)
originalPath := gitConfig.LocalPath
gitConfig.LocalPath = tempPath + gitConfig.ProjectID
commit, err := gitops.SetupGitOps(gitops.GitUserFromContext(ctx), gitConfig)
if err != nil {
return false, errors.New("Failed to setup GitOps : " + err.Error())
}
gitDB.LatestCommit = commit
err = dbOperationsGitOps.ReplaceGitConfig(ctx, bson.D{{"project_id", config.ProjectID}}, &gitDB)
if err != nil {
return false, errors.New("Failed to enable GitOps in DB : " + err.Error())
}
err = os.RemoveAll(originalPath)
if err != nil {
return false, errors.New("Cannot remove existing repo : " + err.Error())
}
err = os.Rename(gitConfig.LocalPath, originalPath)
if err != nil {
return false, errors.New("Cannot copy new repo : " + err.Error())
}
return true, nil
}
// GitOpsNotificationHandler sends workflow run request(single run workflow only) to agent on gitops notification
func GitOpsNotificationHandler(ctx context.Context, clusterInfo model.ClusterIdentity, workflowID string) (string, error) {
cInfo, err := cluster.VerifyCluster(clusterInfo)