github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/azurerm/resource_arm_storage_container.go (about) 1 package azurerm 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 8 "regexp" 9 10 "github.com/Azure/azure-sdk-for-go/storage" 11 "github.com/hashicorp/terraform/helper/schema" 12 ) 13 14 func resourceArmStorageContainer() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceArmStorageContainerCreate, 17 Read: resourceArmStorageContainerRead, 18 Exists: resourceArmStorageContainerExists, 19 Delete: resourceArmStorageContainerDelete, 20 21 Schema: map[string]*schema.Schema{ 22 "name": { 23 Type: schema.TypeString, 24 Required: true, 25 ForceNew: true, 26 ValidateFunc: validateArmStorageContainerName, 27 }, 28 "resource_group_name": { 29 Type: schema.TypeString, 30 Required: true, 31 ForceNew: true, 32 }, 33 "storage_account_name": { 34 Type: schema.TypeString, 35 Required: true, 36 ForceNew: true, 37 }, 38 "container_access_type": { 39 Type: schema.TypeString, 40 Optional: true, 41 ForceNew: true, 42 Default: "private", 43 ValidateFunc: validateArmStorageContainerAccessType, 44 }, 45 "properties": { 46 Type: schema.TypeMap, 47 Computed: true, 48 }, 49 }, 50 } 51 } 52 53 //Following the naming convention as laid out in the docs 54 func validateArmStorageContainerName(v interface{}, k string) (ws []string, errors []error) { 55 value := v.(string) 56 if !regexp.MustCompile(`^\$root$|^[0-9a-z-]+$`).MatchString(value) { 57 errors = append(errors, fmt.Errorf( 58 "only lowercase alphanumeric characters and hyphens allowed in %q: %q", 59 k, value)) 60 } 61 if len(value) < 3 || len(value) > 63 { 62 errors = append(errors, fmt.Errorf( 63 "%q must be between 3 and 63 characters: %q", k, value)) 64 } 65 if regexp.MustCompile(`^-`).MatchString(value) { 66 errors = append(errors, fmt.Errorf( 67 "%q cannot begin with a hyphen: %q", k, value)) 68 } 69 return 70 } 71 72 func validateArmStorageContainerAccessType(v interface{}, k string) (ws []string, errors []error) { 73 value := strings.ToLower(v.(string)) 74 validTypes := map[string]struct{}{ 75 "private": struct{}{}, 76 "blob": struct{}{}, 77 "container": struct{}{}, 78 } 79 80 if _, ok := validTypes[value]; !ok { 81 errors = append(errors, fmt.Errorf("Storage container access type %q is invalid, must be %q, %q or %q", value, "private", "blob", "page")) 82 } 83 return 84 } 85 86 func resourceArmStorageContainerCreate(d *schema.ResourceData, meta interface{}) error { 87 armClient := meta.(*ArmClient) 88 89 resourceGroupName := d.Get("resource_group_name").(string) 90 storageAccountName := d.Get("storage_account_name").(string) 91 92 blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) 93 if err != nil { 94 return err 95 } 96 if !accountExists { 97 return fmt.Errorf("Storage Account %q Not Found", storageAccountName) 98 } 99 100 name := d.Get("name").(string) 101 102 var accessType storage.ContainerAccessType 103 if d.Get("container_access_type").(string) == "private" { 104 accessType = storage.ContainerAccessType("") 105 } else { 106 accessType = storage.ContainerAccessType(d.Get("container_access_type").(string)) 107 } 108 109 log.Printf("[INFO] Creating container %q in storage account %q.", name, storageAccountName) 110 reference := blobClient.GetContainerReference(name) 111 112 createOptions := &storage.CreateContainerOptions{} 113 _, err = reference.CreateIfNotExists(createOptions) 114 if err != nil { 115 return fmt.Errorf("Error creating container %q in storage account %q: %s", name, storageAccountName, err) 116 } 117 118 permissions := storage.ContainerPermissions{ 119 AccessType: accessType, 120 } 121 permissionOptions := &storage.SetContainerPermissionOptions{} 122 err = reference.SetPermissions(permissions, permissionOptions) 123 if err != nil { 124 return fmt.Errorf("Error setting permissions for container %s in storage account %s: %+v", name, storageAccountName, err) 125 } 126 127 d.SetId(name) 128 return resourceArmStorageContainerRead(d, meta) 129 } 130 131 // resourceAzureStorageContainerRead does all the necessary API calls to 132 // read the status of the storage container off Azure. 133 func resourceArmStorageContainerRead(d *schema.ResourceData, meta interface{}) error { 134 armClient := meta.(*ArmClient) 135 136 resourceGroupName := d.Get("resource_group_name").(string) 137 storageAccountName := d.Get("storage_account_name").(string) 138 139 blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) 140 if err != nil { 141 return err 142 } 143 if !accountExists { 144 log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) 145 d.SetId("") 146 return nil 147 } 148 149 name := d.Get("name").(string) 150 containers, err := blobClient.ListContainers(storage.ListContainersParameters{ 151 Prefix: name, 152 Timeout: 90, 153 }) 154 if err != nil { 155 return fmt.Errorf("Failed to retrieve storage containers in account %q: %s", name, err) 156 } 157 158 var found bool 159 for _, cont := range containers.Containers { 160 if cont.Name == name { 161 found = true 162 163 props := make(map[string]interface{}) 164 props["last_modified"] = cont.Properties.LastModified 165 props["lease_status"] = cont.Properties.LeaseStatus 166 props["lease_state"] = cont.Properties.LeaseState 167 props["lease_duration"] = cont.Properties.LeaseDuration 168 169 d.Set("properties", props) 170 } 171 } 172 173 if !found { 174 log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) 175 d.SetId("") 176 } 177 178 return nil 179 } 180 181 func resourceArmStorageContainerExists(d *schema.ResourceData, meta interface{}) (bool, error) { 182 armClient := meta.(*ArmClient) 183 184 resourceGroupName := d.Get("resource_group_name").(string) 185 storageAccountName := d.Get("storage_account_name").(string) 186 187 blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) 188 if err != nil { 189 return false, err 190 } 191 if !accountExists { 192 log.Printf("[DEBUG] Storage account %q not found, removing container %q from state", storageAccountName, d.Id()) 193 d.SetId("") 194 return false, nil 195 } 196 197 name := d.Get("name").(string) 198 199 log.Printf("[INFO] Checking existence of storage container %q in storage account %q", name, storageAccountName) 200 reference := blobClient.GetContainerReference(name) 201 exists, err := reference.Exists() 202 if err != nil { 203 return false, fmt.Errorf("Error querying existence of storage container %q in storage account %q: %s", name, storageAccountName, err) 204 } 205 206 if !exists { 207 log.Printf("[INFO] Storage container %q does not exist in account %q, removing from state...", name, storageAccountName) 208 d.SetId("") 209 } 210 211 return exists, nil 212 } 213 214 // resourceAzureStorageContainerDelete does all the necessary API calls to 215 // delete a storage container off Azure. 216 func resourceArmStorageContainerDelete(d *schema.ResourceData, meta interface{}) error { 217 armClient := meta.(*ArmClient) 218 219 resourceGroupName := d.Get("resource_group_name").(string) 220 storageAccountName := d.Get("storage_account_name").(string) 221 222 blobClient, accountExists, err := armClient.getBlobStorageClientForStorageAccount(resourceGroupName, storageAccountName) 223 if err != nil { 224 return err 225 } 226 if !accountExists { 227 log.Printf("[INFO]Storage Account %q doesn't exist so the container won't exist", storageAccountName) 228 return nil 229 } 230 231 name := d.Get("name").(string) 232 233 log.Printf("[INFO] Deleting storage container %q in account %q", name, storageAccountName) 234 reference := blobClient.GetContainerReference(name) 235 deleteOptions := &storage.DeleteContainerOptions{} 236 if _, err := reference.DeleteIfExists(deleteOptions); err != nil { 237 return fmt.Errorf("Error deleting storage container %q from storage account %q: %s", name, storageAccountName, err) 238 } 239 240 d.SetId("") 241 return nil 242 }