-
Notifications
You must be signed in to change notification settings - Fork 448
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
Use ErrorList for experiment validator #2329
Conversation
89084ec
to
5be749e
Compare
/retest |
This command should not work well. |
Also not sure why some test will fail randomly. They all runs well in my local. cc @tenzen-y |
That is a flaky test: #2269 |
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 doing this @ckcd!
I left a few comments.
for i, param := range parameters { | ||
|
||
if param.ParameterType != experimentsv1beta1.ParameterTypeInt && | ||
param.ParameterType != experimentsv1beta1.ParameterTypeDouble && | ||
param.ParameterType != experimentsv1beta1.ParameterTypeCategorical && | ||
param.ParameterType != experimentsv1beta1.ParameterTypeDiscrete && | ||
param.ParameterType != experimentsv1beta1.ParameterTypeUnknown { | ||
return fmt.Errorf("parameterType: %v is not supported in spec.parameters[%v]: %v", param.ParameterType, i, param) | ||
allErrs = append(allErrs, field.Invalid(parametersPath.Index(i).Child("parameterType"), | ||
param.ParameterType, fmt.Sprintf("parameterType: %v is not supported in spec.parameters[%v]: %v", param.ParameterType, i, param))) |
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.
Should we simplify the error message here (e.g. remove spec.parameters) like we did for other error messages:
allErrs = append(allErrs, field.Required(earlyStoppingPath.Child("algorithmName"), "must be specified")) |
fmt.Sprintf("feasibleSpace must be specified in spec.parameters[%v]: %v", i, param))) | ||
} else { | ||
if param.ParameterType == experimentsv1beta1.ParameterTypeDouble || param.ParameterType == experimentsv1beta1.ParameterTypeInt { | ||
if len(param.FeasibleSpace.List) > 0 { | ||
allErrs = append(allErrs, field.Invalid(parametersPath.Index(i).Child("feasibleSpace").Child("list"), | ||
param.FeasibleSpace.List, fmt.Sprintf("feasibleSpace.list is not supported for parameterType: %v in spec.parameters[%v]: %v", param.ParameterType, i, param))) | ||
} | ||
if param.FeasibleSpace.Max == "" && param.FeasibleSpace.Min == "" { | ||
allErrs = append(allErrs, field.Required(parametersPath.Index(i).Child("feasibleSpace").Child("max"), | ||
fmt.Sprintf("feasibleSpace.max or feasibleSpace.min must be specified for parameterType: %v in spec.parameters[%v]: %v", param.ParameterType, i, param))) |
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.
Same comments for error messages.
} | ||
|
||
// Check if trialSpec or configMap exists | ||
if trialTemplate.TrialSource.TrialSpec == nil && trialTemplate.TrialSource.ConfigMap == nil { | ||
return fmt.Errorf("spec.trialTemplate.trialSpec or spec.trialTemplate.configMap must be specified") | ||
return append(allErrs, field.Required(trialTemplatePath.Child("TrialSource"), "spec.trialTemplate.trialSpec or spec.trialTemplate.configMap must be specified")) |
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.
Same here
@andreyvelich Thanks for your reply! I have made the changes according to your opinion. PTAL again, thanks. |
} | ||
// Format | ||
fileFormat := mcSpec.Source.FileSystemPath.Format | ||
if fileFormat != commonapiv1beta1.TextFormat && fileFormat != commonapiv1beta1.JsonFormat { | ||
return fmt.Errorf("format of metrics file is required by .spec.metricsCollectorSpec.source.fileSystemPath.format") | ||
allErrs = append(allErrs, field.Required(metricsSourcePath.Child("fileSystemPath").Child("format"), | ||
"format of metrics file is required by .spec.metricsCollectorSpec.source.fileSystemPath.format")) |
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.
@ckcd How the error message will look like that we send to the users ?
Do we need to simplify it as follows:
format of metrics file is required for metrics collector
?
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.
@andreyvelich Yes the error message looks a little redundant:
[spec.metricsCollectorSpec.source.fileSystemPath.format: Required value: format of metrics file is required by .spec.metricsCollectorSpec.source.fileSystemPath.format]
I have made changes to remove redundant information according to your suggestion.
PTAL again, Thanks.
98633e5
to
0592e31
Compare
"directory path where tensorflow event files exist is required by .spec.metricsCollectorSpec.source.fileSystemPath.path")) | ||
} | ||
if mcSpec.Source.FileSystemPath.Format != "" { | ||
return fmt.Errorf(".spec.metricsCollectorSpec.source.fileSystemPath.format must be empty") | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("fileSystemPath").Child("format"), | ||
mcSpec.Source.FileSystemPath.Format, ".spec.metricsCollectorSpec.source.fileSystemPath.format must be empty")) | ||
} | ||
case commonapiv1beta1.PrometheusMetricCollector: | ||
i, err := strconv.Atoi(mcSpec.Source.HttpGet.Port.String()) | ||
if err != nil || i <= 0 { | ||
return fmt.Errorf(".spec.metricsCollectorSpec.source.httpGet.port must be a positive integer value for metrics collector kind: %v", mcKind) | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("httpGet").Child("port"), | ||
mcSpec.Source.HttpGet.Port.String(), fmt.Sprintf(".spec.metricsCollectorSpec.source.httpGet.port must be a positive integer value for metrics collector kind: %v", mcKind))) | ||
} | ||
if !strings.HasPrefix(mcSpec.Source.HttpGet.Path, "/") { | ||
return fmt.Errorf(".spec.metricsCollectorSpec.source.httpGet.path is invalid for metrics collector kind: %v", mcKind) | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("httpGet").Child("path"), | ||
mcSpec.Source.HttpGet.Path, fmt.Sprintf(".spec.metricsCollectorSpec.source.httpGet.path is invalid for metrics collector kind: %v", mcKind))) | ||
} | ||
case commonapiv1beta1.CustomCollector: | ||
if mcSpec.Collector.CustomCollector == nil { | ||
return fmt.Errorf(".spec.metricsCollectorSpec.collector.customCollector is required for metrics collector kind: %v", mcKind) | ||
allErrs = append(allErrs, field.Required(metricsCollectorPath.Child("collector").Child("customCollector"), | ||
fmt.Sprintf(".spec.metricsCollectorSpec.collector.customCollector is required for metrics collector kind: %v", mcKind))) | ||
} | ||
if mcSpec.Source.FileSystemPath != nil { | ||
if mcSpec.Source != nil && mcSpec.Source.FileSystemPath != nil { | ||
if !filepath.IsAbs(mcSpec.Source.FileSystemPath.Path) || (mcSpec.Source.FileSystemPath.Kind != commonapiv1beta1.DirectoryKind && | ||
mcSpec.Source.FileSystemPath.Kind != commonapiv1beta1.FileKind) { | ||
return fmt.Errorf(".spec.metricsCollectorSpec.source is invalid") | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("fileSystemPath"), | ||
"", ".spec.metricsCollectorSpec.source is invalid")) | ||
} | ||
} | ||
default: | ||
return fmt.Errorf("invalid metrics collector kind: %v", mcKind) | ||
allErrs = append(allErrs, field.Invalid(metricsCollectorPath.Child("collector").Child("kind"), | ||
mcKind, fmt.Sprintf("invalid metrics collector kind: %v", mcKind))) | ||
} | ||
if mcSpec.Source != nil && mcSpec.Source.Filter != nil && len(mcSpec.Source.Filter.MetricsFormat) > 0 { | ||
// the filter regular expression must have two top subexpressions, the first matched one will be taken as metric name, the second one as metric value | ||
mustTwoBracket, _ := regexp.Compile(`.*\(.*\).*\(.*\).*`) | ||
for _, mFormat := range mcSpec.Source.Filter.MetricsFormat { | ||
if _, err := regexp.Compile(mFormat); err != nil { | ||
return fmt.Errorf("invalid %q in .spec.metricsCollectorSpec.source.filter: %v", mFormat, err) | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("filter").Child("metricsFormat"), | ||
mFormat, fmt.Sprintf("invalid %q in .spec.metricsCollectorSpec.source.filter: %v", mFormat, err))) | ||
} else { | ||
if !mustTwoBracket.MatchString(mFormat) { | ||
return fmt.Errorf("invalid %q in .spec.metricsCollectorSpec.source.filter: two top subexpressions are required", mFormat) | ||
allErrs = append(allErrs, field.Invalid(metricsSourcePath.Child("filter").Child("metricsFormat"), | ||
mFormat, fmt.Sprintf("invalid %q in .spec.metricsCollectorSpec.source.filter: two top subexpressions are required", mFormat))) |
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.
Do you also want to refactor error messages for metricsCollectorSpec
given that we we pass the Child info in the 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.
E.g. the error message might look as follows:
[spec.metricsCollectorSpec.source.fileSystemPath.format: Required value: format of metrics file is required]
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.
@andreyvelich done, sorry for my delay.
Hi @ckcd, do you have some time to work on this PR so we can merge it ? |
0592e31
to
ddfcfd6
Compare
@andreyvelich Sorry for my delay, I have simplified all the
PTAL again. Thanks. |
Please rebase your PR @ckcd, it should fix the E2Es |
Signed-off-by: Kun Chang <curtis@mail.ustc.edu.cn>
ddfcfd6
to
7c19c45
Compare
@andreyvelich sure, I already rebase it. |
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.
Thanks for doing this @ckcd!
/lgtm
/assign @tenzen-y @johnugeorge
@tenzen-y @johnugeorge could you take a look at this? thanks. |
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 think, we should be ready to merge this.
Thank you for your contribution @ckcd 🎉
/lgtm
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: andreyvelich The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Signed-off-by: Kun Chang <curtis@mail.ustc.edu.cn>
Signed-off-by: Kun Chang <curtis@mail.ustc.edu.cn>
What this PR does / why we need it:
For experiment validator, return errors after all fields are verified.
Which issue(s) this PR fixes:
Fixes #2302
Checklist: