Skip to content

Bigtable

package bigtable

import (
    "context"
    "fmt"
    "github.com/testcontainers/testcontainers-go/wait"

    "github.com/testcontainers/testcontainers-go"
)

// bigtableContainer represents the bigtable container type used in the module
type bigtableContainer struct {
    testcontainers.Container
    URI string
}

// setupBigtable creates an instance of the bigtable container type
func setupBigtable(ctx context.Context) (*bigtableContainer, error) {
    req := testcontainers.ContainerRequest{
        Image:        "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators",
        ExposedPorts: []string{"9000/tcp"},
        WaitingFor:   wait.ForLog("running"),
        Cmd: []string{
            "/bin/sh",
            "-c",
            "gcloud beta emulators bigtable start --host-port 0.0.0.0:9000",
        },
    }
    container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
        ContainerRequest: req,
        Started:          true,
    })
    if err != nil {
        return nil, err
    }

    mappedPort, err := container.MappedPort(ctx, "9000")
    if err != nil {
        return nil, err
    }

    hostIP, err := container.Host(ctx)
    if err != nil {
        return nil, err
    }

    uri := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port())

    return &bigtableContainer{Container: container, URI: uri}, nil
}
package bigtable

import (
    "cloud.google.com/go/bigtable"
    "context"
    "google.golang.org/api/option"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "testing"
)

const (
    projectId  = "test-project"
    instanceId = "test-instance"
    tableName  = "test-table"
)

func TestBigtable(t *testing.T) {
    ctx := context.Background()

    container, err := setupBigtable(ctx)
    if err != nil {
        t.Fatal(err)
    }

    // Clean up the container after the test is complete
    t.Cleanup(func() {
        if err := container.Terminate(ctx); err != nil {
            t.Fatalf("failed to terminate container: %s", err)
        }
    })

    options := []option.ClientOption{
        option.WithEndpoint(container.URI),
        option.WithoutAuthentication(),
        option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())),
    }
    adminClient, err := bigtable.NewAdminClient(ctx, projectId, instanceId, options...)
    if err != nil {
        t.Fatal(err)
    }
    err = adminClient.CreateTable(ctx, tableName)
    if err != nil {
        t.Fatal(err)
    }
    err = adminClient.CreateColumnFamily(ctx, tableName, "name")
    if err != nil {
        t.Fatal(err)
    }

    client, err := bigtable.NewClient(ctx, projectId, instanceId, options...)
    if err != nil {
        t.Fatal(err)
    }
    tbl := client.Open(tableName)

    mut := bigtable.NewMutation()
    mut.Set("name", "firstName", bigtable.Now(), []byte("Gopher"))
    err = tbl.Apply(ctx, "1", mut)
    if err != nil {
        t.Fatal(err)
    }

    row, err := tbl.ReadRow(ctx, "1", bigtable.RowFilter(bigtable.FamilyFilter("name")))
    if err != nil {
        t.Fatal(err)
    }
    // perform assertions
    name := string(row["name"][0].Value)
    if name != "Gopher" {
        t.Fatalf("expected row key to be 'Gopher', got '%s'", name)
    }
}