github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/state/payloads.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	"github.com/juju/juju/payload"
    10  )
    11  
    12  // TODO(ericsnow) Track juju-level status in the status collection.
    13  
    14  // EnvPayloads exposes high-level interaction with all payloads
    15  // in an model.
    16  type EnvPayloads interface {
    17  	// ListAll builds the list of registered payloads in the env and returns it.
    18  	ListAll() ([]payload.FullPayloadInfo, error)
    19  }
    20  
    21  // UnitPayloads exposes high-level interaction with payloads for a unit.
    22  type UnitPayloads interface {
    23  	// Track tracks a payload in state. If a payload is
    24  	// already being tracked for the same (unit, payload name, plugin ID)
    25  	// then the request will fail. The unit must also be "alive".
    26  	Track(payload payload.Payload) error
    27  	// SetStatus sets the status of a payload. Only some fields
    28  	// must be set on the provided info: Name, Status, Details.ID, and
    29  	// Details.Status. If the payload is not in state then the request
    30  	// will fail.
    31  	SetStatus(docID, status string) error
    32  	// List builds the list of payloads registered for
    33  	// the given unit and IDs. If no IDs are provided then all
    34  	// registered payloads for the unit are returned. In the case that
    35  	// IDs are provided, any that are not in state are ignored and only
    36  	// the found ones are returned. It is up to the caller to
    37  	// extrapolate the list of missing IDs.
    38  	List(ids ...string) ([]payload.Result, error)
    39  	// LookUpReturns the Juju ID for the corresponding payload.
    40  	LookUp(name, rawID string) (string, error)
    41  	// Untrack removes the identified payload from state. If the
    42  	// given ID is not in state then the request will fail.
    43  	Untrack(id string) error
    44  }
    45  
    46  // TODO(ericsnow) Use a more generic component registration mechanism?
    47  
    48  // PayloadsEnvPersistence provides all the information needed to produce
    49  // a new EnvPayloads value.
    50  type PayloadsEnvPersistence interface {
    51  	Persistence
    52  
    53  	// TODO(ericsnow) Drop the machine-related API and provide UnitTags()?
    54  
    55  	// Machines builds the list of the names that identify
    56  	// all machines in State.
    57  	Machines() ([]string, error)
    58  
    59  	// Machines builds the list of names that identify all units
    60  	// for a given machine.
    61  	MachineUnits(machineName string) ([]string, error)
    62  }
    63  
    64  type newEnvPayloadsFunc func(PayloadsEnvPersistence) (EnvPayloads, error)
    65  type newUnitPayloadsFunc func(persist Persistence, unit, machine string) (UnitPayloads, error)
    66  
    67  // TODO(ericsnow) Merge the 2 vars
    68  var (
    69  	newEnvPayloads  newEnvPayloadsFunc
    70  	newUnitPayloads newUnitPayloadsFunc
    71  )
    72  
    73  // SetPayloadComponent registers the functions that provide the state
    74  // functionality related to payloads.
    75  func SetPayloadsComponent(epFunc newEnvPayloadsFunc, upFunc newUnitPayloadsFunc) {
    76  	newEnvPayloads = epFunc
    77  	newUnitPayloads = upFunc
    78  }
    79  
    80  // EnvPayloads exposes interaction with payloads in state.
    81  func (st *State) EnvPayloads() (EnvPayloads, error) {
    82  	if newEnvPayloads == nil {
    83  		return nil, errors.Errorf("payloads not supported")
    84  	}
    85  
    86  	persist := &payloadsEnvPersistence{
    87  		Persistence: st.newPersistence(),
    88  		st:          st,
    89  	}
    90  	envPayloads, err := newEnvPayloads(persist)
    91  	if err != nil {
    92  		return nil, errors.Trace(err)
    93  	}
    94  
    95  	return envPayloads, nil
    96  }
    97  
    98  // UnitPayloads exposes interaction with payloads in state
    99  // for a the given unit.
   100  func (st *State) UnitPayloads(unit *Unit) (UnitPayloads, error) {
   101  	if newUnitPayloads == nil {
   102  		return nil, errors.Errorf("payloads not supported")
   103  	}
   104  
   105  	machineID, err := unit.AssignedMachineId()
   106  	if err != nil {
   107  		return nil, errors.Trace(err)
   108  	}
   109  	unitID := unit.UnitTag().Id()
   110  
   111  	persist := st.newPersistence()
   112  	unitPayloads, err := newUnitPayloads(persist, unitID, machineID)
   113  	if err != nil {
   114  		return nil, errors.Trace(err)
   115  	}
   116  
   117  	return unitPayloads, nil
   118  }
   119  
   120  type payloadsEnvPersistence struct {
   121  	Persistence
   122  	st *State
   123  }
   124  
   125  // Machines implements PayloadsEnvPersistence.
   126  func (ep *payloadsEnvPersistence) Machines() ([]string, error) {
   127  	ms, err := ep.st.AllMachines()
   128  	if err != nil {
   129  		return nil, errors.Trace(err)
   130  	}
   131  	var names []string
   132  	for _, m := range ms {
   133  		names = append(names, m.Id())
   134  	}
   135  	return names, nil
   136  }
   137  
   138  // MachineUnits implements PayloadsEnvPersistence.
   139  func (ep *payloadsEnvPersistence) MachineUnits(machine string) ([]string, error) {
   140  	us, err := ep.st.UnitsFor(machine)
   141  	if err != nil {
   142  		return nil, errors.Trace(err)
   143  	}
   144  	var names []string
   145  	for _, u := range us {
   146  		names = append(names, u.UnitTag().Id())
   147  	}
   148  	return names, nil
   149  }