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

     1  // Copyright 2014, 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package model_test
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  	jc "github.com/juju/testing/checkers"
    11  	gc "gopkg.in/check.v1"
    12  	"gopkg.in/juju/names.v2"
    13  
    14  	"github.com/juju/juju/apiserver/common"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/cmd/juju/model"
    17  	"github.com/juju/juju/testing"
    18  )
    19  
    20  type retryProvisioningSuite struct {
    21  	testing.FakeJujuXDGDataHomeSuite
    22  	fake *fakeRetryProvisioningClient
    23  }
    24  
    25  var _ = gc.Suite(&retryProvisioningSuite{})
    26  
    27  // fakeRetryProvisioningClient contains some minimal information
    28  // about machines in the environment to mock out the behavior
    29  // of the real RetryProvisioning command.
    30  type fakeRetryProvisioningClient struct {
    31  	m   map[string]fakeMachine
    32  	err error
    33  }
    34  
    35  type fakeMachine struct {
    36  	info string
    37  	data map[string]interface{}
    38  }
    39  
    40  func (f *fakeRetryProvisioningClient) Close() error {
    41  	return nil
    42  }
    43  
    44  func (f *fakeRetryProvisioningClient) RetryProvisioning(machines ...names.MachineTag) (
    45  	[]params.ErrorResult, error) {
    46  
    47  	if f.err != nil {
    48  		return nil, f.err
    49  	}
    50  
    51  	results := make([]params.ErrorResult, len(machines))
    52  
    53  	// For each of the machines passed in, verify that we have the
    54  	// id and that the info string is "broken".
    55  	for i, machine := range machines {
    56  		m, ok := f.m[machine.Id()]
    57  		if ok {
    58  			if m.info == "broken" {
    59  				// The real RetryProvisioning command sets the
    60  				// status data "transient" : true.
    61  				m.data["transient"] = true
    62  			} else {
    63  				results[i].Error = common.ServerError(
    64  					errors.Errorf("%s is not in an error state",
    65  						names.ReadableString(machine)))
    66  			}
    67  		} else {
    68  			results[i].Error = common.ServerError(
    69  				errors.NotFoundf("machine %s", machine.Id()))
    70  		}
    71  	}
    72  
    73  	return results, nil
    74  }
    75  
    76  func (s *retryProvisioningSuite) SetUpTest(c *gc.C) {
    77  	s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
    78  
    79  	// For all tests, create machine 0 (broken) and
    80  	// machine 1 (not broken).
    81  	s.fake = &fakeRetryProvisioningClient{
    82  		m: map[string]fakeMachine{
    83  			"0": {info: "broken",
    84  				data: make(map[string]interface{})},
    85  			"1": {info: "",
    86  				data: make(map[string]interface{})},
    87  		},
    88  	}
    89  }
    90  
    91  var resolvedMachineTests = []struct {
    92  	args   []string
    93  	err    string
    94  	stdErr string
    95  }{
    96  	{
    97  		err: `no machine specified`,
    98  	}, {
    99  		args: []string{"jeremy-fisher"},
   100  		err:  `invalid machine "jeremy-fisher"`,
   101  	}, {
   102  		args:   []string{"42"},
   103  		stdErr: `machine 42 not found`,
   104  	}, {
   105  		args:   []string{"1"},
   106  		stdErr: `machine 1 is not in an error state`,
   107  	}, {
   108  		args: []string{"0"},
   109  	}, {
   110  		args:   []string{"0", "1"},
   111  		stdErr: `machine 1 is not in an error state`,
   112  	}, {
   113  		args: []string{"1", "42"},
   114  		stdErr: `machine 1 is not in an error state` +
   115  			`machine 42 not found`,
   116  	}, {
   117  		args: []string{"0/lxd/0"},
   118  		err:  `invalid machine "0/lxd/0" retry-provisioning does not support containers`,
   119  	},
   120  }
   121  
   122  func (s *retryProvisioningSuite) TestRetryProvisioning(c *gc.C) {
   123  	for i, t := range resolvedMachineTests {
   124  		c.Logf("test %d: %v", i, t.args)
   125  		command := model.NewRetryProvisioningCommandForTest(s.fake)
   126  		context, err := testing.RunCommand(c, command, t.args...)
   127  		if t.err != "" {
   128  			c.Check(err, gc.ErrorMatches, t.err)
   129  			continue
   130  		}
   131  		c.Check(err, jc.ErrorIsNil)
   132  		output := testing.Stderr(context)
   133  		stripped := strings.Replace(output, "\n", "", -1)
   134  		c.Check(stripped, gc.Equals, t.stdErr)
   135  		if t.args[0] == "0" {
   136  			m := s.fake.m["0"]
   137  			c.Check(m.info, gc.Equals, "broken")
   138  			c.Check(m.data["transient"], jc.IsTrue)
   139  		}
   140  	}
   141  }
   142  
   143  func (s *retryProvisioningSuite) TestBlockRetryProvisioning(c *gc.C) {
   144  	s.fake.err = common.OperationBlockedError("TestBlockRetryProvisioning")
   145  	command := model.NewRetryProvisioningCommandForTest(s.fake)
   146  
   147  	for i, t := range resolvedMachineTests {
   148  		c.Logf("test %d: %v", i, t.args)
   149  		_, err := testing.RunCommand(c, command, t.args...)
   150  		if t.err != "" {
   151  			c.Check(err, gc.ErrorMatches, t.err)
   152  			continue
   153  		}
   154  		testing.AssertOperationWasBlocked(c, err, ".*TestBlockRetryProvisioning.*")
   155  	}
   156  }