github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/machine/add_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package machine_test
     5  
     6  import (
     7  	"strconv"
     8  
     9  	"github.com/juju/cmd"
    10  	"github.com/juju/errors"
    11  	jc "github.com/juju/testing/checkers"
    12  	gc "gopkg.in/check.v1"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/cmd/juju/machine"
    17  	"github.com/juju/juju/environs/manual"
    18  	"github.com/juju/juju/provider/dummy"
    19  	"github.com/juju/juju/state/multiwatcher"
    20  	"github.com/juju/juju/storage"
    21  	"github.com/juju/juju/testing"
    22  )
    23  
    24  type AddMachineSuite struct {
    25  	testing.FakeJujuXDGDataHomeSuite
    26  	fakeAddMachine     *fakeAddMachineAPI
    27  	fakeMachineManager *fakeMachineManagerAPI
    28  }
    29  
    30  var _ = gc.Suite(&AddMachineSuite{})
    31  
    32  func (s *AddMachineSuite) SetUpTest(c *gc.C) {
    33  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    34  	s.fakeAddMachine = &fakeAddMachineAPI{}
    35  	s.fakeMachineManager = &fakeMachineManagerAPI{}
    36  }
    37  
    38  func (s *AddMachineSuite) TestInit(c *gc.C) {
    39  	for i, test := range []struct {
    40  		args        []string
    41  		series      string
    42  		constraints string
    43  		placement   string
    44  		count       int
    45  		errorString string
    46  	}{
    47  		{
    48  			count: 1,
    49  		}, {
    50  			args:   []string{"--series", "some-series"},
    51  			count:  1,
    52  			series: "some-series",
    53  		}, {
    54  			args:  []string{"-n", "2"},
    55  			count: 2,
    56  		}, {
    57  			args:      []string{"lxd"},
    58  			count:     1,
    59  			placement: "lxd:",
    60  		}, {
    61  			args:      []string{"lxd", "-n", "2"},
    62  			count:     2,
    63  			placement: "lxd:",
    64  		}, {
    65  			args:      []string{"lxd:4"},
    66  			count:     1,
    67  			placement: "lxd:4",
    68  		}, {
    69  			args:      []string{"ssh:user@10.10.0.3"},
    70  			count:     1,
    71  			placement: "ssh:user@10.10.0.3",
    72  		}, {
    73  			args:      []string{"zone=us-east-1a"},
    74  			count:     1,
    75  			placement: "model-uuid:zone=us-east-1a",
    76  		}, {
    77  			args:      []string{"anything-here"},
    78  			count:     1,
    79  			placement: "model-uuid:anything-here",
    80  		}, {
    81  			args:        []string{"anything", "else"},
    82  			errorString: `unrecognized args: \["else"\]`,
    83  		}, {
    84  			args:      []string{"something:special"},
    85  			count:     1,
    86  			placement: "something:special",
    87  		},
    88  	} {
    89  		c.Logf("test %d", i)
    90  		wrappedCommand, addCmd := machine.NewAddCommandForTest(s.fakeAddMachine, s.fakeAddMachine, s.fakeMachineManager)
    91  		err := testing.InitCommand(wrappedCommand, test.args)
    92  		if test.errorString == "" {
    93  			c.Check(err, jc.ErrorIsNil)
    94  			c.Check(addCmd.Series, gc.Equals, test.series)
    95  			c.Check(addCmd.Constraints.String(), gc.Equals, test.constraints)
    96  			if addCmd.Placement != nil {
    97  				c.Check(addCmd.Placement.String(), gc.Equals, test.placement)
    98  			} else {
    99  				c.Check("", gc.Equals, test.placement)
   100  			}
   101  			c.Check(addCmd.NumMachines, gc.Equals, test.count)
   102  		} else {
   103  			c.Check(err, gc.ErrorMatches, test.errorString)
   104  		}
   105  	}
   106  }
   107  
   108  func (s *AddMachineSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
   109  	add, _ := machine.NewAddCommandForTest(s.fakeAddMachine, s.fakeAddMachine, s.fakeMachineManager)
   110  	return testing.RunCommand(c, add, args...)
   111  }
   112  
   113  func (s *AddMachineSuite) TestAddMachine(c *gc.C) {
   114  	context, err := s.run(c)
   115  	c.Assert(err, jc.ErrorIsNil)
   116  	c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n")
   117  
   118  	c.Assert(s.fakeAddMachine.args, gc.HasLen, 1)
   119  	param := s.fakeAddMachine.args[0]
   120  	c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{
   121  		multiwatcher.JobHostUnits,
   122  	})
   123  }
   124  
   125  func (s *AddMachineSuite) TestSSHPlacement(c *gc.C) {
   126  	s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) {
   127  		return "42", nil
   128  	})
   129  	context, err := s.run(c, "ssh:10.1.2.3")
   130  	c.Assert(err, jc.ErrorIsNil)
   131  	c.Assert(testing.Stderr(context), gc.Equals, "created machine 42\n")
   132  }
   133  
   134  func (s *AddMachineSuite) TestSSHPlacementError(c *gc.C) {
   135  	s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) {
   136  		return "", errors.New("failed to initialize warp core")
   137  	})
   138  	context, err := s.run(c, "ssh:10.1.2.3")
   139  	c.Assert(err, gc.ErrorMatches, "failed to initialize warp core")
   140  	c.Assert(testing.Stderr(context), gc.Equals, "")
   141  }
   142  
   143  func (s *AddMachineSuite) TestParamsPassedOn(c *gc.C) {
   144  	_, err := s.run(c, "--constraints", "mem=8G", "--series=special", "zone=nz")
   145  	c.Assert(err, jc.ErrorIsNil)
   146  	c.Assert(s.fakeAddMachine.args, gc.HasLen, 1)
   147  	param := s.fakeAddMachine.args[0]
   148  	c.Assert(param.Placement.String(), gc.Equals, "fake-uuid:zone=nz")
   149  	c.Assert(param.Series, gc.Equals, "special")
   150  	c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M")
   151  }
   152  
   153  func (s *AddMachineSuite) TestParamsPassedOnNTimes(c *gc.C) {
   154  	_, err := s.run(c, "-n", "3", "--constraints", "mem=8G", "--series=special")
   155  	c.Assert(err, jc.ErrorIsNil)
   156  	c.Assert(s.fakeAddMachine.args, gc.HasLen, 3)
   157  	param := s.fakeAddMachine.args[0]
   158  	c.Assert(param.Series, gc.Equals, "special")
   159  	c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M")
   160  	c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[1])
   161  	c.Assert(s.fakeAddMachine.args[0], jc.DeepEquals, s.fakeAddMachine.args[2])
   162  }
   163  
   164  func (s *AddMachineSuite) TestAddThreeMachinesWithTwoFailures(c *gc.C) {
   165  	s.fakeAddMachine.successOrder = []bool{true, false, false}
   166  	expectedOutput := `created machine 0
   167  failed to create 2 machines
   168  `
   169  	context, err := s.run(c, "-n", "3")
   170  	c.Assert(err, gc.ErrorMatches, "something went wrong, something went wrong")
   171  	c.Assert(testing.Stderr(context), gc.Equals, expectedOutput)
   172  }
   173  
   174  func (s *AddMachineSuite) TestBlockedError(c *gc.C) {
   175  	s.fakeAddMachine.addError = common.OperationBlockedError("TestBlockedError")
   176  	_, err := s.run(c)
   177  	testing.AssertOperationWasBlocked(c, err, ".*TestBlockedError.*")
   178  }
   179  
   180  func (s *AddMachineSuite) TestAddMachineWithDisks(c *gc.C) {
   181  	s.fakeMachineManager.apiVersion = 1
   182  	_, err := s.run(c, "--disks", "2,1G", "--disks", "2G")
   183  	c.Assert(err, jc.ErrorIsNil)
   184  	c.Assert(s.fakeAddMachine.args, gc.HasLen, 0)
   185  	c.Assert(s.fakeMachineManager.args, gc.HasLen, 1)
   186  	param := s.fakeMachineManager.args[0]
   187  	c.Assert(param.Disks, gc.DeepEquals, []storage.Constraints{
   188  		{Size: 1024, Count: 2},
   189  		{Size: 2048, Count: 1},
   190  	})
   191  }
   192  
   193  func (s *AddMachineSuite) TestAddMachineWithDisksUnsupported(c *gc.C) {
   194  	_, err := s.run(c, "--disks", "2,1G", "--disks", "2G")
   195  	c.Assert(err, gc.ErrorMatches, "cannot add machines with disks: not supported by the API server")
   196  }
   197  
   198  type fakeAddMachineAPI struct {
   199  	successOrder []bool
   200  	currentOp    int
   201  	args         []params.AddMachineParams
   202  	addError     error
   203  	providerType string
   204  }
   205  
   206  func (f *fakeAddMachineAPI) Close() error {
   207  	return nil
   208  }
   209  
   210  func (f *fakeAddMachineAPI) ModelUUID() (string, bool) {
   211  	return "fake-uuid", true
   212  }
   213  
   214  func (f *fakeAddMachineAPI) AddMachines(args []params.AddMachineParams) ([]params.AddMachinesResult, error) {
   215  	if f.addError != nil {
   216  		return nil, f.addError
   217  	}
   218  	results := []params.AddMachinesResult{}
   219  	for i := range args {
   220  		f.args = append(f.args, args[i])
   221  		if i >= len(f.successOrder) || f.successOrder[i] {
   222  			results = append(results, params.AddMachinesResult{
   223  				Machine: strconv.Itoa(i),
   224  				Error:   nil,
   225  			})
   226  		} else {
   227  			results = append(results, params.AddMachinesResult{
   228  				Machine: string(i),
   229  				Error:   &params.Error{Message: "something went wrong", Code: "1"},
   230  			})
   231  		}
   232  		f.currentOp++
   233  	}
   234  	return results, nil
   235  }
   236  
   237  func (f *fakeAddMachineAPI) ForceDestroyMachines(machines ...string) error {
   238  	return errors.NotImplementedf("ForceDestroyMachines")
   239  }
   240  
   241  func (f *fakeAddMachineAPI) ProvisioningScript(params.ProvisioningScriptParams) (script string, err error) {
   242  	return "", errors.NotImplementedf("ProvisioningScript")
   243  }
   244  
   245  func (f *fakeAddMachineAPI) ModelGet() (map[string]interface{}, error) {
   246  	providerType := "dummy"
   247  	if f.providerType != "" {
   248  		providerType = f.providerType
   249  	}
   250  	return dummy.SampleConfig().Merge(map[string]interface{}{
   251  		"type": providerType,
   252  	}), nil
   253  }
   254  
   255  type fakeMachineManagerAPI struct {
   256  	apiVersion int
   257  	fakeAddMachineAPI
   258  }
   259  
   260  func (f *fakeMachineManagerAPI) BestAPIVersion() int {
   261  	return f.apiVersion
   262  }