github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/cmd/snap/cmd_model_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package main_test 21 22 import ( 23 "fmt" 24 "net/http" 25 26 "gopkg.in/check.v1" 27 28 snap "github.com/snapcore/snapd/cmd/snap" 29 ) 30 31 const happyModelAssertionResponse = `type: model 32 authority-id: mememe 33 series: 16 34 brand-id: mememe 35 model: test-model 36 architecture: amd64 37 base: core18 38 gadget: pc=18 39 kernel: pc-kernel=18 40 store: mememestore 41 system-user-authority: 42 - youyouyou 43 - mememe 44 required-snaps: 45 - core 46 - hello-world 47 timestamp: 2017-07-27T00:00:00.0Z 48 sign-key-sha3-384: 8B3Wmemeu3H6i4dEV4Q85Q4gIUCHIBCNMHq49e085QeLGHi7v27l3Cqmemer4__t 49 50 AcLBcwQAAQoAHRYhBMbX+t6MbKGH5C3nnLZW7+q0g6ELBQJdTdwTAAoJELZW7+q0g6ELEvgQAI3j 51 jXTqR6kKOqvw94pArwdMDUaZ++tebASAZgso8ejrW2DQGWSc0Q7SQICIR8bvHxqS1GtupQswOzwS 52 U8hjDTv7WEchH1jylyTj/1W1GernmitTKycecRlEkSOE+EpuqBFgTtj6PdA1Fj3CiCRi1rLMhgF2 53 luCOitBLaP+E8P3fuATsLqqDLYzt1VY4Y14MU75hMn+CxAQdnOZTI+NzGMasPsldmOYCPNaN/b3N 54 6/fDLU47RtNlMJ3K0Tz8kj0bqRbegKlD0RdNbAgo9iZwNmrr5E9WCu9f/0rUor/NIxO77H2ExIll 55 zhmsZ7E6qlxvAgBmzKgAXrn68gGrBkIb0eXKiCaKy/i2ApvjVZ9HkOzA6Ldd+SwNJv/iA8rdiMsq 56 p2BfKV5f3ju5b6+WktHxAakJ8iqQmj9Yh7piHjsOAUf1PEJd2s2nqQ+pEEn1F0B23gVCY/Fa9YRQ 57 iKtWVeL3rBw4dSAaK9rpTMqlNcr+yrdXfTK5YzkCC6RU4yzc5MW0hKeseeSiEDSaRYxvftjFfVNa 58 ZaVXKg8Lu+cHtCJDeYXEkPIDQzXswdBO1M8Mb9D0mYxQwHxwvsWv1DByB+Otq08EYgPh4kyHo7ag 59 85yK2e/NQ/fxSwQJMhBF74jM1z9arq6RMiE/KOleFAOraKn2hcROKnEeinABW+sOn6vNuMVv 60 ` 61 62 const happyUC20ModelAssertionResponse = `type: model 63 authority-id: testrootorg 64 series: 16 65 brand-id: testrootorg 66 model: test-snapd-core-20-amd64 67 architecture: amd64 68 base: core20 69 grade: secured 70 snaps: 71 - 72 default-channel: 20/edge 73 id: UqFziVZDHLSyO3TqSWgNBoAdHbLI4dAH 74 name: pc 75 type: gadget 76 - 77 default-channel: 20/edge 78 id: pYVQrBcKmBa0mZ4CCN7ExT6jH8rY1hza 79 name: pc-kernel 80 type: kernel 81 - 82 default-channel: latest/stable 83 id: DLqre5XGLbDqg9jPtiAhRRjDuPVa5X1q 84 name: core20 85 type: base 86 - 87 default-channel: latest/stable 88 id: PMrrV4ml8uWuEUDBT8dSGnKUYbevVhc4 89 name: snapd 90 type: snapd 91 timestamp: 2018-09-11T22:00:00+00:00 92 sign-key-sha3-384: hIedp1AvrWlcDI4uS_qjoFLzjKl5enu4G2FYJpgB3Pj-tUzGlTQBxMBsBmi-tnJR 93 94 AcLBUgQAAQoABgUCX06qogAAv10QAFaqQ0NDDvIB7LqM0xNIz+5Y6PB5wJaRk0HqVsg2LlNgS0PQ 95 uJf0uFMV4GjQMraL7ZYv9BGyUoA+cz8Nbiz85m1g2ADt0ugqR/x2bAojii9lbFLmWpDMJcZhrtB1 96 3k32lEUwqTMvzYTGiZ6TVug0KYbdmf2+5IGxsayAS3EwdrfbuGRHZOv6XGV7bmm1GEwCRAFvgHCk 97 BHKoLZ+rfbNclF4l6G+biWJTdyc5jCMpMQ6X/INnx2hXaMRf9Jfrpl6s2bGCfsxW6HVf7AWZ8qHK 98 jtWPQqJ6NFu2Kw1lYIA202ReK8DC3gfAlOeNzUG5dTPor3KwAoDJJI8ZaQypOazEhO9SHERIutbP 99 eqPxPmEoB2+E0/o0+g0o5jK4qww3Yd7b8FTDkqm2xfuuldWAiAA4x6ZOQb2So9OLT6ovqHnD3D2r 100 pLW/lhqwfKp3xzIVUrLi0sjGOVXu5xFDDRyFICZ6kwC7JynRGfHoa5E2y7rv8ehnOZQJ+esz9sgY 101 lCJcyJ8vhabDlVHg0msSeNKMVBwhQnOSakEwlcfVyaSnapArkF+OCAMl8cuGpMTKO7vJLIJo2c2P 102 jcVE0ftsTGs9eBi2HmdDhu3e3fmxHt9VcC4uRSOnYNVcJnMh0yVmG8RGS/Dqcz04II7llww6JJYG 103 KKjQ3RU/TduXa8VJsoWiRRUYAv3H 104 ` 105 106 const happyModelWithDisplayNameAssertionResponse = `type: model 107 authority-id: mememe 108 series: 16 109 brand-id: mememe 110 model: test-model 111 architecture: amd64 112 display-name: Model Name 113 base: core18 114 gadget: pc=18 115 kernel: pc-kernel=18 116 store: mememestore 117 system-user-authority: 118 - youyouyou 119 - mememe 120 required-snaps: 121 - core 122 - hello-world 123 timestamp: 2017-07-27T00:00:00.0Z 124 sign-key-sha3-384: 8B3Wmemeu3H6i4dEV4Q85Q4gIUCHIBCNMHq49e085QeLGHi7v27l3Cqmemer4__t 125 126 AcLBcwQAAQoAHRYhBMbX+t6MbKGH5C3nnLZW7+q0g6ELBQJdTdwTAAoJELZW7+q0g6ELEvgQAI3j 127 jXTqR6kKOqvw94pArwdMDUaZ++tebASAZgso8ejrW2DQGWSc0Q7SQICIR8bvHxqS1GtupQswOzwS 128 U8hjDTv7WEchH1jylyTj/1W1GernmitTKycecRlEkSOE+EpuqBFgTtj6PdA1Fj3CiCRi1rLMhgF2 129 luCOitBLaP+E8P3fuATsLqqDLYzt1VY4Y14MU75hMn+CxAQdnOZTI+NzGMasPsldmOYCPNaN/b3N 130 6/fDLU47RtNlMJ3K0Tz8kj0bqRbegKlD0RdNbAgo9iZwNmrr5E9WCu9f/0rUor/NIxO77H2ExIll 131 zhmsZ7E6qlxvAgBmzKgAXrn68gGrBkIb0eXKiCaKy/i2ApvjVZ9HkOzA6Ldd+SwNJv/iA8rdiMsq 132 p2BfKV5f3ju5b6+WktHxAakJ8iqQmj9Yh7piHjsOAUf1PEJd2s2nqQ+pEEn1F0B23gVCY/Fa9YRQ 133 iKtWVeL3rBw4dSAaK9rpTMqlNcr+yrdXfTK5YzkCC6RU4yzc5MW0hKeseeSiEDSaRYxvftjFfVNa 134 ZaVXKg8Lu+cHtCJDeYXEkPIDQzXswdBO1M8Mb9D0mYxQwHxwvsWv1DByB+Otq08EYgPh4kyHo7ag 135 85yK2e/NQ/fxSwQJMhBF74jM1z9arq6RMiE/KOleFAOraKn2hcROKnEeinABW+sOn6vNuMVv 136 ` 137 138 const happyAccountAssertionResponse = `type: account 139 authority-id: canonical 140 account-id: mememe 141 display-name: MeMeMe 142 timestamp: 2016-04-01T00:00:00.0Z 143 username: meuser 144 validation: certified 145 sign-key-sha3-384: -CvQKAwRQ5h3Ffn10FILJoEZUXOv6km9FwA80-Rcj-f-6jadQ89VRswHNiEB9Lxk 146 147 AcLDXAQAAQoABgUCV7UYzwAKCRDUpVvql9g3IK7uH/4udqNOurx5WYVknzXdwekp0ovHCQJ0iBPw 148 TSFxEVr9faZSzb7eqJ1WicHsShf97PYS3ClRYAiluFsjRA8Y03kkSVJHjC+sIwGFubsnkmgflt6D 149 WEmYIl0UBmeaEDS8uY4Xvp9NsLTzNEj2kvzy/52gKaTc1ZSl5RDL9ppMav+0V9iBYpiDPBWH2rJ+ 150 aDSD8Rkyygm0UscfAKyDKH4lrvZ0WkYyi1YVNPrjQ/AtBySh6Q4iJ3LifzKa9woIyAuJET/4/FPY 151 oirqHAfuvNod36yNQIyNqEc20AvTvZNH0PSsg4rq3DLjIPzv5KbJO9lhsasNJK1OdL6x8Yqrdsbk 152 ldZp4qkzfjV7VOMQKaadfcZPRaVVeJWOBnBiaukzkhoNlQi1sdCdkBB/AJHZF8QXw6c7vPDcfnCV 153 1lW7ddQ2p8IsJbT6LzpJu3GW/P4xhNgCjtCJ1AJm9a9RqLwQYgdLZwwDa9iCRtqTbRXBlfy3apps 154 1VjbQ3h5iCd0hNfwDBnGVm1rhLKHCD1DUdNE43oN2ZlE7XGyh0HFV6vKlpqoW3eoXCIxWu+HBY96 155 +LSl/jQgCkb0nxYyzEYK4Reb31D0mYw1Nji5W+MIF5E09+DYZoOT0UvR05YMwMEOeSdI/hLWg/5P 156 k+GDK+/KopMmpd4D1+jjtF7ZvqDpmAV98jJGB2F88RyVb4gcjmFFyTi4Kv6vzz/oLpbm0qrizC0W 157 HLGDN/ymGA5sHzEgEx7U540vz/q9VX60FKqL2YZr/DcyY9GKX5kCG4sNqIIHbcJneZ4frM99oVDu 158 7Jv+DIx/Di6D1ULXol2XjxbbJLKHFtHksR97ceaFvcZwTogC61IYUBJCvvMoqdXAWMhEXCr0QfQ5 159 Xbi31XW2d4/lF/zWlAkRnGTzufIXFni7+nEuOK0SQEzO3/WaRedK1SGOOtTDjB8/3OJeW96AUYK5 160 oTIynkYkEyHWMNCXALg+WQW6L4/YO7aUjZ97zOWIugd7Xy63aT3r/EHafqaY2nacOhLfkeKZ830b 161 o/ezjoZQAxbh6ce7JnXRgE9ELxjdAhBTpGjmmmN2sYrJ7zP9bOgly0BnEPXGSQfFA+NNNw1FADx1 162 MUY8q9DBjmVtgqY+1KGTV5X8KvQCBMODZIf/XJPHdCRAHxMd8COypcwgL2vDIIXpOFbi1J/B0GF+ 163 eklxk9wzBA8AecBMCwCzIRHDNpD1oa2we38bVFrOug6e/VId1k1jYFJjiLyLCDmV8IMYwEllHSXp 164 LQAdm3xZ7t4WnxYC8YSCk9mXf3CZg59SpmnV5Q5Z6A5Pl7Nc3sj7hcsMBZEsOMPzNC9dPsBnZvjs 165 WpPUffJzEdhHBFhvYMuD4Vqj6ejUv9l3oTrjQWVC` 166 167 // note: this serial assertion was generated by adding print statements to the 168 // test in api_model_test.go that generate a fake serial assertion 169 const happySerialAssertionResponse = `type: serial 170 authority-id: my-brand 171 brand-id: my-brand 172 model: my-old-model 173 serial: serialserial 174 device-key: 175 AcZrBFaFwYABAvCgEOrrLA6FKcreHxCcOoTgBUZ+IRG7Nb8tzmEAklaQPGpv7skapUjwD1luE2go 176 mTcoTssVHrfLpBoSDV1aBs44rg3NK40ZKPJP7d2zkds1GxUo1Ea5vfet3SJ4h3aRABEBAAE= 177 device-key-sha3-384: iqLo9doLzK8De9925UrdUyuvPbBad72OTWVE9YJXqd6nz9dKvwJ_lHP5bVxrl3VO 178 timestamp: 2019-08-26T16:34:21-05:00 179 sign-key-sha3-384: anCEGC2NYq7DzDEi6y7OafQCVeVLS90XlLt9PNjrRl9sim5rmRHDDNFNO7ODcWQW 180 181 AcJwBAABCgAGBQJdZFBdAADCLALwR6Sy24wm9PffwbvUhOEXneyY3BnxKC0+NgdHu1gU8go9vEP1 182 i+Flh5uoS70+MBIO+nmF8T+9JWIx2QWFDDxvcuFosnIhvUajCEQohauys5FMz/H/WvB0vrbTBpvK 183 eg== 184 ` 185 186 const happySerialUC20AssertionResponse = `type: serial 187 authority-id: testrootorg 188 brand-id: testrootorg 189 model: test-snapd-core-20-amd64 190 serial: 7777 191 device-key: 192 AcbBTQRWhcGAARAAuKf9n7WvZDI7u3NzMkD8WN+dxCYrb0UE9XIaHcbrj0i2zJpxCtUtpzoEo7Uk 193 Cvxuhr2uBpzAa8fScwzOd77MGHIZQDpS7sFSkhYsSSN0m4sy8vRevsj0roN31fugCjRnhtLTkgxo 194 KSoAsK87vYnC+m5V5AHaRER7q1KgpUoVD7eLOJZyrd/tWecsLL9OK87yAQHdF/cVlQupOP6OU3fK 195 DllER6V2TD4jADK2Gyj2lDhy3F0+rE0a+zsGpmQQBorvzbozUHgBE3z/XjTTMrHYP4m+4V5HeWdn 196 rHt/x1LZ8wMTCMT1eeruclC82UPRgF0zWI+P7WgBqogJpCbfadhAj1zvKW+5vJ385n0BU7PoAZtA 197 KddBbsmEnfK/gWIxgFemIrYcYGhIBxYY6iNcygTYRFo4R9xm3bELHLG+viHggih4Lrjnb4sLHOdC 198 h3C4/45bY+6hSno8GQGlp4kYQQM8mrF9st51jIM6oyB84NtoySLYYE1wMeGNzDHSuI+1IiRmaTgy 199 Q2ImXTuqOhclhNA1sOi3R4H+oOBxe6GmoM5ATBPBqJeqUEvK8GpSRCig0QH4qMNF/abNKwvKhGMZ 200 LqtpFp5LNx7xYuAwoVkcq0nxQTsXctl3gJqY+lRx7mIeoXLZPKZyJees+5v96oa9lMdNX3f5UUpX 201 zq0cNhdgHrXZfcsAEQEAAQ== 202 device-key-sha3-384: CZeO_5nJm_Rg0izosNfcQRoQj9nFtAmK2Y_tz4YjlKlvS93b_9gTDHuby5HHwi7d 203 timestamp: 2020-09-03T14:42:47-05:00 204 sign-key-sha3-384: hIedp1AvrWlcDI4uS_qjoFLzjKl5enu4G2FYJpgB3Pj-tUzGlTQBxMBsBmi-tnJR 205 206 AcLBUgQAAQoABgUCX1FHNwAAqFoQABFiyzipoTYAuYN0Wd7cXuPPD7z+z+E+LoZZ+j4vUKqvnGX8 207 tksb2nEEOQhjSvVof5pPOswWgq8Nj52dtYA20R5Zgfy0MZHHcCCfgxaRj6EiFyrG5h9l5wWMnzdb 208 pXo9SJ3hxw6lKdj3n9RAAY0mACvw6f/trcyLeSxQ7EBm6X9c4ohJSjlHkKj0TlKkNTrFflko5aQH 209 uJUk/YgsvMTZUHbgj6QKHlODUH8iRvOHxzn/Y9BlnzBsb/SyzvNTPeQyzFtd9QkESI2sWghviys2 210 fGeEZPeXU6xts6Ht+xhr3mj5npZwkkL/6YxSzm9owQ0zGrfaFTswN+xoDKZ5498qRtSY3mCK/5xx 211 kvWpOTHHhfvuS3GGyvRZOih7IAffDEwQsUNh8V9IjQNNTIkCYTPZz4WBM42mI8UgeDsnDImmcoc0 212 GlqBeCxUigszJlEdUAHQklwW7Sgp13mceR3zB7BHgp4Sk7n0RyPuTQUA94ys6SeesK5YphwmhVed 213 V02lkdeqRbGt3yZ/T5Zg8CIUIM0RKDSqoHgvoCMZh98dRGv6LPRj/P0RSWmjYWotjdK+lXK1fySM 214 RXMNJIInZoC0x8qEwGLXVl5V3z8motLG71ie7PQ677W0dE9XM5LRnZHEKXP41jfaOO9vu12TtBsh 215 pe/pnYDfIzU6OyOsdmkGWaWD+nbD 216 ` 217 218 const noModelAssertionYetResponse = ` 219 { 220 "type": "error", 221 "status-code": 404, 222 "status": "Not Found", 223 "result": { 224 "message": "no model assertion yet", 225 "kind": "assertion-not-found", 226 "value": "model" 227 } 228 }` 229 230 const noSerialAssertionYetResponse = ` 231 { 232 "type": "error", 233 "status-code": 404, 234 "status": "Not Found", 235 "result": { 236 "message": "no serial assertion yet", 237 "kind": "assertion-not-found", 238 "value": "serial" 239 } 240 }` 241 242 // helper for constructing different types of responses to the client 243 type checkResponder func(c *check.C, w http.ResponseWriter, r *http.Request) 244 245 func simpleHappyResponder(body string) checkResponder { 246 return func(c *check.C, w http.ResponseWriter, r *http.Request) { 247 c.Check(r.Method, check.Equals, "GET") 248 c.Check(r.URL.RawQuery, check.Equals, "") 249 fmt.Fprintln(w, body) 250 } 251 } 252 253 func simpleUnhappyResponder(errBody string) checkResponder { 254 return func(c *check.C, w http.ResponseWriter, r *http.Request) { 255 c.Check(r.Method, check.Equals, "GET") 256 c.Check(r.URL.RawQuery, check.Equals, "") 257 w.Header().Set("Content-Type", "application/json") 258 w.WriteHeader(404) 259 fmt.Fprintln(w, errBody) 260 } 261 } 262 263 func simpleAssertionAccountResponder(body string) checkResponder { 264 return func(c *check.C, w http.ResponseWriter, r *http.Request) { 265 c.Check(r.Method, check.Equals, "GET") 266 w.Header().Set("X-Ubuntu-Assertions-Count", "1") 267 fmt.Fprintln(w, body) 268 } 269 } 270 271 func makeHappyTestServerHandler(c *check.C, modelResp, serialResp, accountResp checkResponder) func(w http.ResponseWriter, r *http.Request) { 272 var nModelSerial, nModel, nKnown int 273 return func(w http.ResponseWriter, r *http.Request) { 274 switch r.URL.Path { 275 case "/v2/model": 276 switch nModel { 277 case 0: 278 modelResp(c, w, r) 279 default: 280 c.Fatalf("expected to get 1 request for /v2/model, now on %d", nModel+1) 281 } 282 nModel++ 283 case "/v2/model/serial": 284 switch nModelSerial { 285 case 0: 286 serialResp(c, w, r) 287 default: 288 c.Fatalf("expected to get 1 request for /v2/model, now on %d", nModelSerial+1) 289 } 290 nModelSerial++ 291 case "/v2/assertions/account": 292 switch nKnown { 293 case 0: 294 accountResp(c, w, r) 295 default: 296 c.Fatalf("expected to get 1 request for /v2/model, now on %d", nKnown+1) 297 } 298 nKnown++ 299 default: 300 c.Fatalf("unexpected request to %s", r.URL.Path) 301 } 302 } 303 } 304 305 func (s *SnapSuite) TestNoModelYet(c *check.C) { 306 s.RedirectClientToTestServer( 307 makeHappyTestServerHandler( 308 c, 309 simpleUnhappyResponder(noModelAssertionYetResponse), 310 simpleUnhappyResponder(noSerialAssertionYetResponse), 311 simpleAssertionAccountResponder(happyAccountAssertionResponse), 312 )) 313 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"model"}) 314 c.Assert(err, check.ErrorMatches, `device not ready yet \(no assertions found\)`) 315 } 316 317 func (s *SnapSuite) TestNoSerialYet(c *check.C) { 318 s.RedirectClientToTestServer( 319 makeHappyTestServerHandler( 320 c, 321 simpleHappyResponder(happyModelAssertionResponse), 322 simpleUnhappyResponder(noSerialAssertionYetResponse), 323 simpleAssertionAccountResponder(happyAccountAssertionResponse), 324 )) 325 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--serial"}) 326 c.Assert(err, check.ErrorMatches, `device not registered yet \(no serial assertion found\)`) 327 c.Check(s.Stderr(), check.Equals, "") 328 c.Check(s.Stdout(), check.Equals, ` 329 brand-id: mememe 330 model: test-model 331 `[1:]) 332 } 333 334 func (s *SnapSuite) TestModel(c *check.C) { 335 336 for _, tt := range []struct { 337 comment string 338 modelF checkResponder 339 serialF checkResponder 340 outText string 341 }{ 342 { 343 comment: "normal serial and model asserts", 344 modelF: simpleHappyResponder(happyModelAssertionResponse), 345 serialF: simpleHappyResponder(happySerialAssertionResponse), 346 outText: ` 347 brand MeMeMe (meuser*) 348 model test-model 349 serial serialserial 350 `[1:], 351 }, 352 { 353 comment: "normal uc20 serial and model asserts", 354 modelF: simpleHappyResponder(happyUC20ModelAssertionResponse), 355 serialF: simpleHappyResponder(happySerialUC20AssertionResponse), 356 outText: ` 357 brand MeMeMe (meuser*) 358 model test-snapd-core-20-amd64 359 grade secured 360 serial 7777 361 `[1:], 362 }, 363 { 364 comment: "model assert has display-name", 365 modelF: simpleHappyResponder(happyModelWithDisplayNameAssertionResponse), 366 serialF: simpleHappyResponder(happySerialAssertionResponse), 367 outText: ` 368 brand MeMeMe (meuser*) 369 model Model Name (test-model) 370 serial serialserial 371 `[1:], 372 }, 373 { 374 comment: "missing serial assert", 375 modelF: simpleHappyResponder(happyModelAssertionResponse), 376 serialF: simpleUnhappyResponder(noSerialAssertionYetResponse), 377 outText: ` 378 brand MeMeMe (meuser*) 379 model test-model 380 serial - (device not registered yet) 381 `[1:], 382 }, 383 } { 384 s.RedirectClientToTestServer( 385 makeHappyTestServerHandler( 386 c, 387 tt.modelF, 388 tt.serialF, 389 simpleAssertionAccountResponder(happyAccountAssertionResponse), 390 )) 391 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model"}) 392 c.Assert(err, check.IsNil) 393 c.Assert(rest, check.DeepEquals, []string{}) 394 c.Check(s.Stdout(), check.Equals, tt.outText, check.Commentf("\n%s\n", tt.outText)) 395 c.Check(s.Stderr(), check.Equals, "") 396 s.ResetStdStreams() 397 } 398 } 399 400 func (s *SnapSuite) TestModelVerbose(c *check.C) { 401 s.RedirectClientToTestServer( 402 makeHappyTestServerHandler( 403 c, 404 simpleHappyResponder(happyModelAssertionResponse), 405 simpleHappyResponder(happySerialAssertionResponse), 406 simpleAssertionAccountResponder(happyAccountAssertionResponse), 407 )) 408 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--verbose", "--abs-time"}) 409 c.Assert(err, check.IsNil) 410 c.Assert(rest, check.DeepEquals, []string{}) 411 c.Check(s.Stdout(), check.Equals, ` 412 brand-id: mememe 413 model: test-model 414 serial: serialserial 415 architecture: amd64 416 base: core18 417 gadget: pc=18 418 kernel: pc-kernel=18 419 store: mememestore 420 system-user-authority: 421 - youyouyou 422 - mememe 423 timestamp: 2017-07-27T00:00:00Z 424 required-snaps: 425 - core 426 - hello-world 427 `[1:]) 428 c.Check(s.Stderr(), check.Equals, "") 429 } 430 431 func (s *SnapSuite) TestModelVerboseDisplayName(c *check.C) { 432 s.RedirectClientToTestServer( 433 makeHappyTestServerHandler( 434 c, 435 simpleHappyResponder(happyModelWithDisplayNameAssertionResponse), 436 simpleHappyResponder(happySerialAssertionResponse), 437 simpleAssertionAccountResponder(happyAccountAssertionResponse), 438 )) 439 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--verbose", "--abs-time"}) 440 c.Assert(err, check.IsNil) 441 c.Assert(rest, check.DeepEquals, []string{}) 442 c.Check(s.Stdout(), check.Equals, ` 443 brand-id: mememe 444 model: test-model 445 serial: serialserial 446 architecture: amd64 447 base: core18 448 display-name: Model Name 449 gadget: pc=18 450 kernel: pc-kernel=18 451 store: mememestore 452 system-user-authority: 453 - youyouyou 454 - mememe 455 timestamp: 2017-07-27T00:00:00Z 456 required-snaps: 457 - core 458 - hello-world 459 `[1:]) 460 c.Check(s.Stderr(), check.Equals, "") 461 } 462 463 func (s *SnapSuite) TestModelVerboseNoSerialYet(c *check.C) { 464 s.RedirectClientToTestServer( 465 makeHappyTestServerHandler( 466 c, 467 simpleHappyResponder(happyModelAssertionResponse), 468 simpleUnhappyResponder(noSerialAssertionYetResponse), 469 simpleAssertionAccountResponder(happyAccountAssertionResponse), 470 )) 471 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--verbose", "--abs-time"}) 472 c.Assert(err, check.IsNil) 473 c.Assert(rest, check.DeepEquals, []string{}) 474 c.Check(s.Stdout(), check.Equals, ` 475 brand-id: mememe 476 model: test-model 477 serial: -- (device not registered yet) 478 architecture: amd64 479 base: core18 480 gadget: pc=18 481 kernel: pc-kernel=18 482 store: mememestore 483 system-user-authority: 484 - youyouyou 485 - mememe 486 timestamp: 2017-07-27T00:00:00Z 487 required-snaps: 488 - core 489 - hello-world 490 `[1:]) 491 c.Check(s.Stderr(), check.Equals, "") 492 } 493 494 func (s *SnapSuite) TestModelAssertion(c *check.C) { 495 s.RedirectClientToTestServer( 496 makeHappyTestServerHandler( 497 c, 498 simpleHappyResponder(happyModelAssertionResponse), 499 simpleHappyResponder(happySerialAssertionResponse), 500 simpleAssertionAccountResponder(happyAccountAssertionResponse), 501 )) 502 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--assertion"}) 503 c.Assert(err, check.IsNil) 504 c.Assert(rest, check.DeepEquals, []string{}) 505 c.Check(s.Stdout(), check.Equals, happyModelAssertionResponse) 506 c.Check(s.Stderr(), check.Equals, "") 507 } 508 509 func (s *SnapSuite) TestModelAssertionVerbose(c *check.C) { 510 // check that no calls to the server happen 511 s.RedirectClientToTestServer( 512 func(w http.ResponseWriter, r *http.Request) { 513 c.Fatalf("unexpected request to %s", r.URL.Path) 514 }, 515 ) 516 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--assertion", "--verbose"}) 517 c.Assert(err, check.ErrorMatches, "cannot use --verbose with --assertion") 518 c.Check(s.Stdout(), check.Equals, "") 519 c.Check(s.Stderr(), check.Equals, "") 520 } 521 522 func (s *SnapSuite) TestSerial(c *check.C) { 523 s.RedirectClientToTestServer( 524 makeHappyTestServerHandler( 525 c, 526 simpleHappyResponder(happyModelAssertionResponse), 527 simpleHappyResponder(happySerialAssertionResponse), 528 simpleAssertionAccountResponder(happyAccountAssertionResponse), 529 )) 530 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--serial"}) 531 c.Assert(err, check.IsNil) 532 c.Assert(rest, check.DeepEquals, []string{}) 533 c.Check(s.Stdout(), check.Equals, ` 534 brand-id: my-brand 535 model: my-old-model 536 serial: serialserial 537 `[1:]) 538 c.Check(s.Stderr(), check.Equals, "") 539 } 540 541 func (s *SnapSuite) TestSerialVerbose(c *check.C) { 542 s.RedirectClientToTestServer( 543 makeHappyTestServerHandler( 544 c, 545 simpleHappyResponder(happyModelAssertionResponse), 546 simpleHappyResponder(happySerialAssertionResponse), 547 simpleAssertionAccountResponder(happyAccountAssertionResponse), 548 )) 549 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--serial", "--verbose", "--abs-time"}) 550 c.Assert(err, check.IsNil) 551 c.Assert(rest, check.DeepEquals, []string{}) 552 c.Check(s.Stdout(), check.Equals, ` 553 brand-id: my-brand 554 model: my-old-model 555 serial: serialserial 556 timestamp: 2019-08-26T16:34:21-05:00 557 device-key-sha3-384: | 558 iqLo9doLzK8De9925UrdUyuvPbBad72OTWVE9YJXqd6nz9dKvwJ_lHP5bVxrl3VO 559 device-key: | 560 AcZrBFaFwYABAvCgEOrrLA6FKcreHxCcOoTgBUZ+IRG7Nb8tzmEAklaQPGpv7skapUjwD1luE2g 561 omTcoTssVHrfLpBoSDV1aBs44rg3NK40ZKPJP7d2zkds1GxUo1Ea5vfet3SJ4h3aRABEBAAE= 562 `[1:]) 563 c.Check(s.Stderr(), check.Equals, "") 564 } 565 566 func (s *SnapSuite) TestSerialAssertion(c *check.C) { 567 s.RedirectClientToTestServer( 568 makeHappyTestServerHandler( 569 c, 570 simpleHappyResponder(happyModelAssertionResponse), 571 simpleHappyResponder(happySerialAssertionResponse), 572 simpleAssertionAccountResponder(happyAccountAssertionResponse), 573 )) 574 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--serial", "--assertion"}) 575 c.Assert(err, check.IsNil) 576 c.Assert(rest, check.DeepEquals, []string{}) 577 c.Check(s.Stdout(), check.Equals, happySerialAssertionResponse) 578 c.Check(s.Stderr(), check.Equals, "") 579 } 580 581 func (s *SnapSuite) TestSerialAssertionSerialAssertionMissing(c *check.C) { 582 s.RedirectClientToTestServer( 583 makeHappyTestServerHandler( 584 c, 585 simpleHappyResponder(happyModelAssertionResponse), 586 simpleUnhappyResponder(noSerialAssertionYetResponse), 587 simpleAssertionAccountResponder(happyAccountAssertionResponse), 588 )) 589 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"model", "--serial", "--assertion"}) 590 c.Assert(err, check.ErrorMatches, `device not ready yet \(no assertions found\)`) 591 c.Assert(s.Stdout(), check.Equals, "") 592 c.Assert(s.Stderr(), check.Equals, "") 593 }