github.com/chipaca/snappy@v0.0.0-20210104084008-1f06296fe8ad/cmd/snap/cmd_recovery_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2020 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 "github.com/snapcore/snapd/release" 30 ) 31 32 func (s *SnapSuite) TestRecoveryHelp(c *C) { 33 msg := `Usage: 34 snap.test recovery [recovery-OPTIONS] 35 36 The recovery command lists the available recovery systems. 37 38 With --show-keys it displays recovery keys that can be used to unlock the 39 encrypted partitions if the device-specific automatic unlocking does not work. 40 41 [recovery command options] 42 --color=[auto|never|always] Use a little bit of color to highlight 43 some things. (default: auto) 44 --unicode=[auto|never|always] Use a little bit of Unicode to improve 45 legibility. (default: auto) 46 --show-keys Show recovery keys (if available) to 47 unlock encrypted partitions. 48 ` 49 s.testSubCommandHelp(c, "recovery", msg) 50 } 51 52 func (s *SnapSuite) TestRecovery(c *C) { 53 n := 0 54 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 55 switch n { 56 case 0: 57 c.Check(r.Method, Equals, "GET") 58 c.Check(r.URL.Path, Equals, "/v2/systems") 59 c.Check(r.URL.RawQuery, Equals, "") 60 fmt.Fprintln(w, `{"type": "sync", "result": { 61 "systems": [ 62 { 63 "current": true, 64 "label": "20200101", 65 "model": { 66 "model": "model-id-1", 67 "brand-id": "brand-id-1", 68 "display-name": "Wonky Model" 69 }, 70 "brand": { 71 "id": "brand-id-1", 72 "username": "brand-1", 73 "display-name": "Wonky Publishing" 74 }, 75 "actions": [ 76 {"title": "recover", "mode": "recover"}, 77 {"title": "reinstall", "mode": "install"} 78 ] 79 }, 80 { 81 "label": "20200802", 82 "model": { 83 "model": "model-id-2", 84 "brand-id": "brand-id-1", 85 "display-name": "Other Model" 86 }, 87 "brand": { 88 "id": "brand-id-2", 89 "username": "brand-2", 90 "display-name": "Other Publishing" 91 }, 92 "actions": [ 93 {"title": "recover", "mode": "recover"}, 94 {"title": "reinstall", "mode": "install"} 95 ] 96 } 97 ] 98 }}`) 99 default: 100 c.Fatalf("expected to get 1 requests, now on %d", n+1) 101 } 102 103 n++ 104 }) 105 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"recovery"}) 106 c.Assert(err, IsNil) 107 c.Assert(rest, DeepEquals, []string{}) 108 c.Check(s.Stdout(), Equals, ` 109 Label Brand Model Notes 110 20200101 brand-1 model-id-1 current 111 20200802 brand-2 model-id-2 - 112 `[1:]) 113 c.Check(s.Stderr(), Equals, "") 114 } 115 116 func (s *SnapSuite) TestNoRecoverySystems(c *C) { 117 n := 0 118 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 119 switch n { 120 case 0: 121 c.Check(r.Method, Equals, "GET") 122 c.Check(r.URL.Path, Equals, "/v2/systems") 123 c.Check(r.URL.RawQuery, Equals, "") 124 fmt.Fprintln(w, `{"type": "sync", "result": {}}`) 125 default: 126 c.Fatalf("expected to get 1 requests, now on %d", n+1) 127 } 128 129 n++ 130 }) 131 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"recovery"}) 132 c.Assert(err, IsNil) 133 c.Assert(rest, DeepEquals, []string{}) 134 c.Check(s.Stdout(), Equals, "") 135 c.Check(s.Stderr(), Equals, "No recovery systems available.\n") 136 } 137 138 func (s *SnapSuite) TestNoRecoverySystemsError(c *C) { 139 n := 0 140 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 141 switch n { 142 case 0: 143 c.Check(r.Method, Equals, "GET") 144 c.Check(r.URL.Path, Equals, "/v2/systems") 145 c.Check(r.URL.RawQuery, Equals, "") 146 fmt.Fprintln(w, `{"type": "error", "result": {"message": "permission denied"}, "status-code": 403}`) 147 default: 148 c.Fatalf("expected to get 1 requests, now on %d", n+1) 149 } 150 151 n++ 152 }) 153 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"recovery"}) 154 c.Check(err, ErrorMatches, `cannot list recovery systems: permission denied`) 155 } 156 157 func (s *SnapSuite) TestRecoveryShowRecoveryKeyOnClassicErrors(c *C) { 158 restore := release.MockOnClassic(true) 159 defer restore() 160 161 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 162 c.Fatalf("unexpected server call") 163 }) 164 _, err := snap.Parser(snap.Client()).ParseArgs([]string{"recovery", "--show-keys"}) 165 c.Assert(err, ErrorMatches, `command "show-keys" is not available on classic systems`) 166 } 167 168 func (s *SnapSuite) TestRecoveryShowRecoveryKeyHappy(c *C) { 169 restore := release.MockOnClassic(false) 170 defer restore() 171 172 n := 0 173 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 174 switch n { 175 case 0: 176 c.Check(r.Method, Equals, "GET") 177 c.Check(r.URL.Path, Equals, "/v2/system-recovery-keys") 178 c.Check(r.URL.RawQuery, Equals, "") 179 fmt.Fprintln(w, `{"type": "sync", "result": {"recovery-key": "61665-00531-54469-09783-47273-19035-40077-28287", "reinstall-key":"1234"}}`) 180 default: 181 c.Fatalf("expected to get 1 requests, now on %d", n+1) 182 } 183 184 n++ 185 }) 186 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"recovery", "--show-keys"}) 187 c.Assert(err, IsNil) 188 c.Assert(rest, DeepEquals, []string{}) 189 c.Check(s.Stdout(), Equals, `recovery: 61665-00531-54469-09783-47273-19035-40077-28287 190 reinstall: 1234 191 `) 192 c.Check(s.Stderr(), Equals, "") 193 c.Check(n, Equals, 1) 194 }