github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/api/controller/controller_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package controller_test
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/names.v2"
    13  	"gopkg.in/macaroon.v1"
    14  
    15  	apitesting "github.com/juju/juju/api/base/testing"
    16  	"github.com/juju/juju/api/controller"
    17  	"github.com/juju/juju/apiserver/common"
    18  	"github.com/juju/juju/apiserver/params"
    19  	"github.com/juju/juju/environs"
    20  	jujutesting "github.com/juju/testing"
    21  	"github.com/juju/utils"
    22  )
    23  
    24  type Suite struct {
    25  	jujutesting.IsolationSuite
    26  }
    27  
    28  var _ = gc.Suite(&Suite{})
    29  
    30  func (s *Suite) TestInitiateMigration(c *gc.C) {
    31  	s.checkInitiateMigration(c, makeSpec())
    32  }
    33  
    34  func (s *Suite) TestInitiateMigrationExternalControl(c *gc.C) {
    35  	spec := makeSpec()
    36  	spec.ExternalControl = true
    37  	s.checkInitiateMigration(c, spec)
    38  }
    39  
    40  func (s *Suite) TestInitiateMigrationSkipPrechecks(c *gc.C) {
    41  	spec := makeSpec()
    42  	spec.SkipInitialPrechecks = true
    43  	s.checkInitiateMigration(c, spec)
    44  }
    45  
    46  func (s *Suite) checkInitiateMigration(c *gc.C, spec controller.MigrationSpec) {
    47  	client, stub := makeClient(params.InitiateMigrationResults{
    48  		Results: []params.InitiateMigrationResult{{
    49  			MigrationId: "id",
    50  		}},
    51  	})
    52  	id, err := client.InitiateMigration(spec)
    53  	c.Assert(err, jc.ErrorIsNil)
    54  	c.Check(id, gc.Equals, "id")
    55  	stub.CheckCalls(c, []jujutesting.StubCall{
    56  		{"Controller.InitiateMigration", []interface{}{specToArgs(spec)}},
    57  	})
    58  }
    59  
    60  func specToArgs(spec controller.MigrationSpec) params.InitiateMigrationArgs {
    61  	var macsJSON []byte
    62  	if len(spec.TargetMacaroons) > 0 {
    63  		var err error
    64  		macsJSON, err = json.Marshal(spec.TargetMacaroons)
    65  		if err != nil {
    66  			panic(err)
    67  		}
    68  	}
    69  	return params.InitiateMigrationArgs{
    70  		Specs: []params.MigrationSpec{{
    71  			ModelTag: names.NewModelTag(spec.ModelUUID).String(),
    72  			TargetInfo: params.MigrationTargetInfo{
    73  				ControllerTag: names.NewControllerTag(spec.TargetControllerUUID).String(),
    74  				Addrs:         spec.TargetAddrs,
    75  				CACert:        spec.TargetCACert,
    76  				AuthTag:       names.NewUserTag(spec.TargetUser).String(),
    77  				Password:      spec.TargetPassword,
    78  				Macaroons:     string(macsJSON),
    79  			},
    80  			ExternalControl:      spec.ExternalControl,
    81  			SkipInitialPrechecks: spec.SkipInitialPrechecks,
    82  		}},
    83  	}
    84  }
    85  
    86  func (s *Suite) TestInitiateMigrationError(c *gc.C) {
    87  	client, _ := makeClient(params.InitiateMigrationResults{
    88  		Results: []params.InitiateMigrationResult{{
    89  			Error: common.ServerError(errors.New("boom")),
    90  		}},
    91  	})
    92  	id, err := client.InitiateMigration(makeSpec())
    93  	c.Check(id, gc.Equals, "")
    94  	c.Check(err, gc.ErrorMatches, "boom")
    95  }
    96  
    97  func (s *Suite) TestInitiateMigrationResultMismatch(c *gc.C) {
    98  	client, _ := makeClient(params.InitiateMigrationResults{
    99  		Results: []params.InitiateMigrationResult{
   100  			{MigrationId: "id"},
   101  			{MigrationId: "wtf"},
   102  		},
   103  	})
   104  	id, err := client.InitiateMigration(makeSpec())
   105  	c.Check(id, gc.Equals, "")
   106  	c.Check(err, gc.ErrorMatches, "unexpected number of results returned")
   107  }
   108  
   109  func (s *Suite) TestInitiateMigrationCallError(c *gc.C) {
   110  	apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error {
   111  		return errors.New("boom")
   112  	})
   113  	client := controller.NewClient(apiCaller)
   114  	id, err := client.InitiateMigration(makeSpec())
   115  	c.Check(id, gc.Equals, "")
   116  	c.Check(err, gc.ErrorMatches, "boom")
   117  }
   118  
   119  func (s *Suite) TestInitiateMigrationValidationError(c *gc.C) {
   120  	client, stub := makeClient(params.InitiateMigrationResults{})
   121  	spec := makeSpec()
   122  	spec.ModelUUID = "not-a-uuid"
   123  	id, err := client.InitiateMigration(spec)
   124  	c.Check(id, gc.Equals, "")
   125  	c.Check(err, gc.ErrorMatches, "model UUID not valid")
   126  	c.Check(stub.Calls(), gc.HasLen, 0) // API call shouldn't have happened
   127  }
   128  
   129  func (s *Suite) TestHostedModelConfigs_CallError(c *gc.C) {
   130  	apiCaller := apitesting.APICallerFunc(func(string, int, string, string, interface{}, interface{}) error {
   131  		return errors.New("boom")
   132  	})
   133  	client := controller.NewClient(apiCaller)
   134  	config, err := client.HostedModelConfigs()
   135  	c.Check(config, gc.HasLen, 0)
   136  	c.Check(err, gc.ErrorMatches, "boom")
   137  }
   138  
   139  func (s *Suite) TestHostedModelConfigs_FormatResults(c *gc.C) {
   140  	apiCaller := apitesting.APICallerFunc(func(objType string, version int, id, request string, arg, result interface{}) error {
   141  		c.Assert(objType, gc.Equals, "Controller")
   142  		c.Assert(request, gc.Equals, "HostedModelConfigs")
   143  		c.Assert(arg, gc.IsNil)
   144  		out := result.(*params.HostedModelConfigsResults)
   145  		c.Assert(out, gc.NotNil)
   146  		*out = params.HostedModelConfigsResults{
   147  			Models: []params.HostedModelConfig{
   148  				{
   149  					Name:     "first",
   150  					OwnerTag: "user-foo@bar",
   151  					Config: map[string]interface{}{
   152  						"name": "first",
   153  					},
   154  					CloudSpec: &params.CloudSpec{
   155  						Type: "magic",
   156  						Name: "first",
   157  					},
   158  				}, {
   159  					Name:     "second",
   160  					OwnerTag: "bad-tag",
   161  				}, {
   162  					Name:     "third",
   163  					OwnerTag: "user-foo@bar",
   164  					Config: map[string]interface{}{
   165  						"name": "third",
   166  					},
   167  					CloudSpec: &params.CloudSpec{
   168  						Name: "third",
   169  					},
   170  				},
   171  			},
   172  		}
   173  		return nil
   174  	})
   175  	client := controller.NewClient(apiCaller)
   176  	config, err := client.HostedModelConfigs()
   177  	c.Assert(config, gc.HasLen, 3)
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	first := config[0]
   180  	c.Assert(first.Name, gc.Equals, "first")
   181  	c.Assert(first.Owner, gc.Equals, names.NewUserTag("foo@bar"))
   182  	c.Assert(first.Config, gc.DeepEquals, map[string]interface{}{
   183  		"name": "first",
   184  	})
   185  	c.Assert(first.CloudSpec, gc.DeepEquals, environs.CloudSpec{
   186  		Type: "magic",
   187  		Name: "first",
   188  	})
   189  	second := config[1]
   190  	c.Assert(second.Name, gc.Equals, "second")
   191  	c.Assert(second.Error.Error(), gc.Equals, `"bad-tag" is not a valid tag`)
   192  	third := config[2]
   193  	c.Assert(third.Name, gc.Equals, "third")
   194  	c.Assert(third.Error.Error(), gc.Equals, "validating CloudSpec: empty Type not valid")
   195  }
   196  
   197  func makeClient(results params.InitiateMigrationResults) (
   198  	*controller.Client, *jujutesting.Stub,
   199  ) {
   200  	var stub jujutesting.Stub
   201  	apiCaller := apitesting.APICallerFunc(
   202  		func(objType string, version int, id, request string, arg, result interface{}) error {
   203  			stub.AddCall(objType+"."+request, arg)
   204  			out := result.(*params.InitiateMigrationResults)
   205  			*out = results
   206  			return nil
   207  		},
   208  	)
   209  	client := controller.NewClient(apiCaller)
   210  	return client, &stub
   211  }
   212  
   213  func makeSpec() controller.MigrationSpec {
   214  	mac, err := macaroon.New([]byte("secret"), "id", "location")
   215  	if err != nil {
   216  		panic(err)
   217  	}
   218  	return controller.MigrationSpec{
   219  		ModelUUID:            randomUUID(),
   220  		TargetControllerUUID: randomUUID(),
   221  		TargetAddrs:          []string{"1.2.3.4:5"},
   222  		TargetCACert:         "cert",
   223  		TargetUser:           "someone",
   224  		TargetPassword:       "secret",
   225  		TargetMacaroons:      []macaroon.Slice{{mac}},
   226  	}
   227  }
   228  
   229  func randomUUID() string {
   230  	return utils.MustNewUUID().String()
   231  }