Merge pull request #1238 from cloudskiff/add_build_flag_to_disable_telemetry

Add a global switch to disable third party
main
Elie 2021-11-29 14:15:54 +01:00 committed by GitHub
commit ede653f49f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 133 additions and 52 deletions

View File

@ -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"
}

View File

@ -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)

View File

@ -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 {

View File

@ -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()

View File

@ -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() {

View File

@ -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,

View File

@ -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())
}

View File

@ -5,3 +5,7 @@ type Build struct{}
func (b Build) IsRelease() bool {
return false
}
func (b Build) IsUsageReportingEnabled() bool {
return false
}

View File

@ -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
}