-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Sam Berning <[email protected]>
- Loading branch information
1 parent
7aaa381
commit d2fb229
Showing
7 changed files
with
474 additions
and
2 deletions.
There are no files selected for viewing
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,87 @@ | ||
// 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: "Gathers logs and info into a bundle to help debug issues", | ||
} | ||
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", | ||
RunE: newGenerateSupportBundleAction(logger, builder, lcc).runAdapter, | ||
} | ||
|
||
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 (a *generateSupportBundleAction) runAdapter(cmd *cobra.Command, args []string) error { | ||
return a.run() | ||
} | ||
|
||
func (a *generateSupportBundleAction) run() error { | ||
err := a.assertVMExists() | ||
if err != nil { | ||
return err | ||
} | ||
a.logger.Info("Generating support bundle...") | ||
bundleFile, err := a.builder.GenerateSupportBundle() | ||
if err != nil { | ||
return err | ||
} | ||
a.logger.Infof("Bundle created: %s", bundleFile) | ||
return nil | ||
} | ||
|
||
func (a *generateSupportBundleAction) assertVMExists() error { | ||
status, err := lima.GetVMStatus(a.lcc, a.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 | ||
} | ||
} |
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,24 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNewSupportBundleCommand(t *testing.T) { | ||
t.Parallel() | ||
|
||
cmd := newSupportBundleCommand(nil, nil, nil) | ||
assert.Equal(t, cmd.Name(), "support-bundle") | ||
} | ||
|
||
func TestNewSupportBundleGenerateCommand(t *testing.T) { | ||
t.Parallel() | ||
|
||
cmd := newSupportBundleGenerateCommand(nil, nil, nil) | ||
assert.Equal(t, cmd.Name(), "generate") | ||
} |
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,100 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package support | ||
|
||
import ( | ||
"github.com/runfinch/finch/pkg/command" | ||
fpath "github.com/runfinch/finch/pkg/path" | ||
"github.com/runfinch/finch/pkg/version" | ||
"path" | ||
"strings" | ||
) | ||
|
||
type platformData struct { | ||
Os string `yaml:"os"` | ||
Arch string `yaml:"arch"` | ||
Finch string `yaml:"finch"` | ||
} | ||
|
||
// BundleConfig provides methods that configure what is included in a support bundle | ||
type BundleConfig struct { | ||
finch fpath.Finch | ||
homeDir string | ||
ecc command.Creator | ||
} | ||
|
||
// NewBundleConfig creates a new BundleConfig | ||
func NewBundleConfig(finch fpath.Finch, homeDir string, ecc command.Creator) BundleConfig { | ||
return BundleConfig{ | ||
finch: finch, | ||
homeDir: homeDir, | ||
ecc: ecc, | ||
} | ||
} | ||
|
||
func (c *BundleConfig) logFiles() []string { | ||
return []string{ | ||
path.Join(c.finch.LimaInstancePath(), "ha.stderr.log"), | ||
path.Join(c.finch.LimaInstancePath(), "ha.stdout.log"), | ||
path.Join(c.finch.LimaInstancePath(), "serial.log"), | ||
} | ||
} | ||
|
||
func (c *BundleConfig) configFiles() []string { | ||
return []string{ | ||
path.Join(c.finch.LimaInstancePath(), "lima.yaml"), | ||
c.finch.ConfigFilePath(c.homeDir), | ||
} | ||
} | ||
|
||
func (c *BundleConfig) platformData() (*platformData, error) { | ||
platform := &platformData{} | ||
|
||
// populate OS version | ||
os, err := c.getOSVersion() | ||
if err != nil { | ||
return nil, err | ||
} | ||
platform.Os = os | ||
|
||
// populate arch | ||
arch, err := c.getArch() | ||
if err != nil { | ||
return nil, err | ||
} | ||
platform.Arch = arch | ||
|
||
// populate Finch version | ||
platform.Finch = getFinchVersion() | ||
|
||
return platform, nil | ||
} | ||
|
||
func (c *BundleConfig) getOSVersion() (string, error) { | ||
cmd := c.ecc.Create("sw_vers", "-productVersion") | ||
out, err := cmd.Output() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
os := strings.TrimSuffix(string(out), "\n") | ||
|
||
return os, nil | ||
} | ||
|
||
func (c *BundleConfig) getArch() (string, error) { | ||
cmd := c.ecc.Create("uname", "-m") | ||
out, err := cmd.Output() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
arch := strings.TrimSuffix(string(out), "\n") | ||
|
||
return arch, nil | ||
} | ||
|
||
func getFinchVersion() string { | ||
return version.Version | ||
} |
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,135 @@ | ||
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// Package support provides functions and methods to produce Finch support bundles | ||
package support | ||
|
||
import ( | ||
"archive/zip" | ||
"fmt" | ||
"io" | ||
"path" | ||
"time" | ||
|
||
"github.com/runfinch/finch/pkg/flog" | ||
"github.com/spf13/afero" | ||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
const ( | ||
bundlePrefix = "finch-support" | ||
platformFileName = "platform.yaml" | ||
logPrefix = "logs" | ||
configPrefix = "configs" | ||
) | ||
|
||
// BundleBuilder provides methods to generate support bundles. | ||
type BundleBuilder struct { | ||
logger flog.Logger | ||
fs afero.Fs | ||
config BundleConfig | ||
} | ||
|
||
// NewBundleBuilder produces a new BundleBuilder. | ||
func NewBundleBuilder(logger flog.Logger, fs afero.Fs, config BundleConfig) *BundleBuilder { | ||
return &BundleBuilder{ | ||
logger: logger, | ||
fs: fs, | ||
config: config, | ||
} | ||
} | ||
|
||
// GenerateSupportBundle generates a new support bundle. | ||
func (b *BundleBuilder) GenerateSupportBundle() (string, error) { | ||
zipFileName := bundleFileName() | ||
b.logger.Debugf("Creating %s...", zipFileName) | ||
zipFile, err := b.fs.Create(zipFileName) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
writer := zip.NewWriter(zipFile) | ||
|
||
_, err = writer.Create(fmt.Sprintf("%s/", bundlePrefix)) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
platform, err := b.config.platformData() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
b.logger.Debugln("Gathering platform data...") | ||
err = b.writePlatformData(writer, platform) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
b.logger.Debugln("Copying in log files...") | ||
for _, file := range b.config.logFiles() { | ||
err := b.copyInFile(writer, file, logPrefix) | ||
if err != nil { | ||
return "", err | ||
} | ||
} | ||
|
||
b.logger.Debugln("Copying in config files...") | ||
for _, file := range b.config.configFiles() { | ||
err := b.copyInFile(writer, file, configPrefix) | ||
if err != nil { | ||
return "", err | ||
} | ||
} | ||
|
||
err = writer.Close() | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
return zipFileName, nil | ||
} | ||
|
||
func (b *BundleBuilder) writePlatformData(writer *zip.Writer, platform *platformData) error { | ||
platformFile, err := writer.Create(path.Join(bundlePrefix, platformFileName)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
toWrite, err := yaml.Marshal(&platform) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = platformFile.Write(toWrite) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (b *BundleBuilder) copyInFile(writer *zip.Writer, fileName string, prefix string) error { | ||
f, err := b.fs.Open(fileName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
baseName := path.Base(fileName) | ||
zipCopy, err := writer.Create(path.Join(bundlePrefix, prefix, baseName)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
_, err = io.Copy(zipCopy, f) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func bundleFileName() string { | ||
timestamp := time.Now().Format("20060102150405") | ||
return fmt.Sprintf("%s-%s.zip", bundlePrefix, timestamp) | ||
} |
Oops, something went wrong.