X Tutup
Skip to content

[K8s] Do env-variable expansion on the uninterpreted Config files#974

Merged
thaJeztah merged 1 commit intodocker:masterfrom
simonferquel:compose-kube-env-expansion
May 16, 2018
Merged

[K8s] Do env-variable expansion on the uninterpreted Config files#974
thaJeztah merged 1 commit intodocker:masterfrom
simonferquel:compose-kube-env-expansion

Conversation

@simonferquel
Copy link
Contributor

This fix an issue where composefiles like

version: '3'
services:
  front:
    image: nginx:1.12.1-alpine
      ports:
      - 80

get translated into

version: "3.0"
services:
  front:
    image: nginx:1.12.1-alpine
      ports:
      - mode: ingress
        target: 80
        protocol: tcp

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 expand
short representations into long ones, and don't risk breaking original
compose files.

@simonferquel
Copy link
Contributor Author

ping @mnottale @chris-crone @vdemeester

@dnephin
Copy link
Contributor

dnephin commented Mar 27, 2018

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.

@simonferquel
Copy link
Contributor Author

@dnephin agreed. That is also why we did that for v1beta2 :)

@simonferquel simonferquel force-pushed the compose-kube-env-expansion branch 2 times, most recently from 16442b4 to 270b9eb Compare March 27, 2018 17:42
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)
Copy link
Collaborator

@vdemeester vdemeester Mar 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the need to conserve the same compose version as original file

Do we need that ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Collaborator

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.json

So here are my thoughs:

  • Even with newer version of the controller, we should make the assumption that the v1beta1 api endpoint does not support composefile version higher (to make sure we don't have some weird behavior, like having different behavior between too v1beta1 endpoint 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 v1beta1 endpoint. As long format for describing ports has been introduced in 3.2, we know for a fact that v1beta1 supports that too. That means, we can/should send the compose file to the v1beta1 as version: "3.4" all the time if necessary (or at least 3.2 if it's lower than that).
  • If we need to "customize" the way the structure is marshalled back to a yaml for a specific version (from the current one to "3.x"), then it should be on the struct itself.

@vdemeester
Copy link
Collaborator

cc @silvin-lubecki @thaJeztah

@silvin-lubecki
Copy link
Contributor

silvin-lubecki commented Mar 28, 2018

That means we can/should know for sure in the CLI, which version of the composefile format we can and cannot send to the v1beta1 endpoint. As long format for describing ports has been introduced in 3.2, we know for a fact that v1beta1 supports that too. That means, we can/should send the compose file to the v1beta1 as version: "3.4" all the time if necessary (or at least 3.2 if it's lower than that).

👍 on this.

I think the CLI can error out if a Compose file with greater version than v1beta1 supports is used.

@simonferquel
Copy link
Contributor Author

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)

@simonferquel simonferquel force-pushed the compose-kube-env-expansion branch from 270b9eb to 5aff96f Compare March 28, 2018 12:51
@simonferquel
Copy link
Contributor Author

Done that. Also added a v3.5 schema validation of the resulting composefile after marshalling the composetypes.Config

@simonferquel
Copy link
Contributor Author

@vdemeester does it fit you ?

Copy link
Collaborator

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🐯
(honestly I would have prefered "3.4" because it's what 0.1.x version of controller supports)

@simonferquel
Copy link
Contributor Author

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)

@vdemeester
Copy link
Collaborator

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 v1beta1, it's the safest choice 👼

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const v1beta1MaxComposeVersion = "3.5"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this constant to the apiv1beta1 package? It should be the package responsibility to know which compose version it can handle.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And maybe we should add one also for v1beta2, and generalize the process?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point 😅

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a test with a compose file which fails with a 3.6 version?

@simonferquel
Copy link
Contributor Author

@silvin-lubecki I've moved the const declaration and added a test for v3.6 files

@thaJeztah
Copy link
Member

ping @simonferquel this needs a rebase

Signed-off-by: Simon Ferquel <simon.ferquel@docker.com>
@simonferquel simonferquel force-pushed the compose-kube-env-expansion branch from 8ae6e4d to f766aff Compare May 9, 2018 20:18
Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@thaJeztah
Copy link
Member

I think all comments were addressed, so merging

@thaJeztah thaJeztah merged commit bac0d8f into docker:master May 16, 2018
@GordonTheTurtle GordonTheTurtle added this to the 18.06.0 milestone May 16, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

X Tutup