1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package logadmin
21
22 import (
23 "context"
24 "fmt"
25 "log"
26 "testing"
27 "time"
28
29 "cloud.google.com/go/iam"
30 "cloud.google.com/go/internal/testutil"
31 "cloud.google.com/go/internal/uid"
32 ltest "cloud.google.com/go/logging/internal/testing"
33 "cloud.google.com/go/storage"
34 "google.golang.org/api/iterator"
35 "google.golang.org/api/option"
36 )
37
38 var sinkIDs = uid.NewSpace("GO-CLIENT-TEST-SINK", nil)
39
40 const testFilter = ""
41 const testBucketTTLDays = 1
42
43 var testSinkDestination string
44 var testBucket string
45
46
47
48 func initSinks(ctx context.Context) func() {
49
50 bucketIDs := uid.NewSpace(testProjectID+"-log-sink", nil)
51 testBucket = bucketIDs.New()
52 testSinkDestination = "storage.googleapis.com/" + testBucket
53 var storageClient *storage.Client
54 if integrationTest {
55
56
57 ts := testutil.TokenSource(ctx, storage.ScopeFullControl)
58 var err error
59 storageClient, err = storage.NewClient(ctx, option.WithTokenSource(ts))
60 if err != nil {
61 log.Fatalf("new storage client: %v", err)
62 }
63 bucket := storageClient.Bucket(testBucket)
64 if err := bucket.Create(ctx, testProjectID, nil); err != nil {
65 log.Fatalf("creating storage bucket %q: %v", testBucket, err)
66 }
67
68
69 bucketAttrsToUpdate := storage.BucketAttrsToUpdate{
70 Lifecycle: &storage.Lifecycle{
71 Rules: []storage.LifecycleRule{
72 {
73 Action: storage.LifecycleAction{Type: storage.DeleteAction},
74 Condition: storage.LifecycleCondition{
75 AgeInDays: testBucketTTLDays,
76 },
77 },
78 },
79 },
80 }
81 _, err = bucket.Update(ctx, bucketAttrsToUpdate)
82 if err != nil {
83 log.Fatalf("updating bucket %q lifecycle rule: %v", testBucket, err)
84 }
85
86
87 err = addBucketCreator(testBucket, ltest.SharedServiceAccount)
88 if err != nil {
89 log.Fatal(err)
90 }
91 log.Printf("successfully created bucket %s", testBucket)
92
93 err = addBucketIAMPolicy(testBucket, "group:cloud-logs@google.com", "roles/storage.admin")
94 if err != nil {
95 log.Fatal(err)
96 }
97 }
98
99 it := client.Sinks(ctx)
100 for {
101 s, err := it.Next()
102 if err == iterator.Done {
103 break
104 }
105 if err != nil {
106 log.Printf("listing sinks: %v", err)
107 break
108 }
109 if sinkIDs.Older(s.ID, time.Hour) {
110 client.DeleteSink(ctx, s.ID)
111 }
112 }
113 if integrationTest {
114 for _, bn := range bucketNames(ctx, storageClient) {
115 if bucketIDs.Older(bn, 36*time.Hour) {
116 storageClient.Bucket(bn).Delete(ctx)
117 }
118 }
119 return func() {
120
121 defer storageClient.Close()
122 if err := storageClient.Bucket(testBucket).Delete(ctx); err != nil {
123 log.Printf("deleting %q: %v", testBucket, err)
124 }
125 }
126 }
127 return func() {}
128 }
129
130
131 func bucketNames(ctx context.Context, client *storage.Client) []string {
132 var names []string
133 it := client.Buckets(ctx, testProjectID)
134 loop:
135 for {
136 b, err := it.Next()
137 switch err {
138 case nil:
139 names = append(names, b.Name)
140 case iterator.Done:
141 break loop
142 default:
143 log.Printf("listing buckets: %v", err)
144 break loop
145 }
146 }
147 return names
148 }
149
150
151
152 func addBucketIAMPolicy(bucketName string, identity string, role iam.RoleName) error {
153 if integrationTest {
154 ctx := context.Background()
155 client, err := storage.NewClient(ctx, option.WithTokenSource(testutil.TokenSource(ctx, storage.ScopeFullControl)))
156 if err != nil {
157 return fmt.Errorf("storage.NewClient: %v", err)
158 }
159 defer client.Close()
160
161 ctx, cancel := context.WithTimeout(ctx, time.Second*10)
162 defer cancel()
163
164 bucket := client.Bucket(bucketName)
165 policy, err := bucket.IAM().Policy(ctx)
166 if err != nil {
167 return fmt.Errorf("Bucket(%q).IAM().Policy: %v", bucketName, err)
168 }
169
170 policy.Add(identity, role)
171 if err := bucket.IAM().SetPolicy(ctx, policy); err != nil {
172 return fmt.Errorf("Bucket(%q).IAM().SetPolicy: %v", bucketName, err)
173 }
174 }
175
176 return nil
177 }
178
179
180 func addBucketCreator(bucketName string, identity string) error {
181 return addBucketIAMPolicy(bucketName, identity, "roles/storage.objectCreator")
182 }
183
184 func TestCreateSink(t *testing.T) {
185 ctx := context.Background()
186 sink := &Sink{
187 ID: sinkIDs.New(),
188 Destination: testSinkDestination,
189 Filter: testFilter,
190 IncludeChildren: true,
191 }
192 got, err := client.CreateSink(ctx, sink)
193 if err != nil {
194 t.Fatal(err)
195 }
196 defer client.DeleteSink(ctx, sink.ID)
197
198 sink.WriterIdentity = ltest.SharedServiceAccount
199 if want := sink; !testutil.Equal(got, want) {
200 t.Errorf("got %+v, want %+v", got, want)
201 }
202 got, err = client.Sink(ctx, sink.ID)
203 if err != nil {
204 t.Fatal(err)
205 }
206 if want := sink; !testutil.Equal(got, want) {
207 t.Errorf("got %+v, want %+v", got, want)
208 }
209
210
211 sink.ID = sinkIDs.New()
212 got, err = client.CreateSinkOpt(ctx, sink, SinkOptions{UniqueWriterIdentity: true})
213 if err != nil {
214 t.Fatal(err)
215 }
216 defer client.DeleteSink(ctx, sink.ID)
217
218
219 err = addBucketCreator(testBucket, got.WriterIdentity)
220 if err != nil {
221 t.Fatal(err)
222 }
223
224 if got.WriterIdentity == sink.WriterIdentity {
225 t.Errorf("got %s, want something different", got.WriterIdentity)
226 }
227 }
228
229 func TestUpdateSink(t *testing.T) {
230 ctx := context.Background()
231 sink := &Sink{
232 ID: sinkIDs.New() + "-" + t.Name(),
233 Destination: testSinkDestination,
234 Filter: testFilter,
235 IncludeChildren: true,
236 WriterIdentity: ltest.SharedServiceAccount,
237 }
238
239 _, err := client.CreateSink(ctx, sink)
240 if err != nil {
241 t.Fatal(err)
242 }
243 defer client.DeleteSink(ctx, sink.ID)
244
245 got, err := client.UpdateSink(ctx, sink)
246 if err != nil {
247 t.Fatal(err)
248 }
249 if want := sink; !testutil.Equal(got, want) {
250 t.Errorf("got\n%+v\nwant\n%+v", got, want)
251 }
252 got, err = client.Sink(ctx, sink.ID)
253 if err != nil {
254 t.Fatal(err)
255 }
256 if want := sink; !testutil.Equal(got, want) {
257 t.Errorf("got\n%+v\nwant\n%+v", got, want)
258 }
259
260
261 sink.Filter = ""
262 sink.IncludeChildren = false
263 if _, err := client.UpdateSink(ctx, sink); err != nil {
264 t.Fatal(err)
265 }
266 got, err = client.Sink(ctx, sink.ID)
267 if err != nil {
268 t.Fatal(err)
269 }
270 if want := sink; !testutil.Equal(got, want) {
271 t.Errorf("got\n%+v\nwant\n%+v", got, want)
272 }
273 }
274
275 func TestUpdateSinkOpt(t *testing.T) {
276 ctx := context.Background()
277 id := sinkIDs.New()
278 origSink := &Sink{
279 ID: id,
280 Destination: testSinkDestination,
281 Filter: testFilter,
282 IncludeChildren: true,
283 WriterIdentity: ltest.SharedServiceAccount,
284 }
285
286 _, err := client.CreateSink(ctx, origSink)
287 if err != nil {
288 t.Fatal(err)
289 }
290 defer client.DeleteSink(ctx, origSink.ID)
291
292
293 _, err = client.UpdateSinkOpt(ctx, &Sink{ID: id, Destination: testSinkDestination}, SinkOptions{})
294 if err == nil {
295 t.Errorf("got %v, want nil", err)
296 }
297
298
299 got, err := client.UpdateSinkOpt(ctx, &Sink{ID: id}, SinkOptions{
300 UpdateFilter: true,
301 UpdateIncludeChildren: true,
302 })
303 if err != nil {
304 t.Fatal(err)
305 }
306 want := *origSink
307 want.Filter = ""
308 want.IncludeChildren = false
309 if !testutil.Equal(got, &want) {
310 t.Errorf("got\n%+v\nwant\n%+v", got, want)
311 }
312
313
314 got, err = client.UpdateSinkOpt(ctx, &Sink{ID: id, Filter: "foo"},
315 SinkOptions{UniqueWriterIdentity: true})
316 if err != nil {
317 t.Fatal(err)
318 }
319
320 err = addBucketCreator(testBucket, got.WriterIdentity)
321 if err != nil {
322 t.Fatal(err)
323 }
324 if got.WriterIdentity == want.WriterIdentity {
325 t.Errorf("got %s, want something different", got.WriterIdentity)
326 }
327 want.WriterIdentity = got.WriterIdentity
328 if !testutil.Equal(got, &want) {
329 t.Errorf("got\n%+v\nwant\n%+v", got, want)
330 }
331 }
332
333 func TestListSinks(t *testing.T) {
334 ctx := context.Background()
335 var sinks []*Sink
336 want := map[string]*Sink{}
337 for i := 0; i < 4; i++ {
338 s := &Sink{
339 ID: sinkIDs.New(),
340 Destination: testSinkDestination,
341 Filter: testFilter,
342 WriterIdentity: "serviceAccount:cloud-logs@system.gserviceaccount.com",
343 }
344 sinks = append(sinks, s)
345 want[s.ID] = s
346 }
347 for _, s := range sinks {
348 _, err := client.CreateSink(ctx, s)
349 if err != nil {
350 t.Fatalf("Create(%q): %v", s.ID, err)
351 }
352 defer client.DeleteSink(ctx, s.ID)
353 }
354
355 got := map[string]*Sink{}
356 it := client.Sinks(ctx)
357 for {
358 s, err := it.Next()
359 if err == iterator.Done {
360 break
361 }
362 if err != nil {
363 t.Fatal(err)
364 }
365
366
367 if _, ok := want[s.ID]; ok {
368 got[s.ID] = s
369 }
370 }
371 if !testutil.Equal(got, want) {
372 t.Errorf("got %+v, want %+v", got, want)
373 }
374 }
375
View as plain text