Skip to content

Commit

Permalink
Merge pull request #1336 from snyk/feat/telemetry_iac_source_count
Browse files Browse the repository at this point in the history
Add iac source count to telemetry
  • Loading branch information
eliecharra authored Feb 9, 2022
2 parents 66baef7 + f84b03f commit 506439d
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 19 deletions.
5 changes: 3 additions & 2 deletions pkg/driftctl.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type ScanOptions struct {

type DriftCTL struct {
remoteSupplier resource.Supplier
iacSupplier resource.Supplier
iacSupplier resource.IaCSupplier
alerter alerter.AlerterInterface
analyzer *analyser.Analyzer
resourceFactory resource.ResourceFactory
Expand All @@ -50,7 +50,7 @@ type DriftCTL struct {
}

func NewDriftCTL(remoteSupplier resource.Supplier,
iacSupplier resource.Supplier,
iacSupplier resource.IaCSupplier,
alerter *alerter.Alerter,
analyzer *analyser.Analyzer,
resFactory resource.ResourceFactory,
Expand Down Expand Up @@ -189,6 +189,7 @@ func (d DriftCTL) scan() (remoteResources []*resource.Resource, resourcesFromSta
if err != nil {
return nil, nil, err
}
d.store.Bucket(memstore.TelemetryBucket).Set("iac_source_count", d.iacSupplier.SourceCount())

logrus.Info("Start scanning cloud provider")
d.scanProgress.Start()
Expand Down
13 changes: 12 additions & 1 deletion pkg/driftctl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ func runTest(t *testing.T, cases TestCases) {
res.Sch = schema
}

stateSupplier := &resource.MockSupplier{}
stateSupplier := &resource.MockIaCSupplier{}
stateSupplier.On("Resources").Return(c.stateResources, nil)
stateSupplier.On("SourceCount").Return(uint(2))

if c.remoteResources == nil {
c.remoteResources = []*resource.Resource{}
Expand Down Expand Up @@ -138,6 +139,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 0, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 0, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand All @@ -155,6 +157,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
options: func(t *testing.T) *pkg.ScanOptions {
return &pkg.ScanOptions{Deep: true}
Expand All @@ -173,6 +176,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 0, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand Down Expand Up @@ -226,6 +230,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand Down Expand Up @@ -264,6 +269,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand Down Expand Up @@ -304,6 +310,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand Down Expand Up @@ -344,6 +351,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
},
{
Expand Down Expand Up @@ -434,6 +442,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 4, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 2, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
options: func(t *testing.T) *pkg.ScanOptions {
return &pkg.ScanOptions{
Expand Down Expand Up @@ -530,6 +539,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 6, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 2, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
options: func(t *testing.T) *pkg.ScanOptions {
return &pkg.ScanOptions{
Expand Down Expand Up @@ -628,6 +638,7 @@ func TestDriftctlRun_BasicBehavior(t *testing.T) {
assert.Equal(t, 1, store.Bucket(memstore.TelemetryBucket).Get("total_resources"))
assert.Equal(t, 0, store.Bucket(memstore.TelemetryBucket).Get("total_managed"))
assert.Equal(t, uint(0), store.Bucket(memstore.TelemetryBucket).Get("duration"))
assert.Equal(t, uint(2), store.Bucket(memstore.TelemetryBucket).Get("iac_source_count"))
},
options: func(t *testing.T) *pkg.ScanOptions {
filterStr := "Id=='role-test-1'"
Expand Down
12 changes: 10 additions & 2 deletions pkg/iac/supplier/IacChainSupplier.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

type IacChainSupplier struct {
suppliers []resource.Supplier
suppliers []resource.IaCSupplier
runner *parallel.ParallelRunner
}

Expand All @@ -20,7 +20,15 @@ func NewIacChainSupplier() *IacChainSupplier {
}
}

func (r *IacChainSupplier) AddSupplier(supplier resource.Supplier) {
func (r *IacChainSupplier) SourceCount() uint {
count := uint(0)
for _, supplier := range r.suppliers {
count += supplier.SourceCount()
}
return count
}

func (r *IacChainSupplier) AddSupplier(supplier resource.IaCSupplier) {
r.suppliers = append(r.suppliers, supplier)
}

Expand Down
20 changes: 10 additions & 10 deletions pkg/iac/supplier/IacChainSupplier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ import (
func TestIacChainSupplier_Resources(t *testing.T) {
tests := []struct {
name string
initSuppliers func(suppliers *[]resource.Supplier)
initSuppliers func(suppliers *[]resource.IaCSupplier)
want []*resource.Resource
wantErr bool
}{
{
name: "All failed",
initSuppliers: func(suppliers *[]resource.Supplier) {
sup := &resource.MockSupplier{}
initSuppliers: func(suppliers *[]resource.IaCSupplier) {
sup := &resource.MockIaCSupplier{}
sup.On("Resources").Return(nil, errors.New("1"))
*suppliers = append(*suppliers, sup)

sup = &resource.MockSupplier{}
sup = &resource.MockIaCSupplier{}
sup.On("Resources").Return(nil, errors.New("2"))
*suppliers = append(*suppliers, sup)

sup = &resource.MockSupplier{}
sup = &resource.MockIaCSupplier{}
sup.On("Resources").Return(nil, errors.New("3"))
*suppliers = append(*suppliers, sup)
},
Expand All @@ -35,16 +35,16 @@ func TestIacChainSupplier_Resources(t *testing.T) {
},
{
name: "Partial failed",
initSuppliers: func(suppliers *[]resource.Supplier) {
sup := &resource.MockSupplier{}
initSuppliers: func(suppliers *[]resource.IaCSupplier) {
sup := &resource.MockIaCSupplier{}
sup.On("Resources").Return(nil, errors.New("1"))
*suppliers = append(*suppliers, sup)

sup = &resource.MockSupplier{}
sup = &resource.MockIaCSupplier{}
sup.On("Resources").Return(nil, errors.New("2"))
*suppliers = append(*suppliers, sup)

sup = &resource.MockSupplier{}
sup = &resource.MockIaCSupplier{}
sup.On("Resources").Return([]*resource.Resource{
&resource.Resource{
Id: "ID",
Expand All @@ -67,7 +67,7 @@ func TestIacChainSupplier_Resources(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
r := NewIacChainSupplier()
suppliers := make([]resource.Supplier, 0)
suppliers := make([]resource.IaCSupplier, 0)
tt.initSuppliers(&suppliers)

for _, supplier := range suppliers {
Expand Down
4 changes: 2 additions & 2 deletions pkg/iac/supplier/supplier.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func GetIACSupplier(configs []config.SupplierConfig,
progress output.Progress,
alerter *alerter.Alerter,
factory resource.ResourceFactory,
filter filter.Filter) (resource.Supplier, error) {
filter filter.Filter) (resource.IaCSupplier, error) {

chainSupplier := NewIacChainSupplier()
for _, config := range configs {
Expand All @@ -47,7 +47,7 @@ func GetIACSupplier(configs []config.SupplierConfig,

deserializer := resource.NewDeserializer(factory)

var supplier resource.Supplier
var supplier resource.IaCSupplier
var err error
switch config.Key {
case state.TerraformStateReaderSupplier:
Expand Down
17 changes: 16 additions & 1 deletion pkg/iac/terraform/state/terraform_state_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type TerraformStateReader struct {
progress output.Progress
filter filter.Filter
alerter *alerter.Alerter
sourceCount uint
}

func (r *TerraformStateReader) initReader() error {
Expand All @@ -49,7 +50,16 @@ func (r *TerraformStateReader) initReader() error {
}

func NewReader(config config.SupplierConfig, library *terraform.ProviderLibrary, backendOpts *backend.Options, progress output.Progress, alerter *alerter.Alerter, deserializer *resource.Deserializer, filter filter.Filter) (*TerraformStateReader, error) {
reader := TerraformStateReader{library: library, config: config, deserializer: deserializer, backendOptions: backendOpts, progress: progress, alerter: alerter, filter: filter}
reader := TerraformStateReader{
library: library,
config: config,
deserializer: deserializer,
backendOptions: backendOpts,
progress: progress,
alerter: alerter,
filter: filter,
sourceCount: 0,
}
err := reader.initReader()
if err != nil {
return nil, err
Expand Down Expand Up @@ -214,8 +224,13 @@ func (r *TerraformStateReader) Resources() ([]*resource.Resource, error) {
return r.retrieveMultiplesStates()
}

func (r *TerraformStateReader) SourceCount() uint {
return r.sourceCount
}

func (r *TerraformStateReader) retrieveForState(path string) ([]*resource.Resource, error) {
r.config.Path = path
r.sourceCount += 1
logrus.WithFields(logrus.Fields{
"path": r.config.Path,
"backend": r.config.Backend,
Expand Down
47 changes: 47 additions & 0 deletions pkg/resource/mock_IaCSupplier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion pkg/resource/supplier.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package resource

// Resource Supplier supply the list of resource.Resource, its the front to retrieve remote resources
// Supplier supply the list of resource.Resource, it's the main interface to retrieve remote resources
type Supplier interface {
Resources() ([]*Resource, error)
}

// IaCSupplier supply the list of resource.Resource, it's the main interface to retrieve state resources
type IaCSupplier interface {
Supplier
SourceCount() uint
}

type StoppableSupplier interface {
Supplier
Stop()
Expand Down
5 changes: 5 additions & 0 deletions pkg/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type telemetry struct {
TotalManaged int `json:"total_managed"`
Duration uint `json:"duration"`
ProviderName string `json:"provider_name"`
IaCSourceCount uint `json:"iac_source_count"`
}

type Telemetry struct {
Expand Down Expand Up @@ -59,6 +60,10 @@ func (te Telemetry) SendTelemetry(store memstore.Bucket) {
t.ProviderName = val
}

if val, ok := store.Get("iac_source_count").(uint); ok {
t.IaCSourceCount = val
}

body, err := json.Marshal(t)
if err != nil {
logrus.Debug(err)
Expand Down
2 changes: 2 additions & 0 deletions pkg/telemetry/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ func TestSendTelemetry(t *testing.T) {
TotalManaged: 1,
Duration: 123,
ProviderName: "aws",
IaCSourceCount: 2,
},
setStoreValues: func(s memstore.Bucket, a *analyser.Analysis) {
s.Set("total_resources", a.Summary().TotalResources)
s.Set("total_managed", a.Summary().TotalManaged)
s.Set("duration", uint(a.Duration.Seconds()+0.5))
s.Set("provider_name", "aws")
s.Set("iac_source_count", uint(2))
},
},
{
Expand Down

0 comments on commit 506439d

Please sign in to comment.