From 39e953ae65951f4f4b74a1002ec72c81b6c9f7b1 Mon Sep 17 00:00:00 2001 From: magodo Date: Fri, 28 Jan 2022 13:45:09 +0800 Subject: [PATCH] Resource with exactly one match will be filled in by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The resource IDs which has exactly one recommendation will now be automatically filled in by the TF resource type on the first launch. The line is prefixed by 💡 as an indicator. The following edits on such lines will clear that 💡. --- README.md | 4 ++-- internal/meta/importlist.go | 8 +++++++- internal/ui/common/common.go | 1 + internal/ui/importlist/importlist.go | 11 +++++++++++ internal/ui/importlist/importlist_delegate.go | 10 ++++++++++ internal/ui/importlist/item.go | 8 +++++--- 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5c69035..fd6cd8a 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,11 @@ aztfy [option] The tool will list all the resources resides in the specified resource group. -For each resource, `aztfy` will ask the user to input the Terraform resource type for each Azure resource (e.g. `azurerm_linux_virtual_machine`). Users can press `r` to see the possible resource type for the selected import item, though this is not guaranteed to be 100% accurate. +For each resource, `aztfy` will ask the user to input the Terraform resource type for each Azure resource (e.g. `azurerm_linux_virtual_machine`). Users can press `r` to see the possible resource type for the selected import item, though this is not guaranteed to be 100% accurate. In case there is exactly one resource type match for the import item, that resource type will be automatically be filled in the text input for the users, with a 💡 line prefix as an indication. In some cases, there are Azure resources that have no corresponding Terraform resource (e.g. due to lacks of Terraform support), or some resource might be created as a side effect of provisioning another resource (e.g. the Disk resource is created automatically when provisioning a VM). In these cases, you can skip these resources without typing anything. -After getting the input from user, `aztfy` will run `terraform import` under the hood to import each resource. Then it will run `terraform add -from-state` to generate the Terraform template for each imported resource. Whereas there are kinds of [limitations](https://github.com/apparentlymart/terrafy/blob/main/docs/quirks.md) causing the output of `terraform add` to be an invalid Terraform template in most cases. `aztfy` will leverage extra knowledge from the provider (which is generated from the provider codebase) to further manipulate the template, to make it pass the Terraform validations against the provider. +After going through all the resources to be imported, users press `w` to proceed.`aztfy` will run `terraform import` under the hood to import each resource. Then it will run `terraform add -from-state` to generate the Terraform template for each imported resource. Whereas there are kinds of [limitations](https://github.com/apparentlymart/terrafy/blob/main/docs/quirks.md) causing the output of `terraform add` to be an invalid Terraform template in most cases. `aztfy` will leverage extra knowledge from the provider (which is generated from the provider codebase) to further manipulate the template, to make it pass the Terraform validations against the provider. As the last step, `aztfy` will leverage the ARM template to inject dependencies between each resource. This makes the generated Terraform template to be useful. diff --git a/internal/meta/importlist.go b/internal/meta/importlist.go index c5935d7..9da94fa 100644 --- a/internal/meta/importlist.go +++ b/internal/meta/importlist.go @@ -1,5 +1,8 @@ package meta +// TFResourceTypeSkip is a special resource type which represents to skip this resource from importing. +const TFResourceTypeSkip string = "Skip" + type ImportItem struct { // The azure resource id ResourceID string @@ -18,10 +21,13 @@ type ImportItem struct { // The terraform resource name TFResourceName string + + // Whether this TF resource type is from recommendation + IsRecommended bool } func (item ImportItem) Skip() bool { - return item.TFResourceType == "" + return item.TFResourceType == TFResourceTypeSkip } func (item *ImportItem) TFAddr() string { diff --git a/internal/ui/common/common.go b/internal/ui/common/common.go index 4e6b724..760fefe 100644 --- a/internal/ui/common/common.go +++ b/internal/ui/common/common.go @@ -7,6 +7,7 @@ import ( const ErrorEmoji = "❗️" const WarningEmoji = "❓" const OKEmoji = "✅" +const BulbEmoji = "💡" // Colors for dark and light backgrounds. var ( diff --git a/internal/ui/importlist/importlist.go b/internal/ui/importlist/importlist.go index 631584b..608821f 100644 --- a/internal/ui/importlist/importlist.go +++ b/internal/ui/importlist/importlist.go @@ -43,6 +43,17 @@ func NewModel(c meta.Meta, l meta.ImportList, idx int) Model { for idx, item := range l { ti := textinput.NewModel() ti.SetCursorMode(textinput.CursorStatic) + + // This only happens on the first time to new the model, where each resource's TFResourceType is empty. + // Later iterations, this is either a concret resource type or the TFResourceTypeSkip. + // For this first iteration, we try to give it a recommendation resource type if there is an exact match, otherwise, set it to TFResourceTypeSkip. + if item.TFResourceType == "" { + item.TFResourceType = meta.TFResourceTypeSkip + if len(recommendations[idx]) == 1 { + item.IsRecommended = true + item.TFResourceType = recommendations[idx][0] + } + } if !item.Skip() { ti.SetValue(item.TFResourceType) } diff --git a/internal/ui/importlist/importlist_delegate.go b/internal/ui/importlist/importlist_delegate.go index aa936d8..3542818 100644 --- a/internal/ui/importlist/importlist_delegate.go +++ b/internal/ui/importlist/importlist_delegate.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/Azure/aztfy/internal/meta" "github.com/Azure/aztfy/internal/ui/aztfyclient" "github.com/Azure/aztfy/internal/ui/common" "github.com/Azure/aztfy/schema" @@ -47,6 +48,9 @@ func NewImportItemDelegate() list.ItemDelegate { selItem.v.Imported = false } + // Clear the is recommended flag that were set. + selItem.v.IsRecommended = false + // "Enter" focus current selected item setListKeyMapEnabled(m, false) cmd := selItem.textinput.Focus() @@ -75,6 +79,12 @@ func NewImportItemDelegate() list.ItemDelegate { selItem.v.ValidateError = err return } + + // Reset to TFResourceTypeSkip if value is empty + if rt == "" { + rt = meta.TFResourceTypeSkip + } + selItem.v.TFResourceType = rt return } diff --git a/internal/ui/importlist/item.go b/internal/ui/importlist/item.go index 2aae764..9c846c2 100644 --- a/internal/ui/importlist/item.go +++ b/internal/ui/importlist/item.go @@ -21,6 +21,9 @@ func (i Item) Title() string { case i.v.Imported: return common.OKEmoji + i.v.ResourceID default: + if i.v.IsRecommended { + return common.BulbEmoji + i.v.ResourceID + } return i.v.ResourceID } } @@ -29,11 +32,10 @@ func (i Item) Description() string { if i.textinput.Focused() { return i.textinput.View() } - v := i.textinput.Value() - if v == "" { + if i.v.Skip() { return "(Skip)" } - return v + return i.textinput.Value() } func (i Item) FilterValue() string { return i.v.ResourceID }