From fc523ced93454175436d2c614420c2aa005877b5 Mon Sep 17 00:00:00 2001 From: Rajat Bajaj Date: Thu, 3 Oct 2024 17:33:10 +0530 Subject: [PATCH 1/5] Added cli support to terraform import flow, form and vault connection --- go.mod | 2 +- go.sum | 2 + internal/auth0/auth0.go | 92 ++++++++++++++++--------------- internal/auth0/flow.go | 42 ++++++++++++++ internal/auth0/form.go | 25 +++++++++ internal/cli/terraform.go | 10 +++- internal/cli/terraform_fetcher.go | 68 ++++++++++++++++++++++- 7 files changed, 194 insertions(+), 47 deletions(-) create mode 100644 internal/auth0/flow.go create mode 100644 internal/auth0/form.go diff --git a/go.mod b/go.mod index ab44b8fc7..988c06aa5 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ replace github.com/mholt/archiver/v3 => github.com/anchore/archiver/v3 v3.5.2 require ( github.com/AlecAivazis/survey/v2 v2.3.7 github.com/PuerkitoBio/rehttp v1.4.0 - github.com/auth0/go-auth0 v1.10.0 + github.com/auth0/go-auth0 v1.11.0 github.com/briandowns/spinner v1.23.1 github.com/charmbracelet/glamour v0.8.0 github.com/fsnotify/fsnotify v1.7.0 diff --git a/go.sum b/go.sum index 3d1f71fbe..8b970eaeb 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/auth0/go-auth0 v1.10.0 h1:7fjcuVjtTET5NEg8RPl3uYadGto7WZnBl31LcnXANWc= github.com/auth0/go-auth0 v1.10.0/go.mod h1:VMTiemb4rn2TUPiH9obD2FoHS2FoTALTsnKU0NUXLxk= +github.com/auth0/go-auth0 v1.11.0 h1:gFBVhJCQUW1cET+f/fSH+aXiUebvH2IaaXhMiSaPclw= +github.com/auth0/go-auth0 v1.11.0/go.mod h1:VyYseHsdB4s9jmfBqoxnzJTvZr0w17ZJ5kjNdA+ag9Y= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0 h1:0NmehRCgyk5rljDQLKUO+cRJCnduDyn11+zGZIc9Z48= github.com/aybabtme/iocontrol v0.0.0-20150809002002-ad15bcfc95a0/go.mod h1:6L7zgvqo0idzI7IO8de6ZC051AfXb5ipkIJ7bIA2tGA= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= diff --git a/internal/auth0/auth0.go b/internal/auth0/auth0.go index 737e6a90d..1e8227610 100644 --- a/internal/auth0/auth0.go +++ b/internal/auth0/auth0.go @@ -8,55 +8,61 @@ import ( // API mimics `management.Management`s general interface, except it refers to // the interfaces instead of the concrete structs. type API struct { - Action ActionAPI - Anomaly AnomalyAPI - AttackProtection AttackProtectionAPI - Branding BrandingAPI - BrandingTheme BrandingThemeAPI - Client ClientAPI - ClientGrant ClientGrantAPI - Connection ConnectionAPI - CustomDomain CustomDomainAPI - EmailTemplate EmailTemplateAPI - EmailProvider EmailProviderAPI - Log LogAPI - LogStream LogStreamAPI - Organization OrganizationAPI - Prompt PromptAPI - ResourceServer ResourceServerAPI - Role RoleAPI - Rule RuleAPI - Tenant TenantAPI - User UserAPI - Jobs JobsAPI + Action ActionAPI + Anomaly AnomalyAPI + AttackProtection AttackProtectionAPI + Branding BrandingAPI + BrandingTheme BrandingThemeAPI + Client ClientAPI + ClientGrant ClientGrantAPI + Connection ConnectionAPI + CustomDomain CustomDomainAPI + EmailTemplate EmailTemplateAPI + EmailProvider EmailProviderAPI + Flow FlowAPI + FlowVaultConnection FlowVaultConnectionAPI + Form FormAPI + Log LogAPI + LogStream LogStreamAPI + Organization OrganizationAPI + Prompt PromptAPI + ResourceServer ResourceServerAPI + Role RoleAPI + Rule RuleAPI + Tenant TenantAPI + User UserAPI + Jobs JobsAPI HTTPClient HTTPClientAPI } func NewAPI(m *management.Management) *API { return &API{ - Action: m.Action, - Anomaly: m.Anomaly, - AttackProtection: m.AttackProtection, - Branding: m.Branding, - BrandingTheme: m.BrandingTheme, - Client: m.Client, - ClientGrant: m.ClientGrant, - Connection: m.Connection, - CustomDomain: m.CustomDomain, - EmailTemplate: m.EmailTemplate, - EmailProvider: m.EmailProvider, - Log: m.Log, - LogStream: m.LogStream, - Organization: m.Organization, - Prompt: m.Prompt, - ResourceServer: m.ResourceServer, - Role: m.Role, - Rule: m.Rule, - Tenant: m.Tenant, - User: m.User, - Jobs: m.Job, - HTTPClient: m, + Action: m.Action, + Anomaly: m.Anomaly, + AttackProtection: m.AttackProtection, + Branding: m.Branding, + BrandingTheme: m.BrandingTheme, + Client: m.Client, + ClientGrant: m.ClientGrant, + Connection: m.Connection, + CustomDomain: m.CustomDomain, + EmailTemplate: m.EmailTemplate, + EmailProvider: m.EmailProvider, + Flow: m.Flow, + FlowVaultConnection: m.Flow.Vault, + Form: m.Form, + Log: m.Log, + LogStream: m.LogStream, + Organization: m.Organization, + Prompt: m.Prompt, + ResourceServer: m.ResourceServer, + Role: m.Role, + Rule: m.Rule, + Tenant: m.Tenant, + User: m.User, + Jobs: m.Job, + HTTPClient: m, } } diff --git a/internal/auth0/flow.go b/internal/auth0/flow.go new file mode 100644 index 000000000..31b1d3c08 --- /dev/null +++ b/internal/auth0/flow.go @@ -0,0 +1,42 @@ +//go:generate mockgen -source=flow.go -destination=flow/flow_mock.go -package=mock + +package auth0 + +import ( + "context" + "github.com/auth0/go-auth0/management" +) + +type FlowAPI interface { + // Create a new flow. + Create(ctx context.Context, r *management.Flow, opts ...management.RequestOption) error + + // Read flow details. + Read(ctx context.Context, id string, opts ...management.RequestOption) (r *management.Flow, err error) + + // Update an existing flow. + Update(ctx context.Context, id string, r *management.Flow, opts ...management.RequestOption) error + + // Delete a flow. + Delete(ctx context.Context, id string, opts ...management.RequestOption) error + + // List flow. + List(ctx context.Context, opts ...management.RequestOption) (r *management.FlowList, err error) +} + +type FlowVaultConnectionAPI interface { + // CreateConnection Create a new flow vault connection. + CreateConnection(ctx context.Context, r *management.FlowVaultConnection, opts ...management.RequestOption) error + + // GetConnection Retrieve flow vault connection details. + GetConnection(ctx context.Context, id string, opts ...management.RequestOption) (r *management.FlowVaultConnection, err error) + + // UpdateConnection Update an existing flow vault connection. + UpdateConnection(ctx context.Context, id string, r *management.FlowVaultConnection, opts ...management.RequestOption) error + + // DeleteConnection Delete a flow vault connection. + DeleteConnection(ctx context.Context, id string, opts ...management.RequestOption) error + + // GetConnectionList List flow vault connections. + GetConnectionList(ctx context.Context, opts ...management.RequestOption) (r *management.FlowVaultConnectionList, err error) +} diff --git a/internal/auth0/form.go b/internal/auth0/form.go new file mode 100644 index 000000000..18416a1d0 --- /dev/null +++ b/internal/auth0/form.go @@ -0,0 +1,25 @@ +//go:generate mockgen -source=form.go -destination=form/form_mock.go -package=mock + +package auth0 + +import ( + "context" + "github.com/auth0/go-auth0/management" +) + +type FormAPI interface { + // Create a new form. + Create(ctx context.Context, r *management.Form, opts ...management.RequestOption) error + + // Read form details. + Read(ctx context.Context, id string, opts ...management.RequestOption) (r *management.Form, err error) + + // Update an existing action. + Update(ctx context.Context, id string, r *management.Form, opts ...management.RequestOption) error + + // Delete an action + Delete(ctx context.Context, id string, opts ...management.RequestOption) error + + // List form. + List(ctx context.Context, opts ...management.RequestOption) (r *management.FormList, err error) +} diff --git a/internal/cli/terraform.go b/internal/cli/terraform.go index e00c38900..e25d181e3 100644 --- a/internal/cli/terraform.go +++ b/internal/cli/terraform.go @@ -76,6 +76,12 @@ func (i *terraformInputs) parseResourceFetchers(api *auth0.API) ([]resourceDataF fetchers = append(fetchers, &emailProviderResourceFetcher{api}) case "auth0_email_template": fetchers = append(fetchers, &emailTemplateResourceFetcher{api}) + case "auth0_flow": + fetchers = append(fetchers, &flowResourceFetcher{api}) + case "auth0_flow_vault_connection": + fetchers = append(fetchers, &flowVaultConnectionResourceFetcher{api}) + case "auth0_form": + fetchers = append(fetchers, &formResourceFetcher{api}) case "auth0_guardian": fetchers = append(fetchers, &guardianResourceFetcher{}) case "auth0_log_stream": @@ -273,7 +279,7 @@ func createMainFile(outputDIR string) error { }() fileContent := `terraform { - required_version = "~> 1.5.0" + required_version = ">= 1.5.0" required_providers { auth0 = { source = "auth0/auth0" @@ -329,7 +335,7 @@ func generateTerraformResourceConfig(ctx context.Context, outputDIR string) erro installer := &releases.ExactVersion{ Product: product.Terraform, - Version: version.Must(version.NewVersion("1.5.0")), + Version: version.Must(version.NewVersion("1.8.0")), InstallDir: absoluteOutputPath, } diff --git a/internal/cli/terraform_fetcher.go b/internal/cli/terraform_fetcher.go index 6ec7f1f36..4af16e641 100644 --- a/internal/cli/terraform_fetcher.go +++ b/internal/cli/terraform_fetcher.go @@ -11,7 +11,7 @@ import ( "github.com/auth0/auth0-cli/internal/auth0" ) -var defaultResources = []string{"auth0_action", "auth0_attack_protection", "auth0_branding", "auth0_client", "auth0_client_grant", "auth0_connection", "auth0_custom_domain", "auth0_email_provider", "auth0_email_template", "auth0_guardian", "auth0_organization", "auth0_pages", "auth0_prompt", "auth0_prompt_custom_text", "auth0_resource_server", "auth0_role", "auth0_tenant", "auth0_trigger_actions"} +var defaultResources = []string{"auth0_action", "auth0_attack_protection", "auth0_branding", "auth0_client", "auth0_client_grant", "auth0_connection", "auth0_custom_domain", "auth0_flow", "auth0_flow_vault_connection", "auth0_form", "auth0_email_provider", "auth0_email_template", "auth0_guardian", "auth0_organization", "auth0_pages", "auth0_prompt", "auth0_prompt_custom_text", "auth0_resource_server", "auth0_role", "auth0_tenant", "auth0_trigger_actions"} type ( importDataList []importDataItem @@ -58,6 +58,18 @@ type ( api *auth0.API } + flowResourceFetcher struct { + api *auth0.API + } + + flowVaultConnectionResourceFetcher struct { + api *auth0.API + } + + formResourceFetcher struct { + api *auth0.API + } + guardianResourceFetcher struct{} logStreamResourceFetcher struct { api *auth0.API @@ -272,6 +284,60 @@ func (f *emailTemplateResourceFetcher) FetchData(ctx context.Context) (importDat return data, nil } +func (f *flowResourceFetcher) FetchData(ctx context.Context) (importDataList, error) { + var data importDataList + + flowList, err := f.api.Flow.List(ctx) + if err != nil { + return data, err + } + + for _, flow := range flowList.Flows { + data = append(data, importDataItem{ + ResourceName: "auth0_flow." + sanitizeResourceName(flow.GetName()), + ImportID: flow.GetID(), + }) + } + + return data, nil +} + +func (f *flowVaultConnectionResourceFetcher) FetchData(ctx context.Context) (importDataList, error) { + var data importDataList + + flowVaultConnectionList, err := f.api.Flow.List(ctx) + if err != nil { + return data, err + } + + for _, flow := range flowVaultConnectionList.Flows { + data = append(data, importDataItem{ + ResourceName: "auth0_flow_vault_connection." + sanitizeResourceName(flow.GetName()), + ImportID: flow.GetID(), + }) + } + + return data, nil +} + +func (f *formResourceFetcher) FetchData(ctx context.Context) (importDataList, error) { + var data importDataList + + forms, err := f.api.Form.List(ctx) + if err != nil { + return data, err + } + + for _, form := range forms.Forms { + data = append(data, importDataItem{ + ResourceName: "auth0_form." + sanitizeResourceName(form.GetName()), + ImportID: form.GetID(), + }) + } + + return data, nil +} + func (f *guardianResourceFetcher) FetchData(_ context.Context) (importDataList, error) { return []importDataItem{ { From 6ae00b5d59493a532a86a116152ccfe77b340d75 Mon Sep 17 00:00:00 2001 From: Rajat Bajaj Date: Thu, 3 Oct 2024 17:45:50 +0530 Subject: [PATCH 2/5] Added docs + updated test case --- docs/auth0_terraform_generate.md | 2 +- internal/auth0/flow.go | 1 + internal/auth0/form.go | 3 ++- internal/cli/terraform_test.go | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/auth0_terraform_generate.md b/docs/auth0_terraform_generate.md index f75e676b3..02a4232a6 100644 --- a/docs/auth0_terraform_generate.md +++ b/docs/auth0_terraform_generate.md @@ -33,7 +33,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_attack_protection,auth0_branding,auth0_client,auth0_client_grant,auth0_connection,auth0_custom_domain,auth0_email_provider,auth0_email_template,auth0_guardian,auth0_organization,auth0_pages,auth0_prompt,auth0_prompt_custom_text,auth0_resource_server,auth0_role,auth0_tenant,auth0_trigger_actions]) + -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_attack_protection,auth0_branding,auth0_client,auth0_client_grant,auth0_connection,auth0_custom_domain,auth0_flow,auth0_flow_vault_connection,auth0_form,auth0_email_provider,auth0_email_template,auth0_guardian,auth0_organization,auth0_pages,auth0_prompt,auth0_prompt_custom_text,auth0_resource_server,auth0_role,auth0_tenant,auth0_trigger_actions]) ``` diff --git a/internal/auth0/flow.go b/internal/auth0/flow.go index 31b1d3c08..106085b98 100644 --- a/internal/auth0/flow.go +++ b/internal/auth0/flow.go @@ -4,6 +4,7 @@ package auth0 import ( "context" + "github.com/auth0/go-auth0/management" ) diff --git a/internal/auth0/form.go b/internal/auth0/form.go index 18416a1d0..ec23c3368 100644 --- a/internal/auth0/form.go +++ b/internal/auth0/form.go @@ -4,6 +4,7 @@ package auth0 import ( "context" + "github.com/auth0/go-auth0/management" ) @@ -17,7 +18,7 @@ type FormAPI interface { // Update an existing action. Update(ctx context.Context, id string, r *management.Form, opts ...management.RequestOption) error - // Delete an action + // Delete an action. Delete(ctx context.Context, id string, opts ...management.RequestOption) error // List form. diff --git a/internal/cli/terraform_test.go b/internal/cli/terraform_test.go index c55f37b9b..fe499c9f4 100644 --- a/internal/cli/terraform_test.go +++ b/internal/cli/terraform_test.go @@ -193,7 +193,7 @@ func assertTerraformMainFileWasGeneratedCorrectly(t *testing.T, outputDIR string assert.NoError(t, err) expectedContent := `terraform { - required_version = "~> 1.5.0" + required_version = ">= 1.5.0" required_providers { auth0 = { source = "auth0/auth0" From e9623b746723f2b5931db7589b58252f9f0f3384 Mon Sep 17 00:00:00 2001 From: Rajat Bajaj Date: Wed, 9 Oct 2024 17:34:12 +0530 Subject: [PATCH 3/5] minor update to version --- internal/cli/terraform.go | 2 +- internal/cli/terraform_fetcher.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/internal/cli/terraform.go b/internal/cli/terraform.go index e25d181e3..973633b28 100644 --- a/internal/cli/terraform.go +++ b/internal/cli/terraform.go @@ -335,7 +335,7 @@ func generateTerraformResourceConfig(ctx context.Context, outputDIR string) erro installer := &releases.ExactVersion{ Product: product.Terraform, - Version: version.Must(version.NewVersion("1.8.0")), + Version: version.Must(version.NewVersion("1.5.0")), InstallDir: absoluteOutputPath, } diff --git a/internal/cli/terraform_fetcher.go b/internal/cli/terraform_fetcher.go index ccc66967e..c908b7b8c 100644 --- a/internal/cli/terraform_fetcher.go +++ b/internal/cli/terraform_fetcher.go @@ -305,15 +305,15 @@ func (f *flowResourceFetcher) FetchData(ctx context.Context) (importDataList, er func (f *flowVaultConnectionResourceFetcher) FetchData(ctx context.Context) (importDataList, error) { var data importDataList - flowVaultConnectionList, err := f.api.Flow.List(ctx) + flowVaultConnectionList, err := f.api.FlowVaultConnection.GetConnectionList(ctx) if err != nil { return data, err } - for _, flow := range flowVaultConnectionList.Flows { + for _, flowVaultConnection := range flowVaultConnectionList.Connections { data = append(data, importDataItem{ - ResourceName: "auth0_flow_vault_connection." + sanitizeResourceName(flow.GetName()), - ImportID: flow.GetID(), + ResourceName: "auth0_flow_vault_connection." + sanitizeResourceName(flowVaultConnection.GetName()), + ImportID: flowVaultConnection.GetID(), }) } From 898ec9ab68f90809e9cb812f49d6c04c47335c0d Mon Sep 17 00:00:00 2001 From: Rajat Bajaj Date: Mon, 14 Oct 2024 11:33:26 +0530 Subject: [PATCH 4/5] Added test cases --- internal/auth0/flow.go | 2 +- internal/auth0/form.go | 2 +- internal/auth0/mock/flow_mock.go | 253 +++++++++++++++++++++++++ internal/auth0/mock/form_mock.go | 133 +++++++++++++ internal/cli/terraform_fetcher_test.go | 147 ++++++++++++++ 5 files changed, 535 insertions(+), 2 deletions(-) create mode 100644 internal/auth0/mock/flow_mock.go create mode 100644 internal/auth0/mock/form_mock.go diff --git a/internal/auth0/flow.go b/internal/auth0/flow.go index 106085b98..ead683485 100644 --- a/internal/auth0/flow.go +++ b/internal/auth0/flow.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=flow.go -destination=flow/flow_mock.go -package=mock +//go:generate mockgen -source=flow.go -destination=mock/flow_mock.go -package=mock package auth0 diff --git a/internal/auth0/form.go b/internal/auth0/form.go index ec23c3368..20d562b42 100644 --- a/internal/auth0/form.go +++ b/internal/auth0/form.go @@ -1,4 +1,4 @@ -//go:generate mockgen -source=form.go -destination=form/form_mock.go -package=mock +//go:generate mockgen -source=form.go -destination=mock/form_mock.go -package=mock package auth0 diff --git a/internal/auth0/mock/flow_mock.go b/internal/auth0/mock/flow_mock.go new file mode 100644 index 000000000..8a0e7c38d --- /dev/null +++ b/internal/auth0/mock/flow_mock.go @@ -0,0 +1,253 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: flow.go + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + management "github.com/auth0/go-auth0/management" + gomock "github.com/golang/mock/gomock" +) + +// MockFlowAPI is a mock of FlowAPI interface. +type MockFlowAPI struct { + ctrl *gomock.Controller + recorder *MockFlowAPIMockRecorder +} + +// MockFlowAPIMockRecorder is the mock recorder for MockFlowAPI. +type MockFlowAPIMockRecorder struct { + mock *MockFlowAPI +} + +// NewMockFlowAPI creates a new mock instance. +func NewMockFlowAPI(ctrl *gomock.Controller) *MockFlowAPI { + mock := &MockFlowAPI{ctrl: ctrl} + mock.recorder = &MockFlowAPIMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFlowAPI) EXPECT() *MockFlowAPIMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockFlowAPI) Create(ctx context.Context, r *management.Flow, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Create", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockFlowAPIMockRecorder) Create(ctx, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockFlowAPI)(nil).Create), varargs...) +} + +// Delete mocks base method. +func (m *MockFlowAPI) Delete(ctx context.Context, id string, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Delete", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockFlowAPIMockRecorder) Delete(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockFlowAPI)(nil).Delete), varargs...) +} + +// List mocks base method. +func (m *MockFlowAPI) List(ctx context.Context, opts ...management.RequestOption) (*management.FlowList, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "List", varargs...) + ret0, _ := ret[0].(*management.FlowList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockFlowAPIMockRecorder) List(ctx interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockFlowAPI)(nil).List), varargs...) +} + +// Read mocks base method. +func (m *MockFlowAPI) Read(ctx context.Context, id string, opts ...management.RequestOption) (*management.Flow, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Read", varargs...) + ret0, _ := ret[0].(*management.Flow) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Read indicates an expected call of Read. +func (mr *MockFlowAPIMockRecorder) Read(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockFlowAPI)(nil).Read), varargs...) +} + +// Update mocks base method. +func (m *MockFlowAPI) Update(ctx context.Context, id string, r *management.Flow, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Update", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockFlowAPIMockRecorder) Update(ctx, id, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockFlowAPI)(nil).Update), varargs...) +} + +// MockFlowVaultConnectionAPI is a mock of FlowVaultConnectionAPI interface. +type MockFlowVaultConnectionAPI struct { + ctrl *gomock.Controller + recorder *MockFlowVaultConnectionAPIMockRecorder +} + +// MockFlowVaultConnectionAPIMockRecorder is the mock recorder for MockFlowVaultConnectionAPI. +type MockFlowVaultConnectionAPIMockRecorder struct { + mock *MockFlowVaultConnectionAPI +} + +// NewMockFlowVaultConnectionAPI creates a new mock instance. +func NewMockFlowVaultConnectionAPI(ctrl *gomock.Controller) *MockFlowVaultConnectionAPI { + mock := &MockFlowVaultConnectionAPI{ctrl: ctrl} + mock.recorder = &MockFlowVaultConnectionAPIMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFlowVaultConnectionAPI) EXPECT() *MockFlowVaultConnectionAPIMockRecorder { + return m.recorder +} + +// CreateConnection mocks base method. +func (m *MockFlowVaultConnectionAPI) CreateConnection(ctx context.Context, r *management.FlowVaultConnection, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "CreateConnection", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateConnection indicates an expected call of CreateConnection. +func (mr *MockFlowVaultConnectionAPIMockRecorder) CreateConnection(ctx, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConnection", reflect.TypeOf((*MockFlowVaultConnectionAPI)(nil).CreateConnection), varargs...) +} + +// DeleteConnection mocks base method. +func (m *MockFlowVaultConnectionAPI) DeleteConnection(ctx context.Context, id string, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "DeleteConnection", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteConnection indicates an expected call of DeleteConnection. +func (mr *MockFlowVaultConnectionAPIMockRecorder) DeleteConnection(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConnection", reflect.TypeOf((*MockFlowVaultConnectionAPI)(nil).DeleteConnection), varargs...) +} + +// GetConnection mocks base method. +func (m *MockFlowVaultConnectionAPI) GetConnection(ctx context.Context, id string, opts ...management.RequestOption) (*management.FlowVaultConnection, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "GetConnection", varargs...) + ret0, _ := ret[0].(*management.FlowVaultConnection) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetConnection indicates an expected call of GetConnection. +func (mr *MockFlowVaultConnectionAPIMockRecorder) GetConnection(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConnection", reflect.TypeOf((*MockFlowVaultConnectionAPI)(nil).GetConnection), varargs...) +} + +// GetConnectionList mocks base method. +func (m *MockFlowVaultConnectionAPI) GetConnectionList(ctx context.Context, opts ...management.RequestOption) (*management.FlowVaultConnectionList, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "GetConnectionList", varargs...) + ret0, _ := ret[0].(*management.FlowVaultConnectionList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetConnectionList indicates an expected call of GetConnectionList. +func (mr *MockFlowVaultConnectionAPIMockRecorder) GetConnectionList(ctx interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConnectionList", reflect.TypeOf((*MockFlowVaultConnectionAPI)(nil).GetConnectionList), varargs...) +} + +// UpdateConnection mocks base method. +func (m *MockFlowVaultConnectionAPI) UpdateConnection(ctx context.Context, id string, r *management.FlowVaultConnection, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "UpdateConnection", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateConnection indicates an expected call of UpdateConnection. +func (mr *MockFlowVaultConnectionAPIMockRecorder) UpdateConnection(ctx, id, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConnection", reflect.TypeOf((*MockFlowVaultConnectionAPI)(nil).UpdateConnection), varargs...) +} diff --git a/internal/auth0/mock/form_mock.go b/internal/auth0/mock/form_mock.go new file mode 100644 index 000000000..73161402a --- /dev/null +++ b/internal/auth0/mock/form_mock.go @@ -0,0 +1,133 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: form.go + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + reflect "reflect" + + management "github.com/auth0/go-auth0/management" + gomock "github.com/golang/mock/gomock" +) + +// MockFormAPI is a mock of FormAPI interface. +type MockFormAPI struct { + ctrl *gomock.Controller + recorder *MockFormAPIMockRecorder +} + +// MockFormAPIMockRecorder is the mock recorder for MockFormAPI. +type MockFormAPIMockRecorder struct { + mock *MockFormAPI +} + +// NewMockFormAPI creates a new mock instance. +func NewMockFormAPI(ctrl *gomock.Controller) *MockFormAPI { + mock := &MockFormAPI{ctrl: ctrl} + mock.recorder = &MockFormAPIMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockFormAPI) EXPECT() *MockFormAPIMockRecorder { + return m.recorder +} + +// Create mocks base method. +func (m *MockFormAPI) Create(ctx context.Context, r *management.Form, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Create", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Create indicates an expected call of Create. +func (mr *MockFormAPIMockRecorder) Create(ctx, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockFormAPI)(nil).Create), varargs...) +} + +// Delete mocks base method. +func (m *MockFormAPI) Delete(ctx context.Context, id string, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Delete", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Delete indicates an expected call of Delete. +func (mr *MockFormAPIMockRecorder) Delete(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Delete", reflect.TypeOf((*MockFormAPI)(nil).Delete), varargs...) +} + +// List mocks base method. +func (m *MockFormAPI) List(ctx context.Context, opts ...management.RequestOption) (*management.FormList, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "List", varargs...) + ret0, _ := ret[0].(*management.FormList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// List indicates an expected call of List. +func (mr *MockFormAPIMockRecorder) List(ctx interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "List", reflect.TypeOf((*MockFormAPI)(nil).List), varargs...) +} + +// Read mocks base method. +func (m *MockFormAPI) Read(ctx context.Context, id string, opts ...management.RequestOption) (*management.Form, error) { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Read", varargs...) + ret0, _ := ret[0].(*management.Form) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Read indicates an expected call of Read. +func (mr *MockFormAPIMockRecorder) Read(ctx, id interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Read", reflect.TypeOf((*MockFormAPI)(nil).Read), varargs...) +} + +// Update mocks base method. +func (m *MockFormAPI) Update(ctx context.Context, id string, r *management.Form, opts ...management.RequestOption) error { + m.ctrl.T.Helper() + varargs := []interface{}{ctx, id, r} + for _, a := range opts { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Update", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Update indicates an expected call of Update. +func (mr *MockFormAPIMockRecorder) Update(ctx, id, r interface{}, opts ...interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]interface{}{ctx, id, r}, opts...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockFormAPI)(nil).Update), varargs...) +} diff --git a/internal/cli/terraform_fetcher_test.go b/internal/cli/terraform_fetcher_test.go index 4466266eb..aa7931459 100644 --- a/internal/cli/terraform_fetcher_test.go +++ b/internal/cli/terraform_fetcher_test.go @@ -563,6 +563,153 @@ func TestCustomDomainResourceFetcher_FetchData(t *testing.T) { }) } +func TestFormResourceFetcher_FetchData(t *testing.T) { + t.Run("it successfully generates form import data", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + formAPI := mock.NewMockFormAPI(ctrl) + formAPI.EXPECT(). + List(gomock.Any(), gomock.Any()).Return( + &management.FormList{ + List: management.List{ + Start: 0, + Limit: 1, + Total: 2, + }, + Forms: []*management.Form{ + { + ID: auth0.String("form_id1"), + Name: auth0.String("Form 1"), + }, + { + ID: auth0.String("form_id2"), + Name: auth0.String("Form 2"), + }, + }, + }, nil) + + fetcher := formResourceFetcher{ + api: &auth0.API{ + Form: formAPI, + }, + } + + expectedData := importDataList{ + { + ResourceName: "auth0_form.form_1", + ImportID: "form_id1", + }, + { + ResourceName: "auth0_form.form_2", + ImportID: "form_id2", + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, data) + }) +} + +func TestFlowResourceFetcher_FetchData(t *testing.T) { + t.Run("it successfully generates form import data", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowAPI := mock.NewMockFlowAPI(ctrl) + flowAPI.EXPECT(). + List(gomock.Any(), gomock.Any()).Return( + &management.FlowList{ + List: management.List{ + Start: 0, + Limit: 1, + Total: 2, + }, + Flows: []*management.Flow{ + { + ID: auth0.String("flow_id1"), + Name: auth0.String("Flow 1"), + }, + { + ID: auth0.String("flow_id2"), + Name: auth0.String("Flow 2"), + }, + }, + }, nil) + + fetcher := flowResourceFetcher{ + api: &auth0.API{ + Flow: flowAPI, + }, + } + + expectedData := importDataList{ + { + ResourceName: "auth0_flow.flow_1", + ImportID: "flow_id1", + }, + { + ResourceName: "auth0_flow.flow_2", + ImportID: "flow_id2", + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, data) + }) +} + +func TestFlowVaultConnectionResourceFetcher_FetchData(t *testing.T) { + t.Run("it successfully generates form import data", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowVaultAPI := mock.NewMockFlowVaultConnectionAPI(ctrl) + flowVaultAPI.EXPECT(). + GetConnectionList(gomock.Any()).Return( + &management.FlowVaultConnectionList{ + List: management.List{ + Start: 0, + Limit: 1, + Total: 2, + }, + Connections: []*management.FlowVaultConnection{ + { + ID: auth0.String("flow_vault_connection1"), + Name: auth0.String("Flow Vault Connection 1"), + }, + { + ID: auth0.String("flow_vault_connection2"), + Name: auth0.String("Flow Vault Connection 2"), + }, + }, + }, nil) + + fetcher := flowVaultConnectionResourceFetcher{ + api: &auth0.API{ + FlowVaultConnection: flowVaultAPI, + }, + } + + expectedData := importDataList{ + { + ResourceName: "auth0_flow_vault_connection.flow_vault_connection_1", + ImportID: "flow_vault_connection1", + }, + { + ResourceName: "auth0_flow_vault_connection.flow_vault_connection_2", + ImportID: "flow_vault_connection2", + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Equal(t, expectedData, data) + }) +} + func TestGuardianResourceFetcher_FetchData(t *testing.T) { t.Run("it successfully generates pages guardian data", func(t *testing.T) { fetcher := guardianResourceFetcher{} From e633cc8e287b59f002b56c8a7b42b100ccb98358 Mon Sep 17 00:00:00 2001 From: Rajat Bajaj Date: Mon, 14 Oct 2024 12:28:55 +0530 Subject: [PATCH 5/5] Added negative testing --- internal/cli/terraform_fetcher_test.go | 138 +++++++++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/internal/cli/terraform_fetcher_test.go b/internal/cli/terraform_fetcher_test.go index aa7931459..9b6dda9cf 100644 --- a/internal/cli/terraform_fetcher_test.go +++ b/internal/cli/terraform_fetcher_test.go @@ -610,6 +610,52 @@ func TestFormResourceFetcher_FetchData(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedData, data) }) + + t.Run("it successfully returns empty import list", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + formAPI := mock.NewMockFormAPI(ctrl) + formAPI.EXPECT(). + List(gomock.Any(), gomock.Any()).Return( + &management.FormList{ + List: management.List{ + Start: 0, + Limit: 0, + Total: 0, + }, + Forms: []*management.Form{}, + }, nil) + + fetcher := formResourceFetcher{ + api: &auth0.API{ + Form: formAPI, + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Nil(t, data) + }) + + t.Run("it returns an error if api call fails", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + formAPI := mock.NewMockFormAPI(ctrl) + formAPI.EXPECT(). + List(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("failed to read form")) + + fetcher := formResourceFetcher{ + api: &auth0.API{ + Form: formAPI, + }, + } + + _, err := fetcher.FetchData(context.Background()) + assert.EqualError(t, err, "failed to read form") + }) } func TestFlowResourceFetcher_FetchData(t *testing.T) { @@ -659,6 +705,52 @@ func TestFlowResourceFetcher_FetchData(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedData, data) }) + + t.Run("it successfully returns empty import list", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowAPI := mock.NewMockFlowAPI(ctrl) + flowAPI.EXPECT(). + List(gomock.Any(), gomock.Any()).Return( + &management.FlowList{ + List: management.List{ + Start: 0, + Limit: 0, + Total: 0, + }, + Flows: []*management.Flow{}, + }, nil) + + fetcher := flowResourceFetcher{ + api: &auth0.API{ + Flow: flowAPI, + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Nil(t, data) + }) + + t.Run("it returns an error if api call fails", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowAPI := mock.NewMockFlowAPI(ctrl) + flowAPI.EXPECT(). + List(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("failed to read flow")) + + fetcher := flowResourceFetcher{ + api: &auth0.API{ + Flow: flowAPI, + }, + } + + _, err := fetcher.FetchData(context.Background()) + assert.EqualError(t, err, "failed to read flow") + }) } func TestFlowVaultConnectionResourceFetcher_FetchData(t *testing.T) { @@ -708,6 +800,52 @@ func TestFlowVaultConnectionResourceFetcher_FetchData(t *testing.T) { assert.NoError(t, err) assert.Equal(t, expectedData, data) }) + + t.Run("it successfully returns empty import list", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowVaultAPI := mock.NewMockFlowVaultConnectionAPI(ctrl) + flowVaultAPI.EXPECT(). + GetConnectionList(gomock.Any()).Return( + &management.FlowVaultConnectionList{ + List: management.List{ + Start: 0, + Limit: 0, + Total: 0, + }, + Connections: []*management.FlowVaultConnection{}, + }, nil) + + fetcher := flowVaultConnectionResourceFetcher{ + api: &auth0.API{ + FlowVaultConnection: flowVaultAPI, + }, + } + + data, err := fetcher.FetchData(context.Background()) + assert.NoError(t, err) + assert.Nil(t, data) + }) + + t.Run("it returns an error if api call fails", func(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + flowVaultConnectionAPI := mock.NewMockFlowVaultConnectionAPI(ctrl) + flowVaultConnectionAPI.EXPECT(). + GetConnectionList(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("failed to read flow connection")) + + fetcher := flowVaultConnectionResourceFetcher{ + api: &auth0.API{ + FlowVaultConnection: flowVaultConnectionAPI, + }, + } + + _, err := fetcher.FetchData(context.Background()) + assert.EqualError(t, err, "failed to read flow connection") + }) } func TestGuardianResourceFetcher_FetchData(t *testing.T) {