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

Prints all plugins when invoking sonobuoy results by default #909

Merged
merged 1 commit into from
Sep 27, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion cmd/sonobuoy/app/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"

"github.com/heptio/sonobuoy/pkg/client/results"
"github.com/heptio/sonobuoy/pkg/discovery"
"github.com/heptio/sonobuoy/pkg/errlog"
"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -66,7 +67,11 @@ func NewCmdResults() *cobra.Command {
},
Args: cobra.ExactArgs(1),
}
AddPluginFlag(&data.plugin, cmd.Flags())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, FYI, this was inappropriate to use here. The values --plugin -p were ok, but the description of the flags meaning was specific to the sonobuoy images command.


cmd.Flags().StringVarP(
&data.plugin, "plugin", "p", "",
"Which plugin to show results for. Defaults to printing them all.",
)
cmd.Flags().StringVarP(
&data.mode, "mode", "m", resultModeReport,
`Modifies the format of the output. Valid options are report, detailed, or dump.`,
Expand Down Expand Up @@ -100,13 +105,52 @@ func getReader(filepath string) (*results.Reader, func(), error) {
return r, func() { gzr.Close(); f.Close() }, nil
}

// result takes the resultsInput and tries to print the requested infromation from the archive.
// If there is an error printing any individual plugin, only the last error is printed and all plugins
// continue to be processed.
func result(input resultsInput) error {
r, cleanup, err := getReader(input.archive)
defer cleanup()
if err != nil {
return err
}

// Report on all plugins or the specified one.
plugins := []string{input.plugin}
if len(input.plugin) == 0 {
plugins, err = getPluginList(r)
if err != nil {
return errors.Wrapf(err, "unable to determine plugins to report on")
}
if len(plugins) == 0 {
return fmt.Errorf("no plugins specified by either the --plugin flag or tarball metadata")
}
}

var lastErr error
for i, plugin := range plugins {
input.plugin = plugin

// Load file with a new reader since we can't assume this reader has rewind
// capabilities.
r, cleanup, err := getReader(input.archive)
defer cleanup()

err = printSinglePlugin(input, r)
if err != nil {
lastErr = err
}

// Seperator line, but don't print a needless one at the end.
if i+1 < len(plugins) {
fmt.Println()
}
}

return lastErr
}

func printSinglePlugin(input resultsInput, r *results.Reader) error {
// If we want to dump the whole file, don't decode to an Item object first.
if input.mode == resultModeDump {
fReader, err := r.PluginResultsReader(input.plugin)
Expand Down Expand Up @@ -136,6 +180,15 @@ func result(input resultsInput) error {
}
}

func getPluginList(r *results.Reader) ([]string, error) {
runInfo := discovery.RunInfo{}
err := r.WalkFiles(func(path string, info os.FileInfo, err error) error {
return results.ExtractFileIntoStruct(r.RunInfoFile(), path, info, &runInfo)
})

return runInfo.LoadedPlugins, errors.Wrap(err, "finding plugin list")
}

func getItemInTree(i *results.Item, root string) *results.Item {
if i == nil {
return nil
Expand Down
7 changes: 5 additions & 2 deletions cmd/sonobuoy/app/results_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import (

func ExampleNewCmdResults() {
cmd := NewCmdResults()
cmd.SetArgs([]string{filepath.Join("testdata", "testResultsOutput.tar.gz")})
cmd.SetArgs([]string{
filepath.Join("testdata", "testResultsOutput.tar.gz"),
"--plugin=e2e",
})
cmd.Execute()
// Output:
// Plugin: e2e
Expand All @@ -39,7 +42,7 @@ func ExampleNewCmdResults_detailed() {
cmd := NewCmdResults()
cmd.SetArgs([]string{
filepath.Join("testdata", "testResultsOutput.tar.gz"),
"--mode", "detailed",
"--mode", "detailed", "--plugin=e2e",
})
cmd.Execute()
// Output:
Expand Down
11 changes: 11 additions & 0 deletions pkg/client/results/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ const (
defaultNodesFile = "Nodes.json"
defaultServerVersionFile = "serverversion.json"
defaultServerGroupsFile = "servergroups.json"

// InfoFile contains data not that isn't strictly in another location
// but still relevent to post-processing or understanding the run in some way.
InfoFile = "info.json"
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that a method is provided to return the info file path, does it need to be exported?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So you raise a good question which I definitley touched on when coding this: who is in charge of what information and what is the right way to grab it?

A few different packages hardcode these string values (results.json, errors.json, results/, etc), some of the values here are exported, some arent. Some have methods to return their values, some dont.

I'm going to make a new ticket specifically for fixing this up and clarifying where to find all the results structure (folders/names/etc) and how to use them.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#912

TIL: there is a quick 'Reference comment in new issue' button which will create a new issue with the comment body.

)

// Versions corresponding to Kubernetes minor version values. We used to
Expand Down Expand Up @@ -323,6 +327,13 @@ func ConfigFile(version string) string {
}
}

// RunInfoFile returns the path to the Sonobuoy RunInfo file which is extra metadata about the run.
// This was added in v0.16.1. The function will return the same string even for earlier
// versions where that file does not exist.
func (r *Reader) RunInfoFile() string {
return path.Join(metadataDir, InfoFile)
}

// PluginResultsItem returns the results file from the given plugin if found, error otherwise.
func (r *Reader) PluginResultsItem(plugin string) (*Item, error) {
resultObj := &Item{}
Expand Down
18 changes: 18 additions & 0 deletions pkg/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ const (
pluginDefinitionFilename = "defintion.json"
)

type RunInfo struct {
LoadedPlugins []string `json:"plugins,omitempty"`
}

// Run is the main entrypoint for discovery.
func Run(restConf *rest.Config, cfg *config.Config) (errCount int) {
// Adjust QPS/Burst so that the queries execute as quickly as possible.
Expand Down Expand Up @@ -130,6 +134,11 @@ func Run(restConf *rest.Config, cfg *config.Config) (errCount int) {
}
}

// runInfo is for dumping additional information to help enable processing of the resulting tarball.
runInfo := RunInfo{
LoadedPlugins: []string{},
}

// 4. Run the plugin aggregator
trackErrorsFor("running plugins")(
pluginaggregation.Run(kubeClient, cfg.LoadedPlugins, cfg.Aggregation, cfg.ProgressUpdatesPort, cfg.Namespace, outpath),
Expand Down Expand Up @@ -207,11 +216,20 @@ func Run(restConf *rest.Config, cfg *config.Config) (errCount int) {

// Saving plugin definitions in their respective folders for easy reference.
for _, p := range cfg.LoadedPlugins {
runInfo.LoadedPlugins = append(runInfo.LoadedPlugins, p.GetName())
trackErrorsFor("saving plugin info")(
dumpPlugin(p, outpath),
)
}

// Dump extra metadata that may be useful to postprocessors or analysis.
blob, err := json.Marshal(runInfo)
trackErrorsFor("marshalling run info")(err)
if err == nil {
err = ioutil.WriteFile(path.Join(metapath, results.InfoFile), blob, 0644)
trackErrorsFor("saving" + results.InfoFile)(err)
}

// 8. tarball up results YYYYMMDDHHMM_sonobuoy_UID.tar.gz
tb := cfg.ResultsDir + "/" + t.Format("200601021504") + "_sonobuoy_" + cfg.UUID + ".tar.gz"
err = tarx.Compress(tb, outpath, &tarx.CompressOptions{Compression: tarx.Gzip})
Expand Down