github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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  	"strings"
     9  
    10  	"github.com/juju/cmd"
    11  	"github.com/juju/errors"
    12  	jc "github.com/juju/testing/checkers"
    13  	"github.com/juju/utils/featureflag"
    14  	gc "gopkg.in/check.v1"
    15  
    16  	"github.com/juju/juju/apiserver/params"
    17  	"github.com/juju/juju/cmd/envcmd"
    18  	"github.com/juju/juju/cmd/juju/machine"
    19  	"github.com/juju/juju/environs/manual"
    20  	"github.com/juju/juju/juju/osenv"
    21  	"github.com/juju/juju/state/multiwatcher"
    22  	"github.com/juju/juju/storage"
    23  	"github.com/juju/juju/testing"
    24  )
    25  
    26  type AddMachineSuite struct {
    27  	testing.FakeJujuHomeSuite
    28  	fake *fakeAddMachineAPI
    29  }
    30  
    31  var _ = gc.Suite(&AddMachineSuite{})
    32  
    33  func (s *AddMachineSuite) SetUpTest(c *gc.C) {
    34  	s.FakeJujuHomeSuite.SetUpTest(c)
    35  	s.fake = &fakeAddMachineAPI{}
    36  	s.fake.agentVersion = "1.21.0"
    37  }
    38  
    39  func (s *AddMachineSuite) TestInit(c *gc.C) {
    40  	for i, test := range []struct {
    41  		args        []string
    42  		series      string
    43  		constraints string
    44  		placement   string
    45  		count       int
    46  		errorString string
    47  	}{
    48  		{
    49  			count: 1,
    50  		}, {
    51  			args:   []string{"--series", "some-series"},
    52  			count:  1,
    53  			series: "some-series",
    54  		}, {
    55  			args:  []string{"-n", "2"},
    56  			count: 2,
    57  		}, {
    58  			args:      []string{"lxc"},
    59  			count:     1,
    60  			placement: "lxc:",
    61  		}, {
    62  			args:      []string{"lxc", "-n", "2"},
    63  			count:     2,
    64  			placement: "lxc:",
    65  		}, {
    66  			args:      []string{"lxc:4"},
    67  			count:     1,
    68  			placement: "lxc:4",
    69  		}, {
    70  			args:        []string{"--constraints", "mem=8G"},
    71  			count:       1,
    72  			constraints: "mem=8192M",
    73  		}, {
    74  			args:        []string{"--constraints", "container=lxc"},
    75  			errorString: `container constraint "lxc" not allowed when adding a machine`,
    76  		}, {
    77  			args:      []string{"ssh:user@10.10.0.3"},
    78  			count:     1,
    79  			placement: "ssh:user@10.10.0.3",
    80  		}, {
    81  			args:      []string{"zone=us-east-1a"},
    82  			count:     1,
    83  			placement: "env-uuid:zone=us-east-1a",
    84  		}, {
    85  			args:      []string{"anything-here"},
    86  			count:     1,
    87  			placement: "env-uuid:anything-here",
    88  		}, {
    89  			args:        []string{"anything", "else"},
    90  			errorString: `unrecognized args: \["else"\]`,
    91  		}, {
    92  			args:      []string{"something:special"},
    93  			count:     1,
    94  			placement: "something:special",
    95  		},
    96  	} {
    97  		c.Logf("test %d", i)
    98  		addCmd := &machine.AddCommand{}
    99  		err := testing.InitCommand(addCmd, test.args)
   100  		if test.errorString == "" {
   101  			c.Check(err, jc.ErrorIsNil)
   102  			c.Check(addCmd.Series, gc.Equals, test.series)
   103  			c.Check(addCmd.Constraints.String(), gc.Equals, test.constraints)
   104  			if addCmd.Placement != nil {
   105  				c.Check(addCmd.Placement.String(), gc.Equals, test.placement)
   106  			} else {
   107  				c.Check("", gc.Equals, test.placement)
   108  			}
   109  			c.Check(addCmd.NumMachines, gc.Equals, test.count)
   110  		} else {
   111  			c.Check(err, gc.ErrorMatches, test.errorString)
   112  		}
   113  	}
   114  }
   115  
   116  func (s *AddMachineSuite) run(c *gc.C, args ...string) (*cmd.Context, error) {
   117  	add := machine.NewAddCommand(s.fake)
   118  	return testing.RunCommand(c, envcmd.Wrap(add), args...)
   119  }
   120  
   121  func (s *AddMachineSuite) TestAddMachine(c *gc.C) {
   122  	context, err := s.run(c)
   123  	c.Assert(err, jc.ErrorIsNil)
   124  	c.Assert(testing.Stderr(context), gc.Equals, "created machine 0\n")
   125  
   126  	c.Assert(s.fake.args, gc.HasLen, 1)
   127  	param := s.fake.args[0]
   128  	c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{
   129  		multiwatcher.JobHostUnits,
   130  		multiwatcher.JobManageNetworking,
   131  	})
   132  }
   133  
   134  func (s *AddMachineSuite) TestSSHPlacement(c *gc.C) {
   135  	s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) {
   136  		return "42", nil
   137  	})
   138  	context, err := s.run(c, "ssh:10.1.2.3")
   139  	c.Assert(err, jc.ErrorIsNil)
   140  	c.Assert(testing.Stderr(context), gc.Equals, "created machine 42\n")
   141  }
   142  
   143  func (s *AddMachineSuite) TestSSHPlacementError(c *gc.C) {
   144  	s.PatchValue(machine.ManualProvisioner, func(args manual.ProvisionMachineArgs) (string, error) {
   145  		return "", errors.New("failed to initialize warp core")
   146  	})
   147  	context, err := s.run(c, "ssh:10.1.2.3")
   148  	c.Assert(err, gc.ErrorMatches, "failed to initialize warp core")
   149  	c.Assert(testing.Stderr(context), gc.Equals, "")
   150  }
   151  
   152  func (s *AddMachineSuite) TestParamsPassedOn(c *gc.C) {
   153  	_, err := s.run(c, "--constraints", "mem=8G", "--series=special", "zone=nz")
   154  	c.Assert(err, jc.ErrorIsNil)
   155  	c.Assert(s.fake.args, gc.HasLen, 1)
   156  	param := s.fake.args[0]
   157  	c.Assert(param.Placement.String(), gc.Equals, "fake-uuid:zone=nz")
   158  	c.Assert(param.Series, gc.Equals, "special")
   159  	c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M")
   160  }
   161  
   162  func (s *AddMachineSuite) TestParamsPassedOnNTimes(c *gc.C) {
   163  	_, err := s.run(c, "-n", "3", "--constraints", "mem=8G", "--series=special")
   164  	c.Assert(err, jc.ErrorIsNil)
   165  	c.Assert(s.fake.args, gc.HasLen, 3)
   166  	param := s.fake.args[0]
   167  	c.Assert(param.Series, gc.Equals, "special")
   168  	c.Assert(param.Constraints.String(), gc.Equals, "mem=8192M")
   169  	c.Assert(s.fake.args[0], jc.DeepEquals, s.fake.args[1])
   170  	c.Assert(s.fake.args[0], jc.DeepEquals, s.fake.args[2])
   171  }
   172  
   173  func (s *AddMachineSuite) TestAddThreeMachinesWithTwoFailures(c *gc.C) {
   174  	s.fake.successOrder = []bool{true, false, false}
   175  	expectedOutput := `created machine 0
   176  failed to create 2 machines
   177  `
   178  	context, err := s.run(c, "-n", "3")
   179  	c.Assert(err, gc.ErrorMatches, "something went wrong, something went wrong")
   180  	c.Assert(testing.Stderr(context), gc.Equals, expectedOutput)
   181  }
   182  
   183  func (s *AddMachineSuite) TestBlockedError(c *gc.C) {
   184  	s.fake.addError = &params.Error{Code: params.CodeOperationBlocked}
   185  	_, err := s.run(c)
   186  	c.Assert(err, gc.Equals, cmd.ErrSilent)
   187  	// msg is logged
   188  	stripped := strings.Replace(c.GetTestLog(), "\n", "", -1)
   189  	c.Check(stripped, gc.Matches, ".*To unblock changes.*")
   190  }
   191  
   192  func (s *AddMachineSuite) TestServerIsPreJobManageNetworking(c *gc.C) {
   193  	s.fake.agentVersion = "1.18.1"
   194  	_, err := s.run(c)
   195  	c.Assert(err, jc.ErrorIsNil)
   196  
   197  	c.Assert(s.fake.args, gc.HasLen, 1)
   198  	param := s.fake.args[0]
   199  	c.Assert(param.Jobs, jc.DeepEquals, []multiwatcher.MachineJob{
   200  		multiwatcher.JobHostUnits,
   201  	})
   202  }
   203  
   204  func (s *AddMachineSuite) TestAddMachineWithDisks(c *gc.C) {
   205  	// --disks is not defined unless the "storage" feature flag is enabled.
   206  	_, err := s.run(c, "--disks", "2,1G", "--disks", "2G")
   207  	c.Assert(err, gc.ErrorMatches, "flag provided but not defined: --disks")
   208  
   209  	s.PatchEnvironment(osenv.JujuFeatureFlagEnvKey, "storage")
   210  	featureflag.SetFlagsFromEnvironment(osenv.JujuFeatureFlagEnvKey)
   211  
   212  	_, err = s.run(c, "--disks", "2,1G", "--disks", "2G")
   213  	c.Assert(err, jc.ErrorIsNil)
   214  	c.Assert(s.fake.args, gc.HasLen, 1)
   215  	param := s.fake.args[0]
   216  	c.Assert(param.Disks, gc.DeepEquals, []storage.Constraints{
   217  		{Size: 1024, Count: 2},
   218  		{Size: 2048, Count: 1},
   219  	})
   220  }
   221  
   222  type fakeAddMachineAPI struct {
   223  	successOrder []bool
   224  	currentOp    int
   225  	args         []params.AddMachineParams
   226  	addError     error
   227  	agentVersion interface{}
   228  }
   229  
   230  func (f *fakeAddMachineAPI) Close() error {
   231  	return nil
   232  }
   233  
   234  func (f *fakeAddMachineAPI) EnvironmentUUID() string {
   235  	return "fake-uuid"
   236  }
   237  
   238  func (f *fakeAddMachineAPI) AddMachines(args []params.AddMachineParams) ([]params.AddMachinesResult, error) {
   239  	if f.addError != nil {
   240  		return nil, f.addError
   241  	}
   242  	results := []params.AddMachinesResult{}
   243  	for i := range args {
   244  		f.args = append(f.args, args[i])
   245  		if i >= len(f.successOrder) || f.successOrder[i] {
   246  			results = append(results, params.AddMachinesResult{
   247  				Machine: strconv.Itoa(i),
   248  				Error:   nil,
   249  			})
   250  		} else {
   251  			results = append(results, params.AddMachinesResult{
   252  				Machine: string(i),
   253  				Error:   &params.Error{"something went wrong", "1"},
   254  			})
   255  		}
   256  		f.currentOp++
   257  	}
   258  	return results, nil
   259  }
   260  
   261  func (f *fakeAddMachineAPI) AddMachines1dot18(args []params.AddMachineParams) ([]params.AddMachinesResult, error) {
   262  	return f.AddMachines(args)
   263  }
   264  
   265  func (f *fakeAddMachineAPI) ForceDestroyMachines(machines ...string) error {
   266  	return errors.NotImplementedf("ForceDestroyMachines")
   267  }
   268  
   269  func (f *fakeAddMachineAPI) ProvisioningScript(params.ProvisioningScriptParams) (script string, err error) {
   270  	return "", errors.NotImplementedf("ProvisioningScript")
   271  }
   272  
   273  func (f *fakeAddMachineAPI) EnvironmentGet() (map[string]interface{}, error) {
   274  	return map[string]interface{}{"agent-version": f.agentVersion}, nil
   275  }