From c460a9e97aea10e91cd12844ab5d6e78dd0f8f22 Mon Sep 17 00:00:00 2001 From: Elie Date: Thu, 25 Nov 2021 15:07:50 +0100 Subject: [PATCH] Add a global switch to disable third party --- build/build.go | 11 ++++ main.go | 8 ++- pkg/cmd/driftctl.go | 8 ++- pkg/cmd/driftctl_test.go | 106 +++++++++++++++++++------------- pkg/cmd/scan.go | 4 +- pkg/telemetry/telemetry.go | 17 ++++- pkg/telemetry/telemetry_test.go | 20 +++++- test/build.go | 4 ++ test/mocks/MockBuild.go | 7 ++- 9 files changed, 133 insertions(+), 52 deletions(-) diff --git a/build/build.go b/build/build.go index 8e3e2f52f..61e3cae88 100644 --- a/build/build.go +++ b/build/build.go @@ -2,8 +2,15 @@ package build var env = "dev" +// This flag could be switched to false while building to create a binary without third party network calls +// That mean that following services will be disabled: +// - telemetry +// - version check +var enableUsageReporting = "true" + type BuildInterface interface { IsRelease() bool + IsUsageReportingEnabled() bool } type Build struct{} @@ -11,3 +18,7 @@ type Build struct{} func (b Build) IsRelease() bool { return env == "release" } + +func (b Build) IsUsageReportingEnabled() bool { + return enableUsageReporting == "true" +} diff --git a/main.go b/main.go index a7921a20e..49797af9c 100644 --- a/main.go +++ b/main.go @@ -31,8 +31,14 @@ func run() int { config.Init() logger.Init() + build := build.Build{} + logrus.WithFields(logrus.Fields{ + "isRelease": fmt.Sprintf("%t", build.IsRelease()), + "isUsageReportingEnabled": fmt.Sprintf("%t", build.IsUsageReportingEnabled()), + "version": version.Current(), + }).Debug("Build info") - driftctlCmd := cmd.NewDriftctlCmd(build.Build{}) + driftctlCmd := cmd.NewDriftctlCmd(build) checkVersion := driftctlCmd.ShouldCheckVersion() latestVersionChan := make(chan string) diff --git a/pkg/cmd/driftctl.go b/pkg/cmd/driftctl.go index 5e5f7f8b5..12b7b60b1 100644 --- a/pkg/cmd/driftctl.go +++ b/pkg/cmd/driftctl.go @@ -62,8 +62,10 @@ func NewDriftctlCmd(build build.BuildInterface) *DriftctlCmd { cmd.SetUsageTemplate(usageTemplate) cmd.PersistentFlags().BoolP("help", "h", false, "Display help for command") - cmd.PersistentFlags().BoolP("no-version-check", "", false, "Disable the version check") - cmd.PersistentFlags().BoolP("disable-telemetry", "", false, "Disable telemetry") + if cmd.build.IsUsageReportingEnabled() { + cmd.PersistentFlags().BoolP("no-version-check", "", false, "Disable the version check") + cmd.PersistentFlags().BoolP("disable-telemetry", "", false, "Disable telemetry") + } cmd.PersistentFlags().BoolP("send-crash-report", "", false, "Enable error reporting. Crash data will be sent to us via Sentry.\nWARNING: may leak sensitive data (please read the documentation for more details)\nThis flag should be used only if an error occurs during execution") cmd.AddCommand(NewScanCmd(&pkg.ScanOptions{})) @@ -87,7 +89,7 @@ func (driftctlCmd DriftctlCmd) ShouldCheckVersion() bool { hasVersionCmd := contains(os.Args[1:], "version") hasCompletionCmd := contains(os.Args[1:], "completion") isHelp := contains(os.Args[1:], "help") || contains(os.Args[1:], "--help") || contains(os.Args[1:], "-h") - return driftctlCmd.build.IsRelease() && !hasVersionCmd && !hasCompletionCmd && !noVersionCheckVal && !isHelp && !noVersionCheckEnv + return driftctlCmd.build.IsRelease() && driftctlCmd.build.IsUsageReportingEnabled() && !hasVersionCmd && !hasCompletionCmd && !noVersionCheckVal && !isHelp && !noVersionCheckEnv } func IsReportingEnabled(cmd *cobra.Command) bool { diff --git a/pkg/cmd/driftctl_test.go b/pkg/cmd/driftctl_test.go index efc3dad1b..ee4aec5f4 100644 --- a/pkg/cmd/driftctl_test.go +++ b/pkg/cmd/driftctl_test.go @@ -165,73 +165,91 @@ func TestDriftctlCmd_Invalid(t *testing.T) { func TestDriftctlCmd_ShouldCheckVersion(t *testing.T) { cases := []struct { - Name string - IsRelease bool - args []string - env map[string]string - expected bool + Name string + IsRelease bool + UsageReport bool + args []string + env map[string]string + expected bool }{ { - Name: "When we are in release mode and no args, should check for update", - IsRelease: true, - args: []string{""}, - expected: true, + Name: "When we are in release mode and no args, should check for update", + IsRelease: true, + UsageReport: true, + args: []string{""}, + expected: true, }, { - Name: "Don't check for update for version cmd", - IsRelease: true, - args: []string{"version"}, - expected: false, + Name: "Do not check for update when usage reporting is disabled", + IsRelease: true, + UsageReport: false, + args: []string{""}, + expected: false, }, { - Name: "Don't check for update for help cmd", - IsRelease: true, - args: []string{"help"}, - expected: false, + Name: "Don't check for update for version cmd", + IsRelease: true, + UsageReport: true, + args: []string{"version"}, + expected: false, }, { - Name: "Don't check for update for cmd --help", - IsRelease: true, - args: []string{"scan", "--help"}, - expected: false, + Name: "Don't check for update for help cmd", + IsRelease: true, + UsageReport: true, + args: []string{"help"}, + expected: false, }, { - Name: "Don't check for update for cmd -h", - IsRelease: true, - args: []string{"scan", "-h"}, - expected: false, + Name: "Don't check for update for cmd --help", + IsRelease: true, + UsageReport: true, + args: []string{"scan", "--help"}, + expected: false, }, { - Name: "Don't check for update when no check flag present", - IsRelease: true, - args: []string{"--no-version-check"}, - expected: false, + Name: "Don't check for update for cmd -h", + IsRelease: true, + UsageReport: true, + args: []string{"scan", "-h"}, + expected: false, }, { - Name: "Don't check for update in dev mode", - IsRelease: false, - args: []string{""}, - expected: false, + Name: "Don't check for update when no check flag present", + IsRelease: true, + UsageReport: true, + args: []string{"--no-version-check"}, + expected: false, }, { - Name: "Don't check for update when env DCTL_NO_VERSION_CHECK set", - IsRelease: true, + Name: "Don't check for update in dev mode", + IsRelease: false, + UsageReport: true, + args: []string{""}, + expected: false, + }, + { + Name: "Don't check for update when env DCTL_NO_VERSION_CHECK set", + IsRelease: true, + UsageReport: true, env: map[string]string{ "DCTL_NO_VERSION_CHECK": "foo", }, expected: false, }, { - Name: "Should not return error when launching sub command", - IsRelease: false, - args: []string{"scan", "--from", "tfstate://terraform.tfstate"}, - expected: false, + Name: "Should not return error when launching sub command", + IsRelease: false, + UsageReport: true, + args: []string{"scan", "--from", "tfstate://terraform.tfstate"}, + expected: false, }, { - Name: "Don't check for update for completion cmd", - IsRelease: true, - args: []string{"completion", "bash"}, - expected: false, + Name: "Don't check for update for completion cmd", + IsRelease: true, + UsageReport: true, + args: []string{"completion", "bash"}, + expected: false, }, } @@ -244,7 +262,7 @@ func TestDriftctlCmd_ShouldCheckVersion(t *testing.T) { os.Setenv(key, val) } - cmd := NewDriftctlCmd(mocks.MockBuild{Release: c.IsRelease}) + cmd := NewDriftctlCmd(mocks.MockBuild{Release: c.IsRelease, UsageReporting: c.UsageReport}) os.Args = append([]string{"driftctl"}, c.args...) result := cmd.ShouldCheckVersion() diff --git a/pkg/cmd/scan.go b/pkg/cmd/scan.go index 1f8c19cd2..2b49249d3 100644 --- a/pkg/cmd/scan.go +++ b/pkg/cmd/scan.go @@ -9,6 +9,7 @@ import ( "syscall" "time" + "github.com/cloudskiff/driftctl/build" "github.com/cloudskiff/driftctl/pkg/analyser" "github.com/cloudskiff/driftctl/pkg/memstore" "github.com/cloudskiff/driftctl/pkg/remote/common" @@ -309,7 +310,8 @@ func scanRun(opts *pkg.ScanOptions) error { globaloutput.Printf(color.WhiteString("Provider version used to scan: %s. Use --tf-provider-version to use another version.\n"), resourceSchemaRepository.ProviderVersion.String()) if !opts.DisableTelemetry { - telemetry.SendTelemetry(store.Bucket(memstore.TelemetryBucket)) + tl := telemetry.NewTelemetry(&build.Build{}) + tl.SendTelemetry(store.Bucket(memstore.TelemetryBucket)) } if !analysis.IsSync() { diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index bc23a1f56..236b3fa92 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -6,6 +6,7 @@ import ( "net/http" "runtime" + "github.com/cloudskiff/driftctl/build" "github.com/cloudskiff/driftctl/pkg/memstore" "github.com/cloudskiff/driftctl/pkg/version" "github.com/sirupsen/logrus" @@ -21,7 +22,21 @@ type telemetry struct { ProviderName string `json:"provider_name"` } -func SendTelemetry(store memstore.Bucket) { +type Telemetry struct { + build build.BuildInterface +} + +func NewTelemetry(build build.BuildInterface) *Telemetry { + return &Telemetry{build: build} +} + +func (te Telemetry) SendTelemetry(store memstore.Bucket) { + + if !te.build.IsUsageReportingEnabled() { + logrus.Debug("Usage reporting is disabled on this build, telemetry skipped") + return + } + t := &telemetry{ Version: version.Current(), Os: runtime.GOOS, diff --git a/pkg/telemetry/telemetry_test.go b/pkg/telemetry/telemetry_test.go index f6f149646..41de47036 100644 --- a/pkg/telemetry/telemetry_test.go +++ b/pkg/telemetry/telemetry_test.go @@ -11,6 +11,7 @@ import ( "github.com/cloudskiff/driftctl/pkg/memstore" "github.com/cloudskiff/driftctl/pkg/resource" "github.com/cloudskiff/driftctl/pkg/version" + "github.com/cloudskiff/driftctl/test/mocks" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -126,7 +127,24 @@ func TestSendTelemetry(t *testing.T) { }, ) } - SendTelemetry(store) + tl := NewTelemetry(mocks.MockBuild{UsageReporting: true}) + tl.SendTelemetry(store) }) } } + +func TestTelemetryNotSend(t *testing.T) { + httpmock.Activate() + defer httpmock.DeactivateAndReset() + store := memstore.New().Bucket(memstore.TelemetryBucket) + + httpmock.RegisterResponder( + "POST", + "https://2lvzgmrf2e.execute-api.eu-west-3.amazonaws.com/telemetry", + httpmock.NewErrorResponder(nil), + ) + tl := NewTelemetry(mocks.MockBuild{UsageReporting: false}) + tl.SendTelemetry(store) + + assert.Zero(t, httpmock.GetTotalCallCount()) +} diff --git a/test/build.go b/test/build.go index 2a627879a..010cc1ec3 100644 --- a/test/build.go +++ b/test/build.go @@ -5,3 +5,7 @@ type Build struct{} func (b Build) IsRelease() bool { return false } + +func (b Build) IsUsageReportingEnabled() bool { + return false +} diff --git a/test/mocks/MockBuild.go b/test/mocks/MockBuild.go index 023aaacb6..ed4cd3a59 100644 --- a/test/mocks/MockBuild.go +++ b/test/mocks/MockBuild.go @@ -1,9 +1,14 @@ package mocks type MockBuild struct { - Release bool + Release bool + UsageReporting bool } func (m MockBuild) IsRelease() bool { return m.Release } + +func (m MockBuild) IsUsageReportingEnabled() bool { + return m.UsageReporting +}