driftctl/pkg/remote/scanner.go

136 lines
3.5 KiB
Go
Raw Normal View History

2021-06-28 09:00:59 +00:00
package remote
import (
"context"
2021-03-26 08:44:55 +00:00
"github.com/cloudskiff/driftctl/pkg/alerter"
2021-07-26 09:55:59 +00:00
"github.com/cloudskiff/driftctl/pkg/filter"
2021-03-26 08:44:55 +00:00
"github.com/cloudskiff/driftctl/pkg/parallel"
2021-06-11 15:10:06 +00:00
"github.com/cloudskiff/driftctl/pkg/remote/common"
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"
"github.com/sirupsen/logrus"
)
2021-06-11 15:10:06 +00:00
type ScannerOptions struct {
Deep bool
}
type Scanner struct {
2021-06-11 15:10:06 +00:00
enumeratorRunner *parallel.ParallelRunner
detailsFetcherRunner *parallel.ParallelRunner
remoteLibrary *common.RemoteLibrary
2021-06-28 09:00:59 +00:00
alerter alerter.AlerterInterface
2021-06-11 15:10:06 +00:00
options ScannerOptions
2021-07-26 09:55:59 +00:00
filter filter.Filter
}
2021-07-26 09:55:59 +00:00
func NewScanner(remoteLibrary *common.RemoteLibrary, alerter alerter.AlerterInterface, options ScannerOptions, filter filter.Filter) *Scanner {
return &Scanner{
2021-06-11 15:10:06 +00:00
enumeratorRunner: parallel.NewParallelRunner(context.TODO(), 10),
detailsFetcherRunner: parallel.NewParallelRunner(context.TODO(), 10),
remoteLibrary: remoteLibrary,
alerter: alerter,
options: options,
2021-07-26 09:55:59 +00:00
filter: filter,
}
}
2021-08-09 14:03:04 +00:00
func (s *Scanner) retrieveRunnerResults(runner *parallel.ParallelRunner) ([]*resource.Resource, error) {
results := make([]*resource.Resource, 0)
2021-06-11 15:10:06 +00:00
loop:
for {
select {
case resources, ok := <-runner.Read():
if !ok || resources == nil {
break loop
}
2021-08-09 14:03:04 +00:00
for _, res := range resources.([]*resource.Resource) {
2021-06-11 15:10:06 +00:00
if res != nil {
results = append(results, res)
}
}
case <-runner.DoneChan():
break loop
}
}
return results, runner.Err()
}
2021-08-09 14:03:04 +00:00
func (s *Scanner) scan() ([]*resource.Resource, error) {
2021-06-11 15:10:06 +00:00
for _, enumerator := range s.remoteLibrary.Enumerators() {
2021-07-26 09:55:59 +00:00
if s.filter.IsTypeIgnored(enumerator.SupportedType()) {
logrus.WithFields(logrus.Fields{
"type": enumerator.SupportedType(),
}).Debug("Ignored enumeration of resources since it is ignored in filter")
continue
}
2021-06-11 15:10:06 +00:00
enumerator := enumerator
s.enumeratorRunner.Run(func() (interface{}, error) {
resources, err := enumerator.Enumerate()
if err != nil {
2021-07-06 10:12:55 +00:00
err := HandleResourceEnumerationError(err, s.alerter)
if err == nil {
2021-08-09 14:03:04 +00:00
return []*resource.Resource{}, nil
2021-07-06 10:12:55 +00:00
}
2021-06-11 15:10:06 +00:00
return nil, err
}
for _, res := range resources {
if res == nil {
2021-06-11 15:10:06 +00:00
continue
}
logrus.WithFields(logrus.Fields{
"id": res.ResourceId(),
"type": res.ResourceType(),
2021-06-11 15:10:06 +00:00
}).Debug("Found cloud resource")
}
return resources, nil
})
}
2021-06-11 15:10:06 +00:00
enumerationResult, err := s.retrieveRunnerResults(s.enumeratorRunner)
if err != nil {
return nil, err
}
2021-07-20 12:42:52 +00:00
if !s.options.Deep {
return enumerationResult, nil
}
2021-06-11 15:10:06 +00:00
for _, res := range enumerationResult {
res := res
s.detailsFetcherRunner.Run(func() (interface{}, error) {
fetcher := s.remoteLibrary.GetDetailsFetcher(resource.ResourceType(res.ResourceType()))
if fetcher == nil {
2021-08-09 14:03:04 +00:00
return []*resource.Resource{res}, nil
}
resourceWithDetails, err := fetcher.ReadDetails(res)
if err != nil {
if err := HandleResourceDetailsFetchingError(err, s.alerter); err != nil {
2021-07-20 12:42:52 +00:00
return nil, err
2021-06-11 15:10:06 +00:00
}
2021-08-09 14:03:04 +00:00
return []*resource.Resource{}, nil
2021-06-11 15:10:06 +00:00
}
2021-08-09 14:03:04 +00:00
return []*resource.Resource{resourceWithDetails}, nil
2021-06-11 15:10:06 +00:00
})
}
return s.retrieveRunnerResults(s.detailsFetcherRunner)
}
2021-08-09 14:03:04 +00:00
func (s *Scanner) Resources() ([]*resource.Resource, error) {
resources, err := s.scan()
2021-06-11 15:10:06 +00:00
if err != nil {
return nil, err
}
return resources, err
}
func (s *Scanner) Stop() {
logrus.Debug("Stopping scanner")
2021-06-11 15:10:06 +00:00
s.enumeratorRunner.Stop(errors.New("interrupted"))
s.detailsFetcherRunner.Stop(errors.New("interrupted"))
}