Repository navigation
fix strategy: Merge for YAMLs in Glob sub-dirs
#383
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
Open
jonasbadstuebner
wants to merge
1
commit into
fluxcd:main
Choose a base branch
from
jonasbadstuebner:dev/382
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -176,7 +176,7 @@ c: | |
| source2Dir := filepath.Join(tmpDir, "source2") | ||
| workspaceDir := filepath.Join(tmpDir, "workspace") | ||
|
|
||
| setupDirs(t, source1Dir, source2Dir, workspaceDir) | ||
| setupDirs(t, filepath.Join(source1Dir, "config"), filepath.Join(source2Dir, "config"), workspaceDir) | ||
|
|
||
| // Create first source with base config | ||
| createFile(t, source1Dir, "config1.yaml", ` | ||
|
|
@@ -186,11 +186,17 @@ region: us-west-1 | |
| createFile(t, source1Dir, "config2.yaml", ` | ||
| version: 1.0.0 | ||
| image: my-app:latest | ||
| `) | ||
| createFile(t, filepath.Join(source1Dir, "config"), "config3.yaml", ` | ||
| version: 1.0.0 | ||
| image: my-app:latest | ||
| `) | ||
|
|
||
| // Create second source with overlay config | ||
| createFile(t, source2Dir, "config1.yaml", "env: prod") // This should overwrite the env | ||
| createFile(t, source2Dir, "config2.yaml", "replicas: 5") // This should add a new field | ||
| createFile(t, source2Dir, "config1.yaml", "env: prod") // This should overwrite the env | ||
| createFile(t, source2Dir, "config2.yaml", "replicas: 5") // This should add a new field in the root directory of the glob pattern | ||
| createFile(t, filepath.Join(source2Dir, "config"), "config3.yaml", "replicas: 10") // This should add a new field in a subdirectory matched by the glob pattern | ||
| createFile(t, filepath.Join(source2Dir, "config"), "config4.yaml", "content: hello-world") // This should add a new file | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added this test because the first iteration of my PR had a bug where if the target file would not exist, it would still have tried to merge the source file into it which lead to an error. |
||
|
|
||
| spec := &swapi.OutputArtifact{ | ||
| Name: "yaml-to-yaml-dir-merge", | ||
|
|
@@ -222,6 +228,8 @@ image: my-app:latest | |
| stagingDir := filepath.Join(workspaceDir, "yaml-to-yaml-dir-merge") | ||
| config1Path := filepath.Join(stagingDir, "config1.yaml") | ||
| config2Path := filepath.Join(stagingDir, "config2.yaml") | ||
| config3Path := filepath.Join(stagingDir, "config", "config3.yaml") | ||
| config4Path := filepath.Join(stagingDir, "config", "config4.yaml") | ||
|
|
||
| config1Content, err := os.ReadFile(config1Path) | ||
| g.Expect(err).ToNot(HaveOccurred()) | ||
|
|
@@ -231,6 +239,14 @@ image: my-app:latest | |
| g.Expect(err).ToNot(HaveOccurred()) | ||
| g.Expect(config2Content).ToNot(BeEmpty()) | ||
|
|
||
| config3Content, err := os.ReadFile(config3Path) | ||
| g.Expect(err).ToNot(HaveOccurred()) | ||
| g.Expect(config3Content).ToNot(BeEmpty()) | ||
|
|
||
| config4Content, err := os.ReadFile(config4Path) | ||
| g.Expect(err).ToNot(HaveOccurred()) | ||
| g.Expect(config4Content).ToNot(BeEmpty()) | ||
|
|
||
| // Verify the merged YAML contains expected content | ||
| g.Expect(config1Content).To(MatchYAML(` | ||
| env: prod | ||
|
|
@@ -240,6 +256,14 @@ region: us-west-1 | |
| image: my-app:latest | ||
| replicas: 5 | ||
| version: 1.0.0 | ||
| `)) | ||
| g.Expect(config3Content).To(MatchYAML(` | ||
| image: my-app:latest | ||
| replicas: 10 | ||
| version: 1.0.0 | ||
| `)) | ||
| g.Expect(config4Content).To(MatchYAML(` | ||
| content: hello-world | ||
| `)) | ||
| }, | ||
| }, | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This also changes copies of a plain directory path, not just globs. from: "@git/overrides/" with strategy: Merge goes through applySingleDirectoryCopy → copyFileWithRoots → copyDirWithRoots, so it now merges too. Which means:
At least we should say in the docs that Merge applies recursively and that every colliding file must be single-document YAML/JSON.
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.
If someone has
Mergeset for a dir, after this change we'll corrupt their YAMLs. We are still in beta with the API, but still this is a major breaking change, not sure if a doc entry is acceptable. cc @matheuscscpUh oh!
There was an error while loading. Please reload this page.
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.
Thank you for looking into my PR!
Could you provide test cases where you think they should succeed and they don't with my changes applied?
It would help me a lot to verify that the changes I make don't go against the behaviour you expect from source-watcher.
Should we check for file endings to be
.yaml/.yml? And only merge those and copy the others?Only if they have multiple documents inside, I suppose.
If someone has
Mergeset for a dir,Mergecurrently does nothing, right? That's why I thought that this can't be the intended behaviour.We could also bump the API (
source.extensions.fluxcd.io/v1beta2?) and only apply the new behaviour when the version is v1beta2?Uh oh!
There was an error while loading. Please reload this page.
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 would skip merge using probes in this order:
.yaml/.ymlLog the reason for skipping.
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.
Yeah this is looking like a new strategy:
MergeAllThere 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.
or
MergeRecursivelyor something...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.
Where I'm coming from is that the glob pattern from your test (
@source2/**) matches all files in that folder recursively so it is most intuitive that it will take them one by one and merge them onto the ones in the source.If my PR would be a change that introduces a new strategy, the
Mergestrategy with its current behaviour is confusing, becauseyamlfiles in the root directory get merged but in the child directories they don't.The
...Recursivelypart of the suggested name for a new strategy is already expressed by the glob pattern (**). And...Allwould be just as confusing because it's only merging Yaml files anyway.Uh oh!
There was an error while loading. Please reload this page.
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.
Hmmm... Yeah.... A new strategy would make this very confusing indeed. Maybe we can ship this by bumping to v1beta2? Maybe the controller can check the apiVersion used by the object? Not sure if this is possible, but if it was then we could have different behaviors for v1beta1 and v1beta2 without a breaking change right now. We will remove v1beta1 one day, and that will obviously be a breaking change that we will accept. So if we can branch the code between v1beta1 and v1beta2 then we can ship this fix and make it opt-in for now.
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.
Agreed, the strategy is how a file in processed. Adding Recursively/All makes things very confusing, since the pattern dictates if the operation is recursive or not.