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 }