[K8s] Do env-variable expansion on the uninterpreted Config files#974
Conversation
|
This is an excellent example of why the Compose file YAML should not be used as part of the API. The API should have its own types and the client should translate the compose file representation into the API types (just like with swarm mode). That way updates to the Compose file on the client don't unexpected break the API. |
|
@dnephin agreed. That is also why we did that for v1beta2 :) |
16442b4 to
270b9eb
Compare
| return errors.Errorf("Please specify only one compose file (with --compose-file).") | ||
| } | ||
|
|
||
| // due to env var expansion logic (and the need to conserve the same compose version as original file) |
There was a problem hiding this comment.
the need to conserve the same compose version as original file
Do we need that ?
There was a problem hiding this comment.
At the beginning, I wanted to just override the original composefile version with the latest supported by the cli (in order to align the "long-formats" generating by marshalling composetypes.Config with the version it is supported in), but after a bit of thinking I found that it was a bad idea: if in a future version of the CLI we introduce a new compose schema version, we will generate composefiles that the server-side can't understand if not updated (and we don't want to break compatibility with Docker EE for example).
There was a problem hiding this comment.
@simonferquel this is only for v1beta1 api (compose controller) right ? we know which version we support on that release of the controller, so really, we could, for this case only, decide of a version and never update it (until we drop support for v1beta1 👼 ). It's a special case anyway so let's make the "fix" the simplest.
There was a problem hiding this comment.
I don't think keeping an old config structure and implementing conversion from latest to this reference version is simpler than just doing the variable expansion on non-interpreted config files (this PR basically just expose exiting code to the kubernetes subpackage)
There was a problem hiding this comment.
I don't think keeping an old config structure and implementing conversion from latest to this reference version is simpler than just doing the variable expansion on non-interpreted config files (this PR basically just expose exiting code to the kubernetes subpackage)
Not sure I get that one. We don't keep an old structure anywhere.
As is, we do interpolation twice and use a different "config" between what is sent (just the map serialized) and what's used later (to wait for it to be ready, etc..). This breaks behavior now or maybe more in the future. As an example, this mean we don't call LoadService anymore (for the composefile we send), and thus we won't parse the envfile and update the environment for the service(s) — this is something we do as of now — same for resolveVolumePaths (although it's kinda broken #966).
With that PR, what will be the behavior for v1beta2 implemented in #899 ?
The v1beta1 api version support composefile from 3.0 to 3.x in the first version of the compose controller right ?
// data/config_schema_v3.0.json
// data/config_schema_v3.1.json
// data/config_schema_v3.2.json
// data/config_schema_v3.3.json
// data/config_schema_v3.4.jsonSo here are my thoughs:
- Even with newer version of the controller, we should make the assumption that the
v1beta1api endpoint does not support composefile version higher (to make sure we don't have some weird behavior, like having different behavior between toov1beta1endpoint served by different controller version). - That means we can/should know for sure in the CLI, which version of the composefile format we can and cannot send to the
v1beta1endpoint. Aslong format for describing ports has been introduced in 3.2, we know for a fact thatv1beta1supports that too. That means, we can/should send the compose file to thev1beta1asversion: "3.4"all the time if necessary (or at least3.2if it's lower than that). - If we need to "customize" the way the structure is marshalled back to a
yamlfor a specific version (from the current one to "3.x"), then it should be on the struct itself.
👍 on this. I think the CLI can error out if a Compose file with greater version than v1beta1 supports is used. |
|
Ok, so we would have to be very careful anytime the composetypes.Config (or any of its nested struct) is updated, that we don't replace constructs from v3.5 with a different representation (e.g. that we only add fields). (v3.5 is the latest format supported in ee) |
270b9eb to
5aff96f
Compare
|
Done that. Also added a v3.5 schema validation of the resulting composefile after marshalling the composetypes.Config |
|
@vdemeester does it fit you ? |
vdemeester
left a comment
There was a problem hiding this comment.
LGTM 🐯
(honestly I would have prefered "3.4" because it's what 0.1.x version of controller supports)
|
0.1.x only shipped with a private beta of Docker for Mac, we don't want to support it any way (and docker for desktop ships its own version of the docker CLI aligned with the engine/kubernetes integration anyway) |
Right, but the image is there and public (I think ?) so it "could" still be used. I know we don't support it (as of Docker inc.), but if the there is no need to use 3.5 over 3.4 for |
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| ) | ||
|
|
||
| const v1beta1MaxComposeVersion = "3.5" |
There was a problem hiding this comment.
Can we move this constant to the apiv1beta1 package? It should be the package responsibility to know which compose version it can handle.
There was a problem hiding this comment.
And maybe we should add one also for v1beta2, and generalize the process?
There was a problem hiding this comment.
@silvin-lubecki we don't need one for v1beta2 as we send a struct that is not the composefile, this it has nothing to do with the composefile version
There was a problem hiding this comment.
But I think my first comment is still valid.
| return nil, err | ||
| } | ||
| if err = schema.Validate(resparsedConfig, v1beta1MaxComposeVersion); err != nil { | ||
| return nil, errors.Wrapf(err, "the generated compose yaml file is invalid with v%s", v1beta1MaxComposeVersion) |
There was a problem hiding this comment.
Remove "generated" in the message? I don't know if it will be a useful information for the user?
| }, | ||
| Spec: apiv1beta1.StackSpec{ | ||
| ComposeFile: `version: "3.1" | ||
| ComposeFile: `version: "3.5" |
There was a problem hiding this comment.
Add a test with a compose file which fails with a 3.6 version?
|
@silvin-lubecki I've moved the const declaration and added a test for v3.6 files |
|
ping @simonferquel this needs a rebase |
Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
8ae6e4d to
f766aff
Compare
|
I think all comments were addressed, so merging |
This fix an issue where composefiles like
get translated into
The problem here is that the long format for describing ports has been
introduced in 3.2 and so, the generated compose file is invalid.
I thought first about just always use latest version information to
override the output composefile version, but that would just make the
problem worse once we introduce a new compose file schema in the CLI
that is not supported on the server side.
This PR makes it possible to interpolate the compose files without
converting them into composetypes.Config (but only work on the loaded
config file format:
map[string]interface{}. This way, we don't expandshort representations into long ones, and don't risk breaking original
compose files.