github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/environs/interface.go (about) 1 // Copyright 2011, 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environs 5 6 import ( 7 "io" 8 9 "github.com/juju/jsonschema" 10 "github.com/juju/version" 11 "gopkg.in/juju/environschema.v1" 12 13 "github.com/juju/juju/cloud" 14 "github.com/juju/juju/core/constraints" 15 "github.com/juju/juju/core/instance" 16 "github.com/juju/juju/environs/config" 17 "github.com/juju/juju/environs/context" 18 "github.com/juju/juju/environs/instances" 19 "github.com/juju/juju/network" 20 "github.com/juju/juju/storage" 21 ) 22 23 //go:generate mockgen -package testing -destination testing/package_mock.go github.com/juju/juju/environs EnvironProvider,CloudEnvironProvider,ProviderSchema,ProviderCredentials,FinalizeCredentialContext,FinalizeCloudContext,CloudFinalizer,CloudDetector,CloudRegionDetector,ModelConfigUpgrader,ConfigGetter,CloudDestroyer,Environ,InstancePrechecker,Firewaller,InstanceTagger,InstanceTypesFetcher,Upgrader,UpgradeStep,DefaultConstraintsChecker,ProviderCredentialsRegister,RequestFinalizeCredential,NetworkingEnviron 24 25 // A EnvironProvider represents a computing and storage provider 26 // for either a traditional cloud or a container substrate like k8s. 27 type EnvironProvider interface { 28 config.Validator 29 ProviderCredentials 30 31 // Version returns the version of the provider. This is recorded as the 32 // environ version for each model, and used to identify which upgrade 33 // operations to run when upgrading a model's environ. Providers should 34 // start out at version 0. 35 Version() int 36 37 // CloudSchema returns the schema used to validate input for add-cloud. If 38 // a provider does not support custom clouds, CloudSchema should return 39 // nil. 40 CloudSchema() *jsonschema.Schema 41 42 // Ping tests the connection to the cloud, to verify the endpoint is valid. 43 Ping(ctx context.ProviderCallContext, endpoint string) error 44 45 // PrepareConfig prepares the configuration for a new model, based on 46 // the provided arguments. PrepareConfig is expected to produce a 47 // deterministic output. Any unique values should be based on the 48 // "uuid" attribute of the base configuration. This is called for the 49 // controller model during bootstrap, and also for new hosted models. 50 PrepareConfig(PrepareConfigParams) (*config.Config, error) 51 } 52 53 // A EnvironProvider represents a computing and storage provider 54 // for a traditional cloud like AWS or Openstack. 55 type CloudEnvironProvider interface { 56 EnvironProvider 57 // Open opens the environment and returns it. The configuration must 58 // have passed through PrepareConfig at some point in its lifecycle. 59 // 60 // Open should not perform any expensive operations, such as querying 61 // the cloud API, as it will be called frequently. 62 Open(OpenParams) (Environ, error) 63 } 64 65 // OpenParams contains the parameters for EnvironProvider.Open. 66 type OpenParams struct { 67 // Cloud is the cloud specification to use to connect to the cloud. 68 Cloud CloudSpec 69 70 // Config is the base configuration for the provider. 71 Config *config.Config 72 } 73 74 // ProviderSchema can be implemented by a provider to provide 75 // access to its configuration schema. Once all providers implement 76 // this, it will be included in the EnvironProvider type and the 77 // information made available over the API. 78 type ProviderSchema interface { 79 // Schema returns the schema for the provider. It should 80 // include all fields defined in environs/config, conventionally 81 // by calling config.Schema. 82 Schema() environschema.Fields 83 } 84 85 // PrepareConfigParams contains the parameters for EnvironProvider.PrepareConfig. 86 type PrepareConfigParams struct { 87 // Cloud is the cloud specification to use to connect to the cloud. 88 Cloud CloudSpec 89 90 // Config is the base configuration for the provider. This should 91 // be updated with the region, endpoint and credentials. 92 Config *config.Config 93 } 94 95 // ProviderCredentials is an interface that an EnvironProvider implements 96 // in order to validate and automatically detect credentials for clouds 97 // supported by the provider. 98 // 99 // TODO(axw) replace CredentialSchemas with an updated environschema. 100 // The GUI also needs to be able to handle multiple credential types, 101 // and dependencies in config attributes. 102 type ProviderCredentials interface { 103 // CredentialSchemas returns credential schemas, keyed on 104 // authentication type. These may be used to validate existing 105 // credentials, or to generate new ones (e.g. to create an 106 // interactive form.) 107 CredentialSchemas() map[cloud.AuthType]cloud.CredentialSchema 108 109 // DetectCredentials automatically detects one or more credentials 110 // from the environment. This may involve, for example, inspecting 111 // environment variables, or reading configuration files in 112 // well-defined locations. 113 // 114 // If no credentials can be detected, DetectCredentials should 115 // return an error satisfying errors.IsNotFound. 116 DetectCredentials() (*cloud.CloudCredential, error) 117 118 // FinalizeCredential finalizes a credential, updating any attributes 119 // as necessary. This is always done client-side, when adding the 120 // credential to credentials.yaml and before uploading credentials to 121 // the controller. The provider may completely alter a credential, even 122 // going as far as changing the auth-type, but the output must be a 123 // fully formed credential. 124 FinalizeCredential( 125 FinalizeCredentialContext, 126 FinalizeCredentialParams, 127 ) (*cloud.Credential, error) 128 } 129 130 // ProviderCredentialsRegister is an interface that an EnvironProvider 131 // implements in order to validate and automatically register credentials for 132 // clouds supported by the provider. 133 type ProviderCredentialsRegister interface { 134 135 // RegisterCredentials will return any credentials that need to be 136 // registered for the provider. 137 // 138 // If no credentials can be found, RegisterCredentials should return 139 // an error satisfying errors.IsNotFound. 140 RegisterCredentials(cloud.Cloud) (map[string]*cloud.CloudCredential, error) 141 } 142 143 // RequestFinalizeCredential is an interface that an EnvironProvider implements 144 // in order to call ProviderCredentials.FinalizeCredential strictly rather than 145 // lazily to gather fully formed credentials. 146 type RequestFinalizeCredential interface { 147 148 // ShouldFinalizeCredential asks if a EnvironProvider wants to strictly 149 // finalize a credential. The provider just returns true if they want to 150 // call FinalizeCredential from ProviderCredentials when asked. 151 ShouldFinalizeCredential(cloud.Credential) bool 152 } 153 154 // FinalizeCredentialContext is an interface passed into FinalizeCredential 155 // to provide a means of interacting with the user when finalizing credentials. 156 type FinalizeCredentialContext interface { 157 GetStderr() io.Writer 158 } 159 160 // FinalizeCredentialParams contains the parameters for 161 // ProviderCredentials.FinalizeCredential. 162 type FinalizeCredentialParams struct { 163 // Credential is the credential that the provider should finalize. 164 Credential cloud.Credential 165 166 // CloudEndpoint is the endpoint for the cloud that the credentials are 167 // for. This may be used by the provider to communicate with the cloud 168 // to finalize the credentials. 169 CloudEndpoint string 170 171 // CloudStorageEndpoint is the storage endpoint for the cloud that the 172 // credentials are for. This may be used by the provider to communicate 173 // with the cloud to finalize the credentials. 174 CloudStorageEndpoint string 175 176 // CloudIdentityEndpoint is the identity endpoint for the cloud that the 177 // credentials are for. This may be used by the provider to communicate 178 // with the cloud to finalize the credentials. 179 CloudIdentityEndpoint string 180 } 181 182 // FinalizeCloudContext is an interface passed into FinalizeCloud 183 // to provide a means of interacting with the user when finalizing 184 // a cloud definition. 185 type FinalizeCloudContext interface { 186 // Verbosef will write the formatted string to Stderr if the 187 // verbose flag is true, and to the logger if not. 188 Verbosef(string, ...interface{}) 189 } 190 191 // CloudFinalizer is an interface that an EnvironProvider implements 192 // in order to finalize a cloud.Cloud definition before bootstrapping. 193 type CloudFinalizer interface { 194 // FinalizeCloud finalizes a cloud definition, updating any attributes 195 // as necessary. This is always done client-side, before bootstrapping. 196 FinalizeCloud(FinalizeCloudContext, cloud.Cloud) (cloud.Cloud, error) 197 } 198 199 // CloudDetector is an interface that an EnvironProvider implements 200 // in order to automatically detect clouds from the environment. 201 type CloudDetector interface { 202 // DetectCloud attempts to detect a cloud with the given name 203 // from the environment. This may involve, for example, 204 // inspecting environment variables, or returning special 205 // hard-coded regions (e.g. "localhost" for lxd). 206 // 207 // If no cloud can be detected, DetectCloud should return 208 // an error satisfying errors.IsNotFound. 209 // 210 // DetectCloud should be used in preference to DetectClouds 211 // when a specific cloud is identified, as this may be more 212 // efficient. 213 DetectCloud(name string) (cloud.Cloud, error) 214 215 // DetectClouds detects clouds from the environment. This may 216 // involve, for example, inspecting environment variables, or 217 // returning special hard-coded regions (e.g. "localhost" for lxd). 218 DetectClouds() ([]cloud.Cloud, error) 219 } 220 221 // CloudRegionDetector is an interface that an EnvironProvider implements 222 // in order to automatically detect cloud regions from the environment. 223 type CloudRegionDetector interface { 224 // DetectRegions automatically detects one or more regions 225 // from the environment. This may involve, for example, inspecting 226 // environment variables, or returning special hard-coded regions 227 // (e.g. "localhost" for lxd). The first item in the list will be 228 // considered the default region for bootstrapping if the user 229 // does not specify one. 230 // 231 // If no regions can be detected, DetectRegions should return 232 // an error satisfying errors.IsNotFound. 233 DetectRegions() ([]cloud.Region, error) 234 } 235 236 // ModelConfigUpgrader is an interface that an EnvironProvider may 237 // implement in order to modify environment configuration on agent upgrade. 238 type ModelConfigUpgrader interface { 239 // UpgradeConfig upgrades an old environment configuration by adding, 240 // updating or removing attributes. UpgradeConfig must be idempotent, 241 // as it may be called multiple times in the event of a partial upgrade. 242 // 243 // NOTE(axw) this is currently only called when upgrading to 1.25. 244 // We should update the upgrade machinery to call this for every 245 // version upgrade, so the upgrades package is not tightly coupled 246 // to provider upgrades. 247 // TODO (anastasiamac 2018-04-27) Since it is only for 1.25, do we still need it? 248 UpgradeConfig(cfg *config.Config) (*config.Config, error) 249 } 250 251 // ConfigGetter implements access to an environment's configuration. 252 type ConfigGetter interface { 253 // Config returns the configuration data with which the Environ was created. 254 // Note that this is not necessarily current; the canonical location 255 // for the configuration data is stored in the state. 256 Config() *config.Config 257 } 258 259 // ConfigSetter implements access to an environment's configuration. 260 type ConfigSetter interface { 261 // SetConfig updates the Environ's configuration. 262 // 263 // Calls to SetConfig do not affect the configuration of 264 // values previously obtained from Storage. 265 SetConfig(cfg *config.Config) error 266 } 267 268 // Bootstraper provides the way for bootstrapping controller. 269 type Bootstraper interface { 270 // This will be called very early in the bootstrap procedure, to 271 // give an Environ a chance to perform interactive operations that 272 // are required for bootstrapping. 273 PrepareForBootstrap(ctx BootstrapContext) error 274 275 // Bootstrap creates a new environment, and an instance to host the 276 // controller for that environment. The instance will have the 277 // series and architecture of the Environ's choice, constrained to 278 // those of the available tools. Bootstrap will return the instance's 279 // architecture, series, and a function that must be called to finalize 280 // the bootstrap process by transferring the tools and installing the 281 // initial Juju controller. 282 // 283 // It is possible to direct Bootstrap to use a specific architecture 284 // (or fail if it cannot start an instance of that architecture) by 285 // using an architecture constraint; this will have the effect of 286 // limiting the available tools to just those matching the specified 287 // architecture. 288 Bootstrap(ctx BootstrapContext, callCtx context.ProviderCallContext, params BootstrapParams) (*BootstrapResult, error) 289 } 290 291 // Configer implements access to an environment's configuration. 292 type Configer interface { 293 ConfigGetter 294 ConfigSetter 295 } 296 297 // BootstrapEnviron is an interface that an EnvironProvider implements 298 // in order to bootstrap a controller. 299 type BootstrapEnviron interface { 300 Configer 301 Bootstraper 302 ConstraintsChecker 303 ControllerDestroyer 304 } 305 306 // CloudDestroyer provides the API to cleanup cloud resources. 307 type CloudDestroyer interface { 308 // Destroy shuts down all known machines and destroys the 309 // rest of the environment. Note that on some providers, 310 // very recently started instances may not be destroyed 311 // because they are not yet visible. 312 // 313 // When Destroy has been called, any Environ referring to the 314 // same remote environment may become invalid. 315 Destroy(ctx context.ProviderCallContext) error 316 } 317 318 // An Environ represents a Juju environment. 319 // 320 // Due to the limitations of some providers (for example ec2), the 321 // results of the Environ methods may not be fully sequentially 322 // consistent. In particular, while a provider may retry when it 323 // gets an error for an operation, it will not retry when 324 // an operation succeeds, even if that success is not 325 // consistent with a previous operation. 326 // 327 // Even though Juju takes care not to share an Environ between concurrent 328 // workers, it does allow concurrent method calls into the provider 329 // implementation. The typical provider implementation needs locking to 330 // avoid undefined behaviour when the configuration changes. 331 type Environ interface { 332 // Environ implements storage.ProviderRegistry for acquiring 333 // environ-scoped storage providers supported by the Environ. 334 // StorageProviders returned from Environ.StorageProvider will 335 // be scoped specifically to that Environ. 336 storage.ProviderRegistry 337 338 // CloudDestroyer provides the API to cleanup cloud resources. 339 CloudDestroyer 340 341 // Bootstraper prepares an environment for bootstrapping. 342 Bootstraper 343 344 // Create creates the environment for a new hosted model. 345 // 346 // This will be called before any workers begin operating on the 347 // Environ, to give an Environ a chance to perform operations that 348 // are required for further use. 349 // 350 // Create is not called for the initial controller model; it is 351 // the Bootstrap method's job to create the controller model. 352 Create(context.ProviderCallContext, CreateParams) error 353 354 // ResourceAdopter defines methods for adopting resources. 355 ResourceAdopter 356 357 // InstanceBroker defines methods for starting and stopping 358 // instances. 359 InstanceBroker 360 361 // Configer allows the access of the configuration data. 362 Configer 363 364 // ConstraintsChecker provides a means to check that constraints are valid. 365 ConstraintsChecker 366 367 // Instances returns a slice of instances corresponding to the 368 // given instance ids. If no instances were found, but there 369 // was no other error, it will return ErrNoInstances. If 370 // some but not all the instances were found, the returned slice 371 // will have some nil slots, and an ErrPartialInstances error 372 // will be returned. 373 Instances(ctx context.ProviderCallContext, ids []instance.Id) ([]instances.Instance, error) 374 375 // ControllerInstances returns the IDs of instances corresponding 376 // to Juju controller, having the specified controller UUID. 377 // If there are no controller instances, ErrNoInstances is returned. 378 // If it can be determined that the environment has not been bootstrapped, 379 // then ErrNotBootstrapped should be returned instead. 380 ControllerInstances(ctx context.ProviderCallContext, controllerUUID string) ([]instance.Id, error) 381 382 // Provider returns the EnvironProvider that created this Environ. 383 Provider() EnvironProvider 384 385 InstancePrechecker 386 387 // InstanceTypesFetcher represents an environment that can return 388 // information about the available instance types. 389 InstanceTypesFetcher 390 391 // ControllerDestroyer is similar to Destroy() in that it destroys 392 // the model, which in this case will be the controller model. 393 ControllerDestroyer 394 } 395 396 // ControllerDestroyer is similar to Destroy() in that it destroys 397 // the model, which in this case will be the controller model. 398 // 399 // In addition, this method also destroys any resources relating 400 // to hosted models on the controller on which it is invoked. 401 // This ensures that "kill-controller" can clean up hosted models 402 // when the Juju controller process is unavailable. 403 type ControllerDestroyer interface { 404 DestroyController(ctx context.ProviderCallContext, controllerUUID string) error 405 } 406 407 type ResourceAdopter interface { 408 // AdoptResources is called when the model is moved from one 409 // controller to another using model migration. Some providers tag 410 // instances, disks, and cloud storage with the controller UUID to 411 // aid in clean destruction. This method will be called on the 412 // environ for the target controller so it can update the 413 // controller tags for all of those things. For providers that do 414 // not track the controller UUID, a simple method returning nil 415 // will suffice. The version number of the source controller is 416 // provided for backwards compatibility - if the technique used to 417 // tag items changes, the version number can be used to decide how 418 // to remove the old tags correctly. 419 AdoptResources(ctx context.ProviderCallContext, controllerUUID string, fromVersion version.Number) error 420 } 421 422 // ConstraintsChecker provides a means to check that constraints are valid. 423 type ConstraintsChecker interface { 424 // ConstraintsValidator returns a Validator instance which 425 // is used to validate and merge constraints. 426 ConstraintsValidator(ctx context.ProviderCallContext) (constraints.Validator, error) 427 } 428 429 // InstancePrechecker provides a means of "prechecking" instance 430 // arguments before recording them in state. 431 type InstancePrechecker interface { 432 // PrecheckInstance performs a preflight check on the specified 433 // series and constraints, ensuring that they are possibly valid for 434 // creating an instance in this model. 435 // 436 // PrecheckInstance is best effort, and not guaranteed to eliminate 437 // all invalid parameters. If PrecheckInstance returns nil, it is not 438 // guaranteed that the constraints are valid; if a non-nil error is 439 // returned, then the constraints are definitely invalid. 440 PrecheckInstance(context.ProviderCallContext, PrecheckInstanceParams) error 441 } 442 443 // PrecheckInstanceParams contains the parameters for 444 // InstancePrechecker.PrecheckInstance. 445 type PrecheckInstanceParams struct { 446 // Series contains the series of the machine. 447 Series string 448 449 // Constraints contains the machine constraints. 450 Constraints constraints.Value 451 452 // Placement contains the machine placement directive, if any. 453 Placement string 454 455 // VolumeAttachments contains the parameters for attaching existing 456 // volumes to the instance. The PrecheckInstance method should not 457 // expect the attachment's Machine field to be set, as PrecheckInstance 458 // may be called before a machine ID is allocated. 459 VolumeAttachments []storage.VolumeAttachmentParams 460 } 461 462 // CreateParams contains the parameters for Environ.Create. 463 type CreateParams struct { 464 // ControllerUUID is the UUID of the controller to be that is creating 465 // the Environ. 466 ControllerUUID string 467 } 468 469 // Firewaller exposes methods for managing network ports. 470 type Firewaller interface { 471 // OpenPorts opens the given port ranges for the whole environment. 472 // Must only be used if the environment was setup with the 473 // FwGlobal firewall mode. 474 OpenPorts(ctx context.ProviderCallContext, rules []network.IngressRule) error 475 476 // ClosePorts closes the given port ranges for the whole environment. 477 // Must only be used if the environment was setup with the 478 // FwGlobal firewall mode. 479 ClosePorts(ctx context.ProviderCallContext, rules []network.IngressRule) error 480 481 // IngressRules returns the ingress rules applied to the whole environment. 482 // Must only be used if the environment was setup with the 483 // FwGlobal firewall mode. 484 // It is expected that there be only one ingress rule result for a given 485 // port range - the rule's SourceCIDRs will contain all applicable source 486 // address rules for that port range. 487 IngressRules(ctx context.ProviderCallContext) ([]network.IngressRule, error) 488 } 489 490 // InstanceTagger is an interface that can be used for tagging instances. 491 type InstanceTagger interface { 492 // TagInstance tags the given instance with the specified tags. 493 // 494 // The specified tags will replace any existing ones with the 495 // same names, but other existing tags will be left alone. 496 TagInstance(ctx context.ProviderCallContext, id instance.Id, tags map[string]string) error 497 } 498 499 // InstanceTypesFetcher is an interface that allows for instance information from 500 // a provider to be obtained. 501 type InstanceTypesFetcher interface { 502 InstanceTypes(context.ProviderCallContext, constraints.Value) (instances.InstanceTypesWithCostMetadata, error) 503 } 504 505 // Upgrader is an interface that can be used for upgrading Environs. If an 506 // Environ implements this interface, its UpgradeOperations method will be 507 // invoked to identify operations that should be run on upgrade. 508 type Upgrader interface { 509 // UpgradeOperations returns a list of UpgradeOperations for upgrading 510 // an Environ. 511 UpgradeOperations(context.ProviderCallContext, UpgradeOperationsParams) []UpgradeOperation 512 } 513 514 // UpgradeOperationsParams contains the parameters for 515 // Upgrader.UpgradeOperations. 516 type UpgradeOperationsParams struct { 517 // ControllerUUID is the UUID of the controller that manages 518 // the Environ being upgraded. 519 ControllerUUID string 520 } 521 522 // UpgradeOperation contains a target agent version and sequence of upgrade 523 // steps to apply to get to that version. 524 type UpgradeOperation struct { 525 // TargetVersion is the target environ provider version number to 526 // which the upgrade steps pertain. When a model is upgraded, all 527 // upgrade operations will be run for versions greater than the 528 // recorded environ version. This version number is independent of 529 // the agent and controller versions. 530 TargetVersion int 531 532 // Steps contains the sequence of upgrade steps to apply when 533 // upgrading to the accompanying target version number. 534 Steps []UpgradeStep 535 } 536 537 // UpgradeStep defines an idempotent operation that is run to perform a 538 // specific upgrade step on an Environ. 539 type UpgradeStep interface { 540 // Description is a human readable description of what the upgrade 541 // step does. 542 Description() string 543 544 // Run executes the upgrade business logic. 545 Run(ctx context.ProviderCallContext) error 546 } 547 548 // DefaultConstraintsChecker defines an interface for checking if the default 549 // constraints should be applied for the Environ provider when bootstrapping 550 // the provider. 551 type DefaultConstraintsChecker interface { 552 // ShouldApplyControllerConstraints returns if bootstrapping logic should 553 // use default constraints 554 ShouldApplyControllerConstraints() bool 555 }