konsul

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2023 License: MIT Imports: 12 Imported by: 0

README

Konsul

Konsul is an opinionated wrapper around the official Consul GO Client/SDK client. I've often had to work with configuration stored in Consul KVs and performing client side load balancing for services registered in Consul. I built this library to streamline working with Consul from Go with convenient wrappers and utilities.

Konsul provides the following:

  • Wrapper around KV client to that streamlines handling fetching KVs and unmarshalling the values. The API includes several Must methods to panic on error since I've encountered many cases where if fetching configuration stored in Consul fails the application cannot start up.
  • A Watch function to watch a specific KV and automatically unmarshall and reload configuration on change.
  • An Instancer type to implement client side load balancing of a Consul service.
  • Wrappers to allow zap and zerolog to work with Consul API. The wrappers implement the hclog.Logger interface.

There are examples that can be referenced in the examples directory.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrKeyNotFound is a sentinel error value indicating the key provided
	// doesn't exist.
	ErrKeyNotFound = errors.New("key not found")
)

Functions

func Watch

func Watch(client *api.Client, key string, cfg encoding.BinaryUnmarshaler,
	opts WatchOptions) error

Watch watches a key in Consul's KV store and automatically refreshes a type with the value of the key on change.

This is useful for handing configuration stored in Consul KV store and mapping it to a struct in Go. When the KV is changed it will automatically pass the value to the configuration struct implementing the BinaryUnmarshaler interface allowing it to refresh/update its internals.

Because the nature of the BinaryUnmarshaler interface, cfg should always be a pointer. If a value is provided this function will have no effect as the changes will not be reflected.

Watch is blocking and in nearly all use cases it should be called on a new goroutine. Watch is intended to execute for the entire lifecycle of the application. It doesn't provide a mechanism to stop watching a key. It will only return on an error, and if it returns with an error the application will no longer receive updates when a KV changes. In many cases the caller may want to panic to prevent unexpected behavior since the configuration will not be updated as expected.

Example:

 cfg := &AppConfig{}
	go func() {
		err = konsul.Watch(client, "config/app", cfg, konsul.WatchOptions{
			Logger:                  kzap.Wrap(logger),
			PanicOnUnmarshalFailure: false,
		})
		// If Watch returns an error we aren't getting KV updates anymore so we'll
		// panic rather than running in a potentially weird state where we aren't
		// getting updates.
		if err != nil {
			panic(err)
		}
	}()

Types

type InstanceListener

type InstanceListener interface {
	OnChange(instances []string)
}

InstanceListener is a type the listens for changes from Instancer. An InstanceListener can be registered with an Instancer and upon changes Instancer will invoke the InstanceListener OnChange method with updated instances of the configured service.

type Instancer

type Instancer struct {
	// contains filtered or unexported fields
}

Instancer is a client-side loadbalancer implementation based on Consul services. Instancer yields instances of a service registered in Consul and watches for changes. When changes are detected Instancer updates its internal cache of instances and notifies any listeners.

The zero-value of Instancer is not usable. Use NewInstancer method to create and initialize a new Instancer.

func NewInstancer

func NewInstancer(config InstancerConfig) (*Instancer, error)

NewInstancer initializes a new Instancer with the provided configuration. If the configuration is invalid (misusing the API) this will panic. If the watch plan cannot be parsed this will return a non-nil error. Upon creating the Instancer it will begin to watch Consul for changes immediately.

In the event the plan stops executing due to an error a panic will occur rather than continuing to run in a state where instances could be out of date/invalid.

func (*Instancer) Close

func (i *Instancer) Close()

Close stops the Instancer and the underlying Consul watch plan. After Close is called Instancer is not usable.

func (*Instancer) Instance

func (i *Instancer) Instance() (string, bool)

Instance return a single instance round-robin load balanced along with a boolean value. If there are no instances the boolean value will be false. Otherwise, it will be true to indicate an instance was returned.

This will panic if the Instancer has been closed.

func (*Instancer) Instances

func (i *Instancer) Instances() []string

Instances returns a copy of the current set of instances

This will panic if the Instancer has been closed.

func (*Instancer) RegisterListener

func (i *Instancer) RegisterListener(l InstanceListener)

RegisterListener registers an InstanceListener with an Instancer to be notified when there is a changes to the instances for the configured service. Upon registering the OnChange method of the InstanceListener will be invoked with the current instances of the Instancer.

Note: RegisterListener doesn't prevent the same InstanceListener from being registered multiple times. In such cases its OnChange method will be invoked multiple times.

This will panic if the Instancer has been closed.

type InstancerConfig

type InstancerConfig struct {
	// The Consul api Client to use to communicate with Consul. This is a required
	// field. Providing a nil value will lead to a panic.
	Client *api.Client
	// The registered service in Consul to monitor and load balance. This is a
	// required field. The default zero value will lead to a panic.
	Service string
	// An optional tag to limit the instances Instancer should consider. If this
	// value is the non zero-value only instances that have this tag will be
	// considered.
	Tag string
	// Specifies if Instancer should only consider passing/healthy instances. In
	// nearly all cases this should be set to true.
	PassingOnly bool
	// Determines how Consul client interacts with Consul servers. When true any
	// Consul server can be queried. Otherwise, all queries go to the leader.
	AllowStale bool
	// A logger to log internal behavior of Instancer. If a logger is not provided
	// a default one will be used configured at INFO level.
	Logger hclog.Logger
}

InstancerConfig is a type holding the configuration properties to create and initialize an Instancer.

type KVClient

type KVClient struct {
	// contains filtered or unexported fields
}

KVClient is an opinionated wrapper around the official Consul API Client for working with KVs in Consul.

The zero-value of KVClient is not usable. Use NewKVClient to create and initialize a new instance of KVClient.

func NewKVClient

func NewKVClient(c *api.Client) *KVClient

NewKVClient creates and initializes a new KVClient

func (KVClient) Delete

func (c KVClient) Delete(key string) error

Delete removes a key/value from the Consul KV store. If this operation fails a non-nil error value is returned.

func (KVClient) Get

func (c KVClient) Get(key string, allowStale bool) (KeyValue, error)

Get retrieves a key-value from the Consul KV store. The KeyValue is returned wrapped by an Option as the key may or may not exist in Consul. If an error occurs communicating with Consul a non-nil error value will be returned.

func (KVClient) MustGet

func (c KVClient) MustGet(key string, allowStale bool) KeyValue

MustGet retrieves a key-value from Consul KV store. If an error occurs fetching the key from Consul, or the key doesn't exist this will panic.

func (KVClient) MustPut

func (c KVClient) MustPut(key string, value []byte)

MustPut sets a value for a provided key in Consul KV store. If the operation fails this will panic.

func (KVClient) MustPutJSON

func (c KVClient) MustPutJSON(key string, v any)

MustPutJSON marshals the provided value as JSON and sets that value for the given key in Consul KV store. If an error occurs during this operation this will panic.

func (KVClient) MustPutYAML

func (c KVClient) MustPutYAML(key string, v any)

MustPutYAML marshals the provided value as YAML and sets that value for the given key in Consul KV store. If an error occurs during this operation this will panic.

func (KVClient) Put

func (c KVClient) Put(key string, value []byte) error

Put sets a value for a provided key in Consul KV store. If the operation fails a non-nil error value is returned.

func (KVClient) PutJSON

func (c KVClient) PutJSON(key string, v any) error

PutJSON marshals the provided value as JSON and sets that value for the given key in Consul KV store. If marshaling fails or putting the value in consul fails this returns a non-nil error value.

func (KVClient) PutYAML

func (c KVClient) PutYAML(key string, v any) error

PutYAML marshals the provided value as YAML and sets that value for the given key in Consul KV store. If marshaling fails or putting the value in consul fails this returns a non-nil error value.

type KeyValue

type KeyValue struct {
	// contains filtered or unexported fields
}

KeyValue is a wrapper around KVPair type from official Consul API package. It provides convenient methods to unmarshal the value from Consul as JSON or YAML to a Go type.

func (KeyValue) CreateIndex

func (kv KeyValue) CreateIndex() uint64

CreateIndex holds the index corresponding the creation of this KVPair. This is a read-only field.

func (KeyValue) Flags

func (kv KeyValue) Flags() uint64

Flags are any user-defined flags on the key. It is up to the implementer to check these values, since Consul does not treat them specially.

func (KeyValue) IsEmpty

func (kv KeyValue) IsEmpty() bool

IsEmpty returns a bool indicating if the value of the KV is empty.

IsEmpty can be helpful for handling cases where the key exists in Consul KV store but could have an empty value.

func (KeyValue) Key

func (kv KeyValue) Key() string

Key is the name of the key. It is also part of the URL path when accessed via the API.

func (KeyValue) LockIndex

func (kv KeyValue) LockIndex() uint64

LockIndex holds the index corresponding to a lock on this key, if any. This is a read-only field.

func (KeyValue) ModifyIndex

func (kv KeyValue) ModifyIndex() uint64

ModifyIndex is used for the Check-And-Set operations and can also be fed back into the WaitIndex of the QueryOptions in order to perform blocking queries.

func (KeyValue) MustUnmarshalValueJSON

func (kv KeyValue) MustUnmarshalValueJSON(v any)

MustUnmarshalValueJSON parses the JSON-encoded data of the KeyValue and stores the result in the value pointed to by v. If an error occurs during unmarshalling this will panic.

func (KeyValue) MustUnmarshalValueYAML

func (kv KeyValue) MustUnmarshalValueYAML(v any)

MustUnmarshalValueYAML parses the YAML-encoded data of the KeyValue and stores the result in the value pointed to by v. If an error occurs during unmarshalling this will panic.

func (KeyValue) Namespace

func (kv KeyValue) Namespace() string

Namespace is the namespace the KVPair is associated with Namespacing is a Consul Enterprise feature.

func (KeyValue) Partition

func (kv KeyValue) Partition() string

Partition is the partition the KVPair is associated with Admin Partition is a Consul Enterprise feature.

func (KeyValue) RawValue

func (kv KeyValue) RawValue() []byte

RawValue is the value for the key. This can be any value and is represented as bytes.

func (KeyValue) Session

func (kv KeyValue) Session() string

Session is a string representing the ID of the session. Any other interactions with this key over the same session must specify the same session ID.

func (KeyValue) UnmarshalValueJSON

func (kv KeyValue) UnmarshalValueJSON(v any) error

UnmarshalValueJSON parses the JSON-encoded data of the KeyValue and stores the result in the value pointed to by v. If v is nil or not a pointer, UnmarshalValueJSON returns an InvalidUnmarshalError.

func (KeyValue) UnmarshalValueYAML

func (kv KeyValue) UnmarshalValueYAML(v any) error

UnmarshalValueYAML parses the YAML-encoded data of the KeyValue and stores the result in the value pointed to by v. If v is nil or not a pointer, UnmarshalValueYAML returns an error.

func (KeyValue) Unwrap

func (kv KeyValue) Unwrap() *api.KVPair

Unwrap returns the underlying KVPair

func (KeyValue) Value

func (kv KeyValue) Value() string

Value is the value for the key represented as a string.

type WatchNotificationFunc added in v0.2.0

type WatchNotificationFunc func(key string, err error)

WatchNotificationFunc is a callback function that can optionally be invoked by Watch when a KV is changed to notify the application code. If the KV change was handled successfully the error value will be nil, otherwise a non-nil error value is passed.

type WatchOptions added in v0.2.0

type WatchOptions struct {
	// The logger used to log events and errors while watching a KV in Consul.
	// If not provided a default logger will be used.
	Logger hclog.Logger
	// Flag to control if the Watch function should panic if it cannot successfully
	// unmarshall and update the target type on a KV change event. When true Watch
	// will panic the call to UnmarshalBinary returns an error.
	PanicOnUnmarshalFailure bool
	// An optional callback func that get invoked everytime a KV change is detected.
	WatchNotification WatchNotificationFunc
}

WatchOptions holds configuration properties customizing the behavior of Watch.

Directories

Path Synopsis
examples
kv
log
zap

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL