github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/romulus/sla/sla_test.go (about)

     1  // Copyright 2017 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package sla_test
     5  
     6  import (
     7  	stdtesting "testing"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/cmd/cmdtesting"
    11  	"github.com/juju/errors"
    12  	slawire "github.com/juju/romulus/wireformat/sla"
    13  	"github.com/juju/testing"
    14  	jujutesting "github.com/juju/testing"
    15  	jc "github.com/juju/testing/checkers"
    16  	"github.com/juju/utils"
    17  	gc "gopkg.in/check.v1"
    18  	"gopkg.in/juju/names.v2"
    19  	"gopkg.in/macaroon-bakery.v2-unstable/bakery"
    20  	"gopkg.in/macaroon-bakery.v2-unstable/bakery/checkers"
    21  	"gopkg.in/macaroon.v2-unstable"
    22  
    23  	"github.com/juju/juju/api"
    24  	rcmd "github.com/juju/juju/cmd/juju/romulus"
    25  	"github.com/juju/juju/cmd/juju/romulus/sla"
    26  	"github.com/juju/juju/cmd/modelcmd"
    27  	"github.com/juju/juju/jujuclient"
    28  )
    29  
    30  func TestPackage(t *stdtesting.T) {
    31  	gc.TestingT(t)
    32  }
    33  
    34  var _ = gc.Suite(&supportCommandSuite{})
    35  
    36  type supportCommandSuite struct {
    37  	jujutesting.CleanupSuite
    38  	mockAPI       *mockapi
    39  	mockSLAClient *mockSlaClient
    40  	fakeAPIRoot   *fakeAPIConnection
    41  	charmURL      string
    42  	modelUUID     string
    43  }
    44  
    45  func (s *supportCommandSuite) SetUpTest(c *gc.C) {
    46  	s.CleanupSuite.SetUpTest(c)
    47  	mockAPI, err := newMockAPI()
    48  	c.Assert(err, jc.ErrorIsNil)
    49  	s.mockAPI = mockAPI
    50  	s.mockSLAClient = &mockSlaClient{}
    51  	s.modelUUID = utils.MustNewUUID().String()
    52  	s.fakeAPIRoot = &fakeAPIConnection{model: s.modelUUID}
    53  	s.PatchValue(sla.NewJujuClientStore, s.newMockClientStore)
    54  	s.PatchValue(&rcmd.GetMeteringURLForModelCmd, func(c *modelcmd.ModelCommandBase) (string, error) {
    55  		return "http://example.com", nil
    56  	})
    57  }
    58  
    59  func (s *supportCommandSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
    60  	command := sla.NewSLACommandForTest(s.fakeAPIRoot, s.mockSLAClient, s.mockAPI)
    61  	command.SetClientStore(newMockStore())
    62  	return cmdtesting.RunCommand(c, command, args...)
    63  }
    64  
    65  func newMockStore() *jujuclient.MemStore {
    66  	store := jujuclient.NewMemStore()
    67  	store.CurrentControllerName = "foo"
    68  	store.Controllers["foo"] = jujuclient.ControllerDetails{
    69  		APIEndpoints: []string{"0.1.2.3:1234"},
    70  	}
    71  	store.Models["foo"] = &jujuclient.ControllerModels{
    72  		CurrentModel: "admin/bar",
    73  		Models:       map[string]jujuclient.ModelDetails{"admin/bar": {}},
    74  	}
    75  	return store
    76  }
    77  
    78  func (s supportCommandSuite) TestSupportCommand(c *gc.C) {
    79  	tests := []struct {
    80  		about    string
    81  		level    string
    82  		budget   string
    83  		err      string
    84  		apiErr   error
    85  		apiCalls []testing.StubCall
    86  	}{{
    87  		about: "all is well",
    88  		level: "essential",
    89  		apiCalls: []testing.StubCall{{
    90  			FuncName: "Authorize",
    91  			Args: []interface{}{
    92  				s.modelUUID,
    93  				"essential",
    94  				"",
    95  			},
    96  		}},
    97  	}, {
    98  		about:  "all is well with budget",
    99  		level:  "essential",
   100  		budget: "personal:10",
   101  		apiCalls: []testing.StubCall{{
   102  			FuncName: "Authorize",
   103  			Args: []interface{}{
   104  				s.modelUUID,
   105  				"essential",
   106  				"personal:10",
   107  			},
   108  		}},
   109  	},
   110  	}
   111  	for i, test := range tests {
   112  		c.Logf("running test %d: %v", i, test.about)
   113  		s.mockAPI.ResetCalls()
   114  		if test.apiErr != nil {
   115  			s.mockAPI.SetErrors(test.apiErr)
   116  		}
   117  		ctx, err := s.run(c, test.level, "--budget", test.budget)
   118  		if test.err == "" {
   119  			c.Assert(err, jc.ErrorIsNil)
   120  			c.Assert(s.mockAPI.Calls(), gc.HasLen, 1)
   121  			s.mockAPI.CheckCalls(c, test.apiCalls)
   122  			c.Assert(cmdtesting.Stdout(ctx), gc.Equals, `Model	SLA      	       Message
   123  c:m1 	essential	a test message
   124  `)
   125  		} else {
   126  			c.Assert(err, gc.ErrorMatches, test.err)
   127  		}
   128  	}
   129  }
   130  
   131  func (s *supportCommandSuite) TestDiplayCurrentLevel(c *gc.C) {
   132  	tests := []struct {
   133  		format         string
   134  		expectedOutput string
   135  	}{{
   136  		expectedOutput: `Model	SLA       	Message
   137  c:m1 	mock-level	       
   138  `,
   139  	}, {
   140  		format: "tabular",
   141  		expectedOutput: `Model	SLA       	Message
   142  c:m1 	mock-level	       
   143  `,
   144  	}, {
   145  		format: "json",
   146  		expectedOutput: `{"model":"c:m1","sla":"mock-level"}
   147  `,
   148  	}, {
   149  		format: "yaml",
   150  		expectedOutput: `model: c:m1
   151  sla: mock-level
   152  `,
   153  	},
   154  	}
   155  
   156  	for i, test := range tests {
   157  		c.Logf("running test %d", i)
   158  		args := []string{}
   159  		if test.format != "" {
   160  			args = append(args, "--format", test.format)
   161  		}
   162  		ctx, err := s.run(c, args...)
   163  		c.Assert(err, jc.ErrorIsNil, gc.Commentf("%s", errors.Details(err)))
   164  		c.Assert(cmdtesting.Stdout(ctx), jc.DeepEquals, test.expectedOutput)
   165  	}
   166  }
   167  
   168  func newMockAPI() (*mockapi, error) {
   169  	kp, err := bakery.GenerateKey()
   170  	if err != nil {
   171  		return nil, errors.Trace(err)
   172  	}
   173  	svc, err := bakery.NewService(bakery.NewServiceParams{
   174  		Location: "omnibus",
   175  		Key:      kp,
   176  	})
   177  	if err != nil {
   178  		return nil, errors.Trace(err)
   179  	}
   180  	return &mockapi{
   181  		service: svc,
   182  	}, nil
   183  }
   184  
   185  type mockapi struct {
   186  	testing.Stub
   187  
   188  	service  *bakery.Service
   189  	macaroon *macaroon.Macaroon
   190  }
   191  
   192  func (m *mockapi) Authorize(modelUUID, supportLevel, budget string) (*slawire.SLAResponse, error) {
   193  	err := m.NextErr()
   194  	if err != nil {
   195  		return nil, errors.Trace(err)
   196  	}
   197  	m.AddCall("Authorize", modelUUID, supportLevel, budget)
   198  	macaroon, err := m.service.NewMacaroon([]checkers.Caveat{})
   199  	if err != nil {
   200  		return nil, errors.Trace(err)
   201  	}
   202  	m.macaroon = macaroon
   203  	return &slawire.SLAResponse{
   204  		Credentials: m.macaroon,
   205  		Owner:       "bob",
   206  		Message:     "a test message",
   207  	}, nil
   208  }
   209  
   210  type mockSlaClient struct {
   211  	testing.Stub
   212  }
   213  
   214  func (m *mockSlaClient) SetSLALevel(level, owner string, creds []byte) error {
   215  	m.AddCall("SetSLALevel", level, owner, creds)
   216  	return nil
   217  }
   218  func (m *mockSlaClient) SLALevel() (string, error) {
   219  	m.AddCall("SLALevel")
   220  	return "mock-level", nil
   221  }
   222  
   223  type fakeAPIConnection struct {
   224  	api.Connection
   225  	model string
   226  }
   227  
   228  func (f *fakeAPIConnection) BestFacadeVersion(facade string) int {
   229  	return 2
   230  }
   231  
   232  func (f *fakeAPIConnection) ModelTag() (names.ModelTag, bool) {
   233  	return names.NewModelTag(f.model), false
   234  }
   235  
   236  type mockClientStore struct {
   237  	jujuclient.ClientStore
   238  	modelUUID string
   239  }
   240  
   241  func (s *supportCommandSuite) newMockClientStore() jujuclient.ClientStore {
   242  	return &mockClientStore{modelUUID: s.modelUUID}
   243  }
   244  
   245  func (s *mockClientStore) AllControllers() (map[string]jujuclient.ControllerDetails, error) {
   246  	return map[string]jujuclient.ControllerDetails{
   247  		"c": {},
   248  	}, nil
   249  }
   250  
   251  func (s *mockClientStore) AllModels(controllerName string) (map[string]jujuclient.ModelDetails, error) {
   252  	return map[string]jujuclient.ModelDetails{
   253  		"m1": {ModelUUID: s.modelUUID},
   254  		"m2": {ModelUUID: "uuid2"},
   255  		"m3": {ModelUUID: "uuid3"},
   256  	}, nil
   257  }