Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DXCDT-515: Client grants resource export support #815

Merged
merged 4 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/auth0_terraform_generate.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ auth0 terraform generate [flags]
```
--force Skip confirmation.
-o, --output-dir string Output directory for the generated Terraform config files. If not provided, the files will be saved in the current working directory. (default "./")
-r, --resources strings Resource types to generate Terraform config for. If not provided, config files for all available resources will be generated. (default [auth0_action,auth0_branding,auth0_client,auth0_connection,auth0_custom_domain,auth0_organization,auth0_role,auth0_tenant])
-r, --resources strings Resource types to generate Terraform config for. If not provided, config files for all available resources will be generated. (default [auth0_action,auth0_branding,auth0_client,auth0_client_grant,auth0_connection,auth0_custom_domain,auth0_organization,auth0_role,auth0_tenant])
```


Expand Down
56 changes: 56 additions & 0 deletions internal/auth0/mock/client_grant_mock.go

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

2 changes: 2 additions & 0 deletions internal/cli/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ func (i *terraformInputs) parseResourceFetchers(api *auth0.API) ([]resourceDataF
fetchers = append(fetchers, &brandingResourceFetcher{})
case "auth0_client":
fetchers = append(fetchers, &clientResourceFetcher{api})
case "auth0_client_grant":
fetchers = append(fetchers, &clientGrantResourceFetcher{api})
case "auth0_connection":
fetchers = append(fetchers, &connectionResourceFetcher{api})
case "auth0_custom_domain":
Expand Down
36 changes: 35 additions & 1 deletion internal/cli/terraform_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"github.com/auth0/auth0-cli/internal/auth0"
)

var defaultResources = []string{"auth0_action", "auth0_branding", "auth0_client", "auth0_connection", "auth0_custom_domain", "auth0_organization", "auth0_role", "auth0_tenant"}
var defaultResources = []string{"auth0_action", "auth0_branding", "auth0_client", "auth0_client_grant", "auth0_connection", "auth0_custom_domain", "auth0_organization", "auth0_role", "auth0_tenant"}

type (
importDataList []importDataItem
Expand All @@ -35,6 +35,10 @@ type (
api *auth0.API
}

clientGrantResourceFetcher struct {
api *auth0.API
}

connectionResourceFetcher struct {
api *auth0.API
}
Expand Down Expand Up @@ -93,6 +97,36 @@ func (f *clientResourceFetcher) FetchData(ctx context.Context) (importDataList,
return data, nil
}

func (f *clientGrantResourceFetcher) FetchData(ctx context.Context) (importDataList, error) {
var data importDataList

var page int
for {
grants, err := f.api.ClientGrant.List(
ctx,
management.Page(page),
)
if err != nil {
return nil, err
}

for _, grant := range grants.ClientGrants {
data = append(data, importDataItem{
ResourceName: "auth0_client_grant." + grant.GetClientID() + "_" + sanitizeResourceName(grant.GetAudience()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to get the client name here 😭 but I know we don't have access to it on the client grant, so nothing actionable, just a note.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, its similar to what we do in Deploy CLI. I'll add a ticket for this enhancement.

ImportID: grant.GetID(),
})
}

if !grants.HasNext() {
break
}

page++
}

return data, nil
}

func (f *connectionResourceFetcher) FetchData(ctx context.Context) (importDataList, error) {
var data importDataList

Expand Down
118 changes: 112 additions & 6 deletions internal/cli/terraform_fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,19 @@ func TestActionResourceFetcher_FetchData(t *testing.T) {
assert.EqualError(t, err, "failed to list actions")
})
}

func TestBrandingResourceFetcher_FetchData(t *testing.T) {
t.Run("it successfully generates branding import data", func(t *testing.T) {
fetcher := brandingResourceFetcher{}

data, err := fetcher.FetchData(context.Background())
assert.NoError(t, err)
assert.Len(t, data, 1)
assert.Equal(t, data[0].ResourceName, "auth0_branding.branding")
assert.Greater(t, len(data[0].ImportID), 0)
})
}

func TestClientResourceFetcher_FetchData(t *testing.T) {
t.Run("it successfully retrieves client data", func(t *testing.T) {
ctrl := gomock.NewController(t)
Expand Down Expand Up @@ -241,15 +254,108 @@ func TestClientResourceFetcher_FetchData(t *testing.T) {
})
}

func TestBrandingResourceFetcher_FetchData(t *testing.T) {
t.Run("it successfully generates branding import data", func(t *testing.T) {
fetcher := brandingResourceFetcher{}
func TestClientGrantResourceFetcher_FetchData(t *testing.T) {
t.Run("it successfully retrieves client grant data", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

clientGrantAPI := mock.NewMockClientGrantAPI(ctrl)
clientGrantAPI.EXPECT().
List(gomock.Any(), gomock.Any()).
Return(
&management.ClientGrantList{
List: management.List{
Start: 0,
Limit: 2,
Total: 4,
},
ClientGrants: []*management.ClientGrant{
{
ID: auth0.String("cgr_1"),
ClientID: auth0.String("client-id-1"),
Audience: auth0.String("https://travel0.com/api"),
},
{
ID: auth0.String("cgr_2"),
ClientID: auth0.String("client-id-2"),
Audience: auth0.String("https://travel0.com/api"),
},
},
},
nil,
)
clientGrantAPI.EXPECT().
List(gomock.Any(), gomock.Any()).
Return(
&management.ClientGrantList{
List: management.List{
Start: 2,
Limit: 4,
Total: 4,
},
ClientGrants: []*management.ClientGrant{
{
ID: auth0.String("cgr_3"),
ClientID: auth0.String("client-id-1"),
Audience: auth0.String("https://travel0.us.auth0.com/api/v2/"),
},
{
ID: auth0.String("cgr_4"),
ClientID: auth0.String("client-id-2"),
Audience: auth0.String("https://travel0.us.auth0.com/api/v2/"),
},
},
},
nil,
)

fetcher := clientGrantResourceFetcher{
api: &auth0.API{
ClientGrant: clientGrantAPI,
},
}

expectedData := importDataList{
{
ResourceName: "auth0_client_grant.client-id-1_httpstravel0comapi",
ImportID: "cgr_1",
},
{
ResourceName: "auth0_client_grant.client-id-2_httpstravel0comapi",
ImportID: "cgr_2",
},
{
ResourceName: "auth0_client_grant.client-id-1_httpstravel0usauth0comapiv2",
ImportID: "cgr_3",
},
{
ResourceName: "auth0_client_grant.client-id-2_httpstravel0usauth0comapiv2",
ImportID: "cgr_4",
},
}

data, err := fetcher.FetchData(context.Background())
assert.NoError(t, err)
assert.Len(t, data, 1)
assert.Equal(t, data[0].ResourceName, "auth0_branding.branding")
assert.Greater(t, len(data[0].ImportID), 0)
assert.Equal(t, expectedData, data)
})

t.Run("it returns an error if api call fails", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

clientGrantAPI := mock.NewMockClientGrantAPI(ctrl)
clientGrantAPI.EXPECT().
List(gomock.Any(), gomock.Any()).
Return(nil, fmt.Errorf("failed to list clients"))

fetcher := clientGrantResourceFetcher{
api: &auth0.API{
ClientGrant: clientGrantAPI,
},
}

_, err := fetcher.FetchData(context.Background())
assert.EqualError(t, err, "failed to list clients")
})
}

Expand Down