github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/client/application/backend.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package application 5 6 import ( 7 "github.com/juju/schema" 8 "gopkg.in/juju/charm.v6" 9 csparams "gopkg.in/juju/charmrepo.v3/csclient/params" 10 "gopkg.in/juju/environschema.v1" 11 "gopkg.in/juju/names.v2" 12 13 "github.com/juju/juju/apiserver/common/storagecommon" 14 "github.com/juju/juju/core/application" 15 "github.com/juju/juju/core/constraints" 16 "github.com/juju/juju/core/crossmodel" 17 "github.com/juju/juju/core/instance" 18 "github.com/juju/juju/core/status" 19 "github.com/juju/juju/network" 20 "github.com/juju/juju/state" 21 ) 22 23 // Backend defines the state functionality required by the application 24 // facade. For details on the methods, see the methods on state.State 25 // with the same names. 26 type Backend interface { 27 AllModelUUIDs() ([]string, error) 28 Application(string) (Application, error) 29 ApplyOperation(state.ModelOperation) error 30 AddApplication(state.AddApplicationArgs) (Application, error) 31 RemoteApplication(string) (RemoteApplication, error) 32 AddRemoteApplication(state.AddRemoteApplicationParams) (RemoteApplication, error) 33 AddRelation(...state.Endpoint) (Relation, error) 34 Charm(*charm.URL) (Charm, error) 35 EndpointsRelation(...state.Endpoint) (Relation, error) 36 Relation(int) (Relation, error) 37 InferEndpoints(...string) ([]state.Endpoint, error) 38 Machine(string) (Machine, error) 39 Unit(string) (Unit, error) 40 UnitsInError() ([]Unit, error) 41 SaveController(info crossmodel.ControllerInfo, modelUUID string) (ExternalController, error) 42 ControllerTag() names.ControllerTag 43 Resources() (Resources, error) 44 OfferConnectionForRelation(string) (OfferConnection, error) 45 SaveEgressNetworks(relationKey string, cidrs []string) (state.RelationNetworks, error) 46 } 47 48 // BlockChecker defines the block-checking functionality required by 49 // the application facade. This is implemented by 50 // apiserver/common.BlockChecker. 51 type BlockChecker interface { 52 ChangeAllowed() error 53 RemoveAllowed() error 54 } 55 56 // Application defines a subset of the functionality provided by the 57 // state.Application type, as required by the application facade. For 58 // details on the methods, see the methods on state.Application with 59 // the same names. 60 type Application interface { 61 AddUnit(state.AddUnitParams) (Unit, error) 62 AllUnits() ([]Unit, error) 63 ApplicationConfig() (application.ConfigAttributes, error) 64 Charm() (Charm, bool, error) 65 CharmURL() (*charm.URL, bool) 66 ChangeScale(int) (int, error) 67 Channel() csparams.Channel 68 ClearExposed() error 69 CharmConfig() (charm.Settings, error) 70 Constraints() (constraints.Value, error) 71 Destroy() error 72 DestroyOperation() *state.DestroyApplicationOperation 73 EndpointBindings() (map[string]string, error) 74 Endpoints() ([]state.Endpoint, error) 75 IsExposed() bool 76 IsPrincipal() bool 77 IsRemote() bool 78 Scale(int) error 79 Series() string 80 SetCharm(state.SetCharmConfig) error 81 SetConstraints(constraints.Value) error 82 SetExposed() error 83 SetCharmProfile(string) error 84 SetMetricCredentials([]byte) error 85 SetMinUnits(int) error 86 UpdateApplicationSeries(string, bool) error 87 UpdateCharmConfig(charm.Settings) error 88 UpdateApplicationConfig(application.ConfigAttributes, []string, environschema.Fields, schema.Defaults) error 89 } 90 91 // Charm defines a subset of the functionality provided by the 92 // state.Charm type, as required by the application facade. For 93 // details on the methods, see the methods on state.Charm with 94 // the same names. 95 type Charm interface { 96 charm.Charm 97 } 98 99 // Machine defines a subset of the functionality provided by the 100 // state.Machine type, as required by the application facade. For 101 // details on the methods, see the methods on state.Machine with 102 // the same names. 103 type Machine interface { 104 IsLockedForSeriesUpgrade() (bool, error) 105 IsParentLockedForSeriesUpgrade() (bool, error) 106 UpgradeCharmProfileComplete() (string, error) 107 RemoveUpgradeCharmProfileData() error 108 } 109 110 // Relation defines a subset of the functionality provided by the 111 // state.Relation type, as required by the application facade. For 112 // details on the methods, see the methods on state.Relation with 113 // the same names. 114 type Relation interface { 115 status.StatusSetter 116 Tag() names.Tag 117 Destroy() error 118 Endpoint(string) (state.Endpoint, error) 119 SetSuspended(bool, string) error 120 Suspended() bool 121 SuspendedReason() string 122 } 123 124 // Unit defines a subset of the functionality provided by the 125 // state.Unit type, as required by the application facade. For 126 // details on the methods, see the methods on state.Unit with 127 // the same names. 128 type Unit interface { 129 Name() string 130 Tag() names.Tag 131 UnitTag() names.UnitTag 132 Destroy() error 133 DestroyOperation() *state.DestroyUnitOperation 134 IsPrincipal() bool 135 Life() state.Life 136 Resolve(retryHooks bool) error 137 138 AssignedMachineId() (string, error) 139 AssignWithPolicy(state.AssignmentPolicy) error 140 AssignWithPlacement(*instance.Placement) error 141 } 142 143 // Model defines a subset of the functionality provided by the 144 // state.Model type, as required by the application facade. For 145 // details on the methods, see the methods on state.Model with 146 // the same names. 147 type Model interface { 148 ModelTag() names.ModelTag 149 Name() string 150 Owner() names.UserTag 151 Tag() names.Tag 152 Type() state.ModelType 153 } 154 155 // Resources defines a subset of the functionality provided by the 156 // state.Resources type, as required by the application facade. See 157 // the state.Resources type for details on the methods. 158 type Resources interface { 159 RemovePendingAppResources(string, map[string]string) error 160 } 161 162 type stateShim struct { 163 *state.State 164 } 165 166 type ExternalController state.ExternalController 167 168 func (s stateShim) SaveController(controllerInfo crossmodel.ControllerInfo, modelUUID string) (ExternalController, error) { 169 api := state.NewExternalControllers(s.State) 170 return api.Save(controllerInfo, modelUUID) 171 } 172 173 type storageInterface interface { 174 storagecommon.StorageAccess 175 VolumeAccess() storagecommon.VolumeAccess 176 FilesystemAccess() storagecommon.FilesystemAccess 177 } 178 179 var getStorageState = func(st *state.State) (storageInterface, error) { 180 m, err := st.Model() 181 if err != nil { 182 return nil, err 183 } 184 sb, err := state.NewStorageBackend(st) 185 if err != nil { 186 return nil, err 187 } 188 storageAccess := &storageShim{ 189 StorageAccess: sb, 190 va: sb, 191 fa: sb, 192 } 193 // CAAS models don't support volume storage yet. 194 if m.Type() == state.ModelTypeCAAS { 195 storageAccess.va = nil 196 } 197 return storageAccess, nil 198 } 199 200 type storageShim struct { 201 storagecommon.StorageAccess 202 fa storagecommon.FilesystemAccess 203 va storagecommon.VolumeAccess 204 } 205 206 func (s *storageShim) VolumeAccess() storagecommon.VolumeAccess { 207 return s.va 208 } 209 210 func (s *storageShim) FilesystemAccess() storagecommon.FilesystemAccess { 211 return s.fa 212 } 213 214 // NewStateApplication converts a state.Application into an Application. 215 func NewStateApplication(st *state.State, app *state.Application) Application { 216 return stateApplicationShim{app, st} 217 } 218 219 // CharmToStateCharm converts a Charm into a state.Charm. This is 220 // a hack that is required until the State interface methods we 221 // deal with stop accepting state.Charms, and start accepting 222 // charm.Charm and charm.URL. 223 func CharmToStateCharm(ch Charm) *state.Charm { 224 return ch.(stateCharmShim).Charm 225 } 226 227 func (s stateShim) Application(name string) (Application, error) { 228 a, err := s.State.Application(name) 229 if err != nil { 230 return nil, err 231 } 232 return stateApplicationShim{a, s.State}, nil 233 } 234 235 func (s stateShim) AddApplication(args state.AddApplicationArgs) (Application, error) { 236 a, err := s.State.AddApplication(args) 237 if err != nil { 238 return nil, err 239 } 240 return stateApplicationShim{a, s.State}, nil 241 } 242 243 type remoteApplicationShim struct { 244 *state.RemoteApplication 245 } 246 247 type RemoteApplication interface { 248 Name() string 249 SourceModel() names.ModelTag 250 Endpoints() ([]state.Endpoint, error) 251 AddEndpoints(eps []charm.Relation) error 252 Bindings() map[string]string 253 Spaces() []state.RemoteSpace 254 Destroy() error 255 } 256 257 func (s stateShim) RemoteApplication(name string) (RemoteApplication, error) { 258 app, err := s.State.RemoteApplication(name) 259 return &remoteApplicationShim{app}, err 260 } 261 262 func (s stateShim) AddRemoteApplication(args state.AddRemoteApplicationParams) (RemoteApplication, error) { 263 app, err := s.State.AddRemoteApplication(args) 264 return &remoteApplicationShim{app}, err 265 } 266 267 func (s stateShim) AddRelation(eps ...state.Endpoint) (Relation, error) { 268 r, err := s.State.AddRelation(eps...) 269 if err != nil { 270 return nil, err 271 } 272 return stateRelationShim{r}, nil 273 } 274 275 func (s stateShim) SaveEgressNetworks(relationKey string, cidrs []string) (state.RelationNetworks, error) { 276 api := state.NewRelationEgressNetworks(s.State) 277 return api.Save(relationKey, false, cidrs) 278 } 279 280 func (s stateShim) Charm(curl *charm.URL) (Charm, error) { 281 ch, err := s.State.Charm(curl) 282 if err != nil { 283 return nil, err 284 } 285 return stateCharmShim{ch}, nil 286 } 287 288 func (s stateShim) EndpointsRelation(eps ...state.Endpoint) (Relation, error) { 289 r, err := s.State.EndpointsRelation(eps...) 290 if err != nil { 291 return nil, err 292 } 293 return stateRelationShim{r}, nil 294 } 295 296 func (s stateShim) Relation(id int) (Relation, error) { 297 r, err := s.State.Relation(id) 298 if err != nil { 299 return nil, err 300 } 301 return stateRelationShim{r}, nil 302 } 303 304 func (s stateShim) Machine(name string) (Machine, error) { 305 m, err := s.State.Machine(name) 306 if err != nil { 307 return nil, err 308 } 309 return stateMachineShim{m}, nil 310 } 311 312 func (s stateShim) Unit(name string) (Unit, error) { 313 u, err := s.State.Unit(name) 314 if err != nil { 315 return nil, err 316 } 317 return stateUnitShim{u, s.State}, nil 318 } 319 320 func (s stateShim) UnitsInError() ([]Unit, error) { 321 units, err := s.State.UnitsInError() 322 if err != nil { 323 return nil, err 324 } 325 result := make([]Unit, len(units)) 326 for i, u := range units { 327 result[i] = stateUnitShim{u, s.State} 328 } 329 return result, nil 330 } 331 332 func (s stateShim) Resources() (Resources, error) { 333 return s.State.Resources() 334 } 335 336 type OfferConnection interface{} 337 338 func (s stateShim) OfferConnectionForRelation(key string) (OfferConnection, error) { 339 return s.State.OfferConnectionForRelation(key) 340 } 341 342 type stateApplicationShim struct { 343 *state.Application 344 st *state.State 345 } 346 347 func (a stateApplicationShim) AddUnit(args state.AddUnitParams) (Unit, error) { 348 u, err := a.Application.AddUnit(args) 349 if err != nil { 350 return nil, err 351 } 352 return stateUnitShim{u, a.st}, nil 353 } 354 355 func (a stateApplicationShim) Charm() (Charm, bool, error) { 356 ch, force, err := a.Application.Charm() 357 if err != nil { 358 return nil, false, err 359 } 360 return ch, force, nil 361 } 362 363 func (a stateApplicationShim) AllUnits() ([]Unit, error) { 364 units, err := a.Application.AllUnits() 365 if err != nil { 366 return nil, err 367 } 368 out := make([]Unit, len(units)) 369 for i, u := range units { 370 out[i] = stateUnitShim{u, a.st} 371 } 372 return out, nil 373 } 374 375 type stateCharmShim struct { 376 *state.Charm 377 } 378 379 type stateMachineShim struct { 380 *state.Machine 381 } 382 383 type stateRelationShim struct { 384 *state.Relation 385 } 386 387 type stateUnitShim struct { 388 *state.Unit 389 st *state.State 390 } 391 392 func (u stateUnitShim) AssignWithPolicy(policy state.AssignmentPolicy) error { 393 return u.st.AssignUnit(u.Unit, policy) 394 } 395 396 func (u stateUnitShim) AssignWithPlacement(placement *instance.Placement) error { 397 return u.st.AssignUnitWithPlacement(u.Unit, placement) 398 } 399 400 type Subnet interface { 401 CIDR() string 402 VLANTag() int 403 ProviderId() network.Id 404 ProviderNetworkId() network.Id 405 } 406 407 type subnetShim struct { 408 *state.Subnet 409 } 410 411 type Space interface { 412 Name() string 413 ProviderId() network.Id 414 } 415 416 type spaceShim struct { 417 *state.Space 418 }