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