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