github.com/kubiko/snapd@v0.0.0-20201013125620-d4f3094d9ddf/seed/seed20_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2019-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 seed_test 21 22 import ( 23 "fmt" 24 "os" 25 "path/filepath" 26 "strings" 27 "time" 28 29 . "gopkg.in/check.v1" 30 31 "github.com/snapcore/snapd/asserts" 32 "github.com/snapcore/snapd/asserts/assertstest" 33 "github.com/snapcore/snapd/osutil" 34 "github.com/snapcore/snapd/seed" 35 "github.com/snapcore/snapd/seed/seedtest" 36 "github.com/snapcore/snapd/seed/seedwriter" 37 "github.com/snapcore/snapd/snap" 38 "github.com/snapcore/snapd/snap/snaptest" 39 "github.com/snapcore/snapd/testutil" 40 "github.com/snapcore/snapd/timings" 41 ) 42 43 type seed20Suite struct { 44 testutil.BaseTest 45 46 *seedtest.TestingSeed20 47 devAcct *asserts.Account 48 49 db *asserts.Database 50 51 perfTimings timings.Measurer 52 } 53 54 var _ = Suite(&seed20Suite{}) 55 56 func (s *seed20Suite) SetUpTest(c *C) { 57 s.BaseTest.SetUpTest(c) 58 s.AddCleanup(snap.MockSanitizePlugsSlots(func(snapInfo *snap.Info) {})) 59 60 s.TestingSeed20 = &seedtest.TestingSeed20{} 61 s.SetupAssertSigning("canonical") 62 s.Brands.Register("my-brand", brandPrivKey, map[string]interface{}{ 63 "verification": "verified", 64 }) 65 // needed by TestingSeed20.MakeSeed (to work with makeSnap) 66 67 s.devAcct = assertstest.NewAccount(s.StoreSigning, "developer", map[string]interface{}{ 68 "account-id": "developerid", 69 }, "") 70 assertstest.AddMany(s.StoreSigning, s.devAcct) 71 72 s.SeedDir = c.MkDir() 73 74 db, err := asserts.OpenDatabase(&asserts.DatabaseConfig{ 75 Backstore: asserts.NewMemoryBackstore(), 76 Trusted: s.StoreSigning.Trusted, 77 }) 78 c.Assert(err, IsNil) 79 s.db = db 80 81 s.perfTimings = timings.New(nil) 82 } 83 84 func (s *seed20Suite) commitTo(b *asserts.Batch) error { 85 return b.CommitTo(s.db, nil) 86 } 87 88 func (s *seed20Suite) makeSnap(c *C, yamlKey, publisher string) { 89 if publisher == "" { 90 publisher = "canonical" 91 } 92 s.MakeAssertedSnap(c, snapYaml[yamlKey], nil, snap.R(1), publisher, s.StoreSigning.Database) 93 } 94 95 func (s *seed20Suite) expectedPath(snapName string) string { 96 return filepath.Join(s.SeedDir, "snaps", s.AssertedSnapInfo(snapName).Filename()) 97 } 98 99 func (s *seed20Suite) TestLoadMetaCore20Minimal(c *C) { 100 s.makeSnap(c, "snapd", "") 101 s.makeSnap(c, "core20", "") 102 s.makeSnap(c, "pc-kernel=20", "") 103 s.makeSnap(c, "pc=20", "") 104 105 sysLabel := "20191018" 106 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 107 "display-name": "my model", 108 "architecture": "amd64", 109 "base": "core20", 110 "snaps": []interface{}{ 111 map[string]interface{}{ 112 "name": "pc-kernel", 113 "id": s.AssertedSnapID("pc-kernel"), 114 "type": "kernel", 115 "default-channel": "20", 116 }, 117 map[string]interface{}{ 118 "name": "pc", 119 "id": s.AssertedSnapID("pc"), 120 "type": "gadget", 121 "default-channel": "20", 122 }}, 123 }, nil) 124 125 seed20, err := seed.Open(s.SeedDir, sysLabel) 126 c.Assert(err, IsNil) 127 128 err = seed20.LoadAssertions(s.db, s.commitTo) 129 c.Assert(err, IsNil) 130 131 err = seed20.LoadMeta(s.perfTimings) 132 c.Assert(err, IsNil) 133 134 c.Check(seed20.UsesSnapdSnap(), Equals, true) 135 136 essSnaps := seed20.EssentialSnaps() 137 c.Check(essSnaps, HasLen, 4) 138 139 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 140 { 141 Path: s.expectedPath("snapd"), 142 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 143 EssentialType: snap.TypeSnapd, 144 Essential: true, 145 Required: true, 146 Channel: "latest/stable", 147 }, { 148 Path: s.expectedPath("pc-kernel"), 149 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 150 EssentialType: snap.TypeKernel, 151 Essential: true, 152 Required: true, 153 Channel: "20", 154 }, { 155 Path: s.expectedPath("core20"), 156 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 157 EssentialType: snap.TypeBase, 158 Essential: true, 159 Required: true, 160 Channel: "latest/stable", 161 }, { 162 Path: s.expectedPath("pc"), 163 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 164 EssentialType: snap.TypeGadget, 165 Essential: true, 166 Required: true, 167 Channel: "20", 168 }, 169 }) 170 171 // check that PlaceInfo method works 172 pi := essSnaps[0].PlaceInfo() 173 c.Check(pi.Filename(), Equals, "snapd_1.snap") 174 pi = essSnaps[1].PlaceInfo() 175 c.Check(pi.Filename(), Equals, "pc-kernel_1.snap") 176 pi = essSnaps[2].PlaceInfo() 177 c.Check(pi.Filename(), Equals, "core20_1.snap") 178 pi = essSnaps[3].PlaceInfo() 179 c.Check(pi.Filename(), Equals, "pc_1.snap") 180 181 runSnaps, err := seed20.ModeSnaps("run") 182 c.Assert(err, IsNil) 183 c.Check(runSnaps, HasLen, 0) 184 } 185 186 func (s *seed20Suite) makeCore20MinimalSeed(c *C, sysLabel string) string { 187 s.makeSnap(c, "snapd", "") 188 s.makeSnap(c, "core20", "") 189 s.makeSnap(c, "pc-kernel=20", "") 190 s.makeSnap(c, "pc=20", "") 191 192 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 193 "display-name": "my model", 194 "architecture": "amd64", 195 "base": "core20", 196 "snaps": []interface{}{ 197 map[string]interface{}{ 198 "name": "pc-kernel", 199 "id": s.AssertedSnapID("pc-kernel"), 200 "type": "kernel", 201 "default-channel": "20", 202 }, 203 map[string]interface{}{ 204 "name": "pc", 205 "id": s.AssertedSnapID("pc"), 206 "type": "gadget", 207 "default-channel": "20", 208 }}, 209 }, nil) 210 211 return filepath.Join(s.SeedDir, "systems", sysLabel) 212 } 213 214 func (s *seed20Suite) TestLoadAssertionsModelTempDBHappy(c *C) { 215 r := seed.MockTrusted(s.StoreSigning.Trusted) 216 defer r() 217 218 sysLabel := "20191031" 219 s.makeCore20MinimalSeed(c, sysLabel) 220 221 seed20, err := seed.Open(s.SeedDir, sysLabel) 222 c.Assert(err, IsNil) 223 224 err = seed20.LoadAssertions(nil, nil) 225 c.Assert(err, IsNil) 226 227 model := seed20.Model() 228 c.Check(model.Model(), Equals, "my-model") 229 c.Check(model.Base(), Equals, "core20") 230 231 brand, err := seed20.Brand() 232 c.Assert(err, IsNil) 233 c.Check(brand.AccountID(), Equals, "my-brand") 234 c.Check(brand.DisplayName(), Equals, "My-brand") 235 } 236 237 func (s *seed20Suite) TestLoadAssertionsMultiModels(c *C) { 238 sysLabel := "20191031" 239 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 240 241 err := osutil.CopyFile(filepath.Join(sysDir, "model"), filepath.Join(sysDir, "assertions", "model2"), 0) 242 c.Assert(err, IsNil) 243 244 seed20, err := seed.Open(s.SeedDir, sysLabel) 245 c.Assert(err, IsNil) 246 247 err = seed20.LoadAssertions(s.db, s.commitTo) 248 c.Check(err, ErrorMatches, `system cannot have any model assertion but the one in the system model assertion file`) 249 } 250 251 func (s *seed20Suite) TestLoadAssertionsInvalidModelAssertFile(c *C) { 252 sysLabel := "20191031" 253 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 254 255 modelAssertFn := filepath.Join(sysDir, "model") 256 257 // copy over multiple assertions 258 err := osutil.CopyFile(filepath.Join(sysDir, "assertions", "model-etc"), modelAssertFn, osutil.CopyFlagOverwrite) 259 c.Assert(err, IsNil) 260 261 seed20, err := seed.Open(s.SeedDir, sysLabel) 262 c.Assert(err, IsNil) 263 err = seed20.LoadAssertions(s.db, s.commitTo) 264 c.Check(err, ErrorMatches, `system model assertion file must contain exactly the model assertion`) 265 266 // write whatever single non model assertion 267 seedtest.WriteAssertions(modelAssertFn, s.AssertedSnapRevision("snapd")) 268 269 seed20, err = seed.Open(s.SeedDir, sysLabel) 270 c.Assert(err, IsNil) 271 err = seed20.LoadAssertions(s.db, s.commitTo) 272 c.Check(err, ErrorMatches, `system model assertion file must contain exactly the model assertion`) 273 } 274 275 func (s *seed20Suite) massageAssertions(c *C, fn string, filter func(asserts.Assertion) asserts.Assertion) { 276 assertions := seedtest.ReadAssertions(c, fn) 277 filtered := make([]asserts.Assertion, 0, len(assertions)) 278 for _, a := range assertions { 279 a1 := filter(a) 280 if a1 != nil { 281 filtered = append(filtered, a1) 282 } 283 } 284 seedtest.WriteAssertions(fn, filtered...) 285 } 286 287 func (s *seed20Suite) TestLoadAssertionsUnbalancedDeclsAndRevs(c *C) { 288 sysLabel := "20191031" 289 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 290 291 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 292 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("core20") { 293 return nil 294 } 295 return a 296 }) 297 298 seed20, err := seed.Open(s.SeedDir, sysLabel) 299 c.Assert(err, IsNil) 300 err = seed20.LoadAssertions(s.db, s.commitTo) 301 c.Check(err, ErrorMatches, `system unexpectedly holds a different number of snap-declaration than snap-revision assertions`) 302 } 303 304 func (s *seed20Suite) TestLoadAssertionsMultiSnapRev(c *C) { 305 sysLabel := "20191031" 306 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 307 308 spuriousRev, err := s.StoreSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ 309 "snap-sha3-384": strings.Repeat("B", 64), 310 "snap-size": "1000", 311 "snap-id": s.AssertedSnapID("core20"), 312 "developer-id": "canonical", 313 "snap-revision": "99", 314 "timestamp": time.Now().UTC().Format(time.RFC3339), 315 }, nil, "") 316 c.Assert(err, IsNil) 317 318 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 319 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("snapd") { 320 return spuriousRev 321 } 322 return a 323 }) 324 325 seed20, err := seed.Open(s.SeedDir, sysLabel) 326 c.Assert(err, IsNil) 327 err = seed20.LoadAssertions(s.db, s.commitTo) 328 c.Check(err, ErrorMatches, fmt.Sprintf(`cannot have multiple snap-revisions for the same snap-id: %s`, s.AssertedSnapID("core20"))) 329 } 330 331 func (s *seed20Suite) TestLoadAssertionsMultiSnapDecl(c *C) { 332 sysLabel := "20191031" 333 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 334 335 spuriousDecl, err := s.StoreSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ 336 "series": "16", 337 "snap-id": "idididididididididididididididid", 338 "publisher-id": "canonical", 339 "snap-name": "core20", 340 "timestamp": time.Now().UTC().Format(time.RFC3339), 341 }, nil, "") 342 c.Assert(err, IsNil) 343 344 spuriousRev, err := s.StoreSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ 345 "snap-sha3-384": strings.Repeat("B", 64), 346 "snap-size": "1000", 347 "snap-id": s.AssertedSnapID("core20"), 348 "developer-id": "canonical", 349 "snap-revision": "99", 350 "timestamp": time.Now().UTC().Format(time.RFC3339), 351 }, nil, "") 352 c.Assert(err, IsNil) 353 354 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 355 if a.Type() == asserts.SnapDeclarationType && a.HeaderString("snap-name") == "snapd" { 356 return spuriousDecl 357 } 358 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("snapd") { 359 return spuriousRev 360 } 361 return a 362 }) 363 364 seed20, err := seed.Open(s.SeedDir, sysLabel) 365 c.Assert(err, IsNil) 366 err = seed20.LoadAssertions(s.db, s.commitTo) 367 c.Check(err, ErrorMatches, `cannot have multiple snap-declarations for the same snap-name: core20`) 368 } 369 370 func (s *seed20Suite) TestLoadMetaMissingSnapDeclByName(c *C) { 371 sysLabel := "20191031" 372 373 s.makeSnap(c, "snapd", "") 374 s.makeSnap(c, "core20", "") 375 s.makeSnap(c, "pc-kernel=20", "") 376 s.makeSnap(c, "pc=20", "") 377 378 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 379 "display-name": "my model", 380 "architecture": "amd64", 381 "base": "core20", 382 "grade": "dangerous", 383 "snaps": []interface{}{ 384 map[string]interface{}{ 385 "name": "pc-kernel", 386 "id": s.AssertedSnapID("pc-kernel"), 387 "type": "kernel", 388 "default-channel": "20", 389 }, 390 map[string]interface{}{ 391 "name": "pc", 392 "id": s.AssertedSnapID("pc"), 393 "type": "gadget", 394 "default-channel": "20", 395 }, 396 map[string]interface{}{ 397 "name": "core20", 398 // no id 399 "type": "base", 400 }}, 401 }, nil) 402 403 sysDir := filepath.Join(s.SeedDir, "systems", sysLabel) 404 405 wrongDecl, err := s.StoreSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ 406 "series": "16", 407 "snap-id": "idididididididididididididididid", 408 "publisher-id": "canonical", 409 "snap-name": "core20X", 410 "timestamp": time.Now().UTC().Format(time.RFC3339), 411 }, nil, "") 412 c.Assert(err, IsNil) 413 414 wrongRev, err := s.StoreSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ 415 "snap-sha3-384": strings.Repeat("B", 64), 416 "snap-size": "1000", 417 "snap-id": "idididididididididididididididid", 418 "developer-id": "canonical", 419 "snap-revision": "99", 420 "timestamp": time.Now().UTC().Format(time.RFC3339), 421 }, nil, "") 422 c.Assert(err, IsNil) 423 424 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 425 if a.Type() == asserts.SnapDeclarationType && a.HeaderString("snap-name") == "core20" { 426 return wrongDecl 427 } 428 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("core20") { 429 return wrongRev 430 } 431 return a 432 }) 433 434 seed20, err := seed.Open(s.SeedDir, sysLabel) 435 c.Assert(err, IsNil) 436 437 err = seed20.LoadAssertions(s.db, s.commitTo) 438 c.Assert(err, IsNil) 439 440 err = seed20.LoadMeta(s.perfTimings) 441 c.Check(err, ErrorMatches, `cannot find snap-declaration for snap name: core20`) 442 } 443 444 func (s *seed20Suite) TestLoadMetaMissingSnapDeclByID(c *C) { 445 sysLabel := "20191031" 446 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 447 448 wrongDecl, err := s.StoreSigning.Sign(asserts.SnapDeclarationType, map[string]interface{}{ 449 "series": "16", 450 "snap-id": "idididididididididididididididid", 451 "publisher-id": "canonical", 452 "snap-name": "pc", 453 "timestamp": time.Now().UTC().Format(time.RFC3339), 454 }, nil, "") 455 c.Assert(err, IsNil) 456 457 wrongRev, err := s.StoreSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ 458 "snap-sha3-384": strings.Repeat("B", 64), 459 "snap-size": "1000", 460 "snap-id": "idididididididididididididididid", 461 "developer-id": "canonical", 462 "snap-revision": "99", 463 "timestamp": time.Now().UTC().Format(time.RFC3339), 464 }, nil, "") 465 c.Assert(err, IsNil) 466 467 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 468 if a.Type() == asserts.SnapDeclarationType && a.HeaderString("snap-name") == "pc" { 469 return wrongDecl 470 } 471 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("pc") { 472 return wrongRev 473 } 474 return a 475 }) 476 477 seed20, err := seed.Open(s.SeedDir, sysLabel) 478 c.Assert(err, IsNil) 479 480 err = seed20.LoadAssertions(s.db, s.commitTo) 481 c.Assert(err, IsNil) 482 483 err = seed20.LoadMeta(s.perfTimings) 484 c.Check(err, ErrorMatches, `cannot find snap-declaration for snap-id: pcididididididididididididididid`) 485 } 486 487 func (s *seed20Suite) TestLoadMetaMissingSnap(c *C) { 488 sysLabel := "20191031" 489 s.makeCore20MinimalSeed(c, sysLabel) 490 491 err := os.Remove(filepath.Join(s.SeedDir, "snaps", "pc_1.snap")) 492 c.Assert(err, IsNil) 493 494 seed20, err := seed.Open(s.SeedDir, sysLabel) 495 c.Assert(err, IsNil) 496 497 err = seed20.LoadAssertions(s.db, s.commitTo) 498 c.Assert(err, IsNil) 499 500 err = seed20.LoadMeta(s.perfTimings) 501 c.Check(err, ErrorMatches, `cannot stat snap:.*pc_1\.snap.*`) 502 } 503 504 func (s *seed20Suite) TestLoadMetaWrongSizeSnap(c *C) { 505 sysLabel := "20191031" 506 s.makeCore20MinimalSeed(c, sysLabel) 507 508 err := os.Truncate(filepath.Join(s.SeedDir, "snaps", "pc_1.snap"), 5) 509 c.Assert(err, IsNil) 510 511 seed20, err := seed.Open(s.SeedDir, sysLabel) 512 c.Assert(err, IsNil) 513 514 err = seed20.LoadAssertions(s.db, s.commitTo) 515 c.Assert(err, IsNil) 516 517 err = seed20.LoadMeta(s.perfTimings) 518 c.Check(err, ErrorMatches, `cannot validate ".*pc_1\.snap" for snap "pc" \(snap-id "pc.*"\), wrong size`) 519 } 520 521 func (s *seed20Suite) TestLoadMetaWrongHashSnap(c *C) { 522 sysLabel := "20191031" 523 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 524 525 pcRev := s.AssertedSnapRevision("pc") 526 wrongRev, err := s.StoreSigning.Sign(asserts.SnapRevisionType, map[string]interface{}{ 527 "snap-sha3-384": strings.Repeat("B", 64), 528 "snap-size": pcRev.HeaderString("snap-size"), 529 "snap-id": s.AssertedSnapID("pc"), 530 "developer-id": "canonical", 531 "snap-revision": pcRev.HeaderString("snap-revision"), 532 "timestamp": time.Now().UTC().Format(time.RFC3339), 533 }, nil, "") 534 c.Assert(err, IsNil) 535 536 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 537 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("pc") { 538 return wrongRev 539 } 540 return a 541 }) 542 543 seed20, err := seed.Open(s.SeedDir, sysLabel) 544 c.Assert(err, IsNil) 545 546 err = seed20.LoadAssertions(s.db, s.commitTo) 547 c.Assert(err, IsNil) 548 549 err = seed20.LoadMeta(s.perfTimings) 550 c.Check(err, ErrorMatches, `cannot validate ".*pc_1\.snap" for snap "pc" \(snap-id "pc.*"\), hash mismatch with snap-revision`) 551 } 552 553 func (s *seed20Suite) TestLoadMetaWrongGadgetBase(c *C) { 554 sysLabel := "20191031" 555 sysDir := s.makeCore20MinimalSeed(c, sysLabel) 556 557 // pc with base: core18 558 pc18Decl, pc18Rev := s.MakeAssertedSnap(c, snapYaml["pc=18"], nil, snap.R(2), "canonical") 559 err := os.Rename(s.AssertedSnap("pc"), filepath.Join(s.SeedDir, "snaps", "pc_2.snap")) 560 c.Assert(err, IsNil) 561 s.massageAssertions(c, filepath.Join(sysDir, "assertions", "snaps"), func(a asserts.Assertion) asserts.Assertion { 562 if a.Type() == asserts.SnapDeclarationType && a.HeaderString("snap-name") == "pc" { 563 return pc18Decl 564 } 565 if a.Type() == asserts.SnapRevisionType && a.HeaderString("snap-id") == s.AssertedSnapID("pc") { 566 return pc18Rev 567 } 568 return a 569 }) 570 571 seed20, err := seed.Open(s.SeedDir, sysLabel) 572 c.Assert(err, IsNil) 573 574 err = seed20.LoadAssertions(s.db, s.commitTo) 575 c.Assert(err, IsNil) 576 577 err = seed20.LoadMeta(s.perfTimings) 578 c.Check(err, ErrorMatches, `cannot use gadget snap because its base "core18" is different from model base "core20"`) 579 } 580 581 func (s *seed20Suite) TestLoadMetaCore20(c *C) { 582 s.makeSnap(c, "snapd", "") 583 s.makeSnap(c, "core20", "") 584 s.makeSnap(c, "pc-kernel=20", "") 585 s.makeSnap(c, "pc=20", "") 586 s.makeSnap(c, "required20", "developerid") 587 588 s.AssertedSnapInfo("required20").Contact = "author@example.com" 589 590 sysLabel := "20191018" 591 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 592 "display-name": "my model", 593 "architecture": "amd64", 594 "base": "core20", 595 "snaps": []interface{}{ 596 map[string]interface{}{ 597 "name": "pc-kernel", 598 "id": s.AssertedSnapID("pc-kernel"), 599 "type": "kernel", 600 "default-channel": "20", 601 }, 602 map[string]interface{}{ 603 "name": "pc", 604 "id": s.AssertedSnapID("pc"), 605 "type": "gadget", 606 "default-channel": "20", 607 }, 608 map[string]interface{}{ 609 "name": "required20", 610 "id": s.AssertedSnapID("required20"), 611 }}, 612 }, nil) 613 614 seed20, err := seed.Open(s.SeedDir, sysLabel) 615 c.Assert(err, IsNil) 616 617 err = seed20.LoadAssertions(s.db, s.commitTo) 618 c.Assert(err, IsNil) 619 620 err = seed20.LoadMeta(s.perfTimings) 621 c.Assert(err, IsNil) 622 623 c.Check(seed20.UsesSnapdSnap(), Equals, true) 624 625 essSnaps := seed20.EssentialSnaps() 626 c.Check(essSnaps, HasLen, 4) 627 628 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 629 { 630 Path: s.expectedPath("snapd"), 631 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 632 EssentialType: snap.TypeSnapd, 633 Essential: true, 634 Required: true, 635 Channel: "latest/stable", 636 }, { 637 Path: s.expectedPath("pc-kernel"), 638 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 639 EssentialType: snap.TypeKernel, 640 Essential: true, 641 Required: true, 642 Channel: "20", 643 }, { 644 Path: s.expectedPath("core20"), 645 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 646 EssentialType: snap.TypeBase, 647 Essential: true, 648 Required: true, 649 Channel: "latest/stable", 650 }, { 651 Path: s.expectedPath("pc"), 652 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 653 EssentialType: snap.TypeGadget, 654 Essential: true, 655 Required: true, 656 Channel: "20", 657 }, 658 }) 659 660 runSnaps, err := seed20.ModeSnaps("run") 661 c.Assert(err, IsNil) 662 c.Check(runSnaps, HasLen, 1) 663 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 664 { 665 Path: s.expectedPath("required20"), 666 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 667 Required: true, 668 Channel: "latest/stable", 669 }, 670 }) 671 672 // required20 has default modes: ["run"] 673 installSnaps, err := seed20.ModeSnaps("install") 674 c.Assert(err, IsNil) 675 c.Check(installSnaps, HasLen, 0) 676 } 677 678 func hideSnaps(c *C, all []*seed.Snap, keepTypes []snap.Type) (unhide func()) { 679 var hidden [][]string 680 Hiding: 681 for _, sn := range all { 682 for _, t := range keepTypes { 683 if sn.EssentialType == t { 684 continue Hiding 685 } 686 } 687 origFn := sn.Path 688 hiddenFn := sn.Path + ".hidden" 689 err := os.Rename(origFn, hiddenFn) 690 c.Assert(err, IsNil) 691 hidden = append(hidden, []string{origFn, hiddenFn}) 692 } 693 return func() { 694 for _, h := range hidden { 695 err := os.Rename(h[1], h[0]) 696 c.Assert(err, IsNil) 697 } 698 } 699 } 700 701 func (s *seed20Suite) TestLoadEssentialMetaCore20(c *C) { 702 r := seed.MockTrusted(s.StoreSigning.Trusted) 703 defer r() 704 705 s.makeSnap(c, "snapd", "") 706 s.makeSnap(c, "core20", "") 707 s.makeSnap(c, "pc-kernel=20", "") 708 s.makeSnap(c, "pc=20", "") 709 s.makeSnap(c, "core18", "") 710 s.makeSnap(c, "required18", "developerid") 711 712 sysLabel := "20191018" 713 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 714 "display-name": "my model", 715 "architecture": "amd64", 716 "base": "core20", 717 "snaps": []interface{}{ 718 map[string]interface{}{ 719 "name": "pc-kernel", 720 "id": s.AssertedSnapID("pc-kernel"), 721 "type": "kernel", 722 "default-channel": "20", 723 }, 724 map[string]interface{}{ 725 "name": "pc", 726 "id": s.AssertedSnapID("pc"), 727 "type": "gadget", 728 "default-channel": "20", 729 }, 730 map[string]interface{}{ 731 "name": "core18", 732 "id": s.AssertedSnapID("core18"), 733 "type": "base", 734 }, 735 map[string]interface{}{ 736 "name": "required18", 737 "id": s.AssertedSnapID("required18"), 738 }}, 739 }, nil) 740 741 snapdSnap := &seed.Snap{ 742 Path: s.expectedPath("snapd"), 743 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 744 EssentialType: snap.TypeSnapd, 745 Essential: true, 746 Required: true, 747 Channel: "latest/stable", 748 } 749 pcKernelSnap := &seed.Snap{ 750 Path: s.expectedPath("pc-kernel"), 751 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 752 EssentialType: snap.TypeKernel, 753 Essential: true, 754 Required: true, 755 Channel: "20", 756 } 757 core20Snap := &seed.Snap{Path: s.expectedPath("core20"), 758 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 759 EssentialType: snap.TypeBase, 760 Essential: true, 761 Required: true, 762 Channel: "latest/stable", 763 } 764 pcSnap := &seed.Snap{ 765 Path: s.expectedPath("pc"), 766 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 767 EssentialType: snap.TypeGadget, 768 Essential: true, 769 Required: true, 770 Channel: "20", 771 } 772 core18Snap := &seed.Snap{ 773 // no EssentialType, so it's always hidden, shouldn't matter 774 // because we should not look at it 775 Path: s.expectedPath("core18"), 776 } 777 required18Snap := &seed.Snap{ 778 Path: s.expectedPath("required18"), 779 } 780 781 all := []*seed.Snap{snapdSnap, pcKernelSnap, core20Snap, pcSnap, core18Snap, required18Snap} 782 783 tests := []struct { 784 onlyTypes []snap.Type 785 expected []*seed.Snap 786 }{ 787 {[]snap.Type{snap.TypeSnapd}, []*seed.Snap{snapdSnap}}, 788 {[]snap.Type{snap.TypeKernel}, []*seed.Snap{pcKernelSnap}}, 789 {[]snap.Type{snap.TypeBase}, []*seed.Snap{core20Snap}}, 790 {[]snap.Type{snap.TypeGadget}, []*seed.Snap{pcSnap}}, 791 {[]snap.Type{snap.TypeSnapd, snap.TypeKernel, snap.TypeBase}, []*seed.Snap{snapdSnap, pcKernelSnap, core20Snap}}, 792 // the order in essentialTypes is not relevant 793 {[]snap.Type{snap.TypeGadget, snap.TypeKernel}, []*seed.Snap{pcKernelSnap, pcSnap}}, 794 // degenerate case 795 {[]snap.Type{}, []*seed.Snap(nil)}, 796 } 797 798 for _, t := range tests { 799 // hide the non-requested snaps to make sure they are not 800 // accessed 801 unhide := hideSnaps(c, all, t.onlyTypes) 802 803 seed20, err := seed.Open(s.SeedDir, sysLabel) 804 c.Assert(err, IsNil) 805 806 essSeed20, ok := seed20.(seed.EssentialMetaLoaderSeed) 807 c.Assert(ok, Equals, true) 808 809 err = essSeed20.LoadAssertions(nil, nil) 810 c.Assert(err, IsNil) 811 812 err = essSeed20.LoadEssentialMeta(t.onlyTypes, s.perfTimings) 813 c.Assert(err, IsNil) 814 815 c.Check(essSeed20.UsesSnapdSnap(), Equals, true) 816 817 essSnaps := essSeed20.EssentialSnaps() 818 c.Check(essSnaps, HasLen, len(t.expected)) 819 820 c.Check(essSnaps, DeepEquals, t.expected) 821 822 runSnaps, err := essSeed20.ModeSnaps("run") 823 c.Assert(err, IsNil) 824 c.Check(runSnaps, HasLen, 0) 825 826 unhide() 827 828 // test short-cut helper as well 829 mod, essSnaps, err := seed.ReadSystemEssential(s.SeedDir, sysLabel, t.onlyTypes, s.perfTimings) 830 c.Assert(err, IsNil) 831 c.Check(mod.BrandID(), Equals, "my-brand") 832 c.Check(mod.Model(), Equals, "my-model") 833 c.Check(essSnaps, HasLen, len(t.expected)) 834 c.Check(essSnaps, DeepEquals, t.expected) 835 } 836 } 837 838 func (s *seed20Suite) makeLocalSnap(c *C, yamlKey string) (fname string) { 839 return snaptest.MakeTestSnapWithFiles(c, snapYaml[yamlKey], nil) 840 } 841 842 func (s *seed20Suite) TestLoadMetaCore20LocalSnaps(c *C) { 843 s.makeSnap(c, "snapd", "") 844 s.makeSnap(c, "core20", "") 845 s.makeSnap(c, "pc-kernel=20", "") 846 s.makeSnap(c, "pc=20", "") 847 requiredFn := s.makeLocalSnap(c, "required20") 848 849 sysLabel := "20191030" 850 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 851 "display-name": "my model", 852 "architecture": "amd64", 853 "base": "core20", 854 "grade": "dangerous", 855 "snaps": []interface{}{ 856 map[string]interface{}{ 857 "name": "pc-kernel", 858 "id": s.AssertedSnapID("pc-kernel"), 859 "type": "kernel", 860 "default-channel": "20", 861 }, 862 map[string]interface{}{ 863 "name": "pc", 864 "id": s.AssertedSnapID("pc"), 865 "type": "gadget", 866 "default-channel": "20", 867 }, 868 map[string]interface{}{ 869 "name": "required20", 870 "id": s.AssertedSnapID("required20"), 871 }}, 872 }, []*seedwriter.OptionsSnap{ 873 {Path: requiredFn}, 874 }) 875 876 seed20, err := seed.Open(s.SeedDir, sysLabel) 877 c.Assert(err, IsNil) 878 879 err = seed20.LoadAssertions(s.db, s.commitTo) 880 c.Assert(err, IsNil) 881 882 err = seed20.LoadMeta(s.perfTimings) 883 c.Assert(err, IsNil) 884 885 c.Check(seed20.UsesSnapdSnap(), Equals, true) 886 887 essSnaps := seed20.EssentialSnaps() 888 c.Check(essSnaps, HasLen, 4) 889 890 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 891 { 892 Path: s.expectedPath("snapd"), 893 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 894 EssentialType: snap.TypeSnapd, 895 Essential: true, 896 Required: true, 897 Channel: "latest/stable", 898 }, { 899 Path: s.expectedPath("pc-kernel"), 900 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 901 EssentialType: snap.TypeKernel, 902 Essential: true, 903 Required: true, 904 Channel: "20", 905 }, { 906 Path: s.expectedPath("core20"), 907 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 908 EssentialType: snap.TypeBase, 909 Essential: true, 910 Required: true, 911 Channel: "latest/stable", 912 }, { 913 Path: s.expectedPath("pc"), 914 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 915 EssentialType: snap.TypeGadget, 916 Essential: true, 917 Required: true, 918 Channel: "20", 919 }, 920 }) 921 922 runSnaps, err := seed20.ModeSnaps("run") 923 c.Assert(err, IsNil) 924 c.Check(runSnaps, HasLen, 1) 925 926 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 927 { 928 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "required20_1.0.snap"), 929 SideInfo: &snap.SideInfo{RealName: "required20"}, 930 Required: true, 931 }, 932 }) 933 } 934 935 func (s *seed20Suite) TestLoadMetaCore20ChannelOverride(c *C) { 936 s.makeSnap(c, "snapd", "") 937 s.makeSnap(c, "core20", "") 938 s.makeSnap(c, "pc-kernel=20", "") 939 s.makeSnap(c, "pc=20", "") 940 s.makeSnap(c, "required20", "developerid") 941 942 s.AssertedSnapInfo("required20").Contact = "author@example.com" 943 944 sysLabel := "20191018" 945 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 946 "display-name": "my model", 947 "architecture": "amd64", 948 "base": "core20", 949 "grade": "dangerous", 950 "snaps": []interface{}{ 951 map[string]interface{}{ 952 "name": "pc-kernel", 953 "id": s.AssertedSnapID("pc-kernel"), 954 "type": "kernel", 955 "default-channel": "20", 956 }, 957 map[string]interface{}{ 958 "name": "pc", 959 "id": s.AssertedSnapID("pc"), 960 "type": "gadget", 961 "default-channel": "20", 962 }, 963 map[string]interface{}{ 964 "name": "required20", 965 "id": s.AssertedSnapID("required20"), 966 }}, 967 }, []*seedwriter.OptionsSnap{ 968 {Name: "pc", Channel: "20experimental/edge"}, 969 }) 970 971 seed20, err := seed.Open(s.SeedDir, sysLabel) 972 c.Assert(err, IsNil) 973 974 err = seed20.LoadAssertions(s.db, s.commitTo) 975 c.Assert(err, IsNil) 976 977 err = seed20.LoadMeta(s.perfTimings) 978 c.Assert(err, IsNil) 979 980 c.Check(seed20.UsesSnapdSnap(), Equals, true) 981 982 essSnaps := seed20.EssentialSnaps() 983 c.Check(essSnaps, HasLen, 4) 984 985 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 986 { 987 Path: s.expectedPath("snapd"), 988 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 989 EssentialType: snap.TypeSnapd, 990 Essential: true, 991 Required: true, 992 Channel: "latest/stable", 993 }, { 994 Path: s.expectedPath("pc-kernel"), 995 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 996 EssentialType: snap.TypeKernel, 997 Essential: true, 998 Required: true, 999 Channel: "20", 1000 }, { 1001 Path: s.expectedPath("core20"), 1002 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1003 EssentialType: snap.TypeBase, 1004 Essential: true, 1005 Required: true, 1006 Channel: "latest/stable", 1007 }, { 1008 Path: s.expectedPath("pc"), 1009 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1010 EssentialType: snap.TypeGadget, 1011 Essential: true, 1012 Required: true, 1013 Channel: "20experimental/edge", 1014 }, 1015 }) 1016 1017 runSnaps, err := seed20.ModeSnaps("run") 1018 c.Assert(err, IsNil) 1019 c.Check(runSnaps, HasLen, 1) 1020 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1021 { 1022 Path: s.expectedPath("required20"), 1023 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1024 Required: true, 1025 Channel: "latest/stable", 1026 }, 1027 }) 1028 } 1029 1030 func (s *seed20Suite) TestLoadMetaCore20ChannelOverrideSnapd(c *C) { 1031 s.makeSnap(c, "snapd", "") 1032 s.makeSnap(c, "core20", "") 1033 s.makeSnap(c, "pc-kernel=20", "") 1034 s.makeSnap(c, "pc=20", "") 1035 s.makeSnap(c, "required20", "developerid") 1036 1037 s.AssertedSnapInfo("required20").Contact = "author@example.com" 1038 1039 sysLabel := "20191121" 1040 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1041 "display-name": "my model", 1042 "architecture": "amd64", 1043 "base": "core20", 1044 "grade": "dangerous", 1045 "snaps": []interface{}{ 1046 map[string]interface{}{ 1047 "name": "pc-kernel", 1048 "id": s.AssertedSnapID("pc-kernel"), 1049 "type": "kernel", 1050 "default-channel": "20", 1051 }, 1052 map[string]interface{}{ 1053 "name": "pc", 1054 "id": s.AssertedSnapID("pc"), 1055 "type": "gadget", 1056 "default-channel": "20", 1057 }, 1058 map[string]interface{}{ 1059 "name": "required20", 1060 "id": s.AssertedSnapID("required20"), 1061 }}, 1062 }, []*seedwriter.OptionsSnap{ 1063 {Name: "snapd", Channel: "20experimental/edge"}, 1064 }) 1065 1066 seed20, err := seed.Open(s.SeedDir, sysLabel) 1067 c.Assert(err, IsNil) 1068 1069 err = seed20.LoadAssertions(s.db, s.commitTo) 1070 c.Assert(err, IsNil) 1071 1072 err = seed20.LoadMeta(s.perfTimings) 1073 c.Assert(err, IsNil) 1074 1075 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1076 1077 essSnaps := seed20.EssentialSnaps() 1078 c.Check(essSnaps, HasLen, 4) 1079 1080 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1081 { 1082 Path: s.expectedPath("snapd"), 1083 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1084 EssentialType: snap.TypeSnapd, 1085 Essential: true, 1086 Required: true, 1087 Channel: "20experimental/edge", 1088 }, { 1089 Path: s.expectedPath("pc-kernel"), 1090 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1091 EssentialType: snap.TypeKernel, 1092 Essential: true, 1093 Required: true, 1094 Channel: "20", 1095 }, { 1096 Path: s.expectedPath("core20"), 1097 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1098 EssentialType: snap.TypeBase, 1099 Essential: true, 1100 Required: true, 1101 Channel: "latest/stable", 1102 }, { 1103 Path: s.expectedPath("pc"), 1104 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1105 EssentialType: snap.TypeGadget, 1106 Essential: true, 1107 Required: true, 1108 Channel: "20", 1109 }, 1110 }) 1111 1112 runSnaps, err := seed20.ModeSnaps("run") 1113 c.Assert(err, IsNil) 1114 c.Check(runSnaps, HasLen, 1) 1115 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1116 { 1117 Path: s.expectedPath("required20"), 1118 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1119 Required: true, 1120 Channel: "latest/stable", 1121 }, 1122 }) 1123 } 1124 1125 func (s *seed20Suite) TestLoadMetaCore20LocalSnapd(c *C) { 1126 snapdFn := s.makeLocalSnap(c, "snapd") 1127 s.makeSnap(c, "core20", "") 1128 s.makeSnap(c, "pc-kernel=20", "") 1129 s.makeSnap(c, "pc=20", "") 1130 1131 sysLabel := "20191121" 1132 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1133 "display-name": "my model", 1134 "architecture": "amd64", 1135 "base": "core20", 1136 "grade": "dangerous", 1137 "snaps": []interface{}{ 1138 map[string]interface{}{ 1139 "name": "pc-kernel", 1140 "id": s.AssertedSnapID("pc-kernel"), 1141 "type": "kernel", 1142 "default-channel": "20", 1143 }, 1144 map[string]interface{}{ 1145 "name": "pc", 1146 "id": s.AssertedSnapID("pc"), 1147 "type": "gadget", 1148 "default-channel": "20", 1149 }}, 1150 }, []*seedwriter.OptionsSnap{ 1151 {Path: snapdFn}, 1152 }) 1153 1154 seed20, err := seed.Open(s.SeedDir, sysLabel) 1155 c.Assert(err, IsNil) 1156 1157 err = seed20.LoadAssertions(s.db, s.commitTo) 1158 c.Assert(err, IsNil) 1159 1160 err = seed20.LoadMeta(s.perfTimings) 1161 c.Assert(err, IsNil) 1162 1163 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1164 1165 essSnaps := seed20.EssentialSnaps() 1166 c.Check(essSnaps, HasLen, 4) 1167 1168 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1169 { 1170 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "snapd_1.0.snap"), 1171 SideInfo: &snap.SideInfo{RealName: "snapd"}, 1172 Essential: true, 1173 EssentialType: snap.TypeSnapd, 1174 Required: true, 1175 }, { 1176 Path: s.expectedPath("pc-kernel"), 1177 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1178 EssentialType: snap.TypeKernel, 1179 Essential: true, 1180 Required: true, 1181 Channel: "20", 1182 }, { 1183 Path: s.expectedPath("core20"), 1184 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1185 EssentialType: snap.TypeBase, 1186 Essential: true, 1187 Required: true, 1188 Channel: "latest/stable", 1189 }, { 1190 Path: s.expectedPath("pc"), 1191 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1192 EssentialType: snap.TypeGadget, 1193 Essential: true, 1194 Required: true, 1195 Channel: "20", 1196 }, 1197 }) 1198 1199 runSnaps, err := seed20.ModeSnaps("run") 1200 c.Assert(err, IsNil) 1201 c.Check(runSnaps, HasLen, 0) 1202 } 1203 1204 func (s *seed20Suite) TestLoadMetaCore20ModelOverrideSnapd(c *C) { 1205 s.makeSnap(c, "snapd", "") 1206 s.makeSnap(c, "core20", "") 1207 s.makeSnap(c, "pc-kernel=20", "") 1208 s.makeSnap(c, "pc=20", "") 1209 1210 sysLabel := "20191121" 1211 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1212 "display-name": "my model", 1213 "architecture": "amd64", 1214 "base": "core20", 1215 "grade": "dangerous", 1216 "snaps": []interface{}{ 1217 map[string]interface{}{ 1218 "name": "snapd", 1219 "type": "snapd", 1220 "default-channel": "latest/edge", 1221 }, 1222 map[string]interface{}{ 1223 "name": "pc-kernel", 1224 "id": s.AssertedSnapID("pc-kernel"), 1225 "type": "kernel", 1226 "default-channel": "20", 1227 }, 1228 map[string]interface{}{ 1229 "name": "pc", 1230 "id": s.AssertedSnapID("pc"), 1231 "type": "gadget", 1232 "default-channel": "20", 1233 }}, 1234 }, nil) 1235 1236 seed20, err := seed.Open(s.SeedDir, sysLabel) 1237 c.Assert(err, IsNil) 1238 1239 err = seed20.LoadAssertions(s.db, s.commitTo) 1240 c.Assert(err, IsNil) 1241 1242 err = seed20.LoadMeta(s.perfTimings) 1243 c.Assert(err, IsNil) 1244 1245 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1246 1247 essSnaps := seed20.EssentialSnaps() 1248 c.Check(essSnaps, HasLen, 4) 1249 1250 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1251 { 1252 Path: s.expectedPath("snapd"), 1253 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1254 EssentialType: snap.TypeSnapd, 1255 Essential: true, 1256 Required: true, 1257 Channel: "latest/edge", 1258 }, { 1259 Path: s.expectedPath("pc-kernel"), 1260 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1261 EssentialType: snap.TypeKernel, 1262 Essential: true, 1263 Required: true, 1264 Channel: "20", 1265 }, { 1266 Path: s.expectedPath("core20"), 1267 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1268 EssentialType: snap.TypeBase, 1269 Essential: true, 1270 Required: true, 1271 Channel: "latest/stable", 1272 }, { 1273 Path: s.expectedPath("pc"), 1274 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1275 EssentialType: snap.TypeGadget, 1276 Essential: true, 1277 Required: true, 1278 Channel: "20", 1279 }, 1280 }) 1281 1282 runSnaps, err := seed20.ModeSnaps("run") 1283 c.Assert(err, IsNil) 1284 c.Check(runSnaps, HasLen, 0) 1285 } 1286 1287 func (s *seed20Suite) TestLoadMetaCore20OptionalSnaps(c *C) { 1288 s.makeSnap(c, "snapd", "") 1289 s.makeSnap(c, "core20", "") 1290 s.makeSnap(c, "pc-kernel=20", "") 1291 s.makeSnap(c, "pc=20", "") 1292 s.makeSnap(c, "optional20-a", "developerid") 1293 s.makeSnap(c, "optional20-b", "developerid") 1294 1295 sysLabel := "20191122" 1296 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1297 "display-name": "my model", 1298 "architecture": "amd64", 1299 "base": "core20", 1300 "grade": "signed", 1301 "snaps": []interface{}{ 1302 map[string]interface{}{ 1303 "name": "pc-kernel", 1304 "id": s.AssertedSnapID("pc-kernel"), 1305 "type": "kernel", 1306 "default-channel": "20", 1307 }, 1308 map[string]interface{}{ 1309 "name": "pc", 1310 "id": s.AssertedSnapID("pc"), 1311 "type": "gadget", 1312 "default-channel": "20", 1313 }, 1314 map[string]interface{}{ 1315 "name": "optional20-a", 1316 "id": s.AssertedSnapID("optional20-a"), 1317 "presence": "optional", 1318 }, 1319 map[string]interface{}{ 1320 "name": "optional20-b", 1321 "id": s.AssertedSnapID("optional20-b"), 1322 "presence": "optional", 1323 }}, 1324 }, []*seedwriter.OptionsSnap{ 1325 {Name: "optional20-b"}, 1326 }) 1327 1328 seed20, err := seed.Open(s.SeedDir, sysLabel) 1329 c.Assert(err, IsNil) 1330 1331 err = seed20.LoadAssertions(s.db, s.commitTo) 1332 c.Assert(err, IsNil) 1333 1334 err = seed20.LoadMeta(s.perfTimings) 1335 c.Assert(err, IsNil) 1336 1337 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1338 1339 essSnaps := seed20.EssentialSnaps() 1340 c.Check(essSnaps, HasLen, 4) 1341 1342 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1343 { 1344 Path: s.expectedPath("snapd"), 1345 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1346 EssentialType: snap.TypeSnapd, 1347 Essential: true, 1348 Required: true, 1349 Channel: "latest/stable", 1350 }, { 1351 Path: s.expectedPath("pc-kernel"), 1352 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1353 EssentialType: snap.TypeKernel, 1354 Essential: true, 1355 Required: true, 1356 Channel: "20", 1357 }, { 1358 Path: s.expectedPath("core20"), 1359 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1360 EssentialType: snap.TypeBase, 1361 Essential: true, 1362 Required: true, 1363 Channel: "latest/stable", 1364 }, { 1365 Path: s.expectedPath("pc"), 1366 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1367 EssentialType: snap.TypeGadget, 1368 Essential: true, 1369 Required: true, 1370 Channel: "20", 1371 }, 1372 }) 1373 1374 runSnaps, err := seed20.ModeSnaps("run") 1375 c.Assert(err, IsNil) 1376 c.Check(runSnaps, HasLen, 1) 1377 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1378 { 1379 Path: s.expectedPath("optional20-b"), 1380 SideInfo: &s.AssertedSnapInfo("optional20-b").SideInfo, 1381 Required: false, 1382 Channel: "latest/stable", 1383 }, 1384 }) 1385 } 1386 1387 func (s *seed20Suite) TestLoadMetaCore20OptionalSnapsLocal(c *C) { 1388 s.makeSnap(c, "snapd", "") 1389 s.makeSnap(c, "core20", "") 1390 s.makeSnap(c, "pc-kernel=20", "") 1391 s.makeSnap(c, "pc=20", "") 1392 s.makeSnap(c, "optional20-a", "developerid") 1393 optional20bFn := s.makeLocalSnap(c, "optional20-b") 1394 1395 sysLabel := "20191122" 1396 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1397 "display-name": "my model", 1398 "architecture": "amd64", 1399 "base": "core20", 1400 "grade": "dangerous", 1401 "snaps": []interface{}{ 1402 map[string]interface{}{ 1403 "name": "pc-kernel", 1404 "id": s.AssertedSnapID("pc-kernel"), 1405 "type": "kernel", 1406 "default-channel": "20", 1407 }, 1408 map[string]interface{}{ 1409 "name": "pc", 1410 "id": s.AssertedSnapID("pc"), 1411 "type": "gadget", 1412 "default-channel": "20", 1413 }, 1414 map[string]interface{}{ 1415 "name": "optional20-a", 1416 "id": s.AssertedSnapID("optional20-a"), 1417 "presence": "optional", 1418 }, 1419 map[string]interface{}{ 1420 "name": "optional20-b", 1421 "id": s.AssertedSnapID("optional20-b"), 1422 "presence": "optional", 1423 }}, 1424 }, []*seedwriter.OptionsSnap{ 1425 {Path: optional20bFn}, 1426 }) 1427 1428 seed20, err := seed.Open(s.SeedDir, sysLabel) 1429 c.Assert(err, IsNil) 1430 1431 err = seed20.LoadAssertions(s.db, s.commitTo) 1432 c.Assert(err, IsNil) 1433 1434 err = seed20.LoadMeta(s.perfTimings) 1435 c.Assert(err, IsNil) 1436 1437 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1438 1439 essSnaps := seed20.EssentialSnaps() 1440 c.Check(essSnaps, HasLen, 4) 1441 1442 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1443 { 1444 Path: s.expectedPath("snapd"), 1445 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1446 EssentialType: snap.TypeSnapd, 1447 Essential: true, 1448 Required: true, 1449 Channel: "latest/stable", 1450 }, { 1451 Path: s.expectedPath("pc-kernel"), 1452 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1453 EssentialType: snap.TypeKernel, 1454 Essential: true, 1455 Required: true, 1456 Channel: "20", 1457 }, { 1458 Path: s.expectedPath("core20"), 1459 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1460 EssentialType: snap.TypeBase, 1461 Essential: true, 1462 Required: true, 1463 Channel: "latest/stable", 1464 }, { 1465 Path: s.expectedPath("pc"), 1466 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1467 EssentialType: snap.TypeGadget, 1468 Essential: true, 1469 Required: true, 1470 Channel: "20", 1471 }, 1472 }) 1473 1474 runSnaps, err := seed20.ModeSnaps("run") 1475 c.Assert(err, IsNil) 1476 c.Check(runSnaps, HasLen, 1) 1477 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1478 { 1479 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "optional20-b_1.0.snap"), 1480 SideInfo: &snap.SideInfo{RealName: "optional20-b"}, 1481 1482 Required: false, 1483 }, 1484 }) 1485 } 1486 1487 func (s *seed20Suite) TestLoadMetaCore20ExtraSnaps(c *C) { 1488 s.makeSnap(c, "snapd", "") 1489 s.makeSnap(c, "core20", "") 1490 s.makeSnap(c, "pc-kernel=20", "") 1491 s.makeSnap(c, "pc=20", "") 1492 s.makeSnap(c, "core18", "") 1493 s.makeSnap(c, "cont-producer", "developerid") 1494 contConsumerFn := s.makeLocalSnap(c, "cont-consumer") 1495 1496 sysLabel := "20191122" 1497 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1498 "display-name": "my model", 1499 "architecture": "amd64", 1500 "base": "core20", 1501 "grade": "dangerous", 1502 "snaps": []interface{}{ 1503 map[string]interface{}{ 1504 "name": "pc-kernel", 1505 "id": s.AssertedSnapID("pc-kernel"), 1506 "type": "kernel", 1507 "default-channel": "20", 1508 }, 1509 map[string]interface{}{ 1510 "name": "pc", 1511 "id": s.AssertedSnapID("pc"), 1512 "type": "gadget", 1513 "default-channel": "20", 1514 }}, 1515 }, []*seedwriter.OptionsSnap{ 1516 {Name: "cont-producer", Channel: "edge"}, 1517 {Name: "core18"}, 1518 {Path: contConsumerFn}, 1519 }) 1520 1521 seed20, err := seed.Open(s.SeedDir, sysLabel) 1522 c.Assert(err, IsNil) 1523 1524 err = seed20.LoadAssertions(s.db, s.commitTo) 1525 c.Assert(err, IsNil) 1526 1527 err = seed20.LoadMeta(s.perfTimings) 1528 c.Assert(err, IsNil) 1529 1530 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1531 1532 essSnaps := seed20.EssentialSnaps() 1533 c.Check(essSnaps, HasLen, 4) 1534 1535 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1536 { 1537 Path: s.expectedPath("snapd"), 1538 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1539 EssentialType: snap.TypeSnapd, 1540 Essential: true, 1541 Required: true, 1542 Channel: "latest/stable", 1543 }, { 1544 Path: s.expectedPath("pc-kernel"), 1545 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1546 EssentialType: snap.TypeKernel, 1547 Essential: true, 1548 Required: true, 1549 Channel: "20", 1550 }, { 1551 Path: s.expectedPath("core20"), 1552 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1553 EssentialType: snap.TypeBase, 1554 Essential: true, 1555 Required: true, 1556 Channel: "latest/stable", 1557 }, { 1558 Path: s.expectedPath("pc"), 1559 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1560 EssentialType: snap.TypeGadget, 1561 Essential: true, 1562 Required: true, 1563 Channel: "20", 1564 }, 1565 }) 1566 1567 sysSnapsDir := filepath.Join(s.SeedDir, "systems", sysLabel, "snaps") 1568 1569 runSnaps, err := seed20.ModeSnaps("run") 1570 c.Assert(err, IsNil) 1571 c.Check(runSnaps, HasLen, 3) 1572 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1573 { 1574 Path: filepath.Join(sysSnapsDir, "cont-producer_1.snap"), 1575 SideInfo: &s.AssertedSnapInfo("cont-producer").SideInfo, 1576 Channel: "latest/edge", 1577 }, 1578 { 1579 Path: filepath.Join(sysSnapsDir, "core18_1.snap"), 1580 SideInfo: &s.AssertedSnapInfo("core18").SideInfo, 1581 Channel: "latest/stable", 1582 }, 1583 { 1584 Path: filepath.Join(sysSnapsDir, "cont-consumer_1.0.snap"), 1585 SideInfo: &snap.SideInfo{RealName: "cont-consumer"}, 1586 }, 1587 }) 1588 1589 recoverSnaps, err := seed20.ModeSnaps("recover") 1590 c.Assert(err, IsNil) 1591 c.Check(recoverSnaps, HasLen, 0) 1592 } 1593 1594 func (s *seed20Suite) TestLoadMetaCore20NotRunSnaps(c *C) { 1595 s.makeSnap(c, "snapd", "") 1596 s.makeSnap(c, "core20", "") 1597 s.makeSnap(c, "pc-kernel=20", "") 1598 s.makeSnap(c, "pc=20", "") 1599 s.makeSnap(c, "required20", "developerid") 1600 s.makeSnap(c, "optional20-a", "developerid") 1601 s.makeSnap(c, "optional20-b", "developerid") 1602 1603 sysLabel := "20191122" 1604 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1605 "display-name": "my model", 1606 "architecture": "amd64", 1607 "base": "core20", 1608 "grade": "signed", 1609 "snaps": []interface{}{ 1610 map[string]interface{}{ 1611 "name": "pc-kernel", 1612 "id": s.AssertedSnapID("pc-kernel"), 1613 "type": "kernel", 1614 "default-channel": "20", 1615 }, 1616 map[string]interface{}{ 1617 "name": "pc", 1618 "id": s.AssertedSnapID("pc"), 1619 "type": "gadget", 1620 "default-channel": "20", 1621 }, 1622 map[string]interface{}{ 1623 "name": "required20", 1624 "id": s.AssertedSnapID("required20"), 1625 "modes": []interface{}{"run", "ephemeral"}, 1626 }, 1627 map[string]interface{}{ 1628 "name": "optional20-a", 1629 "id": s.AssertedSnapID("optional20-a"), 1630 "presence": "optional", 1631 "modes": []interface{}{"ephemeral"}, 1632 }, 1633 map[string]interface{}{ 1634 "name": "optional20-b", 1635 "id": s.AssertedSnapID("optional20-b"), 1636 "presence": "optional", 1637 "modes": []interface{}{"install"}, 1638 }}, 1639 }, []*seedwriter.OptionsSnap{ 1640 {Name: "optional20-a"}, 1641 {Name: "optional20-b"}, 1642 }) 1643 1644 seed20, err := seed.Open(s.SeedDir, sysLabel) 1645 c.Assert(err, IsNil) 1646 1647 err = seed20.LoadAssertions(s.db, s.commitTo) 1648 c.Assert(err, IsNil) 1649 1650 err = seed20.LoadMeta(s.perfTimings) 1651 c.Assert(err, IsNil) 1652 1653 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1654 1655 essSnaps := seed20.EssentialSnaps() 1656 c.Check(essSnaps, HasLen, 4) 1657 1658 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1659 { 1660 Path: s.expectedPath("snapd"), 1661 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1662 EssentialType: snap.TypeSnapd, 1663 Essential: true, 1664 Required: true, 1665 Channel: "latest/stable", 1666 }, { 1667 Path: s.expectedPath("pc-kernel"), 1668 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1669 EssentialType: snap.TypeKernel, 1670 Essential: true, 1671 Required: true, 1672 Channel: "20", 1673 }, { 1674 Path: s.expectedPath("core20"), 1675 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1676 EssentialType: snap.TypeBase, 1677 Essential: true, 1678 Required: true, 1679 Channel: "latest/stable", 1680 }, { 1681 Path: s.expectedPath("pc"), 1682 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1683 EssentialType: snap.TypeGadget, 1684 Essential: true, 1685 Required: true, 1686 Channel: "20", 1687 }, 1688 }) 1689 1690 runSnaps, err := seed20.ModeSnaps("run") 1691 c.Assert(err, IsNil) 1692 c.Check(runSnaps, HasLen, 1) 1693 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1694 { 1695 Path: s.expectedPath("required20"), 1696 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1697 Required: true, 1698 Channel: "latest/stable", 1699 }, 1700 }) 1701 1702 installSnaps, err := seed20.ModeSnaps("install") 1703 c.Assert(err, IsNil) 1704 c.Check(installSnaps, HasLen, 3) 1705 c.Check(installSnaps, DeepEquals, []*seed.Snap{ 1706 { 1707 Path: s.expectedPath("required20"), 1708 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1709 Required: true, 1710 Channel: "latest/stable", 1711 }, 1712 { 1713 Path: s.expectedPath("optional20-a"), 1714 SideInfo: &s.AssertedSnapInfo("optional20-a").SideInfo, 1715 Required: false, 1716 Channel: "latest/stable", 1717 }, 1718 { 1719 Path: s.expectedPath("optional20-b"), 1720 SideInfo: &s.AssertedSnapInfo("optional20-b").SideInfo, 1721 Required: false, 1722 Channel: "latest/stable", 1723 }, 1724 }) 1725 1726 recoverSnaps, err := seed20.ModeSnaps("recover") 1727 c.Assert(err, IsNil) 1728 c.Check(recoverSnaps, HasLen, 2) 1729 c.Check(recoverSnaps, DeepEquals, []*seed.Snap{ 1730 { 1731 Path: s.expectedPath("required20"), 1732 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1733 Required: true, 1734 Channel: "latest/stable", 1735 }, 1736 { 1737 Path: s.expectedPath("optional20-a"), 1738 SideInfo: &s.AssertedSnapInfo("optional20-a").SideInfo, 1739 Required: false, 1740 Channel: "latest/stable", 1741 }, 1742 }) 1743 } 1744 1745 func (s *seed20Suite) TestLoadMetaCore20LocalAssertedSnaps(c *C) { 1746 s.makeSnap(c, "snapd", "") 1747 s.makeSnap(c, "core20", "") 1748 s.makeSnap(c, "pc-kernel=20", "") 1749 s.makeSnap(c, "pc=20", "") 1750 s.makeSnap(c, "required20", "developerid") 1751 1752 sysLabel := "20191209" 1753 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1754 "display-name": "my model", 1755 "architecture": "amd64", 1756 "base": "core20", 1757 "grade": "dangerous", 1758 "snaps": []interface{}{ 1759 map[string]interface{}{ 1760 "name": "pc-kernel", 1761 "id": s.AssertedSnapID("pc-kernel"), 1762 "type": "kernel", 1763 "default-channel": "20", 1764 }, 1765 map[string]interface{}{ 1766 "name": "pc", 1767 "id": s.AssertedSnapID("pc"), 1768 "type": "gadget", 1769 "default-channel": "20", 1770 }}, 1771 }, []*seedwriter.OptionsSnap{ 1772 {Path: s.AssertedSnap("pc"), Channel: "edge"}, 1773 {Path: s.AssertedSnap("required20")}, 1774 }) 1775 1776 seed20, err := seed.Open(s.SeedDir, sysLabel) 1777 c.Assert(err, IsNil) 1778 1779 err = seed20.LoadAssertions(s.db, s.commitTo) 1780 c.Assert(err, IsNil) 1781 1782 err = seed20.LoadMeta(s.perfTimings) 1783 c.Assert(err, IsNil) 1784 1785 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1786 1787 essSnaps := seed20.EssentialSnaps() 1788 c.Check(essSnaps, HasLen, 4) 1789 1790 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1791 { 1792 Path: s.expectedPath("snapd"), 1793 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1794 EssentialType: snap.TypeSnapd, 1795 Essential: true, 1796 Required: true, 1797 Channel: "latest/stable", 1798 }, { 1799 Path: s.expectedPath("pc-kernel"), 1800 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1801 EssentialType: snap.TypeKernel, 1802 Essential: true, 1803 Required: true, 1804 Channel: "20", 1805 }, { 1806 Path: s.expectedPath("core20"), 1807 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1808 EssentialType: snap.TypeBase, 1809 Essential: true, 1810 Required: true, 1811 Channel: "latest/stable", 1812 }, { 1813 Path: s.expectedPath("pc"), 1814 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1815 EssentialType: snap.TypeGadget, 1816 Essential: true, 1817 Required: true, 1818 Channel: "20/edge", 1819 }, 1820 }) 1821 1822 sysSnapsDir := filepath.Join(s.SeedDir, "systems", sysLabel, "snaps") 1823 1824 runSnaps, err := seed20.ModeSnaps("run") 1825 c.Assert(err, IsNil) 1826 c.Check(runSnaps, HasLen, 1) 1827 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1828 { 1829 Path: filepath.Join(sysSnapsDir, "required20_1.snap"), 1830 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1831 Channel: "latest/stable", 1832 }, 1833 }) 1834 } 1835 1836 func (s *seed20Suite) TestOpenInvalidLabel(c *C) { 1837 invalid := []string{ 1838 // empty string not included, as it's not a UC20 seed 1839 "/bin", 1840 "../../bin/bar", 1841 ":invalid:", 1842 "日本語", 1843 } 1844 for _, label := range invalid { 1845 seed20, err := seed.Open(s.SeedDir, label) 1846 c.Assert(err, ErrorMatches, fmt.Sprintf("invalid seed system label: %q", label)) 1847 c.Assert(seed20, IsNil) 1848 } 1849 }