github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/modelmanagerinterface.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "time" 8 9 "github.com/juju/collections/set" 10 "github.com/juju/description/v5" 11 "github.com/juju/errors" 12 "github.com/juju/names/v5" 13 14 apiservererrors "github.com/juju/juju/apiserver/errors" 15 "github.com/juju/juju/cloud" 16 "github.com/juju/juju/controller" 17 "github.com/juju/juju/core/network" 18 "github.com/juju/juju/core/permission" 19 "github.com/juju/juju/core/secrets" 20 "github.com/juju/juju/core/status" 21 "github.com/juju/juju/environs" 22 environscloudspec "github.com/juju/juju/environs/cloudspec" 23 "github.com/juju/juju/environs/config" 24 "github.com/juju/juju/state" 25 ) 26 27 // ModelManagerBackend defines methods provided by a state 28 // instance used by the model manager apiserver implementation. 29 // All the interface methods are defined directly on state.State 30 // and are reproduced here for use in tests. 31 type ModelManagerBackend interface { 32 APIHostPortsForAgentsGetter 33 ToolsStorageGetter 34 BlockGetter 35 state.CloudAccessor 36 37 ModelUUID() string 38 ModelBasicInfoForUser(user names.UserTag, isSuperuser bool) ([]state.ModelAccessInfo, error) 39 ModelSummariesForUser(user names.UserTag, isSupersser bool) ([]state.ModelSummary, error) 40 IsControllerAdmin(user names.UserTag) (bool, error) 41 NewModel(state.ModelArgs) (Model, ModelManagerBackend, error) 42 Model() (Model, error) 43 AllModelUUIDs() ([]string, error) 44 GetModel(string) (Model, func() bool, error) 45 GetBackend(string) (ModelManagerBackend, func() bool, error) 46 47 ComposeNewModelConfig(modelAttr map[string]interface{}, regionSpec *environscloudspec.CloudRegionSpec) (map[string]interface{}, error) 48 ControllerModelUUID() string 49 ControllerModelTag() names.ModelTag 50 IsController() bool 51 ControllerConfig() (controller.Config, error) 52 ControllerNodes() ([]ControllerNode, error) 53 ModelConfigDefaultValues(cloudName string) (config.ModelDefaultAttributes, error) 54 UpdateModelConfigDefaultValues(update map[string]interface{}, remove []string, regionSpec *environscloudspec.CloudRegionSpec) error 55 Unit(name string) (*state.Unit, error) 56 Name() string 57 ModelTag() names.ModelTag 58 ModelConfig() (*config.Config, error) 59 AddControllerUser(state.UserAccessSpec) (permission.UserAccess, error) 60 RemoveUserAccess(names.UserTag, names.Tag) error 61 UserAccess(names.UserTag, names.Tag) (permission.UserAccess, error) 62 GetCloudAccess(cloud string, user names.UserTag) (permission.Access, error) 63 AllMachines() (machines []Machine, err error) 64 AllApplications() (applications []Application, err error) 65 AllFilesystems() ([]state.Filesystem, error) 66 AllVolumes() ([]state.Volume, error) 67 ControllerUUID() string 68 ControllerTag() names.ControllerTag 69 Export(leaders map[string]string) (description.Model, error) 70 ExportPartial(state.ExportConfig) (description.Model, error) 71 SetUserAccess(subject names.UserTag, target names.Tag, access permission.Access) (permission.UserAccess, error) 72 SetModelMeterStatus(string, string) error 73 AllSpaces() ([]*state.Space, error) 74 AddSpace(string, network.Id, []string, bool) (*state.Space, error) 75 AllEndpointBindingsSpaceNames() (set.Strings, error) 76 ConstraintsBySpaceName(string) ([]*state.Constraints, error) 77 DefaultEndpointBindingSpace() (string, error) 78 SaveProviderSubnets([]network.SubnetInfo, string) error 79 LatestMigration() (state.ModelMigration, error) 80 DumpAll() (map[string]interface{}, error) 81 Close() error 82 HAPrimaryMachine() (names.MachineTag, error) 83 84 // Secrets methods. 85 ListModelSecrets(bool) (map[string]set.Strings, error) 86 ListSecretBackends() ([]*secrets.SecretBackend, error) 87 GetSecretBackendByID(string) (*secrets.SecretBackend, error) 88 89 // Methods required by the metricsender package. 90 MetricsManager() (*state.MetricsManager, error) 91 MetricsToSend(batchSize int) ([]*state.MetricBatch, error) 92 SetMetricBatchesSent(batchUUIDs []string) error 93 CountOfUnsentMetrics() (int, error) 94 CountOfSentMetrics() (int, error) 95 CleanupOldMetrics() error 96 } 97 98 // Model defines methods provided by a state.Model instance. 99 // All the interface methods are defined directly on state.Model 100 // and are reproduced here for use in tests. 101 type Model interface { 102 Type() state.ModelType 103 Config() (*config.Config, error) 104 Life() state.Life 105 ModelTag() names.ModelTag 106 Owner() names.UserTag 107 Status() (status.StatusInfo, error) 108 CloudName() string 109 Cloud() (cloud.Cloud, error) 110 CloudCredentialTag() (names.CloudCredentialTag, bool) 111 CloudCredential() (state.Credential, bool, error) 112 CloudRegion() string 113 Users() ([]permission.UserAccess, error) 114 Destroy(state.DestroyModelParams) error 115 SLALevel() string 116 SLAOwner() string 117 MigrationMode() state.MigrationMode 118 Name() string 119 UUID() string 120 ControllerUUID() string 121 LastModelConnection(user names.UserTag) (time.Time, error) 122 AddUser(state.UserAccessSpec) (permission.UserAccess, error) 123 AutoConfigureContainerNetworking(environ environs.BootstrapEnviron) error 124 SetCloudCredential(tag names.CloudCredentialTag) (bool, error) 125 } 126 127 var _ ModelManagerBackend = (*modelManagerStateShim)(nil) 128 129 type modelManagerStateShim struct { 130 *state.State 131 model *state.Model 132 pool *state.StatePool 133 user names.UserTag 134 } 135 136 // NewModelManagerBackend returns a modelManagerStateShim wrapping the passed 137 // state, which implements ModelManagerBackend. 138 func NewModelManagerBackend(m *state.Model, pool *state.StatePool) ModelManagerBackend { 139 return modelManagerStateShim{m.State(), m, pool, names.UserTag{}} 140 } 141 142 // NewUserAwareModelManagerBackend returns a user-aware modelManagerStateShim 143 // wrapping the passed state, which implements ModelManagerBackend. The 144 // returned backend may emit redirect errors when attempting a model lookup for 145 // a migrated model that this user had been granted access to. 146 func NewUserAwareModelManagerBackend(m *state.Model, pool *state.StatePool, u names.UserTag) ModelManagerBackend { 147 return modelManagerStateShim{m.State(), m, pool, u} 148 } 149 150 // NewModel implements ModelManagerBackend. 151 func (st modelManagerStateShim) NewModel(args state.ModelArgs) (Model, ModelManagerBackend, error) { 152 aController := state.NewController(st.pool) 153 otherModel, otherState, err := aController.NewModel(args) 154 if err != nil { 155 return nil, nil, err 156 } 157 return modelShim{otherModel}, modelManagerStateShim{otherState, otherModel, st.pool, st.user}, nil 158 } 159 160 func (st modelManagerStateShim) ModelConfigDefaultValues(cloudName string) (config.ModelDefaultAttributes, error) { 161 return st.State.ModelConfigDefaultValues(cloudName) 162 } 163 164 // UpdateModelConfigDefaultValues implements the ModelManagerBackend method. 165 func (st modelManagerStateShim) UpdateModelConfigDefaultValues(update map[string]interface{}, remove []string, regionSpec *environscloudspec.CloudRegionSpec) error { 166 return st.State.UpdateModelConfigDefaultValues(update, remove, regionSpec) 167 } 168 169 // ControllerTag exposes Model ControllerTag for ModelManagerBackend inteface 170 func (st modelManagerStateShim) ControllerTag() names.ControllerTag { 171 return st.model.ControllerTag() 172 } 173 174 // GetBackend implements ModelManagerBackend. 175 func (st modelManagerStateShim) GetBackend(modelUUID string) (ModelManagerBackend, func() bool, error) { 176 otherState, err := st.pool.Get(modelUUID) 177 if err != nil { 178 return nil, nil, errors.Trace(err) 179 } 180 otherModel, err := otherState.Model() 181 if err != nil { 182 defer otherState.Release() 183 if !errors.IsNotFound(err) || st.user.Id() == "" { 184 return nil, nil, err 185 } 186 187 // Check if this model has been migrated and this user had 188 // access to it before its migration. 189 mig, mErr := otherState.CompletedMigration() 190 if mErr != nil && !errors.IsNotFound(mErr) { 191 return nil, nil, errors.Trace(mErr) 192 } 193 194 if mig == nil || mig.ModelUserAccess(st.user) == permission.NoAccess { 195 return nil, nil, errors.Trace(err) // return original NotFound error 196 } 197 198 target, mErr := mig.TargetInfo() 199 if mErr != nil { 200 return nil, nil, errors.Trace(mErr) 201 } 202 203 hps, mErr := network.ParseProviderHostPorts(target.Addrs...) 204 if mErr != nil { 205 return nil, nil, errors.Trace(mErr) 206 } 207 208 return nil, nil, &apiservererrors.RedirectError{ 209 Servers: []network.ProviderHostPorts{hps}, 210 CACert: target.CACert, 211 ControllerAlias: target.ControllerAlias, 212 } 213 } 214 return modelManagerStateShim{otherState.State, otherModel, st.pool, st.user}, otherState.Release, nil 215 } 216 217 // GetModel implements ModelManagerBackend. 218 func (st modelManagerStateShim) GetModel(modelUUID string) (Model, func() bool, error) { 219 model, hp, err := st.pool.GetModel(modelUUID) 220 if err != nil { 221 return nil, nil, errors.Trace(err) 222 } 223 return modelShim{model}, hp.Release, nil 224 } 225 226 // Model implements ModelManagerBackend. 227 func (st modelManagerStateShim) Model() (Model, error) { 228 return modelShim{st.model}, nil 229 } 230 231 // Name implements ModelManagerBackend. 232 func (st modelManagerStateShim) Name() string { 233 return st.model.Name() 234 } 235 236 func (st modelManagerStateShim) ControllerNodes() ([]ControllerNode, error) { 237 nodes, err := st.State.ControllerNodes() 238 if err != nil { 239 return nil, errors.Trace(err) 240 } 241 result := make([]ControllerNode, len(nodes)) 242 for i, n := range nodes { 243 result[i] = n 244 } 245 return result, nil 246 } 247 248 func (st modelManagerStateShim) IsController() bool { 249 return st.State.IsController() 250 } 251 252 func (st modelManagerStateShim) ListModelSecrets(all bool) (map[string]set.Strings, error) { 253 secretsState := state.NewSecrets(st.State) 254 return secretsState.ListModelSecrets(all) 255 } 256 257 func (st modelManagerStateShim) ListSecretBackends() ([]*secrets.SecretBackend, error) { 258 backendState := state.NewSecretBackends(st.State) 259 return backendState.ListSecretBackends() 260 } 261 262 func (st modelManagerStateShim) GetSecretBackendByID(id string) (*secrets.SecretBackend, error) { 263 backendState := state.NewSecretBackends(st.State) 264 return backendState.GetSecretBackendByID(id) 265 } 266 267 var _ Model = (*modelShim)(nil) 268 269 type modelShim struct { 270 *state.Model 271 } 272 273 // Users implements ModelManagerBackend. 274 func (m modelShim) Users() ([]permission.UserAccess, error) { 275 stateUsers, err := m.Model.Users() 276 if err != nil { 277 return nil, err 278 } 279 users := make([]permission.UserAccess, len(stateUsers)) 280 for i, user := range stateUsers { 281 users[i] = user 282 } 283 return users, nil 284 } 285 286 type machineShim struct { 287 *state.Machine 288 } 289 290 func (st modelManagerStateShim) AllMachines() ([]Machine, error) { 291 allStateMachines, err := st.State.AllMachines() 292 if err != nil { 293 return nil, err 294 } 295 all := make([]Machine, len(allStateMachines)) 296 for i, m := range allStateMachines { 297 all[i] = machineShim{m} 298 } 299 return all, nil 300 } 301 302 // Application defines methods provided by a state.Application instance. 303 type Application interface { 304 Name() string 305 UnitCount() int 306 } 307 308 type applicationShim struct { 309 *state.Application 310 } 311 312 func (st modelManagerStateShim) AllApplications() ([]Application, error) { 313 allStateApplications, err := st.State.AllApplications() 314 if err != nil { 315 return nil, err 316 } 317 all := make([]Application, len(allStateApplications)) 318 for i, a := range allStateApplications { 319 all[i] = applicationShim{a} 320 } 321 return all, nil 322 } 323 324 func (st modelManagerStateShim) AllFilesystems() ([]state.Filesystem, error) { 325 sb, err := state.NewStorageBackend(st.State) 326 if err != nil { 327 return nil, err 328 } 329 return sb.AllFilesystems() 330 } 331 332 func (st modelManagerStateShim) AllVolumes() ([]state.Volume, error) { 333 sb, err := state.NewStorageBackend(st.State) 334 if err != nil { 335 return nil, err 336 } 337 return sb.AllVolumes() 338 } 339 340 // ModelConfig returns the underlying model's config. Exposed here to satisfy the 341 // ModelBackend interface. 342 func (st modelManagerStateShim) ModelConfig() (*config.Config, error) { 343 model, err := st.State.Model() 344 if err != nil { 345 return nil, errors.Trace(err) 346 } 347 return model.ModelConfig() 348 } 349 350 // [TODO: Eric Claude Jones] This method ignores an error for the purpose of 351 // expediting refactoring for CAAS features (we are avoiding changing method 352 // signatures so that refactoring doesn't spiral out of control). This method 353 // should be deleted immediately upon the removal of the ModelTag method from 354 // state.State. 355 func (st modelManagerStateShim) ModelTag() names.ModelTag { 356 return names.NewModelTag(st.ModelUUID()) 357 }