From 4d26f5fe0a7a723eae1864176708d6a61bf58234 Mon Sep 17 00:00:00 2001 From: magodo Date: Tue, 16 May 2023 11:48:10 +0800 Subject: [PATCH 1/3] Resource mapping file will now be generated together with the `import.tf` that is the TF plannable import blocks --- internal/meta/base_meta.go | 25 ++++++++++++++++++++++--- main.go | 7 ++++--- pkg/config/config.go | 2 ++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/internal/meta/base_meta.go b/internal/meta/base_meta.go index e2f63f6..12a2068 100644 --- a/internal/meta/base_meta.go +++ b/internal/meta/base_meta.go @@ -178,6 +178,9 @@ func NewBaseMeta(cfg config.CommonConfig) (*baseMeta, error) { if outputFileNames.MainFileName == "" { outputFileNames.MainFileName = "main.tf" } + if outputFileNames.ImportBlockFileName == "" { + outputFileNames.ImportBlockFileName = "import.tf" + } tc := cfg.TelemetryClient if tc == nil { @@ -361,24 +364,40 @@ func (meta baseMeta) GenerateCfg(ctx context.Context, l ImportList) error { func (meta baseMeta) ExportResourceMapping(_ context.Context, l ImportList) error { m := resmap.ResourceMapping{} + f := hclwrite.NewFile() + body := f.Body() for _, item := range l { if item.Skip() { continue } + + // The JSON mapping record m[item.AzureResourceID.String()] = resmap.ResourceMapEntity{ ResourceId: item.TFResourceId, ResourceType: item.TFAddr.Type, ResourceName: item.TFAddr.Name, } + + // The import block + blk := hclwrite.NewBlock("import", nil) + blk.Body().SetAttributeValue("id", cty.StringVal(item.TFResourceId)) + blk.Body().SetAttributeTraversal("to", hcl.Traversal{hcl.TraverseRoot{Name: item.TFAddr.Type}, hcl.TraverseAttr{Name: item.TFAddr.Name}}) + body.AppendBlock(blk) } - output := filepath.Join(meta.outdir, ResourceMappingFileName) b, err := json.MarshalIndent(m, "", "\t") if err != nil { return fmt.Errorf("JSON marshalling the resource mapping: %v", err) } + oMapFile := filepath.Join(meta.outdir, ResourceMappingFileName) // #nosec G306 - if err := os.WriteFile(output, b, 0644); err != nil { - return fmt.Errorf("writing the resource mapping to %s: %v", output, err) + if err := os.WriteFile(oMapFile, b, 0644); err != nil { + return fmt.Errorf("writing the resource mapping to %s: %v", oMapFile, err) + } + + oImportFile := filepath.Join(meta.moduleDir, meta.outputFileNames.ImportBlockFileName) + // #nosec G306 + if err := os.WriteFile(oImportFile, f.Bytes(), 0644); err != nil { + return fmt.Errorf("writing the import block to %s: %v", oImportFile, err) } return nil } diff --git a/main.go b/main.go index bd0a7f0..40c852e 100644 --- a/main.go +++ b/main.go @@ -324,9 +324,10 @@ func main() { mappingFileFlags := append([]cli.Flag{}, commonFlags...) safeOutputFileNames := config.OutputFileNames{ - TerraformFileName: "terraform.aztfexport.tf", - ProviderFileName: "provider.aztfexport.tf", - MainFileName: "main.aztfexport.tf", + TerraformFileName: "terraform.aztfexport.tf", + ProviderFileName: "provider.aztfexport.tf", + MainFileName: "main.aztfexport.tf", + ImportBlockFileName: "import.aztfexport.tf", } app := &cli.App{ diff --git a/pkg/config/config.go b/pkg/config/config.go index 2ceeed1..8853269 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -15,6 +15,8 @@ type OutputFileNames struct { ProviderFileName string // The filename for the generated "main.tf" (default) MainFileName string + // The filename for the generated "import.tf" (default) + ImportBlockFileName string } type CommonConfig struct { From 791fefb2a1782ba4fe6a4604fdcfaa1b3217ded3 Mon Sep 17 00:00:00 2001 From: magodo Date: Wed, 17 May 2023 10:13:12 +0800 Subject: [PATCH 2/3] Only generate import.tf for tf >= v1.6.0 --- internal/meta/base_meta.go | 41 ++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/internal/meta/base_meta.go b/internal/meta/base_meta.go index 12a2068..4fbf8ca 100644 --- a/internal/meta/base_meta.go +++ b/internal/meta/base_meta.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strings" + "github.com/hashicorp/go-version" tfjson "github.com/hashicorp/terraform-json" "github.com/Azure/aztfexport/pkg/config" @@ -362,10 +363,8 @@ func (meta baseMeta) GenerateCfg(ctx context.Context, l ImportList) error { return meta.generateCfg(ctx, l, meta.lifecycleAddon, meta.addDependency) } -func (meta baseMeta) ExportResourceMapping(_ context.Context, l ImportList) error { +func (meta baseMeta) ExportResourceMapping(ctx context.Context, l ImportList) error { m := resmap.ResourceMapping{} - f := hclwrite.NewFile() - body := f.Body() for _, item := range l { if item.Skip() { continue @@ -377,12 +376,6 @@ func (meta baseMeta) ExportResourceMapping(_ context.Context, l ImportList) erro ResourceType: item.TFAddr.Type, ResourceName: item.TFAddr.Name, } - - // The import block - blk := hclwrite.NewBlock("import", nil) - blk.Body().SetAttributeValue("id", cty.StringVal(item.TFResourceId)) - blk.Body().SetAttributeTraversal("to", hcl.Traversal{hcl.TraverseRoot{Name: item.TFAddr.Type}, hcl.TraverseAttr{Name: item.TFAddr.Name}}) - body.AppendBlock(blk) } b, err := json.MarshalIndent(m, "", "\t") if err != nil { @@ -394,10 +387,32 @@ func (meta baseMeta) ExportResourceMapping(_ context.Context, l ImportList) erro return fmt.Errorf("writing the resource mapping to %s: %v", oMapFile, err) } - oImportFile := filepath.Join(meta.moduleDir, meta.outputFileNames.ImportBlockFileName) - // #nosec G306 - if err := os.WriteFile(oImportFile, f.Bytes(), 0644); err != nil { - return fmt.Errorf("writing the import block to %s: %v", oImportFile, err) + // Only generate import.tf when the current using terraform supports plannable import + var supportPlannableImport bool + if meta.tf == nil { + supportPlannableImport = true + } else { + ver, _, err := meta.tf.Version(ctx, true) + if err != nil { + return fmt.Errorf("getting terraform version") + } + supportPlannableImport = ver.GreaterThanOrEqual(version.Must(version.NewVersion("v1.6.0"))) + } + if supportPlannableImport { + f := hclwrite.NewFile() + body := f.Body() + for _, item := range l { + // The import block + blk := hclwrite.NewBlock("import", nil) + blk.Body().SetAttributeValue("id", cty.StringVal(item.TFResourceId)) + blk.Body().SetAttributeTraversal("to", hcl.Traversal{hcl.TraverseRoot{Name: item.TFAddr.Type}, hcl.TraverseAttr{Name: item.TFAddr.Name}}) + body.AppendBlock(blk) + } + oImportFile := filepath.Join(meta.moduleDir, meta.outputFileNames.ImportBlockFileName) + // #nosec G306 + if err := os.WriteFile(oImportFile, f.Bytes(), 0644); err != nil { + return fmt.Errorf("writing the import block to %s: %v", oImportFile, err) + } } return nil } From ce76e98b42e7c79a23275cb3d3c3d24dcf128d56 Mon Sep 17 00:00:00 2001 From: magodo Date: Thu, 25 May 2023 09:43:38 +0800 Subject: [PATCH 3/3] actually it is v1.5.0 --- internal/meta/base_meta.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/meta/base_meta.go b/internal/meta/base_meta.go index 4fbf8ca..574aff8 100644 --- a/internal/meta/base_meta.go +++ b/internal/meta/base_meta.go @@ -396,7 +396,7 @@ func (meta baseMeta) ExportResourceMapping(ctx context.Context, l ImportList) er if err != nil { return fmt.Errorf("getting terraform version") } - supportPlannableImport = ver.GreaterThanOrEqual(version.Must(version.NewVersion("v1.6.0"))) + supportPlannableImport = ver.GreaterThanOrEqual(version.Must(version.NewVersion("v1.5.0"))) } if supportPlannableImport { f := hclwrite.NewFile()