func (s *withoutControllerSuite) TestStorageProviderFallbackToType(c *gc.C) { template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, Placement: "valid", Volumes: []state.MachineVolumeParams{ {Volume: state.VolumeParams{Size: 1000, Pool: "environscoped"}}, {Volume: state.VolumeParams{Size: 1000, Pool: "static"}}, }, } placementMachine, err := s.State.AddOneMachine(template) c.Assert(err, jc.ErrorIsNil) args := params.Entities{Entities: []params.Entity{ {Tag: placementMachine.Tag().String()}, }} result, err := s.provisioner.ProvisioningInfo(args) c.Assert(err, jc.ErrorIsNil) controllerCfg := coretesting.FakeControllerConfig() // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(s.Environ.Provider()) controllerCfg["api-port"] = apiPort c.Assert(result, jc.DeepEquals, params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{ {Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Constraints: template.Constraints, Placement: template.Placement, Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, Volumes: []params.VolumeParams{{ VolumeTag: "volume-1", Size: 1000, Provider: "static", Attributes: nil, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, Attachment: ¶ms.VolumeAttachmentParams{ MachineTag: placementMachine.Tag().String(), VolumeTag: "volume-1", Provider: "static", }, }}, }}, }, }) }
func (s *withoutControllerSuite) TestProvisioningInfoWithEndpointBindings(c *gc.C) { s.addSpacesAndSubnets(c) wordpressMachine, err := s.State.AddOneMachine(state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, }) c.Assert(err, jc.ErrorIsNil) // Use juju names for spaces in bindings, simulating ''juju deploy // --bind...' was called. bindings := map[string]string{ "url": "space1", // has both name and provider ID "db": "space2", // has only name, no provider ID } wordpressCharm := s.AddTestingCharm(c, "wordpress") wordpressService := s.AddTestingServiceWithBindings(c, "wordpress", wordpressCharm, bindings) wordpressUnit, err := wordpressService.AddUnit() c.Assert(err, jc.ErrorIsNil) err = wordpressUnit.AssignToMachine(wordpressMachine) c.Assert(err, jc.ErrorIsNil) args := params.Entities{Entities: []params.Entity{ {Tag: wordpressMachine.Tag().String()}, }} result, err := s.provisioner.ProvisioningInfo(args) c.Assert(err, jc.ErrorIsNil) controllerCfg := coretesting.FakeControllerConfig() // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(s.Environ.Provider()) controllerCfg["api-port"] = apiPort expected := params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{{ Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), tags.JujuUnitsDeployed: wordpressUnit.Name(), }, // Ensure space names are translated to provider IDs, where // possible. EndpointBindings: map[string]string{ "db": "space2", // just name, no provider ID "url": "first space id", // has provider ID // We expect none of the unspecified bindings in the result. }, }, }}} c.Assert(result, jc.DeepEquals, expected) }
func (s *withoutControllerSuite) TestProvisioningInfoWithSingleNegativeAndPositiveSpaceInConstraints(c *gc.C) { s.addSpacesAndSubnets(c) cons := constraints.MustParse("cores=123 mem=8G spaces=^space1,space2") template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, Constraints: cons, Placement: "valid", } placementMachine, err := s.State.AddOneMachine(template) c.Assert(err, jc.ErrorIsNil) args := params.Entities{Entities: []params.Entity{ {Tag: placementMachine.Tag().String()}, }} result, err := s.provisioner.ProvisioningInfo(args) c.Assert(err, jc.ErrorIsNil) controllerCfg := coretesting.FakeControllerConfig() // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(s.Environ.Provider()) controllerCfg["api-port"] = apiPort expected := params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{{ Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Constraints: template.Constraints, Placement: template.Placement, Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, SubnetsToZones: map[string][]string{ "subnet-1": []string{"zone1"}, "subnet-2": []string{"zone2"}, }, }, }}} c.Assert(result, jc.DeepEquals, expected) }
func (s *withoutControllerSuite) TestProvisioningInfoPermissions(c *gc.C) { // Login as a machine agent for machine 0. anAuthorizer := s.authorizer anAuthorizer.EnvironManager = false anAuthorizer.Tag = s.machines[0].Tag() aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, jc.ErrorIsNil) c.Assert(aProvisioner, gc.NotNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag().String()}, {Tag: s.machines[0].Tag().String() + "-lxd-0"}, {Tag: "machine-42"}, {Tag: s.machines[1].Tag().String()}, {Tag: "application-bar"}, }} // Only machine 0 and containers therein can be accessed. results, err := aProvisioner.ProvisioningInfo(args) controllerCfg := coretesting.FakeControllerConfig() // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(s.Environ.Provider()) controllerCfg["api-port"] = apiPort c.Assert(results, jc.DeepEquals, params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{ {Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, }}, {Error: apiservertesting.NotFoundError("machine 0/lxd/0")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutControllerSuite) TestProvisioningInfoWithStorage(c *gc.C) { pm := poolmanager.New(state.NewStateSettings(s.State), dummy.StorageProviders()) _, err := pm.Create("static-pool", "static", map[string]interface{}{"foo": "bar"}) c.Assert(err, jc.ErrorIsNil) cons := constraints.MustParse("cores=123 mem=8G") template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, Constraints: cons, Placement: "valid", Volumes: []state.MachineVolumeParams{ {Volume: state.VolumeParams{Size: 1000, Pool: "static-pool"}}, {Volume: state.VolumeParams{Size: 2000, Pool: "static-pool"}}, }, } placementMachine, err := s.State.AddOneMachine(template) c.Assert(err, jc.ErrorIsNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag().String()}, {Tag: placementMachine.Tag().String()}, }} result, err := s.provisioner.ProvisioningInfo(args) c.Assert(err, jc.ErrorIsNil) controllerCfg := coretesting.FakeControllerConfig() // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(s.Environ.Provider()) controllerCfg["api-port"] = apiPort expected := params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{ {Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, }}, {Result: ¶ms.ProvisioningInfo{ ControllerConfig: controllerCfg, Series: "quantal", Constraints: template.Constraints, Placement: template.Placement, Jobs: []multiwatcher.MachineJob{multiwatcher.JobHostUnits}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, Volumes: []params.VolumeParams{{ VolumeTag: "volume-0", Size: 1000, Provider: "static", Attributes: map[string]interface{}{"foo": "bar"}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, Attachment: ¶ms.VolumeAttachmentParams{ MachineTag: placementMachine.Tag().String(), VolumeTag: "volume-0", Provider: "static", }, }, { VolumeTag: "volume-1", Size: 2000, Provider: "static", Attributes: map[string]interface{}{"foo": "bar"}, Tags: map[string]string{ tags.JujuController: coretesting.ControllerTag.Id(), tags.JujuModel: coretesting.ModelTag.Id(), }, Attachment: ¶ms.VolumeAttachmentParams{ MachineTag: placementMachine.Tag().String(), VolumeTag: "volume-1", Provider: "static", }, }}, }}, }, } // The order of volumes is not predictable, so we make sure we // compare the right ones. This only applies to Results[1] since // it is the only result to contain volumes. if expected.Results[1].Result.Volumes[0].VolumeTag != result.Results[1].Result.Volumes[0].VolumeTag { vols := expected.Results[1].Result.Volumes vols[0], vols[1] = vols[1], vols[0] } c.Assert(result, jc.DeepEquals, expected) }
func (s *JujuConnSuite) setUpConn(c *gc.C) { if s.RootDir != "" { c.Fatal("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = utils.Home() userHomeParams := UserHomeParams{ Username: "******", ModelEnvKey: "controller", SetOldHome: true, } s.CreateUserHome(c, &userHomeParams) cfg, err := config.New(config.UseDefaults, (map[string]interface{})(s.sampleConfig())) c.Assert(err, jc.ErrorIsNil) ctx := testing.Context(c) s.ControllerConfig = testing.FakeControllerConfig() for key, value := range s.ControllerConfigAttrs { s.ControllerConfig[key] = value } cloudSpec := dummy.SampleCloudSpec() environ, err := bootstrap.Prepare( modelcmd.BootstrapContext(ctx), s.ControllerStore, bootstrap.PrepareParams{ ControllerConfig: s.ControllerConfig, ModelConfig: cfg.AllAttrs(), Cloud: cloudSpec, ControllerName: ControllerName, AdminSecret: AdminSecret, }, ) c.Assert(err, jc.ErrorIsNil) // sanity check we've got the correct environment. c.Assert(environ.Config().Name(), gc.Equals, "controller") s.PatchValue(&dummy.DataDir, s.DataDir()) s.LogDir = c.MkDir() s.PatchValue(&dummy.LogDir, s.LogDir) versions := DefaultVersions(environ.Config()) // Upload tools for both preferred and fake default series s.DefaultToolsStorageDir = c.MkDir() s.PatchValue(&tools.DefaultBaseURL, s.DefaultToolsStorageDir) stor, err := filestorage.NewFileStorageWriter(s.DefaultToolsStorageDir) c.Assert(err, jc.ErrorIsNil) // Upload tools to both release and devel streams since config will dictate that we // end up looking in both places. envtesting.AssertUploadFakeToolsVersions(c, stor, "released", "released", versions...) envtesting.AssertUploadFakeToolsVersions(c, stor, "devel", "devel", versions...) s.DefaultToolsStorage = stor s.PatchValue(&keys.JujuPublicKey, sstesting.SignedMetadataPublicKey) // Dummy provider uses a random port, which is added to cfg used to create environment. apiPort := dummy.ApiPort(environ.Provider()) s.ControllerConfig["api-port"] = apiPort err = bootstrap.Bootstrap(modelcmd.BootstrapContext(ctx), environ, bootstrap.BootstrapParams{ ControllerConfig: s.ControllerConfig, CloudName: cloudSpec.Name, CloudRegion: "dummy-region", Cloud: cloud.Cloud{ Type: cloudSpec.Type, AuthTypes: []cloud.AuthType{cloud.EmptyAuthType, cloud.UserPassAuthType}, Endpoint: cloudSpec.Endpoint, IdentityEndpoint: cloudSpec.IdentityEndpoint, StorageEndpoint: cloudSpec.StorageEndpoint, Regions: []cloud.Region{ { Name: "dummy-region", Endpoint: "dummy-endpoint", IdentityEndpoint: "dummy-identity-endpoint", StorageEndpoint: "dummy-storage-endpoint", }, }, }, CloudCredential: cloudSpec.Credential, CloudCredentialName: "cred", AdminSecret: AdminSecret, CAPrivateKey: testing.CAKey, }) c.Assert(err, jc.ErrorIsNil) getStater := environ.(GetStater) s.BackingState = getStater.GetStateInAPIServer() s.BackingStatePool = getStater.GetStatePoolInAPIServer() s.State, err = newState(s.ControllerConfig.ControllerUUID(), environ, s.BackingState.MongoConnectionInfo()) c.Assert(err, jc.ErrorIsNil) apiInfo, err := environs.APIInfo(s.ControllerConfig.ControllerUUID(), testing.ModelTag.Id(), testing.CACert, s.ControllerConfig.APIPort(), environ) c.Assert(err, jc.ErrorIsNil) apiInfo.Tag = s.AdminUserTag(c) apiInfo.Password = AdminSecret s.APIState, err = api.Open(apiInfo, api.DialOpts{}) c.Assert(err, jc.ErrorIsNil) err = s.State.SetAPIHostPorts(s.APIState.APIHostPorts()) c.Assert(err, jc.ErrorIsNil) // Make sure the controller store has the controller api endpoint address set controller, err := s.ControllerStore.ControllerByName(ControllerName) c.Assert(err, jc.ErrorIsNil) controller.APIEndpoints = []string{s.APIState.APIHostPorts()[0][0].String()} err = s.ControllerStore.UpdateController(ControllerName, *controller) c.Assert(err, jc.ErrorIsNil) err = s.ControllerStore.SetCurrentController(ControllerName) c.Assert(err, jc.ErrorIsNil) s.Environ = environ // Insert expected values... servingInfo := state.StateServingInfo{ PrivateKey: testing.ServerKey, Cert: testing.ServerCert, CAPrivateKey: testing.CAKey, SharedSecret: "really, really secret", APIPort: s.ControllerConfig.APIPort(), StatePort: s.ControllerConfig.StatePort(), } s.State.SetStateServingInfo(servingInfo) }