123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- /*
- Copyright 2015 Google Inc. All Rights Reserved.
- 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
- http://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 bigtable
- import (
- "fmt"
- "regexp"
- "strings"
- "golang.org/x/net/context"
- "google.golang.org/cloud"
- btcspb "google.golang.org/cloud/bigtable/internal/cluster_service_proto"
- bttspb "google.golang.org/cloud/bigtable/internal/table_service_proto"
- "google.golang.org/cloud/internal/transport"
- "google.golang.org/grpc"
- )
- const adminAddr = "bigtabletableadmin.googleapis.com:443"
- // AdminClient is a client type for performing admin operations within a specific cluster.
- type AdminClient struct {
- conn *grpc.ClientConn
- tClient bttspb.BigtableTableServiceClient
- project, zone, cluster string
- }
- // NewAdminClient creates a new AdminClient for a given project, zone and cluster.
- func NewAdminClient(ctx context.Context, project, zone, cluster string, opts ...cloud.ClientOption) (*AdminClient, error) {
- o := []cloud.ClientOption{
- cloud.WithEndpoint(adminAddr),
- cloud.WithScopes(AdminScope),
- cloud.WithUserAgent(clientUserAgent),
- }
- o = append(o, opts...)
- conn, err := transport.DialGRPC(ctx, o...)
- if err != nil {
- return nil, fmt.Errorf("dialing: %v", err)
- }
- return &AdminClient{
- conn: conn,
- tClient: bttspb.NewBigtableTableServiceClient(conn),
- project: project,
- zone: zone,
- cluster: cluster,
- }, nil
- }
- // Close closes the AdminClient.
- func (ac *AdminClient) Close() {
- ac.conn.Close()
- }
- func (ac *AdminClient) clusterPrefix() string {
- return fmt.Sprintf("projects/%s/zones/%s/clusters/%s", ac.project, ac.zone, ac.cluster)
- }
- // Tables returns a list of the tables in the cluster.
- func (ac *AdminClient) Tables(ctx context.Context) ([]string, error) {
- prefix := ac.clusterPrefix()
- req := &bttspb.ListTablesRequest{
- Name: prefix,
- }
- res, err := ac.tClient.ListTables(ctx, req)
- if err != nil {
- return nil, err
- }
- names := make([]string, 0, len(res.Tables))
- for _, tbl := range res.Tables {
- names = append(names, strings.TrimPrefix(tbl.Name, prefix+"/tables/"))
- }
- return names, nil
- }
- // CreateTable creates a new table in the cluster.
- // This method may return before the table's creation is complete.
- func (ac *AdminClient) CreateTable(ctx context.Context, table string) error {
- prefix := ac.clusterPrefix()
- req := &bttspb.CreateTableRequest{
- Name: prefix,
- TableId: table,
- }
- _, err := ac.tClient.CreateTable(ctx, req)
- if err != nil {
- return err
- }
- return nil
- }
- // CreateColumnFamily creates a new column family in a table.
- func (ac *AdminClient) CreateColumnFamily(ctx context.Context, table, family string) error {
- // TODO(dsymonds): Permit specifying gcexpr and any other family settings.
- prefix := ac.clusterPrefix()
- req := &bttspb.CreateColumnFamilyRequest{
- Name: prefix + "/tables/" + table,
- ColumnFamilyId: family,
- }
- _, err := ac.tClient.CreateColumnFamily(ctx, req)
- return err
- }
- // DeleteTable deletes a table and all of its data.
- func (ac *AdminClient) DeleteTable(ctx context.Context, table string) error {
- prefix := ac.clusterPrefix()
- req := &bttspb.DeleteTableRequest{
- Name: prefix + "/tables/" + table,
- }
- _, err := ac.tClient.DeleteTable(ctx, req)
- return err
- }
- // DeleteColumnFamily deletes a column family in a table and all of its data.
- func (ac *AdminClient) DeleteColumnFamily(ctx context.Context, table, family string) error {
- prefix := ac.clusterPrefix()
- req := &bttspb.DeleteColumnFamilyRequest{
- Name: prefix + "/tables/" + table + "/columnFamilies/" + family,
- }
- _, err := ac.tClient.DeleteColumnFamily(ctx, req)
- return err
- }
- // TableInfo represents information about a table.
- type TableInfo struct {
- Families []string
- }
- // TableInfo retrieves information about a table.
- func (ac *AdminClient) TableInfo(ctx context.Context, table string) (*TableInfo, error) {
- prefix := ac.clusterPrefix()
- req := &bttspb.GetTableRequest{
- Name: prefix + "/tables/" + table,
- }
- res, err := ac.tClient.GetTable(ctx, req)
- if err != nil {
- return nil, err
- }
- ti := &TableInfo{}
- for fam := range res.ColumnFamilies {
- ti.Families = append(ti.Families, fam)
- }
- return ti, nil
- }
- // SetGCPolicy specifies which cells in a column family should be garbage collected.
- // GC executes opportunistically in the background; table reads may return data
- // matching the GC policy.
- func (ac *AdminClient) SetGCPolicy(ctx context.Context, table, family string, policy GCPolicy) error {
- prefix := ac.clusterPrefix()
- tbl, err := ac.tClient.GetTable(ctx, &bttspb.GetTableRequest{
- Name: prefix + "/tables/" + table,
- })
- if err != nil {
- return err
- }
- fam, ok := tbl.ColumnFamilies[family]
- if !ok {
- return fmt.Errorf("unknown column family %q", family)
- }
- fam.GcRule = policy.proto()
- _, err = ac.tClient.UpdateColumnFamily(ctx, fam)
- return err
- }
- const clusterAdminAddr = "bigtableclusteradmin.googleapis.com:443"
- // ClusterAdminClient is a client type for performing admin operations on clusters.
- // These operations can be substantially more dangerous than those provided by AdminClient.
- type ClusterAdminClient struct {
- conn *grpc.ClientConn
- cClient btcspb.BigtableClusterServiceClient
- project string
- }
- // NewClusterAdminClient creates a new ClusterAdminClient for a given project.
- func NewClusterAdminClient(ctx context.Context, project string, opts ...cloud.ClientOption) (*ClusterAdminClient, error) {
- o := []cloud.ClientOption{
- cloud.WithEndpoint(clusterAdminAddr),
- cloud.WithScopes(ClusterAdminScope),
- cloud.WithUserAgent(clientUserAgent),
- }
- o = append(o, opts...)
- conn, err := transport.DialGRPC(ctx, o...)
- if err != nil {
- return nil, fmt.Errorf("dialing: %v", err)
- }
- return &ClusterAdminClient{
- conn: conn,
- cClient: btcspb.NewBigtableClusterServiceClient(conn),
- project: project,
- }, nil
- }
- // Close closes the ClusterAdminClient.
- func (cac *ClusterAdminClient) Close() {
- cac.conn.Close()
- }
- // ClusterInfo represents information about a cluster.
- type ClusterInfo struct {
- Name string // name of the cluster
- Zone string // GCP zone of the cluster (e.g. "us-central1-a")
- DisplayName string // display name for UIs
- ServeNodes int // number of allocated serve nodes
- }
- var clusterNameRegexp = regexp.MustCompile(`^projects/([^/]+)/zones/([^/]+)/clusters/([a-z][-a-z0-9]*)$`)
- // Clusters returns a list of clusters in the project.
- func (cac *ClusterAdminClient) Clusters(ctx context.Context) ([]*ClusterInfo, error) {
- req := &btcspb.ListClustersRequest{
- Name: "projects/" + cac.project,
- }
- res, err := cac.cClient.ListClusters(ctx, req)
- if err != nil {
- return nil, err
- }
- // TODO(dsymonds): Deal with failed_zones.
- var cis []*ClusterInfo
- for _, c := range res.Clusters {
- m := clusterNameRegexp.FindStringSubmatch(c.Name)
- if m == nil {
- return nil, fmt.Errorf("malformed cluster name %q", c.Name)
- }
- cis = append(cis, &ClusterInfo{
- Name: m[3],
- Zone: m[2],
- DisplayName: c.DisplayName,
- ServeNodes: int(c.ServeNodes),
- })
- }
- return cis, nil
- }
- /* TODO(dsymonds): Re-enable when there's a ClusterAdmin API.
- // SetClusterSize sets the number of server nodes for this cluster.
- func (ac *AdminClient) SetClusterSize(ctx context.Context, nodes int) error {
- req := &btcspb.GetClusterRequest{
- Name: ac.clusterPrefix(),
- }
- clu, err := ac.cClient.GetCluster(ctx, req)
- if err != nil {
- return err
- }
- clu.ServeNodes = int32(nodes)
- _, err = ac.cClient.UpdateCluster(ctx, clu)
- return err
- }
- */
|