Provisioning Cluster Resources

Provisioning cluster resources is managed at the collection or bucket level, depending upon the service affected. Common use cases are outlined here, more recherché use cases are covered in the API docs.

The primary means for managing clusters is through the Couchbase Web UI which provides an easy to use interface for adding, removing, monitoring and modifying buckets. In some instances you may wish to have a programmatic interface. For example, if you wish to manage a cluster from a setup script, or if you are setting up buckets in test scaffolding.

The Go SDK also comes with some convenience functionality for common Couchbase management requests.

Management operations in the SDK may be performed through several interfaces depending on the object:

  • BucketManager — Cluster.Buckets()

  • UserManager — Cluster.Users() // see xref

  • QueryIndexManager — Cluster.QueryIndexes()

  • AnalyticsIndexManager — Cluster.AnalyticsIndexes()

  • SearchIndexManager — Cluster.SearchIndexes()

  • CollectionManager — Bucket.Collections()

  • ViewIndexManager — Bucket.ViewIndexes().

When using a Couchbase version earlier than 6.5, you must create a valid Bucket connection using cluster.Bucket(name) before you can use cluster level managers.

Creating and Removing Buckets

The ClusterManager interface may be used to create and delete buckets from the Couchbase cluster. It is instantiated through the Cluster.Buckets() method.

cluster, err := gocb.Connect("10.112.193.101", opts)
if err != nil {
	panic(err)
}

bucketMgr := cluster.Buckets()

The CreateBucketSettings and BucketSettings structs are used for creating and updating buckets, BucketSettings is also used for exposing information about existing buckets.

Note that any property that is not explicitly set when building the BucketSettings will use the default value. In the case of the update, this is not necessarily the currently configured value, so you should be careful to set all properties to their correct expected values when updating an existing bucket configuration.

Here is the list of parameters available:

Name

Description

Can be updated

Name string

The name of the bucket, required for creation.

false

FlushEnabled boolean

Enables flushing to be performed on this bucket (see the Flushing Buckets section below).

true

ReplicaIndexDisabled boolean

Whether or not to replicate indexes.

false

RAMQuotaMB uint64

How much memory should each node use for the bucket, required for creation.

true

NumReplicas uint32

The number of replicas to use for the bucket.

true

BucketType BucketType

The type of the bucket, required for creation.

false

EvictionPolicy EvictionPolicyType

The type of the eviction to use for the bucket, defaults to valueOnly.

true (note: changing will cause the bucket to restart causing temporary inaccessibility)

MaxTTL time.Duration

The default maximum time-to-live to apply to documents in the bucket. (note: This option is only available for Couchbase and Ephemeral buckets in Couchbase Enterprise Edition.)

true

CompressionMode CompressionMode

The compression mode to apply to documents in the bucket. (note: This option is only available for Couchbase and Ephemeral buckets in Couchbase Enterprise Edition.)

true

ConflictResolutionType ConflictResolutionType

The conflict resolution type to apply to conflicts on the bucket, defaults to seqno

false

The following example creates a "hello" bucket:

err := bucketMgr.CreateBucket(gocb.CreateBucketSettings{
	BucketSettings: gocb.BucketSettings{
		Name:                 "hello",
		FlushEnabled:         false,
		ReplicaIndexDisabled: true,
		RAMQuotaMB:           1024,
		NumReplicas:          1,
		BucketType:           gocb.CouchbaseBucketType,
	},
	ConflictResolutionType: gocb.ConflictResolutionTypeSequenceNumber,
}, nil)
if err != nil {
	panic(err)
}

We can now get this bucket and update it to enable Flush:

settings, err := bucketMgr.GetBucket("test", nil)
if err != nil {
	panic(err)
}

settings.FlushEnabled = true
err = bucketMgr.UpdateBucket(*settings, nil)
if err != nil {
	panic(err)
}

Once you no longer need to use the bucket, you can remove it:

err := bucketMgr.DropBucket("test", nil)
if err != nil {
	panic(err)
}

Flushing Buckets

When a bucket is flushed, all content is removed. Because this operation is potentially dangerous it is disabled by default for each bucket. Bucket flushing may be useful in test environments where it becomes a simpler alternative to removing and creating a test bucket. You may enable bucket flushing on a per-bucket basis using the Couchbase Web Console or when creating a bucket.

You can flush a bucket in the SDK by using the Flush method:

err := bucketMgr.FlushBucket("test", nil)
if err != nil {
	panic(err)
}

The Flush operation may fail if the bucket does not have flush enabled, in that case it will return an ErrBucketNotFlushable.

Collection Management

This is a Developer Preview feature, see the API doc.

Index Management

In general,you will rarely need to work with Index Managers from the SDK. For those occasions when you do, please see the relevant API docs:

View Management

Views are stored in design documents. The SDK provides convenient methods to create, retrieve, and remove design documents. To set up views, you create design documents that contain one or more view definitions, and then insert the design documents into a bucket. Each view in a design document is represented by a name and a set of MapReduce functions. The mandatory map function describes how to select and transform the data from the bucket, and the optional reduce function describes how to aggregate the results.

In the SDK, design documents are represented by the DesignDocument and View structs. All operations on design documents are performed on the ViewIndexManager instance:

viewMgr := bucket.ViewIndexes()

The following example upserts a design document with two views:

designDoc := gocb.DesignDocument{
	Name: "landmarks",
	Views: map[string]gocb.View{
		"by_country": {
			Map:    "function (doc, meta) { if (doc.type == 'landmark') { emit([doc.country, doc.city], null); } }",
			Reduce: nil,
		},
		"by_activity": {
			Map:    "function (doc, meta) { if (doc.type == 'landmark') { emit(doc.activity, null); } }",
			Reduce: "_count",
		},
	},
}

err := viewMgr.UpsertDesignDocument(designDoc, gocb.DesignDocumentNamespaceDevelopment, nil)
if err != nil {
	panic(err)
}

When you want to update an existing document with a new view (or a modification of a view’s definition), you can use the upsertDesignDocument method.

However, this method needs the list of views in the document to be exhaustive, meaning that if you just create the new view definition as previously and add it to a new DesignDocument that you upsert, all your other views will be erased!

The solution is to perform a getDesignDocument, add your view definition to the DesignDocument’s views list, then upsert it. This also works with view modifications, provided the change is in the map or reduce functions (just reuse the same name for the modified View), or for deletion of one out of several views in the document.

Note the use of DesignDocumentNamespaceDevelopment, the other option is DesignDocumentNamespaceProduction. This parameter specifies whether the design document should be created as development, or as production — with the former running over only a small fraction of the documents.

Now that we’ve created a design document we can fetch it:

ddoc, err := viewMgr.GetDesignDocument("landmarks", gocb.DesignDocumentNamespaceDevelopment, nil)
if err != nil {
	panic(err)
}
fmt.Println(ddoc)

We’ve created the design document using DesignDocumentNamespaceDevelopment and now want to push it to production, we can do this with:

err := viewMgr.PublishDesignDocument("landmarks", nil)
if err != nil {
	panic(err)
}

To remove this design document:

err := viewMgr.DropDesignDocument("landmarks", gocb.DesignDocumentNamespaceProduction, nil)
if err != nil {
	panic(err)
}