github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/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  	"gopkg.in/juju/charm.v6"
    14  	"gopkg.in/juju/names.v2"
    15  
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/core/application"
    18  	"github.com/juju/juju/core/network"
    19  	"github.com/juju/juju/core/relation"
    20  	"github.com/juju/juju/storage"
    21  )
    22  
    23  // Context is the interface that all hook helper commands
    24  // depend on to interact with the rest of the system.
    25  type Context interface {
    26  	HookContext
    27  	relationHookContext
    28  	actionHookContext
    29  }
    30  
    31  // HookContext represents the information and functionality that is
    32  // common to all charm hooks.
    33  type HookContext interface {
    34  	ContextUnit
    35  	ContextStatus
    36  	ContextInstance
    37  	ContextNetworking
    38  	ContextLeadership
    39  	ContextMetrics
    40  	ContextStorage
    41  	ContextComponents
    42  	ContextRelations
    43  	ContextVersion
    44  }
    45  
    46  // UnitHookContext is the context for a unit hook.
    47  type UnitHookContext interface {
    48  	HookContext
    49  }
    50  
    51  // RelationHookContext is the context for a relation hook.
    52  type RelationHookContext interface {
    53  	HookContext
    54  	relationHookContext
    55  }
    56  
    57  type relationHookContext interface {
    58  	// HookRelation returns the ContextRelation associated with the executing
    59  	// hook if it was found, or an error if it was not found (or is not available).
    60  	HookRelation() (ContextRelation, error)
    61  
    62  	// RemoteUnitName returns the name of the remote unit the hook execution
    63  	// is associated with if it was found, and an error if it was not found or is not
    64  	// available.
    65  	RemoteUnitName() (string, error)
    66  }
    67  
    68  // ActionHookContext is the context for an action hook.
    69  type ActionHookContext interface {
    70  	HookContext
    71  	actionHookContext
    72  }
    73  
    74  type actionHookContext interface {
    75  	// ActionParams returns the map of params passed with an Action.
    76  	ActionParams() (map[string]interface{}, error)
    77  
    78  	// UpdateActionResults inserts new values for use with action-set.
    79  	// The results struct will be delivered to the controller upon
    80  	// completion of the Action.
    81  	UpdateActionResults(keys []string, value string) error
    82  
    83  	// SetActionMessage sets a message for the Action.
    84  	SetActionMessage(string) error
    85  
    86  	// SetActionFailed sets a failure state for the Action.
    87  	SetActionFailed() error
    88  }
    89  
    90  // ContextUnit is the part of a hook context related to the unit.
    91  type ContextUnit interface {
    92  	// UnitName returns the executing unit's name.
    93  	UnitName() string
    94  
    95  	// Config returns the current application configuration of the executing unit.
    96  	ConfigSettings() (charm.Settings, error)
    97  
    98  	// GoalState returns the goal state for the current unit.
    99  	GoalState() (*application.GoalState, error)
   100  
   101  	// SetPodSpec updates the yaml spec used to create a pod.
   102  	SetPodSpec(specYaml string) error
   103  
   104  	// CloudSpec returns the unit's cloud specification
   105  	CloudSpec() (*params.CloudSpec, 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  	// ApplicationStatus returns the executing unit's application status
   117  	// (including all units).
   118  	ApplicationStatus() (ApplicationStatusInfo, error)
   119  
   120  	// SetApplicationStatus updates the status for the unit's application.
   121  	SetApplicationStatus(StatusInfo) error
   122  }
   123  
   124  // RebootPriority is the type used for reboot requests.
   125  type RebootPriority int
   126  
   127  // ContextInstance is the part of a hook context related to the unit's instance.
   128  type ContextInstance interface {
   129  	// AvailabilityZone returns the executing unit's availability zone or an error
   130  	// if it was not found (or is not available).
   131  	AvailabilityZone() (string, error)
   132  
   133  	// RequestReboot will set the reboot flag to true on the machine agent
   134  	RequestReboot(prio RebootPriority) error
   135  }
   136  
   137  // ContextNetworking is the part of a hook context related to network
   138  // interface of the unit's instance.
   139  type ContextNetworking interface {
   140  	// PublicAddress returns the executing unit's public address or an
   141  	// error if it is not available.
   142  	PublicAddress() (string, error)
   143  
   144  	// PrivateAddress returns the executing unit's private address or an
   145  	// error if it is not available.
   146  	PrivateAddress() (string, error)
   147  
   148  	// OpenPorts marks the supplied port range for opening when the
   149  	// executing unit's application is exposed.
   150  	OpenPorts(protocol string, fromPort, toPort int) error
   151  
   152  	// ClosePorts ensures the supplied port range is closed even when
   153  	// the executing unit's application is exposed (unless it is opened
   154  	// separately by a co- located unit).
   155  	ClosePorts(protocol string, fromPort, toPort int) error
   156  
   157  	// OpenedPorts returns all port ranges currently opened by this
   158  	// unit on its assigned machine. The result is sorted first by
   159  	// protocol, then by number.
   160  	OpenedPorts() []network.PortRange
   161  
   162  	// NetworkInfo returns the network info for the given bindings on the given relation.
   163  	NetworkInfo(bindingNames []string, relationId int) (map[string]params.NetworkInfoResult, error)
   164  }
   165  
   166  // ContextLeadership is the part of a hook context related to the
   167  // unit leadership.
   168  type ContextLeadership interface {
   169  	// IsLeader returns true if the local unit is known to be leader for at
   170  	// least the next 30s.
   171  	IsLeader() (bool, error)
   172  
   173  	// LeaderSettings returns the current leader settings. Once leader settings
   174  	// have been read in a given context, they will not be updated other than
   175  	// via successful calls to WriteLeaderSettings.
   176  	LeaderSettings() (map[string]string, error)
   177  
   178  	// WriteLeaderSettings writes the supplied settings directly to state, or
   179  	// fails if the local unit is not the application's leader.
   180  	WriteLeaderSettings(map[string]string) error
   181  }
   182  
   183  // ContextMetrics is the part of a hook context related to metrics.
   184  type ContextMetrics interface {
   185  	// AddMetric records a metric to return after hook execution.
   186  	AddMetric(string, string, time.Time) error
   187  	// AddMetricLabels records a metric with tags to return after hook execution.
   188  	AddMetricLabels(string, string, time.Time, map[string]string) error
   189  }
   190  
   191  // ContextStorage is the part of a hook context related to storage
   192  // resources associated with the unit.
   193  type ContextStorage interface {
   194  	// StorageTags returns a list of tags for storage instances
   195  	// attached to the unit or an error if they are not available.
   196  	StorageTags() ([]names.StorageTag, error)
   197  
   198  	// Storage returns the ContextStorageAttachment with the supplied
   199  	// tag if it was found, and an error if it was not found or is not
   200  	// available to the context.
   201  	Storage(names.StorageTag) (ContextStorageAttachment, error)
   202  
   203  	// HookStorage returns the storage attachment associated
   204  	// the executing hook if it was found, and an error if it
   205  	// was not found or is not available.
   206  	HookStorage() (ContextStorageAttachment, error)
   207  
   208  	// AddUnitStorage saves storage constraints in the context.
   209  	AddUnitStorage(map[string]params.StorageConstraints) error
   210  }
   211  
   212  // ContextComponents exposes modular Juju components as they relate to
   213  // the unit in the context of the hook.
   214  type ContextComponents interface {
   215  	// Component returns the ContextComponent with the supplied name if
   216  	// it was found.
   217  	Component(name string) (ContextComponent, error)
   218  }
   219  
   220  // ContextRelations exposes the relations associated with the unit.
   221  type ContextRelations interface {
   222  	// Relation returns the relation with the supplied id if it was found, and
   223  	// an error if it was not found or is not available.
   224  	Relation(id int) (ContextRelation, error)
   225  
   226  	// RelationIds returns the ids of all relations the executing unit is
   227  	// currently participating in or an error if they are not available.
   228  	RelationIds() ([]int, error)
   229  }
   230  
   231  // ContextComponent is a single modular Juju component as it relates to
   232  // the current unit and hook. Components should implement this interfaces
   233  // in a type-safe way. Ensuring checked type-conversions are preformed on
   234  // the result and value interfaces. You will use the runner.RegisterComponentFunc
   235  // to register a your components concrete ContextComponent implementation.
   236  //
   237  // See: process/context/context.go for an implementation example.
   238  //
   239  type ContextComponent interface {
   240  	// Flush pushes the component's data to Juju state.
   241  	// In the Flush implementation, call your components API.
   242  	Flush() error
   243  }
   244  
   245  // ContextRelation expresses the capabilities of a hook with respect to a relation.
   246  //go:generate mockgen -package jujuc -destination context_mock_test.go github.com/juju/juju/worker/uniter/runner/jujuc ContextRelation
   247  type ContextRelation interface {
   248  
   249  	// Id returns an integer which uniquely identifies the relation.
   250  	Id() int
   251  
   252  	// Name returns the name the locally executing charm assigned to this relation.
   253  	Name() string
   254  
   255  	// FakeId returns a string of the form "relation-name:123", which uniquely
   256  	// identifies the relation to the hook. In reality, the identification
   257  	// of the relation is the integer following the colon, but the composed
   258  	// name is useful to humans observing it.
   259  	FakeId() string
   260  
   261  	// Settings allows read/write access to the local unit's settings in
   262  	// this relation.
   263  	Settings() (Settings, error)
   264  
   265  	// UnitNames returns a list of the remote units in the relation.
   266  	UnitNames() []string
   267  
   268  	// ReadSettings returns the settings of any remote unit in the relation.
   269  	ReadSettings(unit string) (params.Settings, error)
   270  
   271  	// Suspended returns true if the relation is suspended.
   272  	Suspended() bool
   273  
   274  	// SetStatus sets the relation's status.
   275  	SetStatus(relation.Status) error
   276  }
   277  
   278  // ContextStorageAttachment expresses the capabilities of a hook with
   279  // respect to a storage attachment.
   280  type ContextStorageAttachment interface {
   281  
   282  	// Tag returns a tag which uniquely identifies the storage attachment
   283  	// in the context of the unit.
   284  	Tag() names.StorageTag
   285  
   286  	// Kind returns the kind of the storage.
   287  	Kind() storage.StorageKind
   288  
   289  	// Location returns the location of the storage: the mount point for
   290  	// filesystem-kind stores, and the device path for block-kind stores.
   291  	Location() string
   292  }
   293  
   294  // ContextVersion expresses the parts of a hook context related to
   295  // reporting workload versions.
   296  type ContextVersion interface {
   297  
   298  	// UnitWorkloadVersion returns the currently set workload version for
   299  	// the unit.
   300  	UnitWorkloadVersion() (string, error)
   301  
   302  	// SetUnitWorkloadVersion updates the workload version for the unit.
   303  	SetUnitWorkloadVersion(string) error
   304  }
   305  
   306  // Settings is implemented by types that manipulate unit settings.
   307  type Settings interface {
   308  	Map() params.Settings
   309  	Set(string, string)
   310  	Delete(string)
   311  }
   312  
   313  // NewRelationIdValue returns a gnuflag.Value for convenient parsing of relation
   314  // ids in ctx.
   315  func NewRelationIdValue(ctx Context, result *int) (*relationIdValue, error) {
   316  	v := &relationIdValue{result: result, ctx: ctx}
   317  	id := -1
   318  	if r, err := ctx.HookRelation(); err == nil {
   319  		id = r.Id()
   320  		v.value = r.FakeId()
   321  	} else if !errors.IsNotFound(err) {
   322  		return nil, errors.Trace(err)
   323  	}
   324  	*result = id
   325  	return v, nil
   326  }
   327  
   328  // relationIdValue implements gnuflag.Value for use in relation commands.
   329  type relationIdValue struct {
   330  	result *int
   331  	ctx    Context
   332  	value  string
   333  }
   334  
   335  // String returns the current value.
   336  func (v *relationIdValue) String() string {
   337  	return v.value
   338  }
   339  
   340  // Set interprets value as a relation id, if possible, and returns an error
   341  // if it is not known to the system. The parsed relation id will be written
   342  // to v.result.
   343  func (v *relationIdValue) Set(value string) error {
   344  	trim := value
   345  	if idx := strings.LastIndex(trim, ":"); idx != -1 {
   346  		trim = trim[idx+1:]
   347  	}
   348  	id, err := strconv.Atoi(trim)
   349  	if err != nil {
   350  		return fmt.Errorf("invalid relation id")
   351  	}
   352  	if _, err := v.ctx.Relation(id); err != nil {
   353  		return errors.Trace(err)
   354  	}
   355  	*v.result = id
   356  	v.value = value
   357  	return nil
   358  }