Skip to content

Commit

Permalink
feat: add azurerm_resource_group
Browse files Browse the repository at this point in the history
  • Loading branch information
sundowndev committed Sep 30, 2021
1 parent a86887c commit 9765abb
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ require (
cloud.google.com/go/asset v0.1.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0
github.com/Azure/azure-sdk-for-go/sdk/resources/armresources v0.3.0
github.com/Azure/azure-sdk-for-go/sdk/storage/armstorage v0.2.0
github.com/Azure/azure-sdk-for-go/sdk/to v0.1.4
github.com/Azure/go-autorest/autorest v0.11.3
github.com/aws/aws-sdk-go v1.38.68
github.com/bmatcuk/doublestar/v4 v4.0.1
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-sdk-for-go v45.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v57.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go v57.1.0+incompatible h1:TKQ3ieyB0vVKkF6t9dsWbMjq56O1xU3eh3Ec09v6ajM=
github.com/Azure/azure-sdk-for-go v57.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0 h1:lhSJz9RMbJcTgxifR1hUNJnn6CNYtbgEDtQV22/9RBA=
Expand All @@ -57,10 +58,10 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0 h1:OYa9vmRX2XC5GXRAzegg
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0 h1:v9p9TfTbf7AwNb5NYQt7hI41IfPoLFiFkLtb+bmGjT0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
github.com/Azure/azure-sdk-for-go/sdk/resources/armresources v0.3.0 h1:I1cONUC2nKiGU3JXm2jRB4+QIs06lGqkplVpwy4ie9o=
github.com/Azure/azure-sdk-for-go/sdk/resources/armresources v0.3.0/go.mod h1:LdmyxRi5+2XPnbuv0X9c6ymGle+UkoNvqsBvG+oG53M=
github.com/Azure/azure-sdk-for-go/sdk/storage/armstorage v0.2.0 h1:LOq4ZG6rMgTAZTyGbYHyxL1EVfZdngpUDRY/KvBToMs=
github.com/Azure/azure-sdk-for-go/sdk/storage/armstorage v0.2.0/go.mod h1:mIFJgQ93RCQPBsN2jBDzDOfwJpLacGwXIxmirNQMiq4=
github.com/Azure/azure-sdk-for-go/sdk/to v0.1.4 h1:3w4gk+uYOwplGhID1fDP305/8bI5Aug3URoC1V493KU=
github.com/Azure/azure-sdk-for-go/sdk/to v0.1.4/go.mod h1:UL/d4lvWAzSJUuX+19uKdN0ktyjoOyQhgY+HWNgtIYI=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.3 h1:fyYnmYujkIXUgv88D9/Wo2ybE4Zwd/TmQd5sSI5u2Ws=
Expand Down
6 changes: 4 additions & 2 deletions pkg/remote/azurerm/azurerm_resource_group_enumerator.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ func (e *AzurermResourceGroupEnumerator) Enumerate() ([]*resource.Resource, erro
results,
e.factory.CreateAbstractResource(
string(e.SupportedType()),
*group.Name,
map[string]interface{}{},
*group.ID,
map[string]interface{}{
"name": *group.Name,
},
),
)
}
Expand Down
22 changes: 20 additions & 2 deletions pkg/remote/azurerm/repository/armresources.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,32 @@ type ArmResourcesRespository interface {
ListAllResourceGroups() ([]*armresources.ResourceGroup, error)
}

type armResourcesRepository struct {
type armResourcesListPager interface {
Err() error
NextPage(ctx context.Context) bool
PageResponse() armresources.ResourceGroupsListResponse
}

type armResourcesClient interface {
List(options *armresources.ResourceGroupsListOptions) armResourcesListPager
}

type armResourcesClientImpl struct {
client *armresources.ResourceGroupsClient
}

func (c armResourcesClientImpl) List(options *armresources.ResourceGroupsListOptions) armResourcesListPager {
return c.client.List(options)
}

type armResourcesRepository struct {
client armResourcesClient
cache cache.Cache
}

func NewArmResourcesRepository(con *arm.Connection, config common.AzureProviderConfig, cache cache.Cache) *armResourcesRepository {
return &armResourcesRepository{
armresources.NewResourceGroupsClient(con, config.SubscriptionID),
armResourcesClientImpl{armresources.NewResourceGroupsClient(con, config.SubscriptionID)},
cache,
}
}
Expand Down
152 changes: 152 additions & 0 deletions pkg/remote/azurerm/repository/armresources_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package repository

import (
"reflect"
"testing"

"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resources/armresources"
"github.com/cloudskiff/driftctl/pkg/remote/cache"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func Test_ArmResources_ListAllResourceGroups(t *testing.T) {
expectedResults := []*armresources.ResourceGroup{
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/elie-dev"),
Name: to.StringPtr("elie-dev"),
},
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/william-dev"),
Name: to.StringPtr("william-dev"),
},
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/driftctl-sj-tests"),
Name: to.StringPtr("driftctl-sj-tests"),
},
}

testcases := []struct {
name string
mocks func(*mockArmResourcesListPager, *cache.MockCache)
expected []*armresources.ResourceGroup
wantErr string
}{
{
name: "should return resource groups",
mocks: func(mockPager *mockArmResourcesListPager, mockCache *cache.MockCache) {
mockPager.On("Err").Return(nil).Times(3)
mockPager.On("NextPage", mock.Anything).Return(true).Times(2)
mockPager.On("NextPage", mock.Anything).Return(false).Times(1)
mockPager.On("PageResponse").Return(armresources.ResourceGroupsListResponse{
ResourceGroupsListResult: armresources.ResourceGroupsListResult{
ResourceGroupListResult: armresources.ResourceGroupListResult{
Value: []*armresources.ResourceGroup{
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/elie-dev"),
Name: to.StringPtr("elie-dev"),
},
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/william-dev"),
Name: to.StringPtr("william-dev"),
},
},
},
},
}).Times(1)
mockPager.On("PageResponse").Return(armresources.ResourceGroupsListResponse{
ResourceGroupsListResult: armresources.ResourceGroupsListResult{
ResourceGroupListResult: armresources.ResourceGroupListResult{
Value: []*armresources.ResourceGroup{
{
ID: to.StringPtr("/subscriptions/008b5f48-1b66-4d92-a6b6-d215b4c9b473/resourceGroups/driftctl-sj-tests"),
Name: to.StringPtr("driftctl-sj-tests"),
},
},
},
},
}).Times(1)

mockCache.On("Get", "armResourcesListAllResourceGroups").Return(nil).Times(1)
mockCache.On("Put", "armResourcesListAllResourceGroups", expectedResults).Return(true).Times(1)
},
expected: expectedResults,
},
{
name: "should hit cache and return resource groups",
mocks: func(mockPager *mockArmResourcesListPager, mockCache *cache.MockCache) {
mockCache.On("Get", "armResourcesListAllResourceGroups").Return(expectedResults).Times(1)
},
expected: expectedResults,
},
{
name: "should return remote error",
mocks: func(mockPager *mockArmResourcesListPager, mockCache *cache.MockCache) {
mockPager.On("NextPage", mock.Anything).Return(true).Times(1)
mockPager.On("PageResponse").Return(armresources.ResourceGroupsListResponse{
ResourceGroupsListResult: armresources.ResourceGroupsListResult{
ResourceGroupListResult: armresources.ResourceGroupListResult{
Value: []*armresources.ResourceGroup{},
},
},
}).Times(1)
mockPager.On("Err").Return(errors.New("remote error")).Times(1)

mockCache.On("Get", "armResourcesListAllResourceGroups").Return(nil).Times(1)
},
wantErr: "remote error",
},
{
name: "should return remote error after fetching all pages",
mocks: func(mockPager *mockArmResourcesListPager, mockCache *cache.MockCache) {
mockPager.On("NextPage", mock.Anything).Return(true).Times(1)
mockPager.On("NextPage", mock.Anything).Return(false).Times(1)
mockPager.On("PageResponse").Return(armresources.ResourceGroupsListResponse{
ResourceGroupsListResult: armresources.ResourceGroupsListResult{
ResourceGroupListResult: armresources.ResourceGroupListResult{
Value: []*armresources.ResourceGroup{},
},
},
}).Times(1)
mockPager.On("Err").Return(nil).Times(1)
mockPager.On("Err").Return(errors.New("remote error")).Times(1)

mockCache.On("Get", "armResourcesListAllResourceGroups").Return(nil).Times(1)
},
wantErr: "remote error",
},
}

for _, tt := range testcases {
t.Run(tt.name, func(t *testing.T) {
fakeClient := &mockArmResourcesClient{}
mockPager := &mockArmResourcesListPager{}
mockCache := &cache.MockCache{}

fakeClient.On("List", mock.Anything).Maybe().Return(mockPager)

tt.mocks(mockPager, mockCache)

s := &armResourcesRepository{
client: fakeClient,
cache: mockCache,
}
got, err := s.ListAllResourceGroups()
if tt.wantErr != "" {
assert.EqualError(t, err, tt.wantErr)
} else {
assert.Nil(t, err)
}

fakeClient.AssertExpectations(t)
mockPager.AssertExpectations(t)
mockCache.AssertExpectations(t)

if !reflect.DeepEqual(got, tt.expected) {
t.Errorf("ListAllResourceGroups() got = %v, want %v", got, tt.expected)
}
})
}
}
29 changes: 29 additions & 0 deletions pkg/remote/azurerm/repository/mock_armResourcesClient.go

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

58 changes: 58 additions & 0 deletions pkg/remote/azurerm/repository/mock_armResourcesListPager.go

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

17 changes: 17 additions & 0 deletions pkg/resource/azurerm/azurerm_resource_group.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
package azurerm

import "github.com/cloudskiff/driftctl/pkg/resource"

const AzureResourceGroupResourceType = "azurerm_resource_group"

func initAzureResourceGroupMetadata(resourceSchemaRepository resource.SchemaRepositoryInterface) {
resourceSchemaRepository.SetNormalizeFunc(AzureResourceGroupResourceType, func(res *resource.Resource) {
val := res.Attrs
val.SafeDelete([]string{"timeouts"})
})
resourceSchemaRepository.SetHumanReadableAttributesFunc(AzureResourceGroupResourceType, func(res *resource.Resource) map[string]string {
val := res.Attrs
attrs := make(map[string]string)
if name := val.GetString("name"); name != nil && *name != "" {
attrs["Name"] = *name
}
return attrs
})
}
31 changes: 31 additions & 0 deletions pkg/resource/azurerm/azurerm_resource_group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package azurerm_test

import (
"testing"

"github.com/cloudskiff/driftctl/test"
"github.com/cloudskiff/driftctl/test/acceptance"
)

func TestAcc_Azure_ResourceGroup(t *testing.T) {
acceptance.Run(t, acceptance.AccTestCase{
TerraformVersion: "0.15.5",
Paths: []string{"./testdata/acc/azurerm_resource_group"},
Args: []string{
"scan",
"--to", "azure+tf",
"--filter", "Type=='azurerm_resource_group' && contains(Id, 'acc-test-res-group-')",
},
Checks: []acceptance.AccCheck{
{
Check: func(result *test.ScanResult, stdout string, err error) {
if err != nil {
t.Fatal(err)
}
result.AssertInfrastructureIsInSync()
result.AssertManagedCount(2)
},
},
},
})
}
1 change: 1 addition & 0 deletions pkg/resource/azurerm/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ package azurerm
import "github.com/cloudskiff/driftctl/pkg/resource"

func InitResourcesMetadata(resourceSchemaRepository resource.SchemaRepositoryInterface) {
initAzureResourceGroupMetadata(resourceSchemaRepository)
}
Loading

0 comments on commit 9765abb

Please sign in to comment.