Skip to content

Commit

Permalink
Merge 2.1 into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
jameinel committed Feb 12, 2017
2 parents 94553f7 + 7384af8 commit 1bc7012
Show file tree
Hide file tree
Showing 97 changed files with 1,159 additions and 718 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,22 @@ Building Juju as a Snap Package

Building
--------
This requires the godeps plugin -- make sure your snapcraft version is > 2.13.1. Run snapcraft at the root of the repository. A snap will build.
Make sure your snapcraft version is >= 2.26. Run snapcraft at the root of the repository. A snap will build.

Current State
-------------
Not confined. Credentials are not shared with a debian packaged juju, and any installed juju's will own `juju` on your `$PATH` over the snap.
Classic mode.

Known Issues
------------
None. The snap shares your current credentials and environments as expected with a debian installed version.

Needed for confinement
----------------------
To enable strict mode, the following bugs need to be resolved, and the snap updated accordingly.

* Missing support for abstract unix sockets (https://bugs.launchpad.net/snappy/+bug/1604967)
* Needs SSH interface (https://bugs.launchpad.net/snappy/+bug/1606574)
* Bash completion doesn't work (https://launchpad.net/bugs/1612303)
* Juju plugin support (https://bugs.launchpad.net/juju/+bug/1628538)

Expand Down
12 changes: 12 additions & 0 deletions api/migrationtarget/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,15 @@ func (c *Client) LatestLogTime(modelUUID string) (time.Time, error) {
}
return result, nil
}

// AdoptResources asks the cloud provider to update the controller
// tags for a model's resources. This prevents the resources from
// being destroyed if the source controller is destroyed after the
// model is migrated away.
func (c *Client) AdoptResources(modelUUID string) error {
args := params.AdoptResourcesArgs{
ModelTag: names.NewModelTag(modelUUID).String(),
SourceControllerVersion: jujuversion.Current,
}
return errors.Trace(c.caller.FacadeCall("AdoptResources", args, nil))
}
10 changes: 10 additions & 0 deletions api/migrationtarget/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ func (s *ClientSuite) TestLatestLogTimeError(c *gc.C) {
s.AssertModelCall(c, stub, names.NewModelTag("fake"), "LatestLogTime", err, true)
}

func (s *ClientSuite) TestAdoptResources(c *gc.C) {
client, stub := s.getClientAndStub(c)
err := client.AdoptResources("the-model")
c.Assert(err, gc.ErrorMatches, "boom")
stub.CheckCall(c, 0, "MigrationTarget.AdoptResources", "", params.AdoptResourcesArgs{
ModelTag: "model-the-model",
SourceControllerVersion: jujuversion.Current,
})
}

func (s *ClientSuite) TestUploadCharm(c *gc.C) {
const charmBody = "charming"
curl := charm.MustParseURL("cs:~user/foo-2")
Expand Down
27 changes: 17 additions & 10 deletions apiserver/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,6 @@ func (a *admin) login(req params.LoginRequest, loginVersion int) (params.LoginRe
func (a *admin) checkUserPermissions(userTag names.UserTag, controllerOnlyLogin bool) (*params.AuthUserInfo, error) {

modelAccess := permission.NoAccess
if !controllerOnlyLogin {
// Only grab modelUser permissions if this is not a controller only
// login. In all situations, if the model user is not found, they have
// no authorisation to access this model.
modelUser, err := a.root.state.UserAccess(userTag, a.root.state.ModelTag())
if err != nil {
return nil, errors.Wrap(err, common.ErrPerm)
}
modelAccess = modelUser.Access
}

// TODO(perrito666) remove the following section about everyone group
// when groups are implemented, this accounts only for the lack of a local
Expand All @@ -247,6 +237,23 @@ func (a *admin) checkUserPermissions(userTag names.UserTag, controllerOnlyLogin
} else {
return nil, errors.Annotatef(err, "obtaining ControllerUser for logged in user %s", userTag.Id())
}
if !controllerOnlyLogin {
// Only grab modelUser permissions if this is not a controller only
// login. In all situations, if the model user is not found, they have
// no authorisation to access this model, unless the user is controller
// admin.

modelUser, err := a.root.state.UserAccess(userTag, a.root.state.ModelTag())
if err != nil && controllerAccess != permission.SuperuserAccess {
return nil, errors.Wrap(err, common.ErrPerm)
}
if err != nil && controllerAccess == permission.SuperuserAccess {
modelAccess = permission.AdminAccess
} else {
modelAccess = modelUser.Access
}
}

// It is possible that the everyoneGroup permissions are more capable than an
// individuals. If they are, use them.
if everyoneGroupAccess.GreaterControllerAccessThan(controllerAccess) {
Expand Down
6 changes: 3 additions & 3 deletions apiserver/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (api *AgentAPIV2) getEntity(tag names.Tag) (result params.AgentGetEntitiesR
}

func (api *AgentAPIV2) StateServingInfo() (result params.StateServingInfo, err error) {
if !api.auth.AuthModelManager() {
if !api.auth.AuthController() {
err = common.ErrPerm
return
}
Expand All @@ -131,7 +131,7 @@ func (api *AgentAPIV2) StateServingInfo() (result params.StateServingInfo, err e
var MongoIsMaster = mongo.IsMaster

func (api *AgentAPIV2) IsMaster() (params.IsMasterResult, error) {
if !api.auth.AuthModelManager() {
if !api.auth.AuthController() {
return params.IsMasterResult{}, common.ErrPerm
}

Expand Down Expand Up @@ -160,7 +160,7 @@ func stateJobsToAPIParamsJobs(jobs []state.MachineJob) []multiwatcher.MachineJob

// WatchCredentials watches for changes to the specified credentials.
func (api *AgentAPIV2) WatchCredentials(args params.Entities) (params.NotifyWatchResults, error) {
if !api.auth.AuthModelManager() {
if !api.auth.AuthController() {
return params.NotifyWatchResults{}, common.ErrPerm
}

Expand Down
8 changes: 4 additions & 4 deletions apiserver/agent/agent_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,8 @@ func (s *agentSuite) TestClearReboot(c *gc.C) {

func (s *agentSuite) TestWatchCredentials(c *gc.C) {
authorizer := apiservertesting.FakeAuthorizer{
Tag: names.NewMachineTag("0"),
EnvironManager: true,
Tag: names.NewMachineTag("0"),
Controller: true,
}
api, err := agent.NewAgentAPIV2(s.State, s.resources, authorizer)
c.Assert(err, jc.ErrorIsNil)
Expand All @@ -267,8 +267,8 @@ func (s *agentSuite) TestWatchCredentials(c *gc.C) {

func (s *agentSuite) TestWatchAuthError(c *gc.C) {
authorizer := apiservertesting.FakeAuthorizer{
Tag: names.NewMachineTag("1"),
EnvironManager: false,
Tag: names.NewMachineTag("1"),
Controller: false,
}
api, err := agent.NewAgentAPIV2(s.State, s.resources, authorizer)
c.Assert(err, jc.ErrorIsNil)
Expand Down
2 changes: 1 addition & 1 deletion apiserver/agenttools/agenttools.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func updateToolsAvailability(modelGetter ModelGetter, newEnviron newEnvironFunc,
// UpdateToolsAvailable invokes a lookup and further update in environ
// for new patches of the current tool versions.
func (api *AgentToolsAPI) UpdateToolsAvailable() error {
if !api.authorizer.AuthModelManager() {
if !api.authorizer.AuthController() {
return common.ErrPerm
}
return updateToolsAvailability(api.modelGetter, api.newEnviron, api.findTools, api.envVersionUpdate)
Expand Down
2 changes: 1 addition & 1 deletion apiserver/applicationscaler/facade.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Facade struct {

// NewFacade creates a new authorized Facade.
func NewFacade(backend Backend, res facade.Resources, auth facade.Authorizer) (*Facade, error) {
if !auth.AuthModelManager() {
if !auth.AuthController() {
return nil, common.ErrPerm
}
return &Facade{
Expand Down
2 changes: 1 addition & 1 deletion apiserver/applicationscaler/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type mockAuth struct {
modelManager bool
}

func (mock mockAuth) AuthModelManager() bool {
func (mock mockAuth) AuthController() bool {
return mock.modelManager
}

Expand Down
4 changes: 2 additions & 2 deletions apiserver/block/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func (s *blockSuite) SetUpTest(c *gc.C) {

var err error
auth := testing.FakeAuthorizer{
Tag: s.AdminUserTag(c),
EnvironManager: true,
Tag: s.AdminUserTag(c),
Controller: true,
}
s.api, err = block.NewAPI(s.State, common.NewResources(), auth)
c.Assert(err, jc.ErrorIsNil)
Expand Down
2 changes: 1 addition & 1 deletion apiserver/charmrevisionupdater/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func NewCharmRevisionUpdaterAPI(
resources facade.Resources,
authorizer facade.Authorizer,
) (*CharmRevisionUpdaterAPI, error) {
if !authorizer.AuthMachineAgent() && !authorizer.AuthModelManager() {
if !authorizer.AuthMachineAgent() && !authorizer.AuthController() {
return nil, common.ErrPerm
}
return &CharmRevisionUpdaterAPI{
Expand Down
4 changes: 2 additions & 2 deletions apiserver/charmrevisionupdater/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (s *charmVersionSuite) SetUpTest(c *gc.C) {
s.resources = common.NewResources()
s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
s.authoriser = apiservertesting.FakeAuthorizer{
EnvironManager: true,
Controller: true,
}
var err error
s.charmrevisionupdater, err = charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, s.authoriser)
Expand All @@ -71,7 +71,7 @@ func (s *charmVersionSuite) TestNewCharmRevisionUpdaterAPIAcceptsStateManager(c

func (s *charmVersionSuite) TestNewCharmRevisionUpdaterAPIRefusesNonStateManager(c *gc.C) {
anAuthoriser := s.authoriser
anAuthoriser.EnvironManager = false
anAuthoriser.Controller = false
endPoint, err := charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, anAuthoriser)
c.Assert(endPoint, gc.IsNil)
c.Assert(err, gc.ErrorMatches, "permission denied")
Expand Down
4 changes: 2 additions & 2 deletions apiserver/charms/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ func (s *charmsSuite) SetUpTest(c *gc.C) {

var err error
auth := testing.FakeAuthorizer{
Tag: s.AdminUserTag(c),
EnvironManager: true,
Tag: s.AdminUserTag(c),
Controller: true,
}
s.api, err = charms.NewAPI(s.State, common.NewResources(), auth)
c.Assert(err, jc.ErrorIsNil)
Expand Down
2 changes: 1 addition & 1 deletion apiserver/cleaner/cleaner.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewCleanerAPI(
res facade.Resources,
authorizer facade.Authorizer,
) (*CleanerAPI, error) {
if !authorizer.AuthModelManager() {
if !authorizer.AuthController() {
return nil, common.ErrPerm
}
return &CleanerAPI{
Expand Down
4 changes: 2 additions & 2 deletions apiserver/cleaner/cleaner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (s *CleanerSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetUpTest(c)

s.authoriser = apiservertesting.FakeAuthorizer{
EnvironManager: true,
Controller: true,
}
s.st = &mockState{&testing.Stub{}, false}
cleaner.PatchState(s, s.st)
Expand All @@ -44,7 +44,7 @@ func (s *CleanerSuite) SetUpTest(c *gc.C) {

func (s *CleanerSuite) TestNewCleanerAPIRequiresEnvironManager(c *gc.C) {
anAuthoriser := s.authoriser
anAuthoriser.EnvironManager = false
anAuthoriser.Controller = false
api, err := cleaner.NewCleanerAPI(nil, nil, anAuthoriser)
c.Assert(api, gc.IsNil)
c.Assert(err, gc.ErrorMatches, "permission denied")
Expand Down
1 change: 1 addition & 0 deletions apiserver/client/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type Backend interface {
Application(string) (*state.Application, error)
ApplicationLeaders() (map[string]string, error)
Charm(*charm.URL) (*state.Charm, error)
ControllerTag() names.ControllerTag
EndpointsRelation(...state.Endpoint) (*state.Relation, error)
FindEntity(names.Tag) (state.Entity, error)
ForModel(tag names.ModelTag) (*state.State, error)
Expand Down
14 changes: 12 additions & 2 deletions apiserver/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,22 +65,32 @@ type Client struct {
}

func (c *Client) checkCanRead() error {
isAdmin, err := c.api.auth.HasPermission(permission.SuperuserAccess, c.api.stateAccessor.ControllerTag())
if err != nil {
return errors.Trace(err)
}

canRead, err := c.api.auth.HasPermission(permission.ReadAccess, c.api.stateAccessor.ModelTag())
if err != nil {
return errors.Trace(err)
}
if !canRead {
if !canRead && !isAdmin {
return common.ErrPerm
}
return nil
}

func (c *Client) checkCanWrite() error {
isAdmin, err := c.api.auth.HasPermission(permission.SuperuserAccess, c.api.stateAccessor.ControllerTag())
if err != nil {
return errors.Trace(err)
}

canWrite, err := c.api.auth.HasPermission(permission.WriteAccess, c.api.stateAccessor.ModelTag())
if err != nil {
return errors.Trace(err)
}
if !canWrite {
if !canWrite && !isAdmin {
return common.ErrPerm
}
return nil
Expand Down
4 changes: 2 additions & 2 deletions apiserver/client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ func (s *serverSuite) SetUpTest(c *gc.C) {

func (s *serverSuite) clientForState(c *gc.C, st *state.State) *client.Client {
auth := testing.FakeAuthorizer{
Tag: s.AdminUserTag(c),
EnvironManager: true,
Tag: s.AdminUserTag(c),
Controller: true,
}
urlGetter := common.NewToolsURLGetter(st.ModelUUID(), st)
configGetter := stateenvirons.EnvironConfigGetter{st}
Expand Down
2 changes: 1 addition & 1 deletion apiserver/client/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ func (s *statusUpgradeUnitSuite) SetUpTest(c *gc.C) {
s.resources = common.NewResources()
s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })
s.authoriser = apiservertesting.FakeAuthorizer{
EnvironManager: true,
Controller: true,
}
var err error
s.charmrevisionupdater, err = charmrevisionupdater.NewCharmRevisionUpdaterAPI(s.State, s.resources, s.authoriser)
Expand Down
4 changes: 4 additions & 0 deletions apiserver/client/statushistory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ func (m *mockState) ModelTag() names.ModelTag {
return names.NewModelTag("deadbeef-0bad-400d-8000-4b1d0d06f00d")
}

func (m *mockState) ControllerTag() names.ControllerTag {
return names.NewControllerTag("deadbeef-0bad-400d-8000-4b1d0d06f00d")
}

func (m *mockState) Unit(name string) (client.Unit, error) {
if name != "unit/0" {
return nil, errors.NotFoundf("%v", name)
Expand Down
2 changes: 1 addition & 1 deletion apiserver/cloud/instance_information_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (p *instanceTypesSuite) TestInstanceTypes(c *gc.C) {
cloudSpec: environs.CloudSpec{},
}
authorizer := testing.FakeAuthorizer{Tag: names.NewUserTag("admin"),
EnvironManager: true}
Controller: true}
itCons := constraints.Value{CpuCores: &over9kCPUCores}
failureCons := constraints.Value{}
env := mockEnviron{
Expand Down
2 changes: 1 addition & 1 deletion apiserver/common/modelmachineswatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NewModelMachinesWatcher(st state.ModelMachinesWatcher, resources facade.Res
// model.
func (e *ModelMachinesWatcher) WatchModelMachines() (params.StringsWatchResult, error) {
result := params.StringsWatchResult{}
if !e.authorizer.AuthModelManager() {
if !e.authorizer.AuthController() {
return result, ErrPerm
}
watch := e.st.WatchModelMachines()
Expand Down
8 changes: 4 additions & 4 deletions apiserver/common/modelmachineswatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ func (f *fakeModelMachinesWatcher) WatchModelMachines() state.StringsWatcher {

func (s *modelMachinesWatcherSuite) TestWatchModelMachines(c *gc.C) {
authorizer := apiservertesting.FakeAuthorizer{
Tag: names.NewMachineTag("0"),
EnvironManager: true,
Tag: names.NewMachineTag("0"),
Controller: true,
}
resources := common.NewResources()
s.AddCleanup(func(_ *gc.C) { resources.StopAll() })
Expand All @@ -53,8 +53,8 @@ func (s *modelMachinesWatcherSuite) TestWatchModelMachines(c *gc.C) {

func (s *modelMachinesWatcherSuite) TestWatchAuthError(c *gc.C) {
authorizer := apiservertesting.FakeAuthorizer{
Tag: names.NewMachineTag("1"),
EnvironManager: false,
Tag: names.NewMachineTag("1"),
Controller: false,
}
resources := common.NewResources()
s.AddCleanup(func(_ *gc.C) { resources.StopAll() })
Expand Down
Loading

0 comments on commit 1bc7012

Please sign in to comment.