Skip to content

Commit

Permalink
Branch 241017 (#135)
Browse files Browse the repository at this point in the history
* update tfstate

* remove tfstate file from the temp folder

* escape key and value

* skip resource whose action is create or delete
  • Loading branch information
ms-henglu authored Oct 17, 2024
1 parent eec4215 commit 067a517
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 16 deletions.
3 changes: 3 additions & 0 deletions cmd/migrate_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ func (c *MigrateCommand) MigrateResources(terraform *tf.Terraform, resources []t
if err := os.MkdirAll(tempDir, 0750); err != nil {
log.Fatalf("creating temp workspace %q: %+v", tempDir, err)
}
if err := os.RemoveAll(path.Join(tempDir, "terraform.tfstate")); err != nil {
log.Printf("[WARN] removing temp workspace %q: %+v", tempDir, err)
}
defer func() {
err := os.RemoveAll(path.Join(tempDir, "terraform.tfstate"))
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ require (
github.com/huandu/xstrings v1.5.0 // indirect
github.com/magodo/armid v0.0.0-20230511151020-27880e5961c3 // indirect
github.com/magodo/tfpluginschema v0.0.0-20240902090353-0525d7d8c1c2 // indirect
github.com/magodo/tfstate v0.0.0-20240829105815-03d52976fa13 // indirect
github.com/magodo/tfstate v0.0.0-20241016043929-2c95177bf0e6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ github.com/magodo/tfadd v0.10.1-0.20240902124619-bd18a56f410d h1:dmS4jSfNIfshWkh
github.com/magodo/tfadd v0.10.1-0.20240902124619-bd18a56f410d/go.mod h1:G2Hc13YaLGHa+CPEP/HZzj9sIGyKDM5ZXInzQ8Dp86s=
github.com/magodo/tfpluginschema v0.0.0-20240902090353-0525d7d8c1c2 h1:Unxx8WLxzSxINnq7hItp4cXD7drihgfPltTd91efoBo=
github.com/magodo/tfpluginschema v0.0.0-20240902090353-0525d7d8c1c2/go.mod h1:mh3baLIzKdhegfmLrAX+mpXQBvs4sqiDRTGx5Z5FGo0=
github.com/magodo/tfstate v0.0.0-20240829105815-03d52976fa13 h1:HhTCs5IKRuJxqx3NDI5gWfAD4WCNXiYGXM1dKyPp9rA=
github.com/magodo/tfstate v0.0.0-20240829105815-03d52976fa13/go.mod h1:cm1odSE6eUeMQRjYRARg1sWLP3HPsWjwvmk/+T4eQxs=
github.com/magodo/tfstate v0.0.0-20241016043929-2c95177bf0e6 h1:Uy+WlvEHfZEVTs1Xf5N+177FTdPHx+mWUvsXHR4tGM4=
github.com/magodo/tfstate v0.0.0-20241016043929-2c95177bf0e6/go.mod h1:cm1odSE6eUeMQRjYRARg1sWLP3HPsWjwvmk/+T4eQxs=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
Expand Down
33 changes: 27 additions & 6 deletions helper/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,18 @@ func ListHclFiles(workingDirectory string) []fs.DirEntry {

// GetTokensForExpression convert a literal value to hclwrite.Tokens
func GetTokensForExpression(expression string) hclwrite.Tokens {
f, dialog := hclwrite.ParseConfig([]byte(fmt.Sprintf("%s=%s", "temp", expression)), "", hcl.InitialPos)
if dialog == nil || !dialog.HasErrors() && f != nil {
return f.Body().GetAttribute("temp").Expr().BuildTokens(nil)
syntaxTokens, diags := hclsyntax.LexConfig([]byte(expression), "main.tf", hcl.InitialPos)
if diags.HasErrors() {
return nil
}
return nil
res := make([]*hclwrite.Token, 0)
for _, token := range syntaxTokens {
res = append(res, &hclwrite.Token{
Type: token.Type,
Bytes: token.Bytes,
})
}
return res
}

// ParseHclArray parse `attrValue` to an array, example `attrValue` `["a", "b", 0]` will return ["\"a\"", "\"b\"", "0"]
Expand Down Expand Up @@ -121,9 +128,13 @@ func ToHclSearchReplace(input interface{}, search []string, replacement []string
}
attrs := make([]string, 0)
for k, v := range value {
if v == nil {
attrs = append(attrs, fmt.Sprintf("%s = null", quotedKey(k)))
continue
}
config, ok := ToHclSearchReplace(v, search, replacement)
found = found || ok
attrs = append(attrs, fmt.Sprintf("%s = %s", k, config))
attrs = append(attrs, fmt.Sprintf("%s = %s", quotedKey(k), config))
}
return fmt.Sprintf("{\n%s\n}", strings.Join(attrs, "\n")), found
case string:
Expand All @@ -132,7 +143,7 @@ func ToHclSearchReplace(input interface{}, search []string, replacement []string
return replacement[i], true
}
}
return fmt.Sprintf(`"%s"`, value), false
return fmt.Sprintf(`"%s"`, strings.ReplaceAll(value, "\"", "\\\"")), false
default:
return fmt.Sprintf("%v", value), false
}
Expand All @@ -150,3 +161,13 @@ func GetValueFromExpression(tokens hclwrite.Tokens) interface{} {
}
return nil
}

func quotedKey(input string) string {
if len(input) == 0 {
return input
}
if strings.Contains(input, ".") || strings.Contains(input, "/") || input[0] == '$' || input[0] >= '0' && input[0] <= '9' {
return fmt.Sprintf("\"%s\"", input)
}
return input
}
5 changes: 3 additions & 2 deletions types/azapi_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,8 @@ func (r *AzapiResource) GenerateNewConfig(terraform *tf.Terraform) error {
// import and build combined block
blocks := make([]*hclwrite.Block, 0)
for _, instance := range r.Instances {
if block, err := importAndGenerateConfig(terraform, fmt.Sprintf("%s.%s_%v", r.ResourceType, r.Label, instance.Index), instance.ResourceId, r.ResourceType, false); err == nil {
instanceAddress := fmt.Sprintf("%s.%s_%v", r.ResourceType, r.Label, strings.ReplaceAll(fmt.Sprintf("%v", instance.Index), "/", "_"))
if block, err := importAndGenerateConfig(terraform, instanceAddress, instance.ResourceId, r.ResourceType, false); err == nil {
blocks = append(blocks, block)
}
}
Expand Down Expand Up @@ -211,7 +212,7 @@ func (r *AzapiResource) EmptyImportConfig() string {
if !r.IsMultipleResources() {
config += fmt.Sprintf("resource \"%s\" \"%s\" {}\n", r.ResourceType, r.Label)
} else {
config += fmt.Sprintf("resource \"%s\" \"%s_%v\" {}\n", r.ResourceType, r.Label, instance.Index)
config += fmt.Sprintf("resource \"%s\" \"%s_%s\" {}\n", r.ResourceType, r.Label, strings.ReplaceAll(fmt.Sprintf("%v", instance.Index), "/", "_"))
}
}
return config
Expand Down
5 changes: 3 additions & 2 deletions types/azurerm_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ func (r *AzurermResource) GenerateNewConfig(terraform *tf.Terraform) error {
log.Printf("[INFO] generating config...")
blocks := make([]*hclwrite.Block, 0)
for _, instance := range r.Instances {
if block, err := importAndGenerateConfig(terraform, fmt.Sprintf("%s.%s_%v", r.NewResourceType, r.NewLabel, instance.Index), instance.ResourceId, "", true); err == nil {
instanceAddress := fmt.Sprintf("%s.%s_%v", r.NewResourceType, r.NewLabel, strings.ReplaceAll(fmt.Sprintf("%v", instance.Index), "/", "_"))
if block, err := importAndGenerateConfig(terraform, instanceAddress, instance.ResourceId, "", true); err == nil {
blocks = append(blocks, block)
}
}
Expand Down Expand Up @@ -187,7 +188,7 @@ func (r *AzurermResource) EmptyImportConfig() string {
config := ""
if r.IsMultipleResources() {
for _, instance := range r.Instances {
config += fmt.Sprintf("resource \"azapi_resource\" \"%s_%v\" {}\n", r.NewLabel, instance.Index)
config += fmt.Sprintf("resource \"azapi_resource\" \"%s_%s\" {}\n", r.NewLabel, strings.ReplaceAll(fmt.Sprintf("%v", instance.Index), "/", "_"))
}
} else {
config += fmt.Sprintf("resource \"azapi_resource\" \"%s\" {}\n", r.NewLabel)
Expand Down
4 changes: 4 additions & 0 deletions types/from_plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func ListResourcesFromPlan(p *tfjson.Plan) []AzureResource {
if resourceChange == nil || resourceChange.Change == nil {
continue
}
if len(resourceChange.Change.Actions) != 0 && (resourceChange.Change.Actions[0] == tfjson.ActionCreate || resourceChange.Change.Actions[0] == tfjson.ActionDelete) {
log.Printf("[WARN] resource %s.%s's planned action is %v, which is not supported. Please apply the changes before running the migration tool", resourceChange.Type, resourceChange.Name, resourceChange.Change.Actions)
continue
}

switch resourceChange.Type {
case "azapi_resource":
Expand Down
18 changes: 16 additions & 2 deletions types/hcl.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@ func recursiveUpdate(old *hclwrite.Block, new *hclwrite.Block, before interface{

// InjectReference replaces `block`'s literal value with reference provided by `refs`
func InjectReference(block *hclwrite.Block, refs []Reference) *hclwrite.Block {
if block.Body() == nil {
return block
}
search := make([]string, 0)
replacement := make([]string, 0)
for _, ref := range refs {
Expand Down Expand Up @@ -370,20 +373,31 @@ func CombineBlock(blocks []*hclwrite.Block, output *hclwrite.Block, isForEach bo

// GetForEachConstants converts a map of difference to hcl object
func GetForEachConstants(instances []Instance, items map[string][]hclwrite.Tokens) string {

config := ""
i := 0
for _, instance := range instances {
item := ""
for key := range items {
item += fmt.Sprintf("%s = %s", key, string(items[key][i].Bytes()))
item += fmt.Sprintf("%s = %s\n", quotedKey(key), string(items[key][i].Bytes()))
}
config += fmt.Sprintf("%s = {\n%s\n}\n", instance.Index, item)
config += fmt.Sprintf("%s = {\n%s\n}\n", quotedKey(fmt.Sprintf("%v", instance.Index)), item)
i++
}
config = fmt.Sprintf("{\n%s}\n", config)
return config
}

func quotedKey(input string) string {
if len(input) == 0 {
return input
}
if strings.Contains(input, ".") || strings.Contains(input, "/") || input[0] == '$' || input[0] >= '0' && input[0] <= '9' {
return fmt.Sprintf("\"%s\"", input)
}
return input
}

func CommentOutBlock(block *hclwrite.Block) hclwrite.Tokens {
file := hclwrite.NewEmptyFile()
file.Body().AppendBlock(block)
Expand Down
6 changes: 6 additions & 0 deletions vendor/github.com/magodo/tfstate/cty.go

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

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ github.com/magodo/tfadd/tfadd/internal
# github.com/magodo/tfpluginschema v0.0.0-20240902090353-0525d7d8c1c2
## explicit; go 1.21
github.com/magodo/tfpluginschema/schema
# github.com/magodo/tfstate v0.0.0-20240829105815-03d52976fa13
# github.com/magodo/tfstate v0.0.0-20241016043929-2c95177bf0e6
## explicit; go 1.18
github.com/magodo/tfstate
github.com/magodo/tfstate/terraform/jsonschema
Expand Down

0 comments on commit 067a517

Please sign in to comment.