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

feat: adds support bundles #210

Merged
merged 1 commit into from
Mar 29, 2023
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
3 changes: 3 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ If applicable, add screenshots or logs to help explain your problem.

**Additional context**
Add any other context about the problem here.


_To help debug the issue as quickly as possible, we recommend generating a support bundle with `finch support-bundle-generate` and attaching it to this issue. This packages all Finch-related configs and logs into one file._
12 changes: 10 additions & 2 deletions cmd/finch/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import (
"io"
"os"

"github.com/runfinch/finch/pkg/disk"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/config"
"github.com/runfinch/finch/pkg/dependency"
"github.com/runfinch/finch/pkg/dependency/vmnet"
"github.com/runfinch/finch/pkg/disk"
"github.com/runfinch/finch/pkg/flog"
"github.com/runfinch/finch/pkg/fmemory"
"github.com/runfinch/finch/pkg/fssh"
"github.com/runfinch/finch/pkg/path"
"github.com/runfinch/finch/pkg/support"
"github.com/runfinch/finch/pkg/system"
"github.com/runfinch/finch/pkg/version"

Expand Down Expand Up @@ -88,13 +88,21 @@ var newApp = func(logger flog.Logger, fp path.Finch, fs afero.Fs, fc *config.Fin
fp.QEMUBinDir(),
system.NewStdLib(),
)
supportBundleBuilder := support.NewBundleBuilder(
logger,
fs,
support.NewBundleConfig(fp, system.NewStdLib().Env("HOME")),
fp,
ecc,
)

// append nerdctl commands
allCommands := initializeNerdctlCommands(lcc, logger, fs)
// append finch specific commands
allCommands = append(allCommands,
newVersionCommand(lcc, logger, stdOut),
virtualMachineCommands(logger, fp, lcc, ecc, fs, fc),
newSupportBundleCommand(logger, supportBundleBuilder, lcc),
)

rootCmd.AddCommand(allCommands...)
Expand Down
4 changes: 2 additions & 2 deletions cmd/finch/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ func TestNewApp(t *testing.T) {
assert.Equal(t, cmd.Version, version.Version)
assert.Equal(t, cmd.SilenceUsage, true)
assert.Equal(t, cmd.SilenceErrors, true)
// confirm the number of command, comprised of nerdctl commands + finch commands (version, vm)
assert.Equal(t, len(cmd.Commands()), len(nerdctlCmds)+2)
// confirm the number of command, comprised of nerdctl commands + finch commands (version, vm, support-bundle)
assert.Equal(t, len(cmd.Commands()), len(nerdctlCmds)+3)

// PersistentPreRunE should set logger level to debug if the debug flag exists.
mockCmd := &cobra.Command{}
Expand Down
104 changes: 104 additions & 0 deletions cmd/finch/support_bundle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package main

import (
"fmt"

"github.com/spf13/cobra"

"github.com/runfinch/finch/pkg/command"
"github.com/runfinch/finch/pkg/flog"
"github.com/runfinch/finch/pkg/lima"
"github.com/runfinch/finch/pkg/support"
)

func newSupportBundleCommand(logger flog.Logger, builder support.BundleBuilder, lcc command.LimaCmdCreator) *cobra.Command {
supportBundleCommand := &cobra.Command{
Use: "support-bundle",
Short: "Support bundle management",
}
supportBundleCommand.AddCommand(
newSupportBundleGenerateCommand(logger, builder, lcc),
)
return supportBundleCommand
}

func newSupportBundleGenerateCommand(logger flog.Logger, builder support.BundleBuilder, lcc command.LimaCmdCreator) *cobra.Command {
supportBundleGenerateCommand := &cobra.Command{
Use: "generate",
Args: cobra.NoArgs,
Short: "Generate support bundle",
Long: "Generates a collection of logs and configs that can be uploaded to a Github issue to help debug issues.",
RunE: newGenerateSupportBundleAction(logger, builder, lcc).runAdapter,
}

supportBundleGenerateCommand.Flags().StringArray("include", []string{},
"additional files to include in the support bundle, specified by absolute or relative path")
supportBundleGenerateCommand.Flags().StringArray("exclude", []string{},
ningziwen marked this conversation as resolved.
Show resolved Hide resolved
//nolint:lll // usage string
"files to exclude from the support bundle. if you specify a base name, all files matching that base name will be excluded. if you specify an absolute or relative path, only exact matches will be excluded")
return supportBundleGenerateCommand
}

type generateSupportBundleAction struct {
logger flog.Logger
builder support.BundleBuilder
lcc command.LimaCmdCreator
}

func newGenerateSupportBundleAction(
logger flog.Logger,
builder support.BundleBuilder,
lcc command.LimaCmdCreator,
) *generateSupportBundleAction {
return &generateSupportBundleAction{
logger: logger,
builder: builder,
lcc: lcc,
}
}

func (gsa *generateSupportBundleAction) runAdapter(cmd *cobra.Command, args []string) error {
additionalFiles, err := cmd.Flags().GetStringArray("include")
if err != nil {
return err
}
excludeFiles, err := cmd.Flags().GetStringArray("exclude")
if err != nil {
return err
}
return gsa.run(additionalFiles, excludeFiles)
}

func (gsa *generateSupportBundleAction) run(additionalFiles []string, excludeFiles []string) error {
err := gsa.assertVMExists()
if err != nil {
return err
}
gsa.logger.Info("Generating support bundle...")
bundleFile, err := gsa.builder.GenerateSupportBundle(additionalFiles, excludeFiles)
if err != nil {
return err
}
gsa.logger.Infof("Bundle created: %s", bundleFile)
gsa.logger.Info("Files posted on a Github issue can be read by anyone.")
gsa.logger.Info("Please ensure there is no sensitive information in the bundle before uploading.")
gsa.logger.Info("By default, this bundle contains basic logs and configs for Finch.")
return nil
}

func (gsa *generateSupportBundleAction) assertVMExists() error {
status, err := lima.GetVMStatus(gsa.lcc, gsa.logger, limaInstanceName)
if err != nil {
return err
}
switch status {
case lima.Nonexistent:
return fmt.Errorf("cannot create support bundle for nonexistent VM, run `finch %s init` to create a new instance",
virtualMachineRootCmd)
default:
return nil
}
}
Loading