Runtime Configuration

The runtimevar package provides an easy and portable way to watch runtime configuration variables. This guide shows how to work with runtime configuration variables using the Go CDK.

Opening a Variable🔗

The first step in watching a variable is to instantiate a *runtimevar.Variable.

The easiest way to do so is to use runtimevar.OpenVariable and a URL pointing to the variable, making sure you “blank import” the driver package to link it in. See Concepts: URLs for more details. If you need fine-grained control over the connection settings, you can call the constructor function in the driver package directly (like etcdvar.OpenVariable).

When opening the variable, you can provide a decoder parameter (either as a query parameter for URLs, or explicitly to the constructor) to specify whether the raw value stored in the variable is interpreted as a string, a []byte, or as JSON.

See the guide below for usage of both forms for each supported provider.

Using a Variable🔗

Once you have opened a runtimevar.Variable for the provider you want, you can use it portably.

Latest🔗

The easiest way to a Variable is to use the Variable.Latest method. It returns the latest good Snapshot of the variable value, blocking if no good value has ever been received. The dynamic type of Snapshot.Value depends on the decoder you provided when creating the Variable.

To avoid blocking, you can pass an already-Done context.

snapshot, err := v.Latest(context.Background())
if err != nil {
	log.Fatalf("Error in retrieving variable: %v", err)
}
// If runtimevar.StringDecoder was used when constructing v, the
// snapshot.Value will be of type string.
fmt.Printf("%q\n", snapshot.Value.(string))

Watch🔗

Variable also has a Watch method for obtaining the value of a variable; it has different semantics than Latest and may be useful in some scenarios. We recommend starting with Latest as it’s conceptually simpler to work with.

Supported Services🔗

GCP Runtime Configurator🔗

To open a variable stored in GCP Runtime Configurator via a URL, you can use the runtimevar.OpenVariable function as follows.

import (
	"context"

	_ "gocloud.dev/runtimervar/gcpruntimeconfig"
	"gocloud.dev/runtimevar"
)

// runtimevar.OpenVariable creates a *runtimevar.Variable from a URL.
// The URL Host+Path are used as the GCP Runtime Configurator Variable key;
// see https://cloud.google.com/deployment-manager/runtime-configurator/
// for more details.

v, err := runtimevar.OpenVariable(ctx, "gcpruntimeconfig://projects/myproject/configs/myconfigid/variables/myvar?decoder=string")
if err != nil {
	return err
}
defer v.Close()

GCP Constructor🔗

The gcpruntimeconfig.OpenVariable constructor opens a Runtime Configurator variable.

import (
	"context"

	"gocloud.dev/gcp"
	"gocloud.dev/runtimevar"
	"gocloud.dev/runtimevar/gcpruntimeconfig"
)

// Your GCP credentials.
// See https://cloud.google.com/docs/authentication/production
// for more info on alternatives.
creds, err := gcp.DefaultCredentials(ctx)
if err != nil {
	return err
}

// Connect to the Runtime Configurator service.
client, cleanup, err := gcpruntimeconfig.Dial(ctx, creds.TokenSource)
if err != nil {
	return err
}
defer cleanup()

// Create a decoder for decoding JSON strings into MyConfig.
decoder := runtimevar.NewDecoder(MyConfig{}, runtimevar.JSONDecode)

// You can use the VariableKey helper to construct a Variable key from
// your project ID, config ID, and the variable name; alternatively,
// you can construct the full string yourself (e.g.,
// "projects/gcp-project-id/configs/config-id/variables/variable-name").
// See https://cloud.google.com/deployment-manager/runtime-configurator/
// for more details.
//
// For this example, the GCP Cloud Runtime Configurator variable being
// referenced should have a JSON string that decodes into MyConfig.
variableKey := gcpruntimeconfig.VariableKey("gcp-project-id", "config-id", "variable-name")

// Construct a *runtimevar.Variable that watches the variable.
v, err := gcpruntimeconfig.OpenVariable(client, variableKey, decoder, nil)
if err != nil {
	return err
}
defer v.Close()

AWS Parameter Store🔗

To open a variable stored in AWS Parameter Store via a URL, you can use the runtimevar.OpenVariable function as follows.

import (
	"context"

	_ "gocloud.dev/runtimervar/awsparamstore"
	"gocloud.dev/runtimevar"
)

// runtimevar.OpenVariable creates a *runtimevar.Variable from a URL.

v, err := runtimevar.OpenVariable(ctx, "awsparamstore://myvar?region=us-west-1&decoder=string")
if err != nil {
	return err
}
defer v.Close()

AWS Constructor🔗

The awsparamstore.OpenVariable constructor opens a Parameter Store variable.

import (
	"github.com/aws/aws-sdk-go/aws/session"
	"gocloud.dev/runtimevar"
	"gocloud.dev/runtimevar/awsparamstore"
)

// Establish an AWS session.
// See https://docs.aws.amazon.com/sdk-for-go/api/aws/session/ for more info.
sess, err := session.NewSession(nil)
if err != nil {
	return err
}

// Create a decoder for decoding JSON strings into MyConfig.
decoder := runtimevar.NewDecoder(MyConfig{}, runtimevar.JSONDecode)

// Construct a *runtimevar.Variable that watches the variable.
// For this example, the Parameter Store variable being referenced
// should have a JSON string that decodes into MyConfig.
v, err := awsparamstore.OpenVariable(sess, "cfg-variable-name", decoder, nil)
if err != nil {
	return err
}
defer v.Close()

etcd🔗

The Go CDK supports using etcd for storing variables locally or remotely. To open a variable stored in etcd via a URL, you can use the runtimevar.OpenVariable function as follows.

import (
	"context"

	"gocloud.dev/runtimevar"
	_ "gocloud.dev/runtimevar/etcdvar"
)

// runtimevar.OpenVariable creates a *runtimevar.Variable from a URL.
// The default opener connects to an etcd server based on the environment
// variable ETCD_SERVER_URL.

v, err := runtimevar.OpenVariable(ctx, "etcd://myvarname")
if err != nil {
	return err
}
defer v.Close()

Etcd Constructor🔗

The etcdvar.OpenVariable constructor opens an etcd variable.

import (
	"go.etcd.io/etcd/clientv3"
	"gocloud.dev/runtimevar"
	"gocloud.dev/runtimevar/etcdvar"
)

// Connect to the etcd server.
client, err := clientv3.NewFromURL("http://your.etcd.server:9999")
if err != nil {
	return err
}

// Create a decoder for decoding JSON strings into MyConfig.
decoder := runtimevar.NewDecoder(MyConfig{}, runtimevar.JSONDecode)

// Construct a *runtimevar.Variable that watches the variable.
// The etcd variable being referenced should have a JSON string that
// decodes into MyConfig.
v, err := etcdvar.OpenVariable(client, "cfg-variable-name", decoder, nil)
if err != nil {
	return err
}
defer v.Close()