-
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
Introduced error constants and replaced reflect with cmp #2289
Introduced error constants and replaced reflect with cmp #2289
Conversation
25bea40
to
64c60db
Compare
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 reviewed only against experiments. So, could you refine other codes based on my comments?
ErrConfigMapNotFound = errors.New("ConfigMap not found") | ||
ErrConvertStringToUnstructuredFailed = errors.New("ConvertStringToUnstructured failed") | ||
ErrConvertUnstructuredToStringFailed = errors.New("ConvertUnstructuredToString failed") | ||
ErrParamNotFoundInParameterAssignment = errors.New("unable to find non-meta paramater from TrialParameters in ParameterAssignment") | ||
ErrParamNotFoundInTrialParameters = errors.New("unable to find parameter from ParameterAssignment in TrialParameters") | ||
ErrTemplatePathNotFound = errors.New("TemplatePath not found in ConfigMap") |
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.
ErrConfigMapNotFound = errors.New("ConfigMap not found") | |
ErrConvertStringToUnstructuredFailed = errors.New("ConvertStringToUnstructured failed") | |
ErrConvertUnstructuredToStringFailed = errors.New("ConvertUnstructuredToString failed") | |
ErrParamNotFoundInParameterAssignment = errors.New("unable to find non-meta paramater from TrialParameters in ParameterAssignment") | |
ErrParamNotFoundInTrialParameters = errors.New("unable to find parameter from ParameterAssignment in TrialParameters") | |
ErrTemplatePathNotFound = errors.New("TemplatePath not found in ConfigMap") | |
errConfigMapNotFound = errors.New("configMap not found") | |
errConvertStringToUnstructuredFailed = errors.New("failed to convert string to unstructured") | |
errConvertUnstructuredToStringFailed = errors.New("failed to convert unstructured to string") | |
errParamNotFoundInParameterAssignment = errors.New("unable to find non-meta parameter from TrialParameters in ParameterAssignment") | |
errParamNotFoundInTrialParameters = errors.New("unable to find parameter from ParameterAssignment in TrialParameters") | |
errTrialTemplateNotFound = errors.New("unable to find trial template in ConfigMap") |
It seems that these errors do not need to be exposed, right?
Also, should we make errors more explainable?
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 comment has been addressed in this commit.
@@ -245,18 +237,17 @@ spec: | |||
|
|||
expectedRunSpec, err := util.ConvertStringToUnstructured(expectedStr) | |||
if err != nil { |
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 err != nil { | |
if diff := cmp.Diff(errConvertStringToUnstructuredFailed, err, cmpopts.EquateErrors()); len(diff) != 0 { |
Should we evaluate if the error is appropriate?
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.
expectedRunSpec
is not evaluated using a function in generator.go
so I am not sure if the errors defined in generator.go
are applicable here.
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 see. So, could we use this error? https://github.com/kubernetes/apimachinery/blob/e696ec55a32e2177cd5f2fe1ded91d9485aa5c64/pkg/util/yaml/decoder.go#L255
If it is not working well, could you define a dedicated error as well?
func ConvertStringToUnstructured(in string) (*unstructured.Unstructured, 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.
I think we might need to define a dedicated error since the YAMLSyntaxError
struct's field err
cannot be exported and we therefore cannot initialize a YAMLSyntaxError
struct in generator_test.go
to define the expected 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.
I think it is better to move both errConvertStringToUnstructuredFailed
and errConvertUnstructuredToStringFailed
to katib/pkg/controller.v1beta1/util/unstructured.go.
Please let me know your thoughts.
P.S.: We can also define errConvertObjectToUnstructured
and use it in generator_test.go
.
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.
@tariq-hasan I was missing any context here. Sorry for your confusion.
I meant like this.
if diff := cmp.Diff(nil, err, cmpopts.EquateErrors()); len(diff) != 0 {
t.Errorf("ConvertStringToUnstructured failed (-want,+got):\n%s", diff)
}
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 addressed the comment in this commit.
@@ -245,18 +237,17 @@ spec: | |||
|
|||
expectedRunSpec, err := util.ConvertStringToUnstructured(expectedStr) | |||
if err != nil { | |||
t.Errorf("ConvertStringToUnstructured failed: %v", err) | |||
t.Errorf("%v: %v", ErrConvertStringToUnstructuredFailed, 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.
t.Errorf("%v: %v", ErrConvertStringToUnstructuredFailed, err) | |
t.Errorf("Unexpected error from ConvertStringToUnstructured (-want,+got):\n%s", diff) |
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 above comment applies here as well.
reflect.DeepEqual(expected.Labels, actual.Labels) && | ||
reflect.DeepEqual(expected.Annotations, actual.Annotations) && | ||
cmp.Equal(expected.Labels, actual.Labels) && | ||
cmp.Equal(expected.Annotations, actual.Annotations) && |
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 that these changes are not needed.
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 comment has been addressed in this commit.
@@ -578,8 +578,8 @@ func TestConvertTrialObservation(t *testing.T) { | |||
} | |||
for _, tc := range tcs { |
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.
for _, tc := range tcs { | |
for _, tc := range tcs { | |
t.Run(testDescription, func(T *t.testing){ |
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 comment has been addressed in this commit.
if !reflect.DeepEqual(actualObservation, tc.expectedObservation) { | ||
t.Errorf("Case: %v failed.\nExpected observation: %v \ngot: %v", tc.testDescription, tc.expectedObservation, actualObservation) | ||
if diff := cmp.Diff(actualObservation, tc.expectedObservation); diff != "" { | ||
t.Errorf("Case: %v failed. Diff (-want,+got):\n%s", tc.testDescription, diff) |
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.
t.Errorf("Case: %v failed. Diff (-want,+got):\n%s", tc.testDescription, diff) | |
t.Errorf("Unexpected observation (-want,+got):\n%s", diff) |
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 comment has been addressed in this commit.
@@ -311,7 +311,7 @@ func toGoptunaParams( | |||
} | |||
ir := float64(p) | |||
internalParams[name] = ir | |||
// externalParams[name] = p is prohibited because of reflect.DeepEqual() will be false | |||
// externalParams[name] = p is prohibited because of cmp.Diff() will not be empty |
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 could not follow this. Could you clarify?
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 comment has been addressed in this commit.
if reflect.DeepEqual(ktrial.Params, trials[i].Params) { | ||
if diff := cmp.Diff(ktrial.Params, trials[i].Params); diff == "" { |
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 change is not needed.
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 comment has been addressed in this commit.
@tariq-hasan You should follow this guide to pass DCO check. https://github.com/kubeflow/katib/pull/2289/checks?check_run_id=23472655010 |
4c6db3c
to
4b174b6
Compare
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 this update!
I left some comments.
@@ -86,7 +96,7 @@ func (g *DefaultGenerator) GetRunSpecWithHyperParameters(experiment *experiments | |||
// Convert Trial template to unstructured | |||
runSpec, err := util.ConvertStringToUnstructured(replacedTemplate) | |||
if err != nil { | |||
return nil, fmt.Errorf("ConvertStringToUnstructured failed: %v", err) | |||
return nil, fmt.Errorf("%w: %s", errConvertStringToUnstructuredFailed, err.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.
return nil, fmt.Errorf("%w: %s", errConvertStringToUnstructuredFailed, err.Error()) | |
return nil, fmt.Errorf("%w: %w", errConvertStringToUnstructuredFailed, err) |
Could you just wrap errors?
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 has been fixed in this commit.
@@ -108,7 +118,7 @@ func (g *DefaultGenerator) applyParameters(experiment *experimentsv1beta1.Experi | |||
if trialSpec == nil { | |||
trialSpec, err = util.ConvertStringToUnstructured(trialTemplate) | |||
if err != nil { | |||
return "", fmt.Errorf("ConvertStringToUnstructured failed: %v", err) | |||
return "", fmt.Errorf("%w: %s", errConvertStringToUnstructuredFailed, err.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.
return "", fmt.Errorf("%w: %s", errConvertStringToUnstructuredFailed, err.Error()) | |
return "", fmt.Errorf("%w: %w", errConvertStringToUnstructuredFailed, 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.
Same as above.
@@ -194,20 +205,20 @@ func (g *DefaultGenerator) GetTrialTemplate(instance *experimentsv1beta1.Experim | |||
if trialSource.TrialSpec != nil { | |||
trialTemplateString, err = util.ConvertUnstructuredToString(trialSource.TrialSpec) | |||
if err != nil { | |||
return "", fmt.Errorf("ConvertUnstructuredToString failed: %v", err) | |||
return "", fmt.Errorf("%w: %s", errConvertUnstructuredToStringFailed, err.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.
return "", fmt.Errorf("%w: %s", errConvertUnstructuredToStringFailed, err.Error()) | |
return "", fmt.Errorf("%w: %w", errConvertUnstructuredToStringFailed, 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.
Same as above.
} | ||
} else { | ||
configMapNS := trialSource.ConfigMap.ConfigMapNamespace | ||
configMapName := trialSource.ConfigMap.ConfigMapName | ||
templatePath := trialSource.ConfigMap.TemplatePath | ||
configMap, err := g.client.GetConfigMap(configMapName, configMapNS) | ||
if err != nil { | ||
return "", fmt.Errorf("GetConfigMap failed: %v", err) | ||
return "", fmt.Errorf("%w: %v", errConfigMapNotFound, 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.
return "", fmt.Errorf("%w: %v", errConfigMapNotFound, err) | |
return "", fmt.Errorf("%w: %w", errConfigMapNotFound, 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.
Same as above.
@@ -245,18 +237,17 @@ spec: | |||
|
|||
expectedRunSpec, err := util.ConvertStringToUnstructured(expectedStr) | |||
if err != nil { |
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 see. So, could we use this error? https://github.com/kubernetes/apimachinery/blob/e696ec55a32e2177cd5f2fe1ded91d9485aa5c64/pkg/util/yaml/decoder.go#L255
If it is not working well, could you define a dedicated error as well?
func ConvertStringToUnstructured(in string) (*unstructured.Unstructured, error) { |
} | ||
} | ||
if err == nil && !equality.Semantic.DeepEqual(tc.Pod.Spec.Containers, tc.WantPod.Spec.Containers) { |
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.
Could you apply the cmp approach here as well?
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 as above.
if err == nil && !equality.Semantic.DeepEqual(tc.Pod, tc.WantPod) { | ||
t.Errorf("Unexpected error from mutateMetricsCollectorVolume, expected pod: %v, got: %v", tc.WantPod, tc.Pod) |
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.
Could you apply the cmp approach here as well?
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 as above.
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
for _, tc := range cases { | ||
collectorKind := getSidecarContainerName(tc.CollectorKind) |
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.
collectorKind := getSidecarContainerName(tc.CollectorKind) | |
t.Run(... | |
collectorKind := getSidecarContainerName(tc.CollectorKind) |
Could we use the t.Run
?
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 as above.
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
for name, tc := range cases { | ||
isPrimary := isPrimaryPod(tc.podLabels, tc.primaryPodLabels) |
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.
isPrimary := isPrimaryPod(tc.podLabels, tc.primaryPodLabels) | |
t.Run(... | |
isPrimary := isPrimaryPod(tc.podLabels, tc.primaryPodLabels) |
Could we use the t.Run
?
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 as above.
}, | ||
} | ||
|
||
for _, tc := range testCases { | ||
for _, tc := range cases { | ||
mutatePodMetadata(tc.pod, tc.trial) |
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.
mutatePodMetadata(tc.pod, tc.trial) | |
t.Run(... | |
mutatePodMetadata(tc.pod, tc.trial) |
ditto.
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 as above.
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.
@tariq-hasan Thank you for this update!
Otherwise lgtm.
I left a comment for one suggestion.
@@ -245,18 +237,17 @@ spec: | |||
|
|||
expectedRunSpec, err := util.ConvertStringToUnstructured(expectedStr) | |||
if err != nil { |
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.
@tariq-hasan I was missing any context here. Sorry for your confusion.
I meant like this.
if diff := cmp.Diff(nil, err, cmpopts.EquateErrors()); len(diff) != 0 {
t.Errorf("ConvertStringToUnstructured failed (-want,+got):\n%s", diff)
}
Instance *experimentsv1beta1.Experiment | ||
ParameterAssignments []commonapiv1beta1.ParameterAssignment |
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.
Instance *experimentsv1beta1.Experiment | |
ParameterAssignments []commonapiv1beta1.ParameterAssignment | |
instance *experimentsv1beta1.Experiment | |
parameterAssignments []commonapiv1beta1.ParameterAssignment |
I found these fields are exported. We should not export test fields at all points.
But this is irrelevant to this PR. So, could you open dedicated PR so that we can avoid to export test fields.
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 can open a separate PR once this one is merged.
@tariq-hasan LGTM, but the latest commit seems to violate DCO. |
e8afe14
to
ce09054
Compare
I addressed the issue. I am wondering if I should squash the commits given that the changes are final now. |
The prow automatically squash commits into one. So, I'm ok with either way. |
Makes sense. After reviewing the PR I find that these are the final set of changes
I was thinking if each of these should ideally be its own commit so that we maintain a clear separation of concerns. |
I think that those sets depend on each. So, those should be included in a single PR. Note that: We have no way to select the merge method merge. The prow enforces the squash method. |
Makes sense. |
@tariq-hasan Could you address this error: https://github.com/kubeflow/katib/actions/runs/8700291109/job/23861062475?pr=2289? |
I guess that we could avoid those errors after you rebase this PR. |
Okay. I thought that these might have been flakiness issues as the CI workflow seems to pass and fail quite unpredictably for this test case. I am rebasing the PR. |
ce09054
to
6d33aa5
Compare
No, actually these errors were brought to us by the kubernetes issue w/o supporting SSA for the fake client. |
Got it. |
@tariq-hasan Uhm, it seems that meaningful errors occur. Could you investigate them? |
I am working through them now. |
Thank you! |
I did run into the issues here before. The errors are not always reproducible however. I usually get these errors in the first one to three runs of If I remove the That said I now restarted my local and I am running In the few cases where I ran into the errors I did root-cause that the errors were due to the order of execution of this code with the order of execution for this code. Not sure if you have any thoughts of what might be happening here. |
6d33aa5
to
87a6abc
Compare
Hi @andreyvelich I will try to complete it ASAP. Sorry about the delay. |
2480ef5
to
a578685
Compare
I rebased the PR. I am now working on fixing the error in As a side note, I had to revert the change in
|
fa2cfa2
to
4e1acc7
Compare
I added this commit to tie up each mock method call with the execution of the associated test case. Please let me know if you have any feedback and if this would fix the issue. |
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.
Basically, lgtm
Thank you for doing this!
err bool | ||
testDescription string | ||
cases := map[string]struct { | ||
prepareConfigMap func() |
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.
prepareConfigMap func() | |
mockConfigMapGetter *gomock.Call |
Could you use a more strict 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.
Done.
prepareConfigMap: func() { | ||
c.EXPECT().GetConfigMap(gomock.Any(), gomock.Any()).Return( | ||
map[string]string{templatePath: trialSpec}, nil) | ||
}, |
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.
prepareConfigMap: func() { | |
c.EXPECT().GetConfigMap(gomock.Any(), gomock.Any()).Return( | |
map[string]string{templatePath: trialSpec}, nil) | |
}, | |
mockConfigMapGetter: c.EXPECT().GetConfigMap(gomock.Any(), gomock.Any()).Return( | |
map[string]string{templatePath: trialSpec}, nil) |
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.
Done.
prepareConfigMap: func() { | ||
c.EXPECT().GetConfigMap(gomock.Any(), gomock.Any()).Return( | ||
map[string]string{templatePath: trialSpec}, nil) | ||
}, |
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.
TBH, I think that we should use the client-go fake client instead of go mock.
But, that is another problem. So, could you open an issue to replace go mock with fake client-go?
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.
Done. Ref: #2408
0c34001
to
c8b7f49
Compare
@tariq-hasan Thank you for the updates. |
c8b7f49
to
f058446
Compare
Signed-off-by: tariq-hasan <[email protected]>
Signed-off-by: tariq-hasan <[email protected]>
f058446
to
0cd9b85
Compare
I addressed the error by retaining the strict type checking while wrapping the mock method call within a function to ensure that the ordering of the mock method calls aligns with the test execution cases. |
/rerun-all |
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 the update!
This was not a trivial task, great contributions!
/lgtm
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: tenzen-y 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 |
Thank you for kindly helping with the PR. |
What this PR does / why we need it:
Following the suggestion #2281 (review) from @tenzen-y this code change provides a more thorough comparison of errors through the introduction of error constants and the replacement of
replace.DeepEqual
withcmp.Diff
.In addition some of the test cases in
generator_test.go
have been revised to allow for a more thorough comparison of error messages.Finally cosmetic changes have been applied to some of the tests in order to match the style of the code in config_test.go that compares error constants.
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #2268
Checklist: