hook

package
v0.0.0-...-c60bc85 Latest Latest
Warning

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

Go to latest
Published: May 19, 2017 License: LGPL-3.0 Imports: 18 Imported by: 1

Documentation

Overview

The hook package provides a Go interface to the Juju charm hook commands. It is designed to be used alongside the gocharm command. See http://godoc.org/github.com/juju/gocharm/cmd/gocharm .

When a gocharm-compiled Juju hook runs, the first thing that happens is that the RegisterHooks function is called. This is called both when the hook actually runs and when the charm is built, so it is important that code that runs in this context does nothing except register anything that needs to be registered with the provided Registry.

Note that it is important that the code runs deterministically - it should not register different hooks or relations depending on the current external environment.

Note also that when passing a Registry to some external code, it should be cloned (see the Registry.Clone method) with some locally unique identifier. This identifier has a similar purpose to a field name in a struct - it provides the gocharm logic with a name that it can use to store data associated with registry. At runtime, all local state is stored in the directory /usr/lib/juju-localstate/<env-UUID>. You will see the names provided to Registry.Clone reflected in the names of the files created there.

After all hooks, relations and config options have been registered, any functions registered with Registry.SetContext will be called. This provides code with the Context, which is a charm's handle onto the external Juju world.

Then any registered hooks will be called in the order that they were registered (except wildcard hooks, which run after any others). This is the time that all your hook logic should do what it needs to, such as maintaining relation settings, reacting to configuration changes, etc.

Index

Constants

This section is empty.

Variables

View Source
var ErrUnimplemented = errgo.New("unimplemented hook tool")

Functions

func NewContextFromEnvironment

func NewContextFromEnvironment(r *Registry, stateDir string, hookName string, args []string) (*Context, PersistentState, error)

NewContextFromEnvironment creates a hook context from the current environment, using the given tool runner to acquire information to populate the context, and the given registry to determine which relations to fetch information for.

The hookName argument holds the name of the hook to invoke, and args holds any additional arguments.

The given directory will be used to save persistent state.

It also returns the persistent state associated with the context unless called in a command-running context.

The caller is responsible for calling Close on the returned context.

func RegisterMainHooks

func RegisterMainHooks(r *Registry)

RegisterMainHooks registers any hooks that are needed by any charm. It should be called after any other Register functions.

This function is designed to be called by gocharm generated code only.

Types

type CharmInfo

type CharmInfo struct {
	Name        string
	Summary     string
	Description string
}

CharmInfo holds descriptive information associated with a charm.

type Command

type Command interface {
	// Kill requests that the command be stopped.
	// It may be called concurrently with Wait.
	Kill()

	// Wait waits for the command to complete and
	// returns any error encountered when running.
	Wait() error
}

Command is implemented by running commands that implement long-lived services.

func Main

func Main(r *Registry, ctxt *Context, state PersistentState) (_ Command, err error)

Main creates a new context from the environment and invokes the appropriate command or hook functions from the given registry or sub-registries of it.

If a long-lived command is started, Main returns it rather than waiting for it to complete. This makes it possible to run command functions in tests.

The ctxt value holds the context that will be passed to the hooks; the state value is used to retrieve and save persistent state.

This function is designed to be called by gocharm generated code and tests only.

type Context

type Context struct {

	// UUID holds the globally unique environment id.
	UUID string

	// Unit holds the name of the current charm's unit.
	Unit UnitId

	// CharmDir holds the directory that the charm is running from.
	CharmDir string

	// HookStateDir holds the directory where hook state is stored.
	HookStateDir string

	// HookName holds the name of the currently running hook.
	HookName string

	// Relations holds all the relation data available to the charm.
	// For each relation id, it holds all the units that have joined
	// that relation, and within that, all the relation settings for
	// each of those units.
	//
	// This does not include settings for the charm unit itself.
	Relations map[RelationId]map[UnitId]map[string]string

	// RelationIds holds the relation ids for each relation declared
	// in the charm. For example, if the charm has a relation named
	// "webserver" in its metadata.yaml, the current ids for that
	// relation (i.e. all the relations have have been made by the
	// user) will be in RelationIds["webserver"].
	RelationIds map[string][]RelationId

	// RelationName holds the name of the relation that
	// the current relation hook is running for. It will be
	// one of the relation names declared in the metadata.yaml file.
	RelationName string

	// RelationId holds the id of the relation that
	// the current relation hook is running for. See RelationIds above.
	RelationId RelationId

	// RemoteUnit holds the id of the unit that the current
	// relation hook is running for. This will be empty
	// for a relation-broken hook.
	RemoteUnit UnitId

	// Runner is used to run hook tools by methods on the context.
	Runner ToolRunner

	// RunCommandName holds the name of the command, when
	// the runhook executable is run as a command.
	// If this is set, none of the other fields will be valid.
	// This will never be set when the context is passed
	// into any hook function.
	RunCommandName string

	// RunCommandArgs holds any arguments that were passed to
	// the above command.
	RunCommandArgs []string
	// contains filtered or unexported fields
}

Context provides information about the hook context. It should be treated as read-only.

func (*Context) Close

func (ctxt *Context) Close() error

Close closes ctxt.Runner, if it is not nil.

func (*Context) ClosePort

func (ctxt *Context) ClosePort(proto string, port int) error

ClosePort closes the given port associated with the given protocol. If the port is already closed, this is a no-op.

func (*Context) CommandName

func (ctxt *Context) CommandName() string

CommandName returns a value that can be used to make runhook run the given command when passed as its first argument. The command run will be the command registered with RegisterCommand on the registry this context is derived from. TODO better explanation and an example.

func (*Context) GetAllConfig

func (ctxt *Context) GetAllConfig(val interface{}) error

GetAllConfig unmarshals all the configuration values from a JSON object into the given value, which should be a pointer to a struct or a map. To get all values without knowing what they might be, pass in a pointer to a map[string]interface{} value,

func (*Context) GetConfig

func (ctxt *Context) GetConfig(key string, val interface{}) error

GetConfig reads the charm configuration value for the given key into the value pointed to by val, which should be a pointer to one of the possible configuration option types (string, int, float64 or boolean). To find out whether a value has actually been set (is non-null) pass a pointer to a pointer to the desired type.

func (*Context) GetConfigBool

func (ctxt *Context) GetConfigBool(key string) (bool, error)

GetConfigBool returns the charm configuration value for the given key as a bool. It returns false if the value has not been set.

func (*Context) GetConfigFloat64

func (ctxt *Context) GetConfigFloat64(key string) (float64, error)

GetConfigFloat64 returns the charm configuration value for the given key as a float64. It returns zero if the value has not been set.

func (*Context) GetConfigInt

func (ctxt *Context) GetConfigInt(key string) (int, error)

GetConfigInt returns the charm configuration value for the given key as an int. It returns zero if the value has not been set.

func (*Context) GetConfigString

func (ctxt *Context) GetConfigString(key string) (string, error)

GetConfigString returns the charm configuration value for the given key as a string. It returns the empty string if the value has not been set.

func (*Context) IsRelationHook

func (ctxt *Context) IsRelationHook() bool

IsRelationHook reports whether the current hook is executing as a result of a relation change. If it returns true, then ctxt.RelationName, ctxt.RelationId and possibly ctxt.RemoteUnit will be set.

func (*Context) Logf

func (ctxt *Context) Logf(f string, a ...interface{}) error

Log logs a message through the juju logging facility.

func (*Context) OpenPort

func (ctxt *Context) OpenPort(proto string, port int) error

OpenPort opens the given port using the given protocol ("tcp" or "udp"). It if the port is already open, this is a no-op.

func (*Context) PrivateAddress

func (ctxt *Context) PrivateAddress() (string, error)

PrivateAddress returns the private address of the local unit.

func (*Context) PublicAddress

func (ctxt *Context) PublicAddress() (string, error)

PublicAddress returns the public address of the local unit.

func (*Context) Relation

func (ctxt *Context) Relation() map[string]string

Relation holds the current relation settings for the unit that triggered the current hook. It will panic if the current hook is not a relation-related hook.

func (*Context) SetRelation

func (ctxt *Context) SetRelation(keyvals ...string) error

SetRelation sets the given key-value pairs on the current relation instance.

func (*Context) SetRelationWithId

func (ctxt *Context) SetRelationWithId(relationId RelationId, keyvals ...string) error

SetRelationWithId sets the given key-value pairs on the relation with the given id.

func (*Context) SetStatus

func (ctxt *Context) SetStatus(st Status, message string) error

SetStatus sets the current status of a charm and an associated message. If the status cannot be set because we are using a version of juju that does not yet support it, that error will be silently discarded.

func (*Context) StateDir

func (ctxt *Context) StateDir() string

StateDir returns the path to the directory where local state for the given context will be stored. The directory is relative to the registry through which the context was created. It is not guaranteed to exist.

func (*Context) UnitTag

func (ctxt *Context) UnitTag() string

UnitTag returns the tag of the current unit, useful for using as a file name.

type ContextSetter

type ContextSetter func(ctxt *Context) error

ContextSetter is the type of a function that can set the context for a hook. Usually this is a method that sets a context variable inside a struct.

type PersistentState

type PersistentState interface {
	// Save saves the given state data with the given name.
	Save(name string, data []byte) error

	// Load loads the state data from the given name.
	// If the data has not previously been saved, this
	// should return (nil, nil).
	Load(name string) ([]byte, error)
}

PersistentState is used to save persistent charm state to disk. It is defined as an interface so that it can be defined differently for tests. The customary implementation is DiskState.

func NewDiskState

func NewDiskState(dir string) PersistentState

NewDiskState returns an implementation of PersistentState that stores state in the given directory.

type Registry

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

Registry allows the registration of hook functions.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns a new hook registry.

func (*Registry) CharmInfo

func (r *Registry) CharmInfo() CharmInfo

CharmInfo returns descriptive information about the charm.

func (*Registry) Clone

func (r *Registry) Clone(name string) *Registry

Clone returns a sub-registry of r with the given name. This will use a separate name space for local state and for commands. This should be used when passing a registry to an external package Register function.

This method may not be called more than once on the same registry with the same name. The name must be filesystem safe, and must not contain a '.' character or be blank. If either of these two conditions occur, Clone will panic.

func (*Registry) RegisterAsset

func (r *Registry) RegisterAsset(path string, content []byte)

RegisterAsset registers a file to be included in the charm directory. The given path should be relative to the root of the charm directory.

func (*Registry) RegisterCommand

func (r *Registry) RegisterCommand(f func(args []string) (Command, error))

RegisterCommand registers the given function to be called when the hook is invoked with a first argument of "cmd". It will panic if it is called more than once in the same Registry. The function will be called with any extra arguments passed on the command line, without the command name itself.

The function may return a nil Command if it completes immediately

or return a Command representing a long-running service.

Note that the function will not be called in hook context, so it will not have any of the usual hook context to use.

func (*Registry) RegisterConfig

func (r *Registry) RegisterConfig(name string, opt charm.Option)

RegisterConfig registers a configuration option to be included in the charm's config.yaml. If an option is registered twice with the same name, all of the details must also match.

func (*Registry) RegisterContext

func (r *Registry) RegisterContext(setter ContextSetter, state interface{})

RegisterContext registers a function that will be called to set up a context before hook function execution.

If state is non-nil, it should hold a pointer to a value that will be used to hold persistent state associated with the function. When a hook runs, before the setter function is called, any previously saved state is loaded into the value. When all hooks have completed, the state is saved, making it persistent. The data is saved using JSON.Marshal.

This function may not be called more than once for a given Registry; it will panic if it is.

func (*Registry) RegisterHook

func (r *Registry) RegisterHook(name string, f func() error)

RegisterHook registers the given function to be called when the charm hook with the given name is invoked.

If the name is "*", the function will always be invoked, after any functions registered specifically for the current hook.

If more than one function is registered for a given hook, each function will be called in order of registration until one returns an error.

func (*Registry) RegisterRelation

func (r *Registry) RegisterRelation(rel charm.Relation)

RegisterRelation registers a relation to be included in the charm's metadata.yaml. If a relation is registered twice with the same name, all of the details must also match. If the relation's scope is empty, charm.ScopeGlobal is assumed. If rel.Limit is zero, it is assumed to be 1 if the role is charm.RolePeer or charm.RoleRequirer.

func (*Registry) RegisteredConfig

func (r *Registry) RegisteredConfig() map[string]charm.Option

RegisteredConfig returns the configuration options that have been registered with RegisterConfig.

func (*Registry) RegisteredHooks

func (r *Registry) RegisteredHooks() []string

RegisteredHooks returns the names of all currently registered hooks, excluding wildcard ("*") hooks.

func (*Registry) RegisteredRelations

func (r *Registry) RegisteredRelations() map[string]charm.Relation

RegisteredRelations returns relations that have been registered with RegisterRelation, keyed by relation name.

func (*Registry) SetCharmInfo

func (r *Registry) SetCharmInfo(info CharmInfo)

SetCharmInfo sets the descriptive information associated with the charm. This should be called at least once, otherwise the charm will be named "anon".

type RelationId

type RelationId string

RelationId is the type of the id of a relation. A relation with a given id corresponds to a relation as created by the juju add-relation command.

type Status

type Status string

Status represents the current status of a charm.

const (
	StatusMaintenance Status = "maintenance"
	StatusBlocked     Status = "blocked"
	StatusWaiting     Status = "waiting"
	StatusActive      Status = "active"
)

type ToolRunner

type ToolRunner interface {
	// Run runs the hook tool with the given name
	// and arguments, and returns its standard output.
	// If the command is unimplemented, it should
	// return an error with an ErrUnimplemented cause.
	Run(cmd string, args ...string) (stdout []byte, err error)
	Close() error
}

ToolRunner is used to run hook tools.

type UnitId

type UnitId string

UnitId is the type of the id of a unit.

func (UnitId) Tag

func (id UnitId) Tag() names.UnitTag

Tag returns the juju "tag" name of the unit.

Directories

Path Synopsis
Package hooktest contains utilities for testing gocharm hooks.
Package hooktest contains utilities for testing gocharm hooks.

Jump to

Keyboard shortcuts

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