2020-12-09 15:31:34 +00:00
|
|
|
package pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2021-03-26 08:44:55 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/alerter"
|
|
|
|
"github.com/cloudskiff/driftctl/pkg/parallel"
|
2021-01-20 13:01:57 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/remote"
|
2021-03-26 08:44:55 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/resource"
|
2021-02-09 18:43:39 +00:00
|
|
|
"github.com/pkg/errors"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Scanner struct {
|
2021-03-26 08:44:55 +00:00
|
|
|
resourceSuppliers []resource.Supplier
|
|
|
|
runner *parallel.ParallelRunner
|
|
|
|
alerter *alerter.Alerter
|
|
|
|
resourceSchemaRepository *resource.SchemaRepository
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-03-26 08:44:55 +00:00
|
|
|
func NewScanner(resourceSuppliers []resource.Supplier, alerter *alerter.Alerter, resourceSchemaRepository *resource.SchemaRepository) *Scanner {
|
2020-12-09 15:31:34 +00:00
|
|
|
return &Scanner{
|
2021-03-26 08:44:55 +00:00
|
|
|
resourceSuppliers: resourceSuppliers,
|
|
|
|
runner: parallel.NewParallelRunner(context.TODO(), 10),
|
|
|
|
alerter: alerter,
|
|
|
|
resourceSchemaRepository: resourceSchemaRepository,
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Scanner) Resources() ([]resource.Resource, error) {
|
|
|
|
for _, resourceProvider := range s.resourceSuppliers {
|
|
|
|
supplier := resourceProvider
|
|
|
|
s.runner.Run(func() (interface{}, error) {
|
|
|
|
res, err := supplier.Resources()
|
|
|
|
if err != nil {
|
2021-01-20 13:01:57 +00:00
|
|
|
err := remote.HandleResourceEnumerationError(err, s.alerter)
|
|
|
|
if err == nil {
|
|
|
|
return []resource.Resource{}, nil
|
|
|
|
}
|
2020-12-09 15:31:34 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, resource := range res {
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
"id": resource.TerraformId(),
|
|
|
|
"type": resource.TerraformType(),
|
|
|
|
}).Debug("Found cloud resource")
|
|
|
|
}
|
|
|
|
return res, nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
results := make([]resource.Resource, 0)
|
|
|
|
loop:
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case resources, ok := <-s.runner.Read():
|
|
|
|
if !ok || resources == nil {
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
for _, res := range resources.([]resource.Resource) {
|
2021-03-26 08:44:55 +00:00
|
|
|
|
|
|
|
if resource.IsRefactoredResource(res.TerraformType()) {
|
|
|
|
schema, exist := s.resourceSchemaRepository.GetSchema(res.TerraformType())
|
|
|
|
ctyAttr := resource.ToResourceAttributes(res.CtyValue())
|
|
|
|
ctyAttr.SanitizeDefaultsV3()
|
|
|
|
if exist && schema.NormalizeFunc != nil {
|
|
|
|
schema.NormalizeFunc(ctyAttr)
|
|
|
|
}
|
|
|
|
|
|
|
|
newRes := &resource.AbstractResource{
|
|
|
|
Id: res.TerraformId(),
|
|
|
|
Type: res.TerraformType(),
|
|
|
|
Attrs: ctyAttr,
|
|
|
|
}
|
|
|
|
results = append(results, newRes)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2020-12-09 15:31:34 +00:00
|
|
|
normalisable, ok := res.(resource.NormalizedResource)
|
|
|
|
if ok {
|
|
|
|
normalizedRes, err := normalisable.NormalizeForProvider()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Errorf("Could not normalize remote for res %s: %+v", res.TerraformId(), err)
|
|
|
|
results = append(results, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
results = append(results, normalizedRes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ok {
|
|
|
|
results = append(results, res)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case <-s.runner.DoneChan():
|
|
|
|
break loop
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return results, s.runner.Err()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Scanner) Stop() {
|
|
|
|
logrus.Debug("Stopping scanner")
|
2021-02-09 18:43:39 +00:00
|
|
|
s.runner.Stop(errors.New("interrupted"))
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|