github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/undertaker/undertaker.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package undertaker 5 6 import ( 7 "github.com/juju/errors" 8 "gopkg.in/juju/names.v2" 9 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/facade" 12 "github.com/juju/juju/apiserver/params" 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/state/watcher" 15 ) 16 17 // UndertakerAPI implements the API used by the model undertaker worker. 18 type UndertakerAPI struct { 19 st State 20 resources facade.Resources 21 *common.StatusSetter 22 } 23 24 // NewUndertakerAPI creates a new instance of the undertaker API. 25 func NewUndertakerAPI(st *state.State, resources facade.Resources, authorizer facade.Authorizer) (*UndertakerAPI, error) { 26 m, err := st.Model() 27 if err != nil { 28 return nil, errors.Trace(err) 29 } 30 31 return newUndertakerAPI(&stateShim{st, m}, resources, authorizer) 32 } 33 34 func newUndertakerAPI(st State, resources facade.Resources, authorizer facade.Authorizer) (*UndertakerAPI, error) { 35 if !authorizer.AuthController() { 36 return nil, common.ErrPerm 37 } 38 model, err := st.Model() 39 if err != nil { 40 return nil, errors.Trace(err) 41 } 42 getCanModifyModel := func() (common.AuthFunc, error) { 43 return func(tag names.Tag) bool { 44 if st.IsController() { 45 return true 46 } 47 // Only the agent's model can be modified. 48 modelTag, ok := tag.(names.ModelTag) 49 if !ok { 50 return false 51 } 52 return modelTag.Id() == model.UUID() 53 }, nil 54 } 55 return &UndertakerAPI{ 56 st: st, 57 resources: resources, 58 StatusSetter: common.NewStatusSetter(st, getCanModifyModel), 59 }, nil 60 } 61 62 // ModelInfo returns information on the model needed by the undertaker worker. 63 func (u *UndertakerAPI) ModelInfo() (params.UndertakerModelInfoResult, error) { 64 result := params.UndertakerModelInfoResult{} 65 model, err := u.st.Model() 66 67 if err != nil { 68 return result, errors.Trace(err) 69 } 70 71 result.Result = params.UndertakerModelInfo{ 72 UUID: model.UUID(), 73 GlobalName: model.Owner().String() + "/" + model.Name(), 74 Name: model.Name(), 75 IsSystem: u.st.IsController(), 76 Life: params.Life(model.Life().String()), 77 } 78 79 return result, nil 80 } 81 82 // ProcessDyingModel checks if a dying model has any machines or applications. 83 // If there are none, the model's life is changed from dying to dead. 84 func (u *UndertakerAPI) ProcessDyingModel() error { 85 return u.st.ProcessDyingModel() 86 } 87 88 // RemoveModel removes any records of this model from Juju. 89 func (u *UndertakerAPI) RemoveModel() error { 90 return u.st.RemoveDyingModel() 91 } 92 93 func (u *UndertakerAPI) modelEntitiesWatcher() params.NotifyWatchResult { 94 var nothing params.NotifyWatchResult 95 watch := u.st.WatchModelEntityReferences(u.st.ModelUUID()) 96 if _, ok := <-watch.Changes(); ok { 97 return params.NotifyWatchResult{ 98 NotifyWatcherId: u.resources.Register(watch), 99 } 100 } 101 nothing.Error = common.ServerError(watcher.EnsureErr(watch)) 102 return nothing 103 } 104 105 // WatchModelResources creates watchers for changes to the lifecycle of an 106 // model's machines and services. 107 func (u *UndertakerAPI) WatchModelResources() params.NotifyWatchResults { 108 return params.NotifyWatchResults{ 109 Results: []params.NotifyWatchResult{ 110 u.modelEntitiesWatcher(), 111 }, 112 } 113 } 114 115 // ModelConfig returns the model's configuration. 116 func (u *UndertakerAPI) ModelConfig() (params.ModelConfigResult, error) { 117 result := params.ModelConfigResult{} 118 119 config, err := u.st.ModelConfig() 120 if err != nil { 121 return result, err 122 } 123 allAttrs := config.AllAttrs() 124 result.Config = allAttrs 125 return result, nil 126 }