github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/cloudspec/statehelpers.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package cloudspec 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 10 environscloudspec "github.com/juju/juju/environs/cloudspec" 11 "github.com/juju/juju/state" 12 "github.com/juju/juju/state/stateenvirons" 13 ) 14 15 // Pool describes an interface for retrieving State instances from a 16 // collection. 17 type Pool interface { 18 Get(string) (*state.PooledState, error) 19 } 20 21 // MakeCloudSpecGetter returns a function which returns a CloudSpec 22 // for a given model, using the given Pool. 23 func MakeCloudSpecGetter(pool Pool) func(names.ModelTag) (environscloudspec.CloudSpec, error) { 24 return func(tag names.ModelTag) (environscloudspec.CloudSpec, error) { 25 st, err := pool.Get(tag.Id()) 26 if err != nil { 27 return environscloudspec.CloudSpec{}, errors.Trace(err) 28 } 29 defer st.Release() 30 31 m, err := st.Model() 32 if err != nil { 33 return environscloudspec.CloudSpec{}, errors.Trace(err) 34 } 35 // TODO - CAAS(externalreality): Once cloud methods are migrated 36 // to model EnvironConfigGetter will no longer need to contain 37 // both state and model but only model. 38 // TODO (manadart 2018-02-15): This potentially frees the state from 39 // the pool. Release is called, but the state reference survives. 40 return stateenvirons.EnvironConfigGetter{Model: m}.CloudSpec() 41 } 42 } 43 44 // MakeCloudSpecGetterForModel returns a function which returns a 45 // CloudSpec for a single model. Attempts to request a CloudSpec for 46 // any other model other than the one associated with the given 47 // state.State results in an error. 48 func MakeCloudSpecGetterForModel(st *state.State) func(names.ModelTag) (environscloudspec.CloudSpec, error) { 49 return func(tag names.ModelTag) (environscloudspec.CloudSpec, error) { 50 m, err := st.Model() 51 if err != nil { 52 return environscloudspec.CloudSpec{}, errors.Trace(err) 53 } 54 configGetter := stateenvirons.EnvironConfigGetter{Model: m} 55 56 if tag.Id() != st.ModelUUID() { 57 return environscloudspec.CloudSpec{}, errors.New("cannot get cloud spec for this model") 58 } 59 return configGetter.CloudSpec() 60 } 61 } 62 63 // MakeCloudSpecWatcherForModel returns a function which returns a 64 // NotifyWatcher for cloud spec changes for a single model. 65 // Attempts to request a watcher for any other model other than the 66 // one associated with the given state.State results in an error. 67 func MakeCloudSpecWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) { 68 return func(tag names.ModelTag) (state.NotifyWatcher, error) { 69 m, err := st.Model() 70 if err != nil { 71 return nil, errors.Trace(err) 72 } 73 if tag.Id() != st.ModelUUID() { 74 return nil, errors.New("cannot get cloud spec for this model") 75 } 76 return m.WatchCloudSpecChanges(), nil 77 } 78 } 79 80 // MakeCloudSpecCredentialWatcherForModel returns a function which returns a 81 // NotifyWatcher for changes to a model's credential reference. 82 // This watch will detect when model's credential is replaced with another credential. 83 // Attempts to request a watcher for any other model other than the 84 // one associated with the given state.State results in an error. 85 func MakeCloudSpecCredentialWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) { 86 return func(tag names.ModelTag) (state.NotifyWatcher, error) { 87 m, err := st.Model() 88 if err != nil { 89 return nil, errors.Trace(err) 90 } 91 if tag.Id() != st.ModelUUID() { 92 return nil, errors.New("cannot get cloud spec credential for this model") 93 } 94 return m.WatchModelCredential(), nil 95 } 96 } 97 98 // MakeCloudSpecCredentialContentWatcherForModel returns a function which returns a 99 // NotifyWatcher for credential content changes for a single model. 100 // Attempts to request a watcher for any other model other than the 101 // one associated with the given state.State results in an error. 102 func MakeCloudSpecCredentialContentWatcherForModel(st *state.State) func(names.ModelTag) (state.NotifyWatcher, error) { 103 return func(tag names.ModelTag) (state.NotifyWatcher, error) { 104 m, err := st.Model() 105 if err != nil { 106 return nil, errors.Trace(err) 107 } 108 if tag.Id() != st.ModelUUID() { 109 return nil, errors.New("cannot get cloud spec credential content for this model") 110 } 111 credentialTag, exists := m.CloudCredentialTag() 112 if !exists { 113 return nil, nil 114 } 115 return st.WatchCredential(credentialTag), nil 116 } 117 }