-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Fixes #5404: Skaffold configs downloaded from a url can define remote config dependencies #5405
Conversation
Codecov Report
@@ Coverage Diff @@
## master #5405 +/- ##
==========================================
- Coverage 71.57% 71.43% -0.15%
==========================================
Files 397 399 +2
Lines 14434 14516 +82
==========================================
+ Hits 10331 10369 +38
- Misses 3335 3380 +45
+ Partials 768 767 -1
Continue to review full report at Codecov.
|
cmd/skaffold/app/cmd/parse_config.go
Outdated
return nil, fmt.Errorf("skaffold config named %q found in multiple files: %q and %q", config.Metadata.Name, prevConfig, cfgOpts.file) | ||
prev, found := r.configNameToFile[config.Metadata.Name] | ||
if found { | ||
sl := strings.SplitN(prev, "@", 2) // map value is always formatted as `file_name@config_index` |
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 overloading of configNameToFile
seems error-prone (@
is a valid character in file names). It also seems unnecessary since it's entirely our code: we could just have the map take string
→ struct { name, index }
. But more to the point, we don't seem to use this index anywhere else, so couldn't this search-for-duplicates just use a local variable to maintain its state?
And maybe this search-for-duplicates should be done separately?
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.
don't know what I was doing here 🤦🏽♂️. Removed.
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.
We can't effectively maintain all info in a local variable since we also want to print out the file names that cause the conflict.
@@ -108,11 +108,18 @@ func getConfigs(cfgOpts configOpts, opts config.SkaffoldOptions, r *record) ([]* | |||
func processEachConfig(config *latest.SkaffoldConfig, cfgOpts configOpts, opts config.SkaffoldOptions, r *record, index int) ([]*latest.SkaffoldConfig, error) { |
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.
Would be helpful to describe what index
represents here. (And it's
→ its
)
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.
fixed typo; added description
cmd/skaffold/app/cmd/parse_config.go
Outdated
if prevConfig != cfgOpts.file { | ||
return nil, fmt.Errorf("skaffold config named %q found in multiple files: %q and %q", config.Metadata.Name, prevConfig, cfgOpts.file) | ||
} | ||
if prevIndex != fmt.Sprint(index) { | ||
return nil, fmt.Errorf("multiple skaffold configs named %q found in file %q", config.Metadata.Name, cfgOpts.file) | ||
} |
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.
Can duplicate references not be handled by ParseConfigAndUpgrade()
? So all we'd need is a set of seen config names?
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.
It can't exactly be inside ParseConfigAndUpgrade()
since that works with VersionedConfig
which doesn't have any method like GetName
. To make that change I'd have to modify every version of the skaffold config to satisfy that interface. But you're right in that I can do this check upfront. Moved.
cmd/skaffold/app/cmd/parse_config.go
Outdated
if !util.IsURL(path) { | ||
fi, err := os.Stat(path) | ||
if err != nil { | ||
if os.IsNotExist(errors.Unwrap(err)) { |
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.
The unwrap isn't correct: it's possible the ErrNoExist
is actually a wrapped error. See the example at
https://golang.org/pkg/os/#IsNotExist
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 is a weird one. It was existing code so I didn't mess around with it. It's calculating that the FileNotFound
error from ReadConfiguration
is wrapped exactly once in ParseConfig
. So it unwraps exactly once to get the underlying error. 🤦🏽♂️
I'll convert this to a concrete error type.
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.
The code for IsNotExist
notes:
New code should use
errors.Is(err, os.ErrNotExist)
errors.Is()
will unwrap the error sequentially.
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.
oh, got it. Fixed
return nil, fmt.Errorf("parsing dependencies for skaffold config %s: %w", cfgOpts.file, err) | ||
} | ||
if fi.IsDir() { | ||
path = filepath.Join(path, "skaffold.yaml") | ||
} | ||
cfgOpts.isDependency = cfgOpts.isDependency || path != cfgOpts.file |
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 line is a bit puzzling and warrants a comment as I'm not sure how this situation can arise.
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.
added
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.
What's previous and current? Oh! Is configOpts from the config that required d
as a dependency? That was not clear.
if test.err != "" { | ||
t.CheckDeepEqual(errors.New(strings.ReplaceAll(test.err, "WORK_DIR", wd)), err, cmp.Comparer(errorsComparer)) | ||
} else { | ||
t.CheckDeepEqual(test.expected, cfgs) | ||
} |
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.
Might be easier to have an duplicateError
type, and instead use a function to check the correctness of the error.
Better yet: create an error-code for this situation and test that error code. This should be reported upwards.
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 will make this change in fixing #5412
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.
The tests are failing as you're getting windows path separators. Maybe you need to replace /
→ \
too in the WORKDIR references.
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.
LGTM once the tests pass on Windows.
// validate that config names are unique if specified | ||
seen := make(map[string]bool) | ||
for _, cfg := range parsed { | ||
cfgName := cfg.(*latest.SkaffoldConfig).Metadata.Name |
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.
Maybe we should have a ConfigName()
method on VersionedConfig
?
return nil, fmt.Errorf("parsing dependencies for skaffold config %s: %w", cfgOpts.file, err) | ||
} | ||
if fi.IsDir() { | ||
path = filepath.Join(path, "skaffold.yaml") | ||
} | ||
cfgOpts.isDependency = cfgOpts.isDependency || path != cfgOpts.file |
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.
What's previous and current? Oh! Is configOpts from the config that required d
as a dependency? That was not clear.
if test.err != "" { | ||
t.CheckDeepEqual(errors.New(strings.ReplaceAll(test.err, "WORK_DIR", wd)), err, cmp.Comparer(errorsComparer)) | ||
} else { | ||
t.CheckDeepEqual(test.expected, cfgs) | ||
} |
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.
The tests are failing as you're getting windows path separators. Maybe you need to replace /
→ \
too in the WORKDIR references.
continue | ||
} | ||
if seen[cfgName] { | ||
return nil, fmt.Errorf("multiple skaffold configs named %q found in file %q", cfgName, cfgOpts.file) |
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.
Maybe seen
should be a map of name
→ file? Then you could include at least two of the file nams.
Fixes #5404
This PR makes two changes: