github.com/rigado/snapd@v2.42.5-go-mod+incompatible/cmd/snap/cmd_auto_import_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 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 "io/ioutil" 25 "net/http" 26 "os" 27 "path/filepath" 28 29 . "gopkg.in/check.v1" 30 31 snap "github.com/snapcore/snapd/cmd/snap" 32 "github.com/snapcore/snapd/dirs" 33 "github.com/snapcore/snapd/logger" 34 "github.com/snapcore/snapd/osutil" 35 "github.com/snapcore/snapd/release" 36 ) 37 38 func makeMockMountInfo(c *C, content string) string { 39 fn := filepath.Join(c.MkDir(), "mountinfo") 40 err := ioutil.WriteFile(fn, []byte(content), 0644) 41 c.Assert(err, IsNil) 42 return fn 43 } 44 45 func (s *SnapSuite) TestAutoImportAssertsHappy(c *C) { 46 restore := release.MockOnClassic(false) 47 defer restore() 48 49 fakeAssertData := []byte("my-assertion") 50 51 n := 0 52 total := 2 53 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 54 switch n { 55 case 0: 56 c.Check(r.Method, Equals, "POST") 57 c.Check(r.URL.Path, Equals, "/v2/assertions") 58 postData, err := ioutil.ReadAll(r.Body) 59 c.Assert(err, IsNil) 60 c.Check(postData, DeepEquals, fakeAssertData) 61 fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`) 62 n++ 63 case 1: 64 c.Check(r.Method, Equals, "POST") 65 c.Check(r.URL.Path, Equals, "/v2/create-user") 66 postData, err := ioutil.ReadAll(r.Body) 67 c.Assert(err, IsNil) 68 c.Check(string(postData), Equals, `{"sudoer":true,"known":true}`) 69 70 fmt.Fprintln(w, `{"type": "sync", "result": [{"username": "foo"}]}`) 71 n++ 72 default: 73 c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n) 74 } 75 76 }) 77 78 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 79 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 80 c.Assert(err, IsNil) 81 82 mockMountInfoFmt := ` 83 24 0 8:18 / %s rw,relatime shared:1 - ext4 /dev/sdb2 rw,errors=remount-ro,data=ordered` 84 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 85 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 86 defer restore() 87 88 logbuf, restore := logger.MockLogger() 89 defer restore() 90 91 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 92 c.Assert(err, IsNil) 93 c.Assert(rest, DeepEquals, []string{}) 94 c.Check(s.Stdout(), Equals, `created user "foo"`+"\n") 95 // matches because we may get a: 96 // "WARNING: cannot create syslog logger\n" 97 // in the output 98 c.Check(logbuf.String(), Matches, fmt.Sprintf("(?ms).*imported %s\n", fakeAssertsFn)) 99 c.Check(n, Equals, total) 100 } 101 102 func (s *SnapSuite) TestAutoImportAssertsNotImportedFromLoop(c *C) { 103 restore := release.MockOnClassic(false) 104 defer restore() 105 106 fakeAssertData := []byte("bad-assertion") 107 108 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 109 // assertion is ignored, nothing is posted to this endpoint 110 panic("not reached") 111 }) 112 113 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 114 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 115 c.Assert(err, IsNil) 116 117 mockMountInfoFmtWithLoop := ` 118 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/loop1 rw,errors=remount-ro,data=ordered` 119 content := fmt.Sprintf(mockMountInfoFmtWithLoop, filepath.Dir(fakeAssertsFn)) 120 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 121 defer restore() 122 123 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 124 c.Assert(err, IsNil) 125 c.Assert(rest, DeepEquals, []string{}) 126 c.Check(s.Stdout(), Equals, "") 127 c.Check(s.Stderr(), Equals, "") 128 } 129 130 func (s *SnapSuite) TestAutoImportCandidatesHappy(c *C) { 131 dirs := make([]string, 4) 132 args := make([]interface{}, len(dirs)) 133 files := make([]string, len(dirs)) 134 for i := range dirs { 135 dirs[i] = c.MkDir() 136 args[i] = dirs[i] 137 files[i] = filepath.Join(dirs[i], "auto-import.assert") 138 err := ioutil.WriteFile(files[i], nil, 0644) 139 c.Assert(err, IsNil) 140 } 141 142 mockMountInfoFmtWithLoop := ` 143 too short 144 24 0 8:18 / %[1]s rw,relatime foo ext3 /dev/meep2 no,separator 145 24 0 8:18 / %[2]s rw,relatime - ext3 /dev/meep2 rw,errors=remount-ro,data=ordered 146 24 0 8:18 / %[3]s rw,relatime opt:1 - ext4 /dev/meep3 rw,errors=remount-ro,data=ordered 147 24 0 8:18 / %[4]s rw,relatime opt:1 opt:2 - ext2 /dev/meep1 rw,errors=remount-ro,data=ordered 148 ` 149 150 content := fmt.Sprintf(mockMountInfoFmtWithLoop, args...) 151 restore := snap.MockMountInfoPath(makeMockMountInfo(c, content)) 152 defer restore() 153 154 l, err := snap.AutoImportCandidates() 155 c.Check(err, IsNil) 156 c.Check(l, DeepEquals, files[1:]) 157 } 158 159 func (s *SnapSuite) TestAutoImportAssertsHappyNotOnClassic(c *C) { 160 restore := release.MockOnClassic(true) 161 defer restore() 162 163 fakeAssertData := []byte("my-assertion") 164 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 165 c.Errorf("auto-import on classic is disabled, but something tried to do a %q with %s", r.Method, r.URL.Path) 166 }) 167 168 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 169 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 170 c.Assert(err, IsNil) 171 172 mockMountInfoFmt := ` 173 24 0 8:18 / %s rw,relatime shared:1 - ext4 /dev/sdb2 rw,errors=remount-ro,data=ordered` 174 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 175 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 176 defer restore() 177 178 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 179 c.Assert(err, IsNil) 180 c.Assert(rest, DeepEquals, []string{}) 181 c.Check(s.Stdout(), Equals, "") 182 c.Check(s.Stderr(), Equals, "auto-import is disabled on classic\n") 183 } 184 185 func (s *SnapSuite) TestAutoImportIntoSpool(c *C) { 186 restore := release.MockOnClassic(false) 187 defer restore() 188 189 logbuf, restore := logger.MockLogger() 190 defer restore() 191 192 fakeAssertData := []byte("good-assertion") 193 194 // ensure we can not connect 195 snap.ClientConfig.BaseURL = "can-not-connect-to-this-url" 196 197 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 198 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 199 c.Assert(err, IsNil) 200 201 mockMountInfoFmt := ` 202 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/sc1 rw,errors=remount-ro,data=ordered` 203 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 204 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 205 defer restore() 206 207 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 208 c.Assert(err, IsNil) 209 c.Assert(rest, DeepEquals, []string{}) 210 c.Check(s.Stdout(), Equals, "") 211 // matches because we may get a: 212 // "WARNING: cannot create syslog logger\n" 213 // in the output 214 c.Check(logbuf.String(), Matches, "(?ms).*queuing for later.*\n") 215 216 files, err := ioutil.ReadDir(dirs.SnapAssertsSpoolDir) 217 c.Assert(err, IsNil) 218 c.Check(files, HasLen, 1) 219 c.Check(files[0].Name(), Equals, "iOkaeet50rajLvL-0Qsf2ELrTdn3XIXRIBlDewcK02zwRi3_TJlUOTl9AaiDXmDn.assert") 220 } 221 222 func (s *SnapSuite) TestAutoImportFromSpoolHappy(c *C) { 223 restore := release.MockOnClassic(false) 224 defer restore() 225 226 fakeAssertData := []byte("my-assertion") 227 228 n := 0 229 total := 2 230 s.RedirectClientToTestServer(func(w http.ResponseWriter, r *http.Request) { 231 switch n { 232 case 0: 233 c.Check(r.Method, Equals, "POST") 234 c.Check(r.URL.Path, Equals, "/v2/assertions") 235 postData, err := ioutil.ReadAll(r.Body) 236 c.Assert(err, IsNil) 237 c.Check(postData, DeepEquals, fakeAssertData) 238 fmt.Fprintln(w, `{"type": "sync", "result": {"ready": true, "status": "Done"}}`) 239 n++ 240 case 1: 241 c.Check(r.Method, Equals, "POST") 242 c.Check(r.URL.Path, Equals, "/v2/create-user") 243 postData, err := ioutil.ReadAll(r.Body) 244 c.Assert(err, IsNil) 245 c.Check(string(postData), Equals, `{"sudoer":true,"known":true}`) 246 247 fmt.Fprintln(w, `{"type": "sync", "result": [{"username": "foo"}]}`) 248 n++ 249 default: 250 c.Fatalf("unexpected request: %v (expected %d got %d)", r, total, n) 251 } 252 253 }) 254 255 fakeAssertsFn := filepath.Join(dirs.SnapAssertsSpoolDir, "1234343") 256 err := os.MkdirAll(filepath.Dir(fakeAssertsFn), 0755) 257 c.Assert(err, IsNil) 258 err = ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 259 c.Assert(err, IsNil) 260 261 logbuf, restore := logger.MockLogger() 262 defer restore() 263 264 rest, err := snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 265 c.Assert(err, IsNil) 266 c.Assert(rest, DeepEquals, []string{}) 267 c.Check(s.Stdout(), Equals, `created user "foo"`+"\n") 268 // matches because we may get a: 269 // "WARNING: cannot create syslog logger\n" 270 // in the output 271 c.Check(logbuf.String(), Matches, fmt.Sprintf("(?ms).*imported %s\n", fakeAssertsFn)) 272 c.Check(n, Equals, total) 273 274 c.Check(osutil.FileExists(fakeAssertsFn), Equals, false) 275 } 276 277 func (s *SnapSuite) TestAutoImportIntoSpoolUnhappyTooBig(c *C) { 278 restore := release.MockOnClassic(false) 279 defer restore() 280 281 _, restoreLogger := logger.MockLogger() 282 defer restoreLogger() 283 284 // fake data is bigger than the default assertion limit 285 fakeAssertData := make([]byte, 641*1024) 286 287 // ensure we can not connect 288 snap.ClientConfig.BaseURL = "can-not-connect-to-this-url" 289 290 fakeAssertsFn := filepath.Join(c.MkDir(), "auto-import.assert") 291 err := ioutil.WriteFile(fakeAssertsFn, fakeAssertData, 0644) 292 c.Assert(err, IsNil) 293 294 mockMountInfoFmt := ` 295 24 0 8:18 / %s rw,relatime shared:1 - squashfs /dev/sc1 rw,errors=remount-ro,data=ordered` 296 content := fmt.Sprintf(mockMountInfoFmt, filepath.Dir(fakeAssertsFn)) 297 restore = snap.MockMountInfoPath(makeMockMountInfo(c, content)) 298 defer restore() 299 300 _, err = snap.Parser(snap.Client()).ParseArgs([]string{"auto-import"}) 301 c.Assert(err, ErrorMatches, "cannot queue .*, file size too big: 656384") 302 }