mirror of
https://github.com/railwayapp/cli
synced 2026-04-21 14:07:23 +00:00
162 lines
3.2 KiB
Go
162 lines
3.2 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
|
|
"github.com/railwayapp/cli/entity"
|
|
"github.com/railwayapp/cli/ui"
|
|
)
|
|
|
|
func (h *Handler) Connect(ctx context.Context, req *entity.CommandRequest) error {
|
|
projectCfg, _ := h.ctrl.GetProjectConfigs(ctx)
|
|
|
|
project, err := h.ctrl.GetProject(ctx, projectCfg.Project)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
environment, err := h.ctrl.GetCurrentEnvironment(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Printf("🎉 Connecting to: %s %s\n", ui.MagentaText(project.Name), ui.MagentaText(environment.Name))
|
|
|
|
var plugin string
|
|
|
|
if len(req.Args) == 0 {
|
|
names := make([]string, 0)
|
|
for _, plugin := range project.Plugins {
|
|
// TODO: Better way of handling this
|
|
if plugin.Name != "env" {
|
|
names = append(names, plugin.Name)
|
|
}
|
|
}
|
|
|
|
fmt.Println("Select a database to connect to:")
|
|
plugin, err = ui.PromptPlugins(names)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
plugin = req.Args[0]
|
|
}
|
|
|
|
if !isPluginValid(plugin) {
|
|
return fmt.Errorf("Invalid plugin: %s", plugin)
|
|
}
|
|
envs, err := h.ctrl.GetEnvsForCurrentEnvironment(ctx, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
command, connectEnv := buildConnectCommand(plugin, envs)
|
|
if !commandExistsInPath(command[0]) {
|
|
fmt.Println("🚨", ui.RedText(command[0]), "was not found in $PATH.")
|
|
return nil
|
|
}
|
|
|
|
cmd := exec.CommandContext(ctx, command[0], command[1:]...)
|
|
|
|
cmd.Env = os.Environ()
|
|
for k, v := range connectEnv {
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%+v", k, v))
|
|
}
|
|
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stdout
|
|
cmd.Stdin = os.Stdin
|
|
catchSignals(ctx, cmd, nil)
|
|
|
|
err = cmd.Run()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func commandExistsInPath(cmd string) bool {
|
|
// The error can be safely ignored because it indicates a failure to find the
|
|
// command in $PATH.
|
|
_, err := exec.LookPath(cmd)
|
|
return err == nil
|
|
}
|
|
|
|
func isPluginValid(plugin string) bool {
|
|
switch plugin {
|
|
case "redis":
|
|
fallthrough
|
|
case "psql":
|
|
fallthrough
|
|
case "postgres":
|
|
fallthrough
|
|
case "postgresql":
|
|
fallthrough
|
|
case "mysql":
|
|
fallthrough
|
|
case "mongo":
|
|
fallthrough
|
|
case "mongodb":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func buildConnectCommand(plugin string, envs *entity.Envs) ([]string, map[string]string) {
|
|
var command []string
|
|
var connectEnv map[string]string
|
|
|
|
switch plugin {
|
|
case "redis":
|
|
// run
|
|
command = []string{"redis-cli", "-u", (*envs)["REDIS_URL"]}
|
|
case "psql":
|
|
fallthrough
|
|
case "postgres":
|
|
fallthrough
|
|
case "postgresql":
|
|
connectEnv = map[string]string{
|
|
"PGPASSWORD": (*envs)["PGPASSWORD"],
|
|
}
|
|
command = []string{
|
|
"psql",
|
|
"-U",
|
|
(*envs)["PGUSER"],
|
|
"-h",
|
|
(*envs)["PGHOST"],
|
|
"-p",
|
|
(*envs)["PGPORT"],
|
|
"-d",
|
|
(*envs)["PGDATABASE"],
|
|
}
|
|
case "mongo":
|
|
fallthrough
|
|
case "mongodb":
|
|
command = []string{
|
|
"mongo",
|
|
fmt.Sprintf(
|
|
"mongodb://%s:%s@%s:%s",
|
|
(*envs)["MONGOUSER"],
|
|
(*envs)["MONGOPASSWORD"],
|
|
(*envs)["MONGOHOST"],
|
|
(*envs)["MONGOPORT"],
|
|
),
|
|
}
|
|
case "mysql":
|
|
command = []string{
|
|
"mysql",
|
|
fmt.Sprintf("-h%s", (*envs)["MYSQLHOST"]),
|
|
fmt.Sprintf("-u%s", (*envs)["MYSQLUSER"]),
|
|
fmt.Sprintf("-p%s", (*envs)["MYSQLPASSWORD"]),
|
|
fmt.Sprintf("--port=%s", (*envs)["MYSQLPORT"]),
|
|
"--protocol=TCP",
|
|
(*envs)["MYSQLDATABASE"],
|
|
}
|
|
}
|
|
return command, connectEnv
|
|
}
|