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 }