github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/ibm/instance_groups.go (about)

     1  // Copyright 2019 The Terraformer Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package ibm
    16  
    17  import (
    18  	"fmt"
    19  	"math/rand"
    20  	"os"
    21  	"sync"
    22  
    23  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    24  	"github.com/IBM/go-sdk-core/v4/core"
    25  	"github.com/IBM/vpc-go-sdk/vpcv1"
    26  )
    27  
    28  // InstanceGroupGenerator ...
    29  type InstanceGroupGenerator struct {
    30  	IBMService
    31  	fatalErrors chan error
    32  }
    33  
    34  func (g *InstanceGroupGenerator) loadInstanceGroup(instanceGroupID, instanceGroupName string) terraformutils.Resource {
    35  	resources := terraformutils.NewSimpleResource(
    36  		instanceGroupID,
    37  		instanceGroupName,
    38  		"ibm_is_instance_group",
    39  		"ibm",
    40  		[]string{})
    41  	return resources
    42  }
    43  
    44  func (g *InstanceGroupGenerator) loadInstanceGroupManger(instanceGroupID, instanceGroupManagerID, managerName string, dependsOn []string) terraformutils.Resource {
    45  	if managerName == "" {
    46  		managerName = fmt.Sprintf("manager-%d-%d", rand.Intn(100), rand.Intn(50))
    47  	}
    48  	resources := terraformutils.NewResource(
    49  		fmt.Sprintf("%s/%s", instanceGroupID, instanceGroupManagerID),
    50  		managerName,
    51  		"ibm_is_instance_group_manager",
    52  		"ibm",
    53  		map[string]string{},
    54  		[]string{},
    55  		map[string]interface{}{
    56  			"depends_on": dependsOn,
    57  		})
    58  	return resources
    59  }
    60  
    61  func (g *InstanceGroupGenerator) loadInstanceGroupMangerPolicy(instanceGroupID, instanceGroupManagerID, policyID, policyName string, dependsOn []string) terraformutils.Resource {
    62  	if policyName == "" {
    63  		policyName = fmt.Sprintf("manager-%d-%d", rand.Intn(100), rand.Intn(50))
    64  	}
    65  	resources := terraformutils.NewResource(
    66  		fmt.Sprintf("%s/%s/%s", instanceGroupID, instanceGroupManagerID, policyID),
    67  		policyName,
    68  		"ibm_is_instance_group_manager_policy",
    69  		"ibm",
    70  		map[string]string{},
    71  		[]string{},
    72  		map[string]interface{}{
    73  			"depends_on": dependsOn,
    74  		})
    75  	return resources
    76  }
    77  
    78  func (g *InstanceGroupGenerator) handlePolicies(sess *vpcv1.VpcV1, instanceGroupID, instanceGroupManagerID string, policies, dependsOn []string, waitGroup *sync.WaitGroup) {
    79  	defer waitGroup.Done()
    80  	for _, instanceGroupManagerPolicyID := range policies {
    81  		getInstanceGroupManagerPolicyOptions := vpcv1.GetInstanceGroupManagerPolicyOptions{
    82  			ID:                     &instanceGroupManagerPolicyID,
    83  			InstanceGroupID:        &instanceGroupID,
    84  			InstanceGroupManagerID: &instanceGroupManagerID,
    85  		}
    86  		data, response, err := sess.GetInstanceGroupManagerPolicy(&getInstanceGroupManagerPolicyOptions)
    87  		if err != nil {
    88  			g.fatalErrors <- fmt.Errorf("Error Getting InstanceGroup Manager Policy: %s\n%s", err, response)
    89  		}
    90  		instanceGroupManagerPolicy := data.(*vpcv1.InstanceGroupManagerPolicy)
    91  		g.Resources = append(g.Resources, g.loadInstanceGroupMangerPolicy(instanceGroupID,
    92  			instanceGroupManagerID,
    93  			instanceGroupManagerPolicyID,
    94  			*instanceGroupManagerPolicy.Name,
    95  			dependsOn))
    96  	}
    97  }
    98  
    99  func (g *InstanceGroupGenerator) handleManagers(sess *vpcv1.VpcV1, instanceGroupID string, managers, dependsOn []string, waitGroup *sync.WaitGroup) {
   100  	defer waitGroup.Done()
   101  	var policiesWG sync.WaitGroup
   102  	for _, instanceGroupManagerID := range managers {
   103  		getInstanceGroupManagerOptions := vpcv1.GetInstanceGroupManagerOptions{
   104  			ID:              &instanceGroupManagerID,
   105  			InstanceGroupID: &instanceGroupID,
   106  		}
   107  		instanceGroupManager, response, err := sess.GetInstanceGroupManager(&getInstanceGroupManagerOptions)
   108  		if err != nil {
   109  			g.fatalErrors <- fmt.Errorf("Error Getting InstanceGroup Manager: %s\n%s", err, response)
   110  		}
   111  		g.Resources = append(g.Resources, g.loadInstanceGroupManger(instanceGroupID, instanceGroupManagerID, *instanceGroupManager.Name, dependsOn))
   112  
   113  		policies := make([]string, 0)
   114  
   115  		for i := 0; i < len(instanceGroupManager.Policies); i++ {
   116  			policies = append(policies, *(instanceGroupManager.Policies[i].ID))
   117  		}
   118  		policiesWG.Add(1)
   119  		dependsOn1 := makeDependsOn(dependsOn,
   120  			"ibm_is_instance_group_manger."+terraformutils.TfSanitize(*instanceGroupManager.Name))
   121  		go g.handlePolicies(sess, instanceGroupID, instanceGroupManagerID, policies, dependsOn1, &policiesWG)
   122  	}
   123  	policiesWG.Wait()
   124  }
   125  
   126  func (g *InstanceGroupGenerator) handleInstanceGroups(sess *vpcv1.VpcV1, waitGroup *sync.WaitGroup) {
   127  	// Support for pagination
   128  	defer waitGroup.Done()
   129  	start := ""
   130  	var allrecs []vpcv1.InstanceGroup
   131  	for {
   132  		listInstanceGroupOptions := vpcv1.ListInstanceGroupsOptions{}
   133  		if start != "" {
   134  			listInstanceGroupOptions.Start = &start
   135  		}
   136  		instanceGroupsCollection, response, err := sess.ListInstanceGroups(&listInstanceGroupOptions)
   137  		if err != nil {
   138  			g.fatalErrors <- fmt.Errorf("Error Fetching InstanceGroups %s\n%s", err, response)
   139  		}
   140  		start = GetNext(instanceGroupsCollection.Next)
   141  		allrecs = append(allrecs, instanceGroupsCollection.InstanceGroups...)
   142  		if start == "" {
   143  			break
   144  		}
   145  	}
   146  
   147  	var managersWG sync.WaitGroup
   148  
   149  	for _, instanceGroup := range allrecs {
   150  		var dependsOn []string
   151  		dependsOn = append(dependsOn,
   152  			"ibm_is_instance_group."+terraformutils.TfSanitize(*instanceGroup.Name))
   153  		instanceGoupID := *instanceGroup.ID
   154  		g.Resources = append(g.Resources, g.loadInstanceGroup(instanceGoupID, *instanceGroup.Name))
   155  		managers := make([]string, 0)
   156  		for i := 0; i < len(instanceGroup.Managers); i++ {
   157  			managers = append(managers, *(instanceGroup.Managers[i].ID))
   158  		}
   159  		managersWG.Add(1)
   160  		go g.handleManagers(sess, instanceGoupID, managers, dependsOn, &managersWG)
   161  	}
   162  	managersWG.Wait()
   163  }
   164  
   165  // InitResources ...
   166  func (g *InstanceGroupGenerator) InitResources() error {
   167  	apiKey := os.Getenv("IC_API_KEY")
   168  	if apiKey == "" {
   169  		return fmt.Errorf("no API key set")
   170  	}
   171  
   172  	// Instantiate the service with an API key based IAM authenticator
   173  	sess, err := vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
   174  		Authenticator: &core.IamAuthenticator{
   175  			ApiKey: apiKey,
   176  		},
   177  	})
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	g.fatalErrors = make(chan error)
   183  
   184  	var instanceGroupWG sync.WaitGroup
   185  	instanceGroupWG.Add(1)
   186  	go g.handleInstanceGroups(sess, &instanceGroupWG)
   187  
   188  	select { //nolint
   189  	case err := <-g.fatalErrors:
   190  		close(g.fatalErrors)
   191  		return err
   192  	}
   193  	instanceGroupWG.Wait() //nolint:govet
   194  	return nil
   195  }