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  }