github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/cmd/juju/space/list_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package space_test 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "regexp" 11 "strings" 12 13 "github.com/juju/errors" 14 jc "github.com/juju/testing/checkers" 15 gc "gopkg.in/check.v1" 16 17 "github.com/juju/juju/cmd/juju/space" 18 ) 19 20 type ListSuite struct { 21 BaseSpaceSuite 22 } 23 24 var _ = gc.Suite(&ListSuite{}) 25 26 func (s *ListSuite) SetUpTest(c *gc.C) { 27 s.BaseSpaceSuite.SetUpTest(c) 28 s.newCommand = space.NewListCommand 29 } 30 31 func (s *ListSuite) TestInit(c *gc.C) { 32 for i, test := range []struct { 33 about string 34 args []string 35 expectShort bool 36 expectFormat string 37 expectErr string 38 }{{ 39 about: "unrecognized arguments", 40 args: s.Strings("foo"), 41 expectErr: `unrecognized args: \["foo"\]`, 42 expectFormat: "tabular", 43 }, { 44 about: "invalid format", 45 args: s.Strings("--format", "foo"), 46 expectErr: `invalid value "foo" for option --format: unknown format "foo"`, 47 expectFormat: "tabular", 48 }, { 49 about: "invalid format (value is case-sensitive)", 50 args: s.Strings("--format", "JSON"), 51 expectErr: `invalid value "JSON" for option --format: unknown format "JSON"`, 52 expectFormat: "tabular", 53 }, { 54 about: "json format", 55 args: s.Strings("--format", "json"), 56 expectFormat: "json", 57 }, { 58 about: "yaml format", 59 args: s.Strings("--format", "yaml"), 60 expectFormat: "yaml", 61 }, { 62 about: "tabular format", 63 args: s.Strings("--format", "tabular"), 64 expectFormat: "tabular", 65 }, { 66 // --output and -o are tested separately in TestOutputFormats. 67 about: "both --output and -o specified (latter overrides former)", 68 args: s.Strings("--output", "foo", "-o", "bar"), 69 expectFormat: "tabular", 70 }} { 71 c.Logf("test #%d: %s", i, test.about) 72 command, err := s.InitCommand(c, test.args...) 73 if test.expectErr != "" { 74 c.Check(err, gc.ErrorMatches, test.expectErr) 75 } else { 76 c.Check(err, jc.ErrorIsNil) 77 command := command.(*space.ListCommand) 78 c.Check(command.ListFormat(), gc.Equals, test.expectFormat) 79 c.Check(command.Short, gc.Equals, test.expectShort) 80 } 81 82 // No API calls should be recorded at this stage. 83 s.api.CheckCallNames(c) 84 } 85 } 86 87 func (s *ListSuite) TestOutputFormats(c *gc.C) { 88 outDir := c.MkDir() 89 expectedYAML := ` 90 spaces: 91 space1: 92 2001:db8::/32: 93 type: ipv6 94 provider-id: subnet-public 95 status: terminating 96 zones: 97 - zone2 98 invalid: 99 type: unknown 100 provider-id: no-such 101 status: 'error: invalid subnet CIDR: invalid' 102 zones: 103 - zone1 104 space2: 105 4.3.2.0/28: 106 type: ipv4 107 provider-id: vlan-42 108 status: terminating 109 zones: 110 - zone1 111 10.1.2.0/24: 112 type: ipv4 113 provider-id: subnet-private 114 status: in-use 115 zones: 116 - zone1 117 - zone2 118 `[1:] 119 unwrap := regexp.MustCompile(`[\s+\n]`) 120 expectedJSON := unwrap.ReplaceAllLiteralString(` 121 { 122 "spaces": { 123 "space1": { 124 "2001:db8::/32": { 125 "type": "ipv6", 126 "provider-id": "subnet-public", 127 "status": "terminating", 128 "zones": ["zone2"] 129 }, 130 "invalid": { 131 "type": "unknown", 132 "provider-id": "no-such", 133 "status": "error: invalid subnet CIDR: invalid", 134 "zones": ["zone1"] 135 } 136 }, 137 "space2": { 138 "10.1.2.0/24": { 139 "type": "ipv4", 140 "provider-id": "subnet-private", 141 "status": "in-use", 142 "zones": ["zone1","zone2"] 143 }, 144 "4.3.2.0/28": { 145 "type": "ipv4", 146 "provider-id": "vlan-42", 147 "status": "terminating", 148 "zones": ["zone1"] 149 } 150 } 151 } 152 } 153 `, "") + "\n" 154 // Work around the big unwrap hammer above. 155 expectedJSON = strings.Replace( 156 expectedJSON, 157 "error:invalidsubnetCIDR:invalid", 158 "error: invalid subnet CIDR: invalid", 159 1, 160 ) 161 expectedShortYAML := ` 162 spaces: 163 - space1 164 - space2 165 `[1:] 166 167 expectedShortJSON := unwrap.ReplaceAllLiteralString(` 168 { 169 "spaces": [ 170 "space1", 171 "space2" 172 ] 173 } 174 `, "") + "\n" 175 176 expectedTabular := `Space Subnets 177 space1 2001:db8::/32 178 invalid 179 space2 10.1.2.0/24 180 4.3.2.0/28 181 182 ` 183 expectedShortTabular := `Space 184 space1 185 space2 186 187 ` 188 189 assertAPICalls := func() { 190 // Verify the API calls and reset the recorded calls. 191 s.api.CheckCallNames(c, "ListSpaces", "Close") 192 s.api.ResetCalls() 193 } 194 makeArgs := func(format string, short bool, extraArgs ...string) []string { 195 args := s.Strings(extraArgs...) 196 if format != "" { 197 args = append(args, "--format", format) 198 } 199 if short == true { 200 args = append(args, "--short") 201 } 202 return args 203 } 204 assertOutput := func(format, expected string, short bool) { 205 outFile := filepath.Join(outDir, "output") 206 c.Assert(outFile, jc.DoesNotExist) 207 defer os.Remove(outFile) 208 // Check -o works. 209 var args []string 210 args = makeArgs(format, short, "-o", outFile) 211 s.AssertRunSucceeds(c, "", "", args...) 212 assertAPICalls() 213 214 data, err := ioutil.ReadFile(outFile) 215 c.Assert(err, jc.ErrorIsNil) 216 c.Assert(string(data), gc.Equals, expected) 217 218 // Check the last output argument takes precedence when both 219 // -o and --output are given (and also that --output works the 220 // same as -o). 221 outFile1 := filepath.Join(outDir, "output1") 222 c.Assert(outFile1, jc.DoesNotExist) 223 defer os.Remove(outFile1) 224 outFile2 := filepath.Join(outDir, "output2") 225 c.Assert(outFile2, jc.DoesNotExist) 226 defer os.Remove(outFile2) 227 // Write something in outFile2 to verify its contents are 228 // overwritten. 229 err = ioutil.WriteFile(outFile2, []byte("some contents"), 0644) 230 c.Assert(err, jc.ErrorIsNil) 231 232 args = makeArgs(format, short, "-o", outFile1, "--output", outFile2) 233 s.AssertRunSucceeds(c, "", "", args...) 234 // Check only the last output file was used, and the output 235 // file was overwritten. 236 c.Assert(outFile1, jc.DoesNotExist) 237 data, err = ioutil.ReadFile(outFile2) 238 c.Assert(err, jc.ErrorIsNil) 239 c.Assert(string(data), gc.Equals, expected) 240 assertAPICalls() 241 242 // Finally, check without --output. 243 args = makeArgs(format, short) 244 s.AssertRunSucceeds(c, "", expected, args...) 245 assertAPICalls() 246 } 247 248 for i, test := range []struct { 249 format string 250 expected string 251 short bool 252 }{ 253 {"", expectedTabular, false}, // default format is tabular 254 {"tabular", expectedTabular, false}, 255 {"yaml", expectedYAML, false}, 256 {"json", expectedJSON, false}, 257 {"", expectedShortTabular, true}, // default format is tabular 258 {"tabular", expectedShortTabular, true}, 259 {"yaml", expectedShortYAML, true}, 260 {"json", expectedShortJSON, true}, 261 } { 262 c.Logf("test #%d: format %q, short %v", i, test.format, test.short) 263 assertOutput(test.format, test.expected, test.short) 264 } 265 } 266 267 func (s *ListSuite) TestRunWhenNoSpacesExistSucceeds(c *gc.C) { 268 s.api.Spaces = s.api.Spaces[0:0] 269 270 s.AssertRunSucceeds(c, 271 `no spaces to display\n`, 272 "", // empty stdout. 273 ) 274 275 s.api.CheckCallNames(c, "ListSpaces", "Close") 276 s.api.CheckCall(c, 0, "ListSpaces") 277 } 278 279 func (s *ListSuite) TestRunWhenNoSpacesExistSucceedsWithProperFormat(c *gc.C) { 280 s.api.Spaces = s.api.Spaces[0:0] 281 282 s.AssertRunSucceeds(c, 283 `no spaces to display\n`, 284 "{\"spaces\":{}}\n", // json formatted stdout. 285 "--format=json", 286 ) 287 288 s.AssertRunSucceeds(c, 289 `no spaces to display\n`, 290 "spaces: {}\n", // yaml formatted stdout. 291 "--format=yaml", 292 ) 293 294 s.api.CheckCallNames(c, "ListSpaces", "Close", "ListSpaces", "Close") 295 s.api.CheckCall(c, 0, "ListSpaces") 296 s.api.CheckCall(c, 2, "ListSpaces") 297 } 298 299 func (s *ListSuite) TestRunWhenSpacesNotSupported(c *gc.C) { 300 s.api.SetErrors(errors.NewNotSupported(nil, "spaces not supported")) 301 302 err := s.AssertRunSpacesNotSupported(c, "cannot list spaces: spaces not supported") 303 c.Assert(err, jc.Satisfies, errors.IsNotSupported) 304 305 s.api.CheckCallNames(c, "ListSpaces", "Close") 306 s.api.CheckCall(c, 0, "ListSpaces") 307 } 308 309 func (s *ListSuite) TestRunWhenSpacesAPIFails(c *gc.C) { 310 s.api.SetErrors(errors.New("boom")) 311 312 s.AssertRunFails(c, "cannot list spaces: boom") 313 314 s.api.CheckCallNames(c, "ListSpaces", "Close") 315 s.api.CheckCall(c, 0, "ListSpaces") 316 }