From 7623995320536e716e3b1ea615e3d2a1800fe8a6 Mon Sep 17 00:00:00 2001 From: magodo Date: Wed, 25 Oct 2023 13:57:16 +0800 Subject: [PATCH] Update tfadd to make azapi export more useful & UI adpotion for azapi --- command_before_func.go | 2 +- go.mod | 2 +- go.sum | 4 +-- internal/meta/base_meta.go | 25 ++++++++++++++++--- internal/meta/meta_dummy.go | 11 +++++--- internal/run.go | 2 +- internal/ui/importlist/importlist.go | 18 ++++++++++--- internal/ui/importlist/importlist_delegate.go | 16 +++++++++--- internal/ui/ui.go | 2 +- main.go | 3 ++- pkg/config/config.go | 4 +-- 11 files changed, 65 insertions(+), 24 deletions(-) diff --git a/command_before_func.go b/command_before_func.go index 5f78429..73143a4 100644 --- a/command_before_func.go +++ b/command_before_func.go @@ -172,7 +172,7 @@ The output directory is not empty. Please choose one of actions below: if err != nil { return fmt.Errorf("loading terraform config: %v", err) } - if azurecfg, ok := module.RequiredProviders["azurerm"]; ok { + if azurecfg, ok := module.RequiredProviders[fset.flagProviderName]; ok { fset.flagProviderVersion = strings.Join(azurecfg.VersionConstraints, " ") } } diff --git a/go.mod b/go.mod index bd6a537..0951f86 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/magodo/spinner v0.0.0-20220720073946-50f31b2dc5a6 github.com/magodo/terraform-client-go v0.0.0-20230323074119-02ceb732dd25 github.com/magodo/textinput v0.0.0-20210913072708-7d24f2b4b0c0 - github.com/magodo/tfadd v0.10.1-0.20231024014800-2f2cdcd2fe1c + github.com/magodo/tfadd v0.10.1-0.20231025052212-d9c6bf90d0f2 github.com/magodo/tfmerge v0.0.0-20221214062955-f52e46d03402 github.com/magodo/tfstate v0.0.0-20220409052014-9b9568dda918 github.com/magodo/workerpool v0.0.0-20230119025400-40192d2716ea diff --git a/go.sum b/go.sum index 2649f08..ed92b6c 100644 --- a/go.sum +++ b/go.sum @@ -236,8 +236,8 @@ github.com/magodo/terraform-client-go v0.0.0-20230323074119-02ceb732dd25 h1:V4R1 github.com/magodo/terraform-client-go v0.0.0-20230323074119-02ceb732dd25/go.mod h1:L12osIvZuDH0/UzrWn3+kiBRXDFTuoYaqF7UfTsbbQA= github.com/magodo/textinput v0.0.0-20210913072708-7d24f2b4b0c0 h1:aNtr4iNv/tex2t8W1u3scAoNHEnFlTKhNNHOpYStqbs= github.com/magodo/textinput v0.0.0-20210913072708-7d24f2b4b0c0/go.mod h1:MqYhNP+PC386Bjsx5piZe7T4vDm5QIPv8b1RU0prVnU= -github.com/magodo/tfadd v0.10.1-0.20231024014800-2f2cdcd2fe1c h1:S6a0oeGahKw4u9Sq2mrOsViolpbCcTokf9IgWAQYXpE= -github.com/magodo/tfadd v0.10.1-0.20231024014800-2f2cdcd2fe1c/go.mod h1:6W2btqbRymCIrUhOlqrBgr/CyCa6lzNvs6fypoveye0= +github.com/magodo/tfadd v0.10.1-0.20231025052212-d9c6bf90d0f2 h1:B9LMnFVPXNF1R0iGOWivYYq1CNPl8V2DUG9QVnaCQmo= +github.com/magodo/tfadd v0.10.1-0.20231025052212-d9c6bf90d0f2/go.mod h1:6W2btqbRymCIrUhOlqrBgr/CyCa6lzNvs6fypoveye0= github.com/magodo/tfmerge v0.0.0-20221214062955-f52e46d03402 h1:RyaR4VE7hoR9AyoVH414cpM8V63H4rLe2aZyKdoDV1w= github.com/magodo/tfmerge v0.0.0-20221214062955-f52e46d03402/go.mod h1:ssV++b4DH33rsD592bvpS4Peng3ZfdGNZbFgCDkCfj8= github.com/magodo/tfpluginschema v0.0.0-20220905090502-2d6a05ebaefd h1:L0kTduNwpx60EdBPYOVF9oUY7jdfZHIncvQN490qWd4= diff --git a/internal/meta/base_meta.go b/internal/meta/base_meta.go index 9d88159..31c2ab6 100644 --- a/internal/meta/base_meta.go +++ b/internal/meta/base_meta.go @@ -34,6 +34,7 @@ import ( tfclient "github.com/magodo/terraform-client-go/tfclient" "github.com/magodo/terraform-client-go/tfclient/configschema" "github.com/magodo/terraform-client-go/tfclient/typ" + "github.com/magodo/tfadd/providers/azapi" "github.com/magodo/tfadd/providers/azurerm" "github.com/magodo/tfadd/tfadd" "github.com/magodo/tfmerge/tfmerge" @@ -48,6 +49,8 @@ const SkippedResourcesFileName = "aztfexportSkippedResources.txt" type TFConfigTransformer func(configs ConfigInfos) (ConfigInfos, error) type BaseMeta interface { + // ProviderName returns the target provider name, which is either azurerm or azapi. + ProviderName() string // Init initializes the base meta, including initialize terraform, provider and soem runtime temporary resources. Init(ctx context.Context) error // DeInit deinitializes the base meta, including cleaning up runtime temporary resources. @@ -189,8 +192,13 @@ func NewBaseMeta(cfg config.CommonConfig) (*baseMeta, error) { tc = telemetry.NewNullClient() } - if !cfg.DevProvider && cfg.ProviderVersion == "" && cfg.ProviderName == "azurerm" { - cfg.ProviderVersion = azurerm.ProviderSchemaInfo.Version + if !cfg.DevProvider && cfg.ProviderVersion == "" { + switch cfg.ProviderName { + case "azurerm": + cfg.ProviderVersion = azurerm.ProviderSchemaInfo.Version + case "azapi": + cfg.ProviderVersion = azapi.ProviderSchemaInfo.Version + } } meta := &baseMeta{ @@ -220,6 +228,10 @@ func NewBaseMeta(cfg config.CommonConfig) (*baseMeta, error) { return meta, nil } +func (meta baseMeta) ProviderName() string { + return meta.providerName +} + func (meta baseMeta) Workspace() string { return meta.outdir } @@ -529,7 +541,7 @@ func (meta *baseMeta) buildTerraformConfig(backendType string) string { providerSource := "hashicorp/azurerm" if meta.useAzAPI() { - providerSource = "Azure/azapi" + providerSource = "azure/azapi" } providerVersionLine := "" @@ -881,6 +893,11 @@ func (meta baseMeta) stateToConfig(ctx context.Context, list ImportList) (Config importedList := list.Imported() + providerName := "registry.terraform.io/hashicorp/azurerm" + if meta.useAzAPI() { + providerName = "registry.terraform.io/azure/azapi" + } + if meta.tfclient != nil { for _, item := range importedList { schResp, diags := meta.tfclient.GetProviderSchema() @@ -897,7 +914,7 @@ func (meta baseMeta) stateToConfig(ctx context.Context, list ImportList) (Config Mode: tfjson.ManagedResourceMode, Address: item.TFAddr.String(), Type: item.TFAddr.Type, - ProviderName: "registry.terraform.io/hashicorp/azurerm", + ProviderName: providerName, Value: item.State, }, meta.fullConfig) diff --git a/internal/meta/meta_dummy.go b/internal/meta/meta_dummy.go index 8d4c5b6..4405be4 100644 --- a/internal/meta/meta_dummy.go +++ b/internal/meta/meta_dummy.go @@ -6,11 +6,16 @@ import ( ) type MetaGroupDummy struct { - rg string + rg string + providerName string } -func NewGroupMetaDummy(rg string) MetaGroupDummy { - return MetaGroupDummy{rg: rg} +func NewGroupMetaDummy(rg string, providerName string) MetaGroupDummy { + return MetaGroupDummy{rg: rg, providerName: providerName} +} + +func (m MetaGroupDummy) ProviderName() string { + return m.providerName } func (m MetaGroupDummy) Init(_ context.Context) error { diff --git a/internal/run.go b/internal/run.go index e151274..1ba9149 100644 --- a/internal/run.go +++ b/internal/run.go @@ -17,7 +17,7 @@ import ( ) func BatchImport(ctx context.Context, cfg config.NonInteractiveModeConfig) error { - var c meta.Meta = internalmeta.NewGroupMetaDummy(cfg.ResourceGroupName) + var c meta.Meta = internalmeta.NewGroupMetaDummy(cfg.ResourceGroupName, cfg.ProviderName) if !cfg.MockMeta { var err error c, err = meta.NewMeta(cfg.Config) diff --git a/internal/ui/importlist/importlist.go b/internal/ui/importlist/importlist.go index e10f8f0..636bd6b 100644 --- a/internal/ui/importlist/importlist.go +++ b/internal/ui/importlist/importlist.go @@ -3,12 +3,13 @@ package importlist import ( "context" "fmt" - "github.com/Azure/aztfexport/pkg/meta" "regexp" "sort" "strings" "time" + "github.com/Azure/aztfexport/pkg/meta" + "github.com/Azure/aztfexport/internal/tfaddr" "github.com/Azure/aztfexport/internal/ui/aztfexportclient" "github.com/Azure/aztfexport/internal/ui/common" @@ -17,7 +18,9 @@ import ( "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/magodo/textinput" + "github.com/magodo/tfadd/providers/azapi" "github.com/magodo/tfadd/providers/azurerm" + "github.com/magodo/tfadd/schema" ) type Model struct { @@ -30,8 +33,15 @@ type Model struct { func NewModel(ctx context.Context, c meta.Meta, l meta.ImportList, idx int) Model { // Build candidate words for the textinput - candidates := make([]string, 0, len(azurerm.ProviderSchemaInfo.ResourceSchemas)) - for rt := range azurerm.ProviderSchemaInfo.ResourceSchemas { + var resourceSchemas map[string]*schema.Schema + switch c.ProviderName() { + case "azapi": + resourceSchemas = azapi.ProviderSchemaInfo.ResourceSchemas + case "azurerm": + resourceSchemas = azurerm.ProviderSchemaInfo.ResourceSchemas + } + candidates := make([]string, 0, len(resourceSchemas)) + for rt := range resourceSchemas { candidates = append(candidates, rt) } sort.Strings(candidates) @@ -52,7 +62,7 @@ func NewModel(ctx context.Context, c meta.Meta, l meta.ImportList, idx int) Mode }) } - lst := list.NewModel(items, NewImportItemDelegate(), 0, 0) + lst := list.NewModel(items, NewImportItemDelegate(c.ProviderName()), 0, 0) lst.Title = " " + c.ScopeName() + " " lst.Styles.Title = common.SubtitleStyle lst.StatusMessageLifetime = 3 * time.Second diff --git a/internal/ui/importlist/importlist_delegate.go b/internal/ui/importlist/importlist_delegate.go index 6273807..94b8a66 100644 --- a/internal/ui/importlist/importlist_delegate.go +++ b/internal/ui/importlist/importlist_delegate.go @@ -8,13 +8,14 @@ import ( "github.com/Azure/aztfexport/internal/ui/aztfexportclient" "github.com/Azure/aztfexport/internal/ui/common" + "github.com/magodo/tfadd/providers/azapi" "github.com/magodo/tfadd/providers/azurerm" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" ) -func NewImportItemDelegate() list.ItemDelegate { +func NewImportItemDelegate(providerName string) list.ItemDelegate { d := list.NewDefaultDelegate() d.UpdateFunc = func(msg tea.Msg, m *list.Model) (ret tea.Cmd) { sel := m.SelectedItem() @@ -73,7 +74,7 @@ func NewImportItemDelegate() list.ItemDelegate { selItem.textinput.Blur() // Validate the input and update the selItem.v - addr, err := parseInput(selItem.textinput.Value()) + addr, err := parseInput(selItem.textinput.Value(), providerName) if err != nil { cmd := m.NewStatusMessage(common.ErrorMsgStyle.Render(err.Error())) cmds = append(cmds, cmd) @@ -147,7 +148,7 @@ func setListKeyMapEnabled(m *list.Model, enabled bool) { } } -func parseInput(input string) (*tfaddr.TFAddr, error) { +func parseInput(input string, providerName string) (*tfaddr.TFAddr, error) { v := strings.TrimSpace(input) if v == "" { return &tfaddr.TFAddr{}, nil @@ -158,7 +159,14 @@ func parseInput(input string) (*tfaddr.TFAddr, error) { return nil, err } - if _, ok := azurerm.ProviderSchemaInfo.ResourceSchemas[addr.Type]; !ok { + var ok bool + switch providerName { + case "azurerm": + _, ok = azurerm.ProviderSchemaInfo.ResourceSchemas[addr.Type] + case "azapi": + _, ok = azapi.ProviderSchemaInfo.ResourceSchemas[addr.Type] + } + if !ok { return nil, fmt.Errorf("Invalid resource type %q", addr.Type) } diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 4cef6de..6259fbd 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -89,7 +89,7 @@ func newModel(ctx context.Context, cfg config.InteractiveModeConfig) (*model, er s := spinner.NewModel() s.Spinner = common.Spinner - var c meta.Meta = internalmeta.NewGroupMetaDummy(cfg.ResourceGroupName) + var c meta.Meta = internalmeta.NewGroupMetaDummy(cfg.ResourceGroupName, cfg.ProviderName) if !cfg.MockMeta { var err error c, err = meta.NewMeta(cfg.Config) diff --git a/main.go b/main.go index dc07ef7..d1fbc70 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,7 @@ import ( "github.com/hashicorp/go-hclog" "github.com/magodo/armid" "github.com/magodo/azlist/azlist" + "github.com/magodo/tfadd/providers/azapi" "github.com/magodo/tfadd/providers/azurerm" "github.com/Azure/aztfexport/internal" @@ -153,7 +154,7 @@ func main() { &cli.StringFlag{ Name: "provider-version", EnvVars: []string{"AZTFEXPORT_PROVIDER_VERSION"}, - Usage: fmt.Sprintf("The provider version to use for importing. Defaults to %q for azurerm, defaults to the latest version for azapi", azurerm.ProviderSchemaInfo.Version), + Usage: fmt.Sprintf("The provider version to use for importing. Defaults to %q for azurerm, %s for azapi", azurerm.ProviderSchemaInfo.Version, azapi.ProviderSchemaInfo.Version), Destination: &flagset.flagProviderVersion, }, &cli.StringFlag{ diff --git a/pkg/config/config.go b/pkg/config/config.go index 9ac7e6c..53ea70b 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -30,7 +30,7 @@ type CommonConfig struct { OutputDir string // OutputFileNames specifies the output terraform filenames OutputFileNames OutputFileNames - // ProviderVersion specifies the azurerm provider version used for importing. If this is not set, it will use `azurerm.ProviderSchemaInfo.Version` for importing in order to be consistent with tfadd. + // ProviderVersion specifies the provider version used for importing. If this is not set, it will use `{azurerm|azapi}.ProviderSchemaInfo.Version` for importing in order to be consistent with tfadd. ProviderVersion string // DevProvider specifies whether users have configured the `dev_overrides` for the provider, which then uses a development provider built locally rather than using a version pinned provider from official Terraform registry. // Meanwhile, it will also avoid running `terraform init` during `Init()` for the import directories to avoid caculating the provider hash and populating the lock file (See: https://developer.hashicorp.com/terraform/language/files/dependency-lock). Though the init for the output directory is still needed for initializing the backend. @@ -43,7 +43,7 @@ type CommonConfig struct { BackendType string // BackendConfig specifies an array of Terraform backend configs. BackendConfig []string - // ProviderConfig specifies key value pairs that will be expanded to the terraform-provider-azurerm settings (i.e. `azurerm {}` block) + // ProviderConfig specifies key value pairs that will be expanded to the terraform-provider-{azurerm|azapi} settings (e.g. `azurerm {}` block) // Currently, only the attributes (rather than blocks) are supported. // This is not used directly by aztfexport as the provider configs can be set by environment variable already. // While it is useful for module users that want support multi-users scenarios in one process (in which case changing env vars affect the whole process).