-
Notifications
You must be signed in to change notification settings - Fork 231
Unit test: Verify hc feature-gate disable after enable scenario #299
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
Unit test: Verify hc feature-gate disable after enable scenario #299
Conversation
pkg/operator/operator_test.go
Outdated
| }, | ||
| }, | ||
| expectedMachineHealthCheckController: true, | ||
| }, { |
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.
How does this verify the feature is disable after it's enabled? The operator is initialized from scratch for every test case.
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.
indeed, this is duplicating the tc https://github.com/openshift/machine-api-operator/pull/299/files#diff-d5d9cf6e8104e5231787b5cc89fb7b52R198
michaelgugino
left a comment
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
|
/lgtm cancel |
fe3595f to
b75620e
Compare
b75620e to
8b75de8
Compare
pkg/operator/operator.go
Outdated
| }, nil | ||
| } | ||
|
|
||
| func (optr *Operator) getImages() (string, string, 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.
No need to implement and mock getImages(). You can create Configv1.Infrastructure object and have the fake client return it.
| } | ||
| ensureContainer(modified, existingCurr, required) | ||
| } | ||
| var requiredContainers []corev1.Container |
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.
How is this change related to the unit tests?
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.
pkg/operator/operator.go
Outdated
| syncHandler func(ic string) error | ||
| syncHandler func(ic string) error | ||
| imageGetterFunc imageGetterFuncType | ||
| statusProgressingFunc func() 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.
No need to mock optr.statusProgressing given you can have fake clients return expected objects. Please, give fake client osconfigv1.ClusterOperator object with pre-populated testing values.
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.
Implemented here: #304
8b75de8 to
3bc2f43
Compare
|
@vikaschoudhary16 needs rebase |
3bc2f43 to
a56b76f
Compare
a56b76f to
0ad7f34
Compare
0ad7f34 to
dd00275
Compare
|
/test e2e-aws |
pkg/operator/operator_test.go
Outdated
| Status: v1.InfrastructureStatus{ | ||
| Platform: v1.AWSPlatformType, | ||
| }, | ||
| err := initFeatureGateInformer([]runtime.Object{tc.featureGate}, optr) |
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 still wrong. All tests in the list (tests) are supposed to assume clean/vanilla environment. Initializing fg informer only once leaves previous fg object in the cache. Which might (or might not) influence result of each test in the last. If you want to assume dependency between fg objects, you need to create separate unit test for it.
dd00275 to
5bc06f5
Compare
pkg/operator/operator_test.go
Outdated
| stopCh := make(<-chan struct{}) | ||
| optr := newFakeOperator(nil, []runtime.Object{infra}, stopCh) | ||
|
|
||
| for _, tc := range tests { |
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.
Given the unit test will always have two steps (first enable fg, then disable fg), there is no need to iterate through both tests. It's sufficient to initialize newFakeOperator as it was before, remove initFeatureGateInformer and just call optr.sync two times. After the first call validating the fg is enable, after the second call validating it is not.
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.
remove initFeatureGateInformer
This is not possible because modifying the FeatureGate object which is passed to the fake clientset, will not work. Eventually it makes a copy of the object and therefor any changes to the object will not be reflected back in the object returned by informer in response to the listing operation.
Updated the PR to address other parts. PTAL!
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.
diff --git a/pkg/operator/operator_test.go b/pkg/operator/operator_test.go
index 289f4c9..24c6688 100644
--- a/pkg/operator/operator_test.go
+++ b/pkg/operator/operator_test.go
@@ -15,7 +15,6 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/informers"
fakekube "k8s.io/client-go/kubernetes/fake"
- "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue"
@@ -261,10 +260,11 @@ func TestEnableDisableOperatorSyncClusterAPIControllerHealthCheckController(t *t
Platform: v1.AWSPlatformType,
},
}
- hcFeatureGate := newFeatureGate(v1.TechPreviewNoUpgrade)
stopCh := make(chan struct{})
- optr := newFakeOperator(nil, []runtime.Object{hcFeatureGate, infra}, stopCh)
- optr.sync("test-key")
+ defer close(stopCh)
+
+ optr := newFakeOperator(nil, []runtime.Object{newFeatureGate(v1.TechPreviewNoUpgrade), infra}, stopCh)
+ go optr.Run(2, stopCh)
if err := wait.PollImmediate(1*time.Second, 5*time.Second, func() (bool, error) {
d, err := optr.deployLister.Deployments(targetNamespace).Get(deploymentName)
@@ -272,28 +272,33 @@ func TestEnableDisableOperatorSyncClusterAPIControllerHealthCheckController(t *t
t.Logf("Failed to get %q deployment: %v", deploymentName, err)
return false, nil
}
- if deploymentHasContainer(d, hcControllerName) != true {
+ if !deploymentHasContainer(d, hcControllerName) {
t.Logf("Expected deploymentHasContainer for %q container to be true", hcControllerName)
return false, nil
}
return true, nil
}); err != nil {
- t.Errorf("Failed to verify %q deployment", deploymentName)
+ t.Fatalf("Failed to verify %q deployment", deploymentName)
}
- close(stopCh)
- err := initFeatureGateInformer([]runtime.Object{newFeatureGate(v1.Default)}, optr)
+
+ t.Logf("Found %q container in %q deployment", hcControllerName, deploymentName)
+
+ hcFeatureGate, err := optr.osClient.ConfigV1().FeatureGates().Get(MachineAPIFeatureGateName, metav1.GetOptions{})
if err != nil {
- t.Errorf("Failed to set featuregate 'Default' : %v", err)
+ t.Fatalf("Unable to get %q feature gate: %v", MachineAPIFeatureGateName, err)
+ }
+ hcFeatureGate.Spec.FeatureSet = v1.Default
+ if _, err := optr.osClient.ConfigV1().FeatureGates().Update(hcFeatureGate); err != nil {
+ t.Fatalf("Unable to update %q feature gate and set default feature set: %v", MachineAPIFeatureGateName, err)
}
- optr.sync("test-key")
- if err := wait.PollImmediate(1*time.Second, 5*time.Second, func() (bool, error) {
+ if err := wait.PollImmediate(1*time.Second, 15*time.Second, func() (bool, error) {
d, err := optr.deployLister.Deployments(targetNamespace).Get(deploymentName)
if err != nil {
t.Logf("Failed to get %q deployment: %v", deploymentName, err)
return false, nil
}
- if deploymentHasContainer(d, hcControllerName) != false {
+ if deploymentHasContainer(d, hcControllerName) {
t.Logf("Expected deploymentHasContainer for %q container to be false", hcControllerName)
return false, nil
}
@@ -303,16 +308,3 @@ func TestEnableDisableOperatorSyncClusterAPIControllerHealthCheckController(t *t
}
}
-
-func initFeatureGateInformer(featureGate []runtime.Object, op *Operator) error {
- configClient := fakeos.NewSimpleClientset(featureGate...)
- configSharedInformer := configinformersv1.NewSharedInformerFactoryWithOptions(configClient, 2*time.Minute)
- featureGateInformer := configSharedInformer.Config().V1().FeatureGates()
- op.featureGateLister = featureGateInformer.Lister()
- stopCh := make(<-chan struct{})
- configSharedInformer.Start(stopCh)
- if !cache.WaitForCacheSync(stopCh, featureGateInformer.Informer().HasSynced) {
- return fmt.Errorf("unable to wait for cache to sync")
- }
- return 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.
@vikaschoudhary16 also please improve the messages to be more human readable
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.
updated, thanks!
pkg/operator/operator_test.go
Outdated
| optr := newFakeOperator(nil, []runtime.Object{infra}, stopCh) | ||
| err := initFeatureGateInformer([]runtime.Object{tc.featureGate}, optr) | ||
| if err != nil { | ||
| t.Errorf("Failed to set featuregate %v : %v", tc.featureGate, 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.
Isn't this fatal?
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.
with Errorf this test will be reported failed but others will be executed. Is not that we want?
5bc06f5 to
02ef72f
Compare
pkg/operator/operator_test.go
Outdated
|
|
||
| configSharedInformer.Start(stopCh) | ||
| kubeNamespacedSharedInformer.Start(stopCh) | ||
| kubeInformerstopCh := make(<-chan struct{}) |
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.
Why do we need this separate channel? Shouldn't the following line use stopCh?
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.
Agree, please undo the change.
pkg/operator/operator_test.go
Outdated
| } | ||
|
|
||
| func newFakeOperator(kubeObjects []runtime.Object, osObjects []runtime.Object, stopCh <-chan struct{}) *Operator { | ||
| func newFakeOperator(kubeObjects []runtime.Object, osObjects []runtime.Object, stopCh chan struct{}) *Operator { |
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.
No need for s/<-chan/chan/.
02ef72f to
970bc97
Compare
pkg/operator/operator_test.go
Outdated
|
|
||
| configSharedInformer.Start(stopCh) | ||
| kubeNamespacedSharedInformer.Start(stopCh) | ||
| kubeInformerstopCh := make(<-chan struct{}) |
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.
Agree, please undo the change.
pkg/operator/operator_test.go
Outdated
| } | ||
|
|
||
| stopCh := make(<-chan struct{}) | ||
| stopCh := make(chan struct{}) |
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.
Please undo
pkg/operator/operator_test.go
Outdated
| } | ||
|
|
||
| stopCh := make(<-chan struct{}) | ||
| stopCh := make(chan struct{}) |
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.
Please undo
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.
why should not the stop channel be closed?
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.
undo = s/<-//. Channel only for reading is all that is needed.
pkg/operator/operator_test.go
Outdated
| return false, nil | ||
| } | ||
| if !deploymentHasContainer(d, hcControllerName) { | ||
| t.Logf("Expected deploymentHasContainer for %q container to be true", hcControllerName) |
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.
Expected to found no %q container in %q deployment, got one.
pkg/operator/operator_test.go
Outdated
| } | ||
| return true, nil | ||
| }); err != nil { | ||
| t.Fatalf("Failed to verify %q deployment", deploymentName) |
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.
"Failed to verify %q deployment has %q container"
pkg/operator/operator_test.go
Outdated
| return false, nil | ||
| } | ||
| if deploymentHasContainer(d, hcControllerName) { | ||
| t.Logf("Expected deploymentHasContainer for %q container to be false", hcControllerName) |
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.
Expected to found %q container in %q deployment, found none.
pkg/operator/operator_test.go
Outdated
| } | ||
| return true, nil | ||
| }); err != nil { | ||
| t.Errorf("Failed to verify %q deployment", deploymentName) |
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.
"Failed to verify %q deployment has no %q container"
be7e3a7 to
5d14dd1
Compare
pkg/operator/operator_test.go
Outdated
| } | ||
|
|
||
| func newFakeOperator(kubeObjects []runtime.Object, osObjects []runtime.Object, stopCh <-chan struct{}) *Operator { | ||
| func newFakeOperator(kubeObjects []runtime.Object, osObjects []runtime.Object, stopCh <-chan struct{}, wq string) *Operator { |
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 is wq?
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 this is the way to fix the flake, please open another PR for it. This is irrelevant for this PR.
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.
will it be ok if i create a new commit for this flake fix. Actually with the changes in this PR, this flake has become almost 100% reproducible and thus will be difficult to merge this PR without this fix.
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.
How can different name for a working queue be a fix for the flake?
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.
How does the name, or a different name, fix the flake?
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.
Still, it's unrelated to this PR. Please, open another one.
5d14dd1 to
d45cf1b
Compare
|
@vikaschoudhary16: The following test failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
|
/test e2e-aws-operator |
|
/approve |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: ingvagabund The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
This unit test verifies that if hc feature-gate is disabled after enabling it, hc-controller gets removed.