func (s *withoutStateServerSuite) TestProvisionerFailsWithNonMachineAgentNonManagerUser(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.EnvironManager = true // Works with an environment manager, which is not a machine agent. aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) // But fails with neither a machine agent or an environment manager. anAuthorizer.EnvironManager = false aProvisioner, err = provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.NotNil) c.Assert(aProvisioner, gc.IsNil) c.Assert(err, gc.ErrorMatches, "permission denied") }
func (s *withoutStateServerSuite) 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, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag().String()}, {Tag: s.machines[0].Tag().String() + "-lxc-0"}, {Tag: "machine-42"}, {Tag: s.machines[1].Tag().String()}, {Tag: "service-bar"}, }} // Only machine 0 and containers therein can be accessed. results, err := aProvisioner.ProvisioningInfo(args) c.Assert(results, gc.DeepEquals, params.ProvisioningInfoResults{ Results: []params.ProvisioningInfoResult{ {Result: ¶ms.ProvisioningInfo{ Series: "quantal", Networks: []string{}, Jobs: []params.MachineJob{params.JobHostUnits}, }}, {Error: apiservertesting.NotFoundError("machine 0/lxc/0")}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) { // Machines where there's permission issues are omitted. anAuthorizer := s.authorizer anAuthorizer.EnvironManager = false anAuthorizer.Tag = names.NewMachineTag("1") aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) err = s.machines[0].SetStatus(params.StatusStarted, "blah", nil) c.Assert(err, gc.IsNil) err = s.machines[1].SetStatus(params.StatusError, "transient error", map[string]interface{}{"transient": true, "foo": "bar"}) c.Assert(err, gc.IsNil) err = s.machines[2].SetStatus(params.StatusError, "error", map[string]interface{}{"transient": false}) c.Assert(err, gc.IsNil) err = s.machines[3].SetStatus(params.StatusError, "error", nil) c.Assert(err, gc.IsNil) result, err := aProvisioner.MachinesWithTransientErrors() c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Id: "1", Life: "alive", Status: "error", Info: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}}, }, }) }
func (s *withoutStateServerSuite) TestDistributionGroupMachineAgentAuth(c *gc.C) { anAuthorizer := s.authorizer anAuthorizer.Tag = names.NewMachineTag("1") anAuthorizer.EnvironManager = false provisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Check(err, gc.IsNil) args := params.Entities{Entities: []params.Entity{ {Tag: "machine-0"}, {Tag: "machine-1"}, {Tag: "machine-42"}, {Tag: "machine-0-lxc-99"}, {Tag: "machine-1-lxc-99"}, {Tag: "machine-1-lxc-99-lxc-100"}, }} result, err := provisioner.DistributionGroup(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.DistributionGroupResults{ Results: []params.DistributionGroupResult{ {Error: apiservertesting.ErrUnauthorized}, {Result: []instance.Id{}}, {Error: apiservertesting.ErrUnauthorized}, // only a machine agent for the container or its // parent may access it. {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.NotFoundError("machine 1/lxc/99")}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *withoutStateServerSuite) TestWatchMachineErrorRetry(c *gc.C) { s.PatchValue(&provisioner.ErrorRetryWaitDelay, 2*coretesting.ShortWait) c.Assert(s.resources.Count(), gc.Equals, 0) _, err := s.provisioner.WatchMachineErrorRetry() c.Assert(err, gc.IsNil) // Verify the resources were registered and stop them when done. c.Assert(s.resources.Count(), gc.Equals, 1) resource := s.resources.Get("1") defer statetesting.AssertStop(c, resource) // Check that the Watch has consumed the initial event ("returned" // in the Watch call) wc := statetesting.NewNotifyWatcherC(c, s.State, resource.(state.NotifyWatcher)) wc.AssertNoChange() // We should now get a time triggered change. wc.AssertOneChange() // Make sure WatchMachineErrorRetry fails with a machine agent login. anAuthorizer := s.authorizer anAuthorizer.Tag = names.NewMachineTag("1") anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) result, err := aProvisioner.WatchMachineErrorRetry() c.Assert(err, gc.ErrorMatches, "permission denied") c.Assert(result, gc.DeepEquals, params.NotifyWatchResult{}) }
func (s *withoutStateServerSuite) TestWatchEnvironMachines(c *gc.C) { c.Assert(s.resources.Count(), gc.Equals, 0) got, err := s.provisioner.WatchEnvironMachines() c.Assert(err, gc.IsNil) want := params.StringsWatchResult{ StringsWatcherId: "1", Changes: []string{"0", "1", "2", "3", "4"}, } c.Assert(got.StringsWatcherId, gc.Equals, want.StringsWatcherId) c.Assert(got.Changes, jc.SameContents, want.Changes) // Verify the resources were registered and stop them when done. c.Assert(s.resources.Count(), gc.Equals, 1) resource := s.resources.Get("1") defer statetesting.AssertStop(c, resource) // Check that the Watch has consumed the initial event ("returned" // in the Watch call) wc := statetesting.NewStringsWatcherC(c, s.State, resource.(state.StringsWatcher)) wc.AssertNoChange() // Make sure WatchEnvironMachines fails with a machine agent login. anAuthorizer := s.authorizer anAuthorizer.Tag = names.NewMachineTag("1") anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) result, err := aProvisioner.WatchEnvironMachines() c.Assert(err, gc.ErrorMatches, "permission denied") c.Assert(result, gc.DeepEquals, params.StringsWatchResult{}) }
func (s *withoutStateServerSuite) TestSetSupportedContainersPermissions(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, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) args := params.MachineContainersParams{ Params: []params.MachineContainers{{ MachineTag: "machine-0", ContainerTypes: []instance.ContainerType{instance.LXC}, }, { MachineTag: "machine-1", ContainerTypes: []instance.ContainerType{instance.LXC}, }, { MachineTag: "machine-42", ContainerTypes: []instance.ContainerType{instance.LXC}, }, }, } // Only machine 0 can have it's containers updated. results, err := aProvisioner.SetSupportedContainers(args) c.Assert(results, gc.DeepEquals, params.ErrorResults{ Results: []params.ErrorResult{ {Error: nil}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }
func (s *ImageMetadataSuite) TestMetadataNotInStateButInDataSources(c *gc.C) { // ensure metadata in data sources and not in state useTestImageData(c, testImagesData) criteria := cloudimagemetadata.MetadataFilter{Stream: "daily"} found, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria) c.Assert(errors.IsNotFound(err), jc.IsTrue) c.Assert(found, gc.HasLen, 0) api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) c.Assert(err, jc.ErrorIsNil) result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) c.Assert(err, jc.ErrorIsNil) expected := s.expectedDataSoureImageMetadata() s.assertImageMetadataResults(c, result, expected...) // Also make sure that these images metadata has been written to state for re-use saved, err := s.State.CloudImageMetadataStorage.FindMetadata(criteria) c.Assert(err, jc.ErrorIsNil) stateExpected := s.convertCloudImageMetadata(expected[0]) if len(saved["default cloud images"]) == len(stateExpected) { for i, image := range saved["default cloud images"] { stateExpected[i].DateCreated = image.DateCreated } } c.Assert(saved, gc.DeepEquals, map[string][]cloudimagemetadata.Metadata{ "default cloud images": stateExpected, }) }
func (s *withoutStateServerSuite) TestEnvironConfigNonManager(c *gc.C) { // Now test it with a non-environment manager and make sure // the secret attributes are masked. anAuthorizer := s.authorizer anAuthorizer.Tag = names.NewMachineTag("1") anAuthorizer.EnvironManager = false aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) c.Assert(err, gc.IsNil) s.AssertEnvironConfig(c, aProvisioner, commontesting.NoSecrets) }
func (s *ImageMetadataSuite) TestMetadataNone(c *gc.C) { api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) c.Assert(err, jc.ErrorIsNil) result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) c.Assert(err, jc.ErrorIsNil) expected := make([][]params.CloudImageMetadata, len(s.machines)) for i, _ := range result.Results { expected[i] = nil } s.assertImageMetadataResults(c, result, expected...) }
func (s *withoutControllerSuite) TestMachinesWithTransientErrorsPermission(c *gc.C) { // Machines where there's permission issues are omitted. anAuthorizer := s.authorizer anAuthorizer.EnvironManager = false anAuthorizer.Tag = names.NewMachineTag("1") aProvisioner, err := provisioner.NewProvisionerAPI(s.State, s.resources, anAuthorizer) now := time.Now() sInfo := status.StatusInfo{ Status: status.Started, Message: "blah", Since: &now, } err = s.machines[0].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}, Since: &now, } err = s.machines[1].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "error", Data: map[string]interface{}{"transient": false}, Since: &now, } err = s.machines[2].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) sInfo = status.StatusInfo{ Status: status.Error, Message: "error", Since: &now, } err = s.machines[3].SetStatus(sInfo) c.Assert(err, jc.ErrorIsNil) result, err := aProvisioner.MachinesWithTransientErrors() c.Assert(err, jc.ErrorIsNil) c.Assert(result, gc.DeepEquals, params.StatusResults{ Results: []params.StatusResult{ {Id: "1", Life: "alive", Status: "error", Info: "transient error", Data: map[string]interface{}{"transient": true, "foo": "bar"}}, }, }) }
func (s *provisionerSuite) setUpTest(c *gc.C, withController bool) { s.JujuConnSuite.ConfigAttrs = map[string]interface{}{ "image-stream": "daily", } s.JujuConnSuite.SetUpTest(c) // We're testing with address allocation on by default. There are // separate tests to check the behavior when the flag is not // enabled. s.SetFeatureFlags(feature.AddressAllocation) // Reset previous machines (if any) and create 3 machines // for the tests, plus an optional controller machine. s.machines = nil // Note that the specific machine ids allocated are assumed // to be numerically consecutive from zero. if withController { s.machines = append(s.machines, testing.AddControllerMachine(c, s.State)) } for i := 0; i < 5; i++ { machine, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Check(err, jc.ErrorIsNil) s.machines = append(s.machines, machine) } // Create a FakeAuthorizer so we can check permissions, // set up assuming we logged in as the environment manager. s.authorizer = apiservertesting.FakeAuthorizer{ EnvironManager: true, } // Create the resource registry separately to track invocations to // Register, and to register the root for tools URLs. s.resources = common.NewResources() // Create a provisioner API for the machine. provisionerAPI, err := provisioner.NewProvisionerAPI( s.State, s.resources, s.authorizer, ) c.Assert(err, jc.ErrorIsNil) s.provisioner = provisionerAPI }
func (s *ImageMetadataSuite) TestMetadataFromState(c *gc.C) { api, err := provisioner.NewProvisionerAPI(s.State, s.resources, s.authorizer) c.Assert(err, jc.ErrorIsNil) expected := s.expectedDataSoureImageMetadata() // Write metadata to state. metadata := s.convertCloudImageMetadata(expected[0]) for _, m := range metadata { err := s.State.CloudImageMetadataStorage.SaveMetadata( []cloudimagemetadata.Metadata{m}, ) c.Assert(err, jc.ErrorIsNil) } result, err := api.ProvisioningInfo(s.getTestMachinesTags(c)) c.Assert(err, jc.ErrorIsNil) s.assertImageMetadataResults(c, result, 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 *provisionerSuite) setUpTest(c *gc.C, withStateServer bool) { s.JujuConnSuite.SetUpTest(c) // Reset previous machines (if any) and create 3 machines // for the tests, plus an optional state server machine. s.machines = nil // Note that the specific machine ids allocated are assumed // to be numerically consecutive from zero. if withStateServer { s.machines = append(s.machines, testing.AddStateServerMachine(c, s.State)) } for i := 0; i < 5; i++ { machine, err := s.State.AddMachine("quantal", state.JobHostUnits) c.Check(err, gc.IsNil) s.machines = append(s.machines, machine) } // Create a FakeAuthorizer so we can check permissions, // set up assuming we logged in as the environment manager. s.authorizer = apiservertesting.FakeAuthorizer{ EnvironManager: true, } // Create the resource registry separately to track invocations to // Register, and to register the root for tools URLs. s.resources = common.NewResources() // Create a provisioner API for the machine. provisionerAPI, err := provisioner.NewProvisionerAPI( s.State, s.resources, s.authorizer, ) c.Assert(err, gc.IsNil) s.provisioner = provisionerAPI }
func (s *containerSuite) newCustomAPI(c *gc.C, hostInstId instance.Id, addContainer, provisionContainer bool) *state.Machine { 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) s.provAPI = aProvisioner if hostInstId != "" { err = s.machines[0].SetProvisioned(hostInstId, "fake_nonce", nil) c.Assert(err, jc.ErrorIsNil) } if !addContainer { return nil } container, err := s.State.AddMachineInsideMachine( state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, }, s.machines[0].Id(), instance.LXC, ) c.Assert(err, jc.ErrorIsNil) if provisionContainer { password, err := utils.RandomPassword() c.Assert(err, jc.ErrorIsNil) err = container.SetPassword(password) c.Assert(err, jc.ErrorIsNil) err = container.SetProvisioned("foo", "fake_nonce", nil) c.Assert(err, jc.ErrorIsNil) } return container }
func (s *withoutStateServerSuite) TestLifeAsMachineAgent(c *gc.C) { // NOTE: This and the next call serve to test the two // different authorization schemes: // 1. Machine agents can access their own machine and // any container that has their own machine as parent; // 2. Environment managers can access any machine without // a parent. // There's no need to repeat this test for each method, // because the authorization logic is common. // 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, gc.IsNil) c.Assert(aProvisioner, gc.NotNil) // Make the machine dead before trying to add containers. err = s.machines[0].EnsureDead() c.Assert(err, gc.IsNil) // Create some containers to work on. template := state.MachineTemplate{ Series: "quantal", Jobs: []state.MachineJob{state.JobHostUnits}, } var containers []*state.Machine for i := 0; i < 3; i++ { container, err := s.State.AddMachineInsideMachine(template, s.machines[0].Id(), instance.LXC) c.Check(err, gc.IsNil) containers = append(containers, container) } // Make one container dead. err = containers[1].EnsureDead() c.Assert(err, gc.IsNil) args := params.Entities{Entities: []params.Entity{ {Tag: s.machines[0].Tag().String()}, {Tag: s.machines[1].Tag().String()}, {Tag: containers[0].Tag().String()}, {Tag: containers[1].Tag().String()}, {Tag: containers[2].Tag().String()}, {Tag: "machine-42"}, {Tag: "unit-foo-0"}, {Tag: "service-bar"}, }} result, err := aProvisioner.Life(args) c.Assert(err, gc.IsNil) c.Assert(result, gc.DeepEquals, params.LifeResults{ Results: []params.LifeResult{ {Life: "dead"}, {Error: apiservertesting.ErrUnauthorized}, {Life: "alive"}, {Life: "dead"}, {Life: "alive"}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, {Error: apiservertesting.ErrUnauthorized}, }, }) }