Skip to content

[compose] Share the compose loading code between swarm and k8s stack deploy#845

Merged
vdemeester merged 1 commit into
docker:masterfrom
vdemeester:stack-load-the-same
Feb 19, 2018
Merged

[compose] Share the compose loading code between swarm and k8s stack deploy#845
vdemeester merged 1 commit into
docker:masterfrom
vdemeester:stack-load-the-same

Conversation

@vdemeester
Copy link
Copy Markdown
Collaborator

@vdemeester vdemeester commented Jan 29, 2018

To ensure we are loading the composefile the same wether we are pointing
to swarm or kubernetes, we need to share the loading code between both.

This means though that docker stack deploy pointing to k8s doesn't handle .env anymore (same beahviour as docker stack deploy on swarm).

  • struct mashall to a valid composefile
  • testing this on a real kubernetes cluster with the compose kubernetes on.

Signed-off-by: Vincent Demeester vincent@sbr.pm

@codecov-io
Copy link
Copy Markdown

codecov-io commented Jan 29, 2018

Codecov Report

Merging #845 into master will increase coverage by 1.84%.
The diff coverage is 43.52%.

@@            Coverage Diff             @@
##           master     #845      +/-   ##
==========================================
+ Coverage   53.19%   55.03%   +1.84%     
==========================================
  Files         246      234      -12     
  Lines       16021    15449     -572     
==========================================
- Hits         8522     8502      -20     
+ Misses       6929     6382     -547     
+ Partials      570      565       -5

Comment thread cli/command/stack/deploy.go Outdated
if err != nil {
return details, err
}
// TODO: support multiple files
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This will be fixed by #569 👼

Comment thread cli/command/stack/kubernetes/loader.go Outdated
return nil, nil, errors.Wrapf(err, "cannot load compose file")
}

fmt.Println(string(res))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

println?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yeah it was for debugging purpose, I'll remove once not wip anymore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah right... 😏

@vdemeester vdemeester force-pushed the stack-load-the-same branch 2 times, most recently from a18de0b to d0f6ed5 Compare January 30, 2018 02:13
"github.com/stretchr/testify/require"
)

func TestPlaceholders(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Was this test really useless, as it just disappeared?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes 😏 interpolation is already tested in the cli/compose/... packages 😉

Comment thread cli/command/stack/deploy.go Outdated
return err
}
return kubernetes.RunDeploy(kli, opts)
return kubernetes.RunDeploy(kli, opts, loadComposefile)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't like this functor. I think the only reason is to avoid circular dependency between stack package and swarm/kubernetes packages. A more cleaner way could be moving the loader in its own package, like cli/command/stack/loader.

@vdemeester vdemeester force-pushed the stack-load-the-same branch 2 times, most recently from e1dbd5c to bd61f77 Compare January 31, 2018 23:57
@vdemeester vdemeester changed the title WIP: Share the compose loading code between swarm and k8s stack deploy [compose] Share the compose loading code between swarm and k8s stack deploy Jan 31, 2018
@vdemeester
Copy link
Copy Markdown
Collaborator Author

So… yaml marshaling the types.Config struct from the compose package produce an invalid composefile 🤔 We may need to fix that 😅

@dnephin
Copy link
Copy Markdown
Contributor

dnephin commented Feb 5, 2018

Ya, I guess it's not necessarily designed to be round tripped. How is it invalid?

Copy link
Copy Markdown
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

LGTM

@vdemeester
Copy link
Copy Markdown
Collaborator Author

Services are marshalled as a list, but they are unmarshalled as a mapping.

This PR is not mergeable until we can fix that 😅

@vdemeester vdemeester force-pushed the stack-load-the-same branch 5 times, most recently from 1210082 to 6cb919f Compare February 8, 2018 16:41
@vdemeester
Copy link
Copy Markdown
Collaborator Author

Updated: it should now generate a valid yaml composefile — also tried it out on docker-for-mac kubernetes and it works !

Next step should be to upgrade the current test with everything, probably reuse full-example yaml file (and struct)

Comment thread cli/compose/types/types.go Outdated
}
m["services"] = services
}
if c.Networks != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Are these nil checks necessary (below)? If it is nil, it can assign nil without any problems, right? I think they can be removed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Right 😛

@dnephin
Copy link
Copy Markdown
Contributor

dnephin commented Feb 8, 2018

With full test looks good!

@vdemeester vdemeester force-pushed the stack-load-the-same branch 2 times, most recently from eda38cc to ec92b3a Compare February 9, 2018 09:52
ports:
- 3000
- "3000-3005"
- "3001-3005"
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Changed that to not have duplicate in the marshalled struct later.

@vdemeester
Copy link
Copy Markdown
Collaborator Author

@dnephin Updated with the full-example 🎉

Comment thread cli/command/stack/kubernetes/loader.go Outdated
return nil, err
}

yaml := "version: \"" + version + "\"\n" + string(res)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we do this by marshaling a local struct:

type versionedConfig struct {
    composetypes.Config
    Version string
}

Copy link
Copy Markdown
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.

(removed: PBKAC)

Comment thread cli/command/stack/deploy.go Outdated
Args: cli.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.Namespace = args[0]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

✂️ ✂️ ✂️ ✂️ ✂️ 😇

fmt.Fprintf(dockerCli.Err(), "Ignoring deprecated options:\n\n%s\n\n",
propertyWarnings(deprecatedProperties))
}
return config, configDetails.Version, nil
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not for this PR, but getConfigDetails() actually loads all the config files, and takes the "WorkDir" and "Version" of the first file that's loaded. If we added a Version to composetypes.ConfigFile, that would probably be a bit cleaner, because in loader.Load() we check the version again (we both set the version if it's empty, and check if versions are mixed);

configDict := file.Config
version := schema.Version(configDict)
if configDetails.Version == "" {
configDetails.Version = version
}
if configDetails.Version != version {
return nil, errors.Errorf("version mismatched between two composefiles : %v and %v", configDetails.Version, version)
}

Basically, these types;

// ConfigFile is a filename and the contents of the file as a Dict
type ConfigFile struct {
Filename string
Config map[string]interface{}
}
// ConfigDetails are the details about a group of ConfigFiles
type ConfigDetails struct {
Version string
WorkingDir string
ConfigFiles []ConfigFile
Environment map[string]string
}

Would then look something like;

// ConfigFile is a filename and the contents of the file as a Dict
type ConfigFile struct {
	Version    string
	Filename   string
	WorkingDir string
	Config     map[string]interface{}
}

// ConfigDetails are the details about a group of ConfigFiles
type ConfigDetails struct {
	ConfigFiles []ConfigFile
	Environment map[string]string
}

(Perhaps there should be an option to overwrite the WorkingDir)

Which leads to the question if ConfigDetails on its own is very useful (Environment is currently just the result of os.Environ(), and could be either passed as separate argument to loader.Load(), or fetched there?)

return details, errors.New("no composefile(s)")
}

if composefiles[0] == "-" && len(composefiles) == 1 {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We need to check if this behaviour is documented;

  • working-directory of the first compose-file is used
  • if the first file is from stdin, then the current working-directory is used

/cc @gbarr01

Copy link
Copy Markdown
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.

one nit (unrelated whitespace change), and a suggestion for a follow up, but LGTM

To ensure we are loading the composefile the same wether we are pointing
to swarm or kubernetes, we need to share the loading code between both.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>
Copy link
Copy Markdown
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
Copy Markdown
Member

ping @dnephin still LGTY?

Copy link
Copy Markdown
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

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

LGTM

func TestMarshallConfig(t *testing.T) {
cfg := fullExampleConfig("/foo", "/bar")
expected := `configs: {}
networks:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hopefully MarshalYAML is stable and doesn't change order randomly when we change fields.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

so far it did not 😇

Copy link
Copy Markdown
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

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

LGTM

@vdemeester vdemeester merged commit f56265a into docker:master Feb 19, 2018
@GordonTheTurtle GordonTheTurtle added this to the 18.03.0 milestone Feb 19, 2018
@vdemeester vdemeester deleted the stack-load-the-same branch February 19, 2018 14:28
nobiit pushed a commit to nobidev/docker-cli that referenced this pull request Nov 19, 2025
[compose] Share the compose loading code between swarm and k8s stack deploy
Upstream-commit: f56265a
Component: cli
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