github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/crossmodel/state.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package crossmodel
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/core/crossmodel"
    11  	"github.com/juju/juju/state"
    12  )
    13  
    14  // StatePool provides the subset of a state pool.
    15  type StatePool interface {
    16  	// Get returns a State for a given model from the pool.
    17  	Get(modelUUID string) (Backend, func(), error)
    18  }
    19  
    20  type statePoolShim struct {
    21  	*state.StatePool
    22  }
    23  
    24  func (p *statePoolShim) Get(modelUUID string) (Backend, func(), error) {
    25  	st, err := p.StatePool.Get(modelUUID)
    26  	if err != nil {
    27  		return nil, func() {}, err
    28  	}
    29  	closer := func() {
    30  		st.Release()
    31  	}
    32  	model, err := st.Model()
    33  	if err != nil {
    34  		closer()
    35  		return nil, nil, err
    36  	}
    37  	return stateShim{st.State, model}, closer, err
    38  }
    39  
    40  func GetStatePool(pool *state.StatePool) StatePool {
    41  	return &statePoolShim{pool}
    42  }
    43  
    44  // GetBackend wraps a State to provide a Backend interface implementation.
    45  func GetBackend(st *state.State) stateShim {
    46  	model, err := st.Model()
    47  	if err != nil {
    48  		logger.Errorf("called GetBackend on a State with no Model.")
    49  		return stateShim{}
    50  	}
    51  	return stateShim{State: st, Model: model}
    52  }
    53  
    54  // TODO - CAAS(ericclaudejones): This should contain state alone, model will be
    55  // removed once all relevant methods are moved from state to model.
    56  type stateShim struct {
    57  	*state.State
    58  	*state.Model
    59  }
    60  
    61  func (st stateShim) KeyRelation(key string) (Relation, error) {
    62  	r, err := st.State.KeyRelation(key)
    63  	if err != nil {
    64  		return nil, errors.Trace(err)
    65  	}
    66  	return relationShim{r, st.State}, nil
    67  }
    68  
    69  // ControllerTag returns the tag of the controller in which we are operating.
    70  // This is a temporary transitional step. Eventually code using
    71  // crossmodel.Backend will only need to be passed a state.Model.
    72  func (st stateShim) ControllerTag() names.ControllerTag {
    73  	return st.Model.ControllerTag()
    74  }
    75  
    76  // ControllerTag returns the tag of the controller in which we are operating.
    77  // This is a temporary transitional step.
    78  func (st stateShim) ModelTag() names.ModelTag {
    79  	return st.Model.ModelTag()
    80  }
    81  
    82  type applicationShim struct {
    83  	*state.Application
    84  }
    85  
    86  func (a applicationShim) Charm() (ch Charm, force bool, err error) {
    87  	return a.Application.Charm()
    88  }
    89  
    90  func (st stateShim) Application(name string) (Application, error) {
    91  	a, err := st.State.Application(name)
    92  	if err != nil {
    93  		return nil, errors.Trace(err)
    94  	}
    95  	return applicationShim{a}, nil
    96  }
    97  
    98  type remoteApplicationShim struct {
    99  	*state.RemoteApplication
   100  }
   101  
   102  func (st stateShim) RemoteApplication(name string) (RemoteApplication, error) {
   103  	a, err := st.State.RemoteApplication(name)
   104  	if err != nil {
   105  		return nil, errors.Trace(err)
   106  	}
   107  	return &remoteApplicationShim{a}, nil
   108  }
   109  
   110  func (st stateShim) AddRelation(eps ...state.Endpoint) (Relation, error) {
   111  	r, err := st.State.AddRelation(eps...)
   112  	if err != nil {
   113  		return nil, errors.Trace(err)
   114  	}
   115  	return relationShim{r, st.State}, nil
   116  }
   117  
   118  func (st stateShim) EndpointsRelation(eps ...state.Endpoint) (Relation, error) {
   119  	r, err := st.State.EndpointsRelation(eps...)
   120  	if err != nil {
   121  		return nil, errors.Trace(err)
   122  	}
   123  	return relationShim{r, st.State}, nil
   124  }
   125  
   126  func (st stateShim) AddRemoteApplication(args state.AddRemoteApplicationParams) (RemoteApplication, error) {
   127  	a, err := st.State.AddRemoteApplication(args)
   128  	if err != nil {
   129  		return nil, errors.Trace(err)
   130  	}
   131  	return remoteApplicationShim{a}, nil
   132  }
   133  
   134  func (st stateShim) GetRemoteEntity(token string) (names.Tag, error) {
   135  	r := st.State.RemoteEntities()
   136  	return r.GetRemoteEntity(token)
   137  }
   138  
   139  func (st stateShim) GetToken(entity names.Tag) (string, error) {
   140  	r := st.State.RemoteEntities()
   141  	return r.GetToken(entity)
   142  }
   143  
   144  func (st stateShim) ExportLocalEntity(entity names.Tag) (string, error) {
   145  	r := st.State.RemoteEntities()
   146  	return r.ExportLocalEntity(entity)
   147  }
   148  
   149  func (st stateShim) ImportRemoteEntity(entity names.Tag, token string) error {
   150  	r := st.State.RemoteEntities()
   151  	return r.ImportRemoteEntity(entity, token)
   152  }
   153  
   154  func (st stateShim) ApplicationOfferForUUID(offerUUID string) (*crossmodel.ApplicationOffer, error) {
   155  	return state.NewApplicationOffers(st.State).ApplicationOfferForUUID(offerUUID)
   156  }
   157  
   158  func (s stateShim) SaveIngressNetworks(relationKey string, cidrs []string) (state.RelationNetworks, error) {
   159  	api := state.NewRelationIngressNetworks(s.State)
   160  	return api.Save(relationKey, false, cidrs)
   161  }
   162  
   163  func (s stateShim) IngressNetworks(relationKey string) (state.RelationNetworks, error) {
   164  	api := state.NewRelationIngressNetworks(s.State)
   165  	return api.Networks(relationKey)
   166  }
   167  
   168  func (s stateShim) FirewallRule(service state.WellKnownServiceType) (*state.FirewallRule, error) {
   169  	api := state.NewFirewallRules(s.State)
   170  	return api.Rule(service)
   171  }
   172  
   173  type relationShim struct {
   174  	*state.Relation
   175  	st *state.State
   176  }
   177  
   178  func (r relationShim) RemoteUnit(unitId string) (RelationUnit, error) {
   179  	ru, err := r.Relation.RemoteUnit(unitId)
   180  	if err != nil {
   181  		return nil, errors.Trace(err)
   182  	}
   183  	return relationUnitShim{ru}, nil
   184  }
   185  
   186  func (r relationShim) AllRemoteUnits(appName string) ([]RelationUnit, error) {
   187  	all, err := r.Relation.AllRemoteUnits(appName)
   188  	if err != nil {
   189  		return nil, errors.Trace(err)
   190  	}
   191  	result := make([]RelationUnit, len(all))
   192  	for i, ru := range all {
   193  		result[i] = relationUnitShim{ru}
   194  	}
   195  	return result, nil
   196  }
   197  
   198  func (r relationShim) Unit(unitId string) (RelationUnit, error) {
   199  	unit, err := r.st.Unit(unitId)
   200  	if err != nil {
   201  		return nil, errors.Trace(err)
   202  	}
   203  	ru, err := r.Relation.Unit(unit)
   204  	if err != nil {
   205  		return nil, errors.Trace(err)
   206  	}
   207  	return relationUnitShim{ru}, nil
   208  }
   209  
   210  type relationUnitShim struct {
   211  	*state.RelationUnit
   212  }
   213  
   214  func (r relationUnitShim) Settings() (map[string]interface{}, error) {
   215  	settings, err := r.RelationUnit.Settings()
   216  	if err != nil {
   217  		return nil, errors.Trace(err)
   218  	}
   219  	return settings.Map(), nil
   220  }
   221  
   222  func (r relationUnitShim) ReplaceSettings(s map[string]interface{}) error {
   223  	settings, err := r.RelationUnit.Settings()
   224  	if err != nil {
   225  		return errors.Trace(err)
   226  	}
   227  	settings.Update(s)
   228  	for _, key := range settings.Keys() {
   229  		if _, ok := s[key]; ok {
   230  			continue
   231  		}
   232  		settings.Delete(key)
   233  	}
   234  	_, err = settings.Write()
   235  	return errors.Trace(err)
   236  }