-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(telemetry): add telemetry command
- Loading branch information
1 parent
85c23e1
commit 3420dad
Showing
10 changed files
with
285 additions
and
3 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
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,3 @@ | ||
// Package telemetry contains a command to control what telemetry data is | ||
// recorded. | ||
package telemetry |
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,96 @@ | ||
package telemetry | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
|
||
"github.com/fastly/cli/pkg/cmd" | ||
"github.com/fastly/cli/pkg/config" | ||
fsterr "github.com/fastly/cli/pkg/errors" | ||
"github.com/fastly/cli/pkg/global" | ||
"github.com/fastly/cli/pkg/text" | ||
) | ||
|
||
// RootCommand is the parent command for all subcommands in this package. | ||
// It should be installed under the primary root command. | ||
type RootCommand struct { | ||
cmd.Base | ||
|
||
disable bool | ||
disableBuild bool | ||
disableMachine bool | ||
disablePackage bool | ||
enable bool | ||
enableBuild bool | ||
enableMachine bool | ||
enablePackage bool | ||
} | ||
|
||
// NewRootCommand returns a new command registered in the parent. | ||
func NewRootCommand(parent cmd.Registerer, g *global.Data) *RootCommand { | ||
var c RootCommand | ||
c.Globals = g | ||
c.CmdClause = parent.Command("telemetry", "Control what telemetry data is recorded") | ||
c.CmdClause.Flag("disable", "Disable all telemetry").BoolVar(&c.disable) | ||
c.CmdClause.Flag("disable-build", "Disable telemetry for information regarding the time taken for builds and compilation processes").BoolVar(&c.disableBuild) | ||
c.CmdClause.Flag("disable-machine", "Disable telemetry for general, non-identifying system specifications (CPU, RAM, operating system)").BoolVar(&c.disableMachine) | ||
c.CmdClause.Flag("disable-package", "Disable telemetry for packages and libraries utilized in your source code").BoolVar(&c.disablePackage) | ||
c.CmdClause.Flag("enable", "Enable all telemetry").BoolVar(&c.enable) | ||
c.CmdClause.Flag("enable-build", "Enable telemetry for information regarding the time taken for builds and compilation processes").BoolVar(&c.enableBuild) | ||
c.CmdClause.Flag("enable-machine", "Enable telemetry for general, non-identifying system specifications (CPU, RAM, operating system)").BoolVar(&c.enableMachine) | ||
c.CmdClause.Flag("enable-package", "Enable telemetry for packages and libraries utilized in your source code").BoolVar(&c.enablePackage) | ||
return &c | ||
} | ||
|
||
// Exec implements the command interface. | ||
func (c *RootCommand) Exec(_ io.Reader, out io.Writer) error { | ||
if c.disable && c.enable { | ||
return fsterr.ErrInvalidTelemetryEnableDisableCombo | ||
} | ||
if c.disable { | ||
c.Globals.Config.Telemetry = toggleAll("disable") | ||
} | ||
if c.enable { | ||
c.Globals.Config.Telemetry = toggleAll("enable") | ||
} | ||
if c.disable && (c.enableBuild || c.enableMachine || c.enablePackage) { | ||
text.Info(out, "We will disable all telemetry except for the specified `--enable-*` flags") | ||
text.Break(out) | ||
} | ||
if c.enable && (c.disableBuild || c.disableMachine || c.disablePackage) { | ||
text.Info(out, "We will enable all telemetry except for the specified `--disable-*` flags") | ||
text.Break(out) | ||
} | ||
if c.enableBuild { | ||
c.Globals.Config.Telemetry.BuildInfo = "enable" | ||
} | ||
if c.enableMachine { | ||
c.Globals.Config.Telemetry.MachineInfo = "enable" | ||
} | ||
if c.enablePackage { | ||
c.Globals.Config.Telemetry.PackageInfo = "enable" | ||
} | ||
if c.disableBuild { | ||
c.Globals.Config.Telemetry.BuildInfo = "disable" | ||
} | ||
if c.disableMachine { | ||
c.Globals.Config.Telemetry.MachineInfo = "disable" | ||
} | ||
if c.disablePackage { | ||
c.Globals.Config.Telemetry.PackageInfo = "disable" | ||
} | ||
err := c.Globals.Config.Write(c.Globals.ConfigPath) | ||
if err != nil { | ||
return fmt.Errorf("failed to persist telemetry choices to disk: %w", err) | ||
} | ||
text.Success(out, "configuration updated (see: `fastly config`)") | ||
return nil | ||
} | ||
|
||
func toggleAll(state string) config.Telemetry { | ||
var t config.Telemetry | ||
t.BuildInfo = state | ||
t.MachineInfo = state | ||
t.PackageInfo = state | ||
return t | ||
} |
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,145 @@ | ||
package telemetry_test | ||
|
||
import ( | ||
"bytes" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"testing" | ||
|
||
toml "github.com/pelletier/go-toml" | ||
|
||
"github.com/fastly/cli/pkg/app" | ||
"github.com/fastly/cli/pkg/config" | ||
"github.com/fastly/cli/pkg/revision" | ||
"github.com/fastly/cli/pkg/testutil" | ||
) | ||
|
||
// Scenario is an extension of the base TestScenario. | ||
// It includes manipulating stdin. | ||
type Scenario struct { | ||
testutil.TestScenario | ||
|
||
ExpectedConfig config.Telemetry | ||
} | ||
|
||
func TestTelemetry(t *testing.T) { | ||
var ( | ||
configPath string | ||
data []byte | ||
) | ||
|
||
// Create temp environment to run test code within. | ||
{ | ||
wd, err := os.Getwd() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Read the test config.toml data | ||
path, err := filepath.Abs(filepath.Join("./", "testdata", "config.toml")) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
data, err = os.ReadFile(path) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
// Create a new test environment along with a test config.toml file. | ||
rootdir := testutil.NewEnv(testutil.EnvOpts{ | ||
T: t, | ||
Write: []testutil.FileIO{ | ||
{Src: string(data), Dst: "config.toml"}, | ||
}, | ||
}) | ||
configPath = filepath.Join(rootdir, "config.toml") | ||
defer os.RemoveAll(rootdir) | ||
|
||
if err := os.Chdir(rootdir); err != nil { | ||
t.Fatal(err) | ||
} | ||
defer os.Chdir(wd) | ||
} | ||
|
||
args := testutil.Args | ||
scenarios := []Scenario{ | ||
{ | ||
TestScenario: testutil.TestScenario{ | ||
Args: args("telemetry --enable"), | ||
WantOutput: "SUCCESS: configuration updated (see: `fastly config`)", | ||
}, | ||
ExpectedConfig: config.Telemetry{ | ||
BuildInfo: "enable", | ||
MachineInfo: "enable", | ||
PackageInfo: "enable", | ||
}, | ||
}, | ||
{ | ||
TestScenario: testutil.TestScenario{ | ||
Args: args("telemetry --disable"), | ||
WantOutput: "SUCCESS: configuration updated (see: `fastly config`)", | ||
}, | ||
ExpectedConfig: config.Telemetry{ | ||
BuildInfo: "disable", | ||
MachineInfo: "disable", | ||
PackageInfo: "disable", | ||
}, | ||
}, | ||
} | ||
|
||
for testcaseIdx := range scenarios { | ||
testcase := &scenarios[testcaseIdx] | ||
t.Run(testcase.Name, func(t *testing.T) { | ||
var stdout bytes.Buffer | ||
|
||
opts := testutil.NewRunOpts(testcase.Args, &stdout) | ||
|
||
// We override the config path so that we don't accidentally write over | ||
// our own configuration file. | ||
opts.ConfigPath = configPath | ||
|
||
// We read the static/embedded config so we can get the latest config | ||
// version and so we don't accidentally switch to the UseStatic() version. | ||
var staticConfig config.File | ||
err := toml.Unmarshal(config.Static, &staticConfig) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
// The read of the config file only happens in the main() function, so for | ||
// the sake of the test environment we need to construct an in-memory | ||
// representation of the config file we want to be using. | ||
opts.ConfigFile = config.File{ | ||
ConfigVersion: staticConfig.ConfigVersion, | ||
CLI: config.CLI{ | ||
Version: revision.SemVer(revision.AppVersion), | ||
}, | ||
} | ||
|
||
err = app.Run(opts) | ||
|
||
t.Log(stdout.String()) | ||
|
||
testutil.AssertErrorContains(t, err, testcase.WantError) | ||
testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput) | ||
|
||
in := strings.NewReader("") | ||
verboseMode := false | ||
err = opts.ConfigFile.Read(configPath, in, opts.Stdout, opts.ErrLog, verboseMode) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
if opts.ConfigFile.Telemetry.BuildInfo != testcase.ExpectedConfig.BuildInfo { | ||
t.Errorf("want: %s, got: %s", testcase.ExpectedConfig.BuildInfo, opts.ConfigFile.Telemetry.BuildInfo) | ||
} | ||
if opts.ConfigFile.Telemetry.MachineInfo != testcase.ExpectedConfig.MachineInfo { | ||
t.Errorf("want: %s, got: %s", testcase.ExpectedConfig.MachineInfo, opts.ConfigFile.Telemetry.MachineInfo) | ||
} | ||
if opts.ConfigFile.Telemetry.PackageInfo != testcase.ExpectedConfig.PackageInfo { | ||
t.Errorf("want: %s, got: %s", testcase.ExpectedConfig.PackageInfo, opts.ConfigFile.Telemetry.PackageInfo) | ||
} | ||
}) | ||
} | ||
} |
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,4 @@ | ||
[telemetry] | ||
build_info = "disable" | ||
machine_info = "disable" | ||
package_info = "disable" |
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