Skip to content

feat(loader): made interpolation after merge#644

Closed
idsulik wants to merge 7 commits intocompose-spec:mainfrom
idsulik:issue-11925
Closed

feat(loader): made interpolation after merge#644
idsulik wants to merge 7 commits intocompose-spec:mainfrom
idsulik:issue-11925

Conversation

@idsulik
Copy link
Copy Markdown
Contributor

@idsulik idsulik commented Jun 23, 2024

What this PR does / why we need it:
Changed interpolation order, it used to interpolate for each config file separately, but now it interpolates after merge.
To be honest, I'm not sure it's a good idea, maybe it'll be better to add an option to control it, like --interpolate-after-merge

Which issue(s) this PR fixes:
Fixes docker/compose#11925

Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
@idsulik idsulik requested a review from ndeloof as a code owner June 23, 2024 08:34
@ndeloof
Copy link
Copy Markdown
Collaborator

ndeloof commented Jun 23, 2024

This was my initial intent during compose-go/v2 refactoring, but this breaks when include or extends uses variables for target file/service. Need at least partial interpolation for those - I never took time to look into this, would you like to give it a try ?

@idsulik
Copy link
Copy Markdown
Contributor Author

idsulik commented Jun 23, 2024

but this breaks when include or extends uses variables for target file/service

@ndeloof could you please provide an example?

@ndeloof
Copy link
Copy Markdown
Collaborator

ndeloof commented Jun 23, 2024

A typical use:

services:
  prod:
    image: a

  dev:
    image: a-dev

  app:
    extends: ${BASE:-prod}

@idsulik
Copy link
Copy Markdown
Contributor Author

idsulik commented Jun 23, 2024

@ndeloof pushed changes to interpolate include and extends before merging and interpolate everything after the merge, but I think it becomes too complicated.

return err
}

if !opts.SkipValidation {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

while remove per-file validation ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

accidentally removed, reverted it back

loader/loader.go Outdated

if opts.Interpolate != nil && !opts.SkipInterpolation {
interpolateOptsBeforeMerge = opts.Interpolate.Clone()
interpolateOptsBeforeMerge.KeysToInterpolate = []string{"include", "extends"}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

AFAICT this would interpolate include but will skip include.path, won't it?
This deserves a dedicated test as there's a high risk to introduce a regression with such a change
I also think it would be safer to filter by path (services.*.extends.**) vs attribute name

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it will. Fixed it, now it checks if the Path contains a given part.
Before writing tests I want to know do we agree to do it this way?

tree/path.go Outdated
return strings.Split(string(p), pathSeparator)
}

func (p Path) ContainsPart(part string) bool {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This could work for this use case but is a bit fragile.
IMHO we could make this more deterministic if Matches adds support for "anything and child" ** syntax, so that you can use :

KeysToInterpolate := []{
  "services.*.extends.**"
  "includes.**"
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

pushed changes, wrote tests, if you know any other cases that can be useful, let me know


if opts.Interpolate != nil && !opts.SkipInterpolation {
cfg, err = interp.Interpolate(cfg, *opts.Interpolate)
cfg, err = interp.Interpolate(cfg, interpolateOptsBeforeMerge)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wonder:
as extends will always require interpolation, wouldn't it be simpler to just force interpolation in ApplyExtends and ApplyInclude?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

  1. We call ApplyExtends only if SkipExtends is not true while interpolation happens always(the same for Include)
  2. We call ApplyInclude after interpolation and processors, if we start interpolate inside ApplyInclude in can have consequences, I wanted to keep current logic as much as I can

idsulik added 4 commits June 23, 2024 20:35
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
@ndeloof
Copy link
Copy Markdown
Collaborator

ndeloof commented Jul 1, 2024

Checking this PR again I went with an alternate implementation, reusing your test case: #651

wdyt ?

Anyway, the current compose-spec schema declare types for many attributes which can actually be set by a variable, and validation fails. Would need to first fix the schema

@ndeloof
Copy link
Copy Markdown
Collaborator

ndeloof commented Jul 8, 2024

Closing as #651 has been merged

@ndeloof ndeloof closed this Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Merge does not work properly with required variables

2 participants