terraformutils/providers_mapping.go (154 lines of code) (raw):
package terraformutils
import (
"log"
"math/rand"
"reflect"
"time"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/providerwrapper"
)
type ProvidersMapping struct {
baseProvider ProviderGenerator
Resources map[*Resource]bool
Services map[string]bool
Providers map[ProviderGenerator]bool
providerToService map[ProviderGenerator]string
serviceToProvider map[string]ProviderGenerator
resourceToProvider map[*Resource]ProviderGenerator
}
func NewProvidersMapping(baseProvider ProviderGenerator) *ProvidersMapping {
providersMapping := &ProvidersMapping{
baseProvider: baseProvider,
Resources: map[*Resource]bool{},
Services: map[string]bool{},
Providers: map[ProviderGenerator]bool{},
providerToService: map[ProviderGenerator]string{},
serviceToProvider: map[string]ProviderGenerator{},
resourceToProvider: map[*Resource]ProviderGenerator{},
}
return providersMapping
}
func deepCopyProvider(provider ProviderGenerator) ProviderGenerator {
return reflect.New(reflect.ValueOf(provider).Elem().Type()).Interface().(ProviderGenerator)
}
func (p *ProvidersMapping) GetBaseProvider() ProviderGenerator {
return p.baseProvider
}
func (p *ProvidersMapping) AddServiceToProvider(service string) ProviderGenerator {
newProvider := deepCopyProvider(p.baseProvider)
p.Providers[newProvider] = true
p.Services[service] = true
p.providerToService[newProvider] = service
p.serviceToProvider[service] = newProvider
return newProvider
}
func (p *ProvidersMapping) GetServices() []string {
services := make([]string, len(p.Services))
for service := range p.Services {
services = append(services, service)
}
return services
}
func (p *ProvidersMapping) RemoveServices(services []string) {
for _, service := range services {
delete(p.Services, service)
matchingProvider := p.serviceToProvider[service]
delete(p.Providers, matchingProvider)
delete(p.providerToService, matchingProvider)
delete(p.serviceToProvider, service)
}
}
func (p *ProvidersMapping) ShuffleResources() []*Resource {
resources := []*Resource{}
for resource := range p.Resources {
resources = append(resources, resource)
}
rand.Seed(time.Now().UnixNano())
rand.Shuffle(len(resources), func(i, j int) { resources[i], resources[j] = resources[j], resources[i] })
return resources
}
func (p *ProvidersMapping) ProcessResources(isCleanup bool) {
initialResources := p.resourceToProvider
if isCleanup && len(initialResources) > 0 {
p.Resources = map[*Resource]bool{}
p.resourceToProvider = map[*Resource]ProviderGenerator{}
for provider := range p.Providers {
resources := provider.GetService().GetResources()
log.Printf("Filtered number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources()))
for i := range resources {
resource := resources[i]
p.Resources[&resource] = true
p.resourceToProvider[&resource] = provider
}
}
} else if !isCleanup {
for provider := range p.Providers {
resources := provider.GetService().GetResources()
log.Printf("Number of resources for service %s: %d", p.providerToService[provider], len(provider.GetService().GetResources()))
for i := range resources {
resource := resources[i]
p.Resources[&resource] = true
p.resourceToProvider[&resource] = provider
}
}
}
}
func (p *ProvidersMapping) MatchProvider(resource *Resource) ProviderGenerator {
return p.resourceToProvider[resource]
}
func (p *ProvidersMapping) SetResources(resourceToKeep []*Resource) {
p.Resources = map[*Resource]bool{}
resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
for i := range resourceToKeep {
resource := resourceToKeep[i]
provider := p.resourceToProvider[resource]
if resourcesGroupsByProviders[provider] == nil {
resourcesGroupsByProviders[provider] = []Resource{}
}
resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
p.Resources[resource] = true
}
for provider := range p.Providers {
provider.GetService().SetResources(resourcesGroupsByProviders[provider])
}
}
func (p *ProvidersMapping) GetResourcesByService() map[string][]Resource {
mapping := map[string][]Resource{}
for service := range p.Services {
mapping[service] = []Resource{}
}
for resource := range p.Resources {
provider := p.resourceToProvider[resource]
service := p.providerToService[provider]
mapping[service] = append(mapping[service], *resource)
}
return mapping
}
func (p *ProvidersMapping) ConvertTFStates(providerWrapper *providerwrapper.ProviderWrapper) {
for resource := range p.Resources {
err := resource.ConvertTFstate(providerWrapper)
if err != nil {
log.Printf("failed to convert resources %s because of error %s", resource.InstanceInfo.Id, err)
}
}
resourcesGroupsByProviders := map[ProviderGenerator][]Resource{}
for resource := range p.Resources {
provider := p.resourceToProvider[resource]
if resourcesGroupsByProviders[provider] == nil {
resourcesGroupsByProviders[provider] = []Resource{}
}
resourcesGroupsByProviders[provider] = append(resourcesGroupsByProviders[provider], *resource)
}
for provider := range p.Providers {
provider.GetService().SetResources(resourcesGroupsByProviders[provider])
}
}
func (p *ProvidersMapping) CleanupProviders() {
for provider := range p.Providers {
provider.GetService().PostRefreshCleanup()
err := provider.GetService().PostConvertHook()
if err != nil {
log.Printf("failed run PostConvertHook because of error %s", err)
}
}
p.ProcessResources(true)
}