mirror of https://github.com/hashicorp/terraform
parent
ef221714a4
commit
979f80e18d
@ -0,0 +1,100 @@
|
||||
package artifactory
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
||||
)
|
||||
|
||||
func New() backend.Backend {
|
||||
s := &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"username": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ARTIFACTORY_USERNAME", nil),
|
||||
Description: "Username",
|
||||
},
|
||||
"password": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ARTIFACTORY_PASSWORD", nil),
|
||||
Description: "Password",
|
||||
},
|
||||
"url": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
DefaultFunc: schema.EnvDefaultFunc("ARTIFACTORY_URL", nil),
|
||||
Description: "Artfactory base URL",
|
||||
},
|
||||
"repo": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "The repository name",
|
||||
},
|
||||
"subpath": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Description: "Path within the repository",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
b := &Backend{Backend: s}
|
||||
b.Backend.ConfigureFunc = b.configure
|
||||
return b
|
||||
}
|
||||
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
|
||||
client *ArtifactoryClient
|
||||
}
|
||||
|
||||
func (b *Backend) configure(ctx context.Context) error {
|
||||
data := schema.FromContextBackendConfig(ctx)
|
||||
|
||||
userName := data.Get("username").(string)
|
||||
password := data.Get("password").(string)
|
||||
url := data.Get("url").(string)
|
||||
repo := data.Get("repo").(string)
|
||||
subpath := data.Get("subpath").(string)
|
||||
|
||||
clientConf := &artifactory.ClientConfig{
|
||||
BaseURL: url,
|
||||
Username: userName,
|
||||
Password: password,
|
||||
}
|
||||
nativeClient := artifactory.NewClient(clientConf)
|
||||
|
||||
b.client = &ArtifactoryClient{
|
||||
nativeClient: &nativeClient,
|
||||
userName: userName,
|
||||
password: password,
|
||||
url: url,
|
||||
repo: repo,
|
||||
subpath: subpath,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) States() ([]string, error) {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) DeleteState(string) error {
|
||||
return backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) State(name string) (state.State, error) {
|
||||
if name != backend.DefaultStateName {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
return &remote.State{
|
||||
Client: b.client,
|
||||
}, nil
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
package artifactory
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
||||
)
|
||||
|
||||
const ARTIF_TFSTATE_NAME = "terraform.tfstate"
|
||||
|
||||
type ArtifactoryClient struct {
|
||||
nativeClient *artifactory.ArtifactoryClient
|
||||
userName string
|
||||
password string
|
||||
url string
|
||||
repo string
|
||||
subpath string
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Get() (*remote.Payload, error) {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
output, err := c.nativeClient.Get(p, make(map[string]string))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "404") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: migrate to using X-Checksum-Md5 header from artifactory
|
||||
// needs to be exposed by go-artifactory first
|
||||
|
||||
hash := md5.Sum(output)
|
||||
payload := &remote.Payload{
|
||||
Data: output,
|
||||
MD5: hash[:md5.Size],
|
||||
}
|
||||
|
||||
// If there was no data, then return nil
|
||||
if len(payload.Data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Put(data []byte) error {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
if _, err := c.nativeClient.Put(p, string(data), make(map[string]string)); err == nil {
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("Failed to upload state: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Delete() error {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
err := c.nativeClient.Delete(p)
|
||||
return err
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
||||
)
|
||||
|
||||
const ARTIF_TFSTATE_NAME = "terraform.tfstate"
|
||||
|
||||
func artifactoryFactory(conf map[string]string) (Client, error) {
|
||||
userName, ok := conf["username"]
|
||||
if !ok {
|
||||
userName = os.Getenv("ARTIFACTORY_USERNAME")
|
||||
if userName == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"missing 'username' configuration or ARTIFACTORY_USERNAME environment variable")
|
||||
}
|
||||
}
|
||||
password, ok := conf["password"]
|
||||
if !ok {
|
||||
password = os.Getenv("ARTIFACTORY_PASSWORD")
|
||||
if password == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"missing 'password' configuration or ARTIFACTORY_PASSWORD environment variable")
|
||||
}
|
||||
}
|
||||
url, ok := conf["url"]
|
||||
if !ok {
|
||||
url = os.Getenv("ARTIFACTORY_URL")
|
||||
if url == "" {
|
||||
return nil, fmt.Errorf(
|
||||
"missing 'url' configuration or ARTIFACTORY_URL environment variable")
|
||||
}
|
||||
}
|
||||
repo, ok := conf["repo"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(
|
||||
"missing 'repo' configuration")
|
||||
}
|
||||
subpath, ok := conf["subpath"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf(
|
||||
"missing 'subpath' configuration")
|
||||
}
|
||||
|
||||
clientConf := &artifactory.ClientConfig{
|
||||
BaseURL: url,
|
||||
Username: userName,
|
||||
Password: password,
|
||||
}
|
||||
nativeClient := artifactory.NewClient(clientConf)
|
||||
|
||||
return &ArtifactoryClient{
|
||||
nativeClient: &nativeClient,
|
||||
userName: userName,
|
||||
password: password,
|
||||
url: url,
|
||||
repo: repo,
|
||||
subpath: subpath,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
type ArtifactoryClient struct {
|
||||
nativeClient *artifactory.ArtifactoryClient
|
||||
userName string
|
||||
password string
|
||||
url string
|
||||
repo string
|
||||
subpath string
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Get() (*Payload, error) {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
output, err := c.nativeClient.Get(p, make(map[string]string))
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "404") {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: migrate to using X-Checksum-Md5 header from artifactory
|
||||
// needs to be exposed by go-artifactory first
|
||||
|
||||
hash := md5.Sum(output)
|
||||
payload := &Payload{
|
||||
Data: output,
|
||||
MD5: hash[:md5.Size],
|
||||
}
|
||||
|
||||
// If there was no data, then return nil
|
||||
if len(payload.Data) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return payload, nil
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Put(data []byte) error {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
if _, err := c.nativeClient.Put(p, string(data), make(map[string]string)); err == nil {
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("Failed to upload state: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ArtifactoryClient) Delete() error {
|
||||
p := fmt.Sprintf("%s/%s/%s", c.repo, c.subpath, ARTIF_TFSTATE_NAME)
|
||||
err := c.nativeClient.Delete(p)
|
||||
return err
|
||||
}
|
||||
Loading…
Reference in new issue