types/from_plan.go (138 lines of code) (raw):
package types
import (
"fmt"
"log"
"strings"
tfjson "github.com/hashicorp/terraform-json"
)
func ListResourcesFromPlan(p *tfjson.Plan) []AzureResource {
resources := make([]AzureResource, 0)
if p == nil {
return resources
}
idMap := make(map[string]*tfjson.ResourceChange)
for _, resourceChange := range p.ResourceChanges {
if resourceChange == nil || resourceChange.Change == nil || resourceChange.ProviderName != "registry.terraform.io/hashicorp/azurerm" {
continue
}
idMap[getId(resourceChange.Change.Before)] = resourceChange
}
azapiResourceMap := make(map[string]*AzapiResource)
azapiUpdateResources := make([]AzapiUpdateResource, 0)
azurermResourceMap := make(map[string]*AzurermResource)
for _, resourceChange := range p.ResourceChanges {
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":
address := fmt.Sprintf("%s.%s", resourceChange.Type, resourceChange.Name)
if azapiResourceMap[address] == nil {
azapiResourceMap[address] = &AzapiResource{
Label: resourceChange.Name,
ResourceType: "",
Instances: make([]Instance, 0),
}
}
azapiResourceMap[address].Instances = append(azapiResourceMap[address].Instances, Instance{
Index: resourceChange.Index,
ResourceId: getId(resourceChange.Change.Before),
ApiVersion: getApiVersion(resourceChange.Change.Before),
})
case "azapi_update_resource":
resourceId := getId(resourceChange.Change.Before)
if idMap[resourceId] == nil {
log.Printf("[WARN] resource azapi_update_resource.%s's target is not in the same terraform working directory", resourceChange.Name)
continue
}
rc := idMap[resourceId]
azapiUpdateResources = append(azapiUpdateResources, AzapiUpdateResource{
OldLabel: resourceChange.Name,
Label: rc.Name,
Id: resourceId,
ApiVersion: getApiVersion(resourceChange.Change.Before),
ResourceType: rc.Type,
Change: rc.Change,
})
default:
if strings.HasPrefix(resourceChange.Type, "azurerm") {
address := fmt.Sprintf("%s.%s", resourceChange.Type, resourceChange.Name)
id := getId(resourceChange.Change.Before)
if azurermResourceMap[address] == nil {
if azureId, err := AzurermIdToAzureId(resourceChange.Type, id); err == nil {
id = azureId
}
azurermResourceMap[address] = &AzurermResource{
OldResourceType: resourceChange.Type,
OldLabel: resourceChange.Name,
NewResourceType: "azapi_resource",
NewLabel: NewLabel(id, resourceChange.Name),
Instances: make([]Instance, 0),
}
}
azurermResourceMap[address].Instances = append(azurermResourceMap[address].Instances, Instance{
Index: resourceChange.Index,
ResourceId: id,
})
}
}
}
refValueMap := getRefValueMap(p)
azapiResources := make([]AzapiResource, 0)
for _, v := range azapiResourceMap {
azapiResources = append(azapiResources, *v)
}
azurermResources := make([]AzurermResource, 0)
for _, resourceChange := range azurermResourceMap {
azurermResources = append(azurermResources, *resourceChange)
}
for index, resource := range azapiResources {
azapiResources[index].References = getReferencesForAddress(resource.OldAddress(nil), p, refValueMap)
azapiResources[index].InputProperties = getInputProperties(resource.OldAddress(nil), p)
}
for i, resource := range azapiResources {
outputPropSet := make(map[string]bool)
for j, instance := range resource.Instances {
azapiResources[i].Instances[j].Outputs = getOutputsForAddress(resource.OldAddress(instance.Index), refValueMap)
for _, output := range azapiResources[i].Instances[j].Outputs {
prop := strings.TrimPrefix(output.OldName, fmt.Sprintf("%s.output.", resource.OldAddress(instance.Index)))
if strings.HasPrefix(prop, "identity.userAssignedIdentities") {
prop = "identity.userAssignedIdentities"
}
outputPropSet[prop] = true
}
}
azapiResources[i].OutputProperties = make([]string, 0)
for key := range outputPropSet {
azapiResources[i].OutputProperties = append(azapiResources[i].OutputProperties, key)
}
}
for index, resource := range azapiUpdateResources {
azapiUpdateResources[index].References = getReferencesForAddress(resource.OldAddress(nil), p, refValueMap)
azapiUpdateResources[index].InputProperties = getInputProperties(resource.OldAddress(nil), p)
}
for i, resource := range azapiUpdateResources {
azapiUpdateResources[i].outputs = getOutputsForAddress(resource.OldAddress(nil), refValueMap)
azapiUpdateResources[i].OutputProperties = make([]string, 0)
for _, output := range azapiUpdateResources[i].outputs {
azapiUpdateResources[i].OutputProperties = append(azapiUpdateResources[i].OutputProperties, strings.TrimPrefix(output.OldName, fmt.Sprintf("%s.output.", resource.OldAddress(nil))))
}
}
for index, resource := range azurermResources {
azurermResources[index].References = getReferencesForAddress(resource.OldAddress(nil), p, refValueMap)
}
for _, resource := range azapiResources {
resources = append(resources, &resource)
}
for _, resource := range azapiUpdateResources {
resources = append(resources, &resource)
}
for _, resource := range azurermResources {
resources = append(resources, &resource)
}
return resources
}