Skip to content

Commit

Permalink
environment operations
Browse files Browse the repository at this point in the history
  • Loading branch information
boppanasusanth committed Mar 13, 2024
1 parent 6dadccd commit 8d5086b
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go-lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.51.1
version: v1.56.2
args: -E gofmt -E gci
37 changes: 37 additions & 0 deletions api/environment/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,40 @@ type Status struct {
type DetailResponse struct {
Response Env `yaml:"resp,omitempty" json:"resp,omitempty"`
}

type Operation struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Data interface{} `yaml:"values,omitempty" json:"values,omitempty"`
}

type OperationRequest struct {
Operations []Operation `yaml:"operations,omitempty" json:"operations,omitempty"`
}

type OperationConsent struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
IsFeedbackRequired bool `yaml:"is_feedback_required,omitempty" json:"is_feedback_required,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
}

type OperationValidationResponseBody struct {
Operations []OperationConsent `yaml:"operations,omitempty" json:"operations,omitempty"`
}

type OperationValidationResponse struct {
Response OperationValidationResponseBody `yaml:"resp,omitempty" json:"resp,omitempty"`
}

type OperationOutput struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Errored bool `yaml:"errored,omitempty" json:"errored,omitempty"`
Message string `yaml:"message,omitempty" json:"message,omitempty"`
}

type OperationResponseBody struct {
Operations []OperationOutput `yaml:"operations,omitempty" json:"operations,omitempty"`
}

type OperationResponse struct {
Response OperationResponseBody `yaml:"resp,omitempty" json:"resp,omitempty"`
}
24 changes: 24 additions & 0 deletions internal/backend/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,27 @@ func (e *Env) EnvTypes() (envResp.EnvTypesResponse, error) {

return envResponse, err
}

func (e *Env) ValidateOperation(envName string, data envResp.OperationRequest) (envResp.OperationValidationResponse, error) {
client := newApiClient()

response := client.actionWithRetry(path.Join(envEntity, envName)+"/operate/validate/", "GET", data)
response.Process(true)

var validateOperationResponse envResp.OperationValidationResponse
err := json.Unmarshal(response.Body, &validateOperationResponse)

return validateOperationResponse, err
}

func (e *Env) OperateService(envName string, data envResp.OperationRequest) (envResp.OperationResponse, error) {
client := newApiClient()

response := client.actionWithRetry(path.Join(envEntity, envName)+"/operate/", "PUT", data)
response.Process(true)

var operationResponse envResp.OperationResponse
err := json.Unmarshal(response.Body, &operationResponse)

return operationResponse, err
}
3 changes: 3 additions & 0 deletions internal/command/command_catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ func CommandsCatalog() map[string]cli.CommandFactory {
"set env": func() (cli.Command, error) {
return &commands.Env{Set: true}, nil
},
"operate env": func() (cli.Command, error) {
return &commands.Env{Operate: true}, nil
},
"list env-type": func() (cli.Command, error) {
return &commands.EnvType{List: true}, nil
},
Expand Down
116 changes: 115 additions & 1 deletion internal/command/commands/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ func (e *Env) Run(args []string) int {
component := flagSet.String("component", "", "component name to filter out describe environment")
providerAccount := flagSet.String("account", "", "account name to provision the environment in")
id := flagSet.Int("id", 0, "unique id of a changelog of an env")
filePath := flagSet.String("file", "", "file to update env")
filePath := flagSet.String("file", "", "file to update env or provide options for environment operations")
data := flagSet.String("data", "", "data for updating the env")
displayAll := flagSet.Bool("all", false, "whether to display all environments")
operation := flagSet.String("operation", "", "name of the operation to performed on the environment")
options := flagSet.String("options", "", "options for environment operations")

err := flagSet.Parse(args)
if err != nil {
Expand Down Expand Up @@ -380,6 +382,103 @@ func (e *Env) Run(args []string) int {
return 0
}

if e.Operate {
if *name == "" {
*name = utils.FetchKey(ENV_NAME_KEY)
}

isNamePresent := len(*name) > 0
isOptionsPresent := len(*options) > 0
isFilePresent := len(*filePath) > 0
isOperationPresnt := len(*operation) > 0

if !isNamePresent {
e.Logger.Error("--name cannot be blank")
return 1
}
if !isOperationPresnt {
e.Logger.Error("--operation cannot be blank")
return 1
}
if isOptionsPresent && isFilePresent {
e.Logger.Error("You can provide either --options or --file but not both")
return 1
}

var optionsData map[string]interface{}

if isFilePresent {
parsedConfig, err := parseFile(*filePath)
if err != nil {
e.Logger.Error("Error while parsing service file " + *filePath + " : " + err.Error())
return 1
}
optionsData = parsedConfig.(map[string]interface{})
} else if isOptionsPresent {
err = json.Unmarshal([]byte(*options), &optionsData)
if err != nil {
e.Logger.Error("Unable to parse JSON data " + err.Error())
return 1
}
}

data := environment.OperationRequest{
Operations: []environment.Operation{
{
Name: *operation,
Data: optionsData,
},
},
}

e.Logger.Info("Validating the operation: " + *operation + " on the environment: " + *name)

validateOperateResponse, err := envClient.ValidateOperation(*name, data)
if err != nil {
e.Logger.Error(err.Error())
return 1
}

for _, operation := range validateOperateResponse.Response.Operations {
if operation.IsFeedbackRequired {
consentMessage := fmt.Sprintf("\n%s", operation.Message)
allowedInputs := map[string]struct{}{"Y": {}, "n": {}}
val, err := e.Input.AskWithConstraints(consentMessage, allowedInputs)
if err != nil {
e.Logger.Error(err.Error())
return 1
}
if val != "Y" {
e.Logger.Info("Aborting the operation")
return 1
}
} else {
e.Logger.Output(operation.Message)
}
}

operateResponse, err := envClient.OperateService(*name, data)
if err != nil {
e.Logger.Error(err.Error())
return 1
}

errored := false
for _, operation := range operateResponse.Response.Operations {
if operation.Errored {
e.Logger.Error("Operation [" + operation.Name + "] failed with error: " + operation.Message)
errored = true
} else {
e.Logger.Output(operation.Message)
}
}

if errored {
return 1
}
return 0
}

e.Logger.Error("Not a valid command")
return 127
}
Expand Down Expand Up @@ -464,6 +563,15 @@ func (e *Env) Help() string {
})
}

if e.Operate {
return commandHelper("operate", "environment", "", []Options{
{Flag: "--name", Description: "name of environment"},
{Flag: "--operation", Description: "name of the operation to be performed on the environment"},
{Flag: "--options", Description: "options for the operation in JSON format"},
{Flag: "--file", Description: "path of the file which contains the options for the operation in JSON format"},
})
}

return defaultHelper()
}

Expand Down Expand Up @@ -496,9 +604,15 @@ func (e *Env) Synopsis() string {
if e.Set {
return "Set a default env"
}

if e.Update {
return "update an env"
}

if e.Operate {
return "operate an environment"
}

return defaultHelper()
}

Expand Down
8 changes: 4 additions & 4 deletions internal/command/commands/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ func (s *Service) Run(args []string) int {
"action": *operation,
"config": optionsData,
}
scalingConsent := s.askForScalingConsent(serviceName, envName, dataForScalingConsent)
scalingConsent := s.askForScalingConsent(serviceName, dataForScalingConsent)
if scalingConsent == 1 {
return 1
}
Expand Down Expand Up @@ -481,7 +481,7 @@ func (s *Service) askForConsent(envName *string) int {
return 0
}

func (s *Service) askForScalingConsent(serviceName *string, envName *string, data map[string]interface{}) int {
func (s *Service) askForScalingConsent(serviceName *string, data map[string]interface{}) int {
componentListResponse, err := serviceClient.ScalingServiceConsent(*serviceName, data)
if err != nil {
s.Logger.Error(err.Error())
Expand Down Expand Up @@ -540,7 +540,7 @@ func (s *Service) deployReleasedService(envName *string, serviceName *string, se
"action": "released_service_deploy",
"config": parsedProvisioningConfig,
}
scalingConsent := s.askForScalingConsent(serviceName, envName, dataForScalingConsent)
scalingConsent := s.askForScalingConsent(serviceName, dataForScalingConsent)
if scalingConsent == 1 {
return 1
}
Expand Down Expand Up @@ -712,7 +712,7 @@ func (s *Service) Help() string {
return commandHelper("operate", "service", "", []Options{
{Flag: "--name", Description: "name of service"},
{Flag: "--env", Description: "name of environment"},
{Flag: "--operate", Description: "name of the operation to be performed on the service"},
{Flag: "--operation", Description: "name of the operation to be performed on the service"},
{Flag: "--file", Description: "path of the file which contains the options for the operation in JSON format"},
{Flag: "--options", Description: "options for the operation in JSON format"},
})
Expand Down
2 changes: 1 addition & 1 deletion internal/command/commands/serviceset.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (s *ServiceSet) Help() string {
{Flag: "--name", Description: "name of service-set to deploy"},
{Flag: "--env", Description: "name of environment to deploy service-set in"},
{Flag: "--force", Description: "forcefully deploy service-set into the Env"},
{Flag: "--d11", Description: "config-store-namespace=config store branch/tag to use"},
{Flag: "--d11-config-store-namespace", Description: "config store branch/tag to use"},
{Flag: "--file", Description: "json file to read temporary service-set definition "},
})
}
Expand Down

0 comments on commit 8d5086b

Please sign in to comment.