github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/atlas/resource_artifact.go (about) 1 package atlas 2 3 import ( 4 "fmt" 5 "regexp" 6 7 "github.com/hashicorp/atlas-go/v1" 8 "github.com/hashicorp/terraform/helper/hashcode" 9 "github.com/hashicorp/terraform/helper/schema" 10 ) 11 12 var ( 13 // saneMetaKey is used to sanitize the metadata keys so that 14 // they can be accessed as a variable interpolation from TF 15 saneMetaKey = regexp.MustCompile("[^a-zA-Z0-9-_]") 16 ) 17 18 func resourceArtifact() *schema.Resource { 19 return &schema.Resource{ 20 Create: resourceArtifactRead, 21 Read: resourceArtifactRead, 22 Delete: resourceArtifactDelete, 23 24 Schema: map[string]*schema.Schema{ 25 "name": &schema.Schema{ 26 Type: schema.TypeString, 27 Required: true, 28 ForceNew: true, 29 }, 30 31 "type": &schema.Schema{ 32 Type: schema.TypeString, 33 Required: true, 34 ForceNew: true, 35 }, 36 37 "build": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 ForceNew: true, 41 }, 42 43 "version": &schema.Schema{ 44 Type: schema.TypeString, 45 Optional: true, 46 ForceNew: true, 47 }, 48 49 "metadata_keys": &schema.Schema{ 50 Type: schema.TypeSet, 51 Optional: true, 52 ForceNew: true, 53 Elem: &schema.Schema{Type: schema.TypeString}, 54 Set: func(v interface{}) int { 55 return hashcode.String(v.(string)) 56 }, 57 }, 58 59 "metadata": &schema.Schema{ 60 Type: schema.TypeMap, 61 Optional: true, 62 ForceNew: true, 63 }, 64 65 "file_url": &schema.Schema{ 66 Type: schema.TypeString, 67 Computed: true, 68 }, 69 70 "metadata_full": &schema.Schema{ 71 Type: schema.TypeMap, 72 Computed: true, 73 }, 74 75 "slug": &schema.Schema{ 76 Type: schema.TypeString, 77 Computed: true, 78 }, 79 80 "version_real": &schema.Schema{ 81 Type: schema.TypeString, 82 Computed: true, 83 }, 84 }, 85 } 86 } 87 88 func resourceArtifactRead(d *schema.ResourceData, meta interface{}) error { 89 client := meta.(*atlas.Client) 90 91 // Parse the slug from the name given of the artifact since the API 92 // expects these to be split. 93 user, name, err := atlas.ParseSlug(d.Get("name").(string)) 94 if err != nil { 95 return err 96 } 97 98 // Filter by version or build if given 99 var build, version string 100 if v, ok := d.GetOk("version"); ok { 101 version = v.(string) 102 } else if b, ok := d.GetOk("build"); ok { 103 build = b.(string) 104 } 105 106 // If we have neither, default to latest version 107 if build == "" && version == "" { 108 version = "latest" 109 } 110 111 // Compile the metadata search params 112 md := make(map[string]string) 113 for _, v := range d.Get("metadata_keys").(*schema.Set).List() { 114 md[v.(string)] = atlas.MetadataAnyValue 115 } 116 for k, v := range d.Get("metadata").(map[string]interface{}) { 117 md[k] = v.(string) 118 } 119 120 // Do the search! 121 vs, err := client.ArtifactSearch(&atlas.ArtifactSearchOpts{ 122 User: user, 123 Name: name, 124 Type: d.Get("type").(string), 125 Build: build, 126 Version: version, 127 Metadata: md, 128 }) 129 if err != nil { 130 return fmt.Errorf( 131 "Error searching for artifact '%s/%s': %s", 132 user, name, err) 133 } 134 135 if len(vs) == 0 { 136 return fmt.Errorf("No matching artifact for '%s/%s'", user, name) 137 } else if len(vs) > 1 { 138 return fmt.Errorf( 139 "Got %d results for '%s/%s', only one is allowed", 140 len(vs), user, name) 141 } 142 v := vs[0] 143 144 d.SetId(v.ID) 145 if v.ID == "" { 146 d.SetId(fmt.Sprintf("%s %d", v.Tag, v.Version)) 147 } 148 d.Set("version_real", v.Version) 149 d.Set("metadata_full", cleanMetadata(v.Metadata)) 150 d.Set("slug", v.Slug) 151 152 d.Set("file_url", "") 153 if u, err := client.ArtifactFileURL(v); err != nil { 154 return fmt.Errorf( 155 "Error reading file URL: %s", err) 156 } else if u != nil { 157 d.Set("file_url", u.String()) 158 } 159 160 return nil 161 } 162 163 func resourceArtifactDelete(d *schema.ResourceData, meta interface{}) error { 164 // This just always succeeds since this is a readonly element. 165 d.SetId("") 166 return nil 167 } 168 169 // cleanMetadata is used to ensure the metadata is accessible as 170 // a variable by doing a simple re-write. 171 func cleanMetadata(in map[string]string) map[string]string { 172 out := make(map[string]string, len(in)) 173 for k, v := range in { 174 sane := saneMetaKey.ReplaceAllString(k, "-") 175 out[sane] = v 176 } 177 return out 178 }