github.com/andresvia/terraform@v0.6.15-0.20160412045437-d51c75946785/builtin/providers/azurerm/resource_arm_template_deployment.go (about) 1 package azurerm 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "net/http" 8 "strings" 9 "time" 10 11 "github.com/Azure/azure-sdk-for-go/arm/resources/resources" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 ) 15 16 func resourceArmTemplateDeployment() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceArmTemplateDeploymentCreate, 19 Read: resourceArmTemplateDeploymentRead, 20 Update: resourceArmTemplateDeploymentCreate, 21 Delete: resourceArmTemplateDeploymentDelete, 22 23 Schema: map[string]*schema.Schema{ 24 "name": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 30 "resource_group_name": &schema.Schema{ 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 }, 35 36 "template_body": &schema.Schema{ 37 Type: schema.TypeString, 38 Optional: true, 39 Computed: true, 40 StateFunc: normalizeJson, 41 }, 42 43 "parameters": &schema.Schema{ 44 Type: schema.TypeMap, 45 Optional: true, 46 }, 47 48 "outputs": &schema.Schema{ 49 Type: schema.TypeMap, 50 Computed: true, 51 }, 52 53 "deployment_mode": &schema.Schema{ 54 Type: schema.TypeString, 55 Required: true, 56 }, 57 }, 58 } 59 } 60 61 func resourceArmTemplateDeploymentCreate(d *schema.ResourceData, meta interface{}) error { 62 client := meta.(*ArmClient) 63 deployClient := client.deploymentsClient 64 65 name := d.Get("name").(string) 66 resGroup := d.Get("resource_group_name").(string) 67 deploymentMode := d.Get("deployment_mode").(string) 68 69 log.Printf("[INFO] preparing arguments for Azure ARM Template Deployment creation.") 70 properties := resources.DeploymentProperties{ 71 Mode: resources.DeploymentMode(deploymentMode), 72 } 73 74 if v, ok := d.GetOk("parameters"); ok { 75 params := v.(map[string]interface{}) 76 77 newParams := make(map[string]interface{}, len(params)) 78 for key, val := range params { 79 newParams[key] = struct { 80 Value interface{} 81 }{ 82 Value: val, 83 } 84 } 85 86 properties.Parameters = &newParams 87 } 88 89 if v, ok := d.GetOk("template_body"); ok { 90 template, err := expandTemplateBody(v.(string)) 91 if err != nil { 92 return err 93 } 94 95 properties.Template = &template 96 } 97 98 deployment := resources.Deployment{ 99 Properties: &properties, 100 } 101 resp, err := deployClient.CreateOrUpdate(resGroup, name, deployment) 102 if err != nil { 103 return nil 104 } 105 106 d.SetId(*resp.ID) 107 108 log.Printf("[DEBUG] Waiting for Template Deployment (%s) to become available", name) 109 stateConf := &resource.StateChangeConf{ 110 Pending: []string{"creating", "updating", "accepted", "running"}, 111 Target: []string{"succeeded"}, 112 Refresh: templateDeploymentStateRefreshFunc(client, resGroup, name), 113 Timeout: 10 * time.Minute, 114 } 115 if _, err := stateConf.WaitForState(); err != nil { 116 return fmt.Errorf("Error waiting for Template Deployment (%s) to become available: %s", name, err) 117 } 118 119 return resourceArmTemplateDeploymentRead(d, meta) 120 } 121 122 func resourceArmTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { 123 client := meta.(*ArmClient) 124 deployClient := client.deploymentsClient 125 126 id, err := parseAzureResourceID(d.Id()) 127 if err != nil { 128 return err 129 } 130 resGroup := id.ResourceGroup 131 name := id.Path["deployments"] 132 if name == "" { 133 name = id.Path["Deployments"] 134 } 135 136 resp, err := deployClient.Get(resGroup, name) 137 if resp.StatusCode == http.StatusNotFound { 138 d.SetId("") 139 return nil 140 } 141 if err != nil { 142 return fmt.Errorf("Error making Read request on Azure RM Template Deployment %s: %s", name, err) 143 } 144 var outputs map[string]string 145 if resp.Properties.Outputs != nil && len(*resp.Properties.Outputs) > 0 { 146 outputs = make(map[string]string) 147 for key, output := range *resp.Properties.Outputs { 148 outputMap := output.(map[string]interface{}) 149 outputValue, ok := outputMap["value"] 150 if !ok { 151 // No value 152 continue 153 } 154 155 outputs[key] = outputValue.(string) 156 } 157 } 158 159 d.Set("outputs", outputs) 160 161 return nil 162 } 163 164 func resourceArmTemplateDeploymentDelete(d *schema.ResourceData, meta interface{}) error { 165 client := meta.(*ArmClient) 166 deployClient := client.deploymentsClient 167 168 id, err := parseAzureResourceID(d.Id()) 169 if err != nil { 170 return err 171 } 172 resGroup := id.ResourceGroup 173 name := id.Path["deployments"] 174 if name == "" { 175 name = id.Path["Deployments"] 176 } 177 178 _, err = deployClient.Delete(resGroup, name) 179 return nil 180 } 181 182 func expandTemplateBody(template string) (map[string]interface{}, error) { 183 var templateBody map[string]interface{} 184 err := json.Unmarshal([]byte(template), &templateBody) 185 if err != nil { 186 return nil, fmt.Errorf("Error Expanding the template_body for Azure RM Template Deployment") 187 } 188 return templateBody, nil 189 } 190 191 func normalizeJson(jsonString interface{}) string { 192 if jsonString == nil || jsonString == "" { 193 return "" 194 } 195 var j interface{} 196 err := json.Unmarshal([]byte(jsonString.(string)), &j) 197 if err != nil { 198 return fmt.Sprintf("Error parsing JSON: %s", err) 199 } 200 b, _ := json.Marshal(j) 201 return string(b[:]) 202 } 203 204 func templateDeploymentStateRefreshFunc(client *ArmClient, resourceGroupName string, name string) resource.StateRefreshFunc { 205 return func() (interface{}, string, error) { 206 res, err := client.deploymentsClient.Get(resourceGroupName, name) 207 if err != nil { 208 return nil, "", fmt.Errorf("Error issuing read request in templateDeploymentStateRefreshFunc to Azure ARM for Template Deployment '%s' (RG: '%s'): %s", name, resourceGroupName, err) 209 } 210 211 return res, strings.ToLower(*res.Properties.ProvisioningState), nil 212 } 213 }