diff --git a/cmd/deploy_test.go b/cmd/deploy_test.go index cca52a4..d75500c 100644 --- a/cmd/deploy_test.go +++ b/cmd/deploy_test.go @@ -1,9 +1,11 @@ package cmd import ( + "io/ioutil" "os" "github.com/jarcoal/httpmock" + "github.com/urfave/cli" ) func Example_deploy_quiet_false() { @@ -57,3 +59,27 @@ func Example_deploy_quiet_true() { // Output: } + +func newTestApp(command cli.Command) *cli.App { + a := cli.NewApp() + a.Name = "bcn" + a.Writer = ioutil.Discard + a.Commands = []cli.Command{command} + + pwd, _ := os.Getwd() + HeritageConfigFilePath = pwd + "/test/test-barcelona.yml" + + return a +} + +func readJsonResponse(path string) (string, error) { + jsonFile, err := os.Open(path) + if err != nil { + return "", err + } + + byteValue, _ := ioutil.ReadAll(jsonFile) + defer jsonFile.Close() + + return string(byteValue), err +} diff --git a/cmd/run.go b/cmd/run.go index 9ba4edc..7ba03af 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -1,269 +1,15 @@ package cmd import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "regexp" - "strings" - "time" - - "github.com/degica/barcelona-cli/api" - "github.com/degica/barcelona-cli/config" - "github.com/degica/barcelona-cli/utils" "github.com/urfave/cli" ) var RunCommand = cli.Command{ Name: "run", - Usage: "Run command inside Barcelona environment", - ArgsUsage: "COMMAND...", - Flags: []cli.Flag{ - cli.StringFlag{ - Name: "environment, e", - Usage: "Environment of heritage", - }, - cli.StringFlag{ - Name: "heritage-name, H", - Usage: "Heritage name", - }, - cli.IntFlag{ - Name: "memory, m", - Usage: "Memory size in MB", - }, - cli.StringFlag{ - Name: "user, u", - Usage: "User name", - }, - cli.BoolFlag{ - Name: "detach, D", - Usage: "Detach mode", - }, - cli.StringSliceFlag{ - Name: "envvar, E", - Usage: "Environment variable to pass to task", - }, - cli.StringFlag{ - Name: "b, branch", - Usage: "Git branch name", - }, - }, + Usage: "[Deprecated] Run command inside Barcelona environment", + ArgsUsage: "", + Flags: []cli.Flag{}, Action: func(c *cli.Context) error { - envName := c.String("environment") - heritageName := c.String("heritage-name") - branchName := c.String("branch") - - detach := c.Bool("detach") - envVars := c.StringSlice("envvar") - envVarMap, loadEnvVarMapErr := loadEnvVars(envName) - - if loadEnvVarMapErr != nil { - return cli.NewExitError(loadEnvVarMapErr.Error(), 1) - } - - if len(envName) > 0 && len(heritageName) > 0 { - return cli.NewExitError("environment and heritage-name are exclusive", 1) - } - - if len(branchName) > 0 { - if len(envName) > 0 || len(heritageName) > 0 { - return cli.NewExitError("environment, heritage-name and branch-name are exclusive", 1) - } - - name, err := getHeritageName(branchName) - if err != nil { - return err - } - - heritageName = name - } - - if len(heritageName) == 0 { - env, err := LoadEnvironment(envName) - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - heritageName = env.Name - } - - if len(envVars) > 0 { - varmap, err := checkEnvVars(envVars) - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - for k, v := range varmap { - envVarMap[k] = v - } - } - - if len(c.Args()) == 0 { - return cli.NewExitError("Command is required", 1) - } - - command := strings.Join(c.Args(), " ") - params := map[string]interface{}{ - "interactive": !detach, - "command": command, - "env_vars": envVarMap, - } - memory := c.Int("memory") - if memory > 0 { - params["memory"] = memory - } - - user := c.String("user") - if user != "" { - params["user"] = user - } - err := connectToHeritage(params, heritageName, detach) - - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - - return nil + return cli.NewExitError("This command is deprecated. Please use ecs-exec instead, available at https://github.com/komoju/komoju-ecs-exec", 1) }, } - -func loadEnvVars(envName string) (map[string]string, error) { - result := make(map[string]string) - if len(envName) > 0 { - env, err := LoadEnvironment(envName) - if err != nil { - return nil, err - } - if env.RunEnv != nil { - for k, v := range env.RunEnv.Vars { - result[k] = v - } - } - } - return result, nil -} - -func checkEnvVars(envvarSlice []string) (map[string]string, error) { - var result = make(map[string]string) - - re := regexp.MustCompile(`^([A-Z_]+)=(.*)$`) - for _, envvar := range envvarSlice { - if !re.Match([]byte(envvar)) { - return nil, errors.New(fmt.Sprintf("Env Variable %s is not valid. Name must have PASCAL_CASE=", envvar)) - } - result[re.FindStringSubmatch(envvar)[1]] = re.FindStringSubmatch(envvar)[2] - } - return result, nil -} - -func connectToHeritage(params map[string]interface{}, heritageName string, detach bool) error { - j, err := json.Marshal(params) - - if err != nil { - return err - } - - resp, err := api.DefaultClient.Post("/heritages/"+heritageName+"/oneoffs", bytes.NewBuffer(j)) - if err != nil { - return err - } - - var respOneoff api.OneoffResponse - err = json.Unmarshal(resp, &respOneoff) - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - - oneoff := respOneoff.Oneoff - certificate := respOneoff.Certificate - - if detach { - PrintOneoff(oneoff) - return nil - } - - fmt.Println("Waiting for the process to start") - -LOOP: - for { - path := fmt.Sprintf("/districts/%s/heritages/%s/oneoffs/%d", oneoff.District.Name, heritageName, oneoff.ID) - resp, err := api.DefaultClient.Get(path, nil) - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - var respOneoff api.OneoffResponse - err = json.Unmarshal(resp, &respOneoff) - if err != nil { - return cli.NewExitError(err.Error(), 1) - } - switch respOneoff.Oneoff.Status { - case "RUNNING": - break LOOP - case "PENDING": - time.Sleep(3 * time.Second) - default: - // INACTIVE or STOPPED - return cli.NewExitError("Unexpected task status "+respOneoff.Oneoff.Status, 1) - } - } - - fmt.Println("Connecting to the process") - - var matchedCI *api.ContainerInstance - for _, ci := range oneoff.District.ContainerInstances { - if ci.ContainerInstanceArn == oneoff.ContainerInstanceARN { - matchedCI = ci - break - } - } - - ssh := utils.NewSshCommand( - matchedCI.PrivateIPAddress, - oneoff.District.BastionIP, - certificate, - config.Get(), - &utils.CommandRunner{}, - ) - - if ssh.Run(oneoff.InteractiveRunCommand) != nil && err != nil { - return err - } - - return nil -} - -func getHeritageName(branchName string) (string, error) { - groupName, err := getGroupName() - - if err != nil { - return "", err - } - - review_apps, err := getReviewApps(groupName) - - if err != nil { - return "", err - } - - heritageName := "" - for _, app := range review_apps { - if app.Subject == branchName { - heritageName = app.Heritage.Name - break - } - } - - if heritageName == "" { - return "", errors.New(fmt.Sprintf("No heritage found for branch: %s", branchName)) - } - - return heritageName, nil -} - -func getGroupName() (string, error) { - reviewDef, err := LoadReviewDefinition() - if err != nil { - return "", err - } - - return reviewDef.GroupName, nil -} diff --git a/cmd/run_test.go b/cmd/run_test.go deleted file mode 100644 index 7978ded..0000000 --- a/cmd/run_test.go +++ /dev/null @@ -1,106 +0,0 @@ -package cmd - -import ( - "io/ioutil" - "os" - "testing" - - "github.com/jarcoal/httpmock" - "github.com/urfave/cli" -) - -func TestCheckEnvVars(t *testing.T) { - result, err := checkEnvVars([]string{"ABC=def", "GHI=jkl"}) - - if err != nil { - t.Errorf("Expected there to be no error but got: %s", err) - } - - if result["ABC"] != "def" { - t.Errorf("Expected ABC to be set to def but got: %s", result) - } - - if result["GHI"] != "jkl" { - t.Errorf("Expected ABC to be set to def but got: %s", result) - } -} - -func TestCheckEnvVarsError(t *testing.T) { - result, err := checkEnvVars([]string{"ABCd=def", "GHI=jkl"}) - - if err == nil { - t.Errorf("Expected to be an error but was nil") - } - - if result != nil { - t.Errorf("Expected result to be nil, but was %s", result) - } -} - -func TestRunByBranchName(t *testing.T) { - pwd, _ := os.Getwd() - app := newTestApp(RunCommand) - endpoint := os.Getenv("BARCELONA_ENDPOINT") - - testArgs := []string{"bcn", "run", "-b", "test-branch", "--D", "bash"} - - httpmock.Activate() - defer httpmock.DeactivateAndReset() - - httpmock.RegisterResponder("POST", endpoint+"/v1/auth/github/login", - httpmock.NewStringResponder(200, "{}")) - - resJson, err := readJsonResponse(pwd + "/test/review_group.json") - if err != nil { - t.Fatalf("error running command `loading json %v", err) - } - - httpmock.RegisterResponder("GET", endpoint+"/v1/review_groups/test1/apps", - httpmock.NewStringResponder(200, resJson)) - - resJson, err = readJsonResponse(pwd + "/test/oneoffs.json") - if err != nil { - t.Fatalf("error running command `loading json %v", err) - } - - httpmock.RegisterResponder("POST", endpoint+"/v1/heritages/review-heritage/oneoffs", - httpmock.NewStringResponder(200, resJson)) - - app.Run(testArgs) -} - -func TestWrongFlag(t *testing.T) { - app := newTestApp(RunCommand) - - testArgs := []string{"bcn", "run", "-B", "not-found", "--D", "bash"} - - err := app.Run(testArgs) - - if err.Error() != "flag provided but not defined: -B" { - t.Fatalf("error running command `bcn run %v", err) - } -} - -func newTestApp(command cli.Command) *cli.App { - a := cli.NewApp() - a.Name = "bcn" - a.Writer = ioutil.Discard - a.Commands = []cli.Command{command} - - pwd, _ := os.Getwd() - HeritageConfigFilePath = pwd + "/test/test-barcelona.yml" - - return a -} - -func readJsonResponse(path string) (string, error) { - jsonFile, err := os.Open(path) - if err != nil { - return "", err - } - - byteValue, _ := ioutil.ReadAll(jsonFile) - defer jsonFile.Close() - - return string(byteValue), err -}