github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/worker/uniter/runner/jujuc/context.go (about)

     1  // Copyright 2012, 2013, 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package jujuc
     5  
     6  import (
     7  	"fmt"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/juju/errors"
    13  	"github.com/juju/names"
    14  	"gopkg.in/juju/charm.v5"
    15  
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/network"
    18  	"github.com/juju/juju/storage"
    19  )
    20  
    21  // RebootPriority is the type used for reboot requests.
    22  type RebootPriority int
    23  
    24  const (
    25  	// RebootSkip is a noop.
    26  	RebootSkip RebootPriority = iota
    27  	// RebootAfterHook means wait for current hook to finish before
    28  	// rebooting.
    29  	RebootAfterHook
    30  	// RebootNow means reboot immediately, killing and requeueing the
    31  	// calling hook
    32  	RebootNow
    33  )
    34  
    35  // Context is the interface that all hook helper commands
    36  // depend on to interact with the rest of the system.
    37  type Context interface {
    38  	HookContext
    39  	relationHookContext
    40  	actionHookContext
    41  }
    42  
    43  // HookContext represents the information and functionality that is
    44  // common to all charm hooks.
    45  type HookContext interface {
    46  	ContextUnit
    47  	ContextStatus
    48  	ContextInstance
    49  	ContextNetworking
    50  	ContextLeadership
    51  	ContextMetrics
    52  	ContextStorage
    53  	ContextRelations
    54  }
    55  
    56  // UnitHookContext is the context for a unit hook.
    57  type UnitHookContext interface {
    58  	HookContext
    59  }
    60  
    61  // RelationHookContext is the context for a relation hook.
    62  type RelationHookContext interface {
    63  	HookContext
    64  	relationHookContext
    65  }
    66  
    67  type relationHookContext interface {
    68  	// HookRelation returns the ContextRelation associated with the executing
    69  	// hook if it was found, and whether it was found.
    70  	HookRelation() (ContextRelation, bool)
    71  
    72  	// RemoteUnitName returns the name of the remote unit the hook execution
    73  	// is associated with if it was found, and whether it was found.
    74  	RemoteUnitName() (string, bool)
    75  }
    76  
    77  // ActionHookContext is the context for an action hook.
    78  type ActionHookContext interface {
    79  	HookContext
    80  	actionHookContext
    81  }
    82  
    83  type actionHookContext interface {
    84  	// ActionParams returns the map of params passed with an Action.
    85  	ActionParams() (map[string]interface{}, error)
    86  
    87  	// UpdateActionResults inserts new values for use with action-set.
    88  	// The results struct will be delivered to the state server upon
    89  	// completion of the Action.
    90  	UpdateActionResults(keys []string, value string) error
    91  
    92  	// SetActionMessage sets a message for the Action.
    93  	SetActionMessage(string) error
    94  
    95  	// SetActionFailed sets a failure state for the Action.
    96  	SetActionFailed() error
    97  }
    98  
    99  // ContextUnit is the part of a hook context related to the unit.
   100  type ContextUnit interface {
   101  	// UnitName returns the executing unit's name.
   102  	UnitName() string
   103  
   104  	// Config returns the current service configuration of the executing unit.
   105  	ConfigSettings() (charm.Settings, error)
   106  }
   107  
   108  // ContextStatus is the part of a hook context related to the unit's status.
   109  type ContextStatus interface {
   110  	// UnitStatus returns the executing unit's current status.
   111  	UnitStatus() (*StatusInfo, error)
   112  
   113  	// SetUnitStatus updates the unit's status.
   114  	SetUnitStatus(StatusInfo) error
   115  
   116  	// ServiceStatus returns the executing unit's service status
   117  	// (including all units).
   118  	ServiceStatus() (ServiceStatusInfo, error)
   119  
   120  	// SetServiceStatus updates the status for the unit's service.
   121  	SetServiceStatus(StatusInfo) error
   122  }
   123  
   124  // ContextInstance is the part of a hook context related to the unit's intance.
   125  type ContextInstance interface {
   126  	// AvailabilityZone returns the executing unit's availablilty zone.
   127  	AvailabilityZone() (string, bool)
   128  
   129  	// RequestReboot will set the reboot flag to true on the machine agent
   130  	RequestReboot(prio RebootPriority) error
   131  }
   132  
   133  // ContextNetworking is the part of a hook context related to network
   134  // interface of the unit's instance.
   135  type ContextNetworking interface {
   136  	// PublicAddress returns the executing unit's public address.
   137  	PublicAddress() (string, bool)
   138  
   139  	// PrivateAddress returns the executing unit's private address.
   140  	PrivateAddress() (string, bool)
   141  
   142  	// OpenPorts marks the supplied port range for opening when the
   143  	// executing unit's service is exposed.
   144  	OpenPorts(protocol string, fromPort, toPort int) error
   145  
   146  	// ClosePorts ensures the supplied port range is closed even when
   147  	// the executing unit's service is exposed (unless it is opened
   148  	// separately by a co- located unit).
   149  	ClosePorts(protocol string, fromPort, toPort int) error
   150  
   151  	// OpenedPorts returns all port ranges currently opened by this
   152  	// unit on its assigned machine. The result is sorted first by
   153  	// protocol, then by number.
   154  	OpenedPorts() []network.PortRange
   155  }
   156  
   157  // ContextLeadership is the part of a hook context related to the
   158  // unit leadership.
   159  type ContextLeadership interface {
   160  	// IsLeader returns true if the local unit is known to be leader for at
   161  	// least the next 30s.
   162  	IsLeader() (bool, error)
   163  
   164  	// LeaderSettings returns the current leader settings. Once leader settings
   165  	// have been read in a given context, they will not be updated other than
   166  	// via successful calls to WriteLeaderSettings.
   167  	LeaderSettings() (map[string]string, error)
   168  
   169  	// WriteLeaderSettings writes the supplied settings directly to state, or
   170  	// fails if the local unit is not the service's leader.
   171  	WriteLeaderSettings(map[string]string) error
   172  }
   173  
   174  // ContextMetrics is the part of a hook context related to metrics.
   175  type ContextMetrics interface {
   176  	// AddMetric records a metric to return after hook execution.
   177  	AddMetric(string, string, time.Time) error
   178  }
   179  
   180  // ContextStorage is the part of a hook context related to storage
   181  // resources associated with the unit.
   182  type ContextStorage interface {
   183  	// StorageTags returns a list of tags for storage instances
   184  	// attached to the unit.
   185  	StorageTags() []names.StorageTag
   186  
   187  	// Storage returns the ContextStorageAttachment with the supplied
   188  	// tag if it was found, and whether it was found.
   189  	Storage(names.StorageTag) (ContextStorageAttachment, bool)
   190  
   191  	// HookStorage returns the storage attachment associated
   192  	// the executing hook if it was found, and whether it was found.
   193  	HookStorage() (ContextStorageAttachment, bool)
   194  
   195  	// AddUnitStorage saves storage constraints in the context.
   196  	AddUnitStorage(map[string]params.StorageConstraints)
   197  }
   198  
   199  // ContextRelations exposes the relations associated with the unit.
   200  type ContextRelations interface {
   201  	// Relation returns the relation with the supplied id if it was found, and
   202  	// whether it was found.
   203  	Relation(id int) (ContextRelation, bool)
   204  
   205  	// RelationIds returns the ids of all relations the executing unit is
   206  	// currently participating in.
   207  	RelationIds() []int
   208  }
   209  
   210  // ContextRelation expresses the capabilities of a hook with respect to a relation.
   211  type ContextRelation interface {
   212  
   213  	// Id returns an integer which uniquely identifies the relation.
   214  	Id() int
   215  
   216  	// Name returns the name the locally executing charm assigned to this relation.
   217  	Name() string
   218  
   219  	// FakeId returns a string of the form "relation-name:123", which uniquely
   220  	// identifies the relation to the hook. In reality, the identification
   221  	// of the relation is the integer following the colon, but the composed
   222  	// name is useful to humans observing it.
   223  	FakeId() string
   224  
   225  	// Settings allows read/write access to the local unit's settings in
   226  	// this relation.
   227  	Settings() (Settings, error)
   228  
   229  	// UnitNames returns a list of the remote units in the relation.
   230  	UnitNames() []string
   231  
   232  	// ReadSettings returns the settings of any remote unit in the relation.
   233  	ReadSettings(unit string) (params.Settings, error)
   234  }
   235  
   236  // ContextStorageAttachment expresses the capabilities of a hook with
   237  // respect to a storage attachment.
   238  type ContextStorageAttachment interface {
   239  
   240  	// Tag returns a tag which uniquely identifies the storage attachment
   241  	// in the context of the unit.
   242  	Tag() names.StorageTag
   243  
   244  	// Kind returns the kind of the storage.
   245  	Kind() storage.StorageKind
   246  
   247  	// Location returns the location of the storage: the mount point for
   248  	// filesystem-kind stores, and the device path for block-kind stores.
   249  	Location() string
   250  }
   251  
   252  // Settings is implemented by types that manipulate unit settings.
   253  type Settings interface {
   254  	Map() params.Settings
   255  	Set(string, string)
   256  	Delete(string)
   257  }
   258  
   259  // newRelationIdValue returns a gnuflag.Value for convenient parsing of relation
   260  // ids in ctx.
   261  func newRelationIdValue(ctx Context, result *int) *relationIdValue {
   262  	v := &relationIdValue{result: result, ctx: ctx}
   263  	id := -1
   264  	if r, found := ctx.HookRelation(); found {
   265  		id = r.Id()
   266  		v.value = r.FakeId()
   267  	}
   268  	*result = id
   269  	return v
   270  }
   271  
   272  // relationIdValue implements gnuflag.Value for use in relation commands.
   273  type relationIdValue struct {
   274  	result *int
   275  	ctx    Context
   276  	value  string
   277  }
   278  
   279  // String returns the current value.
   280  func (v *relationIdValue) String() string {
   281  	return v.value
   282  }
   283  
   284  // Set interprets value as a relation id, if possible, and returns an error
   285  // if it is not known to the system. The parsed relation id will be written
   286  // to v.result.
   287  func (v *relationIdValue) Set(value string) error {
   288  	trim := value
   289  	if idx := strings.LastIndex(trim, ":"); idx != -1 {
   290  		trim = trim[idx+1:]
   291  	}
   292  	id, err := strconv.Atoi(trim)
   293  	if err != nil {
   294  		return fmt.Errorf("invalid relation id")
   295  	}
   296  	if _, found := v.ctx.Relation(id); !found {
   297  		return fmt.Errorf("unknown relation id")
   298  	}
   299  	*v.result = id
   300  	v.value = value
   301  	return nil
   302  }
   303  
   304  // newStorageIdValue returns a gnuflag.Value for convenient parsing of storage
   305  // ids in ctx.
   306  func newStorageIdValue(ctx Context, result *names.StorageTag) *storageIdValue {
   307  	v := &storageIdValue{result: result, ctx: ctx}
   308  	if s, found := ctx.HookStorage(); found {
   309  		*v.result = s.Tag()
   310  	}
   311  	return v
   312  }
   313  
   314  // storageIdValue implements gnuflag.Value for use in storage commands.
   315  type storageIdValue struct {
   316  	result *names.StorageTag
   317  	ctx    Context
   318  }
   319  
   320  // String returns the current value.
   321  func (v *storageIdValue) String() string {
   322  	if *v.result == (names.StorageTag{}) {
   323  		return ""
   324  	}
   325  	return v.result.Id()
   326  }
   327  
   328  // Set interprets value as a storage id, if possible, and returns an error
   329  // if it is not known to the system. The parsed storage id will be written
   330  // to v.result.
   331  func (v *storageIdValue) Set(value string) error {
   332  	if !names.IsValidStorage(value) {
   333  		return errors.Errorf("invalid storage ID %q", value)
   334  	}
   335  	tag := names.NewStorageTag(value)
   336  	if _, found := v.ctx.Storage(tag); !found {
   337  		return fmt.Errorf("unknown storage ID")
   338  	}
   339  	*v.result = tag
   340  	return nil
   341  }