github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/undertaker/undertaker.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package undertaker
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/apiserver/params"
    12  	"github.com/juju/juju/status"
    13  	"github.com/juju/juju/watcher"
    14  )
    15  
    16  // NewWatcherFunc exists to let us test Watch properly.
    17  type NewWatcherFunc func(base.APICaller, params.NotifyWatchResult) watcher.NotifyWatcher
    18  
    19  // Client provides access to the undertaker API
    20  type Client struct {
    21  	modelTag   names.ModelTag
    22  	caller     base.FacadeCaller
    23  	newWatcher NewWatcherFunc
    24  }
    25  
    26  // NewClient creates a new client for accessing the undertaker API.
    27  func NewClient(caller base.APICaller, newWatcher NewWatcherFunc) (*Client, error) {
    28  	modelTag, ok := caller.ModelTag()
    29  	if !ok {
    30  		return nil, errors.New("undertaker client is not appropriate for controller-only API")
    31  	}
    32  	return &Client{
    33  		modelTag:   modelTag,
    34  		caller:     base.NewFacadeCaller(caller, "Undertaker"),
    35  		newWatcher: newWatcher,
    36  	}, nil
    37  }
    38  
    39  // ModelInfo returns information on the model needed by the undertaker worker.
    40  func (c *Client) ModelInfo() (params.UndertakerModelInfoResult, error) {
    41  	result := params.UndertakerModelInfoResult{}
    42  	err := c.entityFacadeCall("ModelInfo", &result)
    43  	return result, errors.Trace(err)
    44  }
    45  
    46  // ProcessDyingModel checks if a dying model has any machines or services.
    47  // If there are none, the model's life is changed from dying to dead.
    48  func (c *Client) ProcessDyingModel() error {
    49  	return c.entityFacadeCall("ProcessDyingModel", nil)
    50  }
    51  
    52  // RemoveModel removes any records of this model from Juju.
    53  func (c *Client) RemoveModel() error {
    54  	return c.entityFacadeCall("RemoveModel", nil)
    55  }
    56  
    57  // SetStatus sets the status of the model.
    58  func (c *Client) SetStatus(status status.Status, message string, data map[string]interface{}) error {
    59  	args := params.SetStatus{
    60  		Entities: []params.EntityStatusArgs{
    61  			{c.modelTag.String(), status.String(), message, data},
    62  		},
    63  	}
    64  	var results params.ErrorResults
    65  	if err := c.caller.FacadeCall("SetStatus", args, &results); err != nil {
    66  		return errors.Trace(err)
    67  	}
    68  	if len(results.Results) != 1 {
    69  		return errors.Errorf("expected 1 result, got %d", len(results.Results))
    70  	}
    71  	if results.Results[0].Error != nil {
    72  		return errors.Trace(results.Results[0].Error)
    73  	}
    74  	return nil
    75  }
    76  
    77  func (c *Client) entityFacadeCall(name string, results interface{}) error {
    78  	args := params.Entities{
    79  		Entities: []params.Entity{{c.modelTag.String()}},
    80  	}
    81  	return c.caller.FacadeCall(name, args, results)
    82  }
    83  
    84  // WatchModelResources starts a watcher for changes to the model's
    85  // machines and services.
    86  func (c *Client) WatchModelResources() (watcher.NotifyWatcher, error) {
    87  	var results params.NotifyWatchResults
    88  	err := c.entityFacadeCall("WatchModelResources", &results)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	if len(results.Results) != 1 {
    94  		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
    95  	}
    96  	result := results.Results[0]
    97  	if result.Error != nil {
    98  		return nil, result.Error
    99  	}
   100  	w := c.newWatcher(c.caller.RawAPICaller(), result)
   101  	return w, nil
   102  }