Skip to content

Commit 7cc63df

Browse files
Treat _Default & _Required Sinks same as buckets (#9384) (#16513)
* Treat _Default & _Required Sinks same as buckets * Update documentation. * Update exclusions every time. * Do not check if _Default bucket has been deleted. * Clean-up log statements. * Fixup documentation. * Ensure SA IAM set before associating with bucket. [upstream:407631823fe91540101b6747b98f75eafdc3ada4] Signed-off-by: Modular Magician <[email protected]>
1 parent 001e94b commit 7cc63df

File tree

5 files changed

+71
-24
lines changed

5 files changed

+71
-24
lines changed

.changelog/9384.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
logging: `google_logging_project_sink` now will aqcuire and update the resource that already exists at the desired location. These buckets cannot be removed so deleting this resource will remove the bucket config from your terraform state but will leave the logging bucket unchanged.
3+
```

google/services/logging/resource_logging_project_sink.go

+31-15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"context"
99
"errors"
1010
"fmt"
11+
"log"
1112

1213
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
1314
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
@@ -19,7 +20,7 @@ const nonUniqueWriterAccount = "serviceAccount:[email protected]
1920

2021
func ResourceLoggingProjectSink() *schema.Resource {
2122
schm := &schema.Resource{
22-
Create: resourceLoggingProjectSinkCreate,
23+
Create: resourceLoggingProjectSinkAcquireOrCreate,
2324
Read: resourceLoggingProjectSinkRead,
2425
Delete: resourceLoggingProjectSinkDelete,
2526
Update: resourceLoggingProjectSinkUpdate,
@@ -51,7 +52,7 @@ func ResourceLoggingProjectSink() *schema.Resource {
5152
return schm
5253
}
5354

54-
func resourceLoggingProjectSinkCreate(d *schema.ResourceData, meta interface{}) error {
55+
func resourceLoggingProjectSinkAcquireOrCreate(d *schema.ResourceData, meta interface{}) error {
5556
config := meta.(*transport_tpg.Config)
5657
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
5758
if err != nil {
@@ -67,25 +68,32 @@ func resourceLoggingProjectSinkCreate(d *schema.ResourceData, meta interface{})
6768
uniqueWriterIdentity := d.Get("unique_writer_identity").(bool)
6869
customWriterIdentity := d.Get("custom_writer_identity").(string)
6970

70-
projectSinkCreateRequest := config.NewLoggingClient(userAgent).Projects.Sinks.Create(id.parent(), sink)
71+
log.Printf("[DEBUG] Fetching logging sink config: %#v", id)
7172

72-
// if custom-sa is specified, use it to write log and it requires uniqueWriterIdentity to be set as well
73-
// otherwise set the uniqueWriter identity
74-
if customWriterIdentity != "" {
75-
projectSinkCreateRequest = projectSinkCreateRequest.UniqueWriterIdentity(uniqueWriterIdentity).CustomWriterIdentity(customWriterIdentity)
76-
} else {
77-
projectSinkCreateRequest = projectSinkCreateRequest.UniqueWriterIdentity(uniqueWriterIdentity)
78-
}
73+
res, _ := config.NewLoggingClient(userAgent).Projects.Sinks.Get(id.canonicalId()).Do()
74+
if res == nil {
75+
projectSinkCreateRequest := config.NewLoggingClient(userAgent).Projects.Sinks.Create(id.parent(), sink)
7976

80-
_, err = projectSinkCreateRequest.Do()
77+
// if custom-sa is specified, use it to write log and it requires uniqueWriterIdentity to be set as well
78+
// otherwise set the uniqueWriter identity
79+
if customWriterIdentity != "" {
80+
projectSinkCreateRequest = projectSinkCreateRequest.UniqueWriterIdentity(uniqueWriterIdentity).CustomWriterIdentity(customWriterIdentity)
81+
} else {
82+
projectSinkCreateRequest = projectSinkCreateRequest.UniqueWriterIdentity(uniqueWriterIdentity)
83+
}
8184

82-
if err != nil {
83-
return err
84-
}
85+
_, err = projectSinkCreateRequest.Do()
8586

87+
if err != nil {
88+
return err
89+
}
90+
91+
d.SetId(id.canonicalId())
92+
return resourceLoggingProjectSinkRead(d, meta)
93+
}
8694
d.SetId(id.canonicalId())
8795

88-
return resourceLoggingProjectSinkRead(d, meta)
96+
return resourceLoggingProjectSinkUpdate(d, meta)
8997
}
9098

9199
// if bigquery_options is set unique_writer_identity must be true
@@ -177,6 +185,14 @@ func resourceLoggingProjectSinkUpdate(d *schema.ResourceData, meta interface{})
177185
}
178186

179187
func resourceLoggingProjectSinkDelete(d *schema.ResourceData, meta interface{}) error {
188+
name := d.Get("name")
189+
for _, restrictedName := range []string{"_Required", "_Default"} {
190+
if name == restrictedName {
191+
log.Print("[WARN] Default logging sinks cannot be deleted.")
192+
return nil
193+
}
194+
}
195+
180196
config := meta.(*transport_tpg.Config)
181197
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
182198
if err != nil {

google/services/logging/resource_logging_project_sink_test.go

+30-2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,28 @@ func TestAccLoggingProjectSink_basic(t *testing.T) {
3535
})
3636
}
3737

38+
func TestAccLoggingProjectSink_default(t *testing.T) {
39+
t.Parallel()
40+
41+
sinkName := "_Default"
42+
bucketName := "tf-test-sink-bucket-" + acctest.RandString(t, 10)
43+
44+
acctest.VcrTest(t, resource.TestCase{
45+
PreCheck: func() { acctest.AccTestPreCheck(t) },
46+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
47+
Steps: []resource.TestStep{
48+
{
49+
Config: testAccLoggingProjectSink_basic(sinkName, envvar.GetTestProjectFromEnv(), bucketName),
50+
},
51+
{
52+
ResourceName: "google_logging_project_sink.basic",
53+
ImportState: true,
54+
ImportStateVerify: true,
55+
},
56+
},
57+
})
58+
}
59+
3860
func TestAccLoggingProjectSink_described(t *testing.T) {
3961
t.Parallel()
4062

@@ -515,7 +537,10 @@ resource "google_logging_project_sink" "custom_writer" {
515537
unique_writer_identity = true
516538
custom_writer_identity = "serviceAccount:${google_service_account.test-account1.email}"
517539
518-
depends_on = [google_logging_project_bucket_config.destination-bucket]
540+
depends_on = [
541+
google_logging_project_bucket_config.destination-bucket,
542+
google_service_account_iam_member.loggingsa-customsa-binding,
543+
]
519544
}
520545
`, project, project, org, billingId, serviceAccount, envvar.GetTestProjectFromEnv(), name, envvar.GetTestProjectFromEnv())
521546
}
@@ -569,7 +594,10 @@ resource "google_logging_project_sink" "custom_writer" {
569594
unique_writer_identity = true
570595
custom_writer_identity = "serviceAccount:${google_service_account.test-account2.email}"
571596
572-
depends_on = [google_logging_project_bucket_config.destination-bucket]
597+
depends_on = [
598+
google_logging_project_bucket_config.destination-bucket,
599+
google_service_account_iam_member.loggingsa-customsa-binding,
600+
]
573601
}
574602
`, project, project, org, billingId, serviceAccount, envvar.GetTestProjectFromEnv(), name, envvar.GetTestProjectFromEnv())
575603
}

google/services/logging/resource_logging_sink.go

+3-6
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,11 @@ func expandResourceLoggingSinkForUpdate(d *schema.ResourceData) (sink *logging.L
157157
Filter: d.Get("filter").(string),
158158
Disabled: d.Get("disabled").(bool),
159159
Description: d.Get("description").(string),
160-
ForceSendFields: []string{"Destination", "Filter", "Disabled"},
160+
Exclusions: expandLoggingSinkExclusions(d.Get("exclusions")),
161+
ForceSendFields: []string{"Destination", "Filter", "Disabled", "Exclusions"},
161162
}
162163

163-
updateFields := []string{}
164+
updateFields := []string{"exclusions"}
164165
if d.HasChange("destination") {
165166
updateFields = append(updateFields, "destination")
166167
}
@@ -173,10 +174,6 @@ func expandResourceLoggingSinkForUpdate(d *schema.ResourceData) (sink *logging.L
173174
if d.HasChange("disabled") {
174175
updateFields = append(updateFields, "disabled")
175176
}
176-
if d.HasChange("exclusions") {
177-
sink.Exclusions = expandLoggingSinkExclusions(d.Get("exclusions"))
178-
updateFields = append(updateFields, "exclusions")
179-
}
180177
if d.HasChange("bigquery_options") {
181178
sink.BigqueryOptions = expandLoggingSinkBigqueryOptions(d.Get("bigquery_options"))
182179
updateFields = append(updateFields, "bigqueryOptions")

website/docs/r/logging_project_sink.html.markdown

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ Manages a project-level logging sink. For more information see:
1818

1919
~> **Note** You must [enable the Cloud Resource Manager API](https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com)
2020

21+
~> **Note:** The `_Default` and `_Required` logging sinks are automatically created for a given project and cannot be deleted. Creating a resource of this type will acquire and update the resource that already exists at the desired location. These sinks cannot be removed so deleting this resource will remove the sink config from your terraform state but will leave the logging sink unchanged. The sinks that are currently automatically created are "_Default" and "_Required".
22+
23+
2124
## Example Usage - Basic Sink
2225

2326
```hcl
@@ -164,7 +167,7 @@ resource "google_logging_project_sink" "log-bucket" {
164167

165168
The following arguments are supported:
166169

167-
* `name` - (Required) The name of the logging sink.
170+
* `name` - (Required) The name of the logging sink. Logging automatically creates two sinks: `_Required` and `_Default`.
168171

169172
* `destination` - (Required) The destination of the sink (or, in other words, where logs are written to). Can be a
170173
Cloud Storage bucket, a PubSub topic, a BigQuery dataset or a Cloud Logging bucket . Examples:

0 commit comments

Comments
 (0)