Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

datasources added: artifactory_file & artifactory_fileinfo #65

Merged
merged 10 commits into from
Dec 16, 2019
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module github.com/atlassian/terraform-provider-artifactory

require (
github.com/atlassian/go-artifactory/v2 v2.4.0
github.com/atlassian/go-artifactory/v2 v2.5.0
github.com/hashicorp/terraform v0.12.0
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/atlassian/go-artifactory/v2 v2.4.0 h1:qj2nlDREa8BB03a09BcE+bj7gwlj/VXuD2hBvV80PDM=
github.com/atlassian/go-artifactory/v2 v2.4.0/go.mod h1:mMEbxu89yTyKev4mysL03aSioTEdZ8+08KuMGG7myUY=
github.com/atlassian/go-artifactory/v2 v2.5.0 h1:NKs9kuGgb2Gj+pU+Y7BzFlx6D/e6P82zP3m/FJZpy40=
github.com/atlassian/go-artifactory/v2 v2.5.0/go.mod h1:mMEbxu89yTyKev4mysL03aSioTEdZ8+08KuMGG7myUY=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.16.36/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.19.18 h1:Hb3+b9HCqrOrbAtFstUWg7H5TQ+/EcklJtE8VShVs8o=
Expand Down
142 changes: 142 additions & 0 deletions pkg/artifactory/datasource_artifactory_file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package artifactory

import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"github.com/atlassian/go-artifactory/v2/artifactory"
"github.com/hashicorp/terraform/helper/schema"
"io"
"os"
)

func dataSourceArtifactoryFile() *schema.Resource {
return &schema.Resource{
Read: dataSourceFileRead,

Schema: map[string]*schema.Schema{
"repository": {
Type: schema.TypeString,
Required: true,
},
"path": {
Type: schema.TypeString,
Required: true,
},
"created": {
Type: schema.TypeString,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"last_modified": {
Type: schema.TypeString,
Computed: true,
},
"modified_by": {
Type: schema.TypeString,
Computed: true,
},
"last_updated": {
Type: schema.TypeString,
Computed: true,
},
"download_uri": {
Type: schema.TypeString,
Computed: true,
},
"mimetype": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"md5": {
Type: schema.TypeString,
Computed: true,
},
"sha1": {
Type: schema.TypeString,
Computed: true,
},
"sha256": {
Type: schema.TypeString,
Computed: true,
},
"output_path": {
Type: schema.TypeString,
Required: true,
},
"force_overwrite": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
},
}
}

func dataSourceFileRead(d *schema.ResourceData, m interface{}) error {
c := m.(*artifactory.Artifactory)

repository := d.Get("repository").(string)
path := d.Get("path").(string)
outputPath := d.Get("output_path").(string)
forceOverwrite := d.Get("force_overwrite").(bool)

fileInfo, _, err := c.V1.Artifacts.FileInfo(context.Background(), repository, path)
if err != nil {
return err
}

fileExists := FileExists(outputPath)
chksMatches, _ := VerifySha256Checksum(outputPath, *fileInfo.Checksums.Sha256)

if !fileExists || (!chksMatches && forceOverwrite) {
outFile, err := os.Create(outputPath)
if err != nil {
return err
}

defer outFile.Close()

fileInfo, _, err = c.V1.Artifacts.FileContents(context.Background(), repository, path, outFile)
if err != nil {
return err
}
} else if !chksMatches {
return fmt.Errorf("Local file differs from upstream version")
}

return packFileInfo(fileInfo, d)
}

func FileExists(path string) bool {
if _, err := os.Stat(path); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}

func VerifySha256Checksum(path string, expectedSha256 string) (bool, error) {
f, err := os.Open(path)
if err != nil {
return false, err
}
defer f.Close()

hasher := sha256.New()

if _, err := io.Copy(hasher, f); err != nil {
return false, err
}

return hex.EncodeToString(hasher.Sum(nil)) == expectedSha256, nil
}
56 changes: 56 additions & 0 deletions pkg/artifactory/datasource_artifactory_file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package artifactory

import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"path/filepath"
"testing"
)

func TestFileExists(t *testing.T) {
tmpFile, err := CreateTempFile("test")

assert.Nil(t, err)

defer CloseAndRemove(tmpFile)

existingPath, _ := filepath.Abs(tmpFile.Name())
nonExistingPath := existingPath + "-doesnt-exist"

assert.Equal(t, true, FileExists(existingPath))
assert.Equal(t, false, FileExists(nonExistingPath))
}

func TestVerifySha256Checksum(t *testing.T) {
const testString = "test content"
const expectedSha256 = "6ae8a75555209fd6c44157c0aed8016e763ff435a19cf186f76863140143ff72"

file, err := CreateTempFile(testString)

assert.Nil(t, err)

defer CloseAndRemove(file)

filePath, _ := filepath.Abs(file.Name())

sha256Verified, err := VerifySha256Checksum(filePath, expectedSha256)

assert.Nil(t, err)
assert.Equal(t, true, sha256Verified)
}

func CreateTempFile(content string) (f *os.File, err error) {
file, err := ioutil.TempFile(os.TempDir(), "terraform-provider-artifactory-")

if content != "" {
file.WriteString(content)
}

return file, err
}

func CloseAndRemove(f *os.File) {
f.Close()
os.Remove(f.Name())
}
112 changes: 112 additions & 0 deletions pkg/artifactory/datasource_artifactory_fileinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package artifactory

import (
"context"
"fmt"
"github.com/atlassian/go-artifactory/v2/artifactory"
"github.com/atlassian/go-artifactory/v2/artifactory/v1"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceArtifactoryFileInfo() *schema.Resource {
return &schema.Resource{
Read: dataSourceFileInfoRead,

Schema: map[string]*schema.Schema{
"repository": {
Type: schema.TypeString,
Required: true,
},
"path": {
Type: schema.TypeString,
Required: true,
},
"created": {
Type: schema.TypeString,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Computed: true,
},
"last_modified": {
Type: schema.TypeString,
Computed: true,
},
"modified_by": {
Type: schema.TypeString,
Computed: true,
},
"last_updated": {
Type: schema.TypeString,
Computed: true,
},
"download_uri": {
Type: schema.TypeString,
Computed: true,
},
"mimetype": {
Type: schema.TypeString,
Computed: true,
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"md5": {
Type: schema.TypeString,
Computed: true,
},
"sha1": {
Type: schema.TypeString,
Computed: true,
},
"sha256": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceFileInfoRead(d *schema.ResourceData, m interface{}) error {
c := m.(*artifactory.Artifactory)

repository := d.Get("repository").(string)
path := d.Get("path").(string)

fileInfo, _, err := c.V1.Artifacts.FileInfo(context.Background(), repository, path)
if err != nil {
return err
}

return packFileInfo(fileInfo, d)
}

func packFileInfo(fileInfo *v1.FileInfo, d *schema.ResourceData) error {
hasErr := false
logErr := cascadingErr(&hasErr)

d.SetId(*fileInfo.DownloadUri)

logErr(d.Set("created", *fileInfo.Created))
logErr(d.Set("created_by", *fileInfo.CreatedBy))
logErr(d.Set("last_modified", *fileInfo.LastModified))
logErr(d.Set("modified_by", *fileInfo.ModifiedBy))
logErr(d.Set("last_updated", *fileInfo.LastUpdated))
logErr(d.Set("download_uri", *fileInfo.DownloadUri))
logErr(d.Set("mimetype", *fileInfo.MimeType))
logErr(d.Set("size", *fileInfo.Size))

if fileInfo.Checksums != nil {
logErr(d.Set("md5", *fileInfo.Checksums.Md5))
logErr(d.Set("sha1", *fileInfo.Checksums.Sha1))
logErr(d.Set("sha256", *fileInfo.Checksums.Sha256))
}

if hasErr {
return fmt.Errorf("failed to pack fileInfo")
}

return nil
}
5 changes: 5 additions & 0 deletions pkg/artifactory/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ func Provider() terraform.ResourceProvider {
"artifactory_permission_targets": resourceArtifactoryPermissionTargets(),
},

DataSourcesMap: map[string]*schema.Resource{
"artifactory_file": dataSourceArtifactoryFile(),
"artifactory_fileinfo": dataSourceArtifactoryFileInfo(),
},

ConfigureFunc: providerConfigure,
}
}
Expand Down
4 changes: 4 additions & 0 deletions website/docs/index.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ with the proper credentials before it can be used.
* [Virtual Repositories](./r/artifactory_virtual_repository.html.markdown)
* [Certificates](./r/artifactory_certificate.html.markdown)

- Available Datasources
* [File](./r/artifactory_file.html.markdown)
* [FileInfo](./r/artifactory_fileinfo.html.markdown)

- Deprecated Resources
* [Permission Targets (V1 API)](./r/artifactory_permission_target_v1.html.markdown)

Expand Down
Loading