github.com/GoogleCloudPlatform/terraformer@v0.8.18/terraformutils/providers_mapping.go (about)

     1  package terraformutils
     2  
     3  import (
     4  	"log"
     5  	"math/rand"
     6  	"reflect"
     7  	"time"
     8  
     9  	"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
    10  )
    11  
    12  type ProvidersMapping struct {
    13  	baseProvider       ProviderGenerator
    14  	Resources          map[*Resource]bool
    15  	Services           map[string]bool
    16  	Providers          map[ProviderGenerator]bool
    17  	providerToService  map[ProviderGenerator]string
    18  	serviceToProvider  map[string]ProviderGenerator
    19  	resourceToProvider map[*Resource]ProviderGenerator
    20  }
    21  
    22  func NewProvidersMapping(baseProvider ProviderGenerator) *ProvidersMapping {
    23  	providersMapping := &ProvidersMapping{
    24  		baseProvider:       baseProvider,
    25  		Resources:          map[*Resource]bool{},
    26  		Services:           map[string]bool{},
    27  		Providers:          map[ProviderGenerator]bool{},
    28  		providerToService:  map[ProviderGenerator]string{},
    29  		serviceToProvider:  map[string]ProviderGenerator{},
    30  		resourceToProvider: map[*Resource]ProviderGenerator{},
    31  	}
    32  
    33  	return providersMapping
    34  }
    35  
    36  func deepCopyProvider(provider ProviderGenerator) ProviderGenerator {
    37  	return reflect.New(reflect.ValueOf(provider).Elem().Type()).Interface().(ProviderGenerator)
    38  }
    39  
    40  func (p *ProvidersMapping) GetBaseProvider() ProviderGenerator {
    41  	return p.baseProvider
    42  }
    43  
    44  func (p *ProvidersMapping) AddServiceToProvider(service string) ProviderGenerator {
    45  	newProvider := deepCopyProvider(p.baseProvider)
    46  	p.Providers[newProvider] = true
    47  	p.Services[service] = true
    48  	p.providerToService[newProvider] = service
    49  	p.serviceToProvider[service] = newProvider
    50  
    51  	return newProvider
    52  }
    53  
    54  func (p *ProvidersMapping) GetServices() []string {
    55  	services := make([]string, len(p.Services))
    56  	for service := range p.Services {
    57  		services = append(services, service)
    58  	}
    59  
    60  	return services
    61  }
    62  
    63  func (p *ProvidersMapping) RemoveServices(services []string) {
    64  	for _, service := range services {
    65  		delete(p.Services, service)
    66  
    67  		matchingProvider := p.serviceToProvider[service]
    68  		delete(p.Providers, matchingProvider)
    69  		delete(p.providerToService, matchingProvider)
    70  		delete(p.serviceToProvider, service)
    71  	}
    72  }
    73  
    74  func (p *ProvidersMapping) ShuffleResources() []*Resource {
    75  	resources := []*Resource{}
    76  	for resource := range p.Resources {
    77  		resources = append(resources, resource)
    78  	}
    79  	rand.Seed(time.Now().UnixNano())
    80  	rand.Shuffle(len(resources), func(i, j int) { resources[i], resources[j] = resources[j], resources[i] })
    81  
    82  	return resources
    83  }
    84  
    85  func (p *ProvidersMapping) ProcessResources(isCleanup bool) {
    86  	initialResources := p.resourceToProvider
    87  	if isCleanup && len(initialResources) > 0 {
    88  		p.Resources = map[*Resource]bool{}
    89  		p.resourceToProvider = map[*Resource]ProviderGenerator{}
    90  		for provider := range p.Providers {
    91  			resources := provider.GetService().GetResources()
    92  			log.Printf("Filtered number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources()))
    93  			for i := range resources {
    94  				resource := resources[i]
    95  				p.Resources[&resource] = true
    96  				p.resourceToProvider[&resource] = provider
    97  			}
    98  		}
    99  	} else if !isCleanup {
   100  		for provider := range p.Providers {
   101  			resources := provider.GetService().GetResources()
   102  			log.Printf("Number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources()))
   103  			for i := range resources {
   104  				resource := resources[i]
   105  				p.Resources[&resource] = true
   106  				p.resourceToProvider[&resource] = provider
   107  			}
   108  		}
   109  	}
   110  }
   111  
   112  func (p *ProvidersMapping) MatchProvider(resource *Resource) ProviderGenerator {
   113  	return p.resourceToProvider[resource]
   114  }
   115  
   116  func (p *ProvidersMapping) SetResources(resourceToKeep []*Resource) {
   117  	p.Resources = map[*Resource]bool{}
   118  	resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
   119  	for i := range resourceToKeep {
   120  		resource := resourceToKeep[i]
   121  		provider := p.resourceToProvider[resource]
   122  		if resourcesGroupsByProviders[provider] == nil {
   123  			resourcesGroupsByProviders[provider] = []Resource{}
   124  		}
   125  		resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
   126  		p.Resources[resource] = true
   127  	}
   128  
   129  	for provider := range p.Providers {
   130  		provider.GetService().SetResources(resourcesGroupsByProviders[provider])
   131  	}
   132  }
   133  
   134  func (p *ProvidersMapping) GetResourcesByService() map[string][]Resource {
   135  	mapping := map[string][]Resource{}
   136  	for service := range p.Services {
   137  		mapping[service] = []Resource{}
   138  	}
   139  
   140  	for resource := range p.Resources {
   141  		provider := p.resourceToProvider[resource]
   142  		service := p.providerToService[provider]
   143  		mapping[service] = append(mapping[service], *resource)
   144  	}
   145  
   146  	return mapping
   147  }
   148  
   149  func (p *ProvidersMapping) ConvertTFStates(providerWrapper *providerwrapper.ProviderWrapper) {
   150  	for resource := range p.Resources {
   151  		err := resource.ConvertTFstate(providerWrapper)
   152  		if err != nil {
   153  			log.Printf("failed to convert resources %s because of error %s", resource.InstanceInfo.Id, err)
   154  		}
   155  	}
   156  
   157  	resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
   158  	for resource := range p.Resources {
   159  		provider := p.resourceToProvider[resource]
   160  		if resourcesGroupsByProviders[provider] == nil {
   161  			resourcesGroupsByProviders[provider] = []Resource{}
   162  		}
   163  		resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
   164  	}
   165  
   166  	for provider := range p.Providers {
   167  		provider.GetService().SetResources(resourcesGroupsByProviders[provider])
   168  	}
   169  
   170  }
   171  
   172  func (p *ProvidersMapping) CleanupProviders() {
   173  	for provider := range p.Providers {
   174  		provider.GetService().PostRefreshCleanup()
   175  		err := provider.GetService().PostConvertHook()
   176  		if err != nil {
   177  			log.Printf("failed run PostConvertHook because of error %s", err)
   178  		}
   179  	}
   180  	p.ProcessResources(true)
   181  }