Skip to content
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

Allow the --plugin flag to specify a directory of plugins #911

Merged
merged 1 commit into from
Sep 27, 2019
Merged

Allow the --plugin flag to specify a directory of plugins #911

merged 1 commit into from
Sep 27, 2019

Conversation

johnSchnake
Copy link
Contributor

What this PR does / why we need it:
If someone specifies sonobuoy run|gen --plugin X then X ought to
be allowed to be either a single plugin file or a directory of plugins.

To avoid dropping errors intentionally or processing lots of unnecessary
files, when processing a directory, we only consider *.yaml files. We
also do not recurse deeper into the directory.

Which issue(s) this PR fixes
Fixes #906

Special notes for your reviewer:
This entire diff is almost just test updates. I can split it out so that it is more clear if you want.

I originally wasn't going to have tests for this since there are no tests for flags->GenConfig generation. However I decided that it should be covered and the test was almost doing that anyways.

However, I found a bug when making the test so I had to resolve that too (a one word change). Made comments throughout to help clarify.

Release note:

The --plugin flag (for specifying custom plugins on the command line) can now accept a directory name. If a directory is specified, all *.yaml files will be processed as plugins and loaded as if they had been specified individually.

@johnSchnake johnSchnake requested a review from zubron September 27, 2019 15:05
@@ -104,7 +104,7 @@ func (g *genFlags) Config() (*client.GenConfig, error) {

// the Enabled and Disabled modes of rbacmode don't need the client, so kubeclient can be nil.
// if kubeclient is needed, ErrRBACNoClient will be returned and that error can be reported back up.
rbacEnabled, err := genflags.rbacMode.Enabled(kubeclient)
rbacEnabled, err := g.rbacMode.Enabled(kubeclient)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tiny, mean bug that I found while coding these changes. It is referencing a global variable instead of the value it it was invoked on. This is why it happens to work for actual runs of Sonobuoy (since the global value gets used/set) but not in the test.

Very frustrating to find and another reason why we shouldn't be relying on them. One day we'll get around to fixing all the globals for these cmds...one day...

@@ -85,19 +91,31 @@ func TestResolveConformanceImage(t *testing.T) {
func TestResolveConfig(t *testing.T) {
defaultPluginSearchPath := config.New().PluginSearchPath
defaultAggr := plugin.AggregationConfig{TimeoutSeconds: 10800}
dynamicConfigFileName := "*determinedAtRuntime*"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this to hot-swap out the name since I write the config to a temp file but want the cmdline input to be specified explicitly.

}{
{
name: "NonDisruptiveConformance mode when supplied config is nil (nothing interesting happens)",
input: &genFlags{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test used to be a bit confusing since it could be given a genFlags object or it could be given cmdline input.

Now the test is a bit more consistent by always parsing cmdline input and relying on actual config files.

},
expectedGenConfigPlugins: &client.GenConfig{
StaticPlugins: []*manifest.Manifest{
{SonobuoyConfig: manifest.SonobuoyConfig{Driver: "Job", PluginName: "plugin1", SkipCleanup: false, ResultFormat: "raw"}, Spec: manifest.Container{Container: v1.Container{Name: "plugin", Image: "foo/bar:v1", Command: []string{"./run.sh"}, VolumeMounts: []v1.VolumeMount{{ReadOnly: false, Name: "results", MountPath: plugin.ResultsDir}}}}},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These static plugin lines are long but shouldn't really change. I just had to grab one and then a bit of copy/paste. Details arent too important here, the point is that the right set of plugins got loaded (really just need to look at name/image)

}

conf := tc.input.resolveConfig()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old test was using resolveConfig which generates the config.Config object. However, this isn't sufficient to see if the GenConfig would be appropriate so we were missing the ability to test large sections of input processing.

}

if conf.WorkerImage != tc.expected.WorkerImage {
t.Errorf("Expected worker image %v but got %v", tc.expected.WorkerImage, conf.WorkerImage)
if genConfig.Config.Aggregation.TimeoutSeconds != tc.expected.Aggregation.TimeoutSeconds {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we are generating the 'higher level' genConfig object, these checks just needed tweaked to look at the same value.

}

if !reflect.DeepEqual(conf.PluginSelections, tc.expected.PluginSelections) {
t.Errorf("expected PluginSelections %v but got %v", tc.expected.PluginSelections, conf.PluginSelections)
if diff := pretty.Compare(genConfig.StaticPlugins, tc.expectedGenConfigPlugins.StaticPlugins); diff != "" {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 2 checks here just for the static/dynamic plugins. Consistent with the existing test which is just checking for key bits of data.

If we wanted to change these tests to check the entire genconfig we should probably just serialize the values and use golden files since the objects are so big.

@@ -71,19 +74,53 @@ func (p *pluginList) Set(str string) error {
case pluginSystemdLogs:
p.DynamicPlugins = append(p.DynamicPlugins, str)
default:
b, err := ioutil.ReadFile(str)
finfo, err := os.Stat(str)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I have to stat to check if it is a directory or not, I had to have a new possible error message and so some tests needed updated for this reason as well. Tiny change but impacts a handful of tests.

}

// loadSinglePlugin loads a single plugin located at the given path.
func (p *pluginList) loadSinglePlugin(filepath string) error {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This entire section is just moving code around. The existing load plugin logic was moved here and then the load dir of plugins just gets a list of files and leverages this same method.

cliInput: "--sonobuoy-image=flagImage --config testdata/sonobuoy.conf",
name: "Flags shouldn't override the config settings unless set",
input: "--sonobuoy-image=flagImage --config " + dynamicConfigFileName,
configFileContents: `{"Namespace":"configNS","WorkerImage":"configImage","ImagePullPolicy":"Never","Server":{"timeoutseconds":500}}`,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sonobuoy.conf was used just for a few of these tests and since I already added the logic to make/use a temp one I just deleted the file and copied the contents to a few tests.

Much more flexible and now it is clear what the conf file is for each test instead of having to go look it up.

@johnSchnake
Copy link
Contributor Author

Test failing in CI but passing locally due to me having my KUBECONFIG set and pointed to a real cluster. Will update the tests.

@codecov-io
Copy link

codecov-io commented Sep 27, 2019

Codecov Report

❗ No coverage uploaded for pull request base (master@d9ca4ba). Click here to learn what that means.
The diff coverage is 75%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master     #911   +/-   ##
=========================================
  Coverage          ?   47.42%           
=========================================
  Files             ?       76           
  Lines             ?     5155           
  Branches          ?        0           
=========================================
  Hits              ?     2445           
  Misses            ?     2560           
  Partials          ?      150
Impacted Files Coverage Δ
cmd/sonobuoy/app/gen.go 73.72% <100%> (ø)
cmd/sonobuoy/app/pluginList.go 80.85% <73.91%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d9ca4ba...82f1d41. Read the comment docs.

Copy link
Contributor

@zubron zubron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @johnSchnake! All the extra comments were really helpful 👍

name: "Flags shouldn't override the config settings unless set",
input: &genFlags{},
cliInput: "--config testdata/sonobuoy.conf",
name: "Flags shouldn't override the config settings unless set",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was already like this, but this is a duplicate test name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its not clear to me what one of those is supposed to test; the name indicates resolving conflicts with the flag/config but doesnt actually give any flags other than the config. I'll have it check against some other field so it does something reasonable before merging (and update the name)

If someone specifies `sonobuoy run|gen --plugin X` then X ought to
be allowed to be either a single plugin file or a directory of plugins.

To avoid dropping errors intentionally or processing lots of unnecessary
files, when processing a directory, we only consider *.yaml files. We
also do not recurse deeper into the directory.

Fixes #906

Signed-off-by: John Schnake <[email protected]>
@johnSchnake johnSchnake merged commit 06f638e into vmware-tanzu:master Sep 27, 2019
@johnSchnake johnSchnake deleted the pluginsDir branch September 27, 2019 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Sonobuoy CLI should allow specifying a directory of plugins
3 participants