Remove custom mock and add repository for S3
parent
80f45375f7
commit
76d98ed8e7
|
@ -0,0 +1,37 @@
|
|||
// Code generated by mockery v2.3.0. DO NOT EDIT.
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
aws "github.com/aws/aws-sdk-go/aws"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
s3iface "github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
)
|
||||
|
||||
// MockAwsClientFactoryInterface is an autogenerated mock type for the AwsClientFactoryInterface type
|
||||
type MockAwsClientFactoryInterface struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GetS3Client provides a mock function with given fields: configs
|
||||
func (_m *MockAwsClientFactoryInterface) GetS3Client(configs ...*aws.Config) s3iface.S3API {
|
||||
_va := make([]interface{}, len(configs))
|
||||
for _i := range configs {
|
||||
_va[_i] = configs[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 s3iface.S3API
|
||||
if rf, ok := ret.Get(0).(func(...*aws.Config) s3iface.S3API); ok {
|
||||
r0 = rf(configs...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(s3iface.S3API)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package aws
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
@ -15,6 +15,10 @@ type AwsClientFactory struct {
|
|||
config client.ConfigProvider
|
||||
}
|
||||
|
||||
func NewAWSClientFactory(config client.ConfigProvider) *AwsClientFactory {
|
||||
return &AwsClientFactory{config}
|
||||
}
|
||||
|
||||
func (s AwsClientFactory) GetS3Client(configs ...*aws.Config) s3iface.S3API {
|
||||
return s3.New(s.config, configs...)
|
||||
}
|
|
@ -2,6 +2,8 @@ package aws
|
|||
|
||||
import (
|
||||
"github.com/cloudskiff/driftctl/pkg/alerter"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
)
|
||||
|
@ -22,16 +24,16 @@ func Init(alerter *alerter.Alerter, providerLibrary *terraform.ProviderLibrary,
|
|||
return err
|
||||
}
|
||||
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
s3Repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
|
||||
providerLibrary.AddProvider(terraform.AWS, provider)
|
||||
|
||||
supplierLibrary.AddSupplier(NewS3BucketSupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketInventorySupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketMetricSupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketNotificationSupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketPolicySupplier(provider, factory))
|
||||
supplierLibrary.AddSupplier(NewS3BucketSupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewS3BucketInventorySupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewS3BucketMetricSupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewS3BucketNotificationSupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewS3BucketPolicySupplier(provider, s3Repository))
|
||||
supplierLibrary.AddSupplier(NewEC2EipSupplier(provider))
|
||||
supplierLibrary.AddSupplier(NewEC2EipAssociationSupplier(provider))
|
||||
supplierLibrary.AddSupplier(NewEC2EbsVolumeSupplier(provider))
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
// Code generated by mockery v2.3.0. DO NOT EDIT.
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
s3 "github.com/aws/aws-sdk-go/service/s3"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
// MockS3Repository is an autogenerated mock type for the S3Repository type
|
||||
type MockS3Repository struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GetBucketLocation provides a mock function with given fields: bucket
|
||||
func (_m *MockS3Repository) GetBucketLocation(bucket *s3.Bucket) (string, error) {
|
||||
ret := _m.Called(bucket)
|
||||
|
||||
var r0 string
|
||||
if rf, ok := ret.Get(0).(func(*s3.Bucket) string); ok {
|
||||
r0 = rf(bucket)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*s3.Bucket) error); ok {
|
||||
r1 = rf(bucket)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListAllBuckets provides a mock function with given fields:
|
||||
func (_m *MockS3Repository) ListAllBuckets() ([]*s3.Bucket, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []*s3.Bucket
|
||||
if rf, ok := ret.Get(0).(func() []*s3.Bucket); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*s3.Bucket)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListBucketAnalyticsConfigurations provides a mock function with given fields: bucket, region
|
||||
func (_m *MockS3Repository) ListBucketAnalyticsConfigurations(bucket *s3.Bucket, region string) ([]*s3.AnalyticsConfiguration, error) {
|
||||
ret := _m.Called(bucket, region)
|
||||
|
||||
var r0 []*s3.AnalyticsConfiguration
|
||||
if rf, ok := ret.Get(0).(func(*s3.Bucket, string) []*s3.AnalyticsConfiguration); ok {
|
||||
r0 = rf(bucket, region)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*s3.AnalyticsConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*s3.Bucket, string) error); ok {
|
||||
r1 = rf(bucket, region)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListBucketInventoryConfigurations provides a mock function with given fields: bucket, region
|
||||
func (_m *MockS3Repository) ListBucketInventoryConfigurations(bucket *s3.Bucket, region string) ([]*s3.InventoryConfiguration, error) {
|
||||
ret := _m.Called(bucket, region)
|
||||
|
||||
var r0 []*s3.InventoryConfiguration
|
||||
if rf, ok := ret.Get(0).(func(*s3.Bucket, string) []*s3.InventoryConfiguration); ok {
|
||||
r0 = rf(bucket, region)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*s3.InventoryConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*s3.Bucket, string) error); ok {
|
||||
r1 = rf(bucket, region)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListBucketMetricsConfigurations provides a mock function with given fields: bucket, region
|
||||
func (_m *MockS3Repository) ListBucketMetricsConfigurations(bucket *s3.Bucket, region string) ([]*s3.MetricsConfiguration, error) {
|
||||
ret := _m.Called(bucket, region)
|
||||
|
||||
var r0 []*s3.MetricsConfiguration
|
||||
if rf, ok := ret.Get(0).(func(*s3.Bucket, string) []*s3.MetricsConfiguration); ok {
|
||||
r0 = rf(bucket, region)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*s3.MetricsConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(*s3.Bucket, string) error); ok {
|
||||
r1 = rf(bucket, region)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type S3Repository interface {
|
||||
ListAllBuckets() ([]*s3.Bucket, error)
|
||||
ListBucketInventoryConfigurations(bucket *s3.Bucket, region string) ([]*s3.InventoryConfiguration, error)
|
||||
ListBucketMetricsConfigurations(bucket *s3.Bucket, region string) ([]*s3.MetricsConfiguration, error)
|
||||
ListBucketAnalyticsConfigurations(bucket *s3.Bucket, region string) ([]*s3.AnalyticsConfiguration, error)
|
||||
GetBucketLocation(bucket *s3.Bucket) (string, error)
|
||||
}
|
||||
|
||||
type s3Repository struct {
|
||||
clientFactory client.AwsClientFactoryInterface
|
||||
}
|
||||
|
||||
func NewS3Repository(factory client.AwsClientFactoryInterface) *s3Repository {
|
||||
return &s3Repository{
|
||||
factory,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *s3Repository) ListAllBuckets() ([]*s3.Bucket, error) {
|
||||
out, err := s.clientFactory.GetS3Client(nil).ListBuckets(&s3.ListBucketsInput{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Buckets, nil
|
||||
}
|
||||
|
||||
func (s *s3Repository) ListBucketInventoryConfigurations(bucket *s3.Bucket, region string) ([]*s3.InventoryConfiguration, error) {
|
||||
|
||||
inventoryConfigurations := make([]*s3.InventoryConfiguration, 0)
|
||||
client := s.clientFactory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
request := &s3.ListBucketInventoryConfigurationsInput{
|
||||
Bucket: bucket.Name,
|
||||
ContinuationToken: nil,
|
||||
}
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketInventoryConfigurations(request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(
|
||||
err,
|
||||
"Error listing bucket inventory configuration %s",
|
||||
*bucket.Name,
|
||||
)
|
||||
}
|
||||
inventoryConfigurations = append(inventoryConfigurations, configurations.InventoryConfigurationList...)
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return inventoryConfigurations, nil
|
||||
}
|
||||
|
||||
func (s *s3Repository) ListBucketMetricsConfigurations(bucket *s3.Bucket, region string) ([]*s3.MetricsConfiguration, error) {
|
||||
metricsConfigurationList := make([]*s3.MetricsConfiguration, 0)
|
||||
client := s.clientFactory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
request := &s3.ListBucketMetricsConfigurationsInput{
|
||||
Bucket: bucket.Name,
|
||||
ContinuationToken: nil,
|
||||
}
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketMetricsConfigurations(request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(
|
||||
err,
|
||||
"Error listing bucket metrics configuration %s",
|
||||
*bucket.Name,
|
||||
)
|
||||
}
|
||||
metricsConfigurationList = append(metricsConfigurationList, configurations.MetricsConfigurationList...)
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return metricsConfigurationList, nil
|
||||
}
|
||||
|
||||
func (s *s3Repository) ListBucketAnalyticsConfigurations(bucket *s3.Bucket, region string) ([]*s3.AnalyticsConfiguration, error) {
|
||||
analyticsConfigurationList := make([]*s3.AnalyticsConfiguration, 0)
|
||||
client := s.clientFactory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
request := &s3.ListBucketAnalyticsConfigurationsInput{
|
||||
Bucket: bucket.Name,
|
||||
ContinuationToken: nil,
|
||||
}
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketAnalyticsConfigurations(request)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(
|
||||
err,
|
||||
"Error listing bucket analytics configuration %s",
|
||||
*bucket.Name,
|
||||
)
|
||||
}
|
||||
analyticsConfigurationList = append(analyticsConfigurationList, configurations.AnalyticsConfigurationList...)
|
||||
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return analyticsConfigurationList, nil
|
||||
}
|
||||
|
||||
func (s *s3Repository) GetBucketLocation(bucket *s3.Bucket) (string, error) {
|
||||
bucketLocationRequest := s3.GetBucketLocationInput{Bucket: bucket.Name}
|
||||
bucketLocationResponse, err := s.clientFactory.GetS3Client(nil).GetBucketLocation(&bucketLocationRequest)
|
||||
if err != nil {
|
||||
awsErr, ok := err.(awserr.Error)
|
||||
if ok && awsErr.Code() == s3.ErrCodeNoSuchBucket {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"bucket": *bucket.Name,
|
||||
}).Warning("Unable to retrieve bucket region, this may be an inconsistency in S3 api for fresh deleted bucket, skipping ...")
|
||||
return "", nil
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// Buckets in Region us-east-1 have a LocationConstraint of null.
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html#API_GetBucketLocation_ResponseSyntax
|
||||
if bucketLocationResponse.LocationConstraint == nil {
|
||||
return "us-east-1", err
|
||||
}
|
||||
|
||||
if *bucketLocationResponse.LocationConstraint == "EU" {
|
||||
return "eu-west-1", err
|
||||
}
|
||||
|
||||
return *bucketLocationResponse.LocationConstraint, nil
|
||||
}
|
|
@ -0,0 +1,540 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/mocks"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/r3labs/diff/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_s3Repository_ListAllBuckets(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mocks func(client *mocks.FakeS3)
|
||||
want []*s3.Bucket
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "List buckets",
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("ListBuckets", &s3.ListBucketsInput{}).Return(
|
||||
&s3.ListBucketsOutput{
|
||||
Buckets: []*s3.Bucket{
|
||||
{Name: aws.String("bucket1")},
|
||||
{Name: aws.String("bucket2")},
|
||||
{Name: aws.String("bucket3")},
|
||||
},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: []*s3.Bucket{
|
||||
{Name: aws.String("bucket1")},
|
||||
{Name: aws.String("bucket2")},
|
||||
{Name: aws.String("bucket3")},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Error listing buckets",
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("ListBuckets", &s3.ListBucketsInput{}).Return(
|
||||
nil,
|
||||
awserr.NewRequestFailure(nil, 403, ""),
|
||||
)
|
||||
},
|
||||
want: nil,
|
||||
wantErr: awserr.NewRequestFailure(nil, 403, ""),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockedClient := &mocks.FakeS3{}
|
||||
tt.mocks(mockedClient)
|
||||
factory := client.MockAwsClientFactoryInterface{}
|
||||
factory.On("GetS3Client", (*aws.Config)(nil)).Return(mockedClient).Once()
|
||||
r := NewS3Repository(&factory)
|
||||
got, err := r.ListAllBuckets()
|
||||
factory.AssertExpectations(t)
|
||||
assert.Equal(t, tt.wantErr, err)
|
||||
changelog, err := diff.Diff(got, tt.want)
|
||||
assert.Nil(t, err)
|
||||
if len(changelog) > 0 {
|
||||
for _, change := range changelog {
|
||||
t.Errorf("%s: %s -> %s", strings.Join(change.Path, "."), change.From, change.To)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_s3Repository_ListBucketInventoryConfigurations(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}
|
||||
mocks func(client *mocks.FakeS3)
|
||||
want []*s3.InventoryConfiguration
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "List inventory configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.ListBucketInventoryConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: nil,
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketInventoryConfigurationsOutput{
|
||||
InventoryConfigurationList: []*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("config1")},
|
||||
{Id: awssdk.String("config2")},
|
||||
{Id: awssdk.String("config3")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(true),
|
||||
NextContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
client.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.ListBucketInventoryConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketInventoryConfigurationsOutput{
|
||||
InventoryConfigurationList: []*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("config4")},
|
||||
{Id: awssdk.String("config5")},
|
||||
{Id: awssdk.String("config6")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(false),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: []*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("config1")},
|
||||
{Id: awssdk.String("config2")},
|
||||
{Id: awssdk.String("config3")},
|
||||
{Id: awssdk.String("config4")},
|
||||
{Id: awssdk.String("config5")},
|
||||
{Id: awssdk.String("config6")},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Error listing inventory configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.ListBucketInventoryConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
errors.New("aws error"),
|
||||
)
|
||||
},
|
||||
want: nil,
|
||||
wantErr: "Error listing bucket inventory configuration test-bucket: aws error",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockedClient := &mocks.FakeS3{}
|
||||
tt.mocks(mockedClient)
|
||||
factory := client.MockAwsClientFactoryInterface{}
|
||||
factory.On("GetS3Client", &aws.Config{Region: awssdk.String(tt.input.region)}).Return(mockedClient).Once()
|
||||
r := NewS3Repository(&factory)
|
||||
got, err := r.ListBucketInventoryConfigurations(&tt.input.bucket, tt.input.region)
|
||||
factory.AssertExpectations(t)
|
||||
if err != nil && tt.wantErr == "" {
|
||||
t.Fatalf("Unexpected error %+v", err)
|
||||
}
|
||||
if err != nil {
|
||||
assert.Equal(t, tt.wantErr, err.Error())
|
||||
}
|
||||
changelog, err := diff.Diff(got, tt.want)
|
||||
assert.Nil(t, err)
|
||||
if len(changelog) > 0 {
|
||||
for _, change := range changelog {
|
||||
t.Errorf("%s: %s -> %s", strings.Join(change.Path, "."), change.From, change.To)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_s3Repository_ListBucketMetricsConfigurations(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}
|
||||
mocks func(client *mocks.FakeS3)
|
||||
want []*s3.MetricsConfiguration
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "List metrics configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.ListBucketMetricsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: nil,
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketMetricsConfigurationsOutput{
|
||||
MetricsConfigurationList: []*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("metric1")},
|
||||
{Id: awssdk.String("metric2")},
|
||||
{Id: awssdk.String("metric3")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(true),
|
||||
NextContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
client.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.ListBucketMetricsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketMetricsConfigurationsOutput{
|
||||
MetricsConfigurationList: []*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("metric4")},
|
||||
{Id: awssdk.String("metric5")},
|
||||
{Id: awssdk.String("metric6")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(false),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: []*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("metric1")},
|
||||
{Id: awssdk.String("metric2")},
|
||||
{Id: awssdk.String("metric3")},
|
||||
{Id: awssdk.String("metric4")},
|
||||
{Id: awssdk.String("metric5")},
|
||||
{Id: awssdk.String("metric6")},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Error listing metrics configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.ListBucketMetricsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
errors.New("aws error"),
|
||||
)
|
||||
},
|
||||
want: nil,
|
||||
wantErr: "Error listing bucket metrics configuration test-bucket: aws error",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockedClient := &mocks.FakeS3{}
|
||||
tt.mocks(mockedClient)
|
||||
factory := client.MockAwsClientFactoryInterface{}
|
||||
factory.On("GetS3Client", &aws.Config{Region: awssdk.String(tt.input.region)}).Return(mockedClient).Once()
|
||||
r := NewS3Repository(&factory)
|
||||
got, err := r.ListBucketMetricsConfigurations(&tt.input.bucket, tt.input.region)
|
||||
factory.AssertExpectations(t)
|
||||
if err != nil && tt.wantErr == "" {
|
||||
t.Fatalf("Unexpected error %+v", err)
|
||||
}
|
||||
if err != nil {
|
||||
assert.Equal(t, tt.wantErr, err.Error())
|
||||
}
|
||||
changelog, err := diff.Diff(got, tt.want)
|
||||
assert.Nil(t, err)
|
||||
if len(changelog) > 0 {
|
||||
for _, change := range changelog {
|
||||
t.Errorf("%s: %s -> %s", strings.Join(change.Path, "."), change.From, change.To)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_s3Repository_ListBucketAnalyticsConfigurations(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}
|
||||
mocks func(client *mocks.FakeS3)
|
||||
want []*s3.AnalyticsConfiguration
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "List analytics configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.ListBucketAnalyticsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: nil,
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketAnalyticsConfigurationsOutput{
|
||||
AnalyticsConfigurationList: []*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("analytic1")},
|
||||
{Id: awssdk.String("analytic2")},
|
||||
{Id: awssdk.String("analytic3")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(true),
|
||||
NextContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
client.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.ListBucketAnalyticsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
ContinuationToken: awssdk.String("nexttoken"),
|
||||
},
|
||||
).Return(
|
||||
&s3.ListBucketAnalyticsConfigurationsOutput{
|
||||
AnalyticsConfigurationList: []*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("analytic4")},
|
||||
{Id: awssdk.String("analytic5")},
|
||||
{Id: awssdk.String("analytic6")},
|
||||
},
|
||||
IsTruncated: awssdk.Bool(false),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: []*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("analytic1")},
|
||||
{Id: awssdk.String("analytic2")},
|
||||
{Id: awssdk.String("analytic3")},
|
||||
{Id: awssdk.String("analytic4")},
|
||||
{Id: awssdk.String("analytic5")},
|
||||
{Id: awssdk.String("analytic6")},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Error listing analytics configs",
|
||||
input: struct {
|
||||
bucket s3.Bucket
|
||||
region string
|
||||
}{
|
||||
bucket: s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
region: "us-east-1",
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.ListBucketAnalyticsConfigurationsInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
},
|
||||
).Return(
|
||||
nil,
|
||||
errors.New("aws error"),
|
||||
)
|
||||
},
|
||||
want: nil,
|
||||
wantErr: "Error listing bucket analytics configuration test-bucket: aws error",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockedClient := &mocks.FakeS3{}
|
||||
tt.mocks(mockedClient)
|
||||
factory := client.MockAwsClientFactoryInterface{}
|
||||
factory.On("GetS3Client", &aws.Config{Region: awssdk.String(tt.input.region)}).Return(mockedClient).Once()
|
||||
r := NewS3Repository(&factory)
|
||||
got, err := r.ListBucketAnalyticsConfigurations(&tt.input.bucket, tt.input.region)
|
||||
factory.AssertExpectations(t)
|
||||
if err != nil && tt.wantErr == "" {
|
||||
t.Fatalf("Unexpected error %+v", err)
|
||||
}
|
||||
if err != nil {
|
||||
assert.Equal(t, tt.wantErr, err.Error())
|
||||
}
|
||||
changelog, err := diff.Diff(got, tt.want)
|
||||
assert.Nil(t, err)
|
||||
if len(changelog) > 0 {
|
||||
for _, change := range changelog {
|
||||
t.Errorf("%s: %s -> %s", strings.Join(change.Path, "."), change.From, change.To)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_s3Repository_GetBucketLocation(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
bucket *s3.Bucket
|
||||
mocks func(client *mocks.FakeS3)
|
||||
want string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "get bucket location",
|
||||
bucket: &s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("GetBucketLocation", &s3.GetBucketLocationInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
}).Return(
|
||||
&s3.GetBucketLocationOutput{
|
||||
LocationConstraint: awssdk.String("eu-east-1"),
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: "eu-east-1",
|
||||
},
|
||||
{
|
||||
name: "get bucket location for us-east-2",
|
||||
bucket: &s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("GetBucketLocation", &s3.GetBucketLocationInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
}).Return(
|
||||
&s3.GetBucketLocationOutput{},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
want: "us-east-1",
|
||||
},
|
||||
{
|
||||
name: "get bucket location when no such bucket",
|
||||
bucket: &s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("GetBucketLocation", &s3.GetBucketLocationInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
}).Return(
|
||||
nil,
|
||||
awserr.New(s3.ErrCodeNoSuchBucket, "", nil),
|
||||
)
|
||||
},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "get bucket location when error",
|
||||
bucket: &s3.Bucket{
|
||||
Name: awssdk.String("test-bucket"),
|
||||
},
|
||||
mocks: func(client *mocks.FakeS3) {
|
||||
client.On("GetBucketLocation", &s3.GetBucketLocationInput{
|
||||
Bucket: awssdk.String("test-bucket"),
|
||||
}).Return(
|
||||
nil,
|
||||
awserr.New("UnknownError", "aws error", nil),
|
||||
)
|
||||
},
|
||||
wantErr: "UnknownError: aws error",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
mockedClient := &mocks.FakeS3{}
|
||||
tt.mocks(mockedClient)
|
||||
factory := client.MockAwsClientFactoryInterface{}
|
||||
factory.On("GetS3Client", (*aws.Config)(nil)).Return(mockedClient).Once()
|
||||
r := NewS3Repository(&factory)
|
||||
got, err := r.GetBucketLocation(tt.bucket)
|
||||
factory.AssertExpectations(t)
|
||||
if err != nil && tt.wantErr == "" {
|
||||
t.Fatalf("Unexpected error %+v", err)
|
||||
}
|
||||
if err != nil {
|
||||
assert.Equal(t, tt.wantErr, err.Error())
|
||||
}
|
||||
changelog, err := diff.Diff(got, tt.want)
|
||||
assert.Nil(t, err)
|
||||
if len(changelog) > 0 {
|
||||
for _, change := range changelog {
|
||||
t.Errorf("%s: %s -> %s", strings.Join(change.Path, "."), change.From, change.To)
|
||||
}
|
||||
t.Fail()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,55 +3,49 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
type S3BucketAnalyticSupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
factory AwsClientFactoryInterface
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketAnalyticSupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketAnalyticSupplier {
|
||||
func NewS3BucketAnalyticSupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketAnalyticSupplier {
|
||||
return &S3BucketAnalyticSupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketAnalyticDeserializer(),
|
||||
factory,
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3BucketAnalyticSupplier) Resources() ([]resource.Resource, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
client := s.factory.GetS3Client(nil)
|
||||
response, err := client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsS3BucketAnalyticsConfigurationResourceType, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
name := *bucket.Name
|
||||
region, err := readBucketRegion(&client, name)
|
||||
for _, bucket := range buckets {
|
||||
bucket := *bucket
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region == "" {
|
||||
continue
|
||||
}
|
||||
if err := s.listBucketAnalyticConfiguration(*bucket.Name, region); err != nil {
|
||||
if err := s.listBucketAnalyticConfiguration(&bucket, region); err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationError(err, aws.AwsS3BucketAnalyticsConfigurationResourceType)
|
||||
}
|
||||
}
|
||||
|
@ -63,31 +57,15 @@ func (s *S3BucketAnalyticSupplier) Resources() ([]resource.Resource, error) {
|
|||
return s.deserializer.Deserialize(ctyVals)
|
||||
}
|
||||
|
||||
func (s *S3BucketAnalyticSupplier) listBucketAnalyticConfiguration(name, region string) error {
|
||||
request := &s3.ListBucketAnalyticsConfigurationsInput{
|
||||
Bucket: &name,
|
||||
ContinuationToken: nil,
|
||||
}
|
||||
analyticsConfigurationList := make([]*s3.AnalyticsConfiguration, 0)
|
||||
client := s.factory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
func (s *S3BucketAnalyticSupplier) listBucketAnalyticConfiguration(bucket *s3.Bucket, region string) error {
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketAnalyticsConfigurations(request)
|
||||
if err != nil {
|
||||
logrus.Warnf("Error listing bucket analytics configuration %s: %+v", name, err)
|
||||
return err
|
||||
}
|
||||
analyticsConfigurationList = append(analyticsConfigurationList, configurations.AnalyticsConfigurationList...)
|
||||
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
analyticsConfigurationList, err := s.repository.ListBucketAnalyticsConfigurations(bucket, region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, analytics := range analyticsConfigurationList {
|
||||
id := fmt.Sprintf("%s:%s", name, *analytics.Id)
|
||||
id := fmt.Sprintf("%s:%s", *bucket.Name, *analytics.Id)
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketAnalytic, err := s.reader.ReadResource(
|
||||
terraform.ReadResourceArgs{
|
||||
|
|
|
@ -4,103 +4,141 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketAnalyticSupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
analyticsIDs map[string][]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
listError error
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "multiple bucket with multiple analytics", dirName: "s3_bucket_analytics_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
analyticsIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Analytics_Bucket1",
|
||||
"Analytics2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Analytics_Bucket2",
|
||||
"Analytics2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Analytics_Bucket3",
|
||||
"Analytics2_Bucket3",
|
||||
},
|
||||
test: "multiple bucket with multiple analytics",
|
||||
dirName: "s3_bucket_analytics_multiple",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"ap-northeast-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
[]*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("Analytics_Bucket1")},
|
||||
{Id: awssdk.String("Analytics2_Bucket1")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
"eu-west-3",
|
||||
).Return(
|
||||
[]*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("Analytics_Bucket2")},
|
||||
{Id: awssdk.String("Analytics2_Bucket2")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
"ap-northeast-1",
|
||||
).Return(
|
||||
[]*s3.AnalyticsConfiguration{
|
||||
{Id: awssdk.String("Analytics_Bucket3")},
|
||||
{Id: awssdk.String("Analytics2_Bucket3")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
test: "cannot list bucket", dirName: "s3_bucket_analytics_list_bucket",
|
||||
bucketsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
analyticsIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Analytics_Bucket1",
|
||||
"Analytics2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Analytics_Bucket2",
|
||||
"Analytics2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Analytics_Bucket3",
|
||||
"Analytics2_Bucket3",
|
||||
},
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketAnalyticsConfigurationResourceType, resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
{
|
||||
test: "cannot list Analytics", dirName: "s3_bucket_analytics_list_analytics",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(
|
||||
[]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketAnalyticsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
nil,
|
||||
awserr.NewRequestFailure(nil, 403, ""),
|
||||
)
|
||||
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
analyticsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketAnalyticsConfigurationResourceType),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketAnalyticsConfigurationResourceType),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -114,22 +152,22 @@ func TestS3BucketAnalyticSupplier_Resources(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
mock := mocks.NewMockAWSS3Client(tt.bucketsIDs, tt.analyticsIDs, nil, nil, tt.bucketLocation, tt.listError)
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
factory := mocks.NewMockAwsClientFactory(mock)
|
||||
|
||||
deserializer := awsdeserializer.NewS3BucketAnalyticDeserializer()
|
||||
s := &S3BucketAnalyticSupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -3,55 +3,49 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
type S3BucketInventorySupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
factory AwsClientFactoryInterface
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketInventorySupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketInventorySupplier {
|
||||
func NewS3BucketInventorySupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketInventorySupplier {
|
||||
return &S3BucketInventorySupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketInventoryDeserializer(),
|
||||
factory,
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3BucketInventorySupplier) Resources() ([]resource.Resource, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
client := s.factory.GetS3Client(nil)
|
||||
response, err := client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsS3BucketInventoryResourceType, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
name := *bucket.Name
|
||||
region, err := readBucketRegion(&client, name)
|
||||
for _, bucket := range buckets {
|
||||
bucket := *bucket
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region == "" {
|
||||
continue
|
||||
}
|
||||
if err := s.listBucketInventoryConfiguration(*bucket.Name, region); err != nil {
|
||||
if err := s.listBucketInventoryConfiguration(&bucket, region); err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationError(err, aws.AwsS3BucketInventoryResourceType)
|
||||
}
|
||||
}
|
||||
|
@ -63,31 +57,13 @@ func (s *S3BucketInventorySupplier) Resources() ([]resource.Resource, error) {
|
|||
return s.deserializer.Deserialize(ctyVals)
|
||||
}
|
||||
|
||||
func (s *S3BucketInventorySupplier) listBucketInventoryConfiguration(name, region string) error {
|
||||
request := &s3.ListBucketInventoryConfigurationsInput{
|
||||
Bucket: &name,
|
||||
ContinuationToken: nil,
|
||||
func (s *S3BucketInventorySupplier) listBucketInventoryConfiguration(bucket *s3.Bucket, region string) error {
|
||||
inventoryConfigurations, err := s.repository.ListBucketInventoryConfigurations(bucket, region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inventoryConfigurations := make([]*s3.InventoryConfiguration, 0)
|
||||
client := s.factory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketInventoryConfigurations(request)
|
||||
if err != nil {
|
||||
logrus.Warnf("Error listing bucket inventory configuration %s: %+v", name, err)
|
||||
return err
|
||||
}
|
||||
inventoryConfigurations = append(inventoryConfigurations, configurations.InventoryConfigurationList...)
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, config := range inventoryConfigurations {
|
||||
id := fmt.Sprintf("%s:%s", name, *config.Id)
|
||||
id := fmt.Sprintf("%s:%s", *bucket.Name, *config.Id)
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketInventory, err := s.reader.ReadResource(
|
||||
terraform.ReadResourceArgs{
|
||||
|
|
|
@ -4,102 +4,137 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketInventorySupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
inventoriesIDs map[string][]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "multiple bucket with multiple inventories", dirName: "s3_bucket_inventories_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
inventoriesIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Inventory_Bucket1",
|
||||
"Inventory2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Inventory_Bucket2",
|
||||
"Inventory2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Inventory_Bucket3",
|
||||
"Inventory2_Bucket3",
|
||||
},
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
[]*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("Inventory_Bucket1")},
|
||||
{Id: awssdk.String("Inventory2_Bucket1")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
"eu-west-3",
|
||||
).Return(
|
||||
[]*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("Inventory_Bucket2")},
|
||||
{Id: awssdk.String("Inventory2_Bucket2")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
[]*s3.InventoryConfiguration{
|
||||
{Id: awssdk.String("Inventory_Bucket3")},
|
||||
{Id: awssdk.String("Inventory2_Bucket3")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "cannot list bucket", dirName: "s3_bucket_inventories_list_bucket",
|
||||
bucketsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
inventoriesIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Inventory_Bucket1",
|
||||
"Inventory2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Inventory_Bucket2",
|
||||
"Inventory2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Inventory_Bucket3",
|
||||
"Inventory2_Bucket3",
|
||||
},
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketInventoryResourceType, resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
{
|
||||
test: "cannot list bucket inventories", dirName: "s3_bucket_inventories_list_inventories",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(
|
||||
[]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
repository.On(
|
||||
"ListBucketInventoryConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
nil,
|
||||
awserr.NewRequestFailure(nil, 403, ""),
|
||||
)
|
||||
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
inventoriesIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketInventoryResourceType),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketInventoryResourceType),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -114,21 +149,21 @@ func TestS3BucketInventorySupplier_Resources(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketInventorySupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketInventorySupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
mock := mocks.NewMockAWSS3Client(tt.bucketsIDs, nil, tt.inventoriesIDs, nil, tt.bucketLocation, tt.listError)
|
||||
factory := mocks.NewMockAwsClientFactory(mock)
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
deserializer := awsdeserializer.NewS3BucketInventoryDeserializer()
|
||||
s := &S3BucketInventorySupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -4,102 +4,138 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketMetricSupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
metricsIDs map[string][]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "multiple bucket with multiple metrics", dirName: "s3_bucket_metrics_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
metricsIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Metrics_Bucket1",
|
||||
"Metrics2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Metrics_Bucket2",
|
||||
"Metrics2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Metrics_Bucket3",
|
||||
"Metrics2_Bucket3",
|
||||
},
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"ap-northeast-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
[]*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("Metrics_Bucket1")},
|
||||
{Id: awssdk.String("Metrics2_Bucket1")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
"eu-west-3",
|
||||
).Return(
|
||||
[]*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("Metrics_Bucket2")},
|
||||
{Id: awssdk.String("Metrics2_Bucket2")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
"ap-northeast-1",
|
||||
).Return(
|
||||
[]*s3.MetricsConfiguration{
|
||||
{Id: awssdk.String("Metrics_Bucket3")},
|
||||
{Id: awssdk.String("Metrics2_Bucket3")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "cannot list bucket", dirName: "s3_bucket_metrics_list_bucket",
|
||||
bucketsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
metricsIDs: map[string][]string{
|
||||
"bucket-martin-test-drift": {
|
||||
"Metrics_Bucket1",
|
||||
"Metrics2_Bucket1",
|
||||
},
|
||||
"bucket-martin-test-drift2": {
|
||||
"Metrics_Bucket2",
|
||||
"Metrics2_Bucket2",
|
||||
},
|
||||
"bucket-martin-test-drift3": {
|
||||
"Metrics_Bucket3",
|
||||
"Metrics2_Bucket3",
|
||||
},
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketMetricResourceType, resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
{
|
||||
test: "cannot list metrics", dirName: "s3_bucket_metrics_list_metrics",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(
|
||||
[]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"ListBucketMetricsConfigurations",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
"eu-west-1",
|
||||
).Return(
|
||||
nil,
|
||||
awserr.NewRequestFailure(nil, 403, ""),
|
||||
)
|
||||
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
},
|
||||
metricsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketMetricResourceType),
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketMetricResourceType),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -113,21 +149,21 @@ func TestS3BucketMetricSupplier_Resources(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketMetricSupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketMetricSupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
mock := mocks.NewMockAWSS3Client(tt.bucketsIDs, nil, nil, tt.metricsIDs, tt.bucketLocation, tt.listError)
|
||||
factory := mocks.NewMockAwsClientFactory(mock)
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
deserializer := awsdeserializer.NewS3BucketMetricDeserializer()
|
||||
s := &S3BucketMetricSupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -3,55 +3,49 @@ package aws
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
type S3BucketMetricSupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
factory AwsClientFactoryInterface
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketMetricSupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketMetricSupplier {
|
||||
func NewS3BucketMetricSupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketMetricSupplier {
|
||||
return &S3BucketMetricSupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketMetricDeserializer(),
|
||||
factory,
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3BucketMetricSupplier) Resources() ([]resource.Resource, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
client := s.factory.GetS3Client(nil)
|
||||
response, err := client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsS3BucketMetricResourceType, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
name := *bucket.Name
|
||||
region, err := readBucketRegion(&client, name)
|
||||
for _, bucket := range buckets {
|
||||
bucket := *bucket
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region == "" {
|
||||
continue
|
||||
}
|
||||
if err := s.listBucketMetricConfiguration(*bucket.Name, region); err != nil {
|
||||
if err := s.listBucketMetricConfiguration(&bucket, region); err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationError(err, aws.AwsS3BucketMetricResourceType)
|
||||
}
|
||||
}
|
||||
|
@ -63,31 +57,15 @@ func (s *S3BucketMetricSupplier) Resources() ([]resource.Resource, error) {
|
|||
return s.deserializer.Deserialize(ctyVals)
|
||||
}
|
||||
|
||||
func (s *S3BucketMetricSupplier) listBucketMetricConfiguration(name, region string) error {
|
||||
request := &s3.ListBucketMetricsConfigurationsInput{
|
||||
Bucket: &name,
|
||||
ContinuationToken: nil,
|
||||
}
|
||||
func (s *S3BucketMetricSupplier) listBucketMetricConfiguration(bucket *s3.Bucket, region string) error {
|
||||
|
||||
metricsConfigurationList := make([]*s3.MetricsConfiguration, 0)
|
||||
client := s.factory.GetS3Client(&awssdk.Config{Region: ®ion})
|
||||
|
||||
for {
|
||||
configurations, err := client.ListBucketMetricsConfigurations(request)
|
||||
if err != nil {
|
||||
logrus.Warnf("Error listing bucket analytics configuration %s: %+v", name, err)
|
||||
return err
|
||||
}
|
||||
metricsConfigurationList = append(metricsConfigurationList, configurations.MetricsConfigurationList...)
|
||||
if configurations.IsTruncated != nil && *configurations.IsTruncated {
|
||||
request.ContinuationToken = configurations.NextContinuationToken
|
||||
} else {
|
||||
break
|
||||
}
|
||||
metricsConfigurationList, err := s.repository.ListBucketMetricsConfigurations(bucket, region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, config := range metricsConfigurationList {
|
||||
id := fmt.Sprintf("%s:%s", name, *config.Id)
|
||||
id := fmt.Sprintf("%s:%s", *bucket.Name, *config.Id)
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketMetric, err := s.reader.ReadResource(
|
||||
terraform.ReadResourceArgs{
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
@ -15,37 +14,47 @@ import (
|
|||
type S3BucketNotificationSupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
factory AwsClientFactoryInterface
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketNotificationSupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketNotificationSupplier {
|
||||
func NewS3BucketNotificationSupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketNotificationSupplier {
|
||||
return &S3BucketNotificationSupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketNotificationDeserializer(),
|
||||
factory, terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3BucketNotificationSupplier) Resources() ([]resource.Resource, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
client := s.factory.GetS3Client(nil)
|
||||
response, err := client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsS3BucketNotificationResourceType, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
name := *bucket.Name
|
||||
region, err := readBucketRegion(&client, name)
|
||||
for _, bucket := range buckets {
|
||||
bucket := *bucket
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region == "" {
|
||||
continue
|
||||
}
|
||||
s.listBucketNotificationConfiguration(*bucket.Name, region)
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketPolicy, err := s.reader.ReadResource(terraform.ReadResourceArgs{
|
||||
Ty: aws.AwsS3BucketNotificationResourceType,
|
||||
ID: *bucket.Name,
|
||||
Attributes: map[string]string{
|
||||
"alias": region,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
return *s3BucketPolicy, err
|
||||
})
|
||||
}
|
||||
ctyVals, err := s.runner.Wait()
|
||||
if err != nil {
|
||||
|
@ -68,19 +77,3 @@ func (s *S3BucketNotificationSupplier) Resources() ([]resource.Resource, error)
|
|||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *S3BucketNotificationSupplier) listBucketNotificationConfiguration(name, region string) {
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketPolicy, err := s.reader.ReadResource(terraform.ReadResourceArgs{
|
||||
Ty: aws.AwsS3BucketNotificationResourceType,
|
||||
ID: name,
|
||||
Attributes: map[string]string{
|
||||
"alias": region,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
return *s3BucketPolicy, err
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,65 +4,90 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketNotificationSupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "single bucket without notifications",
|
||||
dirName: "s3_bucket_notifications_no_notif",
|
||||
bucketsIDs: []string{
|
||||
"dritftctl-test-no-notifications",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"dritftctl-test-no-notifications": "eu-west-3",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("dritftctl-test-no-notifications")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("dritftctl-test-no-notifications")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "multiple bucket with notifications", dirName: "s3_bucket_notifications_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"ap-northeast-1",
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "Cannot list bucket", dirName: "s3_bucket_notifications_list_bucket",
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketNotificationResourceType, resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
|
@ -78,21 +103,21 @@ func TestS3BucketNotificationSupplier_Resources(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketNotificationSupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketNotificationSupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
mock := mocks.NewMockAWSS3Client(tt.bucketsIDs, nil, nil, nil, tt.bucketLocation, tt.listError)
|
||||
factory := mocks.NewMockAwsClientFactory(mock)
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
deserializer := awsdeserializer.NewS3BucketNotificationDeserializer()
|
||||
s := &S3BucketNotificationSupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
@ -15,38 +14,50 @@ import (
|
|||
type S3BucketPolicySupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
factory AwsClientFactoryInterface
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketPolicySupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketPolicySupplier {
|
||||
func NewS3BucketPolicySupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketPolicySupplier {
|
||||
return &S3BucketPolicySupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketPolicyDeserializer(),
|
||||
factory,
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *S3BucketPolicySupplier) Resources() ([]resource.Resource, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
client := s.factory.GetS3Client(nil)
|
||||
response, err := client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsS3BucketPolicyResourceType, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
name := *bucket.Name
|
||||
region, err := readBucketRegion(&client, name)
|
||||
for _, bucket := range buckets {
|
||||
bucket := *bucket
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region == "" {
|
||||
continue
|
||||
}
|
||||
s.listBucketPolicyConfiguration(*bucket.Name, region)
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketNotification, err := s.reader.ReadResource(
|
||||
terraform.ReadResourceArgs{
|
||||
Ty: aws.AwsS3BucketPolicyResourceType,
|
||||
ID: *bucket.Name,
|
||||
Attributes: map[string]string{
|
||||
"alias": region,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
return *s3BucketNotification, err
|
||||
})
|
||||
}
|
||||
ctyVals, err := s.runner.Wait()
|
||||
if err != nil {
|
||||
|
@ -68,22 +79,3 @@ func (s *S3BucketPolicySupplier) Resources() ([]resource.Resource, error) {
|
|||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (s *S3BucketPolicySupplier) listBucketPolicyConfiguration(name, region string) {
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
s3BucketNotification, err := s.reader.ReadResource(
|
||||
terraform.ReadResourceArgs{
|
||||
Ty: aws.AwsS3BucketPolicyResourceType,
|
||||
ID: name,
|
||||
Attributes: map[string]string{
|
||||
"alias": region,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
return *s3BucketNotification, err
|
||||
})
|
||||
}
|
||||
|
|
|
@ -4,65 +4,90 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketPolicySupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "single bucket without policy",
|
||||
dirName: "s3_bucket_policy_no_policy",
|
||||
bucketsIDs: []string{
|
||||
"dritftctl-test-no-policy",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"dritftctl-test-no-policy": "eu-west-3",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("dritftctl-test-no-policy")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("dritftctl-test-no-policy")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "multiple bucket with policies", dirName: "s3_bucket_policies_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"ap-northeast-1",
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "cannot list bucket", dirName: "s3_bucket_policies_list_bucket",
|
||||
bucketsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketPolicyResourceType, resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
|
@ -79,21 +104,21 @@ func TestS3BucketPolicySupplier_Resources(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketPolicySupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketPolicySupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
mock := mocks.NewMockAWSS3Client(tt.bucketsIDs, nil, nil, nil, tt.bucketLocation, tt.listError)
|
||||
factory := mocks.NewMockAwsClientFactory(mock)
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
deserializer := awsdeserializer.NewS3BucketPolicyDeserializer()
|
||||
s := &S3BucketPolicySupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -1,97 +1,55 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
type S3BucketSupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
awsClientFactory AwsClientFactoryInterface
|
||||
runner *terraform.ParallelResourceReader
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
repository repository.S3Repository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewS3BucketSupplier(provider *AWSTerraformProvider, factory AwsClientFactoryInterface) *S3BucketSupplier {
|
||||
func NewS3BucketSupplier(provider *AWSTerraformProvider, repository repository.S3Repository) *S3BucketSupplier {
|
||||
return &S3BucketSupplier{
|
||||
provider,
|
||||
awsdeserializer.NewS3BucketDeserializer(),
|
||||
factory,
|
||||
repository,
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s S3BucketSupplier) Resources() ([]resource.Resource, error) {
|
||||
retrieve, err := s.list()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.deserializer.Deserialize(retrieve)
|
||||
}
|
||||
|
||||
func (s *S3BucketSupplier) list() ([]cty.Value, error) {
|
||||
input := &s3.ListBucketsInput{}
|
||||
|
||||
s3Client := s.awsClientFactory.GetS3Client(nil)
|
||||
|
||||
response, err := s3Client.ListBuckets(input)
|
||||
buckets, err := s.repository.ListAllBuckets()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationError(err, aws.AwsS3BucketResourceType)
|
||||
}
|
||||
|
||||
for _, bucket := range response.Buckets {
|
||||
for _, bucket := range buckets {
|
||||
b := *bucket
|
||||
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
return s.readBucket(b, &s3Client)
|
||||
return s.readBucket(b)
|
||||
})
|
||||
}
|
||||
return s.runner.Wait()
|
||||
}
|
||||
|
||||
func readBucketRegion(client *s3iface.S3API, name string) (string, error) {
|
||||
bucketLocationRequest := s3.GetBucketLocationInput{Bucket: &name}
|
||||
bucketLocationResponse, err := (*client).GetBucketLocation(&bucketLocationRequest)
|
||||
values, err := s.runner.Wait()
|
||||
if err != nil {
|
||||
awsErr, ok := err.(awserr.Error)
|
||||
if ok && awsErr.Code() == s3.ErrCodeNoSuchBucket {
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"bucket": name,
|
||||
}).Warning("Unable to retrieve bucket region, this may be an inconsistency in S3 api for fresh deleted bucket, skipping ...")
|
||||
return "", nil
|
||||
}
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Buckets in Region us-east-1 have a LocationConstraint of null.
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html#API_GetBucketLocation_ResponseSyntax
|
||||
if bucketLocationResponse.LocationConstraint == nil {
|
||||
return "us-east-1", err
|
||||
}
|
||||
|
||||
if *bucketLocationResponse.LocationConstraint == "EU" {
|
||||
return "eu-west-1", err
|
||||
}
|
||||
|
||||
return *bucketLocationResponse.LocationConstraint, nil
|
||||
return s.deserializer.Deserialize(values)
|
||||
}
|
||||
|
||||
func (s *S3BucketSupplier) readBucket(bucket s3.Bucket, client *s3iface.S3API) (cty.Value, error) {
|
||||
name := *bucket.Name
|
||||
|
||||
region, err := readBucketRegion(client, name)
|
||||
func (s *S3BucketSupplier) readBucket(bucket s3.Bucket) (cty.Value, error) {
|
||||
region, err := s.repository.GetBucketLocation(&bucket)
|
||||
if err != nil {
|
||||
return cty.NilVal, err
|
||||
}
|
||||
|
@ -101,7 +59,7 @@ func (s *S3BucketSupplier) readBucket(bucket s3.Bucket, client *s3iface.S3API) (
|
|||
|
||||
s3Bucket, err := s.reader.ReadResource(terraform.ReadResourceArgs{
|
||||
Ty: aws.AwsS3BucketResourceType,
|
||||
ID: name,
|
||||
ID: *bucket.Name,
|
||||
Attributes: map[string]string{
|
||||
"alias": region,
|
||||
},
|
||||
|
|
|
@ -4,55 +4,71 @@ import (
|
|||
"context"
|
||||
"testing"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
awssdk "github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/client"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
"github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestS3BucketSupplier_Resources(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
test string
|
||||
dirName string
|
||||
bucketsIDs []string
|
||||
bucketLocation map[string]string
|
||||
listError error
|
||||
wantErr error
|
||||
test string
|
||||
dirName string
|
||||
mocks func(repository *repository.MockS3Repository)
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
test: "multiple bucket", dirName: "s3_bucket_multiple",
|
||||
bucketsIDs: []string{
|
||||
"bucket-martin-test-drift",
|
||||
"bucket-martin-test-drift2",
|
||||
"bucket-martin-test-drift3",
|
||||
},
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On(
|
||||
"ListAllBuckets",
|
||||
).Return([]*s3.Bucket{
|
||||
{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
}, nil)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift")},
|
||||
).Return(
|
||||
"eu-west-1",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift2")},
|
||||
).Return(
|
||||
"eu-west-3",
|
||||
nil,
|
||||
)
|
||||
|
||||
repository.On(
|
||||
"GetBucketLocation",
|
||||
&s3.Bucket{Name: awssdk.String("bucket-martin-test-drift3")},
|
||||
).Return(
|
||||
"ap-northeast-1",
|
||||
nil,
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
test: "cannot list bucket", dirName: "s3_bucket_list",
|
||||
bucketsIDs: nil,
|
||||
listError: awserr.NewRequestFailure(nil, 403, ""),
|
||||
bucketLocation: map[string]string{
|
||||
"bucket-martin-test-drift": "eu-west-1",
|
||||
"bucket-martin-test-drift2": "eu-west-3",
|
||||
"bucket-martin-test-drift3": "ap-northeast-1",
|
||||
mocks: func(repository *repository.MockS3Repository) {
|
||||
repository.On("ListAllBuckets").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
wantErr: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsS3BucketResourceType),
|
||||
},
|
||||
|
@ -68,20 +84,21 @@ func TestS3BucketSupplier_Resources(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory := AwsClientFactory{config: provider.session}
|
||||
supplierLibrary.AddSupplier(NewS3BucketSupplier(provider, factory))
|
||||
repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session))
|
||||
supplierLibrary.AddSupplier(NewS3BucketSupplier(provider, repository))
|
||||
}
|
||||
|
||||
t.Run(tt.test, func(t *testing.T) {
|
||||
|
||||
factory := mocks.NewMockAwsClientFactory(mocks.NewMockAWSS3Client(tt.bucketsIDs, nil, nil, nil, tt.bucketLocation, tt.listError))
|
||||
mock := repository.MockS3Repository{}
|
||||
tt.mocks(&mock)
|
||||
|
||||
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
deserializer := awsdeserializer.NewS3BucketDeserializer()
|
||||
s := &S3BucketSupplier{
|
||||
provider,
|
||||
deserializer,
|
||||
factory,
|
||||
&mock,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
)
|
||||
|
||||
type MockAwsClientFactory struct {
|
||||
client s3iface.S3API
|
||||
}
|
||||
|
||||
func NewMockAwsClientFactory(client s3iface.S3API) MockAwsClientFactory {
|
||||
return MockAwsClientFactory{client}
|
||||
}
|
||||
|
||||
func (s MockAwsClientFactory) GetS3Client(configs ...*aws.Config) s3iface.S3API {
|
||||
return s.client
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
)
|
||||
|
||||
type MockAWSS3Client struct {
|
||||
s3iface.S3API
|
||||
bucketsIDs []string
|
||||
analyticsIDs map[string][]string
|
||||
inventoriesIDs map[string][]string
|
||||
metricsIDs map[string][]string
|
||||
bucketLocations map[string]string
|
||||
err error
|
||||
}
|
||||
|
||||
func NewMockAWSS3Client(bucketsIDs []string, analyticsIDs map[string][]string, inventoriesIDs map[string][]string, metricsIDs map[string][]string, bucketLocations map[string]string, err error) *MockAWSS3Client {
|
||||
return &MockAWSS3Client{bucketsIDs: bucketsIDs, analyticsIDs: analyticsIDs, inventoriesIDs: inventoriesIDs, metricsIDs: metricsIDs, bucketLocations: bucketLocations, err: err}
|
||||
}
|
||||
|
||||
func (m MockAWSS3Client) ListBucketAnalyticsConfigurations(in *s3.ListBucketAnalyticsConfigurationsInput) (*s3.ListBucketAnalyticsConfigurationsOutput, error) {
|
||||
if m.analyticsIDs == nil && m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
|
||||
var configurations []*s3.AnalyticsConfiguration
|
||||
for _, id := range m.analyticsIDs[*in.Bucket] {
|
||||
configurations = append(configurations, &s3.AnalyticsConfiguration{
|
||||
Id: aws.String(id),
|
||||
})
|
||||
}
|
||||
return &s3.ListBucketAnalyticsConfigurationsOutput{
|
||||
AnalyticsConfigurationList: configurations,
|
||||
}, nil
|
||||
}
|
||||
func (m MockAWSS3Client) ListBucketInventoryConfigurations(in *s3.ListBucketInventoryConfigurationsInput) (*s3.ListBucketInventoryConfigurationsOutput, error) {
|
||||
if m.inventoriesIDs == nil && m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
|
||||
var configurations []*s3.InventoryConfiguration
|
||||
for _, id := range m.inventoriesIDs[*in.Bucket] {
|
||||
configurations = append(configurations, &s3.InventoryConfiguration{
|
||||
Id: aws.String(id),
|
||||
})
|
||||
}
|
||||
return &s3.ListBucketInventoryConfigurationsOutput{
|
||||
InventoryConfigurationList: configurations,
|
||||
}, nil
|
||||
}
|
||||
func (m MockAWSS3Client) ListBucketMetricsConfigurations(in *s3.ListBucketMetricsConfigurationsInput) (*s3.ListBucketMetricsConfigurationsOutput, error) {
|
||||
if m.metricsIDs == nil && m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
|
||||
var configurations []*s3.MetricsConfiguration
|
||||
for _, id := range m.metricsIDs[*in.Bucket] {
|
||||
configurations = append(configurations, &s3.MetricsConfiguration{
|
||||
Id: aws.String(id),
|
||||
})
|
||||
}
|
||||
return &s3.ListBucketMetricsConfigurationsOutput{
|
||||
MetricsConfigurationList: configurations,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m MockAWSS3Client) ListBuckets(*s3.ListBucketsInput) (*s3.ListBucketsOutput, error) {
|
||||
if m.bucketsIDs == nil && m.err != nil {
|
||||
return nil, m.err
|
||||
}
|
||||
|
||||
var buckets []*s3.Bucket
|
||||
for _, id := range m.bucketsIDs {
|
||||
buckets = append(buckets, &s3.Bucket{
|
||||
Name: aws.String(id),
|
||||
})
|
||||
}
|
||||
return &s3.ListBucketsOutput{
|
||||
Buckets: buckets,
|
||||
Owner: nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m MockAWSS3Client) GetBucketLocation(input *s3.GetBucketLocationInput) (*s3.GetBucketLocationOutput, error) {
|
||||
location, exists := m.bucketLocations[*input.Bucket]
|
||||
if !exists {
|
||||
panic(fmt.Sprintf("no region provided for bucket %s", *input.Bucket))
|
||||
}
|
||||
return &s3.GetBucketLocationOutput{
|
||||
LocationConstraint: &location,
|
||||
}, nil
|
||||
}
|
Loading…
Reference in New Issue