100 lines
3.4 KiB
Go
100 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
|
|
"proxyctl/internal/app"
|
|
"proxyctl/internal/dockerdaemon"
|
|
"proxyctl/internal/profile"
|
|
"proxyctl/internal/shell"
|
|
"proxyctl/internal/target"
|
|
"proxyctl/internal/tui"
|
|
)
|
|
|
|
func main() {
|
|
if err := run(os.Args[1:], os.Stdin, os.Stdout); err != nil {
|
|
fmt.Fprintln(os.Stderr, "proxyctl:", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run(args []string, input io.Reader, output io.Writer) error {
|
|
return runWithSystemTargets(args, input, output, nil)
|
|
}
|
|
|
|
// runWithSystemTargets keeps process smoke tests hermetic. A nil slice selects
|
|
// production system Targets; a non-nil slice supplies fakes (or no Targets).
|
|
func runWithSystemTargets(args []string, input io.Reader, output io.Writer, systemTargets []target.Target) error {
|
|
executable, err := os.Executable()
|
|
if err != nil {
|
|
return fmt.Errorf("locate proxyctl executable: %w", err)
|
|
}
|
|
return runWithEnvironmentAndTargets(args, input, output, processEnvironment{}, nil, executable, systemTargets)
|
|
}
|
|
|
|
type processEnvironment struct{}
|
|
|
|
func (processEnvironment) CurrentUser() (profile.UserIdentity, error) {
|
|
return profile.SystemCurrentUser()
|
|
}
|
|
func (processEnvironment) LookupUser(name string) (profile.UserIdentity, error) {
|
|
return profile.SystemLookupUser(name)
|
|
}
|
|
func (processEnvironment) LookupEnv(name string) (string, bool) { return os.LookupEnv(name) }
|
|
|
|
func runWithEnvironment(args []string, input io.Reader, output io.Writer, environment profile.IdentityEnvironment, files shell.FileSystem, executable string) error {
|
|
return runWithEnvironmentAndTargets(args, input, output, environment, files, executable, nil)
|
|
}
|
|
|
|
func runWithEnvironmentAndTargets(args []string, input io.Reader, output io.Writer, environment profile.IdentityEnvironment, files shell.FileSystem, executable string, systemTargets []target.Target) error {
|
|
profileConfiguration, err := profile.ResolveConfiguration(environment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
shellConfiguration, err := shell.ResolveConfiguration(environment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
shellTarget := shell.New(shellConfiguration, files, environment)
|
|
|
|
if len(args) != 0 {
|
|
if len(args) != 2 || args[0] != "shell" || (args[1] != "install" && args[1] != "uninstall") {
|
|
return fmt.Errorf("usage: proxyctl [shell install|shell uninstall]")
|
|
}
|
|
availability := shellTarget.Availability(context.Background())
|
|
if !availability.Available {
|
|
return fmt.Errorf("Shell Target unavailable: %s", availability.Evidence)
|
|
}
|
|
if args[1] == "install" {
|
|
if err := shellTarget.Install(context.Background(), executable); err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(output, "Shell integration installed; restart or source your Shell startup file once.")
|
|
return nil
|
|
}
|
|
if err := shellTarget.Uninstall(context.Background()); err != nil {
|
|
return err
|
|
}
|
|
fmt.Fprintln(output, "Shell integration uninstalled.")
|
|
return nil
|
|
}
|
|
|
|
store := profile.NewOwnedFileStoreAt(profileConfiguration.Path, profileConfiguration.Owner, profileConfiguration.TrustedRoot)
|
|
if systemTargets == nil {
|
|
systemTargets = []target.Target{dockerdaemon.New(dockerdaemon.DefaultConfiguration(), nil, nil)}
|
|
}
|
|
targets := append([]target.Target{shellTarget}, systemTargets...)
|
|
application, err := app.NewWithTargets(store, targets)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
program := tea.NewProgram(tui.NewModel(application), tea.WithInput(input), tea.WithOutput(output))
|
|
_, err = program.Run()
|
|
return err
|
|
}
|