-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Add stack config command #2740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add stack config command #2740
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2740 +/- ##
==========================================
+ Coverage 57.14% 57.18% +0.03%
==========================================
Files 297 298 +1
Lines 18634 18679 +45
==========================================
+ Hits 10649 10681 +32
- Misses 7126 7135 +9
- Partials 859 863 +4 |
821f4e0 to
693e951
Compare
3953ff8 to
8f47383
Compare
ae8904c to
4211f1e
Compare
|
Thank you! I haven't had time yet to look closely at these changes, but it came up in our slack channel. I like the general idea; still thinking somewhat about naming of that command. It's good that it matches the For |
Maybe |
I would add, borrowing a bit from Terraform:
@thaJeztah , what are your thoughts on these alternatives? |
Good point, even when Terraform architecture it selves is quite awful (IMO) that term "plan" make sense on both of thus use cases. |
Make use of existing modules and functions in order to output the merged configs. Added skip interpolation flag of variables, so that you can pipe the output back to stack deploy without much hassle. Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
4211f1e to
53247fe
Compare
|
Removing myself as a reviewer because completion is not touched in this PR. |
| Short: "Outputs the final config file, after doing merges and interpolations", | ||
| Args: cli.NoArgs, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| configDetails, err := loader.GetConfigDetails(opts.Composefiles, dockerCli.In()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: @SMFloris why not using LoadComposefile function instead, which actually calls getConfigDetails ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great question!
If I recall correctly, I didn't use it because I wanted to have control on how the compose files are actually getting loaded.
The --skip-interpolation flag is being sent down to the composeLoader.load() call, like so:
optsFunc := func(options *composeLoader.Options) {
options.SkipInterpolation = skipInterpolation
}
config, err := composeLoader.Load(configFiles, optsFunc)
This is kinda important to the use-case of this new command, seeing the output with and without interpolation to figure out where things went wrong and if you're deploying the right thing.
Another reason is that LoadComposefile also does some other things besides loading compose files, it also does some validation (forbidden, deprecated and unsupported properties). I thought those validations were just for deploy since the validation of the composeLoader.load is also used. 🤔 Also, since in my mind I'm piping the output back to docker stack deploy -c - I saw no reason in doing deploy validations when not doing a deploy.
The final reason, since I wasn't that familiar with the code-base and because I added a new command I didn't want to mess too much with the existing signatures of the methods 😅
Now that I'm more familiar with the codebase. I can change the LoadComposefile function to pass down some options to composeLoader.load() call if you want me too (perhaps even adding an option to skip those other validations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah any thoughts on that? I'm a bit on the fence, as if the output is pipped to the docker stack deploy command, then the config should print the warnings I guess... but it can also be pipped to the docker-compose command...
@SMFloris propose to call LoadComposeFile and add the --skip-validation option so one can disable the validation... WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah , could we get your input on the above, please? 😄 We are doing some ugly hacks with downgrading docker-compose in order to get valid docker stack deploy files
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it also does some validation (forbidden, deprecated and unsupported properties). I thought those validations were just for deploy since the validation of the composeLoader.load is also used
So if we're trying to replicate docker-compose config, that command is described as "Validate and view the Compose file"; from that perspective, I think it would make sense to have it validate the compose-file, so that only a valid file would be generated.
but it can also be pipped to the docker-compose command...
Not sure if we should consider if for that (as docker-compose has a config command itself 🤔
propose to call LoadComposeFile and add the
--skip-validationoption so one can disable the validation... WDYT?
Do we know why the --skip-validation option was added in compose? Wondering what the exact use-case is if that would allow it to produce invalid output (or is it skipping specific validation steps?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah , I managed to track the inclusion of these options down to #1128
Maybe reading through that a bit can help jog some memories 😄
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Codecov Report
@@ Coverage Diff @@
## master #2740 +/- ##
==========================================
+ Coverage 57.14% 57.17% +0.02%
==========================================
Files 297 298 +1
Lines 18634 18677 +43
==========================================
+ Hits 10649 10679 +30
- Misses 7126 7135 +9
- Partials 859 863 +4 |
|
@silvin-lubecki @thaJeztah , Any updates or new thoughts on this PR? I'm gonna keep updating this PR and keep it from going stale unless you guys have other thoughts 😄 |
|
@silvin-lubecki @thaJeztah Any new developments on this? |
thaJeztah
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arf, sorry for the very long delay; I had some review comment, but looks like I never posted them 😞
| Short: "Outputs the final config file, after doing merges and interpolations", | ||
| Args: cli.NoArgs, | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| configDetails, err := loader.GetConfigDetails(opts.Composefiles, dockerCli.In()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it also does some validation (forbidden, deprecated and unsupported properties). I thought those validations were just for deploy since the validation of the composeLoader.load is also used
So if we're trying to replicate docker-compose config, that command is described as "Validate and view the Compose file"; from that perspective, I think it would make sense to have it validate the compose-file, so that only a valid file would be generated.
but it can also be pipped to the docker-compose command...
Not sure if we should consider if for that (as docker-compose has a config command itself 🤔
propose to call LoadComposeFile and add the
--skip-validationoption so one can disable the validation... WDYT?
Do we know why the --skip-validation option was added in compose? Wondering what the exact use-case is if that would allow it to produce invalid output (or is it skipping specific validation steps?)
| with `REDIRECT_REGEX=http://host/redirect/${1}`, but then when piping it back to the `stack deploy` | ||
| command it will be interpolated again and result in undefined behavior. | ||
| That is why, when piping the output back to `stack deploy` one should always prefer the `--skip-interpolation` option. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering if we should reverse the default (skip interpolation by default, but allow users to opt-in, with --interpolate)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just about to push this change, but actually saw that the compose loader (loader.go) we use also has a --skip-interpolation flag. It might cause confusion passing !interpolate to it.
@thaJeztah , Should I keep it as it is to avoid confusion or remove --skip-interpolation in favor of --interpolate?
EDIT: clarification
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah , have you thought on how to proceed?
|
@thaJeztah , thanks for your review. I'll take a better look over it tonight and come back 😄 |
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
Signed-off-by: Stoica-Marcu Floris-Andrei <floris.sm@gmail.com>
1b66bb0 to
98d5109
Compare
Add stack config command.
Fixes #2365
Usage:
- What I did
Added stack config command that outputs on stdout the merged and/or interpolated config files for docker stack deploy.
Now it is no longer required to have docker-compose in order to see how configs are interpolated and merged before deploying your stack.
Currently, in our team, we currently use something like this to check our merge/compilation output:
The interpolation and merge that
docker-compose configprovides is untrue in a swarm deploy context since docker-compose and docker/cli are two separate projects and use different methods for interpolation and merge. With the latest version of docker-compose we encountered some problems with the merged/interpolated format not being accepted by docker stack deploy. I decided to bring a config command to docker/cli as well so we won't encounter this problem in the future.Related issues with latest docker-compose version:
docker/compose#7773
docker/compose#7778
I also added relevant unit tests for the two new merges.
- How I did it
I used the existing dependencies (the yaml lib) and functionality present in docker cli (the stack loader and the compose loader) in order to load the config files, merge/interpolate them and then output the yaml to stdout.
Testing on our own docker-compose files, I also noticed that when merging with docker stack deploy some properties did not merge in an expected way and produced unexpected consequences.
the volume property in each service, would not take into account the target of the volume when merging.
I believe that in many cases, you would have a prod compose file with named or anonymous volumes and a dev compose file with a bind mounted volume to the same target. The merge of
docker stack deploywould just concatenate the volumes array and throw an error since you try to mount to the same target. See the example in (How to verify it section of this PR), on how this PR merges them.the command property and entrypoint in each service, would just be concatenated, whereas with
docker-compose configit would've been replaced. Meaning, for example, that if in configFile1 you had a command likecat file1.txtand in configFile2 you have a command likecat file2.txtthe merge ofdocker stack deploy -c configFile1 -c configFile2would result in the command:cat file1.txt cat file2.txtwhich is definitely not what most people would expect and want. Modified this as well so that the command in configFile2 if exists will override the command in configFile1. See the example in (How to verify it section of this PR), on how this PR merges the command/entrypoint.- How to verify it
All you need is two very simple config files:
Now, if you run
$ENV_STRING=helloworld docker-local stack config -c docker-compose.test1.yml -c docker-compose.test2.yml(this is with interpolation), you will get something like this:If you run
docker-local stack config -c docker-compose.test1.yml -c docker-compose.test2.yml --skip-interpolation(this is without interpolation), you will get something like this:- Description for the changelog
Added docker stack config command that outputs the merged and interpolated config files as utilised by stack deploy.
- A picture of a cute animal (not mandatory but encouraged)

Here is neko ikiru san to apologize for the long read
P.S. I am new to Go, please let me know if I did anything in a not so Go way