github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/state/status.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"labix.org/v2/mgo"
    11  	"labix.org/v2/mgo/bson"
    12  	"labix.org/v2/mgo/txn"
    13  
    14  	"github.com/juju/juju/state/api/params"
    15  )
    16  
    17  // statusDoc represents a entity status in Mongodb.  The implicit
    18  // _id field is explicitly set to the global key of the associated
    19  // entity in the document's creation transaction, but omitted to allow
    20  // direct use of the document in both create and update transactions.
    21  type statusDoc struct {
    22  	Status     params.Status
    23  	StatusInfo string
    24  	StatusData params.StatusData
    25  }
    26  
    27  // validateSet returns an error if the statusDoc does not represent a sane
    28  // SetStatus operation.
    29  func (doc statusDoc) validateSet(allowPending bool) error {
    30  	if !doc.Status.Valid() {
    31  		return fmt.Errorf("cannot set invalid status %q", doc.Status)
    32  	}
    33  	switch doc.Status {
    34  	case params.StatusPending:
    35  		if !allowPending {
    36  			return fmt.Errorf("cannot set status %q", doc.Status)
    37  		}
    38  	case params.StatusDown:
    39  		return fmt.Errorf("cannot set status %q", doc.Status)
    40  	case params.StatusError:
    41  		if doc.StatusInfo == "" {
    42  			return fmt.Errorf("cannot set status %q without info", doc.Status)
    43  		}
    44  	}
    45  	if doc.StatusData != nil && doc.Status != params.StatusError {
    46  		return fmt.Errorf("cannot set status data when status is %q", doc.Status)
    47  	}
    48  	return nil
    49  }
    50  
    51  // getStatus retrieves the status document associated with the given
    52  // globalKey and copies it to outStatusDoc, which needs to be created
    53  // by the caller before.
    54  func getStatus(st *State, globalKey string) (statusDoc, error) {
    55  	var doc statusDoc
    56  	err := st.statuses.FindId(globalKey).One(&doc)
    57  	if err == mgo.ErrNotFound {
    58  		return statusDoc{}, errors.NotFoundf("status")
    59  	}
    60  	if err != nil {
    61  		return statusDoc{}, fmt.Errorf("cannot get status %q: %v", globalKey, err)
    62  	}
    63  	return doc, nil
    64  }
    65  
    66  // createStatusOp returns the operation needed to create the given
    67  // status document associated with the given globalKey.
    68  func createStatusOp(st *State, globalKey string, doc statusDoc) txn.Op {
    69  	return txn.Op{
    70  		C:      st.statuses.Name,
    71  		Id:     globalKey,
    72  		Assert: txn.DocMissing,
    73  		Insert: doc,
    74  	}
    75  }
    76  
    77  // updateStatusOp returns the operations needed to update the given
    78  // status document associated with the given globalKey.
    79  func updateStatusOp(st *State, globalKey string, doc statusDoc) txn.Op {
    80  	return txn.Op{
    81  		C:      st.statuses.Name,
    82  		Id:     globalKey,
    83  		Assert: txn.DocExists,
    84  		Update: bson.D{{"$set", doc}},
    85  	}
    86  }
    87  
    88  // removeStatusOp returns the operation needed to remove the status
    89  // document associated with the given globalKey.
    90  func removeStatusOp(st *State, globalKey string) txn.Op {
    91  	return txn.Op{
    92  		C:      st.statuses.Name,
    93  		Id:     globalKey,
    94  		Remove: true,
    95  	}
    96  }