github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/state/multiwatcher/multiwatcher.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package multiwatcher
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"time"
    11  
    12  	"gopkg.in/juju/charm.v5"
    13  
    14  	"github.com/juju/juju/constraints"
    15  	"github.com/juju/juju/instance"
    16  	"github.com/juju/juju/network"
    17  )
    18  
    19  // Life describes the lifecycle state of an entity ("alive", "dying"
    20  // or "dead").
    21  type Life string
    22  
    23  // Status represents the status of an entity.
    24  // It could be a service, unit, machine or its agent.
    25  type Status string
    26  
    27  // EntityInfo is implemented by all entity Info types.
    28  type EntityInfo interface {
    29  	// EntityId returns an identifier that will uniquely
    30  	// identify the entity within its kind
    31  	EntityId() EntityId
    32  }
    33  
    34  type EntityId struct {
    35  	Kind string
    36  	Id   interface{}
    37  }
    38  
    39  // Delta holds details of a change to the environment.
    40  type Delta struct {
    41  	// If Removed is true, the entity has been removed;
    42  	// otherwise it has been created or changed.
    43  	Removed bool
    44  	// Entity holds data about the entity that has changed.
    45  	Entity EntityInfo
    46  }
    47  
    48  // MarshalJSON implements json.Marshaler.
    49  func (d *Delta) MarshalJSON() ([]byte, error) {
    50  	b, err := json.Marshal(d.Entity)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	var buf bytes.Buffer
    55  	buf.WriteByte('[')
    56  	c := "change"
    57  	if d.Removed {
    58  		c = "remove"
    59  	}
    60  	fmt.Fprintf(&buf, "%q,%q,", d.Entity.EntityId().Kind, c)
    61  	buf.Write(b)
    62  	buf.WriteByte(']')
    63  	return buf.Bytes(), nil
    64  }
    65  
    66  // UnmarshalJSON implements json.Unmarshaler.
    67  func (d *Delta) UnmarshalJSON(data []byte) error {
    68  	var elements []json.RawMessage
    69  	if err := json.Unmarshal(data, &elements); err != nil {
    70  		return err
    71  	}
    72  	if len(elements) != 3 {
    73  		return fmt.Errorf(
    74  			"Expected 3 elements in top-level of JSON but got %d",
    75  			len(elements))
    76  	}
    77  	var entityKind, operation string
    78  	if err := json.Unmarshal(elements[0], &entityKind); err != nil {
    79  		return err
    80  	}
    81  	if err := json.Unmarshal(elements[1], &operation); err != nil {
    82  		return err
    83  	}
    84  	if operation == "remove" {
    85  		d.Removed = true
    86  	} else if operation != "change" {
    87  		return fmt.Errorf("Unexpected operation %q", operation)
    88  	}
    89  	switch entityKind {
    90  	case "machine":
    91  		d.Entity = new(MachineInfo)
    92  	case "service":
    93  		d.Entity = new(ServiceInfo)
    94  	case "unit":
    95  		d.Entity = new(UnitInfo)
    96  	case "relation":
    97  		d.Entity = new(RelationInfo)
    98  	case "annotation":
    99  		d.Entity = new(AnnotationInfo)
   100  	case "block":
   101  		d.Entity = new(BlockInfo)
   102  	default:
   103  		return fmt.Errorf("Unexpected entity name %q", entityKind)
   104  	}
   105  	return json.Unmarshal(elements[2], &d.Entity)
   106  }
   107  
   108  // When remote units leave scope, their ids will be noted in the
   109  // Departed field, and no further events will be sent for those units.
   110  type RelationUnitsChange struct {
   111  	Changed  map[string]UnitSettings
   112  	Departed []string
   113  }
   114  
   115  // UnitSettings holds information about a service unit's settings
   116  // within a relation.
   117  type UnitSettings struct {
   118  	Version int64
   119  }
   120  
   121  // MachineInfo holds the information about a Machine
   122  // that is watched by StateMultiwatcher.
   123  type MachineInfo struct {
   124  	Id                       string `bson:"_id"`
   125  	InstanceId               string
   126  	Status                   Status
   127  	StatusInfo               string
   128  	StatusData               map[string]interface{}
   129  	Life                     Life
   130  	Series                   string
   131  	SupportedContainers      []instance.ContainerType
   132  	SupportedContainersKnown bool
   133  	HardwareCharacteristics  *instance.HardwareCharacteristics `json:",omitempty"`
   134  	Jobs                     []MachineJob
   135  	Addresses                []network.Address
   136  	HasVote                  bool
   137  	WantsVote                bool
   138  }
   139  
   140  func (i *MachineInfo) EntityId() EntityId {
   141  	return EntityId{
   142  		Kind: "machine",
   143  		Id:   i.Id,
   144  	}
   145  }
   146  
   147  type StatusInfo struct {
   148  	Err     error
   149  	Current Status
   150  	Message string
   151  	Since   *time.Time
   152  	Version string
   153  	Data    map[string]interface{}
   154  }
   155  
   156  type ServiceInfo struct {
   157  	Name        string `bson:"_id"`
   158  	Exposed     bool
   159  	CharmURL    string
   160  	OwnerTag    string
   161  	Life        Life
   162  	MinUnits    int
   163  	Constraints constraints.Value
   164  	Config      map[string]interface{}
   165  	Subordinate bool
   166  	Status      StatusInfo
   167  }
   168  
   169  func (i *ServiceInfo) EntityId() EntityId {
   170  	return EntityId{
   171  		Kind: "service",
   172  		Id:   i.Name,
   173  	}
   174  }
   175  
   176  type UnitInfo struct {
   177  	Name           string `bson:"_id"`
   178  	Service        string
   179  	Series         string
   180  	CharmURL       string
   181  	PublicAddress  string
   182  	PrivateAddress string
   183  	MachineId      string
   184  	Ports          []network.Port
   185  	PortRanges     []network.PortRange
   186  	Subordinate    bool
   187  	// The following 3 status values are deprecated.
   188  	Status     Status
   189  	StatusInfo string
   190  	StatusData map[string]interface{}
   191  	// Workload and agent state are modelled separately.
   192  	WorkloadStatus StatusInfo
   193  	AgentStatus    StatusInfo
   194  }
   195  
   196  func (i *UnitInfo) EntityId() EntityId {
   197  	return EntityId{
   198  		Kind: "unit",
   199  		Id:   i.Name,
   200  	}
   201  }
   202  
   203  type ActionInfo struct {
   204  	Id         string                 `bson:"_id"`
   205  	Receiver   string                 `bson:"receiver"`
   206  	Name       string                 `bson:"name"`
   207  	Parameters map[string]interface{} `bson:"parameters"`
   208  	Status     string                 `bson:"status"`
   209  	Message    string                 `bson:"message"`
   210  	Results    map[string]interface{} `bson:"results"`
   211  	Enqueued   time.Time              `bson:"enqueued"`
   212  	Started    time.Time              `bson:"started"`
   213  	Completed  time.Time              `bson:"completed"`
   214  }
   215  
   216  func (i *ActionInfo) EntityId() EntityId {
   217  	return EntityId{
   218  		Kind: "action",
   219  		Id:   i.Id,
   220  	}
   221  }
   222  
   223  type RelationInfo struct {
   224  	Key       string `bson:"_id"`
   225  	Id        int
   226  	Endpoints []Endpoint
   227  }
   228  
   229  func (i *RelationInfo) EntityId() EntityId {
   230  	return EntityId{
   231  		Kind: "relation",
   232  		Id:   i.Key,
   233  	}
   234  }
   235  
   236  type AnnotationInfo struct {
   237  	Tag         string
   238  	Annotations map[string]string
   239  }
   240  
   241  func (i *AnnotationInfo) EntityId() EntityId {
   242  	return EntityId{
   243  		Kind: "annotation",
   244  		Id:   i.Tag,
   245  	}
   246  }
   247  
   248  type Endpoint struct {
   249  	ServiceName string
   250  	Relation    charm.Relation
   251  }
   252  
   253  // MachineJob values define responsibilities that machines may be
   254  // expected to fulfil.
   255  type MachineJob string
   256  
   257  const (
   258  	JobHostUnits        MachineJob = "JobHostUnits"
   259  	JobManageEnviron    MachineJob = "JobManageEnviron"
   260  	JobManageNetworking MachineJob = "JobManageNetworking"
   261  
   262  	// Deprecated in 1.18
   263  	JobManageStateDeprecated MachineJob = "JobManageState"
   264  )
   265  
   266  // NeedsState returns true if the job requires a state connection.
   267  func (job MachineJob) NeedsState() bool {
   268  	return job == JobManageEnviron
   269  }
   270  
   271  // AnyJobNeedsState returns true if any of the provided jobs
   272  // require a state connection.
   273  func AnyJobNeedsState(jobs ...MachineJob) bool {
   274  	for _, j := range jobs {
   275  		if j.NeedsState() {
   276  			return true
   277  		}
   278  	}
   279  	return false
   280  }
   281  
   282  // BlockInfo holds the information about blocks
   283  // in this environment that are watched.
   284  type BlockInfo struct {
   285  	Id      string    `bson:"_id"`
   286  	Type    BlockType `bson:"type"`
   287  	Message string    `bson:"message,omitempty"`
   288  	Tag     string    `bson:"tag"`
   289  }
   290  
   291  // EntityId returns block id.
   292  func (i *BlockInfo) EntityId() EntityId {
   293  	return EntityId{
   294  		Kind: "block",
   295  		Id:   i.Id,
   296  	}
   297  }
   298  
   299  // BlockType values define environment block type.
   300  type BlockType string
   301  
   302  const (
   303  	// BlockDestroy type identifies destroy blocks.
   304  	BlockDestroy BlockType = "BlockDestroy"
   305  
   306  	// BlockRemove type identifies remove blocks.
   307  	BlockRemove BlockType = "BlockRemove"
   308  
   309  	// BlockChange type identifies change blocks.
   310  	BlockChange BlockType = "BlockChange"
   311  )