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