- re-add ‘testAccPreCheck()’ to acceptance tests, to ensure necessary GOOGLE_* env vars are set for Acceptance tests.
- remove unused code from datasource
- use URL signature (base64 encoded) as data source ID instead of full URL
This commit is contained in:
Matt Morrison 2016-08-15 17:34:56 +12:00 committed by Matt Morrison
parent ef07ed149d
commit 6f833cd3d7
2 changed files with 22 additions and 27 deletions

View File

@ -17,14 +17,13 @@ import (
"log" "log"
"net/url" "net/url"
"os" "os"
"os/user"
"strconv" "strconv"
"strings" "strings"
"time" "time"
) )
const gcsBaseUrl = "https://storage.googleapis.com" const gcsBaseUrl = "https://storage.googleapis.com"
const envVar = "GOOGLE_APPLICATION_CREDENTIALS" const googleCredentialsEnvVar = "GOOGLE_APPLICATION_CREDENTIALS"
func dataSourceGoogleSignedUrl() *schema.Resource { func dataSourceGoogleSignedUrl() *schema.Resource {
return &schema.Resource{ return &schema.Resource{
@ -132,14 +131,14 @@ func dataSourceGoogleSignedUrlRead(d *schema.ResourceData, meta interface{}) err
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construct URL // Construct URL
finalUrl := urlData.BuildUrl() finalUrl := urlData.BuildUrl()
d.SetId(finalUrl) d.SetId(urlData.EncodedSignature())
d.Set("signed_url", finalUrl) d.Set("signed_url", finalUrl)
return nil return nil
} }
// This looks for credentials json in the following places, // This looks for credentials json in the following places,
// preferring the first location found: // in order of preference:
// //
// 1. Credentials provided in data source `credentials` attribute. // 1. Credentials provided in data source `credentials` attribute.
// 2. Credentials provided in the provider definition. // 2. Credentials provided in the provider definition.
@ -150,15 +149,15 @@ func loadJwtConfig(d *schema.ResourceData, meta interface{}) (*jwt.Config, error
credentials := "" credentials := ""
if v, ok := d.GetOk("credentials"); ok { if v, ok := d.GetOk("credentials"); ok {
log.Println("[DEBUG] using data source credentials") log.Println("[DEBUG] using data source credentials to sign URL")
credentials = v.(string) credentials = v.(string)
} else if config.Credentials != "" { } else if config.Credentials != "" {
log.Println("[DEBUG] using provider credentials") log.Println("[DEBUG] using provider credentials to sign URL")
credentials = config.Credentials credentials = config.Credentials
} else if filename := os.Getenv(envVar); filename != "" { } else if filename := os.Getenv(googleCredentialsEnvVar); filename != "" {
log.Println("[DEBUG] using env GOOGLE_APPLICATION_CREDENTIALS credentials") log.Println("[DEBUG] using env GOOGLE_APPLICATION_CREDENTIALS credentials to sign URL")
credentials = filename credentials = filename
} }
@ -179,14 +178,6 @@ func loadJwtConfig(d *schema.ResourceData, meta interface{}) (*jwt.Config, error
return nil, fmt.Errorf("Credentials not found in datasource, provider configuration or GOOGLE_APPLICATION_CREDENTIALS environment variable.") return nil, fmt.Errorf("Credentials not found in datasource, provider configuration or GOOGLE_APPLICATION_CREDENTIALS environment variable.")
} }
func guessUnixHomeDir() string {
usr, err := user.Current()
if err == nil {
return usr.HomeDir
}
return os.Getenv("HOME")
}
// parsePrivateKey converts the binary contents of a private key file // parsePrivateKey converts the binary contents of a private key file
// to an *rsa.PrivateKey. It detects whether the private key is in a // to an *rsa.PrivateKey. It detects whether the private key is in a
// PEM container or not. If so, it extracts the the private key // PEM container or not. If so, it extracts the the private key
@ -258,13 +249,18 @@ func (u *UrlData) CreateSigningString() []byte {
return buf.Bytes() return buf.Bytes()
} }
// Builds the final signed URL a client can use to retrieve storage object func (u *UrlData) EncodedSignature() string {
func (u *UrlData) BuildUrl() string {
// base64 encode signature // base64 encode signature
encoded := base64.StdEncoding.EncodeToString(u.Signature) encoded := base64.StdEncoding.EncodeToString(u.Signature)
// encoded signature may include /, = characters that need escaping // encoded signature may include /, = characters that need escaping
encoded = url.QueryEscape(encoded) encoded = url.QueryEscape(encoded)
return encoded
}
// Builds the final signed URL a client can use to retrieve storage object
func (u *UrlData) BuildUrl() string {
// set url // set url
// https://cloud.google.com/storage/docs/access-control/create-signed-urls-program // https://cloud.google.com/storage/docs/access-control/create-signed-urls-program
var urlBuffer bytes.Buffer var urlBuffer bytes.Buffer
@ -275,7 +271,7 @@ func (u *UrlData) BuildUrl() string {
urlBuffer.WriteString("&Expires=") urlBuffer.WriteString("&Expires=")
urlBuffer.WriteString(strconv.Itoa(u.Expires)) urlBuffer.WriteString(strconv.Itoa(u.Expires))
urlBuffer.WriteString("&Signature=") urlBuffer.WriteString("&Signature=")
urlBuffer.WriteString(encoded) urlBuffer.WriteString(u.EncodedSignature())
return urlBuffer.String() return urlBuffer.String()
} }

View File

@ -6,12 +6,12 @@ import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
"golang.org/x/oauth2/google" "golang.org/x/oauth2/google"
"io/ioutil" "io/ioutil"
"net/http"
"net/url" "net/url"
) )
@ -75,7 +75,7 @@ func TestUrlData_Signing(t *testing.T) {
} }
func TestUrlData_CreateUrl(t *testing.T) { func TestUrlData_BuildUrl(t *testing.T) {
// unescape and decode the expected signature // unescape and decode the expected signature
encodedSig, err := url.QueryUnescape(testUrlExpectedSignatureBase64Encoded) encodedSig, err := url.QueryUnescape(testUrlExpectedSignatureBase64Encoded)
if err != nil { if err != nil {
@ -107,7 +107,7 @@ func TestUrlData_CreateUrl(t *testing.T) {
func TestDatasourceSignedUrl_basic(t *testing.T) { func TestDatasourceSignedUrl_basic(t *testing.T) {
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
//PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders, Providers: testAccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ resource.TestStep{
@ -124,7 +124,7 @@ func TestDatasourceSignedUrl_accTest(t *testing.T) {
bucketName := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt()) bucketName := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt())
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
//PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders, Providers: testAccProviders,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
resource.TestStep{ resource.TestStep{
@ -163,12 +163,11 @@ func testAccGoogleSignedUrlRetrieval(n string) resource.TestCheckFunc {
url := a["signed_url"] url := a["signed_url"]
// send request to GET object using signed url // send request to GET object using signed url
client := http.DefaultClient client := cleanhttp.DefaultClient()
response, err := client.Get(url) response, err := client.Get(url)
if err != nil { if err != nil {
return err return err
} }
defer response.Body.Close() defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body) body, err := ioutil.ReadAll(response.Body)
if err != nil { if err != nil {