github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/state/remote/artifactory.go (about)

     1  package remote
     2  
     3  import (
     4  	"crypto/md5"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  
     9  	artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
    10  )
    11  
    12  const ARTIF_TFSTATE_NAME = "terraform.tfstate"
    13  
    14  func artifactoryFactory(conf map[string]string) (Client, error) {
    15  	userName, ok := conf["username"]
    16  	if !ok {
    17  		userName = os.Getenv("ARTIFACTORY_USERNAME")
    18  		if userName == "" {
    19  			return nil, fmt.Errorf(
    20  				"missing 'username' configuration or ARTIFACTORY_USERNAME environment variable")
    21  		}
    22  	}
    23  	password, ok := conf["password"]
    24  	if !ok {
    25  		password = os.Getenv("ARTIFACTORY_PASSWORD")
    26  		if password == "" {
    27  			return nil, fmt.Errorf(
    28  				"missing 'password' configuration or ARTIFACTORY_PASSWORD environment variable")
    29  		}
    30  	}
    31  	url, ok := conf["url"]
    32  	if !ok {
    33  		url = os.Getenv("ARTIFACTORY_URL")
    34  		if url == "" {
    35  			return nil, fmt.Errorf(
    36  				"missing 'url' configuration or ARTIFACTORY_URL environment variable")
    37  		}
    38  	}
    39  	repo, ok := conf["repo"]
    40  	if !ok {
    41  		return nil, fmt.Errorf(
    42  			"missing 'repo' configuration")
    43  	}
    44  	subpath, ok := conf["subpath"]
    45  	if !ok {
    46  		return nil, fmt.Errorf(
    47  			"missing 'subpath' configuration")
    48  	}
    49  
    50  	clientConf := &artifactory.ClientConfig{
    51  		BaseURL:  url,
    52  		Username: userName,
    53  		Password: password,
    54  	}
    55  	nativeClient := artifactory.NewClient(clientConf)
    56  
    57  	return &ArtifactoryClient{
    58  		nativeClient: &nativeClient,
    59  		userName:     userName,
    60  		password:     password,
    61  		url:          url,
    62  		repo:         repo,
    63  		subpath:      subpath,
    64  	}, nil
    65  
    66  }
    67  
    68  type ArtifactoryClient struct {
    69  	nativeClient *artifactory.ArtifactoryClient
    70  	userName     string
    71  	password     string
    72  	url          string
    73  	repo         string
    74  	subpath      string
    75  }
    76  
    77  func (c *ArtifactoryClient) Get() (*Payload, error) {
    78  	p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
    79  	output, err := c.nativeClient.Get(p, make(map[string]string))
    80  	if err != nil {
    81  		if strings.Contains(err.Error(), "404") {
    82  			return nil, nil
    83  		}
    84  		return nil, err
    85  	}
    86  
    87  	// TODO: migrate to using X-Checksum-Md5 header from artifactory
    88  	// needs to be exposed by go-artifactory first
    89  
    90  	hash := md5.Sum(output)
    91  	payload := &Payload{
    92  		Data: output,
    93  		MD5:  hash[:md5.Size],
    94  	}
    95  
    96  	// If there was no data, then return nil
    97  	if len(payload.Data) == 0 {
    98  		return nil, nil
    99  	}
   100  
   101  	return payload, nil
   102  }
   103  
   104  func (c *ArtifactoryClient) Put(data []byte) error {
   105  	p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
   106  	if _, err := c.nativeClient.Put(p, string(data), make(map[string]string)); err == nil {
   107  		return nil
   108  	} else {
   109  		return fmt.Errorf("Failed to upload state: %v", err)
   110  	}
   111  }
   112  
   113  func (c *ArtifactoryClient) Delete() error {
   114  	p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
   115  	err := c.nativeClient.Delete(p)
   116  	return err
   117  }