github.com/danrjohnson/terraform@v0.7.0-rc2.0.20160627135212-d0fc1fa086ff/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": { 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 30 "resource_group_name": { 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 }, 35 36 "template_body": { 37 Type: schema.TypeString, 38 Optional: true, 39 Computed: true, 40 StateFunc: normalizeJson, 41 }, 42 43 "parameters": { 44 Type: schema.TypeMap, 45 Optional: true, 46 }, 47 48 "outputs": { 49 Type: schema.TypeMap, 50 Computed: true, 51 }, 52 53 "deployment_mode": { 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 102 _, err := deployClient.CreateOrUpdate(resGroup, name, deployment, make(chan struct{})) 103 if err != nil { 104 return nil 105 } 106 107 read, err := deployClient.Get(resGroup, name) 108 if err != nil { 109 return err 110 } 111 if read.ID == nil { 112 return fmt.Errorf("Cannot read Template Deployment %s (resource group %s) ID", name, resGroup) 113 } 114 115 d.SetId(*read.ID) 116 117 log.Printf("[DEBUG] Waiting for Template Deployment (%s) to become available", name) 118 stateConf := &resource.StateChangeConf{ 119 Pending: []string{"creating", "updating", "accepted", "running"}, 120 Target: []string{"succeeded"}, 121 Refresh: templateDeploymentStateRefreshFunc(client, resGroup, name), 122 Timeout: 40 * time.Minute, 123 } 124 if _, err := stateConf.WaitForState(); err != nil { 125 return fmt.Errorf("Error waiting for Template Deployment (%s) to become available: %s", name, err) 126 } 127 128 return resourceArmTemplateDeploymentRead(d, meta) 129 } 130 131 func resourceArmTemplateDeploymentRead(d *schema.ResourceData, meta interface{}) error { 132 client := meta.(*ArmClient) 133 deployClient := client.deploymentsClient 134 135 id, err := parseAzureResourceID(d.Id()) 136 if err != nil { 137 return err 138 } 139 resGroup := id.ResourceGroup 140 name := id.Path["deployments"] 141 if name == "" { 142 name = id.Path["Deployments"] 143 } 144 145 resp, err := deployClient.Get(resGroup, name) 146 if resp.StatusCode == http.StatusNotFound { 147 d.SetId("") 148 return nil 149 } 150 if err != nil { 151 return fmt.Errorf("Error making Read request on Azure RM Template Deployment %s: %s", name, err) 152 } 153 var outputs map[string]string 154 if resp.Properties.Outputs != nil && len(*resp.Properties.Outputs) > 0 { 155 outputs = make(map[string]string) 156 for key, output := range *resp.Properties.Outputs { 157 outputMap := output.(map[string]interface{}) 158 outputValue, ok := outputMap["value"] 159 if !ok { 160 // No value 161 continue 162 } 163 164 outputs[key] = outputValue.(string) 165 } 166 } 167 168 d.Set("outputs", outputs) 169 170 return nil 171 } 172 173 func resourceArmTemplateDeploymentDelete(d *schema.ResourceData, meta interface{}) error { 174 client := meta.(*ArmClient) 175 deployClient := client.deploymentsClient 176 177 id, err := parseAzureResourceID(d.Id()) 178 if err != nil { 179 return err 180 } 181 resGroup := id.ResourceGroup 182 name := id.Path["deployments"] 183 if name == "" { 184 name = id.Path["Deployments"] 185 } 186 187 _, err = deployClient.Delete(resGroup, name, make(chan struct{})) 188 return nil 189 } 190 191 func expandTemplateBody(template string) (map[string]interface{}, error) { 192 var templateBody map[string]interface{} 193 err := json.Unmarshal([]byte(template), &templateBody) 194 if err != nil { 195 return nil, fmt.Errorf("Error Expanding the template_body for Azure RM Template Deployment") 196 } 197 return templateBody, nil 198 } 199 200 func normalizeJson(jsonString interface{}) string { 201 if jsonString == nil || jsonString == "" { 202 return "" 203 } 204 var j interface{} 205 err := json.Unmarshal([]byte(jsonString.(string)), &j) 206 if err != nil { 207 return fmt.Sprintf("Error parsing JSON: %s", err) 208 } 209 b, _ := json.Marshal(j) 210 return string(b[:]) 211 } 212 213 func templateDeploymentStateRefreshFunc(client *ArmClient, resourceGroupName string, name string) resource.StateRefreshFunc { 214 return func() (interface{}, string, error) { 215 res, err := client.deploymentsClient.Get(resourceGroupName, name) 216 if err != nil { 217 return nil, "", fmt.Errorf("Error issuing read request in templateDeploymentStateRefreshFunc to Azure ARM for Template Deployment '%s' (RG: '%s'): %s", name, resourceGroupName, err) 218 } 219 220 return res, strings.ToLower(*res.Properties.ProvisioningState), nil 221 } 222 }