github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/google/resource_compute_router_peer.go (about)

     1  package google
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"strings"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"google.golang.org/api/compute/v1"
    11  	"google.golang.org/api/googleapi"
    12  )
    13  
    14  func resourceComputeRouterPeer() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceComputeRouterPeerCreate,
    17  		Read:   resourceComputeRouterPeerRead,
    18  		Delete: resourceComputeRouterPeerDelete,
    19  		Importer: &schema.ResourceImporter{
    20  			State: resourceComputeRouterPeerImportState,
    21  		},
    22  
    23  		Schema: map[string]*schema.Schema{
    24  			"name": &schema.Schema{
    25  				Type:     schema.TypeString,
    26  				Required: true,
    27  				ForceNew: true,
    28  			},
    29  			"router": &schema.Schema{
    30  				Type:     schema.TypeString,
    31  				Required: true,
    32  				ForceNew: true,
    33  			},
    34  			"interface": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ForceNew: true,
    38  			},
    39  
    40  			"peer_ip_address": &schema.Schema{
    41  				Type:     schema.TypeString,
    42  				Optional: true,
    43  				ForceNew: true,
    44  			},
    45  
    46  			"peer_asn": &schema.Schema{
    47  				Type:     schema.TypeInt,
    48  				Required: true,
    49  				ForceNew: true,
    50  			},
    51  
    52  			"advertised_route_priority": &schema.Schema{
    53  				Type:     schema.TypeInt,
    54  				Optional: true,
    55  				ForceNew: true,
    56  			},
    57  
    58  			"ip_address": &schema.Schema{
    59  				Type:     schema.TypeString,
    60  				Computed: true,
    61  			},
    62  
    63  			"project": &schema.Schema{
    64  				Type:     schema.TypeString,
    65  				Optional: true,
    66  				Computed: true,
    67  				ForceNew: true,
    68  			},
    69  
    70  			"region": &schema.Schema{
    71  				Type:     schema.TypeString,
    72  				Optional: true,
    73  				Computed: true,
    74  				ForceNew: true,
    75  			},
    76  		},
    77  	}
    78  }
    79  
    80  func resourceComputeRouterPeerCreate(d *schema.ResourceData, meta interface{}) error {
    81  
    82  	config := meta.(*Config)
    83  
    84  	region, err := getRegion(d, config)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	project, err := getProject(d, config)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	routerName := d.Get("router").(string)
    95  	peerName := d.Get("name").(string)
    96  
    97  	routerLock := getRouterLockName(region, routerName)
    98  	mutexKV.Lock(routerLock)
    99  	defer mutexKV.Unlock(routerLock)
   100  
   101  	routersService := config.clientCompute.Routers
   102  	router, err := routersService.Get(project, region, routerName).Do()
   103  	if err != nil {
   104  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   105  			log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
   106  			d.SetId("")
   107  
   108  			return nil
   109  		}
   110  
   111  		return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
   112  	}
   113  
   114  	peers := router.BgpPeers
   115  	for _, peer := range peers {
   116  		if peer.Name == peerName {
   117  			d.SetId("")
   118  			return fmt.Errorf("Router %s has peer %s already", routerName, peerName)
   119  		}
   120  	}
   121  
   122  	ifaceName := d.Get("interface").(string)
   123  
   124  	peer := &compute.RouterBgpPeer{Name: peerName,
   125  		InterfaceName: ifaceName}
   126  
   127  	if v, ok := d.GetOk("peer_ip_address"); ok {
   128  		peer.PeerIpAddress = v.(string)
   129  	}
   130  
   131  	if v, ok := d.GetOk("peer_asn"); ok {
   132  		peer.PeerAsn = int64(v.(int))
   133  	}
   134  
   135  	if v, ok := d.GetOk("advertised_route_priority"); ok {
   136  		peer.AdvertisedRoutePriority = int64(v.(int))
   137  	}
   138  
   139  	log.Printf("[INFO] Adding peer %s", peerName)
   140  	peers = append(peers, peer)
   141  	patchRouter := &compute.Router{
   142  		BgpPeers: peers,
   143  	}
   144  
   145  	log.Printf("[DEBUG] Updating router %s/%s with peers: %+v", region, routerName, peers)
   146  	op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
   147  	if err != nil {
   148  		return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
   149  	}
   150  	d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, peerName))
   151  	err = computeOperationWaitRegion(config, op, project, region, "Patching router")
   152  	if err != nil {
   153  		d.SetId("")
   154  		return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
   155  	}
   156  
   157  	return resourceComputeRouterPeerRead(d, meta)
   158  }
   159  
   160  func resourceComputeRouterPeerRead(d *schema.ResourceData, meta interface{}) error {
   161  
   162  	config := meta.(*Config)
   163  
   164  	region, err := getRegion(d, config)
   165  	if err != nil {
   166  		return err
   167  	}
   168  
   169  	project, err := getProject(d, config)
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	routerName := d.Get("router").(string)
   175  	peerName := d.Get("name").(string)
   176  
   177  	routersService := config.clientCompute.Routers
   178  	router, err := routersService.Get(project, region, routerName).Do()
   179  	if err != nil {
   180  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   181  			log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
   182  			d.SetId("")
   183  
   184  			return nil
   185  		}
   186  
   187  		return fmt.Errorf("Error Reading router %s/%s: %s", region, routerName, err)
   188  	}
   189  
   190  	for _, peer := range router.BgpPeers {
   191  
   192  		if peer.Name == peerName {
   193  			d.SetId(fmt.Sprintf("%s/%s/%s", region, routerName, peerName))
   194  			d.Set("interface", peer.InterfaceName)
   195  			d.Set("peer_ip_address", peer.PeerIpAddress)
   196  			d.Set("peer_asn", peer.PeerAsn)
   197  			d.Set("advertised_route_priority", peer.AdvertisedRoutePriority)
   198  			d.Set("ip_address", peer.IpAddress)
   199  			d.Set("region", region)
   200  			d.Set("project", project)
   201  			return nil
   202  		}
   203  	}
   204  
   205  	log.Printf("[WARN] Removing router peer %s/%s/%s because it is gone", region, routerName, peerName)
   206  	d.SetId("")
   207  	return nil
   208  }
   209  
   210  func resourceComputeRouterPeerDelete(d *schema.ResourceData, meta interface{}) error {
   211  
   212  	config := meta.(*Config)
   213  
   214  	region, err := getRegion(d, config)
   215  	if err != nil {
   216  		return err
   217  	}
   218  
   219  	project, err := getProject(d, config)
   220  	if err != nil {
   221  		return err
   222  	}
   223  
   224  	routerName := d.Get("router").(string)
   225  	peerName := d.Get("name").(string)
   226  
   227  	routerLock := getRouterLockName(region, routerName)
   228  	mutexKV.Lock(routerLock)
   229  	defer mutexKV.Unlock(routerLock)
   230  
   231  	routersService := config.clientCompute.Routers
   232  	router, err := routersService.Get(project, region, routerName).Do()
   233  	if err != nil {
   234  		if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 {
   235  			log.Printf("[WARN] Removing router peer %s because its router %s/%s is gone", peerName, region, routerName)
   236  
   237  			return nil
   238  		}
   239  
   240  		return fmt.Errorf("Error Reading Router %s: %s", routerName, err)
   241  	}
   242  
   243  	var newPeers []*compute.RouterBgpPeer = make([]*compute.RouterBgpPeer, 0, len(router.BgpPeers))
   244  	for _, peer := range router.BgpPeers {
   245  		if peer.Name == peerName {
   246  			continue
   247  		} else {
   248  			newPeers = append(newPeers, peer)
   249  		}
   250  	}
   251  
   252  	if len(newPeers) == len(router.BgpPeers) {
   253  		log.Printf("[DEBUG] Router %s/%s had no peer %s already", region, routerName, peerName)
   254  		d.SetId("")
   255  		return nil
   256  	}
   257  
   258  	log.Printf(
   259  		"[INFO] Removing peer %s from router %s/%s", peerName, region, routerName)
   260  	patchRouter := &compute.Router{
   261  		BgpPeers: newPeers,
   262  	}
   263  
   264  	log.Printf("[DEBUG] Updating router %s/%s with peers: %+v", region, routerName, newPeers)
   265  	op, err := routersService.Patch(project, region, router.Name, patchRouter).Do()
   266  	if err != nil {
   267  		return fmt.Errorf("Error patching router %s/%s: %s", region, routerName, err)
   268  	}
   269  
   270  	err = computeOperationWaitRegion(config, op, project, region, "Patching router")
   271  	if err != nil {
   272  		return fmt.Errorf("Error waiting to patch router %s/%s: %s", region, routerName, err)
   273  	}
   274  
   275  	d.SetId("")
   276  	return nil
   277  }
   278  
   279  func resourceComputeRouterPeerImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
   280  	parts := strings.Split(d.Id(), "/")
   281  	if len(parts) != 3 {
   282  		return nil, fmt.Errorf("Invalid router peer specifier. Expecting {region}/{router}/{peer}")
   283  	}
   284  
   285  	d.Set("region", parts[0])
   286  	d.Set("router", parts[1])
   287  	d.Set("name", parts[2])
   288  
   289  	return []*schema.ResourceData{d}, nil
   290  }