github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cmd/juju/common/constraints_test.go (about) 1 // Copyright 2013 - 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "bytes" 8 "strings" 9 10 "github.com/juju/cmd" 11 "github.com/juju/errors" 12 "github.com/juju/names" 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/juju/juju/apiserver/common" 17 "github.com/juju/juju/cmd/envcmd" 18 // TODO(dimitern): Don't ever import "." unless there's a GOOD 19 // reason to do it. 20 . "github.com/juju/juju/cmd/juju/common" 21 "github.com/juju/juju/constraints" 22 "github.com/juju/juju/testing" 23 ) 24 25 type ConstraintsCommandsSuite struct { 26 testing.FakeJujuHomeSuite 27 fake *fakeConstraintsClient 28 } 29 30 var _ = gc.Suite(&ConstraintsCommandsSuite{}) 31 32 type fakeConstraintsClient struct { 33 err error 34 envCons constraints.Value 35 servCons map[string]constraints.Value 36 } 37 38 func (f *fakeConstraintsClient) addTestingService(name string) { 39 f.servCons[name] = constraints.Value{} 40 } 41 42 func (f *fakeConstraintsClient) Close() error { 43 return nil 44 } 45 46 func (f *fakeConstraintsClient) GetEnvironmentConstraints() (constraints.Value, error) { 47 return f.envCons, nil 48 } 49 50 func (f *fakeConstraintsClient) GetServiceConstraints(name string) (constraints.Value, error) { 51 if !names.IsValidService(name) { 52 return constraints.Value{}, errors.Errorf("%q is not a valid service name", name) 53 } 54 55 cons, ok := f.servCons[name] 56 if !ok { 57 return constraints.Value{}, errors.NotFoundf("service %q", name) 58 } 59 60 return cons, nil 61 } 62 63 func (f *fakeConstraintsClient) SetEnvironmentConstraints(cons constraints.Value) error { 64 if f.err != nil { 65 return f.err 66 } 67 68 f.envCons = cons 69 return nil 70 } 71 72 func (f *fakeConstraintsClient) SetServiceConstraints(name string, cons constraints.Value) error { 73 if f.err != nil { 74 return f.err 75 } 76 77 if !names.IsValidService(name) { 78 return errors.Errorf("%q is not a valid service name", name) 79 } 80 81 _, ok := f.servCons[name] 82 if !ok { 83 return errors.NotFoundf("service %q", name) 84 } 85 86 f.servCons[name] = cons 87 return nil 88 } 89 90 func runCmdLine(c *gc.C, com cmd.Command, args ...string) (code int, stdout, stderr string) { 91 ctx := testing.Context(c) 92 code = cmd.Main(com, ctx, args) 93 stdout = ctx.Stdout.(*bytes.Buffer).String() 94 stderr = ctx.Stderr.(*bytes.Buffer).String() 95 c.Logf("args: %#v\ncode: %d\nstdout: %q\nstderr: %q", args, code, stdout, stderr) 96 return 97 } 98 99 func uint64p(val uint64) *uint64 { 100 return &val 101 } 102 103 func (s *ConstraintsCommandsSuite) assertSet(c *gc.C, args ...string) { 104 command := NewSetConstraintsCommand(s.fake) 105 rcode, rstdout, rstderr := runCmdLine(c, envcmd.Wrap(command), args...) 106 107 c.Assert(rcode, gc.Equals, 0) 108 c.Assert(rstdout, gc.Equals, "") 109 c.Assert(rstderr, gc.Equals, "") 110 } 111 112 func (s *ConstraintsCommandsSuite) assertSetBlocked(c *gc.C, args ...string) { 113 command := NewSetConstraintsCommand(s.fake) 114 rcode, _, _ := runCmdLine(c, envcmd.Wrap(command), args...) 115 116 c.Assert(rcode, gc.Equals, 1) 117 118 // msg is logged 119 stripped := strings.Replace(c.GetTestLog(), "\n", "", -1) 120 c.Check(stripped, gc.Matches, ".*To unblock changes.*") 121 } 122 123 func (s *ConstraintsCommandsSuite) SetUpTest(c *gc.C) { 124 s.FakeJujuHomeSuite.SetUpTest(c) 125 s.fake = &fakeConstraintsClient{servCons: make(map[string]constraints.Value)} 126 } 127 128 func (s *ConstraintsCommandsSuite) TestSetEnviron(c *gc.C) { 129 // Set constraints. 130 s.assertSet(c, "mem=4G", "cpu-power=250") 131 cons, err := s.fake.GetEnvironmentConstraints() 132 c.Assert(err, jc.ErrorIsNil) 133 c.Assert(cons, gc.DeepEquals, constraints.Value{ 134 CpuPower: uint64p(250), 135 Mem: uint64p(4096), 136 }) 137 138 // Clear constraints. 139 s.assertSet(c) 140 cons, err = s.fake.GetEnvironmentConstraints() 141 c.Assert(err, jc.ErrorIsNil) 142 c.Assert(&cons, jc.Satisfies, constraints.IsEmpty) 143 } 144 145 func (s *ConstraintsCommandsSuite) TestBlockSetEnviron(c *gc.C) { 146 // Block operation 147 s.fake.err = common.ErrOperationBlocked("TestBlockSetEnviron") 148 // Set constraints. 149 s.assertSetBlocked(c, "mem=4G", "cpu-power=250") 150 } 151 152 func (s *ConstraintsCommandsSuite) TestSetService(c *gc.C) { 153 s.fake.addTestingService("svc") 154 155 // Set constraints. 156 s.assertSet(c, "-s", "svc", "mem=4G", "cpu-power=250") 157 cons := s.fake.servCons["svc"] 158 c.Assert(cons, gc.DeepEquals, constraints.Value{ 159 CpuPower: uint64p(250), 160 Mem: uint64p(4096), 161 }) 162 163 // Clear constraints. 164 s.assertSet(c, "-s", "svc") 165 cons = s.fake.servCons["svc"] 166 c.Assert(&cons, jc.Satisfies, constraints.IsEmpty) 167 } 168 169 func (s *ConstraintsCommandsSuite) TestBlockSetService(c *gc.C) { 170 s.fake.addTestingService("svc") 171 172 // Block operation 173 s.fake.err = common.ErrOperationBlocked("TestBlockSetService") 174 // Set constraints. 175 s.assertSetBlocked(c, "-s", "svc", "mem=4G", "cpu-power=250") 176 } 177 178 func (s *ConstraintsCommandsSuite) assertSetError(c *gc.C, code int, stderr string, args ...string) { 179 command := NewSetConstraintsCommand(s.fake) 180 rcode, rstdout, rstderr := runCmdLine(c, envcmd.Wrap(command), args...) 181 c.Assert(rcode, gc.Equals, code) 182 c.Assert(rstdout, gc.Equals, "") 183 c.Assert(rstderr, gc.Matches, "error: "+stderr+"\n") 184 } 185 186 func (s *ConstraintsCommandsSuite) TestSetErrors(c *gc.C) { 187 s.assertSetError(c, 2, `invalid service name "badname-0"`, "-s", "badname-0") 188 s.assertSetError(c, 2, `malformed constraint "="`, "=") 189 s.assertSetError(c, 2, `malformed constraint "="`, "-s", "s", "=") 190 s.assertSetError(c, 1, `service "missing" not found`, "-s", "missing") 191 } 192 193 func (s *ConstraintsCommandsSuite) assertGet(c *gc.C, stdout string, args ...string) { 194 command := NewGetConstraintsCommand(s.fake) 195 rcode, rstdout, rstderr := runCmdLine(c, envcmd.Wrap(command), args...) 196 c.Assert(rcode, gc.Equals, 0) 197 c.Assert(rstdout, gc.Equals, stdout) 198 c.Assert(rstderr, gc.Equals, "") 199 } 200 201 func (s *ConstraintsCommandsSuite) TestGetEnvironEmpty(c *gc.C) { 202 s.assertGet(c, "") 203 } 204 205 func (s *ConstraintsCommandsSuite) TestGetEnvironValues(c *gc.C) { 206 cons := constraints.Value{CpuCores: uint64p(64)} 207 s.fake.SetEnvironmentConstraints(cons) 208 s.assertGet(c, "cpu-cores=64\n") 209 } 210 211 func (s *ConstraintsCommandsSuite) TestGetServiceEmpty(c *gc.C) { 212 s.fake.addTestingService("svc") 213 s.assertGet(c, "", "svc") 214 } 215 216 func (s *ConstraintsCommandsSuite) TestGetServiceValues(c *gc.C) { 217 s.fake.addTestingService("svc") 218 s.fake.SetServiceConstraints("svc", constraints.Value{CpuCores: uint64p(64)}) 219 s.assertGet(c, "cpu-cores=64\n", "svc") 220 } 221 222 func (s *ConstraintsCommandsSuite) TestGetFormats(c *gc.C) { 223 cons := constraints.Value{CpuCores: uint64p(64), CpuPower: uint64p(0)} 224 s.fake.SetEnvironmentConstraints(cons) 225 s.assertGet(c, "cpu-cores=64 cpu-power=\n", "--format", "constraints") 226 s.assertGet(c, "cpu-cores: 64\ncpu-power: 0\n", "--format", "yaml") 227 s.assertGet(c, `{"cpu-cores":64,"cpu-power":0}`+"\n", "--format", "json") 228 } 229 230 func (s *ConstraintsCommandsSuite) assertGetError(c *gc.C, code int, stderr string, args ...string) { 231 command := NewGetConstraintsCommand(s.fake) 232 rcode, rstdout, rstderr := runCmdLine(c, envcmd.Wrap(command), args...) 233 c.Assert(rcode, gc.Equals, code) 234 c.Assert(rstdout, gc.Equals, "") 235 c.Assert(rstderr, gc.Matches, "error: "+stderr+"\n") 236 } 237 238 func (s *ConstraintsCommandsSuite) TestGetErrors(c *gc.C) { 239 s.assertGetError(c, 2, `invalid service name "badname-0"`, "badname-0") 240 s.assertGetError(c, 2, `unrecognized args: \["blether"\]`, "goodname", "blether") 241 s.assertGetError(c, 1, `service "missing" not found`, "missing") 242 }