gcs_client.go

Overview

The gcs_client.go file provides an abstraction layer and wrapper implementations for Google Cloud Storage (GCS) client components. Its primary purpose is to define interfaces representing GCS client, bucket, object, object iterator, and writer behaviors to enable flexible mocking during testing. The file also provides concrete wrapper structs that adapt the official Google Cloud Storage Go client types (storage.Client, storage.BucketHandle, storage.ObjectHandle, storage.ObjectIterator, and storage.Writer) to these interfaces. This design facilitates unit testing by allowing dependency injection of mock clients without requiring actual GCS interactions.

This file is a foundational utility in the Google Cloud Storage Service implementation within the broader Artifact Management system, where it abstracts GCS operations such as uploading, downloading, listing, and deleting versioned blobs as artifacts.


Interfaces

The file declares several key interfaces that define the behavior expected from GCS client components:

gcsClient

type gcsClient interface {
    bucket(name string) gcsBucket
}

gcsBucket

type gcsBucket interface {
    object(name string) gcsObject
    objects(ctx context.Context, q *storage.Query) gcsObjectIterator
}

gcsObject

type gcsObject interface {
    newWriter(ctx context.Context) gcsWriter
    newReader(ctx context.Context) (io.ReadCloser, error)
    delete(ctx context.Context) error
    attrs(ctx context.Context) (*storage.ObjectAttrs, error)
}

gcsObjectIterator

type gcsObjectIterator interface {
    next() (*storage.ObjectAttrs, error)
}

gcsWriter

type gcsWriter interface {
    io.Writer
    io.Closer
    SetContentType(string)
}

Wrapper Implementations

Concrete wrapper types adapt the official GCS client types to the above interfaces, enabling the use of interface-typed dependencies and mocking.

gcsClientWrapper

type gcsClientWrapper struct {
    client *storage.Client
}

gcsBucketWrapper

type gcsBucketWrapper struct {
    bucket *storage.BucketHandle
}

gcsObjectWrapper

type gcsObjectWrapper struct {
    object *storage.ObjectHandle
}

gcsObjectIteratorWrapper

type gcsObjectIteratorWrapper struct {
    iter *storage.ObjectIterator
}

gcsWriterWrapper

type gcsWriterWrapper struct {
    w *storage.Writer
}

Implementation Details and Usage Examples

Mocking and Testability

By defining interfaces for GCS client components, this file supports injecting mock implementations during unit tests, enabling testing of artifact storage logic without actual GCS dependencies. The interfaces mirror the minimal subset of GCS client functionality required by the Google Cloud Storage Service.

Wrapper Pattern

The wrappers hold pointers to the real GCS client types and implement the interface methods by forwarding calls to the underlying GCS client. This preserves all GCS client behaviors while enabling interface substitution.

Example: Obtaining an Object Writer

var client gcsClient = &gcsClientWrapper{client: realGCSClient}
bucket := client.bucket("my-bucket")
obj := bucket.object("path/to/object")
writer := obj.newWriter(ctx)
writer.SetContentType("application/octet-stream")
_, err := writer.Write(data)
if err != nil {
    // handle error
}
err = writer.Close()
if err != nil {
    // handle error
}

This example illustrates the process of writing data to a GCS object using the interface abstraction and wrapper.

Interface Compliance Assertions

At the end of the file, the code includes compile-time assertions verifying that the wrappers implement their respective interfaces:

var (
    _ gcsClient         = (*gcsClientWrapper)(nil)
    _ gcsBucket         = (*gcsBucketWrapper)(nil)
    _ gcsObject         = (*gcsObjectWrapper)(nil)
    _ gcsObjectIterator = (*gcsObjectIteratorWrapper)(nil)
    _ gcsWriter         = (*gcsWriterWrapper)(nil)
)

This ensures that any signature mismatches are caught during compilation.


Interaction with Other Components


Mermaid Diagram: Interface and Wrapper Structure

classDiagram
class gcsClient {
+bucket(name)
}
class gcsBucket {
+object(name)
+objects(ctx, q)
}
class gcsObject {
+newWriter(ctx)
+newReader(ctx)
+delete(ctx)
+attrs(ctx)
}
class gcsObjectIterator {
+next()
}
class gcsWriter {
+Write()
+Close()
+SetContentType()
}
class gcsClientWrapper {
-client
+bucket(name)
}
class gcsBucketWrapper {
-bucket
+object(name)
+objects(ctx, q)
}
class gcsObjectWrapper {
-object
+newWriter(ctx)
+newReader(ctx)
+delete(ctx)
+attrs(ctx)
}
class gcsObjectIteratorWrapper {
-iter
+next()
}
class gcsWriterWrapper {
-w
+Write()
+Close()
+SetContentType()
}
gcsClient <|.. gcsClientWrapper
gcsBucket <|.. gcsBucketWrapper
gcsObject <|.. gcsObjectWrapper
gcsObjectIterator <|.. gcsObjectIteratorWrapper
gcsWriter <|.. gcsWriterWrapper
gcsClientWrapper --> gcsBucketWrapper : bucket()
gcsBucketWrapper --> gcsObjectWrapper : object()
gcsBucketWrapper --> gcsObjectIteratorWrapper : objects()
gcsObjectWrapper --> gcsWriterWrapper : newWriter()

Summary

This file defines the interfaces and adapter wrappers for Google Cloud Storage client components, enabling mocking and abstraction for artifact storage operations. It provides the building blocks for the Google Cloud Storage Service to implement versioned, scoped artifact persistence with GCS. The design ensures testability by abstracting the real GCS client behind interfaces while preserving all essential operations such as object write/read/delete, iteration, and metadata access.