Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions storage/control/anywhere_cache_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package control

import (
"bytes"
"context"
"fmt"
"os"
"strings"
"testing"
"time"

"cloud.google.com/go/storage"
"github.com/GoogleCloudPlatform/golang-samples/internal/testutil"
)

func TestAnywhereCache(t *testing.T) {
tc := testutil.SystemTest(t)
ctx := context.Background()

zone := os.Getenv("GOOGLE_SAMPLES_ZONE")
if zone == "" {
zone = "us-central1-a"
}

// Create bucket with UBLA enabled as required for Anywhere Cache.
bucketName := testutil.UniqueBucketName(testPrefix)
b := client.Bucket(bucketName)
Comment on lines +40 to +41
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The variables testPrefix and client are used but not defined or initialized in this test file or package. This will cause a compilation error. You should define testPrefix (e.g., as a constant) and initialize a storage.Client before using them.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jules check other similar tests and fix this

attrs := &storage.BucketAttrs{
UniformBucketLevelAccess: storage.UniformBucketLevelAccess{
Enabled: true,
},
}
if err := b.Create(ctx, tc.ProjectID, attrs); err != nil {
t.Fatalf("Bucket.Create(%q): %v", bucketName, err)
}
t.Cleanup(func() {
testutil.DeleteBucketIfExists(ctx, client, bucketName)
})

cacheName := fmt.Sprintf("buckets/%v/anywhereCaches/%v", bucketName, zone)

// Create Anywhere Cache.
// Using partial match for assertions as per memory guidelines.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := createAnywhereCache(buf, bucketName, zone); err != nil {
r.Errorf("createAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("createAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to create anywhere cache; can't continue")
}

// Get Anywhere Cache.
fullCacheName := fmt.Sprintf("projects/_/buckets/%v/anywhereCaches/%v", bucketName, zone)
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := getAnywhereCache(buf, fullCacheName); err != nil {
r.Errorf("getAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("getAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to get anywhere cache; can't continue")
}

// List Anywhere Caches.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := listAnywhereCaches(buf, bucketName); err != nil {
r.Errorf("listAnywhereCaches: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("listAnywhereCaches: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to list anywhere caches; can't continue")
}

// Update Anywhere Cache.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := updateAnywhereCache(buf, fullCacheName, "admit-on-second-miss"); err != nil {
r.Errorf("updateAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("updateAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to update anywhere cache; can't continue")
}

// Pause Anywhere Cache.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := pauseAnywhereCache(buf, fullCacheName); err != nil {
r.Errorf("pauseAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("pauseAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to pause anywhere cache; can't continue")
}

// Resume Anywhere Cache.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := resumeAnywhereCache(buf, fullCacheName); err != nil {
r.Errorf("resumeAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("resumeAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to resume anywhere cache; can't continue")
}

// Disable Anywhere Cache.
if ok := testutil.Retry(t, 5, time.Second, func(r *testutil.R) {
buf := &bytes.Buffer{}
if err := disableAnywhereCache(buf, fullCacheName); err != nil {
r.Errorf("disableAnywhereCache: %v", err)
}
if got, want := buf.String(), cacheName; !strings.Contains(got, want) {
r.Errorf("disableAnywhereCache: got %q, want to contain %q", got, want)
}
}); !ok {
t.Fatalf("failed to disable anywhere cache")
}
}
66 changes: 66 additions & 0 deletions storage/control/create_anywhere_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package control

// [START storage_control_create_anywhere_cache]
import (
"context"
"fmt"
"io"
"time"

storagecontrol "cloud.google.com/go/storage/control/apiv2"
"cloud.google.com/go/storage/control/apiv2/controlpb"
)

// createAnywhereCache creates an anywhere cache for the given bucket and zone.
func createAnywhereCache(w io.Writer, bucketName, zone string) error {
// bucketName := "bucket-name"
// zone := "us-central1-a"

ctx := context.Background()
client, err := storagecontrol.NewStorageControlClient(ctx)
if err != nil {
return fmt.Errorf("NewStorageControlClient: %w", err)
}
defer client.Close()

ctx, cancel := context.WithTimeout(ctx, time.Minute*20)
defer cancel()

req := &controlpb.CreateAnywhereCacheRequest{
Parent: fmt.Sprintf("projects/_/buckets/%v", bucketName),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to pass the projectID as an argument to the function and use it in the resource path (projects/%v/buckets/%v) instead of hardcoding _. This makes the sample more explicit and robust, as the Control API often requires a specific project ID.

AnywhereCache: &controlpb.AnywhereCache{
Zone: zone,
},
}

// Start a create/update operation and block until it completes.
// Real applications may want to setup a callback, wait on a coroutine, or poll until it completes.
op, err := client.CreateAnywhereCache(ctx, req)
if err != nil {
return fmt.Errorf("CreateAnywhereCache(%q): %w", zone, err)
}

anywhereCache, err := op.Wait(ctx)
if err != nil {
return fmt.Errorf("Wait: %w", err)
}

fmt.Fprintf(w, "Created anywhere cache: %v\n", anywhereCache.GetName())
return nil
}

// [END storage_control_create_anywhere_cache]
55 changes: 55 additions & 0 deletions storage/control/disable_anywhere_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package control

// [START storage_control_disable_anywhere_cache]
import (
"context"
"fmt"
"io"
"time"

storagecontrol "cloud.google.com/go/storage/control/apiv2"
"cloud.google.com/go/storage/control/apiv2/controlpb"
)

// disableAnywhereCache disables an anywhere cache.
func disableAnywhereCache(w io.Writer, cacheName string) error {
// cacheName := "projects/_/buckets/bucket-name/anywhereCaches/us-central1-a"

ctx := context.Background()
client, err := storagecontrol.NewStorageControlClient(ctx)
if err != nil {
return fmt.Errorf("NewStorageControlClient: %w", err)
}
defer client.Close()

ctx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()

req := &controlpb.DisableAnywhereCacheRequest{
Name: cacheName,
}

anywhereCache, err := client.DisableAnywhereCache(ctx, req)
if err != nil {
return fmt.Errorf("DisableAnywhereCache(%q): %w", cacheName, err)
}

fmt.Fprintf(w, "Disabled anywhere cache: %v\n", anywhereCache.GetName())
return nil
}

// [END storage_control_disable_anywhere_cache]
55 changes: 55 additions & 0 deletions storage/control/get_anywhere_cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package control

// [START storage_control_get_anywhere_cache]
import (
"context"
"fmt"
"io"
"time"

storagecontrol "cloud.google.com/go/storage/control/apiv2"
"cloud.google.com/go/storage/control/apiv2/controlpb"
)

// getAnywhereCache gets an anywhere cache for the given name.
func getAnywhereCache(w io.Writer, cacheName string) error {
// cacheName := "projects/_/buckets/bucket-name/anywhereCaches/us-central1-a"

ctx := context.Background()
client, err := storagecontrol.NewStorageControlClient(ctx)
if err != nil {
return fmt.Errorf("NewStorageControlClient: %w", err)
}
defer client.Close()

ctx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()

req := &controlpb.GetAnywhereCacheRequest{
Name: cacheName,
}

anywhereCache, err := client.GetAnywhereCache(ctx, req)
if err != nil {
return fmt.Errorf("GetAnywhereCache(%q): %w", cacheName, err)
}

fmt.Fprintf(w, "Got anywhere cache: %v\n", anywhereCache.GetName())
return nil
}

// [END storage_control_get_anywhere_cache]
62 changes: 62 additions & 0 deletions storage/control/list_anywhere_caches.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package control

// [START storage_control_list_anywhere_caches]
import (
"context"
"fmt"
"io"
"time"

storagecontrol "cloud.google.com/go/storage/control/apiv2"
"cloud.google.com/go/storage/control/apiv2/controlpb"
"google.golang.org/api/iterator"
)

// listAnywhereCaches lists anywhere caches for the given bucket.
func listAnywhereCaches(w io.Writer, bucketName string) error {
// bucketName := "bucket-name"

ctx := context.Background()
client, err := storagecontrol.NewStorageControlClient(ctx)
if err != nil {
return fmt.Errorf("NewStorageControlClient: %w", err)
}
defer client.Close()

ctx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()

req := &controlpb.ListAnywhereCachesRequest{
Parent: fmt.Sprintf("projects/_/buckets/%v", bucketName),
}

it := client.ListAnywhereCaches(ctx, req)
for {
anywhereCache, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return fmt.Errorf("it.Next: %w", err)
}
fmt.Fprintf(w, "%v\n", anywhereCache.GetName())
}

return nil
}

// [END storage_control_list_anywhere_caches]
Loading
Loading