github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/api/uniter/application.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package uniter
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/errors"
    10  	"gopkg.in/juju/charm.v6-unstable"
    11  	"gopkg.in/juju/names.v2"
    12  
    13  	"github.com/juju/juju/api/common"
    14  	apiwatcher "github.com/juju/juju/api/watcher"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/status"
    17  	"github.com/juju/juju/watcher"
    18  )
    19  
    20  // This module implements a subset of the interface provided by
    21  // state.Application, as needed by the uniter API.
    22  
    23  // Application represents the state of an application.
    24  type Application struct {
    25  	st   *State
    26  	tag  names.ApplicationTag
    27  	life params.Life
    28  }
    29  
    30  // Tag returns the application's tag.
    31  func (s *Application) Tag() names.ApplicationTag {
    32  	return s.tag
    33  }
    34  
    35  // Name returns the application name.
    36  func (s *Application) Name() string {
    37  	return s.tag.Id()
    38  }
    39  
    40  // String returns the application as a string.
    41  func (s *Application) String() string {
    42  	return s.Name()
    43  }
    44  
    45  // Watch returns a watcher for observing changes to an application.
    46  func (s *Application) Watch() (watcher.NotifyWatcher, error) {
    47  	return common.Watch(s.st.facade, s.tag)
    48  }
    49  
    50  // WatchRelations returns a StringsWatcher that notifies of changes to
    51  // the lifecycles of relations involving s.
    52  func (s *Application) WatchRelations() (watcher.StringsWatcher, error) {
    53  	var results params.StringsWatchResults
    54  	args := params.Entities{
    55  		Entities: []params.Entity{{Tag: s.tag.String()}},
    56  	}
    57  	err := s.st.facade.FacadeCall("WatchApplicationRelations", args, &results)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	if len(results.Results) != 1 {
    62  		return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
    63  	}
    64  	result := results.Results[0]
    65  	if result.Error != nil {
    66  		return nil, result.Error
    67  	}
    68  	w := apiwatcher.NewStringsWatcher(s.st.facade.RawAPICaller(), result)
    69  	return w, nil
    70  }
    71  
    72  // Life returns the application's current life state.
    73  func (s *Application) Life() params.Life {
    74  	return s.life
    75  }
    76  
    77  // Refresh refreshes the contents of the Service from the underlying
    78  // state.
    79  func (s *Application) Refresh() error {
    80  	life, err := s.st.life(s.tag)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	s.life = life
    85  	return nil
    86  }
    87  
    88  // CharmModifiedVersion increments every time the charm, or any part of it, is
    89  // changed in some way.
    90  func (s *Application) CharmModifiedVersion() (int, error) {
    91  	var results params.IntResults
    92  	args := params.Entities{
    93  		Entities: []params.Entity{{Tag: s.tag.String()}},
    94  	}
    95  	err := s.st.facade.FacadeCall("CharmModifiedVersion", args, &results)
    96  	if err != nil {
    97  		return -1, err
    98  	}
    99  
   100  	if len(results.Results) != 1 {
   101  		return -1, fmt.Errorf("expected 1 result, got %d", len(results.Results))
   102  	}
   103  	result := results.Results[0]
   104  	if result.Error != nil {
   105  		return -1, result.Error
   106  	}
   107  
   108  	return result.Result, nil
   109  }
   110  
   111  // CharmURL returns the service's charm URL, and whether units should
   112  // upgrade to the charm with that URL even if they are in an error
   113  // state (force flag).
   114  //
   115  // NOTE: This differs from state.Service.CharmURL() by returning
   116  // an error instead as well, because it needs to make an API call.
   117  func (s *Application) CharmURL() (*charm.URL, bool, error) {
   118  	var results params.StringBoolResults
   119  	args := params.Entities{
   120  		Entities: []params.Entity{{Tag: s.tag.String()}},
   121  	}
   122  	err := s.st.facade.FacadeCall("CharmURL", args, &results)
   123  	if err != nil {
   124  		return nil, false, err
   125  	}
   126  	if len(results.Results) != 1 {
   127  		return nil, false, fmt.Errorf("expected 1 result, got %d", len(results.Results))
   128  	}
   129  	result := results.Results[0]
   130  	if result.Error != nil {
   131  		return nil, false, result.Error
   132  	}
   133  	if result.Result != "" {
   134  		curl, err := charm.ParseURL(result.Result)
   135  		if err != nil {
   136  			return nil, false, err
   137  		}
   138  		return curl, result.Ok, nil
   139  	}
   140  	return nil, false, fmt.Errorf("%q has no charm url set", s.tag)
   141  }
   142  
   143  // SetStatus sets the status of the service if the passed unitName,
   144  // corresponding to the calling unit, is of the leader.
   145  func (s *Application) SetStatus(unitName string, serviceStatus status.Status, info string, data map[string]interface{}) error {
   146  	tag := names.NewUnitTag(unitName)
   147  	var result params.ErrorResults
   148  	args := params.SetStatus{
   149  		Entities: []params.EntityStatusArgs{
   150  			{
   151  				Tag:    tag.String(),
   152  				Status: serviceStatus.String(),
   153  				Info:   info,
   154  				Data:   data,
   155  			},
   156  		},
   157  	}
   158  	err := s.st.facade.FacadeCall("SetApplicationStatus", args, &result)
   159  	if err != nil {
   160  		return errors.Trace(err)
   161  	}
   162  	return result.OneError()
   163  }
   164  
   165  // Status returns the status of the service if the passed unitName,
   166  // corresponding to the calling unit, is of the leader.
   167  func (s *Application) Status(unitName string) (params.ApplicationStatusResult, error) {
   168  	tag := names.NewUnitTag(unitName)
   169  	var results params.ApplicationStatusResults
   170  	args := params.Entities{
   171  		Entities: []params.Entity{
   172  			{
   173  				Tag: tag.String(),
   174  			},
   175  		},
   176  	}
   177  	err := s.st.facade.FacadeCall("ApplicationStatus", args, &results)
   178  	if err != nil {
   179  		return params.ApplicationStatusResult{}, errors.Trace(err)
   180  	}
   181  	result := results.Results[0]
   182  	if result.Error != nil {
   183  		return params.ApplicationStatusResult{}, result.Error
   184  	}
   185  	return result, nil
   186  }
   187  
   188  // WatchLeadershipSettings returns a watcher which can be used to wait
   189  // for leadership settings changes to be made for the application.
   190  func (s *Application) WatchLeadershipSettings() (watcher.NotifyWatcher, error) {
   191  	return s.st.LeadershipSettings.WatchLeadershipSettings(s.tag.Id())
   192  }