Open Saviq opened 5 years ago
I think this is quite a big deal, I am still trying to wrap my head around it, so sorry if comments and question below sound confused or contradictory.
Overall, it is nice to have a long view of where to go, but perhaps it would be more manageable to split things into elementary steps (identifying dependencies/precedences early and then considering each one in detail).
Perhaps we don't need to resolve the end-goal in detail for now. In particular, the exact final schema is less of an issue to begin with IMO. Personally my concerns go more toward how the feature would work (whatever the exact config contents). Here are some questions and things to think about:
Perhaps we don't need to resolve the end-goal in detail for now. In particular, the exact final schema is less of an issue to begin with IMO. Personally my concerns go more toward how the feature would work (whatever the exact config contents). Here are some questions and things to think about:
Sure, this was a brain-dump for determining the user experience of all this - for that we need to look ahead so we don't step in the wrong direction.
I wanted this issue to only deal with how the data is presented to the user in a CLI environment, I don't put any requirements on how it is handled internally by either the client or daemon. I have omitted your comments that deal with that.
- general symbolic representation/structure
- [x] this seems to be settled as some form of property tree
Yes, that is my proposal and the direction a lot of our projects are going.
- Instances are currently persistified by the daemon, so mixing in instances with the config means the daemons are not only consumers but also producers
Not sure what you mean here. Adding an instance entry in the YAML above would be an error (instance not found), removing it would be a no-op on the instance configuration.
- at what point in the chain of consuming a yaml do we approach validation?
Each entity should be responsible for validating their own piece of the configuration (the client - the client
. subtree, each remote their own).
- the configuration needs to be conveyed over the network, but still written to locally
The YAML is just a presentation format to the user. To show a remote's configuration, the client has to ask the remote to provide it with its current config. No remote config is persisted by the client, it is just sent over the wire.
- concerning the config cli, it is different from both lxc, git... Is it modeled after something else? Otherwise wouldn't it be better to stick to something existing?
It is definitely inspired by LXD, but early on we decided to not have nested commands (lxc config device edit…
) to keep our CLI clean. What kind of changes would you suggest?
Thanks for the reply. OK, perhaps I missed the scope here. I thought this was +/- go for implementation and felt grasping for the architecture part. Anyway, you already clarified some things.
Yes, that is my proposal and the direction a lot of our projects are going.
Sure, sounds like the way to go.
Not sure what you mean here [...]
Oh, I was also under the impression that this config would end up replacing the current image and instance DBs. That would include state info not necessarily driven by the client, which is why I mentioned the daemon as producer. If this is only strict config, that makes it simpler (which often implies better :wink:)
Each entity should be responsible for validating their own piece of the configuration [...]
OK, I was also thinking about each entity internally. Immediate validation means the effects of a multipass set
need to be synchronous. It can't be just writing info somewhere that objects later read as needed, so this impacts my point 3 above (info would have to be propagated).
[...] No remote config is persisted by the client [...]
OK, so we're separating client/remote configs, whatever the backend. I wasn't sure you wanted that.
It is definitely inspired by LXD [...] What kind of changes would you suggest?
git config
is quite similar but nesting (only) the commands (not the contents). So getting, setting, unsetting, all are achieved with git config
(+ appropriate option). And there is no '=' between key and value. If we followed that, we could do
multipass config <key>
to get a yaml treemultipass config <key> <val>
to setmultipass config --add <key> <val>
to addmultipass config --get <key>
to get, etc. This would make it clear we were talking about configuration (plain get/set could be less clear). It would allow grouping config documentation under a single command and it would probably be more familiar.
git config
is quite similar but nesting (only) the commands (not the contents). So getting, setting, unsetting, all are achieved withgit config
(+ appropriate option). And there is no '=' between key and value. If we followed that, we could do* `multipass config <key>` to get a yaml tree * `multipass config <key> <val>` to set * `multipass config --add <key> <val>` to add * `multipass config --get <key>` to get, etc.
The --add
/ --get
seem to me like nested commands even if they pretend not to be… What happens if you multipass config --add <key> <val> --get <key> --add <key> <val>
? Suddenly options actually become positional arguments…
This would make it clear we were talking about configuration (plain get/set could be less clear). It would allow grouping config documentation under a single command and it would probably be more familiar.
Maybe we can still do with config
alone…
multipass config [<subtree|key> …]
to get / edit a yaml tree or a value if a single full key was givenmultipass config <key>=<val> [<key>=<val> …]
to set multiple values at the same timeThe --add / --get seem to me like nested commands even if they pretend not to be
They are, that is why I said nesting (only) the commands (not the contents). I thought it could be worth considering.
What happens if you multipass config --add
--get --add
They would be mutually exclusive (see git help config
).
Maybe we can still do with
config
alone…
Hmm, I prefer the original then. To be fair, I meanwhile noticed get/set would be consistent with snap
.
@Saviq: how do you feel about replacing client.primary-name
with client.petenv-name
? I would favor it, given that "petenv" is already spread throughout code ids, while "primary" is isolated as the current value of the petenv_name
constant.
@ricab it's for presentation to the user, we'd have to explain to the user what it means, and why do we call it primary
there but petenv
here.
Right, good point.
We've been iterating on how could an "integrate with $app" configuration work and I'd like to document what we're thinking:
client:
apps:
windows-terminal:
profiles: primary # or "none", "all"
windows-terminal-private: # Windows Terminal with a custom settings path
type: windows-terminal
settings-file: C:\some\path\settings.json
profiles: all
iterm2:
profiles: primary
lxc:
remotes: all
prefix: mp-
lxc-beta: # a parallel install of LXD from the `beta` channel
remotes: all
command: snap run lxd_beta.lxc
gui:
terminal-app: windows-terminal-private # pointer at one of client.apps above
Each app could have a distinct set of properties that can be extended over time. The type
would default to the key in the client.apps
map, and would route the settings below to the right integration points.
From further discussion on IRC, it would be nice to support a general terminal
, where the user could specify the executable/command, and a linux-terminal
, where the user could specify a terminal that was known to the system via a desktop file.
From further discussion on IRC, it would be nice to support a general
terminal
, where the user could specify the executable/command, and alinux-terminal
, where the user could specify a terminal that was known to the system via a desktop file.
Sure, the above is not meant to be exhaustive :)
Sure, the above is not meant to be exhaustive :)
I know, just wanted to record it for the future :slightly_smiling_face:
So here's a case that I don't think we've fully considered:
$ multipass launch --name driver Launched: driver $ multipass get --keys client.gui.autostart client.gui.hotkey client.primary-name local.bridged-network local.driver local.driver.cpus local.driver.disk local.driver.memory
I think we need to plan for <remote>.instances.<instance-name>.*
to be the disambiguated key (e.g. for multipass config
), with local.<instance-name>.*
being a shorthand, where not ambiguous (e.g. multipass get/set
).
307 has some details on specifics of the "custom repository" feature, but I wanted to collect the user experience and the imaginable extent of the configuration structure here.
The CLI
Three new commands would be introduced, all operating on YAML-formatted data, with
.
(periods) separating depth levels. All operations need to be atomic and return validation errors.The structure
To avoid unnecessary nesting, I propose top-level keys to only be:
client
and remote names, with remote configuration nested under the remote name.That's the extent of configuration that I can come up with right now, please have a look through for errors, missing bits or plain stupidity. ;)
Doubts:
mounts
would be stricter if it wastarget_path: source_path
to ensure key (and hence, mount target) uniqueness, and allow the same source mounted in multiple places; but could be confusingstreams
the same way LXD does, and make them remotes (of different types)remote.instances.instance
means more typing, unless we maybe defineremote:instance
as a shortcut for it; along withdefault-remote
this could arguably be shortened tomultipass config name
, which gets expanded to$default-remote:instance
ifname
not found, and then to$default-remote.instances.instance
null
(~
) could be used to reset instead