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