github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/modelupgrader/modelupgrader.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package modelupgrader 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 "gopkg.in/juju/names.v2" 10 11 "github.com/juju/juju/apiserver/common" 12 "github.com/juju/juju/apiserver/facade" 13 "github.com/juju/juju/apiserver/params" 14 "github.com/juju/juju/environs" 15 ) 16 17 var logger = loggo.GetLogger("juju.apiserver.modelupgrader") 18 19 type Facade struct { 20 backend Backend 21 pool Pool 22 providers ProviderRegistry 23 entityWatcher EntityWatcher 24 statusSetter StatusSetter 25 } 26 27 // EntityWatcher is an interface that provides a means of watching 28 // entities. 29 type EntityWatcher interface { 30 Watch(params.Entities) (params.NotifyWatchResults, error) 31 } 32 33 // ProviderRegistry provides the subset of environs.ProviderRegistry 34 // that we require. 35 type ProviderRegistry interface { 36 Provider(string) (environs.EnvironProvider, error) 37 } 38 39 // StatusSetter is an interface that provides a means of setting 40 // the status of entities. 41 type StatusSetter interface { 42 SetStatus(params.SetStatus) (params.ErrorResults, error) 43 } 44 45 // NewStateFacade provides the signature required for facade registration. 46 func NewStateFacade(ctx facade.Context) (*Facade, error) { 47 pool := NewPool(ctx.StatePool()) 48 registry := environs.GlobalProviderRegistry() 49 watcher := common.NewAgentEntityWatcher( 50 ctx.State(), 51 ctx.Resources(), 52 common.AuthFuncForTagKind(names.ModelTagKind), 53 ) 54 statusSetter := common.NewStatusSetter( 55 ctx.State(), 56 common.AuthFuncForTagKind(names.ModelTagKind), 57 ) 58 return NewFacade(ctx.State(), pool, registry, watcher, statusSetter, ctx.Auth()) 59 } 60 61 // NewFacade returns a new Facade using the given Backend and Authorizer. 62 func NewFacade( 63 backend Backend, 64 pool Pool, 65 providers ProviderRegistry, 66 entityWatcher EntityWatcher, 67 statusSetter StatusSetter, 68 auth facade.Authorizer, 69 ) (*Facade, error) { 70 if !auth.AuthController() { 71 return nil, common.ErrPerm 72 } 73 return &Facade{ 74 backend: backend, 75 pool: pool, 76 providers: providers, 77 entityWatcher: entityWatcher, 78 statusSetter: statusSetter, 79 }, nil 80 } 81 82 // ModelEnvironVersion returns the current version of the environ corresponding 83 // to each specified model. 84 func (f *Facade) ModelEnvironVersion(args params.Entities) (params.IntResults, error) { 85 result := params.IntResults{ 86 Results: make([]params.IntResult, len(args.Entities)), 87 } 88 for i, arg := range args.Entities { 89 v, err := f.modelEnvironVersion(arg) 90 if err != nil { 91 result.Results[i].Error = common.ServerError(err) 92 continue 93 } 94 result.Results[i].Result = v 95 } 96 return result, nil 97 } 98 99 func (f *Facade) modelEnvironVersion(arg params.Entity) (int, error) { 100 tag, err := names.ParseModelTag(arg.Tag) 101 if err != nil { 102 return -1, errors.Trace(err) 103 } 104 model, release, err := f.pool.GetModel(tag.Id()) 105 if err != nil { 106 return -1, errors.Trace(err) 107 } 108 defer release() 109 return model.EnvironVersion(), nil 110 } 111 112 // ModelTargetEnvironVersion returns the target version of the environ 113 // corresponding to each specified model. The target version is the 114 // environ provider's version. 115 func (f *Facade) ModelTargetEnvironVersion(args params.Entities) (params.IntResults, error) { 116 result := params.IntResults{ 117 Results: make([]params.IntResult, len(args.Entities)), 118 } 119 for i, arg := range args.Entities { 120 v, err := f.modelTargetEnvironVersion(arg) 121 if err != nil { 122 result.Results[i].Error = common.ServerError(err) 123 continue 124 } 125 result.Results[i].Result = v 126 } 127 return result, nil 128 } 129 130 func (f *Facade) modelTargetEnvironVersion(arg params.Entity) (int, error) { 131 tag, err := names.ParseModelTag(arg.Tag) 132 if err != nil { 133 return -1, errors.Trace(err) 134 } 135 model, release, err := f.pool.GetModel(tag.Id()) 136 if err != nil { 137 return -1, errors.Trace(err) 138 } 139 defer release() 140 cloud, err := f.backend.Cloud(model.Cloud()) 141 if err != nil { 142 return -1, errors.Trace(err) 143 } 144 provider, err := f.providers.Provider(cloud.Type) 145 if err != nil { 146 return -1, errors.Trace(err) 147 } 148 return provider.Version(), nil 149 } 150 151 // SetModelEnvironVersion sets the current version of the environ corresponding 152 // to each specified model. 153 func (f *Facade) SetModelEnvironVersion(args params.SetModelEnvironVersions) (params.ErrorResults, error) { 154 result := params.ErrorResults{ 155 Results: make([]params.ErrorResult, len(args.Models)), 156 } 157 for i, arg := range args.Models { 158 err := f.setModelEnvironVersion(arg) 159 if err != nil { 160 result.Results[i].Error = common.ServerError(err) 161 } 162 } 163 return result, nil 164 } 165 166 func (f *Facade) setModelEnvironVersion(arg params.SetModelEnvironVersion) error { 167 tag, err := names.ParseModelTag(arg.ModelTag) 168 if err != nil { 169 return errors.Trace(err) 170 } 171 model, release, err := f.pool.GetModel(tag.Id()) 172 if err != nil { 173 return errors.Trace(err) 174 } 175 defer release() 176 return errors.Trace(model.SetEnvironVersion(arg.Version)) 177 } 178 179 // WatchModelEnvironVersion watches for changes to the environ version of the 180 // specified models. 181 // 182 // NOTE(axw) this is currently implemented in terms of state.Model.Watch, so 183 // the client may be notified of changes unrelated to the environ version. 184 func (f *Facade) WatchModelEnvironVersion(args params.Entities) (params.NotifyWatchResults, error) { 185 return f.entityWatcher.Watch(args) 186 } 187 188 // SetModelStatus sets the status of each given model. 189 func (f *Facade) SetModelStatus(args params.SetStatus) (params.ErrorResults, error) { 190 return f.statusSetter.SetStatus(args) 191 }