Skip to content

Commit 059c3e3

Browse files
author
Moritz Clasmeier
committed
Use new roxieenv.AssembleRoxieEnvironment function for assembling environment
Provide separate function for spawning subshell given a deployer.
1 parent 0ac32d3 commit 059c3e3

1 file changed

Lines changed: 70 additions & 64 deletions

File tree

cmd/subshell.go

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -11,94 +11,100 @@ import (
1111
"github.com/stackrox/roxie/internal/deployer"
1212
"github.com/stackrox/roxie/internal/env"
1313
"github.com/stackrox/roxie/internal/logger"
14+
"github.com/stackrox/roxie/internal/roxieenv"
1415
"github.com/stackrox/roxie/internal/types"
1516
)
1617

17-
func spawnSubshell(d *deployer.Deployer, log *logger.Logger) error {
18-
shellPath := shell
19-
if shellPath == "" {
20-
shellPath = os.Getenv("ROXIE_USER_SHELL")
21-
}
22-
if shellPath == "" {
23-
shellPath = os.Getenv("SHELL")
24-
}
25-
if shellPath == "" {
26-
shellPath = "/bin/bash"
27-
}
28-
29-
log.Infof("Spawning sub-shell: %s", shellPath)
30-
31-
env := os.Environ()
32-
33-
centralDeploymentInfo := d.GetCentralDeploymentInfo()
34-
35-
if centralDeploymentInfo.Endpoint != "" {
36-
env = append(env, fmt.Sprintf("API_ENDPOINT=%s", centralDeploymentInfo.Endpoint))
37-
env = append(env, fmt.Sprintf("ROX_ENDPOINT=%s", centralDeploymentInfo.Endpoint))
38-
env = append(env, fmt.Sprintf("ROX_BASE_URL=https://%s", centralDeploymentInfo.Endpoint))
39-
}
40-
41-
if centralDeploymentInfo.Password != "" {
42-
env = append(env, fmt.Sprintf("ROX_ADMIN_PASSWORD=%s", centralDeploymentInfo.Password))
43-
}
18+
// spawnSubshellForDeployerEnv assembles the roxie environment from a Deployer and invokes an interactive subshell.
19+
func spawnSubshellForDeployerEnv(d *deployer.Deployer, log *logger.Logger) error {
20+
return runCommandOrSubshell(d.GetCentralDeploymentInfo(), log, nil)
21+
}
4422

45-
if centralDeploymentInfo.CACertFile != "" {
46-
env = append(env, fmt.Sprintf("ROX_CA_CERT_FILE=%s", centralDeploymentInfo.CACertFile))
23+
// runCommandOrSubshell spawns an interactive subshell or runs the provided command using the given
24+
// central deployment info.
25+
// It handles HAProxy setup, prints the connection banner, and manages shell lifecycle.
26+
func runCommandOrSubshell(centralDeploymentInfo types.CentralDeploymentInfo, log *logger.Logger, args []string) error {
27+
cmdEnv := os.Environ()
28+
for name, val := range roxieenv.AssembleRoxieEnvironment(centralDeploymentInfo).Export() {
29+
cmdEnv = append(cmdEnv, fmt.Sprintf("%s=%s", name, val))
4730
}
48-
49-
env = append(env, fmt.Sprintf("ROX_USERNAME=%s", deployer.AdminUsername))
50-
env = append(env, "ROXIE_SHELL=1")
51-
env = append(env, fmt.Sprintf("name=acs@%s", centralDeploymentInfo.KubeContext))
31+
cmdEnv = append(cmdEnv, "ROXIE_SHELL=1")
32+
cmdEnv = append(cmdEnv, fmt.Sprintf("name=acs@%s", centralDeploymentInfo.KubeContext))
5233

5334
haproxyAvailable := isHAProxyAvailable()
5435

55-
var haproxyCmd *exec.Cmd
56-
var haproxyConfigPath string
57-
5836
if haproxyAvailable && centralDeploymentInfo.Endpoint != "" && centralDeploymentInfo.CACertFile != "" {
59-
var err error
60-
haproxyCmd, haproxyConfigPath, err = startHAProxy(centralDeploymentInfo.Endpoint, centralDeploymentInfo.CACertFile, log)
37+
haproxyCmd, haproxyConfigPath, err := startHAProxy(centralDeploymentInfo.Endpoint, centralDeploymentInfo.CACertFile, log)
6138
if err != nil {
6239
log.Warningf("Failed to start HAProxy: %v", err)
6340
} else {
64-
env = append(env, fmt.Sprintf("ROXIE_HAPROXY_CFG_FILE=%s", haproxyConfigPath))
41+
cmdEnv = append(cmdEnv, "ROXIE_HAPROXY_CFG_FILE="+haproxyConfigPath)
6542
centralDeploymentInfo.HAProxyStarted = true
6643
defer cleanupHAProxy(haproxyCmd, haproxyConfigPath)
6744
}
6845
}
6946

70-
printBanner(centralDeploymentInfo)
71-
72-
shellCmd := exec.Command(shellPath, "-i")
73-
shellCmd.Env = env
74-
shellCmd.Stdin = os.Stdin
75-
shellCmd.Stdout = os.Stdout
76-
shellCmd.Stderr = os.Stderr
77-
78-
err := shellCmd.Run()
47+
var cmd *exec.Cmd
7948

80-
// Print exit message
81-
cyan := color.New(color.FgCyan, color.Bold)
82-
cyan.Println("\n[roxie] Exited subshell. You are now back in your original shell.")
83-
cyan.Println("")
84-
85-
// Don't treat shell exit as an error - shells can exit with non-zero status
86-
// for various reasons (like the last command failing) which is normal behavior
87-
if err != nil {
88-
// Check if it's a normal exit (exit code from the shell)
89-
if exitErr, ok := err.(*exec.ExitError); ok {
90-
// Shell exited (could be normal exit or last command failed)
91-
// This is not an error condition for roxie - the subshell worked fine
92-
_ = exitErr // Acknowledge we handled this
93-
return nil
49+
if subShellMode(args) {
50+
shellPath := resolveShellPath()
51+
log.Infof("Spawning sub-shell: %s", shellPath)
52+
printBanner(centralDeploymentInfo)
53+
cmd = exec.Command(shellPath, "-i")
54+
} else {
55+
// args is non-empty.
56+
cmd = exec.Command(args[0], args[1:]...)
57+
}
58+
cmd.Env = cmdEnv
59+
cmd.Stdin = os.Stdin
60+
cmd.Stdout = os.Stdout
61+
cmd.Stderr = os.Stderr
62+
63+
err := cmd.Run()
64+
65+
if subShellMode(args) {
66+
cyan := color.New(color.FgCyan, color.Bold)
67+
cyan.Println("")
68+
cyan.Println("[roxie] Exited subshell. You are now back in your original shell.")
69+
cyan.Println("[roxie] If you accidentally closed the roxie subshell, you can use `roxie shell` to re-open it.")
70+
cyan.Println("")
71+
72+
// Don't treat shell exit as an error - shells can exit with non-zero status
73+
// for various reasons (like the last command failing) which is normal behavior
74+
if err != nil {
75+
// Check if it's a normal exit (exit code from the shell)
76+
if _, ok := err.(*exec.ExitError); ok {
77+
return nil
78+
}
79+
// Only return error if we couldn't even start the shell
80+
return fmt.Errorf("failed to run subshell: %w", err)
81+
}
82+
} else {
83+
if err != nil {
84+
return fmt.Errorf("failed to execute command: %w", err)
9485
}
95-
// Only return error if we couldn't even start the shell
96-
return fmt.Errorf("failed to run subshell: %w", err)
9786
}
9887

9988
return nil
10089
}
10190

91+
func subShellMode(args []string) bool {
92+
return len(args) == 0
93+
}
94+
95+
func resolveShellPath() string {
96+
if shell != "" {
97+
return shell
98+
}
99+
if s := os.Getenv("ROXIE_USER_SHELL"); s != "" {
100+
return s
101+
}
102+
if s := os.Getenv("SHELL"); s != "" {
103+
return s
104+
}
105+
return "/bin/bash"
106+
}
107+
102108
func startHAProxy(endpoint, caCertFile string, log *logger.Logger) (*exec.Cmd, string, error) {
103109
configFile, err := os.CreateTemp("", "roxie-haproxy-*.cfg")
104110
if err != nil {

0 commit comments

Comments
 (0)