Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for caas namespaces #8441

Merged
merged 1 commit into from
Mar 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 53 additions & 0 deletions api/caasagent/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent

import (
"github.com/juju/errors"
"gopkg.in/juju/names.v2"

"github.com/juju/juju/api/base"
"github.com/juju/juju/api/common/cloudspec"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/core/model"
)

// Client provides access to an agent's view of state.
type Client struct {
facade base.FacadeCaller
*cloudspec.CloudSpecAPI
}

// NewClient returns a version of an api client that provides functionality
// required by caas agent code.
func NewClient(caller base.APICaller) (*Client, error) {
modelTag, isModel := caller.ModelTag()
if !isModel {
return nil, errors.New("expected model specific API connection")
}
facadeCaller := base.NewFacadeCaller(caller, "CAASAgent")
return &Client{
facade: facadeCaller,
CloudSpecAPI: cloudspec.NewCloudSpecAPI(facadeCaller, modelTag),
}, nil
}

// Model returns details of the api's model.
func (st *Client) Model() (*model.Model, error) {
var result params.Model
err := st.facade.FacadeCall("Model", nil, &result)
if err != nil {
return nil, errors.Trace(err)
}
owner, err := names.ParseUserTag(result.OwnerTag)
if err != nil {
return nil, errors.Trace(err)
}
return &model.Model{
Name: result.Name,
Type: model.ModelType(result.Type),
UUID: result.UUID,
Owner: owner,
}, nil
}
52 changes: 52 additions & 0 deletions api/caasagent/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent_test

import (
"github.com/juju/testing"
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
"gopkg.in/juju/names.v2"

basetesting "github.com/juju/juju/api/base/testing"
"github.com/juju/juju/api/caasagent"
"github.com/juju/juju/apiserver/params"
"github.com/juju/juju/core/model"
coretesting "github.com/juju/juju/testing"
)

type agentSuite struct {
testing.IsolationSuite
}

var _ = gc.Suite(&agentSuite{})

func (s *agentSuite) TestModel(c *gc.C) {
apiCaller := basetesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
c.Check(objType, gc.Equals, "CAASAgent")
c.Check(version, gc.Equals, 0)
c.Check(id, gc.Equals, "")
c.Check(request, gc.Equals, "Model")
c.Check(arg, gc.IsNil)
c.Assert(result, gc.FitsTypeOf, &params.Model{})
*(result.(*params.Model)) = params.Model{
Name: "mymodel",
UUID: coretesting.ModelTag.Id(),
Type: "iaas",
OwnerTag: "user-fred",
}
return nil
})

client, err := caasagent.NewClient(apiCaller)
c.Assert(err, jc.ErrorIsNil)
result, err := client.Model()
c.Assert(err, jc.ErrorIsNil)
c.Assert(result, jc.DeepEquals, &model.Model{
Name: "mymodel",
UUID: coretesting.ModelTag.Id(),
Type: "iaas",
Owner: names.NewUserTag("fred"),
})
}
14 changes: 14 additions & 0 deletions api/caasagent/package_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent_test

import (
"testing"

gc "gopkg.in/check.v1"
)

func TestAll(t *testing.T) {
gc.TestingT(t)
}
1 change: 1 addition & 0 deletions api/facadeversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var facadeVersions = map[string]int{
"Backups": 1,
"Block": 2,
"Bundle": 1,
"CAASAgent": 1,
"CAASFirewaller": 1,
"CAASOperator": 1,
"CAASOperatorProvisioner": 1,
Expand Down
2 changes: 2 additions & 0 deletions apiserver/allfacades.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/facade"
"github.com/juju/juju/apiserver/facades/agent/agent" // ModelUser Write
"github.com/juju/juju/apiserver/facades/agent/caasagent"
"github.com/juju/juju/apiserver/facades/agent/caasoperator"
"github.com/juju/juju/apiserver/facades/agent/deployer"
"github.com/juju/juju/apiserver/facades/agent/diskmanager"
Expand Down Expand Up @@ -154,6 +155,7 @@ func AllFacades() *facade.Registry {
reg("Application", 6, application.NewFacadeV6)
reg("CAASFirewaller", 1, caasfirewaller.NewStateFacade)
reg("CAASOperator", 1, caasoperator.NewStateFacade)
reg("CAASAgent", 1, caasagent.NewStateFacade)
reg("CAASOperatorProvisioner", 1, caasoperatorprovisioner.NewStateCAASOperatorProvisionerAPI)
reg("CAASUnitProvisioner", 1, caasunitprovisioner.NewStateFacade)
}
Expand Down
67 changes: 67 additions & 0 deletions apiserver/facades/agent/caasagent/caasagent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent

import (
"github.com/juju/errors"

"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/common/cloudspec"
"github.com/juju/juju/apiserver/facade"
"github.com/juju/juju/apiserver/params"
)

type Facade struct {
auth facade.Authorizer
resources facade.Resources
state CAASAgentState
cloudspec.CloudSpecAPI

model Model
}

// NewStateFacade provides the signature required for facade registration.
func NewStateFacade(ctx facade.Context) (*Facade, error) {
authorizer := ctx.Auth()
resources := ctx.Resources()
model, err := ctx.State().Model()
if err != nil {
return nil, errors.Trace(err)
}
cloudSpecAPI := cloudspec.NewCloudSpec(
cloudspec.MakeCloudSpecGetterForModel(ctx.State()),
common.AuthFuncForTag(model.ModelTag()),
)
return NewFacade(resources, authorizer, stateShim{ctx.State()}, cloudSpecAPI, model)
}

// NewFacade returns a new CAASAgent facade.
func NewFacade(
resources facade.Resources,
authorizer facade.Authorizer,
st CAASAgentState,
cloudSpecAPI cloudspec.CloudSpecAPI,
model Model,
) (*Facade, error) {
if !authorizer.AuthMachineAgent() {
return nil, common.ErrPerm
}
return &Facade{
CloudSpecAPI: cloudSpecAPI,
auth: authorizer,
resources: resources,
state: st,
model: model,
}, nil
}

// Model returns the details about the model.
func (f *Facade) Model() (params.Model, error) {
return params.Model{
Name: f.model.Name(),
Type: string(f.model.Type()),
UUID: f.model.UUID(),
OwnerTag: f.model.Owner().String(),
}, nil
}
67 changes: 67 additions & 0 deletions apiserver/facades/agent/caasagent/caasagent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent_test

import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
"gopkg.in/juju/names.v2"

"github.com/juju/juju/apiserver/common"
"github.com/juju/juju/apiserver/facades/agent/caasagent"
"github.com/juju/juju/apiserver/params"
apiservertesting "github.com/juju/juju/apiserver/testing"
coretesting "github.com/juju/juju/testing"
)

var _ = gc.Suite(&caasagentSuite{})

type caasagentSuite struct {
coretesting.BaseSuite

resources *common.Resources
authorizer *apiservertesting.FakeAuthorizer
facade *caasagent.Facade
st *mockState
}

func (s *caasagentSuite) SetUpTest(c *gc.C) {
s.BaseSuite.SetUpTest(c)

s.resources = common.NewResources()
s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() })

s.authorizer = &apiservertesting.FakeAuthorizer{
Tag: names.NewMachineTag("0"),
}

s.st = &mockState{}
model, err := s.st.Model()
c.Assert(err, jc.ErrorIsNil)

facade, err := caasagent.NewFacade(s.resources, s.authorizer, s.st, nil, model)
c.Assert(err, jc.ErrorIsNil)
s.facade = facade
}

func (s *caasagentSuite) TestPermission(c *gc.C) {
s.authorizer = &apiservertesting.FakeAuthorizer{
Tag: names.NewApplicationTag("someapp"),
}
_, err := caasagent.NewFacade(s.resources, s.authorizer, s.st, nil, nil)
c.Assert(err, gc.ErrorMatches, "permission denied")
}

func (s *caasagentSuite) TestModel(c *gc.C) {
result, err := s.facade.Model()
c.Assert(err, jc.ErrorIsNil)
c.Assert(result, jc.DeepEquals, params.Model{
Name: "some-model",
UUID: coretesting.ModelTag.Id(),
Type: "caas",
OwnerTag: "user-fred",
})

s.st.CheckCallNames(c, "Model")
}
50 changes: 50 additions & 0 deletions apiserver/facades/agent/caasagent/mock_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent_test

import (
"github.com/juju/testing"
"gopkg.in/juju/names.v2"

"github.com/juju/juju/apiserver/facades/agent/caasagent"
"github.com/juju/juju/state"
coretesting "github.com/juju/juju/testing"
)

type mockState struct {
testing.Stub
model mockModel
}

func (st *mockState) Model() (caasagent.Model, error) {
st.MethodCall(st, "Model")
if err := st.NextErr(); err != nil {
return nil, err
}
return &st.model, nil
}

type mockModel struct {
testing.Stub
}

func (st *mockModel) Name() string {
return "some-model"
}

func (st *mockModel) UUID() string {
return coretesting.ModelTag.Id()
}

func (st *mockModel) Type() state.ModelType {
return state.ModelTypeCAAS
}

func (st *mockModel) Owner() names.UserTag {
return names.NewUserTag("fred")
}

func (st *mockModel) ModelTag() names.ModelTag {
return coretesting.ModelTag
}
14 changes: 14 additions & 0 deletions apiserver/facades/agent/caasagent/package_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent_test

import (
"testing"

gc "gopkg.in/check.v1"
)

func TestAll(t *testing.T) {
gc.TestingT(t)
}
33 changes: 33 additions & 0 deletions apiserver/facades/agent/caasagent/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package caasagent

import (
"github.com/juju/juju/state"
"gopkg.in/juju/names.v2"
)

// CAASAgentState provides the subset of global state
// required by the CAAS agent facade.
type CAASAgentState interface {
Model() (Model, error)
}

// Model provides the subset of CAAS model state required
// by the CAAS agent facade.
type Model interface {
Name() string
UUID() string
Type() state.ModelType
Owner() names.UserTag
ModelTag() names.ModelTag
}

type stateShim struct {
*state.State
}

func (st stateShim) Model() (Model, error) {
return st.State.Model()
}
1 change: 1 addition & 0 deletions apiserver/restrict_caasmodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ var commonModelFacadeNames = set.NewStrings(
// caasModelFacadeNames lists facades that are only used with CAAS
// models.
var caasModelFacadeNames = set.NewStrings(
"CAASAgent",
"CAASFirewaller",
"CAASOperator",
"CAASOperatorProvisioner",
Expand Down