github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/builtin/providers/cloudstack/resource_cloudstack_static_nat.go (about)

     1  package cloudstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	"github.com/xanzy/go-cloudstack/cloudstack"
    10  )
    11  
    12  func resourceCloudStackStaticNAT() *schema.Resource {
    13  	return &schema.Resource{
    14  		Create: resourceCloudStackStaticNATCreate,
    15  		Exists: resourceCloudStackStaticNATExists,
    16  		Read:   resourceCloudStackStaticNATRead,
    17  		Delete: resourceCloudStackStaticNATDelete,
    18  
    19  		Schema: map[string]*schema.Schema{
    20  			"ip_address_id": &schema.Schema{
    21  				Type:     schema.TypeString,
    22  				Required: true,
    23  				ForceNew: true,
    24  			},
    25  
    26  			"virtual_machine_id": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Required: true,
    29  				ForceNew: true,
    30  			},
    31  
    32  			"vm_guest_ip": &schema.Schema{
    33  				Type:     schema.TypeString,
    34  				Optional: true,
    35  				Computed: true,
    36  				ForceNew: true,
    37  			},
    38  
    39  			"project": &schema.Schema{
    40  				Type:     schema.TypeString,
    41  				Optional: true,
    42  				Computed: true,
    43  				ForceNew: true,
    44  			},
    45  		},
    46  	}
    47  }
    48  
    49  func resourceCloudStackStaticNATCreate(d *schema.ResourceData, meta interface{}) error {
    50  	cs := meta.(*cloudstack.CloudStackClient)
    51  
    52  	ipaddressid := d.Get("ip_address_id").(string)
    53  
    54  	vm, _, err := cs.VirtualMachine.GetVirtualMachineByID(
    55  		d.Get("virtual_machine_id").(string),
    56  		cloudstack.WithProject(d.Get("project").(string)),
    57  	)
    58  	if err != nil {
    59  		return err
    60  	}
    61  
    62  	// Create a new parameter struct
    63  	p := cs.NAT.NewEnableStaticNatParams(ipaddressid, vm.Id)
    64  
    65  	if vmGuestIP, ok := d.GetOk("vm_guest_ip"); ok {
    66  		p.SetVmguestip(vmGuestIP.(string))
    67  
    68  		// Set the network ID based on the guest IP, needed when the public IP address
    69  		// is not associated with any network yet
    70  	NICS:
    71  		for _, nic := range vm.Nic {
    72  			if vmGuestIP.(string) == nic.Ipaddress {
    73  				p.SetNetworkid(nic.Networkid)
    74  				break NICS
    75  			}
    76  			for _, ip := range nic.Secondaryip {
    77  				if vmGuestIP.(string) == ip.Ipaddress {
    78  					p.SetNetworkid(nic.Networkid)
    79  					break NICS
    80  				}
    81  			}
    82  		}
    83  	} else {
    84  		// If no guest IP is configured, use the primary NIC
    85  		p.SetNetworkid(vm.Nic[0].Networkid)
    86  	}
    87  
    88  	_, err = cs.NAT.EnableStaticNat(p)
    89  	if err != nil {
    90  		return fmt.Errorf("Error enabling static NAT: %s", err)
    91  	}
    92  
    93  	d.SetId(ipaddressid)
    94  
    95  	return resourceCloudStackStaticNATRead(d, meta)
    96  }
    97  
    98  func resourceCloudStackStaticNATExists(d *schema.ResourceData, meta interface{}) (bool, error) {
    99  	cs := meta.(*cloudstack.CloudStackClient)
   100  
   101  	// Get the IP address details
   102  	ip, count, err := cs.Address.GetPublicIpAddressByID(
   103  		d.Id(),
   104  		cloudstack.WithProject(d.Get("project").(string)),
   105  	)
   106  	if err != nil {
   107  		if count == 0 {
   108  			log.Printf("[DEBUG] IP address with ID %s no longer exists", d.Id())
   109  			return false, nil
   110  		}
   111  
   112  		return false, err
   113  	}
   114  
   115  	return ip.Isstaticnat, nil
   116  }
   117  
   118  func resourceCloudStackStaticNATRead(d *schema.ResourceData, meta interface{}) error {
   119  	cs := meta.(*cloudstack.CloudStackClient)
   120  
   121  	// Get the IP address details
   122  	ip, count, err := cs.Address.GetPublicIpAddressByID(
   123  		d.Id(),
   124  		cloudstack.WithProject(d.Get("project").(string)),
   125  	)
   126  	if err != nil {
   127  		if count == 0 {
   128  			log.Printf("[DEBUG] IP address with ID %s no longer exists", d.Id())
   129  			d.SetId("")
   130  			return nil
   131  		}
   132  
   133  		return err
   134  	}
   135  
   136  	if !ip.Isstaticnat {
   137  		log.Printf("[DEBUG] Static NAT is no longer enabled for IP address with ID %s", d.Id())
   138  		d.SetId("")
   139  		return nil
   140  	}
   141  
   142  	d.Set("virtual_machine_id", ip.Virtualmachineid)
   143  	d.Set("vm_guest_ip", ip.Vmipaddress)
   144  
   145  	setValueOrID(d, "project", ip.Project, ip.Projectid)
   146  
   147  	return nil
   148  }
   149  
   150  func resourceCloudStackStaticNATDelete(d *schema.ResourceData, meta interface{}) error {
   151  	cs := meta.(*cloudstack.CloudStackClient)
   152  
   153  	// Create a new parameter struct
   154  	p := cs.NAT.NewDisableStaticNatParams(d.Id())
   155  
   156  	// Disable static NAT
   157  	_, err := cs.NAT.DisableStaticNat(p)
   158  	if err != nil {
   159  		// This is a very poor way to be told the ID does no longer exist :(
   160  		if strings.Contains(err.Error(), fmt.Sprintf(
   161  			"Invalid parameter id value=%s due to incorrect long value format, "+
   162  				"or entity does not exist", d.Id())) {
   163  			return nil
   164  		}
   165  
   166  		return fmt.Errorf("Error disabling static NAT: %s", err)
   167  	}
   168  
   169  	return nil
   170  }