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