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/mever/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 ¶
- Variables
- func NewContextFromEnvironment(r *Registry, stateDir string, hookName string, args []string) (*Context, PersistentState, error)
- func RegisterMainHooks(r *Registry)
- type CharmInfo
- type Command
- type Context
- func (ctxt *Context) Close() error
- func (ctxt *Context) ClosePort(proto string, port int) error
- func (ctxt *Context) CommandName() string
- func (ctxt *Context) GetAllConfig(val interface{}) error
- func (ctxt *Context) GetConfig(key string, val interface{}) error
- func (ctxt *Context) GetConfigBool(key string) (bool, error)
- func (ctxt *Context) GetConfigFloat64(key string) (float64, error)
- func (ctxt *Context) GetConfigInt(key string) (int, error)
- func (ctxt *Context) GetConfigString(key string) (string, error)
- func (ctxt *Context) IsRelationHook() bool
- func (ctxt *Context) Logf(f string, a ...interface{}) error
- func (ctxt *Context) OpenPort(proto string, port int) error
- func (ctxt *Context) PrivateAddress() (string, error)
- func (ctxt *Context) PublicAddress() (string, error)
- func (ctxt *Context) Relation() map[string]string
- func (ctxt *Context) SetRelation(keyvals ...string) error
- func (ctxt *Context) SetRelationWithId(relationId RelationId, keyvals ...string) error
- func (ctxt *Context) SetStatus(st Status, message string) error
- func (ctxt *Context) StateDir() string
- func (ctxt *Context) UnitTag() string
- type ContextSetter
- type PersistentState
- type Registry
- func (r *Registry) CharmInfo() CharmInfo
- func (r *Registry) Clone(name string) *Registry
- func (r *Registry) RegisterAsset(path string, content []byte)
- func (r *Registry) RegisterCommand(f func(args []string) (Command, error))
- func (r *Registry) RegisterConfig(name string, opt charm.Option)
- func (r *Registry) RegisterContext(setter ContextSetter, state interface{})
- func (r *Registry) RegisterHook(name string, f func() error)
- func (r *Registry) RegisterRelation(rel charm.Relation)
- func (r *Registry) RegisterResource(res resource.Meta)
- func (r *Registry) RegisteredConfig() map[string]charm.Option
- func (r *Registry) RegisteredHooks() []string
- func (r *Registry) RegisteredRelations() map[string]charm.Relation
- func (r *Registry) RegisteredResources() map[string]resource.Meta
- func (r *Registry) SetCharmInfo(info CharmInfo)
- type RelationId
- type Status
- type ToolRunner
- type UnitId
Constants ¶
This section is empty.
Variables ¶
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 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) ClosePort ¶
ClosePort closes the given port associated with the given protocol. If the port is already closed, this is a no-op.
func (*Context) CommandName ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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 ¶
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) OpenPort ¶
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 ¶
PrivateAddress returns the private address of the local unit.
func (*Context) PublicAddress ¶
PublicAddress returns the public address of the local unit.
func (*Context) Relation ¶
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 ¶
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 ¶
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.
type ContextSetter ¶
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 (*Registry) Clone ¶
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 ¶
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 ¶
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 ¶
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 ¶
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) RegisterResource ¶
RegisterResource registers a resource to be included in the charm's metadata.yaml. If a resource is registered twice with the same name, all of the details must also match.
func (*Registry) RegisteredConfig ¶
RegisteredConfig returns the configuration options that have been registered with RegisterConfig.
func (*Registry) RegisteredHooks ¶
RegisteredHooks returns the names of all currently registered hooks, excluding wildcard ("*") hooks.
func (*Registry) RegisteredRelations ¶
RegisteredRelations returns relations that have been registered with RegisterRelation, keyed by relation name.
func (*Registry) RegisteredResources ¶
RegisteredResources returns resources that have been registered with RegisterResource.
func (*Registry) SetCharmInfo ¶
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 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.