Remodel preevy profile
Problem Description
The Preevy profile is currently two things:
- A persistent state which can be saved either locally or remotely. Contains the tunneling key, default flags and driver data.
- A map of references to the persistent states ("context"), which is always saved locally. Maps a local name to the location of the persistent state.
Managing the two using a single set of CRUD actions is confusing. Specifically:
| command | state | reference |
|---|---|---|
create |
✅ | ✅ |
import |
❌ | ✅ |
ls |
❌ | ✅ |
rm |
❌ if remote ✅ if local | ✅ |
cp |
✅ | ⚠️ creates a new reference, fails if it exists |
config update |
✅ | ❌ |
current and use |
❌ | ✅ |
Prior art
Docker CLI
Docker CLI has multiple contexts stored locally, and no state. Context is only editable using the CLI context commands. All CRUD operations on the context are supported in addition to import/export in blob format.
Usage: docker context COMMAND
Manage contexts
Commands:
create Create a context
export Export a context to a tar archive FILE or a tar stream on STDOUT.
import Import a context from a tar or zip file
inspect Display detailed information on one or more contexts
ls List contexts
rm Remove one or more contexts
show Print the name of the current context
update Update a context
use Set the current docker context
kubectl
Similarly to Docker CLI, kubectl has multiple contexts and no state. Contexts are stored in the kubeconfig file and are editable both using the CLI and directly by editing the file. Multiple kubeconfig files are allowed, with merging logic.
Examples: (source)
kubectl config view
kubectl config get-contexts # display list of contexts
kubectl config current-context # display the current-context
kubectl config use-context my-cluster-name # set the default context to my-cluster-name
kubectl config set-cluster my-cluster-name # set a cluster entry in the kubeconfig
kubectl config set-cluster my-cluster-name --proxy-url=my-proxy-url
kubectl config set-credentials kubeuser/foo.kubernetes.com --username=kubeuser --password=kubepassword
kubectl config set-context --current --namespace=ggckad-s2
kubectl config unset users.foo # delete user foo
Pulumi
Pulumi has a single context set locally via the login command (and unset via logout). The context references the state which can be stored on various backends (local, s3, gc, azblob, Pulumi Cloud).
Examples (source)
pulumi login # default Pulumi Cloud
pulumi login https://api.pulumi.acmecorp.com # self hosted Pulumi
pulumi login file://~
pulumi login s3://my-pulumi-state-bucket
There is no option to override the context on a specific command like in e.g, docker --context <context> ... or kubectl --context <context> ...
Suggested solutions
I suggest changing the preevy profile commands to only manage the state: tunneling key, default flags and driver data.
CRUD operations on the profile:
preevy profile create [url] [...args] # unspecified args will be prompted for
preevy profile rm <url>
preevy profile config view
preevy profile config update [...args]
preevy profile key
preevy profile cp <src> <dest>
preevy profile mv <src> <dest> # cp and rm
The reference to the profile can currently be expressed fully by the URL of the profile. There is no additional data (e.g, credentials or storage parameters).
We can support either a single context (a-la Pulumi), or a list of contexts similar to Docker CLI/kubectl and our existing features.
Option 1: Multiple contexts
This essentially allows referencing multiple profiles using local names.
Introduce a new entity "context" and a CLI topic preevy context:
preevy context add <name> <url>
preevy context update <name> <url>
preevy context rm <name>
preevy context ls
preevy context show
preevy context use <name>
The profile creation command can have flags to also add a new context or set an existing context with the new profile:
preevy profile create [--set-context <name>] [url] [...args]
Override context for a specific command
This is currently supported with the --profile global flag. We'll need to rename it to --context:
preevy up --context <name>
Convenience command init
preevy init -> preevy profile create --set-context default
Option 2: Single context
The main UX change here is dropping support for local names for the profile URLs.
Changing the current profile is done via the preevy profile use command:
preevy profile use <url>
preevy profile current # shows the URL
Looks good! I think having multiple context and having a way to override context is important, especially if preevy is used by other tools (like Docker extension that always use a specific context created by the extension). While we can separate the profile/context commands, I think we should see how we can make it easy to make it go end-in-end.
For example: Preevy init: profile create (params) -> context add (alias) --use Preevy init: --from=(url): context add (alias) (url) --use Preevy move/migrate-profile: preevy profile copy, preevy context update, preevy profile rm I think it's important that the main flows will be clear and won't require multiple commands
Migration can be relatively easy as (we can use deprecation policy and make these commands hidden): Preevy profile use -> preevy context use Preevy profile rm* -> preevy context rm Preevy profile import -> preevy context add (alias) (url) --use Preevy profile current -> preevy context show
** Not sure if we need preevy profile mv, also since we currently have profile rm, it might worth using preevy profile remove/delete for backward compatibility (maybe add flags that differ between clearing the data, and removing the container which might not always be possible or desired).