-
Notifications
You must be signed in to change notification settings - Fork 344
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add plugin flag for custom, local plugins
The user can now load custom plugin manifests into the YAML that Sonobuoy will run with the --plugin flag. For backwards compatibility, if no plugins are specified in this manner and instead a PluginSelection object is still specified, we will fallback to adding the necessary plugins. When loading plugins using the flag, they should specify either a filename which points to a plugin manifest or one of the sentinal values representing our internal plugins: e2e or systemd-logs. Plugins must be uniquely defined by the plugin name. Fixes #405 Signed-off-by: John Schnake <jschnake@vmware.com>
- Loading branch information
1 parent
1a72321
commit 1b56c31
Showing
28 changed files
with
2,147 additions
and
61 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
Copyright Sonobuoy Contributors 2019 | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package app | ||
|
||
import ( | ||
"io/ioutil" | ||
"strings" | ||
|
||
"github.com/heptio/sonobuoy/pkg/plugin/manifest" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/pflag" | ||
|
||
kuberuntime "k8s.io/apimachinery/pkg/runtime" | ||
) | ||
|
||
// pluginList represents a []manifest.Manifest objects describing plugins. | ||
type pluginList struct { | ||
// StaticPlugins are plugins which do not depend on other values and can be | ||
// written to YAML as-is. | ||
StaticPlugins []*manifest.Manifest | ||
|
||
// DynamicPlugins are ones which require all the other gen input in order to finalize. | ||
// E.g. the e2e plugin was templated to use all those other values. | ||
DynamicPlugins []string | ||
} | ||
|
||
const ( | ||
pluginE2E = "e2e" | ||
pluginSystemdLogs = "systemd-logs" | ||
) | ||
|
||
// Make sure pluginList implements Value properly | ||
var _ pflag.Value = &pluginList{} | ||
|
||
// String needed for pflag.Value | ||
func (p *pluginList) String() string { | ||
pluginNames := make( | ||
[]string, | ||
len(p.DynamicPlugins)+len(p.StaticPlugins), | ||
len(p.DynamicPlugins)+len(p.StaticPlugins), | ||
) | ||
for i := range p.StaticPlugins { | ||
pluginNames[i] = p.StaticPlugins[i].SonobuoyConfig.PluginName | ||
} | ||
pluginNames = append(pluginNames, p.DynamicPlugins...) | ||
return strings.Join(pluginNames, ",") | ||
} | ||
|
||
// Type needed for pflag.Value | ||
func (p *pluginList) Type() string { return "pluginList" } | ||
|
||
// Set sets the explicit path of the loader to the provided config file | ||
func (p *pluginList) Set(str string) error { | ||
switch str { | ||
case pluginE2E: | ||
p.DynamicPlugins = append(p.DynamicPlugins, str) | ||
case pluginSystemdLogs: | ||
p.DynamicPlugins = append(p.DynamicPlugins, str) | ||
default: | ||
b, err := ioutil.ReadFile(str) | ||
if err != nil { | ||
return errors.Wrapf(err, "unable to read file '%v'", str) | ||
} | ||
|
||
newPlugin, err := loadManifest(b) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to load plugin file '%v'", str) | ||
} | ||
|
||
p.StaticPlugins = append(p.StaticPlugins, newPlugin) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func loadManifest(bytes []byte) (*manifest.Manifest, error) { | ||
var def manifest.Manifest | ||
err := kuberuntime.DecodeInto(manifest.Decoder, bytes, &def) | ||
return &def, errors.Wrap(err, "couldn't decode yaml for plugin definition") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
Copyright the Sonobuoy contributors 2019 | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package app | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/heptio/sonobuoy/pkg/plugin/manifest" | ||
"github.com/kylelemons/godebug/pretty" | ||
) | ||
|
||
func TestSetPluginList(t *testing.T) { | ||
testCases := []struct { | ||
desc string | ||
list pluginList | ||
input string | ||
expect pluginList | ||
expectErr string | ||
}{ | ||
{ | ||
desc: "empty filename", | ||
expectErr: `unable to read file '': open : no such file or directory`, | ||
}, { | ||
desc: "file does not exist", | ||
input: "no-file", | ||
expectErr: `unable to read file 'no-file': open no-file: no such file or directory`, | ||
}, { | ||
desc: "bad manifest", | ||
input: "testdata/badmanifest.yaml", | ||
expectErr: `failed to load plugin file 'testdata/badmanifest.yaml': couldn't decode yaml for plugin definition: couldn't get version/kind; json parse error: json: cannot unmarshal string into Go value of type struct { APIVersion string "json:\"apiVersion,omitempty\""; Kind string "json:\"kind,omitempty\"" }`, | ||
}, { | ||
desc: "loading e2e", | ||
input: "e2e", | ||
list: pluginList{}, | ||
expect: pluginList{DynamicPlugins: []string{"e2e"}}, | ||
}, { | ||
desc: "loading systemd-logs", | ||
input: "systemd-logs", | ||
list: pluginList{}, | ||
expect: pluginList{DynamicPlugins: []string{"systemd-logs"}}, | ||
}, { | ||
desc: "loading from file", | ||
input: "testdata/goodmanifest.yaml", | ||
list: pluginList{}, | ||
expect: pluginList{StaticPlugins: []*manifest.Manifest{ | ||
&manifest.Manifest{SonobuoyConfig: manifest.SonobuoyConfig{PluginName: "test"}}, | ||
}}, | ||
}, { | ||
desc: "dynamic and static", | ||
input: "e2e", | ||
list: pluginList{StaticPlugins: []*manifest.Manifest{ | ||
&manifest.Manifest{SonobuoyConfig: manifest.SonobuoyConfig{PluginName: "test"}}, | ||
}}, | ||
expect: pluginList{ | ||
StaticPlugins: []*manifest.Manifest{ | ||
&manifest.Manifest{SonobuoyConfig: manifest.SonobuoyConfig{PluginName: "test"}}, | ||
}, | ||
DynamicPlugins: []string{"e2e"}, | ||
}, | ||
}, { | ||
desc: "multiple dynamic", | ||
input: "systemd-logs", | ||
list: pluginList{DynamicPlugins: []string{"e2e"}}, | ||
expect: pluginList{ | ||
DynamicPlugins: []string{"e2e", "systemd-logs"}, | ||
}, | ||
}, | ||
} | ||
for _, tc := range testCases { | ||
t.Run(tc.desc, func(t *testing.T) { | ||
err := tc.list.Set(tc.input) | ||
switch { | ||
case err != nil && len(tc.expectErr) == 0: | ||
t.Fatalf("Expected nil error but got %q", err) | ||
case err != nil && len(tc.expectErr) > 0: | ||
if fmt.Sprint(err) != tc.expectErr { | ||
t.Errorf("Expected error \n\t%q\nbut got\n\t%q", tc.expectErr, err) | ||
} | ||
return | ||
case err == nil && len(tc.expectErr) > 0: | ||
t.Fatalf("Expected error %q but got nil", tc.expectErr) | ||
default: | ||
// No error | ||
} | ||
|
||
if diff := pretty.Compare(tc.expect, tc.list); diff != "" { | ||
t.Fatalf("\n\n%s\n", diff) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
not a valid manifest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
sonobuoy-config: | ||
plugin-name: test |
Oops, something went wrong.