diff --git a/builtin/providers/cloudstack/provider.go b/builtin/providers/cloudstack/provider.go index 4f5dc49a3e24..34addd6052c9 100644 --- a/builtin/providers/cloudstack/provider.go +++ b/builtin/providers/cloudstack/provider.go @@ -54,6 +54,7 @@ func Provider() terraform.ResourceProvider { "cloudstack_nic": resourceCloudStackNIC(), "cloudstack_port_forward": resourceCloudStackPortForward(), "cloudstack_secondary_ipaddress": resourceCloudStackSecondaryIPAddress(), + "cloudstack_security_group": resourceCloudStackSecurityGroup(), "cloudstack_ssh_keypair": resourceCloudStackSSHKeyPair(), "cloudstack_static_nat": resourceCloudStackStaticNAT(), "cloudstack_template": resourceCloudStackTemplate(), diff --git a/builtin/providers/cloudstack/resource_cloudstack_security_group.go b/builtin/providers/cloudstack/resource_cloudstack_security_group.go new file mode 100644 index 000000000000..3bca42f8622f --- /dev/null +++ b/builtin/providers/cloudstack/resource_cloudstack_security_group.go @@ -0,0 +1,128 @@ +package cloudstack + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/xanzy/go-cloudstack/cloudstack" +) + +func resourceCloudStackSecurityGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceCloudStackSecurityGroupCreate, + Read: resourceCloudStackSecurityGroupRead, + Delete: resourceCloudStackSecurityGroupDelete, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "description": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "project": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + } +} + +func resourceCloudStackSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + name := d.Get("name").(string) + + // Create a new parameter struct + p := cs.SecurityGroup.NewCreateSecurityGroupParams(name) + + // Set the description + if description, ok := d.GetOk("description"); ok { + p.SetDescription(description.(string)) + } else { + p.SetDescription(name) + } + + // If there is a project supplied, we retrieve and set the project id + if err := setProjectid(p, cs, d); err != nil { + return err + } + + log.Printf("[DEBUG] Creating security group %s", name) + r, err := cs.SecurityGroup.CreateSecurityGroup(p) + if err != nil { + return err + } + + log.Printf("[DEBUG] Security group %s successfully created with ID: %s", name, r.SecurityGroup.Id) + d.SetId(r.SecurityGroup.Id) + + return resourceCloudStackSecurityGroupRead(d, meta) +} + +func resourceCloudStackSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + log.Printf("[DEBUG] Retrieving security group %s (ID=%s)", d.Get("name").(string), d.Id()) + + // Get the security group details + ag, count, err := cs.SecurityGroup.GetSecurityGroupByID( + d.Id(), + cloudstack.WithProject(d.Get("project").(string)), + ) + if err != nil { + if count == 0 { + log.Printf("[DEBUG] Security group %s does not longer exist", d.Get("name").(string)) + d.SetId("") + return nil + } + + log.Printf("[DEBUG] Found %v groups matching", count) + + return err + } + + // Update the config + d.Set("name", ag.Name) + d.Set("description", ag.Description) + + return nil +} + +func resourceCloudStackSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { + cs := meta.(*cloudstack.CloudStackClient) + + // Create a new parameter struct + p := cs.SecurityGroup.NewDeleteSecurityGroupParams() + p.SetId(d.Id()) + + // If there is a project supplied, we retrieve and set the project id + if err := setProjectid(p, cs, d); err != nil { + return err + } + + // Delete the security group + _, err := cs.SecurityGroup.DeleteSecurityGroup(p) + if err != nil { + // This is a very poor way to be told the ID does no longer exist :( + if strings.Contains(err.Error(), fmt.Sprintf( + "Invalid parameter id value=%s due to incorrect long value format, "+ + "or entity does not exist", d.Id())) { + return nil + } + + return fmt.Errorf("Error deleting security group: %s", err) + } + + return nil +}