Merge pull request #824 from cloudskiff/fea/split_lambda_function_supplier

split lambda_function_supplier
main
William BEUIL 2021-07-09 11:19:32 +02:00 committed by GitHub
commit 92dbd59471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 220 additions and 171946 deletions

View File

@ -144,8 +144,10 @@ func Init(version string, alerter *alerter.Alerter,
remoteLibrary.AddEnumerator(NewIamPolicyEnumerator(iamRepository, factory)) remoteLibrary.AddEnumerator(NewIamPolicyEnumerator(iamRepository, factory))
remoteLibrary.AddDetailsFetcher(aws.AwsIamPolicyResourceType, common.NewGenericDetailsFetcher(aws.AwsIamPolicyResourceType, provider, deserializer)) remoteLibrary.AddDetailsFetcher(aws.AwsIamPolicyResourceType, common.NewGenericDetailsFetcher(aws.AwsIamPolicyResourceType, provider, deserializer))
remoteLibrary.AddEnumerator(NewLambdaFunctionEnumerator(lambdaRepository, factory))
remoteLibrary.AddDetailsFetcher(aws.AwsLambdaFunctionResourceType, NewLambdaFunctionDetailsFetcher(provider, deserializer))
supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, s3Repository, deserializer)) supplierLibrary.AddSupplier(NewS3BucketAnalyticSupplier(provider, s3Repository, deserializer))
supplierLibrary.AddSupplier(NewLambdaFunctionSupplier(provider, deserializer, lambdaRepository))
supplierLibrary.AddSupplier(NewIamUserSupplier(provider, deserializer, iamRepository)) supplierLibrary.AddSupplier(NewIamUserSupplier(provider, deserializer, iamRepository))
supplierLibrary.AddSupplier(NewIamUserPolicySupplier(provider, deserializer, iamRepository)) supplierLibrary.AddSupplier(NewIamUserPolicySupplier(provider, deserializer, iamRepository))
supplierLibrary.AddSupplier(NewIamUserPolicyAttachmentSupplier(provider, deserializer, iamRepository)) supplierLibrary.AddSupplier(NewIamUserPolicyAttachmentSupplier(provider, deserializer, iamRepository))

View File

@ -0,0 +1,36 @@
package aws
import (
"github.com/cloudskiff/driftctl/pkg/resource"
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/cloudskiff/driftctl/pkg/terraform"
"github.com/sirupsen/logrus"
)
type LambdaFunctionDetailsFetcher struct {
reader terraform.ResourceReader
deserializer *resource.Deserializer
}
func NewLambdaFunctionDetailsFetcher(provider terraform.ResourceReader, deserializer *resource.Deserializer) *LambdaFunctionDetailsFetcher {
return &LambdaFunctionDetailsFetcher{
reader: provider,
deserializer: deserializer,
}
}
func (r *LambdaFunctionDetailsFetcher) ReadDetails(topic resource.Resource) (resource.Resource, error) {
val, err := r.reader.ReadResource(terraform.ReadResourceArgs{
ID: topic.TerraformId(),
Ty: resourceaws.AwsLambdaFunctionResourceType,
Attributes: map[string]string{
"function_name": topic.TerraformId(),
},
})
if err != nil {
logrus.Error(err)
return nil, err
}
return r.deserializer.DeserializeOne(resourceaws.AwsLambdaFunctionResourceType, *val)
}

View File

@ -0,0 +1,46 @@
package aws
import (
"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"
)
type LambdaFunctionEnumerator struct {
repository repository.LambdaRepository
factory resource.ResourceFactory
}
func NewLambdaFunctionEnumerator(repo repository.LambdaRepository, factory resource.ResourceFactory) *LambdaFunctionEnumerator {
return &LambdaFunctionEnumerator{
repository: repo,
factory: factory,
}
}
func (e *LambdaFunctionEnumerator) SupportedType() resource.ResourceType {
return resourceaws.AwsLambdaFunctionResourceType
}
func (e *LambdaFunctionEnumerator) Enumerate() ([]resource.Resource, error) {
functions, err := e.repository.ListAllLambdaFunctions()
if err != nil {
return nil, remoteerror.NewResourceEnumerationError(err, string(e.SupportedType()))
}
results := make([]resource.Resource, len(functions))
for _, function := range functions {
results = append(
results,
e.factory.CreateAbstractResource(
string(e.SupportedType()),
*function.FunctionName,
map[string]interface{}{},
),
)
}
return results, err
}

View File

@ -1,69 +0,0 @@
package aws
import (
"github.com/aws/aws-sdk-go/service/lambda"
"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"
"github.com/cloudskiff/driftctl/pkg/terraform"
"github.com/sirupsen/logrus"
"github.com/zclconf/go-cty/cty"
)
type LambdaFunctionSupplier struct {
reader terraform.ResourceReader
deserializer *resource.Deserializer
repository repository.LambdaRepository
runner *terraform.ParallelResourceReader
}
func NewLambdaFunctionSupplier(provider *AWSTerraformProvider, deserializer *resource.Deserializer, repository repository.LambdaRepository) *LambdaFunctionSupplier {
return &LambdaFunctionSupplier{
provider,
deserializer,
repository,
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
}
}
func (s *LambdaFunctionSupplier) Resources() ([]resource.Resource, error) {
functions, err := s.repository.ListAllLambdaFunctions()
if err != nil {
return nil, remoteerror.NewResourceEnumerationError(err, resourceaws.AwsLambdaFunctionResourceType)
}
results := make([]cty.Value, 0)
if len(functions) > 0 {
for _, function := range functions {
fun := *function
s.runner.Run(func() (cty.Value, error) {
return s.readLambda(fun)
})
}
results, err = s.runner.Wait()
if err != nil {
return nil, err
}
}
return s.deserializer.Deserialize(resourceaws.AwsLambdaFunctionResourceType, results)
}
func (s *LambdaFunctionSupplier) readLambda(function lambda.FunctionConfiguration) (cty.Value, error) {
name := *function.FunctionName
resFunction, err := s.reader.ReadResource(
terraform.ReadResourceArgs{
Ty: resourceaws.AwsLambdaFunctionResourceType,
ID: name,
Attributes: map[string]string{
"function_name": name,
},
},
)
if err != nil {
logrus.Warnf("Error reading function %s[%s]: %+v", name, resourceaws.AwsLambdaFunctionResourceType, err)
return cty.NilVal, err
}
return *resFunction, nil
}

View File

@ -1,117 +0,0 @@
package aws
import (
"context"
"testing"
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
"github.com/cloudskiff/driftctl/pkg/remote/cache"
testresource "github.com/cloudskiff/driftctl/test/resource"
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/stretchr/testify/assert"
"github.com/cloudskiff/driftctl/pkg/parallel"
"github.com/cloudskiff/driftctl/test/goldenfile"
"github.com/cloudskiff/driftctl/pkg/resource"
"github.com/cloudskiff/driftctl/pkg/terraform"
"github.com/cloudskiff/driftctl/test"
"github.com/cloudskiff/driftctl/test/mocks"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/lambda"
)
func TestLambdaFunctionSupplier_Resources(t *testing.T) {
tests := []struct {
test string
dirName string
mocks func(repo *repository.MockLambdaRepository)
err error
}{
{
test: "no lambda functions",
dirName: "lambda_function_empty",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{}, nil)
},
err: nil,
},
{
test: "with lambda functions",
dirName: "lambda_function_multiple",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{
{
FunctionName: aws.String("foo"),
},
{
FunctionName: aws.String("bar"),
},
}, nil)
},
err: nil,
},
{
test: "One lambda with signing",
dirName: "lambda_function_signed",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{
{
FunctionName: aws.String("foo"),
},
}, nil)
},
err: nil,
},
{
test: "cannot list lambda functions",
dirName: "lambda_function_empty",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{}, awserr.NewRequestFailure(nil, 403, ""))
},
err: remoteerror.NewResourceEnumerationError(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsLambdaFunctionResourceType),
},
}
for _, tt := range tests {
shouldUpdate := tt.dirName == *goldenfile.Update
providerLibrary := terraform.NewProviderLibrary()
supplierLibrary := resource.NewSupplierLibrary()
repo := testresource.InitFakeSchemaRepository("aws", "3.19.0")
resourceaws.InitResourcesMetadata(repo)
factory := terraform.NewTerraformResourceFactory(repo)
deserializer := resource.NewDeserializer(factory)
if shouldUpdate {
provider, err := InitTestAwsProvider(providerLibrary)
if err != nil {
t.Fatal(err)
}
supplierLibrary.AddSupplier(NewLambdaFunctionSupplier(provider, deserializer, repository.NewLambdaRepository(provider.session, cache.New(0))))
}
t.Run(tt.test, func(t *testing.T) {
provider := mocks.NewMockedGoldenTFProvider(tt.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
client := &repository.MockLambdaRepository{}
tt.mocks(client)
s := &LambdaFunctionSupplier{
provider,
deserializer,
client,
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
}
got, err := s.Resources()
assert.Equal(t, tt.err, err)
test.CtyTestDiff(got, tt.dirName, provider, deserializer, shouldUpdate, t)
})
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
package remote
import (
"testing"
awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/lambda"
"github.com/cloudskiff/driftctl/mocks"
"github.com/cloudskiff/driftctl/pkg/remote/aws"
"github.com/cloudskiff/driftctl/pkg/remote/cache"
"github.com/cloudskiff/driftctl/pkg/remote/common"
testresource "github.com/cloudskiff/driftctl/test/resource"
terraform2 "github.com/cloudskiff/driftctl/test/terraform"
"github.com/stretchr/testify/mock"
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
"github.com/cloudskiff/driftctl/pkg/resource"
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/cloudskiff/driftctl/pkg/terraform"
"github.com/cloudskiff/driftctl/test"
"github.com/cloudskiff/driftctl/test/goldenfile"
"github.com/stretchr/testify/assert"
)
func TestScanLambdaFunction(t *testing.T) {
tests := []struct {
test string
dirName string
mocks func(repo *repository.MockLambdaRepository)
err error
}{
{
test: "no lambda functions",
dirName: "lambda_function_empty",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{}, nil)
},
err: nil,
},
{
test: "with lambda functions",
dirName: "lambda_function_multiple",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{
{
FunctionName: awssdk.String("foo"),
},
{
FunctionName: awssdk.String("bar"),
},
}, nil)
},
err: nil,
},
{
test: "One lambda with signing",
dirName: "lambda_function_signed",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{
{
FunctionName: awssdk.String("foo"),
},
}, nil)
},
err: nil,
},
{
test: "cannot list lambda functions",
dirName: "lambda_function_empty",
mocks: func(repo *repository.MockLambdaRepository) {
repo.On("ListAllLambdaFunctions").Return([]*lambda.FunctionConfiguration{}, awserr.NewRequestFailure(nil, 403, ""))
},
err: nil,
},
}
schemaRepository := testresource.InitFakeSchemaRepository("aws", "3.19.0")
resourceaws.InitResourcesMetadata(schemaRepository)
factory := terraform.NewTerraformResourceFactory(schemaRepository)
deserializer := resource.NewDeserializer(factory)
for _, c := range tests {
t.Run(c.test, func(tt *testing.T) {
shouldUpdate := c.dirName == *goldenfile.Update
session := session.Must(session.NewSessionWithOptions(session.Options{
SharedConfigState: session.SharedConfigEnable,
}))
alerter := &mocks.AlerterInterface{}
alerter.On("SendAlert", mock.Anything, mock.Anything).Maybe().Return()
scanOptions := ScannerOptions{Deep: true}
providerLibrary := terraform.NewProviderLibrary()
remoteLibrary := common.NewRemoteLibrary()
// Initialize mocks
fakeRepo := &repository.MockLambdaRepository{}
c.mocks(fakeRepo)
var repo repository.LambdaRepository = fakeRepo
providerVersion := "3.19.0"
realProvider, err := terraform2.InitTestAwsProvider(providerLibrary, providerVersion)
if err != nil {
t.Fatal(err)
}
provider := terraform2.NewFakeTerraformProvider(realProvider)
provider.WithResponse(c.dirName)
// Replace mock by real resources if we are in update mode
if shouldUpdate {
err := realProvider.Init()
if err != nil {
t.Fatal(err)
}
provider.ShouldUpdate()
repo = repository.NewLambdaRepository(session, cache.New(0))
}
remoteLibrary.AddEnumerator(aws.NewLambdaFunctionEnumerator(repo, factory))
remoteLibrary.AddDetailsFetcher(resourceaws.AwsLambdaFunctionResourceType, aws.NewLambdaFunctionDetailsFetcher(provider, deserializer))
s := NewScanner(nil, remoteLibrary, alerter, scanOptions)
got, err := s.Resources()
assert.Equal(tt, c.err, err)
if err != nil {
return
}
test.TestAgainstGoldenFile(got, resourceaws.AwsLambdaFunctionResourceType, c.dirName, provider, deserializer, shouldUpdate, tt)
})
}
}