diff --git a/cmd/agent/agent.go b/cmd/agent/agent.go index df9d622bb..669e84e9f 100644 --- a/cmd/agent/agent.go +++ b/cmd/agent/agent.go @@ -7,7 +7,6 @@ import ( "github.com/skevetter/devpod/cmd/agent/container" "github.com/skevetter/devpod/cmd/agent/workspace" "github.com/skevetter/devpod/cmd/flags" - "github.com/skevetter/devpod/pkg/client/clientimplementation" "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/envfile" "github.com/skevetter/log" @@ -63,12 +62,12 @@ func AgentPersistentPreRunE( log.Default.SetLevel(logrus.FatalLevel) } else if globalFlags.Debug { log.Default.SetLevel(logrus.DebugLevel) - } else if os.Getenv(clientimplementation.DevPodDebug) == "true" { + } else if os.Getenv(config.EnvDebug) == config.BoolTrue { log.Default.SetLevel(logrus.DebugLevel) } if globalFlags.DevPodHome != "" { - _ = os.Setenv(config.DEVPOD_HOME, globalFlags.DevPodHome) + _ = os.Setenv(config.EnvHome, globalFlags.DevPodHome) } // apply environment diff --git a/cmd/agent/container/daemon.go b/cmd/agent/container/daemon.go index df75f9cd5..682c5b6a2 100644 --- a/cmd/agent/container/daemon.go +++ b/cmd/agent/container/daemon.go @@ -15,8 +15,8 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/agent" + config2 "github.com/skevetter/devpod/pkg/config" agentd "github.com/skevetter/devpod/pkg/daemon/agent" - "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/ts" "github.com/skevetter/log" @@ -25,8 +25,8 @@ import ( ) const ( - RootDir = "/var/devpod" - DaemonConfigPath = "/var/run/secrets/devpod/daemon_config" + RootDir = agent.ContainerDataDir + DaemonConfigPath = "/var/run/secrets/" + config2.BinaryName + "/daemon_config" ) type DaemonCmd struct { @@ -142,7 +142,7 @@ func (cmd *DaemonCmd) loadConfig() error { if err != nil { if errors.Is(err, os.ErrNotExist) { // check environment variable - encodedCfg = os.Getenv(config.WorkspaceDaemonConfigExtraEnvVar) + encodedCfg = os.Getenv(config2.EnvWorkspaceDaemonConfig) } else { return fmt.Errorf("get daemon config file %s: %w", DaemonConfigPath, err) } diff --git a/cmd/agent/container/setup.go b/cmd/agent/container/setup.go index c674415de..81ddf1784 100644 --- a/cmd/agent/container/setup.go +++ b/cmd/agent/container/setup.go @@ -347,9 +347,10 @@ func (cmd *SetupContainerCmd) startContainerDaemon( return nil } - return command.StartBackgroundOnce("devpod.daemon", func() (*exec.Cmd, error) { + return command.StartBackgroundOnce(config2.BinaryName+".daemon", func() (*exec.Cmd, error) { logger.Debugf( - "start devpod container daemon with inactivity timeout %s", + "start %s container daemon with inactivity timeout %s", + config2.BinaryName, workspaceInfo.ContainerTimeout, ) binaryPath, err := os.Executable() @@ -630,7 +631,7 @@ func configureSystemGitCredentials( } gitCredentials := fmt.Sprintf("!'%s' agent git-credentials --port %d", binaryPath, serverPort) - _ = os.Setenv("DEVPOD_GIT_HELPER_PORT", strconv.Itoa(serverPort)) + _ = os.Setenv(config2.EnvGitHelperPort, strconv.Itoa(serverPort)) err = git.CommandContext(ctx, git.GetDefaultExtraEnv(false), "config", "--system", "--add", "credential.helper", gitCredentials). diff --git a/cmd/agent/container/ssh_server.go b/cmd/agent/container/ssh_server.go index d86f364dc..881589203 100644 --- a/cmd/agent/container/ssh_server.go +++ b/cmd/agent/container/ssh_server.go @@ -7,13 +7,15 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/cmd/flags" + "github.com/skevetter/devpod/pkg/agent" + "github.com/skevetter/devpod/pkg/config" helperssh "github.com/skevetter/devpod/pkg/ssh/server" "github.com/skevetter/devpod/pkg/ssh/server/port" "github.com/skevetter/log" "github.com/spf13/cobra" ) -const BaseLogDir = "/var/devpod" +var BaseLogDir = agent.ContainerDataDir // SSHServerCmd holds the ssh server cmd flags. type SSHServerCmd struct { @@ -74,7 +76,7 @@ func getFileLogger(remoteUser string, debug bool) log.Logger { } fallback := log.NewDiscardLogger(logLevel) - targetFolder := filepath.Join(os.TempDir(), ".devpod") + targetFolder := filepath.Join(os.TempDir(), config.ConfigDirName) if remoteUser != "" { targetFolder = filepath.Join(BaseLogDir, remoteUser) } diff --git a/cmd/agent/container_tunnel.go b/cmd/agent/container_tunnel.go index 28aa40cbb..60f4aa857 100644 --- a/cmd/agent/container_tunnel.go +++ b/cmd/agent/container_tunnel.go @@ -11,9 +11,9 @@ import ( "github.com/skevetter/devpod/cmd/agent/workspace" "github.com/skevetter/devpod/cmd/flags" "github.com/skevetter/devpod/pkg/agent" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer" "github.com/skevetter/devpod/pkg/devcontainer/config" - "github.com/skevetter/devpod/pkg/devcontainer/setup" "github.com/skevetter/devpod/pkg/encoding" provider2 "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/log" @@ -127,7 +127,7 @@ func startDevContainer( } else if encoding.IsLegacyUID(workspaceConfig.Workspace.UID) { // make sure workspace result is in devcontainer buf := &bytes.Buffer{} - err = runner.Command(ctx, "root", "cat "+setup.ResultLocation, nil, buf, buf) + err = runner.Command(ctx, "root", "cat "+pkgconfig.DevContainerResultPath, nil, buf, buf) if err != nil { // start container _, err = StartContainer(ctx, runner, log, workspaceConfig) diff --git a/cmd/agent/workspace/up.go b/cmd/agent/workspace/up.go index db1dcaef1..6a731a2bc 100644 --- a/cmd/agent/workspace/up.go +++ b/cmd/agent/workspace/up.go @@ -17,6 +17,7 @@ import ( "github.com/skevetter/devpod/pkg/agent/tunnelserver" "github.com/skevetter/devpod/pkg/client/clientimplementation" "github.com/skevetter/devpod/pkg/command" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/credentials" agentdaemon "github.com/skevetter/devpod/pkg/daemon/agent" "github.com/skevetter/devpod/pkg/devcontainer" @@ -645,8 +646,8 @@ type credentialsConfig struct { } func configureCredentials(cfg credentialsConfig) (string, string, error) { - if cfg.workspaceInfo.Agent.InjectDockerCredentials != "true" && - cfg.workspaceInfo.Agent.InjectGitCredentials != "true" { + if cfg.workspaceInfo.Agent.InjectDockerCredentials != config.BoolTrue && + cfg.workspaceInfo.Agent.InjectGitCredentials != config.BoolTrue { return "", "", nil } @@ -665,7 +666,7 @@ func configureCredentials(cfg credentialsConfig) (string, string, error) { } dockerCredentials := "" - if cfg.workspaceInfo.Agent.InjectDockerCredentials == "true" { + if cfg.workspaceInfo.Agent.InjectDockerCredentials == config.BoolTrue { dockerCredentials, err = dockercredentials.ConfigureCredentialsMachine( cfg.workspaceInfo.Origin, serverPort, @@ -677,13 +678,13 @@ func configureCredentials(cfg credentialsConfig) (string, string, error) { } gitCredentials := "" - if cfg.workspaceInfo.Agent.InjectGitCredentials == "true" { + if cfg.workspaceInfo.Agent.InjectGitCredentials == config.BoolTrue { gitCredentials = fmt.Sprintf( "!'%s' agent git-credentials --port %d", binaryPath, serverPort, ) - _ = os.Setenv("DEVPOD_GIT_HELPER_PORT", strconv.Itoa(serverPort)) + _ = os.Setenv(config.EnvGitHelperPort, strconv.Itoa(serverPort)) } return dockerCredentials, gitCredentials, nil diff --git a/cmd/build.go b/cmd/build.go index 81bc72663..75a557fab 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -71,13 +71,15 @@ func NewBuildCmd(flags *flags.GlobalFlags) *cobra.Command { } } - if devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == "true" { + if devPodConfig.ContextOption( + config.ContextOptionSSHStrictHostKeyChecking, + ) == config.BoolTrue { cmd.StrictHostKeyChecking = true } // create a temporary workspace exists := workspace2.Exists(ctx, devPodConfig, args, "", cmd.Owner, log.Default) - sshConfigFile, err := os.CreateTemp("", "devpodssh.config") + sshConfigFile, err := os.CreateTemp("", config.BinaryName+"ssh.config") if err != nil { return err } diff --git a/cmd/delete.go b/cmd/delete.go index 33840ed91..fe58f223f 100644 --- a/cmd/delete.go +++ b/cmd/delete.go @@ -74,7 +74,7 @@ func (cmd *DeleteCmd) Run(cobraCmd *cobra.Command, args []string) error { func (cmd *DeleteCmd) loadConfig() (*config.Config, error) { _, err := clientimplementation.DecodeOptionsFromEnv( - clientimplementation.DevPodFlagsDelete, + config.EnvFlagsDelete, &cmd.DeleteOptions, ) if err != nil { diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go index ee132b250..b9b2e1832 100644 --- a/cmd/flags/flags.go +++ b/cmd/flags/flags.go @@ -1,6 +1,7 @@ package flags import ( + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" flag "github.com/spf13/pflag" ) @@ -24,7 +25,7 @@ func SetGlobalFlags(flags *flag.FlagSet) *GlobalFlags { flags.StringVar( &globalFlags.DevPodHome, - "devpod-home", + config.BinaryName+"-home", "", "If defined will override the default devpod home", ) diff --git a/cmd/helper/get_workspace_config.go b/cmd/helper/get_workspace_config.go index 72e9e5845..c0d7945eb 100644 --- a/cmd/helper/get_workspace_config.go +++ b/cmd/helper/get_workspace_config.go @@ -74,7 +74,7 @@ func (cmd *GetWorkspaceConfigCommand) Run( level = logrus.DebugLevel } var logger log.Logger = log.NewStdoutLogger(os.Stdin, os.Stdout, os.Stderr, level) - if os.Getenv("DEVPOD_UI") == "true" { + if os.Getenv(config.EnvUI) == config.BoolTrue { logger = log.Discard } logger.Debugf("Resolving devcontainer config for source: %s", rawSource) @@ -85,7 +85,7 @@ func (cmd *GetWorkspaceConfigCommand) Run( done := make(chan *devcontainer.GetWorkspaceConfigResult, 1) errChan := make(chan error, 1) - tmpDir, err := os.MkdirTemp("", "devpod") + tmpDir, err := os.MkdirTemp("", config.BinaryName) if err != nil { return err } @@ -98,7 +98,9 @@ func (cmd *GetWorkspaceConfigCommand) Run( rawSource, tmpDir, cmd.maxDepth, - devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == "true", + devPodConfig.ContextOption( + config.ContextOptionSSHStrictHostKeyChecking, + ) == config.BoolTrue, logger, ) if err != nil { diff --git a/cmd/ide/use.go b/cmd/ide/use.go index b4ef8f081..0f518450c 100644 --- a/cmd/ide/use.go +++ b/cmd/ide/use.go @@ -87,7 +87,7 @@ func setOptions( userOptions = options2.InheritOptionsFromEnvironment( userOptions, ideOptions, - "DEVPOD_IDE_"+ide+"_", + config.EnvIDEPrefix+ide+"_", ) optionValues, err := ideparse.ParseOptions(userOptions, ideOptions) diff --git a/cmd/pro/daemon/start.go b/cmd/pro/daemon/start.go index 1daf32a08..ea07fc315 100644 --- a/cmd/pro/daemon/start.go +++ b/cmd/pro/daemon/start.go @@ -78,7 +78,7 @@ func (cmd *StartCmd) Run( devPodConfig *config.Config, provider *providerpkg.ProviderConfig, ) error { - isDesktopControlled := os.Getenv("DEVPOD_UI") == "true" + isDesktopControlled := os.Getenv(config.EnvUI) == config.BoolTrue dir, err := ensureDaemonDir(devPodConfig.DefaultContext, provider.Name) if err != nil { return err diff --git a/cmd/pro/login.go b/cmd/pro/login.go index f50896b29..367e4ac9b 100644 --- a/cmd/pro/login.go +++ b/cmd/pro/login.go @@ -23,7 +23,6 @@ import ( const ( PROVIDER_BINARY = "PRO_PROVIDER" - providerRepo = "skevetter/devpod" ) // LoginCmd holds the login cmd flags. @@ -126,7 +125,7 @@ func (cmd *LoginCmd) Run(ctx context.Context, fullURL string, log log.Logger) er } else { // find a provider name if cmd.Provider == "" { - cmd.Provider = "devpod-pro" + cmd.Provider = config.ProReleaseName } cmd.Provider = provider.ToProInstanceID(cmd.Provider) @@ -139,7 +138,7 @@ func (cmd *LoginCmd) Run(ctx context.Context, fullURL string, log log.Logger) er // provider already exists? if providers[cmd.Provider] != nil { // alternative name - cmd.Provider = provider.ToProInstanceID("devpod-" + host) + cmd.Provider = provider.ToProInstanceID(config.BinaryName + "-" + host) if providers[cmd.Provider] != nil { return fmt.Errorf( "provider %s already exists, please choose a different name via --provider", @@ -257,7 +256,7 @@ func (cmd *LoginCmd) addLoftProvider( log.Infof("Add DevPod Pro provider...") // is development? - if cmd.ProviderSource == providerRepo+"@v0.0.0" { + if cmd.ProviderSource == config.RepoSlug+"@v0.0.0" { log.Debugf("Add development provider") _, err = workspace.AddProviderRaw(workspace.ProviderParams{ DevPodConfig: devPodConfig, @@ -284,7 +283,7 @@ func (cmd *LoginCmd) resolveProviderSource(url string) error { return nil } if cmd.Version != "" { - cmd.ProviderSource = providerRepo + "@" + cmd.Version + cmd.ProviderSource = config.RepoSlug + "@" + cmd.Version return nil } @@ -292,7 +291,7 @@ func (cmd *LoginCmd) resolveProviderSource(url string) error { if err != nil { return fmt.Errorf("get version: %w", err) } - cmd.ProviderSource = providerRepo + "@" + version + cmd.ProviderSource = config.RepoSlug + "@" + version return nil } diff --git a/cmd/pro/pro.go b/cmd/pro/pro.go index 32799b452..66fcf4f46 100644 --- a/cmd/pro/pro.go +++ b/cmd/pro/pro.go @@ -37,7 +37,7 @@ func NewProCmd(flags *flags.GlobalFlags, streamLogger *log.StreamLogger) *cobra. streamLogger.SetLevel(logrus.DebugLevel) } - if os.Getenv("DEVPOD_DEBUG") == "true" { + if os.Getenv(config.EnvDebug) == config.BoolTrue { log.Default.SetLevel(logrus.DebugLevel) } if flags.LogOutput == "json" { diff --git a/cmd/pro/provider/create/workspace.go b/cmd/pro/provider/create/workspace.go index 9110b8264..d6246625e 100644 --- a/cmd/pro/provider/create/workspace.go +++ b/cmd/pro/provider/create/workspace.go @@ -9,6 +9,7 @@ import ( managementv1 "github.com/loft-sh/api/v4/pkg/apis/management/v1" "github.com/skevetter/devpod/cmd/pro/flags" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/platform/form" @@ -81,10 +82,10 @@ func (cmd *WorkspaceCmd) Run( } // Info through env, right now only used by CLI - workspaceID := os.Getenv(provider.WORKSPACE_ID) - workspaceUID := os.Getenv(provider.WORKSPACE_UID) - workspaceFolder := os.Getenv(provider.WORKSPACE_FOLDER) - workspaceContext := os.Getenv(provider.WORKSPACE_CONTEXT) + workspaceID := os.Getenv(config.EnvProviderWorkspaceID) + workspaceUID := os.Getenv(config.EnvProviderWorkspaceUID) + workspaceFolder := os.Getenv(config.EnvProviderWorkspaceFolder) + workspaceContext := os.Getenv(config.EnvProviderWorkspaceContext) workspacePicture := os.Getenv(platform.WorkspacePictureEnv) workspaceSource := os.Getenv(platform.WorkspaceSourceEnv) if workspaceUID == "" || workspaceID == "" || workspaceFolder == "" { diff --git a/cmd/pro/provider/get/version.go b/cmd/pro/provider/get/version.go index 39ad2b51e..d5a6656c3 100644 --- a/cmd/pro/provider/get/version.go +++ b/cmd/pro/provider/get/version.go @@ -63,13 +63,13 @@ func (cmd *VersionCmd) Run( return err } - providerContext := os.Getenv(provider.PROVIDER_CONTEXT) + providerContext := os.Getenv(config.EnvProviderContext) if providerContext == "" { providerContext = config.DefaultContext } - providerID := os.Getenv(provider.PROVIDER_ID) + providerID := os.Getenv(config.EnvProviderID) if providerID == "" { - return fmt.Errorf("provider ID %s not defined", providerID) + return fmt.Errorf("provider ID env var %s not defined", config.EnvProviderID) } // get our own version diff --git a/cmd/pro/provider/list/workspaces.go b/cmd/pro/provider/list/workspaces.go index b2a13b685..bd53671b8 100644 --- a/cmd/pro/provider/list/workspaces.go +++ b/cmd/pro/provider/list/workspaces.go @@ -8,11 +8,11 @@ import ( managementv1 "github.com/loft-sh/api/v4/pkg/apis/management/v1" "github.com/skevetter/devpod/cmd/pro/flags" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/platform/labels" "github.com/skevetter/devpod/pkg/platform/project" - "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/log" "github.com/spf13/cobra" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -66,7 +66,7 @@ func (cmd *WorkspacesCmd) Run(ctx context.Context) error { ) } - filterByOwner := os.Getenv(provider.LOFT_FILTER_BY_OWNER) == "true" + filterByOwner := os.Getenv(config.EnvLoftFilterByOwner) == config.BoolTrue workspaces := []*managementv1.DevPodWorkspaceInstance{} for _, p := range projectList.Items { ns := project.ProjectNamespace(p.GetName()) diff --git a/cmd/pro/provider/provider.go b/cmd/pro/provider/provider.go index bcaeb1168..63da6cd78 100644 --- a/cmd/pro/provider/provider.go +++ b/cmd/pro/provider/provider.go @@ -10,10 +10,9 @@ import ( "github.com/skevetter/devpod/cmd/pro/provider/list" "github.com/skevetter/devpod/cmd/pro/provider/update" "github.com/skevetter/devpod/cmd/pro/provider/watch" - "github.com/skevetter/devpod/pkg/client/clientimplementation" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" - "github.com/skevetter/devpod/pkg/telemetry" "github.com/skevetter/log" "github.com/spf13/cobra" ) @@ -33,20 +32,20 @@ func NewProProviderCmd(globalFlags *flags.GlobalFlags) *cobra.Command { log.Default.SetFormat(log.JSONFormat) - if os.Getenv(clientimplementation.DevPodDebug) == "true" { + if os.Getenv(config.EnvDebug) == config.BoolTrue { globalFlags.Debug = true } // Disable debug hints if we execute pro commands from DevPod Desktop // We're reusing the agent.AgentExecutedAnnotation for simplicity, could rename in the future - if os.Getenv(telemetry.UIEnvVar) == "true" { + if os.Getenv(config.EnvUI) == config.BoolTrue { cmd.VisitParents(func(c *cobra.Command) { // find the root command - if c.Name() == "devpod" { + if c.Name() == config.BinaryName { if c.Annotations == nil { c.Annotations = map[string]string{} } - c.Annotations[agent.AgentExecutedAnnotation] = "true" + c.Annotations[agent.AgentExecutedAnnotation] = config.BoolTrue } }) } diff --git a/cmd/pro/provider/ssh.go b/cmd/pro/provider/ssh.go index 18de6787b..f4274e43d 100644 --- a/cmd/pro/provider/ssh.go +++ b/cmd/pro/provider/ssh.go @@ -7,6 +7,7 @@ import ( "os" "github.com/skevetter/devpod/cmd/pro/flags" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/platform/remotecommand" @@ -67,7 +68,7 @@ func (cmd *SshCmd) Run( baseClient, workspace, "ssh", - platform.OptionsFromEnv("DEVPOD_FLAGS_SSH"), + platform.OptionsFromEnv(config.EnvFlagsSSH), cmd.Log, ) if err != nil { diff --git a/cmd/pro/provider/status.go b/cmd/pro/provider/status.go index ace73a25d..504f49fc0 100644 --- a/cmd/pro/provider/status.go +++ b/cmd/pro/provider/status.go @@ -9,6 +9,7 @@ import ( storagev1 "github.com/loft-sh/api/v4/pkg/apis/storage/v1" "github.com/skevetter/devpod/cmd/pro/flags" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/platform/remotecommand" @@ -80,7 +81,7 @@ func (cmd *StatusCmd) Run( baseClient, workspace, "getstatus", - platform.OptionsFromEnv("DEVPOD_FLAGS_STATUS"), + platform.OptionsFromEnv(config.EnvFlagsStatus), cmd.Log, ) if err != nil { diff --git a/cmd/pro/provider/up.go b/cmd/pro/provider/up.go index 503389988..42f26a3ec 100644 --- a/cmd/pro/provider/up.go +++ b/cmd/pro/provider/up.go @@ -11,7 +11,7 @@ import ( storagev1 "github.com/loft-sh/api/v4/pkg/apis/storage/v1" "github.com/sirupsen/logrus" "github.com/skevetter/devpod/cmd/pro/flags" - "github.com/skevetter/devpod/pkg/client/clientimplementation" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/platform/remotecommand" @@ -37,7 +37,7 @@ type streams struct { // NewUpCmd creates a new command. func NewUpCmd(globalFlags *flags.GlobalFlags) *cobra.Command { logLevel := logrus.InfoLevel - if os.Getenv(clientimplementation.DevPodDebug) == "true" || globalFlags.Debug { + if os.Getenv(config.EnvDebug) == config.BoolTrue || globalFlags.Debug { logLevel = logrus.DebugLevel } @@ -112,8 +112,8 @@ func (cmd *UpCmd) up( client client.Client, ) error { options := platform.OptionsFromEnv(storagev1.DevPodFlagsUp) - if options != nil && os.Getenv("DEBUG") == "true" { - options.Add("debug", "true") + if options != nil && os.Getenv(config.EnvDebug) == config.BoolTrue { + options.Add("debug", config.BoolTrue) } conn, err := platform.DialInstance(client, workspace, "up", options, cmd.Log) diff --git a/cmd/pro/provider/watch/workspaces.go b/cmd/pro/provider/watch/workspaces.go index b4aaef4af..b9e92ce11 100644 --- a/cmd/pro/provider/watch/workspaces.go +++ b/cmd/pro/provider/watch/workspaces.go @@ -78,7 +78,7 @@ func (cmd *WorkspacesCmd) Run( cmd.Context = config.DefaultContext } - projectName := os.Getenv(provider.LOFT_PROJECT) + projectName := os.Getenv(config.EnvLoftProject) if projectName == "" { return fmt.Errorf("project name not found") } @@ -104,7 +104,7 @@ func (cmd *WorkspacesCmd) Run( workspaceInformer := factory.Management().V1().DevPodWorkspaceInstances() self := baseClient.Self() - filterByOwner := os.Getenv(provider.LOFT_FILTER_BY_OWNER) == "true" + filterByOwner := os.Getenv(config.EnvLoftFilterByOwner) == config.BoolTrue instanceStore := newStore(workspaceInformer, self, cmd.Context, filterByOwner, cmd.Log) _, err = workspaceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ diff --git a/cmd/pro/start.go b/cmd/pro/start.go index 7955089ad..69be1e6fc 100644 --- a/cmd/pro/start.go +++ b/cmd/pro/start.go @@ -27,6 +27,7 @@ import ( "github.com/mgutz/ansi" "github.com/sirupsen/logrus" proflags "github.com/skevetter/devpod/cmd/pro/flags" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/util" @@ -54,7 +55,7 @@ const ( defaultUser = "admin" ) -const defaultReleaseName = "devpod-pro" +var defaultReleaseName = config.ProReleaseName var defaultDeploymentName = "loft" // Need to update helm chart if we change this! @@ -93,8 +94,8 @@ type StartCmd struct { func NewStartCmd(flags *proflags.GlobalFlags) *cobra.Command { cmd := &StartCmd{ GlobalFlags: *flags, - Product: "devpod-pro", - ChartName: "devpod-pro", + Product: config.ProReleaseName, + ChartName: config.ProReleaseName, Log: log.Default, } startCmd := &cobra.Command{ @@ -112,7 +113,7 @@ func NewStartCmd(flags *proflags.GlobalFlags) *cobra.Command { startCmd.Flags(). StringVar(&cmd.Context, "context", "", "The kube context to use for installation") startCmd.Flags(). - StringVar(&cmd.Namespace, "namespace", "devpod-pro", "The namespace to install into") + StringVar(&cmd.Namespace, "namespace", config.ProReleaseName, "The namespace to install into") startCmd.Flags(). StringVar(&cmd.Host, "host", "", "Provide a hostname to enable ingress and configure its hostname") startCmd.Flags(). @@ -271,7 +272,7 @@ func (cmd *StartCmd) appendReleaseArgs(extraArgs []string) []string { } func writePasswordValuesFile(password string) (string, error) { - f, err := os.CreateTemp("", "devpod-values-*.yaml") + f, err := os.CreateTemp("", config.BinaryName+"-values-*.yaml") if err != nil { return "", fmt.Errorf("create temp values file: %w", err) } @@ -570,7 +571,7 @@ Thanks for using DevPod Pro! func (cmd *StartCmd) startDocker(ctx context.Context) error { cmd.Log.Infof("Starting DevPod Pro in Docker...") - name := "devpod-pro" + name := config.ProReleaseName // prepare installation err := cmd.prepareDocker() @@ -1388,7 +1389,7 @@ func uninstall( kubeContext, namespace string, log log.Logger, ) error { - releaseName := "devpod-pro" + releaseName := config.ProReleaseName deploy, err := kubeClient.AppsV1(). Deployments(namespace). Get(ctx, defaultDeploymentName, metav1.GetOptions{}) @@ -1555,7 +1556,7 @@ func enterHostNameQuestion(log log.Logger) (string, error) { return log.Question(&survey.QuestionOptions{ Question: fmt.Sprintf( "Enter a hostname for your %s instance (e.g. loft.my-domain.tld): \n ", - "DevPod Pro", + config.ProductNamePro, ), ValidationFunc: func(answer string) error { u, err := netUrl.Parse("https://" + answer) diff --git a/cmd/pro/version.go b/cmd/pro/version.go index 836633095..a030d9835 100644 --- a/cmd/pro/version.go +++ b/cmd/pro/version.go @@ -60,8 +60,8 @@ func (cmd *VersionCmd) Run( providerConfig *provider.ProviderConfig, ) error { opts := devPodConfig.ProviderOptions(providerConfig.Name) - opts[provider.PROVIDER_ID] = config.OptionValue{Value: providerConfig.Name} - opts[provider.PROVIDER_CONTEXT] = config.OptionValue{Value: cmd.Context} + opts[config.EnvProviderID] = config.OptionValue{Value: providerConfig.Name} + opts[config.EnvProviderContext] = config.OptionValue{Value: cmd.Context} var buf bytes.Buffer // ignore --debug because we tunnel json through stdio diff --git a/cmd/pro/watch_workspaces.go b/cmd/pro/watch_workspaces.go index df3aacd30..289707c12 100644 --- a/cmd/pro/watch_workspaces.go +++ b/cmd/pro/watch_workspaces.go @@ -72,9 +72,9 @@ func (cmd *WatchWorkspacesCmd) Run( defer cancel() if cmd.FilterByOwner { - opts[provider.LOFT_FILTER_BY_OWNER] = config.OptionValue{Value: "true"} + opts[config.EnvLoftFilterByOwner] = config.OptionValue{Value: "true"} } - opts[provider.LOFT_PROJECT] = config.OptionValue{Value: cmd.Project} + opts[config.EnvLoftProject] = config.OptionValue{Value: cmd.Project} sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT) diff --git a/cmd/provider/list-default-providers.go b/cmd/provider/list-default-providers.go index e96f334b1..2bb274524 100644 --- a/cmd/provider/list-default-providers.go +++ b/cmd/provider/list-default-providers.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/skevetter/devpod/cmd/flags" + "github.com/skevetter/devpod/pkg/config" devpodhttp "github.com/skevetter/devpod/pkg/http" "github.com/spf13/cobra" ) @@ -43,13 +44,13 @@ func (cmd *ListAvailableCmd) Run(ctx context.Context) error { return err } - _, _ = fmt.Fprintln(os.Stdout, "List of available providers from skevetter:") + _, _ = fmt.Fprintln(os.Stdout, "List of available providers from "+config.RepoOwner+":") for _, v := range jsonResult { name, ok := v["name"].(string) if !ok || name == "" { continue } - if after, ok0 := strings.CutPrefix(name, "devpod-provider-"); ok0 { + if after, ok0 := strings.CutPrefix(name, config.ProviderPrefix); ok0 { _, _ = fmt.Fprintln(os.Stdout, "\t", after) } } @@ -60,7 +61,7 @@ func (cmd *ListAvailableCmd) Run(ctx context.Context) error { func fetchProviderRepos(ctx context.Context) ([]map[string]any, error) { req, err := http.NewRequestWithContext(ctx, "GET", - "https://api.github.com/users/skevetter/repos?per_page=100", + config.GitHubAPIUserURL+"/repos?per_page=100", nil, ) if err != nil { diff --git a/cmd/provider/set_options.go b/cmd/provider/set_options.go index 87c6cab20..103b97991 100644 --- a/cmd/provider/set_options.go +++ b/cmd/provider/set_options.go @@ -80,7 +80,7 @@ func (cmd *SetOptionsCmd) Run(ctx context.Context, args []string, log log.Logger } log.Debugf("providerName=%+v", providerName) - if os.Getenv("DEVPOD_UI") == "" && len(cmd.Options) == 0 { + if os.Getenv(config.EnvUI) == "" && len(cmd.Options) == 0 { return fmt.Errorf("please specify option") } log.Debugf("Options=%+v", cmd.Options) diff --git a/cmd/provider/update.go b/cmd/provider/update.go index f55ee5d59..5f80e8e0f 100644 --- a/cmd/provider/update.go +++ b/cmd/provider/update.go @@ -49,7 +49,7 @@ func NewUpdateCmd(flags *flags.GlobalFlags) *cobra.Command { func (cmd *UpdateCmd) Run(ctx context.Context, devPodConfig *config.Config, args []string) error { if len(args) != 1 && len(args) != 2 { return fmt.Errorf("please specify either a local file, URL or Git repository. " + - "E.g. devpod provider update my-provider skevetter/devpod-provider-gcloud") + "E.g. devpod provider update my-provider " + config.ProviderPrefix + "gcloud") } providerSource := "" diff --git a/cmd/provider/use.go b/cmd/provider/use.go index 3568306f1..1decf9db8 100644 --- a/cmd/provider/use.go +++ b/cmd/provider/use.go @@ -181,7 +181,7 @@ func configureProviderOptions( cfg.UserOptions = options2.InheritOptionsFromEnvironment( cfg.UserOptions, cfg.Provider.Options, - "DEVPOD_PROVIDER_"+cfg.Provider.Name+"_", + config.EnvProviderPrefix+cfg.Provider.Name+"_", ) // parse options diff --git a/cmd/root.go b/cmd/root.go index b4d70eaca..55112cd19 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,7 +17,6 @@ import ( "github.com/skevetter/devpod/cmd/pro" "github.com/skevetter/devpod/cmd/provider" "github.com/skevetter/devpod/cmd/use" - "github.com/skevetter/devpod/pkg/client/clientimplementation" "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/telemetry" log2 "github.com/skevetter/log" @@ -32,7 +31,7 @@ var globalFlags *flags.GlobalFlags // NewRootCmd returns a new root command. func NewRootCmd() *cobra.Command { return &cobra.Command{ - Use: "devpod", + Use: config.BinaryName, Short: "DevPod", SilenceUsage: true, SilenceErrors: true, @@ -52,12 +51,12 @@ func NewRootCmd() *cobra.Command { log2.Default.SetLevel(logrus.FatalLevel) } else if globalFlags.Debug { log2.Default.SetLevel(logrus.DebugLevel) - } else if os.Getenv(clientimplementation.DevPodDebug) == "true" { + } else if os.Getenv(config.EnvDebug) == config.BoolTrue { log2.Default.SetLevel(logrus.DebugLevel) } if globalFlags.DevPodHome != "" { - _ = os.Setenv(config.DEVPOD_HOME, globalFlags.DevPodHome) + _ = os.Setenv(config.EnvHome, globalFlags.DevPodHome) } devPodConfig, err := config.LoadConfig(globalFlags.Context, globalFlags.Provider) @@ -69,7 +68,7 @@ func NewRootCmd() *cobra.Command { }, PersistentPostRunE: func(cmd *cobra.Command, args []string) error { if globalFlags.DevPodHome != "" { - _ = os.Unsetenv(config.DEVPOD_HOME) + _ = os.Unsetenv(config.EnvHome) } return nil @@ -102,10 +101,10 @@ func Execute() { log2.Default.Fatalf("%+v", err) } else { if rootCmd.Annotations == nil || - rootCmd.Annotations[agent.AgentExecutedAnnotation] != "true" { + rootCmd.Annotations[agent.AgentExecutedAnnotation] != config.BoolTrue { if terminal.IsTerminalIn { log2.Default.Error("Try using the --debug flag to see a more verbose output") - } else if os.Getenv(telemetry.UIEnvVar) == "true" { + } else if os.Getenv(config.EnvUI) == config.BoolTrue { log2.Default.Error( "Try enabling Debug mode under Settings to see a more verbose output", ) @@ -167,13 +166,13 @@ func inheritFlagsFromEnvironment(flags *flag.FlagSet) { // calculate environment variable name from flag name suffix := strings.ToUpper(strings.ReplaceAll(flag.Name, "-", "_")) - // do not prepend "DEVPOD_" to the environment variable name if the flag name starts with "devpod" + // do not prepend the env prefix if the flag name already starts with it // (applies to one flag - "devpod-home"). var environmentVariable string - if strings.HasPrefix(suffix, "DEVPOD_") { + if strings.HasPrefix(suffix, config.EnvPrefix) { environmentVariable = suffix } else { - environmentVariable = "DEVPOD_" + suffix + environmentVariable = config.EnvPrefix + suffix } if value, exists := os.LookupEnv(environmentVariable); exists { diff --git a/cmd/ssh.go b/cmd/ssh.go index 1d23f7189..e6371a84d 100644 --- a/cmd/ssh.go +++ b/cmd/ssh.go @@ -171,8 +171,8 @@ func (cmd *SSHCmd) Run( log log.Logger, ) error { // add ssh keys to agent - if devPodConfig.ContextOption(config.ContextOptionSSHAgentForwarding) == "true" && - devPodConfig.ContextOption(config.ContextOptionSSHAddPrivateKeys) == "true" { + if devPodConfig.ContextOption(config.ContextOptionSSHAgentForwarding) == config.BoolTrue && + devPodConfig.ContextOption(config.ContextOptionSSHAddPrivateKeys) == config.BoolTrue { log.Debug( "adding ssh keys to agent, disable via 'devpod context set-options -o SSH_ADD_PRIVATE_KEYS=false'", ) @@ -268,7 +268,7 @@ func (cmd *SSHCmd) jumpContainerTailscale( // Handle GPG agent forwarding if cmd.GPGAgentForwarding || - devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == "true" { + devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == config.BoolTrue { if gpg.IsGpgTunnelRunning(ctx, cmd.User, toolSSHClient, log) { log.Debugf("[GPG] exporting already running, skipping") } else if err := cmd.setupGPGAgent(ctx, toolSSHClient, log); err != nil { @@ -501,13 +501,13 @@ func (cmd *SSHCmd) startTunnel( if cmd.StartServices { configureDockerCredentials := devPodConfig.ContextOption( config.ContextOptionSSHInjectDockerCredentials, - ) == "true" + ) == config.BoolTrue configureGitCredentials := devPodConfig.ContextOption( config.ContextOptionSSHInjectGitCredentials, - ) == "true" + ) == config.BoolTrue configureGitSSHSignatureHelper := devPodConfig.ContextOption( config.ContextOptionGitSSHSignatureForwarding, - ) == "true" + ) == config.BoolTrue go cmd.startServices( ctx, @@ -526,7 +526,7 @@ func (cmd *SSHCmd) startTunnel( // check if we should do gpg agent forwarding if cmd.GPGAgentForwarding || - devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == "true" { + devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == config.BoolTrue { // Check if a forwarding is already enabled and running, in that case // we skip the forwarding and keep using the original one if gpg.IsGpgTunnelRunning(ctx, cmd.User, containerClient, log) { @@ -584,7 +584,7 @@ func (cmd *SSHCmd) startTunnel( User: cmd.User, Command: cmd.Command, AgentForwarding: cmd.AgentForwarding && - devPodConfig.ContextOption(config.ContextOptionSSHAgentForwarding) == "true", + devPodConfig.ContextOption(config.ContextOptionSSHAgentForwarding) == config.BoolTrue, SessionOptions: machine.SSHSessionOptions{ TermMode: cmd.TermMode, InstallTerminfo: cmd.InstallTerminfo, diff --git a/cmd/status.go b/cmd/status.go index f85532477..0dca185b5 100644 --- a/cmd/status.go +++ b/cmd/status.go @@ -35,7 +35,7 @@ func NewStatusCmd(flags *flags.GlobalFlags) *cobra.Command { Short: "Shows the status of a workspace", RunE: func(cobraCmd *cobra.Command, args []string) error { _, err := clientimplementation.DecodeOptionsFromEnv( - clientimplementation.DevPodFlagsStatus, + config.EnvFlagsStatus, &cmd.StatusOptions, ) if err != nil { diff --git a/cmd/up.go b/cmd/up.go index deb7d9c90..61c7c3390 100644 --- a/cmd/up.go +++ b/cmd/up.go @@ -94,7 +94,7 @@ func (cmd *UpCmd) execute(cobraCmd *cobra.Command, args []string) error { if err != nil { return err } - if devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == "true" { + if devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == config.BoolTrue { cmd.StrictHostKeyChecking = true } @@ -362,11 +362,11 @@ func (cmd *UpCmd) configureWorkspace( ) error { if cmd.ConfigureSSH { devPodHome := "" - if envDevPodHome, ok := os.LookupEnv("DEVPOD_HOME"); ok { + if envDevPodHome, ok := os.LookupEnv(config.EnvHome); ok { devPodHome = envDevPodHome } setupGPGAgentForwarding := cmd.GPGAgentForwarding || - devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == "true" + devPodConfig.ContextOption(config.ContextOptionGPGAgentForwarding) == config.BoolTrue sshConfigIncludePath := devPodConfig.ContextOption(config.ContextOptionSSHConfigIncludePath) if err := configureSSH(client, configureSSHParams{ @@ -533,7 +533,7 @@ func (o *ideOpener) openVSCodeFlavor( params := vscode.OpenParams{ Workspace: o.client.Workspace(), Folder: folder, - NewWindow: vscode.Options.GetValue(ideOptions, vscode.OpenNewWindow) == "true", + NewWindow: vscode.Options.GetValue(ideOptions, vscode.OpenNewWindow) == config.BoolTrue, Flavor: flavorMap[ideName], Log: o.log, } @@ -819,12 +819,14 @@ func (cmd *UpCmd) devPodUpMachine( } return sshtunnel.ExecuteCommand(ctx, sshtunnel.ExecuteCommandOptions{ - Client: client, - AddPrivateKeys: devPodConfig.ContextOption(config.ContextOptionSSHAddPrivateKeys) == "true", - AgentInject: agentInjectFunc, - SSHCommand: sshTunnelCmd, - Command: agentCommand, - Log: log, + Client: client, + AddPrivateKeys: devPodConfig.ContextOption( + config.ContextOptionSSHAddPrivateKeys, + ) == config.BoolTrue, + AgentInject: agentInjectFunc, + SSHCommand: sshTunnelCmd, + Command: agentCommand, + Log: log, TunnelServerFunc: func(ctx context.Context, stdin io.WriteCloser, stdout io.Reader) (*config2.Result, error) { return tunnelserver.RunUpServer( ctx, @@ -867,7 +869,7 @@ func startJupyterNotebookInBrowser( // wait until reachable then open browser targetURL := fmt.Sprintf("http://localhost:%d/lab", jupyterPort) - if jupyter.Options.GetValue(ideOptions, jupyter.OpenOption) == "true" { + if jupyter.Options.GetValue(ideOptions, jupyter.OpenOption) == config.BoolTrue { go func() { err = open2.Open(ctx, targetURL, logger) if err != nil { @@ -925,7 +927,7 @@ func startRStudioInBrowser( // wait until reachable then open browser targetURL := fmt.Sprintf("http://localhost:%d", port) - if rstudio.Options.GetValue(ideOptions, rstudio.OpenOption) == "true" { + if rstudio.Options.GetValue(ideOptions, rstudio.OpenOption) == config.BoolTrue { go func() { err = open2.Open(ctx, targetURL, logger) if err != nil { @@ -1018,7 +1020,7 @@ func startVSCodeInBrowser( // wait until reachable then open browser targetURL := fmt.Sprintf("http://localhost:%d/?folder=%s", vscodePort, workspaceFolder) - if openvscode.Options.GetValue(ideOptions, openvscode.OpenOption) == "true" { + if openvscode.Options.GetValue(ideOptions, openvscode.OpenOption) == config.BoolTrue { go func() { err = open2.Open(ctx, targetURL, logger) if err != nil { @@ -1033,7 +1035,10 @@ func startVSCodeInBrowser( // start in browser logger.Infof("Starting vscode in browser mode at %s", targetURL) - forwardPorts := openvscode.Options.GetValue(ideOptions, openvscode.ForwardPortsOption) == "true" + forwardPorts := openvscode.Options.GetValue( + ideOptions, + openvscode.ForwardPortsOption, + ) == config.BoolTrue extraPorts := []string{fmt.Sprintf("%s:%d", vscodeAddress, openvscode.DefaultVSCodePort)} return startBrowserTunnel( ctx, @@ -1213,13 +1218,13 @@ func startBrowserTunnel( configureDockerCredentials := devPodConfig.ContextOption( config.ContextOptionSSHInjectDockerCredentials, - ) == "true" + ) == config.BoolTrue configureGitCredentials := devPodConfig.ContextOption( config.ContextOptionSSHInjectGitCredentials, - ) == "true" + ) == config.BoolTrue configureGitSSHSignatureHelper := devPodConfig.ContextOption( config.ContextOptionGitSSHSignatureForwarding, - ) == "true" + ) == config.BoolTrue // run in container err := tunnel.RunServices( @@ -1300,7 +1305,7 @@ func configureSSH(client client2.BaseWorkspaceClient, params configureSSHParams) func mergeDevPodUpOptions(baseOptions *provider2.CLIOptions) error { oldOptions := *baseOptions found, err := clientimplementation.DecodeOptionsFromEnv( - clientimplementation.DevPodFlagsUp, + config.EnvFlagsUp, baseOptions, ) if err != nil { @@ -1444,7 +1449,7 @@ func buildDotCmdAgentArguments( dotfilesRepo, } - if devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == "true" { + if devPodConfig.ContextOption(config.ContextOptionSSHStrictHostKeyChecking) == config.BoolTrue { agentArguments = append(agentArguments, "--strict-host-key-checking") } @@ -1574,7 +1579,7 @@ func setupGitSSHSignature( client.Workspace(), "--command", shellescape.QuoteCommand( - []string{"devpod", "agent", "git-ssh-signature-helper", signingKey}, + []string{config.BinaryName, "agent", "git-ssh-signature-helper", signingKey}, ), ).CombinedOutput() if err != nil { diff --git a/desktop/src/App/useChangelogModal.tsx b/desktop/src/App/useChangelogModal.tsx index 92cf896eb..ef695b4be 100644 --- a/desktop/src/App/useChangelogModal.tsx +++ b/desktop/src/App/useChangelogModal.tsx @@ -14,9 +14,10 @@ import { useEffect, useMemo, useState } from "react" import { Release } from "@/gen" import { useReleases } from "@/lib" import { useVersion } from "@/lib/useVersion" +import { BINARY_NAME } from "@/client/repo" import { Changelog } from "./Changelog" -const LAST_INSTALLED_VERSION_KEY = "devpod-last-installed-version" +const LAST_INSTALLED_VERSION_KEY = `${BINARY_NAME}-last-installed-version` export function useChangelogModal(isReady: boolean) { const currentVersion = useVersion() diff --git a/desktop/src/client/client.ts b/desktop/src/client/client.ts index 124d3f2a8..43fc717f3 100644 --- a/desktop/src/client/client.ts +++ b/desktop/src/client/client.ts @@ -12,6 +12,7 @@ import * as process from "@tauri-apps/plugin-process" import { Command } from "@tauri-apps/plugin-shell" import * as updater from "@tauri-apps/plugin-updater" import { TSettings } from "@/contexts" +import { BINARY_NAME } from "./repo" import { Release } from "@/gen" import { Result, Return, hasCapability, isError, noop } from "@/lib" import { TCommunityContributions, TProInstance, TUnsubscribeFn } from "@/types" @@ -315,13 +316,13 @@ class Client { const home_dir = await this.getEnv("HOME") // this will throw if doesn't exist const exists = await invoke("file_exists", { - filepath: home_dir + "/.local/bin/devpod", + filepath: home_dir + `/.local/bin/${BINARY_NAME}`, }) return Return.Value(exists) } - const result = await Command.create("run-path-devpod", ["version"]).execute() + const result = await Command.create(`run-path-${BINARY_NAME}`, ["version"]).execute() if (result.code !== 0) { return Return.Value(false) } diff --git a/desktop/src/client/command.ts b/desktop/src/client/command.ts index 8f4f00394..9fcb96e36 100644 --- a/desktop/src/client/command.ts +++ b/desktop/src/client/command.ts @@ -11,6 +11,7 @@ import { DEVPOD_UI_ENV_VAR, DEVPOD_ADDITIONAL_ENV_VARS, } from "./constants" +import { FLATPAK_ID } from "./repo" import { TStreamEvent } from "./types" import { TAURI_SERVER_URL } from "./tauriClient" import { invoke } from "@tauri-apps/api/core" @@ -91,7 +92,7 @@ export class Command implements TCommand> { if (this.isFlatpak === undefined) { this.isFlatpak = await this.getEnv("FLATPAK_ID") if (this.isFlatpak) { - this.extraEnvVars["FLATPAK_ID"] = "sh.loft.devpod" + this.extraEnvVars["FLATPAK_ID"] = FLATPAK_ID this.extraEnvVars[DEVPOD_ADDITIONAL_ENV_VARS] = recordToCSV(this.extraEnvVars) this.sidecarCommand = ShellCommand.sidecar(DEVPOD_BINARY, this.args, { env: this.extraEnvVars, diff --git a/desktop/src/client/constants.ts b/desktop/src/client/constants.ts index c8be78a53..7a17256c7 100644 --- a/desktop/src/client/constants.ts +++ b/desktop/src/client/constants.ts @@ -1,4 +1,6 @@ -export const DEVPOD_GIT_REPOSITORY = "https://github.com/skevetter/devpod" +import { BINARY_NAME, GITHUB_REPO_URL } from "./repo" + +export const DEVPOD_GIT_REPOSITORY = GITHUB_REPO_URL export const DEFAULT_STATIC_COMMAND_CONFIG = { streamResponse: false, @@ -7,7 +9,7 @@ export const DEFAULT_STATIC_COMMAND_CONFIG = { /** placeholder for arbitrary additional flags */ export const WORKSPACE_COMMAND_ADDITIONAL_FLAGS_KEY = "additionalFlags" -export const DEVPOD_BINARY = "bin/devpod" +export const DEVPOD_BINARY = `bin/${BINARY_NAME}` export const DEVPOD_COMMAND_LIST = "list" export const DEVPOD_COMMAND_STATUS = "status" export const DEVPOD_COMMAND_UP = "up" diff --git a/desktop/src/client/repo.ts b/desktop/src/client/repo.ts new file mode 100644 index 000000000..4e14da47e --- /dev/null +++ b/desktop/src/client/repo.ts @@ -0,0 +1,21 @@ +export const REPO_OWNER = "skevetter" +export const REPO_NAME = "devpod" +export const REPO_SLUG = `${REPO_OWNER}/${REPO_NAME}` +export const BINARY_NAME = REPO_NAME +export const PRODUCT_NAME = "DevPod" +export const PRODUCT_NAME_PRO = `${PRODUCT_NAME} Pro` +export const PRO_RELEASE_NAME = `${REPO_NAME}-pro` +export const PROVIDER_PREFIX = `${REPO_NAME}-provider-` +export const SSH_HOST_SUFFIX = `.${BINARY_NAME}` + +export const GITHUB_REPO_URL = `https://github.com/${REPO_SLUG}` +export const GITHUB_RELEASES_URL = `${GITHUB_REPO_URL}/releases` +export const GITHUB_ISSUES_URL = `${GITHUB_REPO_URL}/issues/new/choose` +export const WEBSITE_BASE_URL = `https://${REPO_NAME}.sh` +export const WEBSITE_DOCS_URL = `${WEBSITE_BASE_URL}/docs` +export const WEBSITE_PRO_URL = `${WEBSITE_BASE_URL}/pro` +export const WEBSITE_ASSETS_URL = `${WEBSITE_BASE_URL}/assets` + +export const FLATPAK_ID = `sh.loft.${REPO_NAME}` +export const CONTAINER_NAME = BINARY_NAME +export const SHARED_MACHINE_PREFIX = `${BINARY_NAME}-shared-` diff --git a/desktop/src/components/Layout/ProSwitcher.tsx b/desktop/src/components/Layout/ProSwitcher.tsx index 09b9032f0..aff6e7635 100644 --- a/desktop/src/components/Layout/ProSwitcher.tsx +++ b/desktop/src/components/Layout/ProSwitcher.tsx @@ -1,4 +1,5 @@ import { client } from "@/client/client" +import { WEBSITE_PRO_URL } from "@/client/repo" import { useProInstances, useProviders, useSettings } from "@/contexts" import { CheckCircle, CircleWithArrow, DevPodProBadge, ExclamationTriangle } from "@/icons" import { @@ -49,7 +50,7 @@ export function ProSwitcher() { const backgroundColor = useColorModeValue("white", "gray.900") const handleAnnouncementClicked = () => { - client.openUrl("https://devpod.sh/pro") + client.openUrl(WEBSITE_PRO_URL) } const { experimental_devPodPro } = useSettings() const isProUnauthenticated = proInstances?.some(({ authenticated }) => !authenticated) @@ -248,7 +249,7 @@ function EmptyProInstances({ onConnect }: TEmptyProInstancesProps) { You don't have any Pro instances set up. Connect to an existing Instance or create a new one.
- client.openUrl("https://devpod.sh/pro")}> + client.openUrl(WEBSITE_PRO_URL)}> Learn more
diff --git a/desktop/src/components/Layout/StatusBar.tsx b/desktop/src/components/Layout/StatusBar.tsx index 81cabf8b9..d5cd9872f 100644 --- a/desktop/src/components/Layout/StatusBar.tsx +++ b/desktop/src/components/Layout/StatusBar.tsx @@ -26,6 +26,7 @@ import { useMemo, useRef } from "react" import { FaBug } from "react-icons/fa" import { HiDocumentMagnifyingGlass, HiMagnifyingGlassPlus } from "react-icons/hi2" import { client } from "@/client/client" +import { BINARY_NAME, GITHUB_REPO_URL, GITHUB_ISSUES_URL, WEBSITE_DOCS_URL } from "@/client/repo" import { useChangeSettings } from "@/contexts" import { Debug, useDebug } from "@/lib" import { useArch, usePlatform } from "@/lib/systemInfo" @@ -107,7 +108,7 @@ function GitHubStar() { rounded="full" icon={} aria-label="Loving DevPod? Give us a star on GitHub" - onClick={() => client.openUrl("https://github.com/skevetter/devpod")} + onClick={() => client.openUrl(GITHUB_REPO_URL)} /> ) @@ -123,7 +124,7 @@ function OSSDocs() { rounded="full" icon={} aria-label="How to DevPod - Docs" - onClick={() => client.openUrl("https://devpod.sh/docs")} + onClick={() => client.openUrl(WEBSITE_DOCS_URL)} /> ) @@ -139,7 +140,7 @@ function OSSReportIssue() { rounded="full" icon={} aria-label="Report an Issue" - onClick={() => client.openUrl("https://github.com/skevetter/devpod/issues/new/choose")} + onClick={() => client.openUrl(GITHUB_ISSUES_URL)} /> ) @@ -168,7 +169,7 @@ function DebugMenu() { const url = new URL(rawLink.replace(/#/g, "?")) const workspaceUID = url.searchParams.get("workspace-uid") const workspaceID = url.searchParams.get("workspace-id") - const host = url.searchParams.get("devpod-pro-host") + const host = url.searchParams.get(`${BINARY_NAME}-pro-host`) const project = url.searchParams.get("project") if (!workspaceUID || !workspaceID || !host || !project) { console.error( diff --git a/desktop/src/components/LoftOSSBadge.tsx b/desktop/src/components/LoftOSSBadge.tsx index 568a092dd..2869958dd 100644 --- a/desktop/src/components/LoftOSSBadge.tsx +++ b/desktop/src/components/LoftOSSBadge.tsx @@ -1,5 +1,6 @@ import { Link, Text } from "@chakra-ui/react" import { client } from "@/client/client" +import { GITHUB_REPO_URL } from "@/client/repo" export function LoftOSSBadge() { return ( @@ -7,7 +8,7 @@ export function LoftOSSBadge() { display="flex" alignItems="center" justifyContent="start" - onClick={() => client.openUrl("https://github.com/skevetter/devpod")}> + onClick={() => client.openUrl(GITHUB_REPO_URL)}> community maintained diff --git a/desktop/src/components/useInstallCLI.tsx b/desktop/src/components/useInstallCLI.tsx index e07b002c4..0cec6a87c 100644 --- a/desktop/src/components/useInstallCLI.tsx +++ b/desktop/src/components/useInstallCLI.tsx @@ -15,6 +15,7 @@ import { import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query" import { useMemo, useRef } from "react" import { client } from "@/client/client" +import { FLATPAK_ID } from "@/client/repo" import { CheckCircle, ExclamationCircle } from "@/icons" import { Err, Failed, isError, isMacOS, isWindows } from "@/lib" import { QueryKeys } from "@/queryKeys" @@ -115,7 +116,7 @@ export function useInstallCLI() { Adds the DevPod CLI to your $PATH.{" "} {isWindows ? ( <> - It will be placed in %APP_DATA%\sh.loft.devpod\bin + It will be placed in {`%APPDATA%\\${FLATPAK_ID}\\bin`} ) : ( <> diff --git a/desktop/src/contexts/DevPodContext/Pro/ProProvider.tsx b/desktop/src/contexts/DevPodContext/Pro/ProProvider.tsx index 92be50175..e835bc6f1 100644 --- a/desktop/src/contexts/DevPodContext/Pro/ProProvider.tsx +++ b/desktop/src/contexts/DevPodContext/Pro/ProProvider.tsx @@ -1,4 +1,5 @@ import { client as globalClient } from "@/client/client" +import { BINARY_NAME } from "@/client/repo" import { DaemonClient } from "@/client/pro/client" import { TWorkspaceOwnerFilterState } from "@/components" import { ToolbarActions, ToolbarTitle } from "@/components/Layout/Toolbar" @@ -203,7 +204,7 @@ export function ProProvider({ host, children }: { host: string; children: ReactN ) } -const PROJECT_STORAGE_KEY = "devpod_current_project" +const PROJECT_STORAGE_KEY = `${BINARY_NAME}_current_project` function getProjectStorageKey(host: string) { return `${PROJECT_STORAGE_KEY}_${host}` diff --git a/desktop/src/contexts/DevPodContext/action/actionHistory.ts b/desktop/src/contexts/DevPodContext/action/actionHistory.ts index 41f52c27d..1a9af73c5 100644 --- a/desktop/src/contexts/DevPodContext/action/actionHistory.ts +++ b/desktop/src/contexts/DevPodContext/action/actionHistory.ts @@ -1,6 +1,7 @@ import { Action, TActionObj, TActions } from "./action" +import { BINARY_NAME } from "@/client/repo" -const HISTORY_KEY = "devpod-workspace-action-history" +const HISTORY_KEY = `${BINARY_NAME}-workspace-action-history` const MAX_HISTORY_ENTRIES = 50 export class ActionHistory { diff --git a/desktop/src/contexts/DevPodContext/proInstances/useProInstanceManager.ts b/desktop/src/contexts/DevPodContext/proInstances/useProInstanceManager.ts index 3463768a5..16608b9e0 100644 --- a/desktop/src/contexts/DevPodContext/proInstances/useProInstanceManager.ts +++ b/desktop/src/contexts/DevPodContext/proInstances/useProInstanceManager.ts @@ -1,4 +1,5 @@ import { DaemonClient } from "@/client/pro/client" +import { PRO_RELEASE_NAME } from "@/client/repo" import { Err, Failed } from "@/lib" import { useMutation, useQueryClient } from "@tanstack/react-query" import { useMemo } from "react" @@ -6,7 +7,7 @@ import { client } from "@/client" import { QueryKeys } from "@/queryKeys" import { TProInstanceLoginConfig, TProInstanceManager, TProvider, TWithProID } from "@/types" -const FALLBACK_PROVIDER_NAME = "devpod-pro" +const FALLBACK_PROVIDER_NAME = PRO_RELEASE_NAME export function useProInstanceManager(): TProInstanceManager { const queryClient = useQueryClient() diff --git a/desktop/src/lib/store.ts b/desktop/src/lib/store.ts index 0d5bfc67d..da4426fac 100644 --- a/desktop/src/lib/store.ts +++ b/desktop/src/lib/store.ts @@ -1,4 +1,5 @@ import { LazyStore } from "@tauri-apps/plugin-store" +import { BINARY_NAME } from "@/client/repo" import { TUnsubscribeFn } from "@/types" import { EventManager } from "./eventManager" import { exists } from "./helpers" @@ -49,7 +50,7 @@ export class LocalStorageBackend implements TStorageBacken constructor(private storageKey: string) {} private getKey(key: keyof TBaseStore): string { - return `devpod-${this.storageKey}-${key.toString()}` + return `${BINARY_NAME}-${this.storageKey}-${key.toString()}` } public async set(key: TKey, value: T[TKey]): Promise { diff --git a/desktop/src/lib/useStoreTroubleshoot.ts b/desktop/src/lib/useStoreTroubleshoot.ts index 2b5019cd0..93aade8e9 100644 --- a/desktop/src/lib/useStoreTroubleshoot.ts +++ b/desktop/src/lib/useStoreTroubleshoot.ts @@ -1,4 +1,5 @@ import { client } from "@/client/client" +import { BINARY_NAME } from "@/client/repo" import { TActionObj } from "@/contexts/DevPodContext/action" import { TWorkspace } from "@/types" import { useToast } from "@chakra-ui/react" @@ -68,7 +69,7 @@ export function useStoreTroubleshoot() { const out = await zip.generateAsync({ type: "uint8array" }) - await client.writeFile([targetFolder, "devpod_troubleshoot.zip"], out) + await client.writeFile([targetFolder, `${BINARY_NAME}_troubleshoot.zip`], out) return true }, diff --git a/desktop/src/main.tsx b/desktop/src/main.tsx index b163fbf35..77bd71dda 100644 --- a/desktop/src/main.tsx +++ b/desktop/src/main.tsx @@ -11,6 +11,7 @@ import { ThemeProvider } from "./Theme/ThemeProvider" import { SettingsProvider } from "./contexts" import { router } from "./routes" import { client } from "./client/client" +import { BINARY_NAME } from "./client/repo" import { ColorModeScript } from "@chakra-ui/react" dayjs.extend(relativeTime) @@ -31,7 +32,7 @@ const logger: Logger | undefined = import.meta.env.PROD const queryClient = new QueryClient({ logger }) let render = true -const l = localStorage.getItem("devpod-location-current") // check usePreserveLocation before changing this +const l = localStorage.getItem(`${BINARY_NAME}-location-current`) // check usePreserveLocation before changing this if (l) { const loc = JSON.parse(l) as Location if (window.location.pathname !== loc.pathname) { diff --git a/desktop/src/useWelcomeModal.tsx b/desktop/src/useWelcomeModal.tsx index a90c61a08..b2b2f486e 100644 --- a/desktop/src/useWelcomeModal.tsx +++ b/desktop/src/useWelcomeModal.tsx @@ -16,11 +16,12 @@ import { import { useCallback, useEffect, useMemo, useState } from "react" import { useNavigate } from "react-router" import { client } from "./client" +import { BINARY_NAME, GITHUB_RELEASES_URL, WEBSITE_DOCS_URL } from "./client/repo" import { LoftOSSBadge, Step, Steps, useInstallCLI } from "./components" import { Briefcase, CommandLine, DevpodWordmark } from "./icons" import { Routes } from "./routes.constants" -const IS_FIRST_VISIT_KEY = "devpod-is-first-visit" +const IS_FIRST_VISIT_KEY = `${BINARY_NAME}-is-first-visit` export function useWelcomeModal() { const navigate = useNavigate() @@ -98,9 +99,7 @@ export function useWelcomeModal() { cloud. It's also possible to extend DevPod and write your own custom providers.
For more information, head over to our{" "} - client.openUrl("https://devpod.sh/docs")}> - documentation. - + client.openUrl(WEBSITE_DOCS_URL)}>documentation. Let's set you up! @@ -117,10 +116,7 @@ export function useWelcomeModal() { DevPod ships with a powerful CLI that allows you to create, manage and connect to your workspaces and providers. You can either{" "} - - client.openUrl("https://github.com/skevetter/devpod/releases") - }> + client.openUrl(GITHUB_RELEASES_URL)}> download the standalone binary {" "} or directly add it to your $PATH. diff --git a/desktop/src/views/Pro/CreateWorkspace/IDEInput.tsx b/desktop/src/views/Pro/CreateWorkspace/IDEInput.tsx index 39cfd8ea9..9e505121a 100644 --- a/desktop/src/views/Pro/CreateWorkspace/IDEInput.tsx +++ b/desktop/src/views/Pro/CreateWorkspace/IDEInput.tsx @@ -1,4 +1,5 @@ import { IDEIcon } from "@/components" +import { SSH_HOST_SUFFIX } from "@/client/repo" import { TIDE } from "@/types" import { InfoIcon } from "@chakra-ui/icons" import { Box, Card, HStack, Text, Tooltip, useColorModeValue } from "@chakra-ui/react" @@ -47,7 +48,8 @@ function IDECard({ name, isSelected, icon, onClick }: TIDECardProps) { SSH - + diff --git a/desktop/src/views/Pro/Workspace/WorkspaceDetails.tsx b/desktop/src/views/Pro/Workspace/WorkspaceDetails.tsx index d224f82f8..b26668b20 100644 --- a/desktop/src/views/Pro/Workspace/WorkspaceDetails.tsx +++ b/desktop/src/views/Pro/Workspace/WorkspaceDetails.tsx @@ -1,4 +1,5 @@ import { ProWorkspaceInstance } from "@/contexts" +import { CONTAINER_NAME } from "@/client/repo" import { CPU, Clock, @@ -65,7 +66,7 @@ export function WorkspaceDetails({ const mainContainerImage = useMemo( () => instance.status?.kubernetes?.podStatus?.containerStatuses?.find( - ({ name }) => name === "devpod" + ({ name }) => name === CONTAINER_NAME )?.image, [instance.status?.kubernetes] ) @@ -347,14 +348,14 @@ function KubernetesDetails({ status }: TKubernetesDetailsProps) { const storageCapacity = status.persistentVolumeClaimStatus?.capacity?.["storage"] const resources = useMemo(() => { const mainContainerResources = status.podStatus?.containerResources?.find( - ({ name }) => name === "devpod" + ({ name }) => name === CONTAINER_NAME ) if (!mainContainerResources) { return [] } const mainContainerMetrics = status.podStatus?.containerMetrics?.find( - ({ name }) => name === "devpod" + ({ name }) => name === CONTAINER_NAME ) const indexedMetrics: Record = {} if (mainContainerMetrics?.usage) { @@ -438,7 +439,7 @@ function PodStatus({ podStatus }: { podStatus: StorageV1DevPodWorkspaceInstanceP // check container status first const containerStatus = podStatus.containerStatuses?.find( (container) => - container.name === "devpod" && + container.name === CONTAINER_NAME && (container.state?.waiting?.reason || container.state?.terminated?.reason) ) if (containerStatus) { diff --git a/desktop/src/views/Providers/AddProvider/SetupProviderSourceForm.tsx b/desktop/src/views/Providers/AddProvider/SetupProviderSourceForm.tsx index be6c66245..9e85b8555 100644 --- a/desktop/src/views/Providers/AddProvider/SetupProviderSourceForm.tsx +++ b/desktop/src/views/Providers/AddProvider/SetupProviderSourceForm.tsx @@ -48,6 +48,7 @@ import { useCommunityContributions } from "@/useCommunityContributions" import { LoadingProviderIndicator } from "./LoadingProviderIndicator" import { FieldName, TFormValues, TSetupProviderResult } from "./types" import { useAddProvider } from "./useAddProvider" +import { PROVIDER_PREFIX, REPO_OWNER } from "@/client/repo" import { PROVIDER_NAME_REGEX } from "../../../lib/validation" const DEFAULT_VAL_OPTS: SetValueConfig = { shouldDirty: true, @@ -490,7 +491,7 @@ function CustomProviderInput({ field, isInvalid, onAccept }: TCustomProviderInpu We never collect any actual values, only anonymized metadata! For an in-depth explanation, please refer to the{" "} - client.openUrl("https://devpod.sh/docs/other-topics/telemetry")}> + client.openUrl(`${WEBSITE_DOCS_URL}/other-topics/telemetry`)}> documentation diff --git a/desktop/src/views/Workspaces/CreateWorkspace/CreateWorkspace.tsx b/desktop/src/views/Workspaces/CreateWorkspace/CreateWorkspace.tsx index 37dd675e5..60be056e2 100644 --- a/desktop/src/views/Workspaces/CreateWorkspace/CreateWorkspace.tsx +++ b/desktop/src/views/Workspaces/CreateWorkspace/CreateWorkspace.tsx @@ -48,6 +48,7 @@ import { WorkspaceSourceInput } from "./WorkspaceSourceInput" import { COMMUNITY_WORKSPACE_EXAMPLES, WORKSPACE_EXAMPLES } from "./constants" import { FieldName, TCreateWorkspaceArgs, TFormValues, TSelectProviderOptions } from "./types" import { useCreateWorkspaceForm } from "./useCreateWorkspaceForm" +import { SHARED_MACHINE_PREFIX } from "@/client/repo" export function CreateWorkspace() { const { ides } = useIDEs() @@ -458,7 +459,7 @@ function ProviderInput({ options, field, onAddProviderClicked }: TProviderInputP return ( provider?.state?.singleMachine && workspace.provider?.name === provider.config?.name && - workspace.machine?.machineId?.startsWith("devpod-shared-") + workspace.machine?.machineId?.startsWith(SHARED_MACHINE_PREFIX) ) })?.id }, [provider, workspaces]) diff --git a/desktop/src/views/Workspaces/WorkspaceControls.tsx b/desktop/src/views/Workspaces/WorkspaceControls.tsx index 66925d749..c196bbe8a 100644 --- a/desktop/src/views/Workspaces/WorkspaceControls.tsx +++ b/desktop/src/views/Workspaces/WorkspaceControls.tsx @@ -22,6 +22,7 @@ import { import { useMemo, useCallback, useState } from "react" import { HiOutlineCode, HiShare } from "react-icons/hi" import { client } from "@/client/client" +import { BINARY_NAME, WEBSITE_BASE_URL } from "@/client/repo" import { IDEGroup, IDEIcon } from "@/components" import { TActionID, useProInstances } from "@/contexts" import { @@ -286,9 +287,9 @@ function useShareWorkspace( const searchParams = new URLSearchParams() searchParams.set("workspace-uid", workspace_uid) searchParams.set("workspace-id", workspace_id) - searchParams.set("devpod-pro-host", devpodProHost) + searchParams.set(`${BINARY_NAME}-pro-host`, devpodProHost) - const link = `https://devpod.sh/import#${searchParams.toString()}` + const link = `${WEBSITE_BASE_URL}/import#${searchParams.toString()}` const res = await client.writeToClipboard(link) if (!res.ok) { toast({ diff --git a/hack/pro/main.go b/hack/pro/main.go index adaa71afb..736e8138c 100644 --- a/hack/pro/main.go +++ b/hack/pro/main.go @@ -9,6 +9,8 @@ import ( "os" "path/filepath" "strings" + + "github.com/skevetter/devpod/pkg/config" ) //go:embed provider.yaml @@ -24,12 +26,13 @@ func main() { basePath = os.Args[2] } + bin := config.BinaryName checksumMap := map[string]string{ - filepath.Join(basePath, "devpod-linux-amd64"): "##CHECKSUM_LINUX_AMD64##", - filepath.Join(basePath, "devpod-linux-arm64"): "##CHECKSUM_LINUX_ARM64##", - filepath.Join(basePath, "devpod-darwin-amd64"): "##CHECKSUM_DARWIN_AMD64##", - filepath.Join(basePath, "devpod-darwin-arm64"): "##CHECKSUM_DARWIN_ARM64##", - filepath.Join(basePath, "devpod-windows-amd64.exe"): "##CHECKSUM_WINDOWS_AMD64##", + filepath.Join(basePath, bin+"-linux-amd64"): "##CHECKSUM_LINUX_AMD64##", + filepath.Join(basePath, bin+"-linux-arm64"): "##CHECKSUM_LINUX_ARM64##", + filepath.Join(basePath, bin+"-darwin-amd64"): "##CHECKSUM_DARWIN_AMD64##", + filepath.Join(basePath, bin+"-darwin-arm64"): "##CHECKSUM_DARWIN_ARM64##", + filepath.Join(basePath, bin+"-windows-amd64.exe"): "##CHECKSUM_WINDOWS_AMD64##", } partial := os.Getenv("PARTIAL") == "true" diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index fae14f244..8a074d089 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -16,6 +16,7 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/command" "github.com/skevetter/devpod/pkg/compress" + "github.com/skevetter/devpod/pkg/config" provider2 "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/devpod/pkg/version" "github.com/skevetter/log" @@ -23,28 +24,27 @@ import ( const DefaultInactivityTimeout = time.Minute * 20 -const ContainerDevPodHelperLocation = "/usr/local/bin/devpod" +// ContainerDataDir is the base directory for DevPod data inside containers. +const ContainerDataDir = "/var/" + config.BinaryName -const RemoteDevPodHelperLocation = "/tmp/devpod" +const ContainerDevPodHelperLocation = "/usr/local/bin/" + config.BinaryName -const ContainerActivityFile = "/tmp/devpod.activity" +const RemoteDevPodHelperLocation = "/tmp/" + config.BinaryName -const defaultAgentDownloadURL = "https://github.com/skevetter/devpod/releases/download/" +const ContainerActivityFile = "/tmp/" + config.BinaryName + ".activity" -const EnvDevPodAgentURL = "DEVPOD_AGENT_URL" - -const EnvDevPodAgentPreferDownload = "DEVPOD_AGENT_PREFER_DOWNLOAD" +var defaultAgentDownloadURL = config.GitHubReleasesURL + "/download/" const WorkspaceBusyFile = "workspace.lock" func DefaultAgentDownloadURL() string { - devPodAgentURL := os.Getenv(EnvDevPodAgentURL) + devPodAgentURL := os.Getenv(config.EnvAgentURL) if devPodAgentURL != "" { return strings.TrimRight(devPodAgentURL, "/") } if version.GetVersion() == version.DevVersion { - return "https://github.com/skevetter/devpod/releases/latest/download" + return config.GitHubReleasesURL + "/latest/download" } return defaultAgentDownloadURL + version.GetVersion() @@ -411,7 +411,7 @@ func writeWorkspaceInfo(file string, workspaceInfo *provider2.AgentWorkspaceInfo func rerunAsRoot(workspaceInfo *provider2.AgentWorkspaceInfo, log log.Logger) (bool, error) { // check if root is required if runtime.GOOS != "linux" || os.Getuid() == 0 || - (workspaceInfo != nil && workspaceInfo.Agent.Local == "true") { + (workspaceInfo != nil && workspaceInfo.Agent.Local == config.BoolTrue) { return false, nil } diff --git a/pkg/agent/agent_test.go b/pkg/agent/agent_test.go index b4a82cc74..ffaa8efb4 100644 --- a/pkg/agent/agent_test.go +++ b/pkg/agent/agent_test.go @@ -4,6 +4,7 @@ import ( "os" "testing" + "github.com/skevetter/devpod/pkg/config" "github.com/stretchr/testify/suite" ) @@ -13,31 +14,31 @@ type AgentTestSuite struct { } func (s *AgentTestSuite) SetupTest() { - s.originalEnv = os.Getenv(EnvDevPodAgentURL) + s.originalEnv = os.Getenv(config.EnvAgentURL) } func (s *AgentTestSuite) TearDownTest() { if s.originalEnv != "" { - _ = os.Setenv(EnvDevPodAgentURL, s.originalEnv) + _ = os.Setenv(config.EnvAgentURL, s.originalEnv) } else { - _ = os.Unsetenv(EnvDevPodAgentURL) + _ = os.Unsetenv(config.EnvAgentURL) } } func (s *AgentTestSuite) TestDefaultAgentDownloadURL_NoTrailingSlash() { - _ = os.Setenv(EnvDevPodAgentURL, "https://example.com/releases/latest/download") + _ = os.Setenv(config.EnvAgentURL, "https://example.com/releases/latest/download") result := DefaultAgentDownloadURL() s.Equal("https://example.com/releases/latest/download", result) } func (s *AgentTestSuite) TestDefaultAgentDownloadURL_SingleTrailingSlash() { - _ = os.Setenv(EnvDevPodAgentURL, "https://example.com/releases/latest/download/") + _ = os.Setenv(config.EnvAgentURL, "https://example.com/releases/latest/download/") result := DefaultAgentDownloadURL() s.Equal("https://example.com/releases/latest/download", result) } func (s *AgentTestSuite) TestDefaultAgentDownloadURL_MultipleTrailingSlashes() { - _ = os.Setenv(EnvDevPodAgentURL, "https://example.com/releases/latest/download///") + _ = os.Setenv(config.EnvAgentURL, "https://example.com/releases/latest/download///") result := DefaultAgentDownloadURL() s.Equal("https://example.com/releases/latest/download", result) } diff --git a/pkg/agent/binary.go b/pkg/agent/binary.go index b907e85f3..a2b64dd1c 100644 --- a/pkg/agent/binary.go +++ b/pkg/agent/binary.go @@ -11,6 +11,7 @@ import ( "runtime" "strings" + "github.com/skevetter/devpod/pkg/config" devpodhttp "github.com/skevetter/devpod/pkg/http" "github.com/skevetter/log" ) @@ -26,7 +27,7 @@ type BinaryManager struct { } func NewBinaryManager(logger log.Logger, downloadURL string) *BinaryManager { - cachePath := filepath.Join(os.TempDir(), "devpod-cache") + cachePath := filepath.Join(os.TempDir(), config.BinaryName+"-cache") cache := &BinaryCache{BaseDir: cachePath} return &BinaryManager{ @@ -64,7 +65,7 @@ func (c *BinaryCache) Set(arch string, data io.Reader) error { } func (c *BinaryCache) pathFor(arch string) string { - return filepath.Join(c.BaseDir, "devpod-"+osLinux+"-"+arch) + return filepath.Join(c.BaseDir, config.BinaryName+"-"+osLinux+"-"+arch) } func (c *BinaryCache) atomicWrite(path string, data io.Reader) error { @@ -72,7 +73,7 @@ func (c *BinaryCache) atomicWrite(path string, data io.Reader) error { return err } - file, err := os.CreateTemp(filepath.Dir(path), "devpod-*.tmp") + file, err := os.CreateTemp(filepath.Dir(path), config.BinaryName+"-*.tmp") if err != nil { return err } @@ -167,7 +168,7 @@ func (s *HTTPDownloadSource) SourceName() string { } func (s *HTTPDownloadSource) buildDownloadURL(arch string) (string, error) { - binaryName := "devpod-" + osLinux + "-" + arch + binaryName := config.BinaryName + "-" + osLinux + "-" + arch downloadURL, err := url.JoinPath(s.BaseURL, binaryName) if err != nil { return "", fmt.Errorf("failed to construct download URL: %w", err) @@ -297,7 +298,7 @@ func (s *HTTPDownloadSource) createTempFile( pw *io.PipeWriter, streamErr *error, ) (*os.File, string, error) { - file, err := os.CreateTemp(filepath.Dir(cachePath), "devpod-agent-*.tmp") + file, err := os.CreateTemp(filepath.Dir(cachePath), config.BinaryName+"-agent-*.tmp") if err != nil { if _, copyErr := io.Copy(pw, body); copyErr != nil { *streamErr = copyErr diff --git a/pkg/agent/inject.go b/pkg/agent/inject.go index cf45455c9..94c9d3daa 100644 --- a/pkg/agent/inject.go +++ b/pkg/agent/inject.go @@ -12,6 +12,7 @@ import ( "time" "github.com/sirupsen/logrus" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/inject" "github.com/skevetter/devpod/pkg/shell" "github.com/skevetter/devpod/pkg/version" @@ -139,9 +140,9 @@ func (o *InjectOptions) applyPreferDownloadDefaults() { } isDefaultURL := o.DownloadURL == DefaultAgentDownloadURL() - hasCustomAgentURL := os.Getenv(EnvDevPodAgentURL) != "" || !isDefaultURL + hasCustomAgentURL := os.Getenv(config.EnvAgentURL) != "" || !isDefaultURL - preferDownloadEnv := os.Getenv(EnvDevPodAgentPreferDownload) + preferDownloadEnv := os.Getenv(config.EnvAgentPreferDownload) switch { case preferDownloadEnv != "": o.applyEnvPreference(preferDownloadEnv) @@ -159,7 +160,7 @@ func (o *InjectOptions) applyPreferDownloadDefaults() { func (o *InjectOptions) applyEnvPreference(preferDownloadEnv string) { pref, err := strconv.ParseBool(preferDownloadEnv) if err != nil { - o.Log.Warnf("failed to parse %s, using default", EnvDevPodAgentPreferDownload) + o.Log.Warnf("failed to parse %s, using default", config.EnvAgentPreferDownload) pref = true } o.PreferDownloadFromRemoteUrl = Bool(pref) diff --git a/pkg/agent/tunnelserver/tunnelserver.go b/pkg/agent/tunnelserver/tunnelserver.go index d98c50e28..c2bfc92ea 100644 --- a/pkg/agent/tunnelserver/tunnelserver.go +++ b/pkg/agent/tunnelserver/tunnelserver.go @@ -15,6 +15,7 @@ import ( "github.com/moby/patternmatcher/ignorefile" "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/agent/tunnel" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/dockercredentials" "github.com/skevetter/devpod/pkg/extract" @@ -446,13 +447,13 @@ func (t *tunnelServer) StreamWorkspace( // Get .devpodignore files to exclude excludes := []string{} - f, err := os.Open(filepath.Join(t.workspace.Source.LocalFolder, ".devpodignore")) + f, err := os.Open(filepath.Join(t.workspace.Source.LocalFolder, pkgconfig.IgnoreFileName)) if err == nil { excludes, err = ignorefile.ReadAll(f) if err != nil { t.log.WithFields(logrus.Fields{ "error": err, - }).Warn("error reading .devpodignore file") + }).Warn("error reading " + pkgconfig.IgnoreFileName + " file") } } @@ -491,13 +492,13 @@ func (t *tunnelServer) StreamMount( // Get .devpodignore files to exclude excludes := []string{} if t.workspace != nil { - f, err := os.Open(filepath.Join(t.workspace.Source.LocalFolder, ".devpodignore")) + f, err := os.Open(filepath.Join(t.workspace.Source.LocalFolder, pkgconfig.IgnoreFileName)) if err == nil { excludes, err = ignorefile.ReadAll(f) if err != nil { t.log.WithFields(logrus.Fields{ "error": err, - }).Warn("error reading .devpodignore file") + }).Warn("error reading " + pkgconfig.IgnoreFileName + " file") } } } diff --git a/pkg/agent/workspace.go b/pkg/agent/workspace.go index e2bc5c17e..e9c16f2ad 100644 --- a/pkg/agent/workspace.go +++ b/pkg/agent/workspace.go @@ -29,10 +29,10 @@ import ( ) var extraSearchLocations = []string{ - "/home/devpod/.devpod/agent", + "/home/devpod/" + config.ConfigDirName + "/agent", "/opt/devpod/agent", "/var/lib/devpod/agent", - "/var/devpod/agent", + ContainerDataDir + "/agent", } var ErrFindAgentHomeFolder = fmt.Errorf("couldn't find devpod home directory") @@ -52,7 +52,7 @@ func findDir(agentFolder string, validate func(path string) bool) string { } // check environment - homeFolder := os.Getenv(config.DEVPOD_HOME) + homeFolder := os.Getenv(config.EnvHome) if homeFolder != "" { homeFolder = filepath.Join(homeFolder, "agent") if !validate(homeFolder) { @@ -65,7 +65,7 @@ func findDir(agentFolder string, validate func(path string) bool) string { // check home folder first homeDir, _ := util.UserHomeDir() if homeDir != "" { - homeDir = filepath.Join(homeDir, ".devpod", "agent") + homeDir = filepath.Join(homeDir, config.ConfigDirName, "agent") if validate(homeDir) { return homeDir } @@ -74,7 +74,7 @@ func findDir(agentFolder string, validate func(path string) bool) string { // check root folder homeDir, _ = command.GetHome("root") if homeDir != "" { - homeDir = filepath.Join(homeDir, ".devpod", "agent") + homeDir = filepath.Join(homeDir, config.ConfigDirName, "agent") if validate(homeDir) { return homeDir } @@ -153,7 +153,7 @@ func isDirExecutable(dir string) (bool, error) { return false, err } - testFile := filepath.Join(dir, "devpod_test.sh") + testFile := filepath.Join(dir, config.BinaryName+"_test.sh") // #nosec G306,G703 -- TODO Consider using a more secure permission setting and ownership if needed. if err := os.WriteFile(testFile, []byte(`#!/bin/sh echo DevPod @@ -426,20 +426,22 @@ func CloneRepositoryForWorkspace( log.Done("cloned repository") // Get .devpodignore files to exclude - f, err := os.Open(filepath.Join(workspaceDir, ".devpodignore")) + f, err := os.Open( + filepath.Join(workspaceDir, config.IgnoreFileName), + ) // #nosec G304 -- path is controlled by the application, not user input if err != nil { return nil } excludes, err := ignorefile.ReadAll(f) if err != nil { - log.Warn(".devpodignore file is invalid : ", err) + log.Warn(config.IgnoreFileName+" file is invalid : ", err) return nil } // Remove files from workspace content folder for _, exclude := range excludes { _ = os.RemoveAll(filepath.Join(workspaceDir, exclude)) } - log.Debug("Ignore files from .devpodignore ", excludes) + log.Debug("Ignore files from "+config.IgnoreFileName+" ", excludes) return nil } diff --git a/pkg/client/clientimplementation/daemonclient/client.go b/pkg/client/clientimplementation/daemonclient/client.go index be3efc367..27ba183a7 100644 --- a/pkg/client/clientimplementation/daemonclient/client.go +++ b/pkg/client/clientimplementation/daemonclient/client.go @@ -30,15 +30,6 @@ import ( "tailscale.com/tailcfg" ) -var ( - DevPodDebug = "DEVPOD_DEBUG" - - DevPodFlagsUp = "DEVPOD_FLAGS_UP" - DevPodFlagsSsh = "DEVPOD_FLAGS_SSH" - DevPodFlagsDelete = "DEVPOD_FLAGS_DELETE" - DevPodFlagsStatus = "DEVPOD_FLAGS_STATUS" -) - func New( devPodConfig *config.Config, prov *provider.ProviderConfig, diff --git a/pkg/client/clientimplementation/daemonclient/up.go b/pkg/client/clientimplementation/daemonclient/up.go index 092542aa7..29b18e449 100644 --- a/pkg/client/clientimplementation/daemonclient/up.go +++ b/pkg/client/clientimplementation/daemonclient/up.go @@ -14,6 +14,7 @@ import ( storagev1 "github.com/loft-sh/api/v4/pkg/apis/storage/v1" "github.com/loft-sh/apiserver/pkg/builders" clientpkg "github.com/skevetter/devpod/pkg/client" + devpodconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" devpodlog "github.com/skevetter/devpod/pkg/log" "github.com/skevetter/devpod/pkg/platform" @@ -44,8 +45,9 @@ func (c *client) Up(ctx context.Context, opt clientpkg.UpOptions) (*config.Resul } // check if the workspace is migrated and we need to force recreate or reset - if instance.Annotations["loft.sh/migrated"] == "true" && !opt.Recreate && !opt.Reset { - if os.Getenv("DEVPOD_UI") == "true" { + if instance.Annotations["loft.sh/migrated"] == devpodconfig.BoolTrue && !opt.Recreate && + !opt.Reset { + if os.Getenv(devpodconfig.EnvUI) == devpodconfig.BoolTrue { return nil, fmt.Errorf( "workspace %s is migrated and needs to be rebuild or reset. "+ "Please click on rebuild or reset on the workspace to do this", diff --git a/pkg/client/clientimplementation/machine_client.go b/pkg/client/clientimplementation/machine_client.go index 958a030cf..da9506886 100644 --- a/pkg/client/clientimplementation/machine_client.go +++ b/pkg/client/clientimplementation/machine_client.go @@ -176,7 +176,12 @@ func (s *machineClient) AgentPath() string { } func (s *machineClient) AgentLocal() bool { - return options.ResolveAgentConfig(s.devPodConfig, s.config, nil, s.machine).Local == "true" + return options.ResolveAgentConfig( + s.devPodConfig, + s.config, + nil, + s.machine, + ).Local == config.BoolTrue } func (s *machineClient) AgentURL() string { diff --git a/pkg/client/clientimplementation/proxy_client.go b/pkg/client/clientimplementation/proxy_client.go index 1e44d0b86..69598bd9d 100644 --- a/pkg/client/clientimplementation/proxy_client.go +++ b/pkg/client/clientimplementation/proxy_client.go @@ -27,17 +27,6 @@ import ( "github.com/skevetter/log/terminal" ) -var ( - DevPodDebug = "DEVPOD_DEBUG" - - DevPodPlatformOptions = "DEVPOD_PLATFORM_OPTIONS" - - DevPodFlagsUp = "DEVPOD_FLAGS_UP" - DevPodFlagsSsh = "DEVPOD_FLAGS_SSH" - DevPodFlagsDelete = "DEVPOD_FLAGS_DELETE" - DevPodFlagsStatus = "DEVPOD_FLAGS_STATUS" -) - const ( lockTimeout = 5 * time.Minute lockRetry = time.Second @@ -276,7 +265,7 @@ func (s *proxyClient) Ssh(ctx context.Context, opt client.SshOptions) error { return s.executor.executeWithJSONLog(ctx, execParams{ name: "ssh", command: s.config.Exec.Proxy.Ssh, - extraEnv: EncodeOptions(opt, DevPodFlagsSsh), + extraEnv: EncodeOptions(opt, config.EnvFlagsSSH), stdin: opt.Stdin, stdout: opt.Stdout, }) @@ -294,7 +283,7 @@ func (s *proxyClient) Stop(ctx context.Context, opt client.StopOptions) error { } func (s *proxyClient) Up(ctx context.Context, opt client.UpOptions) error { - opts := EncodeOptions(opt.CLIOptions, DevPodFlagsUp) + opts := EncodeOptions(opt.CLIOptions, config.EnvFlagsUp) if opt.Debug { opts["DEBUG"] = "true" } @@ -363,7 +352,7 @@ func (s *proxyClient) Delete(ctx context.Context, opt client.DeleteOptions) erro err := s.executor.executeWithJSONLog(ctx, execParams{ name: "delete", command: s.config.Exec.Proxy.Delete, - extraEnv: EncodeOptions(opt, DevPodFlagsDelete), + extraEnv: EncodeOptions(opt, config.EnvFlagsDelete), stdout: io.Discard, }) if err != nil && !opt.Force { @@ -399,7 +388,7 @@ func (s *proxyClient) Status( Machine: nil, Options: s.devPodConfig.ProviderOptions(s.config.Name), Config: s.config, - ExtraEnv: EncodeOptions(options, DevPodFlagsStatus), + ExtraEnv: EncodeOptions(options, config.EnvFlagsStatus), Stdin: nil, Stdout: io.MultiWriter(stdout, buf), Stderr: buf, @@ -459,7 +448,7 @@ func DecodeOptionsFromEnv(name string, into any) (bool, error) { } func DecodePlatformOptionsFromEnv(into *devpod.PlatformOptions) error { - raw := os.Getenv(DevPodPlatformOptions) + raw := os.Getenv(config.EnvPlatformOptions) if raw == "" { return nil } diff --git a/pkg/client/clientimplementation/services.go b/pkg/client/clientimplementation/services.go index c20d2706c..42469fc7b 100644 --- a/pkg/client/clientimplementation/services.go +++ b/pkg/client/clientimplementation/services.go @@ -73,13 +73,13 @@ func getCredentialConfig( cfg := credentialConfig{ docker: devPodConfig.ContextOption( config.ContextOptionSSHInjectDockerCredentials, - ) == "true", + ) == config.BoolTrue, git: devPodConfig.ContextOption( config.ContextOptionSSHInjectGitCredentials, - ) == "true", + ) == config.BoolTrue, gitSSHSignature: devPodConfig.ContextOption( config.ContextOptionGitSSHSignatureForwarding, - ) == "true", + ) == config.BoolTrue, } if workspace == nil || workspace.Status.Instance == nil { diff --git a/pkg/client/clientimplementation/workspace_client.go b/pkg/client/clientimplementation/workspace_client.go index d172635da..b7a112d54 100644 --- a/pkg/client/clientimplementation/workspace_client.go +++ b/pkg/client/clientimplementation/workspace_client.go @@ -93,7 +93,7 @@ func (s *workspaceClient) AgentLocal() bool { s.config, s.workspace, s.machine, - ).Local == "true" + ).Local == config.BoolTrue } func (s *workspaceClient) AgentPath() string { @@ -178,14 +178,14 @@ func (s *workspaceClient) AgentInjectGitCredentials(cliOptions provider.CLIOptio s.m.Lock() defer s.m.Unlock() - return s.agentInfo(cliOptions).Agent.InjectGitCredentials == "true" + return s.agentInfo(cliOptions).Agent.InjectGitCredentials == config.BoolTrue } func (s *workspaceClient) AgentInjectDockerCredentials(cliOptions provider.CLIOptions) bool { s.m.Lock() defer s.m.Unlock() - return s.agentInfo(cliOptions).Agent.InjectDockerCredentials == "true" + return s.agentInfo(cliOptions).Agent.InjectDockerCredentials == config.BoolTrue } func (s *workspaceClient) AgentInfo( @@ -794,7 +794,7 @@ func RunCommand(opts RunCommandOptions) error { // Add debug env var if logger provided and in debug mode if opts.Log != nil && opts.Log.GetLevel() == logrus.DebugLevel { - opts.Environ = append(opts.Environ, DevPodDebug+"=true") + opts.Environ = append(opts.Environ, config.EnvDebug+"="+config.BoolTrue) } // use shell if command length is equal 1 diff --git a/pkg/config/dir.go b/pkg/config/dir.go index 51b144118..d0db0e8f2 100644 --- a/pkg/config/dir.go +++ b/pkg/config/dir.go @@ -7,14 +7,11 @@ import ( "github.com/skevetter/devpod/pkg/util" ) -// Override devpod home. -const DEVPOD_HOME = "DEVPOD_HOME" - -// Override config path. -const DEVPOD_CONFIG = "DEVPOD_CONFIG" +// ConfigDirName is the hidden directory name used for DevPod configuration. +const ConfigDirName = "." + RepoName func GetConfigDir() (string, error) { - homeDir := os.Getenv(DEVPOD_HOME) + homeDir := os.Getenv(EnvHome) if homeDir != "" { return homeDir, nil } @@ -24,12 +21,12 @@ func GetConfigDir() (string, error) { return "", err } - configDir := filepath.Join(homeDir, ".devpod") + configDir := filepath.Join(homeDir, ConfigDirName) return configDir, nil } func GetConfigPath() (string, error) { - configOrigin := os.Getenv(DEVPOD_CONFIG) + configOrigin := os.Getenv(EnvConfig) if configOrigin == "" { configDir, err := GetConfigDir() if err != nil { diff --git a/pkg/config/env.go b/pkg/config/env.go new file mode 100644 index 000000000..e9503c612 --- /dev/null +++ b/pkg/config/env.go @@ -0,0 +1,149 @@ +package config + +// BoolTrue and BoolFalse are the string representations used for boolean +// configuration values throughout the application (env vars, options, agent config). +const ( + BoolTrue = "true" + BoolFalse = "false" +) + +// Environment variable constants used throughout the application. +// All constants follow the EnvXxx naming convention. +const ( + // EnvBinaryPath is set to the path of the DevPod binary. + EnvBinaryPath = "DEVPOD" + + // EnvHome overrides the default DevPod home directory. + EnvHome = "DEVPOD_HOME" + + // EnvConfig overrides the default config file path. + EnvConfig = "DEVPOD_CONFIG" + + // EnvUI indicates the desktop UI is active. + EnvUI = "DEVPOD_UI" + + // EnvDebug enables debug logging. + EnvDebug = "DEVPOD_DEBUG" + + // EnvDisableTelemetry disables telemetry collection. + EnvDisableTelemetry = "DEVPOD_DISABLE_TELEMETRY" + + // EnvAgentURL overrides the agent download URL. + EnvAgentURL = "DEVPOD_AGENT_URL" + + // EnvAgentPreferDownload forces agent binary download even if a local copy exists. + EnvAgentPreferDownload = "DEVPOD_AGENT_PREFER_DOWNLOAD" + + // EnvOS is set to the host operating system (runtime.GOOS). + EnvOS = "DEVPOD_OS" + + // EnvArch is set to the host architecture (runtime.GOARCH). + EnvArch = "DEVPOD_ARCH" + + // EnvLogLevel is set to the current log level. + EnvLogLevel = "DEVPOD_LOG_LEVEL" + + // EnvWorkspaceID is the current workspace identifier. + EnvWorkspaceID = "DEVPOD_WORKSPACE_ID" + + // EnvWorkspaceUID is the current workspace unique identifier. + EnvWorkspaceUID = "DEVPOD_WORKSPACE_UID" + + // EnvWorkspaceDaemonConfig holds the workspace daemon configuration. + EnvWorkspaceDaemonConfig = "DEVPOD_WORKSPACE_DAEMON_CONFIG" + + // EnvWorkspaceCredentialsPort is the workspace credentials server port. + EnvWorkspaceCredentialsPort = "DEVPOD_WORKSPACE_CREDENTIALS_PORT" // #nosec G101 + + // EnvCredentialsServerPort is the credentials server port on the host side. + EnvCredentialsServerPort = "DEVPOD_CREDENTIALS_SERVER_PORT" // #nosec G101 + + // EnvGitHelperPort is the git credential helper forwarding port. + EnvGitHelperPort = "DEVPOD_GIT_HELPER_PORT" + + // EnvCraneName overrides the crane binary name. + EnvCraneName = "DEVPOD_CRANE_NAME" + + // EnvPlatformOptions holds serialized platform options. + EnvPlatformOptions = "DEVPOD_PLATFORM_OPTIONS" + + // EnvFlagsUp holds extra flags for the up command. + EnvFlagsUp = "DEVPOD_FLAGS_UP" + + // EnvFlagsSSH holds extra flags for the ssh command. + EnvFlagsSSH = "DEVPOD_FLAGS_SSH" + + // EnvFlagsDelete holds extra flags for the delete command. + EnvFlagsDelete = "DEVPOD_FLAGS_DELETE" + + // EnvFlagsStatus holds extra flags for the status command. + EnvFlagsStatus = "DEVPOD_FLAGS_STATUS" + + // EnvSubdomain is the subdomain configuration for DevPod Pro. + EnvSubdomain = "DEVPOD_SUBDOMAIN" + + // EnvPrefix is the base prefix for all DevPod environment variables. + EnvPrefix = "DEVPOD_" + + // EnvIDEPrefix is the prefix for IDE-specific option env vars (append IDE name + "_"). + EnvIDEPrefix = EnvPrefix + "IDE_" + + // EnvProviderPrefix is the prefix for provider-specific option env vars (append provider name + "_"). + EnvProviderPrefix = EnvPrefix + "PROVIDER_" + + // --- Provider-scoped env vars (set when running provider commands) ---. + + // EnvProviderWorkspaceID is the workspace identifier passed to providers. + EnvProviderWorkspaceID = "WORKSPACE_ID" + + // EnvProviderWorkspaceUID is the workspace UID passed to providers. + EnvProviderWorkspaceUID = "WORKSPACE_UID" + + // EnvProviderWorkspacePicture is the workspace picture URL passed to providers. + EnvProviderWorkspacePicture = "WORKSPACE_PICTURE" + + // EnvProviderWorkspaceFolder is the workspace folder path passed to providers. + EnvProviderWorkspaceFolder = "WORKSPACE_FOLDER" + + // EnvProviderWorkspaceContext is the workspace context passed to providers. + EnvProviderWorkspaceContext = "WORKSPACE_CONTEXT" + + // EnvProviderWorkspaceOrigin is the workspace origin passed to providers. + EnvProviderWorkspaceOrigin = "WORKSPACE_ORIGIN" + + // EnvProviderWorkspaceSource is the workspace source passed to providers. + EnvProviderWorkspaceSource = "WORKSPACE_SOURCE" + + // EnvProviderWorkspaceProvider is the workspace provider name passed to providers. + EnvProviderWorkspaceProvider = "WORKSPACE_PROVIDER" + + // EnvProviderMachineID is the machine identifier passed to providers. + EnvProviderMachineID = "MACHINE_ID" + + // EnvProviderMachineContext is the machine context passed to providers. + EnvProviderMachineContext = "MACHINE_CONTEXT" + + // EnvProviderMachineFolder is the machine folder path passed to providers. + EnvProviderMachineFolder = "MACHINE_FOLDER" + + // EnvProviderMachineProvider is the machine provider name passed to providers. + EnvProviderMachineProvider = "MACHINE_PROVIDER" + + // EnvProviderID is the provider identifier passed to providers. + EnvProviderID = "PROVIDER_ID" + + // EnvProviderContext is the provider context passed to providers. + EnvProviderContext = "PROVIDER_CONTEXT" + + // EnvProviderFolder is the provider folder path passed to providers. + EnvProviderFolder = "PROVIDER_FOLDER" + + // EnvLoftProject is the Loft project name for pro features. + EnvLoftProject = "LOFT_PROJECT" + + // EnvLoftFilterByOwner enables filtering by owner in Loft. + EnvLoftFilterByOwner = "LOFT_FILTER_BY_OWNER" + + // EnvDevcontainerID is the devcontainer identifier. + EnvDevcontainerID = "DEVCONTAINER_ID" +) diff --git a/pkg/config/paths.go b/pkg/config/paths.go new file mode 100644 index 000000000..a4f393c65 --- /dev/null +++ b/pkg/config/paths.go @@ -0,0 +1,18 @@ +package config + +const ( + // IgnoreFileName is the name of the devpod ignore file. + IgnoreFileName = "." + BinaryName + "ignore" + + // SSHSignatureHelperPath is the path to the SSH signature helper script. + SSHSignatureHelperPath = "/usr/local/bin/" + BinaryName + "-ssh-signature" + + // SSHSignatureHelperName is the name used in git config for the SSH signature program. + SSHSignatureHelperName = BinaryName + "-ssh-signature" + + // DockerCredentialHelperName is the docker credential helper binary name. + DockerCredentialHelperName = "docker-credential-" + BinaryName + + // DevContainerResultPath is where devcontainer results are written. + DevContainerResultPath = "/var/run/" + BinaryName + "/result.json" +) diff --git a/pkg/config/product.go b/pkg/config/product.go new file mode 100644 index 000000000..467c8d9d2 --- /dev/null +++ b/pkg/config/product.go @@ -0,0 +1,12 @@ +package config + +const ( + // ProductName is the display name for the product. + ProductName = "DevPod" + + // ProductNamePro is the display name for the Pro product. + ProductNamePro = ProductName + " Pro" + + // DaemonServiceDescription is the system daemon service description. + DaemonServiceDescription = ProductName + " Agent Service" +) diff --git a/pkg/config/repo.go b/pkg/config/repo.go new file mode 100644 index 000000000..b8b3439ce --- /dev/null +++ b/pkg/config/repo.go @@ -0,0 +1,26 @@ +package config + +const ( + RepoOwner = "skevetter" + RepoName = "devpod" + RepoSlug = RepoOwner + "/" + RepoName + GitHubRepoURL = "https://github.com/" + RepoSlug + GitHubReleasesURL = GitHubRepoURL + "/releases" + GitHubAPIUserURL = "https://api.github.com/users/" + RepoOwner + ProviderPrefix = RepoName + "-provider-" + + // ProReleaseName is the Helm release / product name for DevPod Pro. + ProReleaseName = RepoName + "-pro" + + // BinaryName is the CLI binary base name used in downloads and SSH host suffixes. + BinaryName = RepoName + + // SSHHostSuffix is appended to workspace IDs for SSH config host entries. + SSHHostSuffix = "." + BinaryName + + // WebsiteBaseURL is the project website used for asset URLs. + WebsiteBaseURL = "https://" + RepoName + ".sh" + + // WebsiteAssetsURL is the base URL for icon/image assets. + WebsiteAssetsURL = WebsiteBaseURL + "/assets" +) diff --git a/pkg/credentials/server.go b/pkg/credentials/server.go index 79f8203c0..607eb50f3 100644 --- a/pkg/credentials/server.go +++ b/pkg/credentials/server.go @@ -12,13 +12,11 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/agent/tunnel" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/log" ) -const ( - DefaultPort = "12049" - CredentialsServerPortEnv = "DEVPOD_CREDENTIALS_SERVER_PORT" // #nosec G101 -) +const DefaultPort = "12049" func RunCredentialsServer( ctx context.Context, @@ -85,7 +83,7 @@ func RunCredentialsServer( } func GetPort() (int, error) { - strPort := cmp.Or(os.Getenv(CredentialsServerPortEnv), DefaultPort) + strPort := cmp.Or(os.Getenv(config.EnvCredentialsServerPort), DefaultPort) port, err := strconv.Atoi(strPort) if err != nil { return 0, fmt.Errorf("convert port %s: %w", strPort, err) diff --git a/pkg/daemon/agent/daemon.go b/pkg/daemon/agent/daemon.go index 25fe696be..3fe69cd16 100644 --- a/pkg/daemon/agent/daemon.go +++ b/pkg/daemon/agent/daemon.go @@ -12,6 +12,7 @@ import ( "github.com/loft-sh/api/v4/pkg/devpod" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" provider2 "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/log" @@ -100,7 +101,11 @@ func InstallDaemon(agentDir string, interval string, log log.Logger) error { } // check if admin - service, err := daemon.New("devpod", "DevPod Agent Service", daemon.SystemDaemon) + service, err := daemon.New( + pkgconfig.BinaryName, + pkgconfig.DaemonServiceDescription, + daemon.SystemDaemon, + ) if err != nil { return err } @@ -148,7 +153,11 @@ func RemoveDaemon() error { } // check if admin - service, err := daemon.New("devpod", "DevPod Agent Service", daemon.SystemDaemon) + service, err := daemon.New( + pkgconfig.BinaryName, + pkgconfig.DaemonServiceDescription, + daemon.SystemDaemon, + ) if err != nil { return err } diff --git a/pkg/daemon/platform/daemon.go b/pkg/daemon/platform/daemon.go index 56542e3d2..5b3b9c009 100644 --- a/pkg/daemon/platform/daemon.go +++ b/pkg/daemon/platform/daemon.go @@ -13,6 +13,7 @@ import ( "time" "github.com/sirupsen/logrus" + "github.com/skevetter/devpod/pkg/config" devpodlog "github.com/skevetter/devpod/pkg/log" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/devpod/pkg/ts" @@ -193,7 +194,7 @@ func initLogging(rootDir string, debug bool) log.Logger { logPath := filepath.Join(rootDir, "daemon.log") logger := log.NewFileLogger(logPath, logLevel) - if os.Getenv("DEVPOD_UI") != "true" { + if os.Getenv(config.EnvUI) != config.BoolTrue { logger = devpodlog.NewCombinedLogger( logLevel, logger, @@ -221,7 +222,7 @@ func dialLocal(l *localServer) dialFunc { type clientType string var ( - devPodClientType clientType = "devpod" + devPodClientType clientType = clientType(config.BinaryName) tailscaleClientType clientType = "tailscale" ) diff --git a/pkg/daemon/platform/socket.go b/pkg/daemon/platform/socket.go index bf2a49dbc..9986687ed 100644 --- a/pkg/daemon/platform/socket.go +++ b/pkg/daemon/platform/socket.go @@ -9,10 +9,12 @@ import ( "os" "path/filepath" "time" + + "github.com/skevetter/devpod/pkg/config" ) func GetSocketAddr(providerName string) string { - return filepath.Join("/tmp", fmt.Sprintf("devpod-%s.sock", providerName)) + return filepath.Join("/tmp", fmt.Sprintf(config.BinaryName+"-%s.sock", providerName)) } func Dial(addr string) (net.Conn, error) { diff --git a/pkg/devcontainer/build.go b/pkg/devcontainer/build.go index 13a520ad6..29d38bc39 100644 --- a/pkg/devcontainer/build.go +++ b/pkg/devcontainer/build.go @@ -10,6 +10,7 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/compose" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/build" "github.com/skevetter/devpod/pkg/devcontainer/buildkit" "github.com/skevetter/devpod/pkg/devcontainer/config" @@ -391,7 +392,7 @@ func (r *runner) buildImage( // This should only be OSS kubernetes as of March 06, 2025. dockerDriver, ok := r.Driver.(driver.DockerDriver) if options.ForceDockerless || !ok { - if r.WorkspaceConfig.Agent.Dockerless.Disabled == "true" { + if r.WorkspaceConfig.Agent.Dockerless.Disabled == pkgconfig.BoolTrue { return nil, fmt.Errorf( "cannot build devcontainer because driver is non-docker and dockerless fallback is disabled", ) diff --git a/pkg/devcontainer/config.go b/pkg/devcontainer/config.go index 046623021..1295c512c 100644 --- a/pkg/devcontainer/config.go +++ b/pkg/devcontainer/config.go @@ -9,6 +9,7 @@ import ( "path/filepath" "slices" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/devcontainer/crane" "github.com/skevetter/devpod/pkg/language" @@ -28,7 +29,7 @@ func (r *runner) getRawConfig(options provider2.CLIOptions) (*config.DevContaine } else { rawParsedConfig.Origin = path.Join( filepath.ToSlash(r.LocalWorkspaceFolder), - ".devcontainer.devpod.json", + ".devcontainer."+pkgconfig.BinaryName+".json", ) } return rawParsedConfig, nil diff --git a/pkg/devcontainer/config/build.go b/pkg/devcontainer/config/build.go index 7bdcd47a5..090bae46a 100644 --- a/pkg/devcontainer/config/build.go +++ b/pkg/devcontainer/config/build.go @@ -1,6 +1,7 @@ package config import ( + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/dockerfile" ) @@ -8,10 +9,8 @@ const ( DockerIDLabel = "dev.containers.id" DockerfileDefaultTarget = "dev_container_auto_added_stage_label" - DevPodContextFeatureFolder = ".devpod-internal" + DevPodContextFeatureFolder = pkgconfig.ConfigDirName + "-internal" DevPodDockerlessBuildInfoFolder = "/workspaces/.dockerless" - - WorkspaceDaemonConfigExtraEnvVar = "DEVPOD_WORKSPACE_DAEMON_CONFIG" ) func GetDockerLabelForID(id string) []string { diff --git a/pkg/devcontainer/config/prebuild.go b/pkg/devcontainer/config/prebuild.go index 39ccb7358..94d09f22d 100644 --- a/pkg/devcontainer/config/prebuild.go +++ b/pkg/devcontainer/config/prebuild.go @@ -10,6 +10,7 @@ import ( "github.com/moby/patternmatcher" "github.com/moby/patternmatcher/ignorefile" "github.com/sirupsen/logrus" + pkgconfig "github.com/skevetter/devpod/pkg/config" util "github.com/skevetter/devpod/pkg/util/hash" "github.com/skevetter/log" "github.com/skevetter/log/hash" @@ -57,7 +58,7 @@ func CalculatePrebuildHash(params PrebuildHashParams) (string, error) { } combined := arch + string(configJSON) + params.DockerfileContent + contextHash - finalHash := "devpod-" + hash.String(combined)[:32] + finalHash := pkgconfig.BinaryName + "-" + hash.String(combined)[:32] params.Log.WithFields(logrus.Fields{ "architecture": arch, diff --git a/pkg/devcontainer/config/result.go b/pkg/devcontainer/config/result.go index a180b2670..7e9becb01 100644 --- a/pkg/devcontainer/config/result.go +++ b/pkg/devcontainer/config/result.go @@ -3,9 +3,11 @@ package config import ( "maps" "slices" + + pkgconfig "github.com/skevetter/devpod/pkg/config" ) -const UserLabel = "devpod.user" +const UserLabel = pkgconfig.BinaryName + ".user" type Result struct { DevContainerConfigWithPath *DevContainerConfigWithPath `json:"DevContainerConfigWithPath"` @@ -66,12 +68,13 @@ func GetRemoteUser(result *Result) string { } func GetDevPodCustomizations(parsedConfig *DevContainerConfig) *DevPodCustomizations { - if parsedConfig.Customizations == nil || parsedConfig.Customizations["devpod"] == nil { + if parsedConfig.Customizations == nil || + parsedConfig.Customizations[pkgconfig.BinaryName] == nil { return &DevPodCustomizations{} } devPod := &DevPodCustomizations{} - err := Convert(parsedConfig.Customizations["devpod"], devPod) + err := Convert(parsedConfig.Customizations[pkgconfig.BinaryName], devPod) if err != nil { return &DevPodCustomizations{} } diff --git a/pkg/devcontainer/crane/run.go b/pkg/devcontainer/crane/run.go index 33c410d6f..72bc2a3ad 100644 --- a/pkg/devcontainer/crane/run.go +++ b/pkg/devcontainer/crane/run.go @@ -8,6 +8,7 @@ import ( "os/exec" "path/filepath" + "github.com/skevetter/devpod/pkg/config" provider2 "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/log" ) @@ -20,9 +21,9 @@ const ( EnvironmentCrane = "environment" - defaultBinName = "devpod-crane" - envDevPodCraneName = "DEVPOD_CRANE_NAME" - tmpDirTemplate = "devpod-crane-*" + defaultBinName = config.BinaryName + "-crane" + envDevPodCraneName = config.EnvCraneName + tmpDirTemplate = config.BinaryName + "-crane-*" ) type Content struct { diff --git a/pkg/devcontainer/feature/features.go b/pkg/devcontainer/feature/features.go index 2767d8f4f..ecde274da 100644 --- a/pkg/devcontainer/feature/features.go +++ b/pkg/devcontainer/feature/features.go @@ -16,6 +16,7 @@ import ( v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/sirupsen/logrus" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/extract" devpodhttp "github.com/skevetter/devpod/pkg/http" @@ -383,5 +384,5 @@ func tryDownload(url, destFile string, httpHeaders map[string]string) error { func getFeaturesTempFolder(id string) string { hashedID := hash.String(id)[:10] - return filepath.Join(os.TempDir(), "devpod", "features", hashedID) + return filepath.Join(os.TempDir(), pkgconfig.BinaryName, "features", hashedID) } diff --git a/pkg/devcontainer/setup/setup.go b/pkg/devcontainer/setup/setup.go index 30f811be8..727c5607e 100644 --- a/pkg/devcontainer/setup/setup.go +++ b/pkg/devcontainer/setup/setup.go @@ -16,8 +16,10 @@ import ( "github.com/loft-sh/api/v4/pkg/devpod" "github.com/sirupsen/logrus" + "github.com/skevetter/devpod/pkg/agent" "github.com/skevetter/devpod/pkg/agent/tunnel" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" copy2 "github.com/skevetter/devpod/pkg/copy" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/envfile" @@ -27,10 +29,6 @@ import ( clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) -const ( - ResultLocation = "/var/run/devpod/result.json" -) - type ContainerSetupConfig struct { SetupInfo *config.Result ExtraWorkspaceEnv []string @@ -90,17 +88,20 @@ func writeResultFile(cfg *ContainerSetupConfig) { return } - existing, _ := os.ReadFile(ResultLocation) + existing, _ := os.ReadFile(pkgconfig.DevContainerResultPath) if string(rawBytes) == string(existing) { return } - if err := os.MkdirAll(filepath.Dir(ResultLocation), 0o755); err != nil { // #nosec G301 - cfg.Log.Warnf("error create %s: %v", filepath.Dir(ResultLocation), err) + if err := os.MkdirAll( // #nosec G301 + filepath.Dir(pkgconfig.DevContainerResultPath), + 0o755, + ); err != nil { + cfg.Log.Warnf("error create %s: %v", filepath.Dir(pkgconfig.DevContainerResultPath), err) } - if err := os.WriteFile(ResultLocation, rawBytes, 0o600); err != nil { - cfg.Log.Warnf("error write result to %s: %v", ResultLocation, err) + if err := os.WriteFile(pkgconfig.DevContainerResultPath, rawBytes, 0o600); err != nil { + cfg.Log.Warnf("error write result to %s: %v", pkgconfig.DevContainerResultPath, err) } } @@ -336,7 +337,7 @@ func shouldSkipKubeConfig(tunnelClient tunnel.TunnelClient, log log.Logger) bool return true } - markerPath := filepath.Join("/var/devpod", "setupKubeConfig.marker") + markerPath := filepath.Join(agent.ContainerDataDir, "setupKubeConfig.marker") info, err := os.Stat(markerPath) if err == nil { if info.Mode().Perm()&0o022 != 0 { @@ -418,7 +419,7 @@ func ensureKubeConfigMaps(config *clientcmdapi.Config) *clientcmdapi.Config { } func markerFileExists(markerName string, markerContent string) (bool, error) { - markerName = filepath.Join("/var/devpod", markerName+".marker") + markerName = filepath.Join(agent.ContainerDataDir, markerName+".marker") t, err := os.ReadFile(markerName) if err != nil && !os.IsNotExist(err) { return false, err diff --git a/pkg/devcontainer/single.go b/pkg/devcontainer/single.go index 2aff740d1..0ea345808 100644 --- a/pkg/devcontainer/single.go +++ b/pkg/devcontainer/single.go @@ -9,6 +9,7 @@ import ( "time" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/daemon/agent" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/devcontainer/metadata" @@ -21,8 +22,6 @@ var dockerlessImage = "ghcr.io/loft-sh/dockerless:0.2.0" const ( DevPodExtraEnvVar = "DEVPOD" RemoteContainersExtraEnvVar = "REMOTE_CONTAINERS" - WorkspaceIDExtraEnvVar = "DEVPOD_WORKSPACE_ID" - WorkspaceUIDExtraEnvVar = "DEVPOD_WORKSPACE_UID" DefaultEntrypoint = ` while ! command -v /usr/local/bin/devpod >/dev/null 2>&1; do @@ -177,7 +176,7 @@ func (r *runner) runSingleContainer( if err != nil { r.Log.Errorf("Failed to marshal daemon config: %v", err) } else { - mergedConfig.ContainerEnv[config.WorkspaceDaemonConfigExtraEnvVar] = data + mergedConfig.ContainerEnv[pkgconfig.EnvWorkspaceDaemonConfig] = data } } @@ -398,11 +397,11 @@ func (r *runner) addExtraEnvVars(env map[string]string) map[string]string { env[RemoteContainersExtraEnvVar] = "true" if r.WorkspaceConfig != nil && r.WorkspaceConfig.Workspace != nil && r.WorkspaceConfig.Workspace.ID != "" { - env[WorkspaceIDExtraEnvVar] = r.WorkspaceConfig.Workspace.ID + env[pkgconfig.EnvWorkspaceID] = r.WorkspaceConfig.Workspace.ID } if r.WorkspaceConfig != nil && r.WorkspaceConfig.Workspace != nil && r.WorkspaceConfig.Workspace.UID != "" { - env[WorkspaceUIDExtraEnvVar] = r.WorkspaceConfig.Workspace.UID + env[pkgconfig.EnvWorkspaceUID] = r.WorkspaceConfig.Workspace.UID } return env diff --git a/pkg/dockercredentials/dockercredentials.go b/pkg/dockercredentials/dockercredentials.go index 02b5f5381..015dfb619 100644 --- a/pkg/dockercredentials/dockercredentials.go +++ b/pkg/dockercredentials/dockercredentials.go @@ -12,6 +12,7 @@ import ( "github.com/docker/cli/cli/config/types" "github.com/kballard/go-shellquote" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/docker" "github.com/skevetter/devpod/pkg/file" "github.com/skevetter/devpod/pkg/random" @@ -91,7 +92,7 @@ func configureCredentials( } // write credentials helper - helperName := "docker-credential-devpod" + helperName := pkgconfig.DockerCredentialHelperName if runtime.GOOS == windowsOS { helperName += ".cmd" } @@ -124,7 +125,7 @@ func configureCredentials( return fmt.Errorf("write credential helper: %w", err) } - dockerConfig.CredentialsStore = "devpod" + dockerConfig.CredentialsStore = pkgconfig.BinaryName err = dockerConfig.Save() if err != nil { return err diff --git a/pkg/dockercredentials/helper.go b/pkg/dockercredentials/helper.go index 5f0e92bd1..9d04c1ce4 100644 --- a/pkg/dockercredentials/helper.go +++ b/pkg/dockercredentials/helper.go @@ -11,6 +11,7 @@ import ( "time" "github.com/docker/docker-credential-helpers/credentials" + "github.com/skevetter/devpod/pkg/config" ) const ( @@ -124,7 +125,7 @@ func (h *Helper) getFromCredentialsServer(serverURL string) (string, string, err } func (h *Helper) getFromWorkspaceServer(serverURL string) (string, string, error) { - workspacePort := os.Getenv("DEVPOD_WORKSPACE_CREDENTIALS_PORT") + workspacePort := os.Getenv(config.EnvWorkspaceCredentialsPort) if workspacePort == "" { return "", "", fmt.Errorf("no workspace port") } diff --git a/pkg/driver/custom/custom.go b/pkg/driver/custom/custom.go index 0dac072d7..f952b3f6a 100644 --- a/pkg/driver/custom/custom.go +++ b/pkg/driver/custom/custom.go @@ -12,6 +12,7 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/agent" "github.com/skevetter/devpod/pkg/client/clientimplementation" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/driver" "github.com/skevetter/devpod/pkg/provider" @@ -286,7 +287,7 @@ func (c *customDriver) GetDevContainerLogs( var _ driver.ReprovisioningDriver = (*customDriver)(nil) func (c *customDriver) CanReprovision() bool { - return c.workspaceInfo.Agent.Custom.CanReprovision == "true" + return c.workspaceInfo.Agent.Custom.CanReprovision == pkgconfig.BoolTrue } func (c *customDriver) runCommand( @@ -312,12 +313,12 @@ func (c *customDriver) runCommand( if err != nil { return err } - environ = append(environ, provider.DEVCONTAINER_ID+"="+workspaceId) + environ = append(environ, pkgconfig.EnvDevcontainerID+"="+workspaceId) environ = append(environ, extraEnv...) // set debug level if log.GetLevel() == logrus.DebugLevel { - environ = append(environ, clientimplementation.DevPodDebug+"=true") + environ = append(environ, pkgconfig.EnvDebug+"="+pkgconfig.BoolTrue) } // run the command diff --git a/pkg/driver/docker/docker.go b/pkg/driver/docker/docker.go index 98c53388b..18c3b7233 100644 --- a/pkg/driver/docker/docker.go +++ b/pkg/driver/docker/docker.go @@ -1073,24 +1073,24 @@ func (d *dockerDriver) createTempFiles() (*tempFiles, error) { files := &tempFiles{} var err error - files.passwdIn, err = os.CreateTemp("", "devpod_container_passwd_in") + files.passwdIn, err = os.CreateTemp("", config2.BinaryName+"_container_passwd_in") if err != nil { return nil, err } - files.groupIn, err = os.CreateTemp("", "devpod_container_group_in") + files.groupIn, err = os.CreateTemp("", config2.BinaryName+"_container_group_in") if err != nil { files.cleanup() return nil, err } - files.passwdOut, err = os.CreateTemp("", "devpod_container_passwd_out") + files.passwdOut, err = os.CreateTemp("", config2.BinaryName+"_container_passwd_out") if err != nil { files.cleanup() return nil, err } - files.groupOut, err = os.CreateTemp("", "devpod_container_group_out") + files.groupOut, err = os.CreateTemp("", config2.BinaryName+"_container_group_out") if err != nil { files.cleanup() return nil, err diff --git a/pkg/driver/kubernetes/driver.go b/pkg/driver/kubernetes/driver.go index 9074ec8c8..7945526f1 100644 --- a/pkg/driver/kubernetes/driver.go +++ b/pkg/driver/kubernetes/driver.go @@ -182,7 +182,7 @@ func (k *KubernetesDriver) CommandDevContainer( return k.client.Exec(ctx, &ExecStreamOptions{ Pod: workspaceId, Namespace: k.namespace, - Container: "devpod", + Container: DevContainerName, Command: args, Stdin: stdin, Stdout: stdout, @@ -198,7 +198,7 @@ func (k *KubernetesDriver) GetDevContainerLogs( ) error { workspaceID = getID(workspaceID) - logs, err := k.client.Logs(ctx, k.namespace, workspaceID, "devpod", true) + logs, err := k.client.Logs(ctx, k.namespace, workspaceID, DevContainerName, true) if err != nil { return fmt.Errorf("get logs: %w", err) } diff --git a/pkg/driver/kubernetes/init_container.go b/pkg/driver/kubernetes/init_container.go index 2cd867add..2c2fa2972 100644 --- a/pkg/driver/kubernetes/init_container.go +++ b/pkg/driver/kubernetes/init_container.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/driver" corev1 "k8s.io/api/core/v1" ) @@ -70,7 +71,7 @@ func (k *KubernetesDriver) getInitContainers( RunAsGroup: &[]int64{0}[0], RunAsNonRoot: &[]bool{false}[0], } - if k.options.StrictSecurity == "true" { + if k.options.StrictSecurity == pkgconfig.BoolTrue { securityContext = nil } diff --git a/pkg/driver/kubernetes/run.go b/pkg/driver/kubernetes/run.go index 1d8340cbc..c1a2d2b1c 100644 --- a/pkg/driver/kubernetes/run.go +++ b/pkg/driver/kubernetes/run.go @@ -9,6 +9,7 @@ import ( "strconv" "strings" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/devcontainer/config" "github.com/skevetter/devpod/pkg/driver" provider2 "github.com/skevetter/devpod/pkg/provider" @@ -19,17 +20,17 @@ import ( ) const ( - DevContainerName = "devpod" - InitContainerName = "devpod-init" + DevContainerName = pkgconfig.BinaryName + InitContainerName = pkgconfig.BinaryName + "-init" ) const ( - DevPodCreatedLabel = "devpod.sh/created" - DevPodWorkspaceLabel = "devpod.sh/workspace" - DevPodWorkspaceUIDLabel = "devpod.sh/workspace-uid" + DevPodCreatedLabel = pkgconfig.BinaryName + ".sh/created" + DevPodWorkspaceLabel = pkgconfig.BinaryName + ".sh/workspace" + DevPodWorkspaceUIDLabel = pkgconfig.BinaryName + ".sh/workspace-uid" - DevPodInfoAnnotation = "devpod.sh/info" - DevPodLastAppliedAnnotation = "devpod.sh/last-applied-configuration" + DevPodInfoAnnotation = pkgconfig.BinaryName + ".sh/info" + DevPodLastAppliedAnnotation = pkgconfig.BinaryName + ".sh/last-applied-configuration" ClusterAutoscalerSaveToEvictAnnotation = "cluster-autoscaler.kubernetes.io/safe-to-evict" ) @@ -51,7 +52,7 @@ func (k *KubernetesDriver) RunDevContainer( workspaceId = getID(workspaceId) // namespace - if k.namespace != "" && k.options.CreateNamespace == "true" { + if k.namespace != "" && k.options.CreateNamespace == pkgconfig.BoolTrue { err := k.createNamespace(ctx) if err != nil { return err @@ -172,7 +173,7 @@ func (k *KubernetesDriver) runContainer( daemonConfig := "" for k, v := range options.Env { // filter out daemon config, that's going to be mounted through a secret - if k == config.WorkspaceDaemonConfigExtraEnvVar { + if k == pkgconfig.EnvWorkspaceDaemonConfig { daemonConfig = v continue } @@ -228,8 +229,8 @@ func (k *KubernetesDriver) runContainer( // ensure pull secrets pullSecretsCreated := false - if k.options.KubernetesPullSecretsEnabled == "true" && - k.agentConfig.InjectDockerCredentials == "true" { + if k.options.KubernetesPullSecretsEnabled == pkgconfig.BoolTrue && + k.agentConfig.InjectDockerCredentials == pkgconfig.BoolTrue { pullSecretsCreated, err = k.EnsurePullSecret(ctx, getPullSecretsName(id), options.Image) if err != nil { return err @@ -264,7 +265,7 @@ func (k *KubernetesDriver) runContainer( FSGroupChangePolicy: ptr.To(corev1.FSGroupChangeOnRootMismatch), } } - if k.options.KubernetesPullSecretsEnabled == "true" && pullSecretsCreated { + if k.options.KubernetesPullSecretsEnabled == pkgconfig.BoolTrue && pullSecretsCreated { pod.Spec.ImagePullSecrets = []corev1.LocalObjectReference{{Name: getPullSecretsName(id)}} } pod.Spec.RestartPolicy = corev1.RestartPolicyNever @@ -364,8 +365,8 @@ func getContainers( ) []corev1.Container { if daemonConfigSecretName != "" { volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: "devpod-daemon-config", - MountPath: "/var/run/secrets/devpod", + Name: DevContainerName + "-daemon-config", + MountPath: "/var/run/secrets/" + DevContainerName, }) } devPodContainer := corev1.Container{ @@ -385,7 +386,7 @@ func getContainers( }, } - if strictSecurity == "true" { + if strictSecurity == pkgconfig.BoolTrue { devPodContainer.SecurityContext = nil } @@ -424,7 +425,7 @@ func getContainers( func getVolumes(pod *corev1.Pod, id string, daemonConfigSecretName string) []corev1.Volume { volumes := []corev1.Volume{ { - Name: "devpod", + Name: DevContainerName, VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ ClaimName: id, @@ -435,7 +436,7 @@ func getVolumes(pod *corev1.Pod, id string, daemonConfigSecretName string) []cor if daemonConfigSecretName != "" { volumes = append(volumes, corev1.Volume{ - Name: "devpod-daemon-config", + Name: DevContainerName + "-daemon-config", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ SecretName: daemonConfigSecretName, @@ -458,9 +459,9 @@ func getVolumeMount(idx int, mount *config.Mount) corev1.VolumeMount { } return corev1.VolumeMount{ - Name: "devpod", + Name: DevContainerName, MountPath: mount.Target, - SubPath: fmt.Sprintf("devpod/%s", subPath), + SubPath: fmt.Sprintf(DevContainerName+"/%s", subPath), } } @@ -520,15 +521,15 @@ func (k *KubernetesDriver) StartDevContainer(ctx context.Context, workspaceId st } func getID(workspaceID string) string { - return "devpod-" + workspaceID + return DevContainerName + "-" + workspaceID } func getPullSecretsName(workspaceID string) string { - return fmt.Sprintf("devpod-pull-secret-%s", workspaceID) + return fmt.Sprintf(DevContainerName+"-pull-secret-%s", workspaceID) } func getDaemonSecretName(workspaceID string) string { - return fmt.Sprintf("devpod-daemon-secret-%s", workspaceID) + return fmt.Sprintf(DevContainerName+"-daemon-secret-%s", workspaceID) } func optionsEqual(a, b *provider2.ProviderKubernetesDriverConfig) bool { diff --git a/pkg/gitcredentials/gitcredentials.go b/pkg/gitcredentials/gitcredentials.go index d1da57aa7..04ba01cc5 100644 --- a/pkg/gitcredentials/gitcredentials.go +++ b/pkg/gitcredentials/gitcredentials.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/skevetter/devpod/pkg/command" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/file" "github.com/skevetter/devpod/pkg/git" "github.com/skevetter/log/scanner" @@ -210,7 +211,7 @@ func GetUser(userName string) (*GitUser, error) { func GetCredentials(requestObj *GitCredentials) (*GitCredentials, error) { // run in git helper mode if we have a port - gitHelperPort := os.Getenv("DEVPOD_GIT_HELPER_PORT") + gitHelperPort := os.Getenv(config.EnvGitHelperPort) if gitHelperPort != "" { binaryPath, err := os.Executable() if err != nil { @@ -259,7 +260,7 @@ func GetHTTPPath(ctx context.Context, params GetHttpPathParameters) (string, err configKey := fmt.Sprintf("credential.%s://%s.useHttpPath", params.Protocol, params.Host) out, _ := git.CommandContext(ctx, git.GetDefaultExtraEnv(false), "config", "--get", configKey). Output() - if strings.TrimSpace(string(out)) != "true" { + if strings.TrimSpace(string(out)) != config.BoolTrue { return "", nil } // We can assume the GitRepository is always HTTP(S) based as otherwise we wouldn't diff --git a/pkg/gitsshsigning/helper.go b/pkg/gitsshsigning/helper.go index 2d7f1962a..2267cb4c2 100644 --- a/pkg/gitsshsigning/helper.go +++ b/pkg/gitsshsigning/helper.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/file" "github.com/skevetter/log" ) @@ -17,16 +18,16 @@ const ( devpod agent git-ssh-signature "$@" ` - HelperScriptPath = "/usr/local/bin/devpod-ssh-signature" - GitConfigTemplate = ` +) + +var GitConfigTemplate = ` [gpg "ssh"] - program = devpod-ssh-signature + program = ` + pkgconfig.SSHSignatureHelperName + ` [gpg] format = ssh [user] signingkey = %s ` -) // ConfigureHelper sets up the Git SSH signing helper script and updates the Git configuration for the specified user. // @@ -60,7 +61,7 @@ func ConfigureHelper(userName, gitSigningKey string, log log.Logger) error { // RemoveHelper removes the git SSH signing helper script and any related configuration. func RemoveHelper(userName string) error { - if err := os.Remove(HelperScriptPath); err != nil && !os.IsNotExist(err) { + if err := os.Remove(pkgconfig.SSHSignatureHelperPath); err != nil && !os.IsNotExist(err) { return err } @@ -82,7 +83,7 @@ func createHelperScript() error { "sudo", "bash", "-c", - fmt.Sprintf("echo '%s' > %s", HelperScript, HelperScriptPath), + fmt.Sprintf("echo '%s' > %s", HelperScript, pkgconfig.SSHSignatureHelperPath), ) if err := cmd.Run(); err != nil { return err @@ -91,7 +92,8 @@ func createHelperScript() error { } func makeScriptExecutable() error { - return exec.Command("sudo", "chmod", "+x", HelperScriptPath).Run() + cmd := exec.Command("sudo", "chmod", "+x", pkgconfig.SSHSignatureHelperPath) // #nosec G204 + return cmd.Run() } func getGitConfigPath(userName string) (string, error) { @@ -108,7 +110,7 @@ func updateGitConfig(gitConfigPath, userName, gitSigningKey string) error { return err } - if !strings.Contains(configContent, "program = devpod-ssh-signature") { + if !strings.Contains(configContent, "program = "+pkgconfig.SSHSignatureHelperName) { newConfig := fmt.Sprintf(GitConfigTemplate, gitSigningKey) newContent := removeSignatureHelper(configContent) + newConfig if err := writeGitConfig(gitConfigPath, newContent, userName); err != nil { @@ -208,7 +210,7 @@ func filterGpgSSHSection(lines []string) []string { var kept []string for _, line := range lines[1:] { trimmed := strings.TrimSpace(line) - if !strings.HasPrefix(trimmed, "program = devpod-ssh-signature") { + if !strings.HasPrefix(trimmed, "program = "+pkgconfig.SSHSignatureHelperName) { kept = append(kept, line) } } diff --git a/pkg/ide/fleet/fleet.go b/pkg/ide/fleet/fleet.go index 01a6660fb..431583f6e 100644 --- a/pkg/ide/fleet/fleet.go +++ b/pkg/ide/fleet/fleet.go @@ -21,7 +21,7 @@ import ( ) const ( - FleetURLFileName = "devpod-fleet.url.txt" + FleetURLFileName = config.BinaryName + "-fleet.url.txt" VersionOption = "VERSION" DownloadAmd64Option = "DOWNLOAD_AMD64" DownloadArm64Option = "DOWNLOAD_ARM64" diff --git a/pkg/ide/ideparse/parse.go b/pkg/ide/ideparse/parse.go index f630655fb..6639fcc43 100644 --- a/pkg/ide/ideparse/parse.go +++ b/pkg/ide/ideparse/parse.go @@ -42,29 +42,29 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDENone, DisplayName: "None", Options: map[string]ide.Option{}, - Icon: "https://devpod.sh/assets/none.svg", - IconDark: "https://devpod.sh/assets/none_dark.svg", + Icon: config.WebsiteAssetsURL + "/none.svg", + IconDark: config.WebsiteAssetsURL + "/none_dark.svg", Group: config.IDEGroupPrimary, }, { Name: config.IDEVSCode, DisplayName: "VS Code", Options: vscode.Options, - Icon: "https://devpod.sh/assets/vscode.svg", + Icon: config.WebsiteAssetsURL + "/vscode.svg", Group: config.IDEGroupPrimary, }, { Name: config.IDEOpenVSCode, DisplayName: "VS Code Browser", Options: openvscode.Options, - Icon: "https://devpod.sh/assets/vscodebrowser.svg", + Icon: config.WebsiteAssetsURL + "/vscodebrowser.svg", Group: config.IDEGroupPrimary, }, { Name: config.IDECursor, DisplayName: "Cursor", Options: vscode.Options, - Icon: "https://devpod.sh/assets/cursor.svg", + Icon: config.WebsiteAssetsURL + "/cursor.svg", Experimental: true, Group: config.IDEGroupPrimary, }, @@ -72,7 +72,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEZed, DisplayName: "Zed", Options: ide.Options{}, - Icon: "https://devpod.sh/assets/zed.svg", + Icon: config.WebsiteAssetsURL + "/zed.svg", Experimental: true, Group: config.IDEGroupPrimary, }, @@ -80,7 +80,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDECodium, DisplayName: "VSCodium", Options: vscode.Options, - Icon: "https://devpod.sh/assets/codium.svg", + Icon: config.WebsiteAssetsURL + "/codium.svg", Experimental: true, Group: config.IDEGroupPrimary, }, @@ -88,35 +88,35 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEIntellij, DisplayName: "IntelliJ IDEA", Options: jetbrains.IntellijOptions, - Icon: "https://devpod.sh/assets/intellij.svg", + Icon: config.WebsiteAssetsURL + "/intellij.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEPyCharm, DisplayName: "PyCharm", Options: jetbrains.PyCharmOptions, - Icon: "https://devpod.sh/assets/pycharm.svg", + Icon: config.WebsiteAssetsURL + "/pycharm.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEPhpStorm, DisplayName: "PhpStorm", Options: jetbrains.PhpStormOptions, - Icon: "https://devpod.sh/assets/phpstorm.svg", + Icon: config.WebsiteAssetsURL + "/phpstorm.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDERider, DisplayName: "Rider", Options: jetbrains.RiderOptions, - Icon: "https://devpod.sh/assets/rider.svg", + Icon: config.WebsiteAssetsURL + "/rider.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEFleet, DisplayName: "Fleet", Options: fleet.Options, - Icon: "https://devpod.sh/assets/fleet.svg", + Icon: config.WebsiteAssetsURL + "/fleet.svg", Experimental: true, Group: config.IDEGroupJetBrains, }, @@ -124,50 +124,50 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEGoland, DisplayName: "GoLand", Options: jetbrains.GolandOptions, - Icon: "https://devpod.sh/assets/goland.svg", + Icon: config.WebsiteAssetsURL + "/goland.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEWebStorm, DisplayName: "WebStorm", Options: jetbrains.WebStormOptions, - Icon: "https://devpod.sh/assets/webstorm.svg", + Icon: config.WebsiteAssetsURL + "/webstorm.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDERustRover, DisplayName: "RustRover", Options: jetbrains.RustRoverOptions, - Icon: "https://devpod.sh/assets/rustrover.svg", + Icon: config.WebsiteAssetsURL + "/rustrover.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDERubyMine, DisplayName: "RubyMine", Options: jetbrains.RubyMineOptions, - Icon: "https://devpod.sh/assets/rubymine.svg", + Icon: config.WebsiteAssetsURL + "/rubymine.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDECLion, DisplayName: "CLion", Options: jetbrains.CLionOptions, - Icon: "https://devpod.sh/assets/clion.svg", + Icon: config.WebsiteAssetsURL + "/clion.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEDataSpell, DisplayName: "DataSpell", Options: jetbrains.DataSpellOptions, - Icon: "https://devpod.sh/assets/dataspell.svg", + Icon: config.WebsiteAssetsURL + "/dataspell.svg", Group: config.IDEGroupJetBrains, }, { Name: config.IDEJupyterNotebook, DisplayName: "Jupyter Notebook", Options: jupyter.Options, - Icon: "https://devpod.sh/assets/jupyter.svg", - IconDark: "https://devpod.sh/assets/jupyter_dark.svg", + Icon: config.WebsiteAssetsURL + "/jupyter.svg", + IconDark: config.WebsiteAssetsURL + "/jupyter_dark.svg", Experimental: true, Group: config.IDEGroupOther, }, @@ -175,7 +175,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEVSCodeInsiders, DisplayName: "VS Code Insiders", Options: vscode.Options, - Icon: "https://devpod.sh/assets/vscode_insiders.svg", + Icon: config.WebsiteAssetsURL + "/vscode_insiders.svg", Experimental: true, Group: config.IDEGroupOther, }, @@ -183,7 +183,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEPositron, DisplayName: "Positron", Options: vscode.Options, - Icon: "https://devpod.sh/assets/positron.svg", + Icon: config.WebsiteAssetsURL + "/positron.svg", Experimental: true, Group: config.IDEGroupOther, }, @@ -191,7 +191,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDERStudio, DisplayName: "RStudio Server", Options: rstudio.Options, - Icon: "https://devpod.sh/assets/rstudio.svg", + Icon: config.WebsiteAssetsURL + "/rstudio.svg", Experimental: true, Group: config.IDEGroupOther, }, @@ -199,7 +199,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEWindsurf, DisplayName: "Windsurf Editor", Options: vscode.Options, - Icon: "https://devpod.sh/assets/windsurf.svg", + Icon: config.WebsiteAssetsURL + "/windsurf.svg", Experimental: true, Group: config.IDEGroupPrimary, }, @@ -207,7 +207,7 @@ var AllowedIDEs = []AllowedIDE{ Name: config.IDEAntigravity, DisplayName: "Google Antigravity", Options: vscode.Options, - Icon: "https://devpod.sh/assets/antigravity.svg", + Icon: config.WebsiteAssetsURL + "/antigravity.svg", Experimental: true, Group: config.IDEGroupPrimary, }, diff --git a/pkg/ide/jetbrains/generic.go b/pkg/ide/jetbrains/generic.go index 36610c857..13c436e82 100644 --- a/pkg/ide/jetbrains/generic.go +++ b/pkg/ide/jetbrains/generic.go @@ -12,6 +12,7 @@ import ( "runtime" "github.com/sirupsen/logrus" + "github.com/skevetter/devpod/pkg/agent" "github.com/skevetter/devpod/pkg/command" config2 "github.com/skevetter/devpod/pkg/config" copy2 "github.com/skevetter/devpod/pkg/copy" @@ -93,7 +94,7 @@ func (o *GenericJetBrainsServer) OpenGateway(workspaceFolder, workspaceID string o.getDirectory(path.Join("/", "home", o.userName)), ) + `&projectPath=` + url.QueryEscape( workspaceFolder, - ) + `&host=` + workspaceID + `.devpod&port=22&user=` + url.QueryEscape( + ) + `&host=` + workspaceID + config2.SSHHostSuffix + `&port=22&user=` + url.QueryEscape( o.userName, ) + `&type=ssh&deploy=false`, ) @@ -113,7 +114,7 @@ func (o *GenericJetBrainsServer) GetVolume() string { } func (o *GenericJetBrainsServer) getDownloadFolder() string { - return fmt.Sprintf("/var/devpod/%s", o.options.ID) + return filepath.Join(agent.ContainerDataDir, o.options.ID) } func (o *GenericJetBrainsServer) Install(setupInfo *config.Result) error { diff --git a/pkg/ide/rstudio/rstudio.go b/pkg/ide/rstudio/rstudio.go index 409555b63..0fe208dd1 100644 --- a/pkg/ide/rstudio/rstudio.go +++ b/pkg/ide/rstudio/rstudio.go @@ -14,6 +14,7 @@ import ( "runtime" "strings" + "github.com/skevetter/devpod/pkg/agent" "github.com/skevetter/devpod/pkg/command" "github.com/skevetter/devpod/pkg/config" copypkg "github.com/skevetter/devpod/pkg/copy" @@ -47,7 +48,7 @@ var Options = ide.Options{ const ( DefaultServerPort = 8787 - downloadFolder = "/var/devpod/rstudio-server" + downloadFolder = agent.ContainerDataDir + "/rstudio-server" dataFolder = "/usr/local/share/devpod/rstudio-server/data" // rstudioConfigFolder is where RStudio expects configuration. rstudioConfigFolder = "/etc/rstudio" diff --git a/pkg/ide/vscode/open.go b/pkg/ide/vscode/open.go index 6960a1399..dd0bfe3ed 100644 --- a/pkg/ide/vscode/open.go +++ b/pkg/ide/vscode/open.go @@ -10,6 +10,7 @@ import ( "strings" "github.com/skevetter/devpod/pkg/command" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/log" "github.com/skratchdot/open-golang/open" ) @@ -103,7 +104,7 @@ func openViaBrowser(params OpenParams) error { } folder := strings.TrimPrefix(params.Folder, "/") - pathStr := fmt.Sprintf("/ssh-remote+%s.devpod/%s", params.Workspace, folder) + pathStr := fmt.Sprintf("/ssh-remote+%s"+pkgconfig.SSHHostSuffix+"/%s", params.Workspace, folder) u := &url.URL{ Scheme: config.scheme, Host: "vscode-remote", @@ -222,7 +223,7 @@ func buildOpenArgs(workspace, folder string, newWindow, hasContainersExtension b u := &url.URL{ Scheme: "vscode-remote", - Host: "ssh-remote+" + workspace + ".devpod", + Host: "ssh-remote+" + workspace + pkgconfig.SSHHostSuffix, Path: strings.TrimPrefix(folder, "/"), } folderURI := u.String() diff --git a/pkg/ide/zed/zed.go b/pkg/ide/zed/zed.go index a9084443d..5afe39186 100644 --- a/pkg/ide/zed/zed.go +++ b/pkg/ide/zed/zed.go @@ -24,7 +24,7 @@ func Open( workspaceFolder = fmt.Sprintf("/%s", workspaceFolder) } - sshHost := fmt.Sprintf("%s.devpod%s", workspaceID, workspaceFolder) + sshHost := workspaceID + config.SSHHostSuffix + workspaceFolder openURL := fmt.Sprintf("zed://ssh/%s", sshHost) err := open.Run(openURL) if err != nil { diff --git a/pkg/ide/zed/zed_linux.go b/pkg/ide/zed/zed_linux.go index b2c147a02..24e9ff396 100644 --- a/pkg/ide/zed/zed_linux.go +++ b/pkg/ide/zed/zed_linux.go @@ -24,7 +24,7 @@ func Open( workspaceFolder = fmt.Sprintf("/%s", workspaceFolder) } - sshHost := fmt.Sprintf("%s.devpod%s", workspaceID, workspaceFolder) + sshHost := workspaceID + config.SSHHostSuffix + workspaceFolder openURL := fmt.Sprintf("zed://ssh/%s", sshHost) out, err := exec.Command("xdg-open", openURL).CombinedOutput() if err != nil { diff --git a/pkg/inject/download_urls.go b/pkg/inject/download_urls.go index b264a8a5b..0e600b773 100644 --- a/pkg/inject/download_urls.go +++ b/pkg/inject/download_urls.go @@ -3,11 +3,13 @@ package inject import ( "net/url" "strings" + + "github.com/skevetter/devpod/pkg/config" ) const ( - AmdUrl = "devpod-linux-amd64" - ArmUrl = "devpod-linux-arm64" + AmdUrl = config.BinaryName + "-linux-amd64" + ArmUrl = config.BinaryName + "-linux-arm64" BinNamePlaceholder = "${BIN_NAME}" ) diff --git a/pkg/inject/inject.go b/pkg/inject/inject.go index 1949e9239..53cd98544 100644 --- a/pkg/inject/inject.go +++ b/pkg/inject/inject.go @@ -13,6 +13,7 @@ import ( "github.com/sirupsen/logrus" "github.com/skevetter/devpod/pkg/command" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/log" ) @@ -240,7 +241,7 @@ func isInjectingOfBinaryNeeded(lineStr string) bool { } func getFileReader(localFile LocalFile, lineStr string) (io.ReadCloser, error) { - isArm := strings.TrimPrefix(lineStr, "ARM-") == "true" + isArm := strings.TrimPrefix(lineStr, "ARM-") == config.BoolTrue return localFile(isArm) } diff --git a/pkg/loftconfig/config.go b/pkg/loftconfig/config.go index 6527eb17c..d6c591279 100644 --- a/pkg/loftconfig/config.go +++ b/pkg/loftconfig/config.go @@ -4,19 +4,32 @@ import ( "fmt" "os/exec" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform/client" "github.com/skevetter/log" ) func AuthDevpodCliToPlatform(config *client.Config, logger log.Logger) error { - cmd := exec.Command("devpod", "pro", "login", "--access-key", config.AccessKey, config.Host) + cmd := exec.Command( // #nosec G204 -- binary name is a compile-time constant + pkgconfig.BinaryName, + "pro", + "login", + "--access-key", + config.AccessKey, + config.Host, + ) out, err := cmd.CombinedOutput() if err != nil { - logger.Debugf("Failed executing `devpod pro login`: %w, output: %s", err, out) + logger.Debugf( + "Failed executing `%s pro login`: %w, output: %s", + pkgconfig.BinaryName, + err, + out, + ) return fmt.Errorf( - "error executing 'devpod pro login' command: %w, access key: %v, host: %v", + "error executing '%s pro login' command: %w, host: %v", + pkgconfig.BinaryName, err, - config.AccessKey, config.Host, ) } diff --git a/pkg/options/resolve.go b/pkg/options/resolve.go index 844e479f5..069578c6a 100644 --- a/pkg/options/resolve.go +++ b/pkg/options/resolve.go @@ -380,7 +380,7 @@ func resolveAgentCredentials( // resolveAgentDownloadURL resolves the agent download URL (env -> context -> default). func resolveAgentDownloadURL(devConfig *config.Config) string { - devPodAgentURL := os.Getenv(agent.EnvDevPodAgentURL) + devPodAgentURL := os.Getenv(config.EnvAgentURL) if devPodAgentURL != "" { return strings.TrimSuffix(devPodAgentURL, "/") + "/" } diff --git a/pkg/platform/client/client.go b/pkg/platform/client/client.go index 046ffe8ea..b0c8efcfb 100644 --- a/pkg/platform/client/client.go +++ b/pkg/platform/client/client.go @@ -19,6 +19,7 @@ import ( managementv1 "github.com/loft-sh/api/v4/pkg/apis/management/v1" storagev1 "github.com/loft-sh/api/v4/pkg/apis/storage/v1" "github.com/loft-sh/api/v4/pkg/auth" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/platform/kube" "github.com/skevetter/devpod/pkg/platform/project" "github.com/skevetter/devpod/pkg/util" @@ -328,7 +329,7 @@ func (c *client) Login(host string, insecure bool, log log.Logger) error { msg += " --insecure" } msg += "'" - log.Infof(msg, host, "devpod pro login", host) + log.Infof(msg, host, pkgconfig.BinaryName+" pro login", host) log.Infof("Logging into DevPod Pro...") key = <-keyChannel @@ -445,7 +446,7 @@ func VerifyVersion(baseClient Client) error { return fmt.Errorf( "unsupported %[1]s version %[2]s. Please downgrade your CLI to below v%[3]d.0.0 to support this version, "+ "as %[1]s v%[3]d.0.0 and newer versions are incompatible with v%[4]d.x.x", - "DevPod Pro", + pkgconfig.ProductNamePro, v.Version, cliVersion.Major, backendMajor, @@ -454,7 +455,7 @@ func VerifyVersion(baseClient Client) error { return fmt.Errorf( "unsupported %[1]s version %[2]s. Please upgrade your CLI to v%[3]d.0.0 or above to support this version, "+ "as %[1]s v%[3]d.0.0 and newer versions are incompatible with v%[4]d.x.x", - "DevPod Pro", + pkgconfig.ProductNamePro, v.Version, backendMajor, cliVersion.Major, @@ -512,7 +513,7 @@ func GetRestConfig(host, token string, insecure bool) (*rest.Config, error) { if err != nil { return nil, err } - config.UserAgent = "devpod/" + version.GetVersion() + config.UserAgent = pkgconfig.BinaryName + "/" + version.GetVersion() return config, nil } diff --git a/pkg/platform/deploy.go b/pkg/platform/deploy.go index 1d88de3d8..773f668be 100644 --- a/pkg/platform/deploy.go +++ b/pkg/platform/deploy.go @@ -7,6 +7,7 @@ import ( "strings" "time" + pkgconfig "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/log" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -45,11 +46,11 @@ func WaitForPodReady( LabelSelector: "app=loft", }) if err != nil { - log.Warnf("Error trying to retrieve %s pod: %v", "DevPod Pro", err) + log.Warnf("Error trying to retrieve %s pod: %v", pkgconfig.ProductNamePro, err) return false, nil } else if len(pods.Items) == 0 { if time.Now().After(now.Add(time.Second * 10)) { - log.Infof("Still waiting for a %s pod...", "DevPod Pro") + log.Infof("Still waiting for a %s pod...", pkgconfig.ProductNamePro) now = time.Now() } return false, nil @@ -90,7 +91,7 @@ func WaitForPodReady( if err != nil { return false, fmt.Errorf( "there seems to be an issue with %s starting up: %s (%s). Please reach out to our support at https://loft.sh/", - "DevPod Pro", + pkgconfig.ProductNamePro, message, reason, ) @@ -103,7 +104,7 @@ func WaitForPodReady( "%[1]s logs: \n%[2]v \nThere seems to be an issue with %[1]s starting up. "+ "Looks like you try to install %[1]s into an air-gapped environment, "+ "please reach out to our support at https://loft.sh/ for an offline license", - "DevPod Pro", + pkgconfig.ProductNamePro, string(out), ) } @@ -111,7 +112,7 @@ func WaitForPodReady( return false, fmt.Errorf( "%[1]s logs: \n%v \nThere seems to be an issue with %[1]s starting up: %[2]s (%[3]s). "+ "Please reach out to our support at https://loft.sh/", - "DevPod Pro", + pkgconfig.ProductNamePro, string(out), message, reason, @@ -120,20 +121,20 @@ func WaitForPodReady( if containerStatus.State.Waiting.Message != "" { log.Infof( "Please keep waiting, %s container is still starting up: %s (%s)", - "DevPod Pro", + pkgconfig.ProductNamePro, containerStatus.State.Waiting.Message, containerStatus.State.Waiting.Reason, ) } else if containerStatus.State.Waiting.Reason != "" { log.Infof( "Please keep waiting, %s container is still starting up: %s", - "DevPod Pro", + pkgconfig.ProductNamePro, containerStatus.State.Waiting.Reason, ) } else { log.Infof( "Please keep waiting, %s container is still starting up...", - "DevPod Pro", + pkgconfig.ProductNamePro, ) } diff --git a/pkg/provider/dir.go b/pkg/provider/dir.go index d1ae70695..83abebc51 100644 --- a/pkg/provider/dir.go +++ b/pkg/provider/dir.go @@ -21,7 +21,7 @@ const ( ProInstanceConfigFile = "pro.json" ProviderConfigFile = "provider.json" - DaemonStateFile = "devpod_ts.state" + DaemonStateFile = config.BinaryName + "_ts.state" ) func GetProInstancesDir(context string) (string, error) { diff --git a/pkg/provider/download.go b/pkg/provider/download.go index 83e49a8fc..3e427e3d3 100644 --- a/pkg/provider/download.go +++ b/pkg/provider/download.go @@ -32,7 +32,7 @@ const ( tarSuffix = ".tar" tgzSuffix = ".tgz" zipSuffix = ".zip" - cacheDir = "devpod-binaries" + cacheDir = config.BinaryName + "-binaries" ) var ( @@ -588,7 +588,7 @@ func extractZipArchive(body io.ReadCloser, targetFolder, targetPath string) (str } func downloadToTempFile(reader io.Reader) (string, error) { - tempFile, err := os.CreateTemp("", "devpod-archive-*") + tempFile, err := os.CreateTemp("", config.BinaryName+"-archive-*") if err != nil { return "", err } diff --git a/pkg/provider/env.go b/pkg/provider/env.go index adddd03d5..09db44a45 100644 --- a/pkg/provider/env.go +++ b/pkg/provider/env.go @@ -12,43 +12,6 @@ import ( log2 "github.com/skevetter/log" ) -const ( - // general. - DEVPOD = "DEVPOD" - DEVPOD_OS = "DEVPOD_OS" - DEVPOD_ARCH = "DEVPOD_ARCH" - DEVPOD_LOG_LEVEL = "DEVPOD_LOG_LEVEL" - - // workspace. - WORKSPACE_ID = "WORKSPACE_ID" - WORKSPACE_UID = "WORKSPACE_UID" - WORKSPACE_PICTURE = "WORKSPACE_PICTURE" - WORKSPACE_FOLDER = "WORKSPACE_FOLDER" - WORKSPACE_CONTEXT = "WORKSPACE_CONTEXT" - WORKSPACE_ORIGIN = "WORKSPACE_ORIGIN" - WORKSPACE_SOURCE = "WORKSPACE_SOURCE" - WORKSPACE_PROVIDER = "WORKSPACE_PROVIDER" - - // machine. - MACHINE_ID = "MACHINE_ID" - MACHINE_CONTEXT = "MACHINE_CONTEXT" - MACHINE_FOLDER = "MACHINE_FOLDER" - MACHINE_PROVIDER = "MACHINE_PROVIDER" - - // provider. - PROVIDER_ID = "PROVIDER_ID" - PROVIDER_CONTEXT = "PROVIDER_CONTEXT" - PROVIDER_FOLDER = "PROVIDER_FOLDER" - - // pro. - LOFT_PROJECT = "LOFT_PROJECT" - LOFT_FILTER_BY_OWNER = "LOFT_FILTER_BY_OWNER" -) - -const ( - DEVCONTAINER_ID = "DEVCONTAINER_ID" -) - func combineOptions( resolvedOptions map[string]config.OptionValue, otherOptions map[string]config.OptionValue, @@ -101,34 +64,34 @@ func ToOptionsWorkspace(workspace *Workspace) map[string]string { retVars := map[string]string{} if workspace != nil { if workspace.ID != "" { - retVars[WORKSPACE_ID] = workspace.ID + retVars[config.EnvProviderWorkspaceID] = workspace.ID } if workspace.UID != "" { - retVars[WORKSPACE_UID] = workspace.UID + retVars[config.EnvProviderWorkspaceUID] = workspace.UID } - retVars[WORKSPACE_FOLDER], _ = GetWorkspaceDir(workspace.Context, workspace.ID) - retVars[WORKSPACE_FOLDER] = filepath.ToSlash(retVars[WORKSPACE_FOLDER]) + workspaceFolder, _ := GetWorkspaceDir(workspace.Context, workspace.ID) + retVars[config.EnvProviderWorkspaceFolder] = filepath.ToSlash(workspaceFolder) if workspace.Context != "" { - retVars[WORKSPACE_CONTEXT] = workspace.Context - retVars[MACHINE_CONTEXT] = workspace.Context + retVars[config.EnvProviderWorkspaceContext] = workspace.Context + retVars[config.EnvProviderMachineContext] = workspace.Context } if workspace.Origin != "" { - retVars[WORKSPACE_ORIGIN] = filepath.ToSlash(workspace.Origin) + retVars[config.EnvProviderWorkspaceOrigin] = filepath.ToSlash(workspace.Origin) } if workspace.Picture != "" { - retVars[WORKSPACE_PICTURE] = workspace.Picture + retVars[config.EnvProviderWorkspacePicture] = workspace.Picture } - retVars[WORKSPACE_SOURCE] = workspace.Source.String() + retVars[config.EnvProviderWorkspaceSource] = workspace.Source.String() if workspace.Provider.Name != "" { - retVars[WORKSPACE_PROVIDER] = workspace.Provider.Name + retVars[config.EnvProviderWorkspaceProvider] = workspace.Provider.Name } if workspace.Machine.ID != "" { - retVars[MACHINE_ID] = workspace.Machine.ID + retVars[config.EnvProviderMachineID] = workspace.Machine.ID machineDir, _ := GetMachineDir(workspace.Context, workspace.Machine.ID) - retVars[MACHINE_FOLDER] = filepath.ToSlash(machineDir) + retVars[config.EnvProviderMachineFolder] = filepath.ToSlash(machineDir) } if workspace.Pro != nil && workspace.Pro.Project != "" { - retVars[LOFT_PROJECT] = workspace.Pro.Project + retVars[config.EnvLoftProject] = workspace.Pro.Project } maps.Copy(retVars, GetBaseEnvironment(workspace.Context, workspace.Provider.Name)) } @@ -139,15 +102,17 @@ func ToOptionsMachine(machine *Machine) map[string]string { retVars := map[string]string{} if machine != nil { if machine.ID != "" { - retVars[MACHINE_ID] = machine.ID + retVars[config.EnvProviderMachineID] = machine.ID } - retVars[MACHINE_FOLDER], _ = GetMachineDir(machine.Context, machine.ID) - retVars[MACHINE_FOLDER] = filepath.ToSlash(retVars[MACHINE_FOLDER]) + retVars[config.EnvProviderMachineFolder], _ = GetMachineDir(machine.Context, machine.ID) + retVars[config.EnvProviderMachineFolder] = filepath.ToSlash( + retVars[config.EnvProviderMachineFolder], + ) if machine.Context != "" { - retVars[MACHINE_CONTEXT] = machine.Context + retVars[config.EnvProviderMachineContext] = machine.Context } if machine.Provider.Name != "" { - retVars[MACHINE_PROVIDER] = machine.Provider.Name + retVars[config.EnvProviderMachineProvider] = machine.Provider.Name } maps.Copy(retVars, GetBaseEnvironment(machine.Context, machine.Provider.Name)) } @@ -183,14 +148,14 @@ func GetBaseEnvironment(context, provider string) map[string]string { // devpod binary devPodBinary, _ := os.Executable() - retVars[DEVPOD] = filepath.ToSlash(devPodBinary) - retVars[DEVPOD_OS] = runtime.GOOS - retVars[DEVPOD_ARCH] = runtime.GOARCH - retVars[PROVIDER_ID] = provider - retVars[PROVIDER_CONTEXT] = context + retVars[config.EnvBinaryPath] = filepath.ToSlash(devPodBinary) + retVars[config.EnvOS] = runtime.GOOS + retVars[config.EnvArch] = runtime.GOARCH + retVars[config.EnvProviderID] = provider + retVars[config.EnvProviderContext] = context providerFolder, _ := GetProviderDir(context, provider) - retVars[PROVIDER_FOLDER] = filepath.ToSlash(providerFolder) - retVars[DEVPOD_LOG_LEVEL] = log2.Default.GetLevel().String() + retVars[config.EnvProviderFolder] = filepath.ToSlash(providerFolder) + retVars[config.EnvLogLevel] = log2.Default.GetLevel().String() return retVars } diff --git a/pkg/ssh/config.go b/pkg/ssh/config.go index 780d78d65..a5ab929ce 100644 --- a/pkg/ssh/config.go +++ b/pkg/ssh/config.go @@ -11,6 +11,7 @@ import ( "strings" "sync" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/util" "github.com/skevetter/log" "github.com/skevetter/log/scanner" @@ -48,7 +49,7 @@ func ConfigureSSHConfig(params SSHConfigParams) error { newFile, err := addHost(addHostParams{ path: targetPath, - host: params.Workspace + "." + "devpod", + host: params.Workspace + config.SSHHostSuffix, user: params.User, context: params.Context, workspace: params.Workspace, @@ -299,14 +300,18 @@ func GetUser( } user := "root" - _, err = transformHostSection(targetPath, workspaceID+"."+"devpod", func(line string) string { - splitted := strings.Split(strings.ToLower(strings.TrimSpace(line)), " ") - if len(splitted) == 2 && splitted[0] == "user" { - user = strings.Trim(splitted[1], "\"") - } + _, err = transformHostSection( + targetPath, + workspaceID+config.SSHHostSuffix, + func(line string) string { + splitted := strings.Split(strings.ToLower(strings.TrimSpace(line)), " ") + if len(splitted) == 2 && splitted[0] == "user" { + user = strings.Trim(splitted[1], "\"") + } - return line - }) + return line + }, + ) if err != nil { return "", err } @@ -328,7 +333,7 @@ func RemoveFromConfig( targetPath = sshConfigIncludePath } - newFile, err := removeFromConfig(targetPath, workspaceID+"."+"devpod") + newFile, err := removeFromConfig(targetPath, workspaceID+config.SSHHostSuffix) if err != nil { return fmt.Errorf("parse ssh config: %w", err) } diff --git a/pkg/ssh/keys.go b/pkg/ssh/keys.go index 2318fd539..dca30cfec 100644 --- a/pkg/ssh/keys.go +++ b/pkg/ssh/keys.go @@ -12,15 +12,16 @@ import ( "path/filepath" "sync" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/provider" "github.com/skevetter/devpod/pkg/util" "golang.org/x/crypto/ssh" ) var ( - DevPodSSHHostKeyFile = "id_devpod_rsa_host" - DevPodSSHPrivateKeyFile = "id_devpod_rsa" - DevPodSSHPublicKeyFile = "id_devpod_rsa.pub" + DevPodSSHHostKeyFile = "id_" + config.BinaryName + "_rsa_host" + DevPodSSHPrivateKeyFile = "id_" + config.BinaryName + "_rsa" + DevPodSSHPublicKeyFile = "id_" + config.BinaryName + "_rsa.pub" ) var keyLock sync.Mutex @@ -84,7 +85,7 @@ func GetPrivateKeyRaw(context, workspaceID string) ([]byte, error) { func GetDevPodKeysDir() string { dir, err := util.UserHomeDir() if err == nil { - tempDir := filepath.Join(dir, ".devpod", "keys") + tempDir := filepath.Join(dir, config.ConfigDirName, "keys") // #nosec G301 -- TODO Consider using a more secure permission setting and ownership if needed. err = os.MkdirAll(tempDir, 0o755) if err == nil { @@ -93,7 +94,7 @@ func GetDevPodKeysDir() string { } tempDir := os.TempDir() - return filepath.Join(tempDir, "devpod-ssh") + return filepath.Join(tempDir, config.BinaryName+"-ssh") } func GetDevPodHostKey() (string, error) { diff --git a/pkg/telemetry/collect.go b/pkg/telemetry/collect.go index 4d2b786be..fae518404 100644 --- a/pkg/telemetry/collect.go +++ b/pkg/telemetry/collect.go @@ -26,20 +26,18 @@ const ( PanicSeverity ErrorSeverityType = "panic" ) -const UIEnvVar = "DEVPOD_UI" - var UIEventsExceptions []string = []string{ - "devpod list", - "devpod status", - "devpod provider list", - "devpod pro list", - "devpod pro check-health", - "devpod pro check-update", - "devpod ide list", - "devpod ide use", - "devpod provider use", - "devpod version", - "devpod context options", + config.BinaryName + " list", + config.BinaryName + " status", + config.BinaryName + " provider list", + config.BinaryName + " pro list", + config.BinaryName + " pro check-health", + config.BinaryName + " pro check-update", + config.BinaryName + " ide list", + config.BinaryName + " ide use", + config.BinaryName + " provider use", + config.BinaryName + " version", + config.BinaryName + " context options", } // skip everything in pro mode. @@ -56,8 +54,8 @@ type CLICollector interface { // StartCLI starts collecting events and sending them to the backend from the CLI. func StartCLI(devPodConfig *config.Config, cmd *cobra.Command) { telemetryOpt := devPodConfig.ContextOption(config.ContextOptionTelemetry) - if telemetryOpt == "false" || version.GetVersion() == version.DevVersion || - os.Getenv("DEVPOD_DISABLE_TELEMETRY") == "true" { + if telemetryOpt == config.BoolFalse || version.GetVersion() == version.DevVersion || + os.Getenv(config.EnvDisableTelemetry) == config.BoolTrue { return } @@ -103,7 +101,7 @@ func (d *cliCollector) RecordCLI(err error) { return } cmd := d.cmd.CommandPath() - isUI := os.Getenv(UIEnvVar) == "true" + isUI := os.Getenv(config.EnvUI) == config.BoolTrue // Ignore certain commands triggered by DevPod Desktop if isUI { if slices.Contains(UIEventsExceptions, cmd) { @@ -154,9 +152,9 @@ func (d *cliCollector) RecordCLI(err error) { isPro = true } } - eventType := "devpod_cli" + eventType := config.BinaryName + "_cli" if isPro { - eventType = "devpod_cli_runner" + eventType = config.BinaryName + "_cli_runner" } // build the event and record diff --git a/pkg/ts/util.go b/pkg/ts/util.go index 7bf76e8d7..2ec362096 100644 --- a/pkg/ts/util.go +++ b/pkg/ts/util.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/log" "tailscale.com/client/local" "tailscale.com/ipn" @@ -22,11 +23,11 @@ func GetClientHostname(userName string) (string, error) { return "", err } osHostname = strings.ToLower(strings.ReplaceAll(osHostname, ".", "-")) - return fmt.Sprintf("devpod.%s.%s.client", osHostname, userName), nil + return fmt.Sprintf(config.BinaryName+".%s.%s.client", osHostname, userName), nil } func GetWorkspaceHostname(name, namespace string) string { - return fmt.Sprintf("devpod.%s.%s.workspace", name, namespace) + return fmt.Sprintf(config.BinaryName+".%s.%s.workspace", name, namespace) } func ParseWorkspaceHostname(hostname string) (name string, project string, err error) { diff --git a/pkg/tunnel/services.go b/pkg/tunnel/services.go index 31ba9462f..5f33519f4 100644 --- a/pkg/tunnel/services.go +++ b/pkg/tunnel/services.go @@ -19,7 +19,6 @@ import ( "github.com/skevetter/devpod/pkg/agent/tunnelserver" "github.com/skevetter/devpod/pkg/config" config2 "github.com/skevetter/devpod/pkg/devcontainer/config" - "github.com/skevetter/devpod/pkg/devcontainer/setup" "github.com/skevetter/devpod/pkg/gitsshsigning" "github.com/skevetter/devpod/pkg/ide/openvscode" "github.com/skevetter/devpod/pkg/netstat" @@ -57,7 +56,7 @@ type RunServicesOptions struct { // getExitAfterTimeout calculates the timeout value based on configuration. func getExitAfterTimeout(devPodConfig *config.Config) time.Duration { - if devPodConfig.ContextOption(config.ContextOptionExitAfterTimeout) != "true" { + if devPodConfig.ContextOption(config.ContextOptionExitAfterTimeout) != config.BoolTrue { return 0 } return defaultExitTimeout @@ -260,7 +259,7 @@ func getContainerResult(ctx context.Context, p portForwardParams) (*config2.Resu stderr := &bytes.Buffer{} err := devssh.Run(ctx, devssh.RunOptions{ Client: p.containerClient, - Command: "cat " + setup.ResultLocation, + Command: "cat " + config.DevContainerResultPath, Stdout: stdout, Stderr: stderr, }) @@ -278,7 +277,7 @@ func getContainerResult(ctx context.Context, p portForwardParams) (*config2.Resu if err != nil { return nil, fmt.Errorf("error parsing container result %s: %w", stdout.String(), err) } - p.log.Debugf("parsed container result from %s", setup.ResultLocation) + p.log.Debugf("parsed container result from %s", config.DevContainerResultPath) return result, nil } diff --git a/pkg/upgrade/upgrade.go b/pkg/upgrade/upgrade.go index 58fb83ad4..67481e236 100644 --- a/pkg/upgrade/upgrade.go +++ b/pkg/upgrade/upgrade.go @@ -7,12 +7,11 @@ import ( "strings" "github.com/creativeprojects/go-selfupdate" + "github.com/skevetter/devpod/pkg/config" "github.com/skevetter/devpod/pkg/version" "github.com/skevetter/log" ) -const defaultRepository = "skevetter/devpod" - // Upgrade downloads the latest release from github and replaces devpod if a new version is found. // If dryRun is true, it only shows what would be downloaded without actually upgrading. func Upgrade(ctx context.Context, targetVersion string, dryRun bool, logger log.Logger) error { @@ -72,7 +71,7 @@ func detectRelease( return nil, nil, fmt.Errorf("initialize updater: %w", err) } - repo := selfupdate.ParseSlug(defaultRepository) + repo := selfupdate.ParseSlug(config.RepoSlug) if targetVersion != "" { release, err := detectSpecificVersion(ctx, updater, repo, targetVersion) diff --git a/pkg/workspace/list.go b/pkg/workspace/list.go index a3e925e9f..19482c109 100644 --- a/pkg/workspace/list.go +++ b/pkg/workspace/list.go @@ -363,7 +363,7 @@ func listInstancesProxyProvider( log log.Logger, ) ([]managementv1.DevPodWorkspaceInstance, error) { opts := devPodConfig.ProviderOptions(provider) - opts[providerpkg.LOFT_FILTER_BY_OWNER] = config.OptionValue{Value: "true"} + opts[config.EnvLoftFilterByOwner] = config.OptionValue{Value: "true"} var stdout bytes.Buffer var stderr bytes.Buffer diff --git a/pkg/workspace/machine.go b/pkg/workspace/machine.go index 19867e668..1f8af5b8c 100644 --- a/pkg/workspace/machine.go +++ b/pkg/workspace/machine.go @@ -259,7 +259,7 @@ func createMachine(context, machineID, providerName string) (*providerpkg.Machin } func SingleMachineName(devPodConfig *config.Config, provider string, log log.Logger) string { - legacyMachineName := "devpod-shared-" + provider + legacyMachineName := config.BinaryName + "-shared-" + provider machines, err := listMachines(devPodConfig, log) if err == nil { for _, machine := range machines { @@ -270,7 +270,7 @@ func SingleMachineName(devPodConfig *config.Config, provider string, log log.Log } return encoding.SafeConcatNameMax( - []string{"devpod-shared", provider, encoding.GetMachineUIDShort(log)}, + []string{config.BinaryName + "-shared", provider, encoding.GetMachineUIDShort(log)}, encoding.MachineUIDLength, ) } diff --git a/pkg/workspace/provider.go b/pkg/workspace/provider.go index 8d6a55c31..1d0e94b58 100644 --- a/pkg/workspace/provider.go +++ b/pkg/workspace/provider.go @@ -21,16 +21,6 @@ import ( "github.com/skevetter/log" ) -const ( - httpPrefix = "http://" - httpsPrefix = "https://" - githubPrefix = "github.com/" - yamlExt = ".yaml" - ymlExt = ".yml" - dsStorePrefix = ".DS_Store" - providerPrefix = "skevetter/devpod-provider-" -) - var ErrNoWorkspaceFound = errors.New("no workspace found") type ProviderWithOptions struct { @@ -305,7 +295,7 @@ func downloadProviderGithub( originalPath string, log log.Logger, ) ([]byte, *provider.ProviderSource, error) { - path := strings.TrimPrefix(originalPath, githubPrefix) + path := strings.TrimPrefix(originalPath, "github.com/") release := "" index := strings.LastIndex(path, "@") @@ -316,7 +306,7 @@ func downloadProviderGithub( splitted := strings.Split(strings.TrimSuffix(path, "/"), "/") if len(splitted) == 1 { - path = providerPrefix + path + path = config.RepoOwner + "/" + config.ProviderPrefix + path } else if len(splitted) != 2 { return nil, nil, fmt.Errorf( "invalid github path format: expected 'owner/repo' or 'provider-name', got %q", @@ -400,7 +390,7 @@ func loadUnconfiguredProviders( func shouldSkipEntry(entry os.DirEntry, retProviders map[string]*ProviderWithOptions) bool { return retProviders[entry.Name()] != nil || !entry.IsDir() || - strings.HasPrefix(entry.Name(), dsStorePrefix) + strings.HasPrefix(entry.Name(), ".DS_Store") } func loadProviderEntry( @@ -587,8 +577,8 @@ func resolveURLProvider( retSource *provider.ProviderSource, log log.Logger, ) ([]byte, bool, error) { - if !strings.HasPrefix(providerSource, httpPrefix) && - !strings.HasPrefix(providerSource, httpsPrefix) { + if !strings.HasPrefix(providerSource, "http://") && + !strings.HasPrefix(providerSource, "https://") { return nil, false, nil } @@ -605,7 +595,7 @@ func resolveFileProvider( providerSource string, retSource *provider.ProviderSource, ) ([]byte, bool, error) { - if !strings.HasSuffix(providerSource, yamlExt) && !strings.HasSuffix(providerSource, ymlExt) { + if !strings.HasSuffix(providerSource, ".yaml") && !strings.HasSuffix(providerSource, ".yml") { return nil, false, nil }