mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-04 17:51:11 +00:00
Merge pull request #3272 from lwander/f-gce-bucket-acls
provider/gce: Implemented bucket & object ACLs, as well as documentation and tests
This commit is contained in:
commit
29368d3219
@ -54,7 +54,9 @@ func Provider() terraform.ResourceProvider {
|
|||||||
"google_dns_record_set": resourceDnsRecordSet(),
|
"google_dns_record_set": resourceDnsRecordSet(),
|
||||||
"google_compute_instance_group_manager": resourceComputeInstanceGroupManager(),
|
"google_compute_instance_group_manager": resourceComputeInstanceGroupManager(),
|
||||||
"google_storage_bucket": resourceStorageBucket(),
|
"google_storage_bucket": resourceStorageBucket(),
|
||||||
|
"google_storage_bucket_acl": resourceStorageBucketAcl(),
|
||||||
"google_storage_bucket_object": resourceStorageBucketObject(),
|
"google_storage_bucket_object": resourceStorageBucketObject(),
|
||||||
|
"google_storage_object_acl": resourceStorageObjectAcl(),
|
||||||
},
|
},
|
||||||
|
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
|
@ -24,10 +24,10 @@ func resourceStorageBucket() *schema.Resource {
|
|||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
"predefined_acl": &schema.Schema{
|
"predefined_acl": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Default: "projectPrivate",
|
Deprecated: "Please use resource \"storage_bucket_acl.predefined_acl\" instead.",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
"location": &schema.Schema{
|
"location": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
@ -69,7 +69,6 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error
|
|||||||
|
|
||||||
// Get the bucket and acl
|
// Get the bucket and acl
|
||||||
bucket := d.Get("name").(string)
|
bucket := d.Get("name").(string)
|
||||||
acl := d.Get("predefined_acl").(string)
|
|
||||||
location := d.Get("location").(string)
|
location := d.Get("location").(string)
|
||||||
|
|
||||||
// Create a bucket, setting the acl, location and name.
|
// Create a bucket, setting the acl, location and name.
|
||||||
@ -95,7 +94,12 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := config.clientStorage.Buckets.Insert(config.Project, sb).PredefinedAcl(acl).Do()
|
call := config.clientStorage.Buckets.Insert(config.Project, sb)
|
||||||
|
if v, ok := d.GetOk("predefined_acl"); ok {
|
||||||
|
call = call.PredefinedAcl(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := call.Do()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error creating bucket %s: %v", bucket, err)
|
fmt.Printf("Error creating bucket %s: %v", bucket, err)
|
||||||
|
292
resource_storage_bucket_acl.go
Normal file
292
resource_storage_bucket_acl.go
Normal file
@ -0,0 +1,292 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
"google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceStorageBucketAcl() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceStorageBucketAclCreate,
|
||||||
|
Read: resourceStorageBucketAclRead,
|
||||||
|
Update: resourceStorageBucketAclUpdate,
|
||||||
|
Delete: resourceStorageBucketAclDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"bucket": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"predefined_acl": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"role_entity": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"default_acl": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RoleEntity struct {
|
||||||
|
Role string
|
||||||
|
Entity string
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBucketAclId(bucket string) string {
|
||||||
|
return bucket + "-acl"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRoleEntityPair(role_entity string) (*RoleEntity, error) {
|
||||||
|
split := strings.Split(role_entity, ":")
|
||||||
|
if len(split) != 2 {
|
||||||
|
return nil, fmt.Errorf("Error, each role entity pair must be " +
|
||||||
|
"formatted as ROLE:entity")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RoleEntity{Role: split[0], Entity: split[1]}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageBucketAclCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
predefined_acl := ""
|
||||||
|
default_acl := ""
|
||||||
|
role_entity := make([]interface{}, 0)
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("predefined_acl"); ok {
|
||||||
|
predefined_acl = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("role_entity"); ok {
|
||||||
|
role_entity = v.([]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("default_acl"); ok {
|
||||||
|
default_acl = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(predefined_acl) > 0 {
|
||||||
|
if len(role_entity) > 0 {
|
||||||
|
return fmt.Errorf("Error, you cannot specify both " +
|
||||||
|
"\"predefined_acl\" and \"role_entity\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := config.clientStorage.Buckets.Get(bucket).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = config.clientStorage.Buckets.Update(bucket,
|
||||||
|
res).PredefinedAcl(predefined_acl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
} else if len(role_entity) > 0 {
|
||||||
|
for _, v := range(role_entity) {
|
||||||
|
pair, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
bucketAccessControl := &storage.BucketAccessControl{
|
||||||
|
Role: pair.Role,
|
||||||
|
Entity: pair.Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG]: storing re %s-%s", pair.Role, pair.Entity)
|
||||||
|
|
||||||
|
_, err = config.clientStorage.BucketAccessControls.Insert(bucket, bucketAccessControl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(default_acl) > 0 {
|
||||||
|
res, err := config.clientStorage.Buckets.Get(bucket).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = config.clientStorage.Buckets.Update(bucket,
|
||||||
|
res).PredefinedDefaultObjectAcl(default_acl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func resourceStorageBucketAclRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
|
||||||
|
// Predefined ACLs cannot easily be parsed once they have been processed
|
||||||
|
// by the GCP server
|
||||||
|
if _, ok := d.GetOk("predefined_acl"); !ok {
|
||||||
|
role_entity := make([]interface{}, 0)
|
||||||
|
re_local := d.Get("role_entity").([]interface{})
|
||||||
|
re_local_map := make(map[string]string)
|
||||||
|
for _, v := range(re_local) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Old state has malformed Role/Entity pair: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
re_local_map[res.Entity] = res.Role
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := config.clientStorage.BucketAccessControls.List(bucket).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range(res.Items) {
|
||||||
|
log.Printf("[DEBUG]: examining re %s-%s", v.Role, v.Entity)
|
||||||
|
// We only store updates to the locally defined access controls
|
||||||
|
if _, in := re_local_map[v.Entity]; in {
|
||||||
|
role_entity = append(role_entity, fmt.Sprintf("%s:%s", v.Role, v.Entity))
|
||||||
|
log.Printf("[DEBUG]: saving re %s-%s", v.Role, v.Entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("role_entity", role_entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(getBucketAclId(bucket))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageBucketAclUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
|
||||||
|
if d.HasChange("role_entity") {
|
||||||
|
o, n := d.GetChange("role_entity")
|
||||||
|
old_re, new_re := o.([]interface{}), n.([]interface{})
|
||||||
|
|
||||||
|
old_re_map := make(map[string]string)
|
||||||
|
for _, v := range(old_re) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Old state has malformed Role/Entity pair: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
old_re_map[res.Entity] = res.Role
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range(new_re) {
|
||||||
|
pair, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
bucketAccessControl := &storage.BucketAccessControl{
|
||||||
|
Role: pair.Role,
|
||||||
|
Entity: pair.Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the old state is missing this entity, it needs to
|
||||||
|
// be created. Otherwise it is updated
|
||||||
|
if _, ok := old_re_map[pair.Entity]; ok {
|
||||||
|
_, err = config.clientStorage.BucketAccessControls.Update(
|
||||||
|
bucket, pair.Entity, bucketAccessControl).Do()
|
||||||
|
} else {
|
||||||
|
_, err = config.clientStorage.BucketAccessControls.Insert(
|
||||||
|
bucket, bucketAccessControl).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we only store the keys that have to be removed
|
||||||
|
delete(old_re_map, pair.Entity)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity, _ := range(old_re_map) {
|
||||||
|
log.Printf("[DEBUG]: removing entity %s", entity)
|
||||||
|
err := config.clientStorage.BucketAccessControls.Delete(bucket, entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating ACL for bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange("default_acl") {
|
||||||
|
default_acl := d.Get("default_acl").(string)
|
||||||
|
|
||||||
|
res, err := config.clientStorage.Buckets.Get(bucket).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = config.clientStorage.Buckets.Update(bucket,
|
||||||
|
res).PredefinedDefaultObjectAcl(default_acl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating bucket %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageBucketAclDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
|
||||||
|
re_local := d.Get("role_entity").([]interface{})
|
||||||
|
for _, v := range(re_local) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG]: removing entity %s", res.Entity)
|
||||||
|
|
||||||
|
err = config.clientStorage.BucketAccessControls.Delete(bucket, res.Entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting entity %s ACL: %s", res.Entity, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
232
resource_storage_bucket_acl_test.go
Normal file
232
resource_storage_bucket_acl_test.go
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
|
||||||
|
//"google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var roleEntityBasic1 = "OWNER:user-omeemail@gmail.com"
|
||||||
|
|
||||||
|
var roleEntityBasic2 = "READER:user-anotheremail@gmail.com"
|
||||||
|
|
||||||
|
var roleEntityBasic3_owner = "OWNER:user-yetanotheremail@gmail.com"
|
||||||
|
|
||||||
|
var roleEntityBasic3_reader = "READER:user-yetanotheremail@gmail.com"
|
||||||
|
|
||||||
|
var testAclBucketName = fmt.Sprintf("%s-%d", "tf-test-acl-bucket", rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
||||||
|
|
||||||
|
func TestAccGoogleStorageBucketAcl_basic(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageBucketAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasic1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic2),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageBucketAcl_upgrade(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageBucketAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasic1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic2),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasic2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasicDelete,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageBucketAcl_downgrade(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageBucketAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasic2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasic3,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageBucketAcl(testAclBucketName, roleEntityBasic3_reader),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclBasicDelete,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageBucketAclDelete(testAclBucketName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageBucketAcl_predefined(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageBucketAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageBucketsAclPredefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckGoogleStorageBucketAclDelete(bucket, roleEntityS string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
roleEntity, _ := getRoleEntityPair(roleEntityS)
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
_, err := config.clientStorage.BucketAccessControls.Get(bucket, roleEntity.Entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error, entity %s still exists", roleEntity.Entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckGoogleStorageBucketAcl(bucket, roleEntityS string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
roleEntity, _ := getRoleEntityPair(roleEntityS)
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
res, err := config.clientStorage.BucketAccessControls.Get(bucket, roleEntity.Entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving contents of acl for bucket %s: %s", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.Role != roleEntity.Role) {
|
||||||
|
return fmt.Errorf("Error, Role mismatch %s != %s", res.Role, roleEntity.Role)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccGoogleStorageBucketAclDestroy(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_storage_bucket_acl" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket := rs.Primary.Attributes["bucket"]
|
||||||
|
|
||||||
|
_, err := config.clientStorage.BucketAccessControls.List(bucket).Do()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Acl for bucket %s still exists", bucket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testGoogleStorageBucketsAclBasic1 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_acl" "acl" {
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, roleEntityBasic1, roleEntityBasic2)
|
||||||
|
|
||||||
|
var testGoogleStorageBucketsAclBasic2 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_acl" "acl" {
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, roleEntityBasic2, roleEntityBasic3_owner)
|
||||||
|
|
||||||
|
var testGoogleStorageBucketsAclBasicDelete = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_acl" "acl" {
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = []
|
||||||
|
}
|
||||||
|
`, testAclBucketName)
|
||||||
|
|
||||||
|
var testGoogleStorageBucketsAclBasic3 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_acl" "acl" {
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, roleEntityBasic2, roleEntityBasic3_reader)
|
||||||
|
|
||||||
|
|
||||||
|
var testGoogleStorageBucketsAclPredefined = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_acl" "acl" {
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
predefined_acl = "projectPrivate"
|
||||||
|
default_acl = "projectPrivate"
|
||||||
|
}
|
||||||
|
`, testAclBucketName)
|
@ -33,7 +33,7 @@ func resourceStorageBucketObject() *schema.Resource {
|
|||||||
},
|
},
|
||||||
"predefined_acl": &schema.Schema{
|
"predefined_acl": &schema.Schema{
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Default: "projectPrivate",
|
Deprecated: "Please use resource \"storage_object_acl.predefined_acl\" instead.",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
ForceNew: true,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
@ -59,7 +59,6 @@ func resourceStorageBucketObjectCreate(d *schema.ResourceData, meta interface{})
|
|||||||
bucket := d.Get("bucket").(string)
|
bucket := d.Get("bucket").(string)
|
||||||
name := d.Get("name").(string)
|
name := d.Get("name").(string)
|
||||||
source := d.Get("source").(string)
|
source := d.Get("source").(string)
|
||||||
acl := d.Get("predefined_acl").(string)
|
|
||||||
|
|
||||||
file, err := os.Open(source)
|
file, err := os.Open(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -72,7 +71,10 @@ func resourceStorageBucketObjectCreate(d *schema.ResourceData, meta interface{})
|
|||||||
insertCall := objectsService.Insert(bucket, object)
|
insertCall := objectsService.Insert(bucket, object)
|
||||||
insertCall.Name(name)
|
insertCall.Name(name)
|
||||||
insertCall.Media(file)
|
insertCall.Media(file)
|
||||||
insertCall.PredefinedAcl(acl)
|
if v, ok := d.GetOk("predefined_acl"); ok {
|
||||||
|
insertCall.PredefinedAcl(v.(string))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
_, err = insertCall.Do()
|
_, err = insertCall.Do()
|
||||||
|
|
||||||
|
254
resource_storage_object_acl.go
Normal file
254
resource_storage_object_acl.go
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
|
||||||
|
"google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceStorageObjectAcl() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceStorageObjectAclCreate,
|
||||||
|
Read: resourceStorageObjectAclRead,
|
||||||
|
Update: resourceStorageObjectAclUpdate,
|
||||||
|
Delete: resourceStorageObjectAclDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"bucket": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"object": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
"role_entity": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
"predefined_acl": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getObjectAclId(object string) string {
|
||||||
|
return object + "-acl"
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageObjectAclCreate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
object := d.Get("object").(string)
|
||||||
|
|
||||||
|
predefined_acl := ""
|
||||||
|
role_entity := make([]interface{}, 0)
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("predefined_acl"); ok {
|
||||||
|
predefined_acl = v.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk("role_entity"); ok {
|
||||||
|
role_entity = v.([]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(predefined_acl) > 0 {
|
||||||
|
if len(role_entity) > 0 {
|
||||||
|
return fmt.Errorf("Error, you cannot specify both " +
|
||||||
|
"\"predefined_acl\" and \"role_entity\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := config.clientStorage.Objects.Get(bucket, object).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error reading object %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err = config.clientStorage.Objects.Update(bucket,object,
|
||||||
|
res).PredefinedAcl(predefined_acl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating object %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageBucketAclRead(d, meta);
|
||||||
|
} else if len(role_entity) > 0 {
|
||||||
|
for _, v := range(role_entity) {
|
||||||
|
pair, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
objectAccessControl := &storage.ObjectAccessControl{
|
||||||
|
Role: pair.Role,
|
||||||
|
Entity: pair.Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[DEBUG]: setting role = %s, entity = %s", pair.Role, pair.Entity)
|
||||||
|
|
||||||
|
_, err = config.clientStorage.ObjectAccessControls.Insert(bucket,
|
||||||
|
object, objectAccessControl).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error setting ACL for %s on object %s: %v", pair.Entity, object, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageObjectAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error, you must specify either " +
|
||||||
|
"\"predefined_acl\" or \"role_entity\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func resourceStorageObjectAclRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
object := d.Get("object").(string)
|
||||||
|
|
||||||
|
// Predefined ACLs cannot easily be parsed once they have been processed
|
||||||
|
// by the GCP server
|
||||||
|
if _, ok := d.GetOk("predefined_acl"); !ok {
|
||||||
|
role_entity := make([]interface{}, 0)
|
||||||
|
re_local := d.Get("role_entity").([]interface{})
|
||||||
|
re_local_map := make(map[string]string)
|
||||||
|
for _, v := range(re_local) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Old state has malformed Role/Entity pair: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
re_local_map[res.Entity] = res.Role
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := config.clientStorage.ObjectAccessControls.List(bucket, object).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range(res.Items) {
|
||||||
|
role := ""
|
||||||
|
entity := ""
|
||||||
|
for key, val := range (v.(map[string]interface{})) {
|
||||||
|
if key == "role" {
|
||||||
|
role = val.(string)
|
||||||
|
} else if key == "entity" {
|
||||||
|
entity = val.(string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, in := re_local_map[entity]; in {
|
||||||
|
role_entity = append(role_entity, fmt.Sprintf("%s:%s", role, entity))
|
||||||
|
log.Printf("[DEBUG]: saving re %s-%s", role, entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("role_entity", role_entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(getObjectAclId(object))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageObjectAclUpdate(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
object := d.Get("object").(string)
|
||||||
|
|
||||||
|
if d.HasChange("role_entity") {
|
||||||
|
o, n := d.GetChange("role_entity")
|
||||||
|
old_re, new_re := o.([]interface{}), n.([]interface{})
|
||||||
|
|
||||||
|
old_re_map := make(map[string]string)
|
||||||
|
for _, v := range(old_re) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Old state has malformed Role/Entity pair: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
old_re_map[res.Entity] = res.Role
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range(new_re) {
|
||||||
|
pair, err := getRoleEntityPair(v.(string))
|
||||||
|
|
||||||
|
objectAccessControl := &storage.ObjectAccessControl{
|
||||||
|
Role: pair.Role,
|
||||||
|
Entity: pair.Entity,
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the old state is missing this entity, it needs to
|
||||||
|
// be created. Otherwise it is updated
|
||||||
|
if _, ok := old_re_map[pair.Entity]; ok {
|
||||||
|
_, err = config.clientStorage.ObjectAccessControls.Update(
|
||||||
|
bucket, object, pair.Entity, objectAccessControl).Do()
|
||||||
|
} else {
|
||||||
|
_, err = config.clientStorage.ObjectAccessControls.Insert(
|
||||||
|
bucket, object, objectAccessControl).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we only store the keys that have to be removed
|
||||||
|
delete(old_re_map, pair.Entity)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for entity, _ := range(old_re_map) {
|
||||||
|
log.Printf("[DEBUG]: removing entity %s", entity)
|
||||||
|
err := config.clientStorage.ObjectAccessControls.Delete(bucket, object, entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error updating ACL for object %s: %v", bucket, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceStorageObjectAclRead(d, meta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStorageObjectAclDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
config := meta.(*Config)
|
||||||
|
|
||||||
|
bucket := d.Get("bucket").(string)
|
||||||
|
object := d.Get("object").(string)
|
||||||
|
|
||||||
|
re_local := d.Get("role_entity").([]interface{})
|
||||||
|
for _, v := range(re_local) {
|
||||||
|
res, err := getRoleEntityPair(v.(string))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entity := res.Entity
|
||||||
|
|
||||||
|
log.Printf("[DEBUG]: removing entity %s", entity)
|
||||||
|
|
||||||
|
err = config.clientStorage.ObjectAccessControls.Delete(bucket, object,
|
||||||
|
entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error deleting entity %s ACL: %s",
|
||||||
|
entity, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
310
resource_storage_object_acl_test.go
Normal file
310
resource_storage_object_acl_test.go
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
package google
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
"math/rand"
|
||||||
|
"io/ioutil"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
|
||||||
|
//"google.golang.org/api/storage/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tfObjectAcl, errObjectAcl = ioutil.TempFile("", "tf-gce-test")
|
||||||
|
var testAclObjectName = fmt.Sprintf("%s-%d", "tf-test-acl-object",
|
||||||
|
rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
||||||
|
|
||||||
|
func TestAccGoogleStorageObjectAcl_basic(t *testing.T) {
|
||||||
|
objectData := []byte("data data data")
|
||||||
|
ioutil.WriteFile(tfObjectAcl.Name(), objectData, 0644)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
if errObjectAcl != nil {
|
||||||
|
panic(errObjectAcl)
|
||||||
|
}
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageObjectAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasic1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageObjectAcl_upgrade(t *testing.T) {
|
||||||
|
objectData := []byte("data data data")
|
||||||
|
ioutil.WriteFile(tfObjectAcl.Name(), objectData, 0644)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
if errObjectAcl != nil {
|
||||||
|
panic(errObjectAcl)
|
||||||
|
}
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageObjectAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasic1,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasic2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasicDelete,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic3_reader),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageObjectAcl_downgrade(t *testing.T) {
|
||||||
|
objectData := []byte("data data data")
|
||||||
|
ioutil.WriteFile(tfObjectAcl.Name(), objectData, 0644)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
if errObjectAcl != nil {
|
||||||
|
panic(errObjectAcl)
|
||||||
|
}
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageObjectAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasic2,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic3_owner),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasic3,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageObjectAcl(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic3_reader),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclBasicDelete,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic1),
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic2),
|
||||||
|
testAccCheckGoogleStorageObjectAclDelete(testAclBucketName,
|
||||||
|
testAclObjectName, roleEntityBasic3_reader),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccGoogleStorageObjectAcl_predefined(t *testing.T) {
|
||||||
|
objectData := []byte("data data data")
|
||||||
|
ioutil.WriteFile(tfObjectAcl.Name(), objectData, 0644)
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() {
|
||||||
|
if errObjectAcl != nil {
|
||||||
|
panic(errObjectAcl)
|
||||||
|
}
|
||||||
|
testAccPreCheck(t)
|
||||||
|
},
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccGoogleStorageObjectAclDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testGoogleStorageObjectsAclPredefined,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckGoogleStorageObjectAcl(bucket, object, roleEntityS string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
roleEntity, _ := getRoleEntityPair(roleEntityS)
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
res, err := config.clientStorage.ObjectAccessControls.Get(bucket,
|
||||||
|
object, roleEntity.Entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error retrieving contents of acl for bucket %s: %s", bucket, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.Role != roleEntity.Role) {
|
||||||
|
return fmt.Errorf("Error, Role mismatch %s != %s", res.Role, roleEntity.Role)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckGoogleStorageObjectAclDelete(bucket, object, roleEntityS string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
roleEntity, _ := getRoleEntityPair(roleEntityS)
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
_, err := config.clientStorage.ObjectAccessControls.Get(bucket,
|
||||||
|
object, roleEntity.Entity).Do()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Error, Entity still exists %s", roleEntity.Entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccGoogleStorageObjectAclDestroy(s *terraform.State) error {
|
||||||
|
config := testAccProvider.Meta().(*Config)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
if rs.Type != "google_storage_bucket_acl" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bucket := rs.Primary.Attributes["bucket"]
|
||||||
|
object := rs.Primary.Attributes["object"]
|
||||||
|
|
||||||
|
_, err := config.clientStorage.ObjectAccessControls.List(bucket, object).Do()
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
return fmt.Errorf("Acl for bucket %s still exists", bucket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var testGoogleStorageObjectsAclBasicDelete = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "object" {
|
||||||
|
name = "%s"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
source = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_object_acl" "acl" {
|
||||||
|
object = "${google_storage_bucket_object.object.name}"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = []
|
||||||
|
}
|
||||||
|
`, testAclBucketName, testAclObjectName, tfObjectAcl.Name())
|
||||||
|
|
||||||
|
var testGoogleStorageObjectsAclBasic1 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "object" {
|
||||||
|
name = "%s"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
source = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_object_acl" "acl" {
|
||||||
|
object = "${google_storage_bucket_object.object.name}"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, testAclObjectName, tfObjectAcl.Name(),
|
||||||
|
roleEntityBasic1, roleEntityBasic2)
|
||||||
|
|
||||||
|
var testGoogleStorageObjectsAclBasic2 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "object" {
|
||||||
|
name = "%s"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
source = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_object_acl" "acl" {
|
||||||
|
object = "${google_storage_bucket_object.object.name}"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, testAclObjectName, tfObjectAcl.Name(),
|
||||||
|
roleEntityBasic2, roleEntityBasic3_owner)
|
||||||
|
|
||||||
|
var testGoogleStorageObjectsAclBasic3 = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "object" {
|
||||||
|
name = "%s"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
source = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_object_acl" "acl" {
|
||||||
|
object = "${google_storage_bucket_object.object.name}"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
role_entity = ["%s", "%s"]
|
||||||
|
}
|
||||||
|
`, testAclBucketName, testAclObjectName, tfObjectAcl.Name(),
|
||||||
|
roleEntityBasic2, roleEntityBasic3_reader)
|
||||||
|
|
||||||
|
var testGoogleStorageObjectsAclPredefined = fmt.Sprintf(`
|
||||||
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
name = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_object" "object" {
|
||||||
|
name = "%s"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
source = "%s"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_object_acl" "acl" {
|
||||||
|
object = "${google_storage_bucket_object.object.name}"
|
||||||
|
bucket = "${google_storage_bucket.bucket.name}"
|
||||||
|
predefined_acl = "projectPrivate"
|
||||||
|
}
|
||||||
|
`, testAclBucketName, testAclObjectName, tfObjectAcl.Name())
|
Loading…
Reference in New Issue
Block a user