-
Notifications
You must be signed in to change notification settings - Fork 38.7k
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
Flexvolume dynamic plugin discovery: Prober unit tests and basic e2e test. #51474
Conversation
6b0f5f4
to
43f9872
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.
e2e test lgtm
pkg/volume/flexvolume/watcher.go
Outdated
@@ -0,0 +1,69 @@ | |||
/* | |||
Copyright 2017 The Kubernetes Authors. |
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.
Move this to util/filesystem?
pkg/volume/flexvolume/probe.go
Outdated
case err := <-prober.watcher.Errors: | ||
glog.Errorf("Received an error from watcher: %s", err) | ||
} | ||
prober.watcher.Init(func(event fsnotify.Event) { |
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.
Move this block to initWatcher?
pkg/volume/flexvolume/probe.go
Outdated
} | ||
|
||
// Creates a new filesystem watcher and adds watches for the plugin directory | ||
// and all of its subdirectories. | ||
func (prober *flexVolumeProber) initWatcher() error { | ||
var err error | ||
if prober.watcher, err = fsnotify.NewWatcher(); err != nil { | ||
return fmt.Errorf("Error creating new watcher: %s", err) | ||
if prober.watcher == 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.
Do we need the nil check? Is initWatcher called more than once?
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 mock watcher is injected by creating an instance of flexVolumeProber with watcher already assigned. The nil check is to make sure the mock is not overridden.
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.
Ideally code shouldn't know whether or not it's working with a mock, doing so breaks the abstraction.
Can we always assign the watcher to the flexVolumeProber before we get 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.
We can initialize the watcher in GetDynamicPluginProber() (the prober constructor, essentially), but it would have to handle the possibility of an error somehow. Returning the error from a constructor seems strange, and we shouldn't handle the error here. IMO it's better to call it in Init().
Or, it gets passed into the constructor as a dependency. I don't think the caller should worry about the details of underlying watcher implementation, especially when most of the time it's the default watcher anyway.
From the perspective of this code, it's doing a safety check to make sure watcher is always initialized. There isn't any code that depends on the watcher being a mock or 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.
It's fine to return an error from the constructor, IMO.
@@ -213,8 +209,8 @@ func (prober *flexVolumeProber) initWatcher() error { | |||
|
|||
// Creates the plugin directory, if it doesn't already exist. | |||
func (prober *flexVolumeProber) createPluginDir() error { | |||
if _, err := os.Stat(prober.pluginDir); os.IsNotExist(err) { | |||
err := os.MkdirAll(prober.pluginDir, 0755) | |||
if _, err := prober.fs.Stat(prober.pluginDir); os.IsNotExist(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.
Log a warning & event from here that Flex volume plugin directory is not present. This is not supposed to happen.
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.
@derekwaynecarr is this an appropriate place for an event or should they just log an error? IIRC events are really more appropriate for alerting on state changes, and it's probably better to just log an error here. Though I suppose you could consider "Recreating" a state change...
pkg/volume/flexvolume/probe_test.go
Outdated
"fmt" | ||
"github.com/fsnotify/fsnotify" | ||
"github.com/stretchr/testify/assert" | ||
utilfs "k8s.io/kubernetes/pkg/util/filesystem" |
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.
Fix package order
pkg/volume/flexvolume/probe_test.go
Outdated
} | ||
|
||
// Mock filesystem watcher | ||
type mockWatcher 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.
Move this to separate 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.
+1. I'd also rename it to fakeWatcher, which is more conventional in our codebase
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.
ACK
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.
Keeping the file inside Flexvolume directory since fakes may look different depending on test.
pkg/util/filesystem/fakefs.go
Outdated
@@ -21,6 +21,7 @@ import ( | |||
"time" | |||
|
|||
"github.com/spf13/afero" | |||
"path/filepath" |
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.
Fix package order
fixes #51570 |
061138e
to
9545c15
Compare
func (DefaultFs) ReadFile(filename string) ([]byte, error) { | ||
return ioutil.ReadFile(filename) | ||
} | ||
|
||
// TempFile via os.TempFile | ||
// TempFile via ioutil.TempFile |
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!
@@ -62,12 +63,12 @@ func (fs *fakeFs) Chtimes(name string, atime time.Time, mtime time.Time) error { | |||
return fs.a.Fs.Chtimes(name, atime, mtime) | |||
} | |||
|
|||
// ReadFile via afero.Fs.ReadFile | |||
// ReadFile via afero.ReadFile |
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!
func (fs *fakeFs) ReadFile(filename string) ([]byte, error) { | ||
return fs.a.ReadFile(filename) | ||
} | ||
|
||
// TempFile via afero.Fs.TempFile | ||
// TempFile via afero.TempFile |
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!
pkg/util/filesystem/watcher.go
Outdated
"github.com/fsnotify/fsnotify" | ||
) | ||
|
||
// A callback-based filesystem watcher abstraction for fsnotify. |
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.
Comment should look like "FSWatcher..."
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.
ACK
pkg/util/filesystem/watcher.go
Outdated
// Add a filesystem path to watch | ||
AddWatch(path string) error | ||
} | ||
type FSEventHandler func(event fsnotify.Event) |
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 add a godoc 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.
ACK
pkg/volume/flexvolume/probe_test.go
Outdated
func TestProberMultipleEvents(t *testing.T) { | ||
// Arrange | ||
_, fs, watcher, prober := initTestEnvironment(t) | ||
for i := 0; i < 5; i++ { |
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.
put the number of iterations in a variable so you can adjust more easily/calculate the number for your assertions w/o hardcoding
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.
ACK
pkg/volume/flexvolume/probe_test.go
Outdated
} | ||
|
||
// Mock filesystem watcher | ||
type mockWatcher 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.
+1. I'd also rename it to fakeWatcher, which is more conventional in our codebase
pkg/volume/flexvolume/probe_test.go
Outdated
} | ||
|
||
// Mock Flexvolume plugin | ||
type mockPluginFactory 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.
Rename this to fakePluginFactory and move to a separate file. We typically put the fakes in the same package as the real ones, but in a different 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.
ACK
@@ -170,7 +174,7 @@ var _ = SIGDescribe("Flexvolumes [Disruptive] [Feature:FlexVolume]", func() { | |||
driverInstallAs := driver + "-" + suffix | |||
|
|||
By(fmt.Sprintf("installing flexvolume %s on node %s as %s", path.Join(driverDir, driver), node.Name, driverInstallAs)) | |||
installFlex(&node, "k8s", driverInstallAs, path.Join(driverDir, driver)) | |||
installFlex(&node, "k8s", driverInstallAs, path.Join(driverDir, driver), true /* restart */) |
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.
Not sure I'm a fan of comments interleaved with code in the same line.
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 is mainly to clarify the parameter name, and is used in several places in the code base AFAIK.
driverInstallAs := driver + "-" + suffix | ||
|
||
By(fmt.Sprintf("installing flexvolume %s on node %s as %s", path.Join(driverDir, driver), node.Name, driverInstallAs)) | ||
installFlex(&node, "k8s", driverInstallAs, path.Join(driverDir, driver), false /* restart */) |
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.
Again not sure I like the interleaved comments. And this one should probably read "skip restart", in any case.
952439b
to
096f6c7
Compare
…olume prober 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.
One minor comment. Other than that looks good.
@@ -0,0 +1,53 @@ | |||
/* |
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.
Move this to util too?
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 decided to leave it in Flexvolume directory because fakes could be different depending on test.
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.
ACK
/lgtm |
/test pull-kubernetes-e2e-gce-etcd3 |
Thanks @verult. |
/approve |
1 similar comment
/approve |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: chakri-nelluri, saad-ali, thockin, verult Associated issue: 50031 The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Automatic merge from submit-queue (batch tested with PRs 51805, 51725, 50925, 51474, 51638) |
What this PR does / why we need it: Tests for changes introduced in PR #50031 .
As part of the prober unit test, I mocked filesystem, filesystem watch, and Flexvolume plugin initialization.
Moved the filesystem event goroutine to watcher implementation.
Which issue this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close that issue when PR gets merged): fixes #51147Special notes for your reviewer:
First commit contains added functionality of the mock filesystem.
Second commit is the refactor for moving mock filesystem into a common util directory.
Third commit is the unit and e2e tests.
Release note:
/release-note-none
/sig storage
/assign @saad-ali @liggitt
/cc @mtaufen @chakri-nelluri @wongma7