diff --git a/cmd/add_test.go b/cmd/add_test.go index fe4f374..5474646 100644 --- a/cmd/add_test.go +++ b/cmd/add_test.go @@ -84,7 +84,7 @@ var _ = Describe("Add Command", func() { }) }) - When("add profile that is already exisiting", func() { + When("add profile that is already existing", func() { profileName := "lab.cluster1" envs := []string{"env1=var1", "env2=var2"} BeforeEach(func() { diff --git a/cmd/delete_test.go b/cmd/delete_test.go index e8531b2..e74e8cb 100644 --- a/cmd/delete_test.go +++ b/cmd/delete_test.go @@ -104,7 +104,7 @@ var _ = Describe("Edit Command", func() { }) When("delete profile that is not existing", func() { - profileName := fmt.Sprintf("not-exisiting-profile-%v", GinkgoRandomSeed()) + profileName := fmt.Sprintf("not-existing-profile-%v", GinkgoRandomSeed()) BeforeEach(func() { args = append(args, profileName) input = "y" diff --git a/cmd/root.go b/cmd/root.go index 1769464..08057df 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -53,12 +53,23 @@ func cmdExampleRoot() string { # specify env var profile to use envp profile-name -- kubectl get namespaces + + # skip init-script + envp profile-name --skip-init -- kubectl get namespaces ` } +// flags struct for start command +type rootFlags struct { + skipInitScript bool +} + // rootCommand sets environment variable and execute command line func rootCommand(sh *shell.ShellCommand) *cobra.Command { + // add flags + var flags rootFlags + cmd := &cobra.Command{ Use: "envp profile-name [flags] -- [command line to execute, e.g. kubectl]", Short: "ENVP is cli wrapper that sets environment variables by profile when you execute the command line", @@ -111,12 +122,14 @@ func rootCommand(sh *shell.ShellCommand) *cobra.Command { } // Execute command - if err := sh.Execute(command, profile); err != nil { + if err := sh.Execute(command, profile, flags.skipInitScript); err != nil { return err } return nil }, } + cmd.Flags().BoolVarP(&flags.skipInitScript, "skip-init", "s", false, `Skip running initialization scripts from the profile's "init-script"`) + return cmd } diff --git a/cmd/root_test.go b/cmd/root_test.go index 57ec309..85c65d3 100644 --- a/cmd/root_test.go +++ b/cmd/root_test.go @@ -201,8 +201,8 @@ var _ = Describe("Root Command", func() { }) }) - When("execute command with profile that is not exisiting", func() { - profileName := fmt.Sprintf("not-exisiting-profile-%v", GinkgoRandomSeed()) + When("execute command with profile that is not existing", func() { + profileName := fmt.Sprintf("not-existing-profile-%v", GinkgoRandomSeed()) BeforeEach(func() { args = append(args, profileName, "--", "echo", "hello") }) @@ -212,7 +212,7 @@ var _ = Describe("Root Command", func() { }) }) - When("execute command but shell command that is not exisiting", func() { + When("execute command but shell command that is not existing", func() { profileName := "lab.cluster2" BeforeEach(func() { args = append(args, profileName, "--", "1293471029384701298374019872498-aslkaslkjasdfjklasdfjklasdf-202020202") @@ -223,40 +223,34 @@ var _ = Describe("Root Command", func() { }) }) - // When("execute start command with empty string of profile", func() { - // profileName := "" - // BeforeEach(func() { - // args = append(args, profileName) - // input = "echo hello" - // }) - - // It("should be error", func() { - // Expect(err).Should(HaveOccurred()) - // }) - // }) - - // When("execute start command with valid inputs but omit profile name", func() { - // BeforeEach(func() { - // args = []string{} - // input = "env" - // }) - - // It("should not be error", func() { - // Expect(err).ShouldNot(HaveOccurred()) - // }) - - // It("should execute for default profile and include environment variable of default profile", func() { - // p, err := cfg.DefaultProfile() - // Expect(err).ShouldNot(HaveOccurred()) - // for _, e := range p.Env { - // Expect(stdout.String()).Should(ContainSubstring(e.String())) - // } - // }) - - // It("should include ENVP_PROFILE environment variable that is match to default profile", func() { - // p, err := cfg.DefaultProfile() - // Expect(err).ShouldNot(HaveOccurred()) - // Expect(stdout.String()).Should(ContainSubstring(fmt.Sprintf("ENVP_PROFILE=%s", p.Name))) - // }) - // }) + When("execute start command with profile that has init-script", func() { + // profile-with-init-script profile do "echo meow" + // so that, we should see "meow" in the stdout + BeforeEach(func() { + args = append(args, "profile-with-init-script", "--", "echo", "hello") + }) + + It("output should include result of init-script", func() { + fmt.Println(stdout.String(), err) + Expect(err).ShouldNot(HaveOccurred()) + Expect(stdout.String()).Should(ContainSubstring("meow")) + Expect(stdout.String()).Should(ContainSubstring("hello")) + }) + }) + + When("execute start command with skip-init flag", func() { + // profile-with-init-script profile do "echo meow" + // so that, we should see "meow" in the stdout + // but, "meow" should not seen because "skip-init" flag has passed + BeforeEach(func() { + args = append(args, "profile-with-init-script", "--skip-init", "--", "echo", "hello") + }) + + It("output should NOT include result of init-script", func() { + fmt.Println(stdout.String(), err) + Expect(err).ShouldNot(HaveOccurred()) + Expect(stdout.String()).ShouldNot(ContainSubstring("meow")) + Expect(stdout.String()).Should(ContainSubstring("hello")) + }) + }) }) diff --git a/cmd/start.go b/cmd/start.go index 7162782..2c4dc62 100644 --- a/cmd/start.go +++ b/cmd/start.go @@ -10,6 +10,11 @@ func init() { rootCmd.AddCommand(startCommand(shell.NewShellCommand())) } +// flags struct for start command +type startFlags struct { + skipInitScript bool +} + // example of delete command func cmdExampleStart() string { return ` @@ -18,12 +23,18 @@ func cmdExampleStart() string { # start new shell session with specific profile envp start + + # skip "init-script" of profile when start new shell session with specific profile + envp start --skip-init ` } // deleteCommand delete/remove environment variable profile and it's envionment variables from the config file func startCommand(sh *shell.ShellCommand) *cobra.Command { + // add flags + var flags startFlags + cmd := &cobra.Command{ Use: "start profile-name", Short: "Start new shell session with environment variable profile", @@ -43,10 +54,13 @@ func startCommand(sh *shell.ShellCommand) *cobra.Command { } // ignore error message from shell. let shell print out the errors - sh.StartShell(profile) + sh.StartShell(profile, flags.skipInitScript) return nil }, } + + cmd.Flags().BoolVarP(&flags.skipInitScript, "skip-init", "s", false, `Skip running initialization scripts from the profile's "init-script" during shell startup`) + return cmd } diff --git a/cmd/start_test.go b/cmd/start_test.go index c6e40bd..6c506db 100644 --- a/cmd/start_test.go +++ b/cmd/start_test.go @@ -101,8 +101,8 @@ var _ = Describe("Start Command", func() { }) }) - When("execute start command with profile that is not exisiting", func() { - profileName := fmt.Sprintf("not-exisiting-profile-%v", GinkgoRandomSeed()) + When("execute start command with profile that is not existing", func() { + profileName := fmt.Sprintf("not-existing-profile-%v", GinkgoRandomSeed()) BeforeEach(func() { args = append(args, profileName) input = "echo hello" @@ -149,4 +149,38 @@ var _ = Describe("Start Command", func() { Expect(stdout.String()).Should(ContainSubstring(fmt.Sprintf("ENVP_PROFILE=%s", p.Name))) }) }) + + When("execute start command with profile that has init-script", func() { + // profile-with-init-script profile do "echo meow" + // so that, we should see "meow" in the stdout + profileName := "profile-with-init-script" + BeforeEach(func() { + args = append(args, profileName) + input = "exit" + }) + + It("output should include result of init-script", func() { + fmt.Println(stdout.String(), err) + Expect(err).ShouldNot(HaveOccurred()) + Expect(stdout.String()).Should(ContainSubstring("meow")) + }) + }) + + When("execute start command with skip-init flag", func() { + // profile-with-init-script profile do "echo meow" + // so that, we should see "meow" in the stdout + // but, "meow" should not seen because "skip-init" flag has passed + profileName := "profile-with-init-script" + BeforeEach(func() { + args = append(args, profileName) + args = append(args, "--skip-init") + input = "exit" + }) + + It("output should NOT include result of init-script", func() { + fmt.Println(stdout.String(), err) + Expect(err).ShouldNot(HaveOccurred()) + Expect(stdout.String()).ShouldNot(ContainSubstring("meow")) + }) + }) }) diff --git a/internal/shell/shell.go b/internal/shell/shell.go index eb6f298..088bf71 100644 --- a/internal/shell/shell.go +++ b/internal/shell/shell.go @@ -35,12 +35,12 @@ func NewShellCommand() *ShellCommand { } // Execute executes given command -func (s *ShellCommand) Execute(cmd []string, profile *config.NamedProfile) error { - return s.execCommand(cmd[0], cmd, profile) +func (s *ShellCommand) Execute(cmd []string, profile *config.NamedProfile, skipInitScript bool) error { + return s.execCommand(cmd[0], cmd, profile, skipInitScript) } // StartShell runs default shell of user to create new shell session -func (s *ShellCommand) StartShell(profile *config.NamedProfile) error { +func (s *ShellCommand) StartShell(profile *config.NamedProfile, skipInitScript bool) error { sh := os.Getenv("SHELL") // use /bin/sh if SHELL is not set @@ -54,7 +54,7 @@ func (s *ShellCommand) StartShell(profile *config.NamedProfile) error { s.Stdout.Write([]byte(fmt.Sprintln("> press ctrl+d or type exit to close session"))) // execute the command - err := s.execCommand(sh, []string{sh, "-c", sh}, profile) + err := s.execCommand(sh, []string{sh, "-c", sh}, profile, skipInitScript) if err != nil { s.Stderr.Write([]byte(fmt.Sprintln(color.MagentaString(err.Error())))) } @@ -67,7 +67,7 @@ func (s *ShellCommand) StartShell(profile *config.NamedProfile) error { } // execCommand executes the os/exec Command with environment variables injection -func (s *ShellCommand) execCommand(argv0 string, argv []string, profile *config.NamedProfile) error { +func (s *ShellCommand) execCommand(argv0 string, argv []string, profile *config.NamedProfile, skipInitScript bool) error { // first arg should be the command to execute // check if command can be found in the PATH binary, err := exec.LookPath(argv0) @@ -88,9 +88,11 @@ func (s *ShellCommand) execCommand(argv0 string, argv []string, profile *config. // set ENVP_PROFILE cmd.Env = appendEnvpProfile(cmd.Env, profile.Name) - // run init-script - if err := s.executeInitScript(profile); err != nil { - return err + if !skipInitScript { + // run init-script + if err := s.executeInitScript(profile); err != nil { + return err + } } // run command diff --git a/internal/shell/shell_test.go b/internal/shell/shell_test.go index bdf78ac..d4fd202 100644 --- a/internal/shell/shell_test.go +++ b/internal/shell/shell_test.go @@ -22,14 +22,17 @@ var _ = Describe("Shell", func() { Describe("run Execute", func() { + var stdout, stderr bytes.Buffer sc := NewShellCommand() + sc.Stdout = &stdout + sc.Stderr = &stderr Context("eligible command", func() { When("passing non-empty envs", func() { It("should not return err", func() { cmd := "echo" - err := sc.Execute([]string{cmd}, &profile) + err := sc.Execute([]string{cmd}, &profile, false) Expect(err).ToNot(HaveOccurred()) }) }) @@ -37,7 +40,7 @@ var _ = Describe("Shell", func() { When("pass wrong arg to command", func() { It("should return err", func() { cmd := []string{"cat", "/not-existing-dir/not-existing-file-rand-meow"} - err := sc.Execute(cmd, &profile) + err := sc.Execute(cmd, &profile, false) Expect(err).To(HaveOccurred()) }) }) @@ -46,11 +49,29 @@ var _ = Describe("Shell", func() { When("run non-existing command", func() { It("should not return err", func() { cmd := "" - err := sc.Execute([]string{cmd}, &profile) + err := sc.Execute([]string{cmd}, &profile, false) Expect(err).To(HaveOccurred()) }) }) + When("skip-init param is true", func() { + + profile := config.NamedProfile{ + Name: "my-profile", + Profile: config.NewProfile(), + } + + // The init script contains 'exit 1' which would normally cause an error, + // but since skip-init=true, the script will be skipped entirely + profile.InitScript = "exit 1" + + It("should not error because init-script won't be running", func() { + cmd := []string{"echo", "hello"} + err := sc.Execute(cmd, &profile, true) + Expect(err).NotTo(HaveOccurred()) + Expect(stdout.String()).Should(ContainSubstring("hello")) + }) + }) }) Describe("run StartShell", func() { @@ -68,7 +89,7 @@ var _ = Describe("Shell", func() { When("pass not empty envs", func() { It("should not return err", func() { - err := sc.StartShell(&profile) + err := sc.StartShell(&profile, false) Expect(err).ToNot(HaveOccurred()) }) }) @@ -79,7 +100,7 @@ var _ = Describe("Shell", func() { Name: "", Profile: config.NewProfile(), } - err := sc.StartShell(&profile) + err := sc.StartShell(&profile, false) Expect(err).ToNot(HaveOccurred()) Expect(stdout.String()).NotTo(BeEmpty()) Expect(stderr.String()).To(BeEmpty()) @@ -99,7 +120,7 @@ var _ = Describe("Shell", func() { Name: "my-profile", Profile: config.NewProfile(), } - err := sc.StartShell(&profile) + err := sc.StartShell(&profile, false) Expect(err).NotTo(HaveOccurred()) }) JustAfterEach(func() { @@ -205,7 +226,7 @@ var _ = Describe("env shell command substitution", func() { It("StartShell should show parsing error message in stderr", func() { - err := sc.StartShell(&profile) + err := sc.StartShell(&profile, false) Expect(err).To(HaveOccurred()) Expect(stderr.String()).NotTo(BeEmpty()) Expect(stderr.String()).To(ContainSubstring("error processing value of TEST_SUBST_3")) @@ -282,7 +303,7 @@ var _ = Describe("init-script", func() { } profile.InitScript = "exit 1" - err := sc.StartShell(&profile) + err := sc.StartShell(&profile, false) It("should error", func() { Expect(err).To(HaveOccurred()) @@ -293,6 +314,28 @@ var _ = Describe("init-script", func() { }) }) + When("skip-init param is true", func() { + + var stdout, stderr bytes.Buffer + sc := NewShellCommand() + sc.Stdout = &stdout + sc.Stderr = &stderr + + profile := config.NamedProfile{ + Name: "my-profile", + Profile: config.NewProfile(), + } + + // The init script contains 'exit 1' which would normally cause an error, + // but since skip-init=true, the script will be skipped entirely + profile.InitScript = "exit 1" + err := sc.StartShell(&profile, true) + + It("should not error because init-script won't be running", func() { + Expect(err).NotTo(HaveOccurred()) + }) + }) + When("init-script use defined Env", func() { var stdout, stderr bytes.Buffer