Skip to content

Commit

Permalink
Add resource_logging_billing_account_sink resource (#457)
Browse files Browse the repository at this point in the history
* Add resource_logging_billing_account_sink resource

* Fix bad style
  • Loading branch information
selmanj authored Sep 26, 2017
1 parent f8936fb commit 8231d6a
Show file tree
Hide file tree
Showing 8 changed files with 405 additions and 72 deletions.
1 change: 1 addition & 0 deletions google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ func Provider() terraform.ResourceProvider {
"google_dns_record_set": resourceDnsRecordSet(),
"google_folder": resourceGoogleFolder(),
"google_folder_iam_policy": resourceGoogleFolderIamPolicy(),
"google_logging_billing_account_sink": resourceLoggingBillingAccountSink(),
"google_logging_project_sink": resourceLoggingProjectSink(),
"google_sourcerepo_repository": resourceSourceRepoRepository(),
"google_spanner_instance": resourceSpannerInstance(),
Expand Down
75 changes: 75 additions & 0 deletions google/resource_logging_billing_account_sink.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package google

import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceLoggingBillingAccountSink() *schema.Resource {
schm := &schema.Resource{
Create: resourceLoggingBillingAccountSinkCreate,
Read: resourceLoggingBillingAccountSinkRead,
Delete: resourceLoggingBillingAccountSinkDelete,
Update: resourceLoggingBillingAccountSinkUpdate,
Schema: resourceLoggingSinkSchema(),
}
schm.Schema["billing_account"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
}
return schm
}

func resourceLoggingBillingAccountSinkCreate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

id, sink := expandResourceLoggingSink(d, "billingAccounts", d.Get("billing_account").(string))

// The API will reject any requests that don't explicitly set 'uniqueWriterIdentity' to true.
_, err := config.clientLogging.BillingAccounts.Sinks.Create(id.parent(), sink).UniqueWriterIdentity(true).Do()
if err != nil {
return err
}

d.SetId(id.canonicalId())
return resourceLoggingBillingAccountSinkRead(d, meta)
}

func resourceLoggingBillingAccountSinkRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

sink, err := config.clientLogging.BillingAccounts.Sinks.Get(d.Id()).Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("Billing Logging Sink %s", d.Get("name").(string)))
}

flattenResourceLoggingSink(d, sink)
return nil

}

func resourceLoggingBillingAccountSinkUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

sink := expandResourceLoggingSinkForUpdate(d)

// The API will reject any requests that don't explicitly set 'uniqueWriterIdentity' to true.
_, err := config.clientLogging.BillingAccounts.Sinks.Patch(d.Id(), sink).UniqueWriterIdentity(true).Do()
if err != nil {
return err
}

return resourceLoggingBillingAccountSinkRead(d, meta)
}

func resourceLoggingBillingAccountSinkDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

_, err := config.clientLogging.Projects.Sinks.Delete(d.Id()).Do()
if err != nil {
return err
}

return nil
}
166 changes: 166 additions & 0 deletions google/resource_logging_billing_account_sink_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package google

import (
"fmt"
"os"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"google.golang.org/api/logging/v2"
)

func TestAccLoggingBillingAccountSink_basic(t *testing.T) {
skipIfEnvNotSet(t, "GOOGLE_BILLING_ACCOUNT")

sinkName := "tf-test-sink-" + acctest.RandString(10)
bucketName := "tf-test-sink-bucket-" + acctest.RandString(10)
billingAccount := os.Getenv("GOOGLE_BILLING_ACCOUNT")

var sink logging.LogSink

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckLoggingBillingAccountSinkDestroy,
Steps: []resource.TestStep{
{
Config: testAccLoggingBillingAccountSink_basic(sinkName, bucketName, billingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckLoggingBillingAccountSinkExists("google_logging_billing_account_sink.basic", &sink),
testAccCheckLoggingBillingAccountSink(&sink, "google_logging_billing_account_sink.basic"),
),
},
},
})
}

func TestAccLoggingBillingAccountSink_update(t *testing.T) {
skipIfEnvNotSet(t, "GOOGLE_BILLING_ACCOUNT")

sinkName := "tf-test-sink-" + acctest.RandString(10)
bucketName := "tf-test-sink-bucket-" + acctest.RandString(10)
updatedBucketName := "tf-test-sink-bucket-" + acctest.RandString(10)
billingAccount := os.Getenv("GOOGLE_BILLING_ACCOUNT")

var sinkBefore, sinkAfter logging.LogSink

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckLoggingBillingAccountSinkDestroy,
Steps: []resource.TestStep{
{
Config: testAccLoggingBillingAccountSink_update(sinkName, bucketName, billingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckLoggingBillingAccountSinkExists("google_logging_billing_account_sink.update", &sinkBefore),
testAccCheckLoggingBillingAccountSink(&sinkBefore, "google_logging_billing_account_sink.update"),
),
}, {
Config: testAccLoggingBillingAccountSink_update(sinkName, updatedBucketName, billingAccount),
Check: resource.ComposeTestCheckFunc(
testAccCheckLoggingBillingAccountSinkExists("google_logging_billing_account_sink.update", &sinkAfter),
testAccCheckLoggingBillingAccountSink(&sinkAfter, "google_logging_billing_account_sink.update"),
),
},
},
})

// Destination should have changed, but WriterIdentity should be the same
if sinkBefore.Destination == sinkAfter.Destination {
t.Errorf("Expected Destination to change, but it didn't: Destination = %#v", sinkBefore.Destination)
}
if sinkBefore.WriterIdentity != sinkAfter.WriterIdentity {
t.Errorf("Expected WriterIdentity to be the same, but it differs: before = %#v, after = %#v",
sinkBefore.WriterIdentity, sinkAfter.WriterIdentity)
}
}

func testAccCheckLoggingBillingAccountSinkDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

for _, rs := range s.RootModule().Resources {
if rs.Type != "google_logging_billing_account_sink" {
continue
}

attributes := rs.Primary.Attributes

_, err := config.clientLogging.BillingAccounts.Sinks.Get(attributes["id"]).Do()
if err == nil {
return fmt.Errorf("billing sink still exists")
}
}

return nil
}

func testAccCheckLoggingBillingAccountSinkExists(n string, sink *logging.LogSink) resource.TestCheckFunc {
return func(s *terraform.State) error {
attributes, err := getResourceAttributes(n, s)
if err != nil {
return err
}
config := testAccProvider.Meta().(*Config)

si, err := config.clientLogging.BillingAccounts.Sinks.Get(attributes["id"]).Do()
if err != nil {
return err
}
*sink = *si

return nil
}
}

func testAccCheckLoggingBillingAccountSink(sink *logging.LogSink, n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
attributes, err := getResourceAttributes(n, s)
if err != nil {
return err
}

if sink.Destination != attributes["destination"] {
return fmt.Errorf("mismatch on destination: api has %s but client has %s", sink.Destination, attributes["destination"])
}

if sink.Filter != attributes["filter"] {
return fmt.Errorf("mismatch on filter: api has %s but client has %s", sink.Filter, attributes["filter"])
}

if sink.WriterIdentity != attributes["writer_identity"] {
return fmt.Errorf("mismatch on writer_identity: api has %s but client has %s", sink.WriterIdentity, attributes["writer_identity"])
}

return nil
}
}

func testAccLoggingBillingAccountSink_basic(name, bucketName, billingAccount string) string {
return fmt.Sprintf(`
resource "google_logging_billing_account_sink" "basic" {
name = "%s"
billing_account = "%s"
destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}"
filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR"
}
resource "google_storage_bucket" "log-bucket" {
name = "%s"
}`, name, billingAccount, getTestProjectFromEnv(), bucketName)
}

func testAccLoggingBillingAccountSink_update(name, bucketName, billingAccount string) string {
return fmt.Sprintf(`
resource "google_logging_billing_account_sink" "update" {
name = "%s"
billing_account = "%s"
destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}"
filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR"
}
resource "google_storage_bucket" "log-bucket" {
name = "%s"
}`, name, billingAccount, getTestProjectFromEnv(), bucketName)
}
90 changes: 19 additions & 71 deletions google/resource_logging_project_sink.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,30 @@ import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/logging/v2"
)

const nonUniqueWriterAccount = "serviceAccount:[email protected]"

func resourceLoggingProjectSink() *schema.Resource {
return &schema.Resource{
schm := &schema.Resource{
Create: resourceLoggingProjectSinkCreate,
Read: resourceLoggingProjectSinkRead,
Delete: resourceLoggingProjectSinkDelete,
Update: resourceLoggingProjectSinkUpdate,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"destination": {
Type: schema.TypeString,
Required: true,
},

"filter": {
Type: schema.TypeString,
Optional: true,
},

"project": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"unique_writer_identity": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},

"writer_identity": {
Type: schema.TypeString,
Computed: true,
},
},
Schema: resourceLoggingSinkSchema(),
}
schm.Schema["project"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
}
schm.Schema["unique_writer_identity"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
}
return schm
}

func resourceLoggingProjectSinkCreate(d *schema.ResourceData, meta interface{}) error {
Expand All @@ -61,23 +38,10 @@ func resourceLoggingProjectSinkCreate(d *schema.ResourceData, meta interface{})
return err
}

name := d.Get("name").(string)

id := LoggingSinkId{
resourceType: "projects",
resourceId: project,
name: name,
}

sink := logging.LogSink{
Name: d.Get("name").(string),
Destination: d.Get("destination").(string),
Filter: d.Get("filter").(string),
}

id, sink := expandResourceLoggingSink(d, "projects", project)
uniqueWriterIdentity := d.Get("unique_writer_identity").(bool)

_, err = config.clientLogging.Projects.Sinks.Create(id.parent(), &sink).UniqueWriterIdentity(uniqueWriterIdentity).Do()
_, err = config.clientLogging.Projects.Sinks.Create(id.parent(), sink).UniqueWriterIdentity(uniqueWriterIdentity).Do()
if err != nil {
return err
}
Expand All @@ -95,10 +59,7 @@ func resourceLoggingProjectSinkRead(d *schema.ResourceData, meta interface{}) er
return handleNotFoundError(err, d, fmt.Sprintf("Project Logging Sink %s", d.Get("name").(string)))
}

d.Set("name", sink.Name)
d.Set("destination", sink.Destination)
d.Set("filter", sink.Filter)
d.Set("writer_identity", sink.WriterIdentity)
flattenResourceLoggingSink(d, sink)
if sink.WriterIdentity != nonUniqueWriterAccount {
d.Set("unique_writer_identity", true)
} else {
Expand All @@ -110,23 +71,10 @@ func resourceLoggingProjectSinkRead(d *schema.ResourceData, meta interface{}) er
func resourceLoggingProjectSinkUpdate(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

// Can only update destination/filter right now. Despite the method below using 'Patch', the API requires both
// destination and filter (even if unchanged).
sink := logging.LogSink{
Destination: d.Get("destination").(string),
Filter: d.Get("filter").(string),
}

if d.HasChange("destination") {
sink.ForceSendFields = append(sink.ForceSendFields, "Destination")
}
if d.HasChange("filter") {
sink.ForceSendFields = append(sink.ForceSendFields, "Filter")
}

sink := expandResourceLoggingSinkForUpdate(d)
uniqueWriterIdentity := d.Get("unique_writer_identity").(bool)

_, err := config.clientLogging.Projects.Sinks.Patch(d.Id(), &sink).UniqueWriterIdentity(uniqueWriterIdentity).Do()
_, err := config.clientLogging.Projects.Sinks.Patch(d.Id(), sink).UniqueWriterIdentity(uniqueWriterIdentity).Do()
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 8231d6a

Please sign in to comment.