github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/state/stateenvirons/policy.go (about) 1 // Copyright 2014, 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package stateenvirons 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/juju/caas" 9 10 "github.com/juju/juju/core/constraints" 11 "github.com/juju/juju/environs" 12 "github.com/juju/juju/environs/config" 13 "github.com/juju/juju/environs/context" 14 "github.com/juju/juju/state" 15 "github.com/juju/juju/storage" 16 "github.com/juju/juju/storage/provider" 17 ) 18 19 // environStatePolicy implements state.Policy in 20 // terms of environs.Environ and related types. 21 type environStatePolicy struct { 22 st *state.State 23 getEnviron NewEnvironFunc 24 getBroker NewCAASBrokerFunc 25 } 26 27 // GetNewPolicyFunc returns a state.NewPolicyFunc that will return 28 // a state.Policy implemented in terms of either environs.Environ 29 // or caas.Broker and related types. 30 func GetNewPolicyFunc() state.NewPolicyFunc { 31 return func(st *state.State) state.Policy { 32 return environStatePolicy{st, GetNewEnvironFunc(environs.New), GetNewCAASBrokerFunc(caas.New)} 33 } 34 } 35 36 // Prechecker implements state.Policy. 37 func (p environStatePolicy) Prechecker() (environs.InstancePrechecker, error) { 38 model, err := p.st.Model() 39 if err != nil { 40 return nil, errors.Trace(err) 41 } 42 if model.Type() == state.ModelTypeIAAS { 43 return p.getEnviron(p.st) 44 } 45 return p.getBroker(p.st) 46 } 47 48 // ConfigValidator implements state.Policy. 49 func (p environStatePolicy) ConfigValidator() (config.Validator, error) { 50 model, err := p.st.Model() 51 if err != nil { 52 return nil, errors.Trace(err) 53 } 54 if model.Type() != state.ModelTypeIAAS { 55 // TODO(caas) CAAS providers should also support 56 // config validation. 57 return nil, errors.NotImplementedf("ConfigValidator") 58 } 59 return environProvider(p.st) 60 } 61 62 // ProviderConfigSchemaSource implements state.Policy. 63 func (p environStatePolicy) ProviderConfigSchemaSource() (config.ConfigSchemaSource, error) { 64 model, err := p.st.Model() 65 if err != nil { 66 return nil, errors.Trace(err) 67 } 68 if model.Type() != state.ModelTypeIAAS { 69 // TODO(caas) CAAS providers should also provide 70 // a config schema. 71 return nil, errors.NotImplementedf("ProviderConfigSchemaSource") 72 } 73 provider, err := environProvider(p.st) 74 if err != nil { 75 return nil, errors.Trace(err) 76 } 77 if cs, ok := provider.(config.ConfigSchemaSource); ok { 78 return cs, nil 79 } 80 return nil, errors.NotImplementedf("config.ConfigSource") 81 } 82 83 // ConstraintsValidator implements state.Policy. 84 func (p environStatePolicy) ConstraintsValidator(ctx context.ProviderCallContext) (constraints.Validator, error) { 85 model, err := p.st.Model() 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 90 if model.Type() == state.ModelTypeIAAS { 91 env, err := p.getEnviron(p.st) 92 if err != nil { 93 return nil, err 94 } 95 return env.ConstraintsValidator(ctx) 96 } 97 broker, err := p.getBroker(p.st) 98 if err != nil { 99 return nil, errors.Trace(err) 100 } 101 return broker.ConstraintsValidator(ctx) 102 } 103 104 // InstanceDistributor implements state.Policy. 105 func (p environStatePolicy) InstanceDistributor() (context.Distributor, error) { 106 model, err := p.st.Model() 107 if err != nil { 108 return nil, errors.Trace(err) 109 } 110 if model.Type() != state.ModelTypeIAAS { 111 // Only IAAS models support machines, hence distribution. 112 return nil, errors.NotImplementedf("InstanceDistributor") 113 } 114 env, err := p.getEnviron(p.st) 115 if err != nil { 116 return nil, err 117 } 118 if p, ok := env.(context.Distributor); ok { 119 return p, nil 120 } 121 return nil, errors.NotImplementedf("InstanceDistributor") 122 } 123 124 // StorageProviderRegistry implements state.Policy. 125 func (p environStatePolicy) StorageProviderRegistry() (storage.ProviderRegistry, error) { 126 model, err := p.st.Model() 127 if err != nil { 128 return nil, errors.Trace(err) 129 } 130 return NewStorageProviderRegistryForModel(model, p.getEnviron, p.getBroker) 131 } 132 133 // NewStorageProviderRegistryForModel returns a storage provider registry 134 // for the specified model. 135 func NewStorageProviderRegistryForModel( 136 model *state.Model, 137 newEnv NewEnvironFunc, 138 newBroker NewCAASBrokerFunc, 139 ) (_ storage.ProviderRegistry, err error) { 140 var reg storage.ProviderRegistry 141 if model.Type() == state.ModelTypeIAAS { 142 if reg, err = newEnv(model.State()); err != nil { 143 return nil, errors.Trace(err) 144 } 145 } else { 146 if reg, err = newBroker(model.State()); err != nil { 147 return nil, errors.Trace(err) 148 } 149 } 150 return NewStorageProviderRegistry(reg), nil 151 } 152 153 // NewStorageProviderRegistry returns a storage.ProviderRegistry that chains 154 // the provided registry with the common storage providers. 155 func NewStorageProviderRegistry(reg storage.ProviderRegistry) storage.ProviderRegistry { 156 return storage.ChainedProviderRegistry{reg, provider.CommonStorageProviders()} 157 } 158 159 func environProvider(st *state.State) (environs.EnvironProvider, error) { 160 model, err := st.Model() 161 if err != nil { 162 return nil, errors.Annotate(err, "getting model") 163 } 164 cloud, err := st.Cloud(model.Cloud()) 165 if err != nil { 166 return nil, errors.Annotate(err, "getting cloud") 167 } 168 // EnvironProvider implements state.ConfigValidator. 169 return environs.Provider(cloud.Type) 170 }