gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/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").EditedContact = "mailto: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 err = seed20.LoadAssertions(nil, nil) 807 c.Assert(err, IsNil) 808 809 err = seed20.LoadEssentialMeta(t.onlyTypes, s.perfTimings) 810 c.Assert(err, IsNil) 811 812 c.Check(seed20.UsesSnapdSnap(), Equals, true) 813 814 essSnaps := seed20.EssentialSnaps() 815 c.Check(essSnaps, HasLen, len(t.expected)) 816 817 c.Check(essSnaps, DeepEquals, t.expected) 818 819 runSnaps, err := seed20.ModeSnaps("run") 820 c.Assert(err, IsNil) 821 c.Check(runSnaps, HasLen, 0) 822 823 unhide() 824 825 // test short-cut helper as well 826 mod, essSnaps, err := seed.ReadSystemEssential(s.SeedDir, sysLabel, t.onlyTypes, s.perfTimings) 827 c.Assert(err, IsNil) 828 c.Check(mod.BrandID(), Equals, "my-brand") 829 c.Check(mod.Model(), Equals, "my-model") 830 c.Check(essSnaps, HasLen, len(t.expected)) 831 c.Check(essSnaps, DeepEquals, t.expected) 832 } 833 } 834 835 func (s *seed20Suite) TestReadSystemEssentialAndBetterEarliestTime(c *C) { 836 r := seed.MockTrusted(s.StoreSigning.Trusted) 837 defer r() 838 839 s.makeSnap(c, "snapd", "") 840 s.makeSnap(c, "core20", "") 841 s.makeSnap(c, "pc-kernel=20", "") 842 s.makeSnap(c, "pc=20", "") 843 s.makeSnap(c, "core18", "") 844 t0 := time.Now().UTC().Truncate(time.Second) 845 s.SetSnapAssertionNow(t0.Add(2 * time.Second)) 846 s.makeSnap(c, "required18", "developerid") 847 s.SetSnapAssertionNow(time.Time{}) 848 849 snapdSnap := &seed.Snap{ 850 Path: s.expectedPath("snapd"), 851 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 852 EssentialType: snap.TypeSnapd, 853 Essential: true, 854 Required: true, 855 Channel: "latest/stable", 856 } 857 pcKernelSnap := &seed.Snap{ 858 Path: s.expectedPath("pc-kernel"), 859 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 860 EssentialType: snap.TypeKernel, 861 Essential: true, 862 Required: true, 863 Channel: "20", 864 } 865 core20Snap := &seed.Snap{Path: s.expectedPath("core20"), 866 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 867 EssentialType: snap.TypeBase, 868 Essential: true, 869 Required: true, 870 Channel: "latest/stable", 871 } 872 pcSnap := &seed.Snap{ 873 Path: s.expectedPath("pc"), 874 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 875 EssentialType: snap.TypeGadget, 876 Essential: true, 877 Required: true, 878 Channel: "20", 879 } 880 881 tests := []struct { 882 onlyTypes []snap.Type 883 expected []*seed.Snap 884 }{ 885 {[]snap.Type{snap.TypeSnapd}, []*seed.Snap{snapdSnap}}, 886 {[]snap.Type{snap.TypeKernel}, []*seed.Snap{pcKernelSnap}}, 887 {[]snap.Type{snap.TypeBase}, []*seed.Snap{core20Snap}}, 888 {[]snap.Type{snap.TypeGadget}, []*seed.Snap{pcSnap}}, 889 {[]snap.Type{snap.TypeSnapd, snap.TypeKernel, snap.TypeBase}, []*seed.Snap{snapdSnap, pcKernelSnap, core20Snap}}, 890 // the order in essentialTypes is not relevant 891 {[]snap.Type{snap.TypeGadget, snap.TypeKernel}, []*seed.Snap{pcKernelSnap, pcSnap}}, 892 // degenerate case 893 {[]snap.Type{}, []*seed.Snap(nil)}, 894 } 895 896 baseLabel := "20210315" 897 898 testReadSystemEssentialAndBetterEarliestTime := func(sysLabel string, earliestTime, modelTime, improvedTime time.Time) { 899 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 900 "display-name": "my model", 901 "timestamp": modelTime.Format(time.RFC3339), 902 "architecture": "amd64", 903 "base": "core20", 904 "snaps": []interface{}{ 905 map[string]interface{}{ 906 "name": "pc-kernel", 907 "id": s.AssertedSnapID("pc-kernel"), 908 "type": "kernel", 909 "default-channel": "20", 910 }, 911 map[string]interface{}{ 912 "name": "pc", 913 "id": s.AssertedSnapID("pc"), 914 "type": "gadget", 915 "default-channel": "20", 916 }, 917 map[string]interface{}{ 918 "name": "core18", 919 "id": s.AssertedSnapID("core18"), 920 "type": "base", 921 }, 922 map[string]interface{}{ 923 "name": "required18", 924 "id": s.AssertedSnapID("required18"), 925 }}, 926 }, nil) 927 928 for _, t := range tests { 929 // test short-cut helper as well 930 mod, essSnaps, betterTime, err := seed.ReadSystemEssentialAndBetterEarliestTime(s.SeedDir, sysLabel, t.onlyTypes, earliestTime, s.perfTimings) 931 c.Assert(err, IsNil) 932 c.Check(mod.BrandID(), Equals, "my-brand") 933 c.Check(mod.Model(), Equals, "my-model") 934 c.Check(mod.Timestamp().Equal(modelTime), Equals, true) 935 c.Check(essSnaps, HasLen, len(t.expected)) 936 c.Check(essSnaps, DeepEquals, t.expected) 937 c.Check(betterTime.Equal(improvedTime), Equals, true, Commentf("%v expected: %v", betterTime, improvedTime)) 938 } 939 } 940 941 revsTime := s.AssertedSnapRevision("required18").Timestamp() 942 t2 := revsTime.Add(1 * time.Second) 943 944 timeCombos := []struct { 945 earliestTime, modelTime, improvedTime time.Time 946 }{ 947 {time.Time{}, t0, revsTime}, 948 {t2.AddDate(-1, 0, 0), t0, revsTime}, 949 {t2.AddDate(-1, 0, 0), t2, t2}, 950 {t2.AddDate(0, 1, 0), t2, t2.AddDate(0, 1, 0)}, 951 } 952 953 for i, c := range timeCombos { 954 label := fmt.Sprintf("%s%d", baseLabel, i) 955 testReadSystemEssentialAndBetterEarliestTime(label, c.earliestTime, c.modelTime, c.improvedTime) 956 } 957 } 958 959 func (s *seed20Suite) TestLoadEssentialAndMetaCore20(c *C) { 960 r := seed.MockTrusted(s.StoreSigning.Trusted) 961 defer r() 962 963 s.makeSnap(c, "snapd", "") 964 s.makeSnap(c, "core20", "") 965 s.makeSnap(c, "pc-kernel=20", "") 966 s.makeSnap(c, "pc=20", "") 967 s.makeSnap(c, "core18", "") 968 s.makeSnap(c, "required18", "developerid") 969 970 sysLabel := "20191018" 971 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 972 "display-name": "my model", 973 "architecture": "amd64", 974 "base": "core20", 975 "snaps": []interface{}{ 976 map[string]interface{}{ 977 "name": "pc-kernel", 978 "id": s.AssertedSnapID("pc-kernel"), 979 "type": "kernel", 980 "default-channel": "20", 981 }, 982 map[string]interface{}{ 983 "name": "pc", 984 "id": s.AssertedSnapID("pc"), 985 "type": "gadget", 986 "default-channel": "20", 987 }, 988 map[string]interface{}{ 989 "name": "core18", 990 "id": s.AssertedSnapID("core18"), 991 "type": "base", 992 }, 993 map[string]interface{}{ 994 "name": "required18", 995 "id": s.AssertedSnapID("required18"), 996 }}, 997 }, nil) 998 999 snapdSnap := &seed.Snap{ 1000 Path: s.expectedPath("snapd"), 1001 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1002 EssentialType: snap.TypeSnapd, 1003 Essential: true, 1004 Required: true, 1005 Channel: "latest/stable", 1006 } 1007 pcKernelSnap := &seed.Snap{ 1008 Path: s.expectedPath("pc-kernel"), 1009 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1010 EssentialType: snap.TypeKernel, 1011 Essential: true, 1012 Required: true, 1013 Channel: "20", 1014 } 1015 core20Snap := &seed.Snap{Path: s.expectedPath("core20"), 1016 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1017 EssentialType: snap.TypeBase, 1018 Essential: true, 1019 Required: true, 1020 Channel: "latest/stable", 1021 } 1022 pcSnap := &seed.Snap{ 1023 Path: s.expectedPath("pc"), 1024 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1025 EssentialType: snap.TypeGadget, 1026 Essential: true, 1027 Required: true, 1028 Channel: "20", 1029 } 1030 1031 seed20, err := seed.Open(s.SeedDir, sysLabel) 1032 c.Assert(err, IsNil) 1033 1034 err = seed20.LoadAssertions(nil, nil) 1035 c.Assert(err, IsNil) 1036 1037 err = seed20.LoadEssentialMeta([]snap.Type{snap.TypeGadget}, s.perfTimings) 1038 c.Assert(err, IsNil) 1039 1040 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1041 1042 essSnaps := seed20.EssentialSnaps() 1043 c.Check(essSnaps, DeepEquals, []*seed.Snap{pcSnap}) 1044 1045 err = seed20.LoadEssentialMeta([]snap.Type{snap.TypeSnapd, snap.TypeKernel, snap.TypeBase, snap.TypeGadget}, s.perfTimings) 1046 c.Assert(err, IsNil) 1047 1048 essSnaps = seed20.EssentialSnaps() 1049 c.Check(essSnaps, DeepEquals, []*seed.Snap{snapdSnap, pcKernelSnap, core20Snap, pcSnap}) 1050 1051 runSnaps, err := seed20.ModeSnaps("run") 1052 c.Assert(err, IsNil) 1053 c.Check(runSnaps, HasLen, 0) 1054 1055 // caching in place 1056 hideSnaps(c, []*seed.Snap{snapdSnap, core20Snap, pcKernelSnap}, nil) 1057 1058 err = seed20.LoadMeta(s.perfTimings) 1059 c.Assert(err, IsNil) 1060 1061 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1062 1063 essSnaps = seed20.EssentialSnaps() 1064 c.Check(essSnaps, DeepEquals, []*seed.Snap{snapdSnap, pcKernelSnap, core20Snap, pcSnap}) 1065 1066 runSnaps, err = seed20.ModeSnaps("run") 1067 c.Assert(err, IsNil) 1068 c.Check(runSnaps, HasLen, 2) 1069 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1070 { 1071 Path: s.expectedPath("core18"), 1072 SideInfo: &s.AssertedSnapInfo("core18").SideInfo, 1073 Required: true, 1074 Channel: "latest/stable", 1075 }, { 1076 Path: s.expectedPath("required18"), 1077 SideInfo: &s.AssertedSnapInfo("required18").SideInfo, 1078 Required: true, 1079 Channel: "latest/stable", 1080 }, 1081 }) 1082 1083 } 1084 1085 func (s *seed20Suite) makeLocalSnap(c *C, yamlKey string) (fname string) { 1086 return snaptest.MakeTestSnapWithFiles(c, snapYaml[yamlKey], nil) 1087 } 1088 1089 func (s *seed20Suite) TestLoadMetaCore20LocalSnaps(c *C) { 1090 s.makeSnap(c, "snapd", "") 1091 s.makeSnap(c, "core20", "") 1092 s.makeSnap(c, "pc-kernel=20", "") 1093 s.makeSnap(c, "pc=20", "") 1094 requiredFn := s.makeLocalSnap(c, "required20") 1095 1096 sysLabel := "20191030" 1097 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1098 "display-name": "my model", 1099 "architecture": "amd64", 1100 "base": "core20", 1101 "grade": "dangerous", 1102 "snaps": []interface{}{ 1103 map[string]interface{}{ 1104 "name": "pc-kernel", 1105 "id": s.AssertedSnapID("pc-kernel"), 1106 "type": "kernel", 1107 "default-channel": "20", 1108 }, 1109 map[string]interface{}{ 1110 "name": "pc", 1111 "id": s.AssertedSnapID("pc"), 1112 "type": "gadget", 1113 "default-channel": "20", 1114 }, 1115 map[string]interface{}{ 1116 "name": "required20", 1117 "id": s.AssertedSnapID("required20"), 1118 }}, 1119 }, []*seedwriter.OptionsSnap{ 1120 {Path: requiredFn}, 1121 }) 1122 1123 seed20, err := seed.Open(s.SeedDir, sysLabel) 1124 c.Assert(err, IsNil) 1125 1126 err = seed20.LoadAssertions(s.db, s.commitTo) 1127 c.Assert(err, IsNil) 1128 1129 err = seed20.LoadMeta(s.perfTimings) 1130 c.Assert(err, IsNil) 1131 1132 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1133 1134 essSnaps := seed20.EssentialSnaps() 1135 c.Check(essSnaps, HasLen, 4) 1136 1137 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1138 { 1139 Path: s.expectedPath("snapd"), 1140 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1141 EssentialType: snap.TypeSnapd, 1142 Essential: true, 1143 Required: true, 1144 Channel: "latest/stable", 1145 }, { 1146 Path: s.expectedPath("pc-kernel"), 1147 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1148 EssentialType: snap.TypeKernel, 1149 Essential: true, 1150 Required: true, 1151 Channel: "20", 1152 }, { 1153 Path: s.expectedPath("core20"), 1154 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1155 EssentialType: snap.TypeBase, 1156 Essential: true, 1157 Required: true, 1158 Channel: "latest/stable", 1159 }, { 1160 Path: s.expectedPath("pc"), 1161 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1162 EssentialType: snap.TypeGadget, 1163 Essential: true, 1164 Required: true, 1165 Channel: "20", 1166 }, 1167 }) 1168 1169 runSnaps, err := seed20.ModeSnaps("run") 1170 c.Assert(err, IsNil) 1171 c.Check(runSnaps, HasLen, 1) 1172 1173 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1174 { 1175 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "required20_1.0.snap"), 1176 SideInfo: &snap.SideInfo{RealName: "required20"}, 1177 Required: true, 1178 }, 1179 }) 1180 } 1181 1182 func (s *seed20Suite) TestLoadMetaCore20ChannelOverride(c *C) { 1183 s.makeSnap(c, "snapd", "") 1184 s.makeSnap(c, "core20", "") 1185 s.makeSnap(c, "pc-kernel=20", "") 1186 s.makeSnap(c, "pc=20", "") 1187 s.makeSnap(c, "required20", "developerid") 1188 1189 s.AssertedSnapInfo("required20").EditedContact = "mailto:author@example.com" 1190 1191 sysLabel := "20191018" 1192 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1193 "display-name": "my model", 1194 "architecture": "amd64", 1195 "base": "core20", 1196 "grade": "dangerous", 1197 "snaps": []interface{}{ 1198 map[string]interface{}{ 1199 "name": "pc-kernel", 1200 "id": s.AssertedSnapID("pc-kernel"), 1201 "type": "kernel", 1202 "default-channel": "20", 1203 }, 1204 map[string]interface{}{ 1205 "name": "pc", 1206 "id": s.AssertedSnapID("pc"), 1207 "type": "gadget", 1208 "default-channel": "20", 1209 }, 1210 map[string]interface{}{ 1211 "name": "required20", 1212 "id": s.AssertedSnapID("required20"), 1213 }}, 1214 }, []*seedwriter.OptionsSnap{ 1215 {Name: "pc", Channel: "20experimental/edge"}, 1216 }) 1217 1218 seed20, err := seed.Open(s.SeedDir, sysLabel) 1219 c.Assert(err, IsNil) 1220 1221 err = seed20.LoadAssertions(s.db, s.commitTo) 1222 c.Assert(err, IsNil) 1223 1224 err = seed20.LoadMeta(s.perfTimings) 1225 c.Assert(err, IsNil) 1226 1227 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1228 1229 essSnaps := seed20.EssentialSnaps() 1230 c.Check(essSnaps, HasLen, 4) 1231 1232 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1233 { 1234 Path: s.expectedPath("snapd"), 1235 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1236 EssentialType: snap.TypeSnapd, 1237 Essential: true, 1238 Required: true, 1239 Channel: "latest/stable", 1240 }, { 1241 Path: s.expectedPath("pc-kernel"), 1242 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1243 EssentialType: snap.TypeKernel, 1244 Essential: true, 1245 Required: true, 1246 Channel: "20", 1247 }, { 1248 Path: s.expectedPath("core20"), 1249 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1250 EssentialType: snap.TypeBase, 1251 Essential: true, 1252 Required: true, 1253 Channel: "latest/stable", 1254 }, { 1255 Path: s.expectedPath("pc"), 1256 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1257 EssentialType: snap.TypeGadget, 1258 Essential: true, 1259 Required: true, 1260 Channel: "20experimental/edge", 1261 }, 1262 }) 1263 1264 runSnaps, err := seed20.ModeSnaps("run") 1265 c.Assert(err, IsNil) 1266 c.Check(runSnaps, HasLen, 1) 1267 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1268 { 1269 Path: s.expectedPath("required20"), 1270 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1271 Required: true, 1272 Channel: "latest/stable", 1273 }, 1274 }) 1275 } 1276 1277 func (s *seed20Suite) TestLoadMetaCore20ChannelOverrideSnapd(c *C) { 1278 s.makeSnap(c, "snapd", "") 1279 s.makeSnap(c, "core20", "") 1280 s.makeSnap(c, "pc-kernel=20", "") 1281 s.makeSnap(c, "pc=20", "") 1282 s.makeSnap(c, "required20", "developerid") 1283 1284 s.AssertedSnapInfo("required20").EditedContact = "mailto:author@example.com" 1285 1286 sysLabel := "20191121" 1287 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1288 "display-name": "my model", 1289 "architecture": "amd64", 1290 "base": "core20", 1291 "grade": "dangerous", 1292 "snaps": []interface{}{ 1293 map[string]interface{}{ 1294 "name": "pc-kernel", 1295 "id": s.AssertedSnapID("pc-kernel"), 1296 "type": "kernel", 1297 "default-channel": "20", 1298 }, 1299 map[string]interface{}{ 1300 "name": "pc", 1301 "id": s.AssertedSnapID("pc"), 1302 "type": "gadget", 1303 "default-channel": "20", 1304 }, 1305 map[string]interface{}{ 1306 "name": "required20", 1307 "id": s.AssertedSnapID("required20"), 1308 }}, 1309 }, []*seedwriter.OptionsSnap{ 1310 {Name: "snapd", Channel: "20experimental/edge"}, 1311 }) 1312 1313 seed20, err := seed.Open(s.SeedDir, sysLabel) 1314 c.Assert(err, IsNil) 1315 1316 err = seed20.LoadAssertions(s.db, s.commitTo) 1317 c.Assert(err, IsNil) 1318 1319 err = seed20.LoadMeta(s.perfTimings) 1320 c.Assert(err, IsNil) 1321 1322 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1323 1324 essSnaps := seed20.EssentialSnaps() 1325 c.Check(essSnaps, HasLen, 4) 1326 1327 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1328 { 1329 Path: s.expectedPath("snapd"), 1330 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1331 EssentialType: snap.TypeSnapd, 1332 Essential: true, 1333 Required: true, 1334 Channel: "20experimental/edge", 1335 }, { 1336 Path: s.expectedPath("pc-kernel"), 1337 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1338 EssentialType: snap.TypeKernel, 1339 Essential: true, 1340 Required: true, 1341 Channel: "20", 1342 }, { 1343 Path: s.expectedPath("core20"), 1344 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1345 EssentialType: snap.TypeBase, 1346 Essential: true, 1347 Required: true, 1348 Channel: "latest/stable", 1349 }, { 1350 Path: s.expectedPath("pc"), 1351 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1352 EssentialType: snap.TypeGadget, 1353 Essential: true, 1354 Required: true, 1355 Channel: "20", 1356 }, 1357 }) 1358 1359 runSnaps, err := seed20.ModeSnaps("run") 1360 c.Assert(err, IsNil) 1361 c.Check(runSnaps, HasLen, 1) 1362 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1363 { 1364 Path: s.expectedPath("required20"), 1365 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1366 Required: true, 1367 Channel: "latest/stable", 1368 }, 1369 }) 1370 } 1371 1372 func (s *seed20Suite) TestLoadMetaCore20LocalSnapd(c *C) { 1373 snapdFn := s.makeLocalSnap(c, "snapd") 1374 s.makeSnap(c, "core20", "") 1375 s.makeSnap(c, "pc-kernel=20", "") 1376 s.makeSnap(c, "pc=20", "") 1377 1378 sysLabel := "20191121" 1379 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1380 "display-name": "my model", 1381 "architecture": "amd64", 1382 "base": "core20", 1383 "grade": "dangerous", 1384 "snaps": []interface{}{ 1385 map[string]interface{}{ 1386 "name": "pc-kernel", 1387 "id": s.AssertedSnapID("pc-kernel"), 1388 "type": "kernel", 1389 "default-channel": "20", 1390 }, 1391 map[string]interface{}{ 1392 "name": "pc", 1393 "id": s.AssertedSnapID("pc"), 1394 "type": "gadget", 1395 "default-channel": "20", 1396 }}, 1397 }, []*seedwriter.OptionsSnap{ 1398 {Path: snapdFn}, 1399 }) 1400 1401 seed20, err := seed.Open(s.SeedDir, sysLabel) 1402 c.Assert(err, IsNil) 1403 1404 err = seed20.LoadAssertions(s.db, s.commitTo) 1405 c.Assert(err, IsNil) 1406 1407 err = seed20.LoadMeta(s.perfTimings) 1408 c.Assert(err, IsNil) 1409 1410 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1411 1412 essSnaps := seed20.EssentialSnaps() 1413 c.Check(essSnaps, HasLen, 4) 1414 1415 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1416 { 1417 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "snapd_1.0.snap"), 1418 SideInfo: &snap.SideInfo{RealName: "snapd"}, 1419 Essential: true, 1420 EssentialType: snap.TypeSnapd, 1421 Required: true, 1422 }, { 1423 Path: s.expectedPath("pc-kernel"), 1424 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1425 EssentialType: snap.TypeKernel, 1426 Essential: true, 1427 Required: true, 1428 Channel: "20", 1429 }, { 1430 Path: s.expectedPath("core20"), 1431 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1432 EssentialType: snap.TypeBase, 1433 Essential: true, 1434 Required: true, 1435 Channel: "latest/stable", 1436 }, { 1437 Path: s.expectedPath("pc"), 1438 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1439 EssentialType: snap.TypeGadget, 1440 Essential: true, 1441 Required: true, 1442 Channel: "20", 1443 }, 1444 }) 1445 1446 runSnaps, err := seed20.ModeSnaps("run") 1447 c.Assert(err, IsNil) 1448 c.Check(runSnaps, HasLen, 0) 1449 } 1450 1451 func (s *seed20Suite) TestLoadMetaCore20ModelOverrideSnapd(c *C) { 1452 s.makeSnap(c, "snapd", "") 1453 s.makeSnap(c, "core20", "") 1454 s.makeSnap(c, "pc-kernel=20", "") 1455 s.makeSnap(c, "pc=20", "") 1456 1457 sysLabel := "20191121" 1458 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1459 "display-name": "my model", 1460 "architecture": "amd64", 1461 "base": "core20", 1462 "grade": "dangerous", 1463 "snaps": []interface{}{ 1464 map[string]interface{}{ 1465 "name": "snapd", 1466 "type": "snapd", 1467 "default-channel": "latest/edge", 1468 }, 1469 map[string]interface{}{ 1470 "name": "pc-kernel", 1471 "id": s.AssertedSnapID("pc-kernel"), 1472 "type": "kernel", 1473 "default-channel": "20", 1474 }, 1475 map[string]interface{}{ 1476 "name": "pc", 1477 "id": s.AssertedSnapID("pc"), 1478 "type": "gadget", 1479 "default-channel": "20", 1480 }}, 1481 }, nil) 1482 1483 seed20, err := seed.Open(s.SeedDir, sysLabel) 1484 c.Assert(err, IsNil) 1485 1486 err = seed20.LoadAssertions(s.db, s.commitTo) 1487 c.Assert(err, IsNil) 1488 1489 err = seed20.LoadMeta(s.perfTimings) 1490 c.Assert(err, IsNil) 1491 1492 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1493 1494 essSnaps := seed20.EssentialSnaps() 1495 c.Check(essSnaps, HasLen, 4) 1496 1497 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1498 { 1499 Path: s.expectedPath("snapd"), 1500 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1501 EssentialType: snap.TypeSnapd, 1502 Essential: true, 1503 Required: true, 1504 Channel: "latest/edge", 1505 }, { 1506 Path: s.expectedPath("pc-kernel"), 1507 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1508 EssentialType: snap.TypeKernel, 1509 Essential: true, 1510 Required: true, 1511 Channel: "20", 1512 }, { 1513 Path: s.expectedPath("core20"), 1514 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1515 EssentialType: snap.TypeBase, 1516 Essential: true, 1517 Required: true, 1518 Channel: "latest/stable", 1519 }, { 1520 Path: s.expectedPath("pc"), 1521 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1522 EssentialType: snap.TypeGadget, 1523 Essential: true, 1524 Required: true, 1525 Channel: "20", 1526 }, 1527 }) 1528 1529 runSnaps, err := seed20.ModeSnaps("run") 1530 c.Assert(err, IsNil) 1531 c.Check(runSnaps, HasLen, 0) 1532 } 1533 1534 func (s *seed20Suite) TestLoadMetaCore20OptionalSnaps(c *C) { 1535 s.makeSnap(c, "snapd", "") 1536 s.makeSnap(c, "core20", "") 1537 s.makeSnap(c, "pc-kernel=20", "") 1538 s.makeSnap(c, "pc=20", "") 1539 s.makeSnap(c, "optional20-a", "developerid") 1540 s.makeSnap(c, "optional20-b", "developerid") 1541 1542 sysLabel := "20191122" 1543 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1544 "display-name": "my model", 1545 "architecture": "amd64", 1546 "base": "core20", 1547 "grade": "signed", 1548 "snaps": []interface{}{ 1549 map[string]interface{}{ 1550 "name": "pc-kernel", 1551 "id": s.AssertedSnapID("pc-kernel"), 1552 "type": "kernel", 1553 "default-channel": "20", 1554 }, 1555 map[string]interface{}{ 1556 "name": "pc", 1557 "id": s.AssertedSnapID("pc"), 1558 "type": "gadget", 1559 "default-channel": "20", 1560 }, 1561 map[string]interface{}{ 1562 "name": "optional20-a", 1563 "id": s.AssertedSnapID("optional20-a"), 1564 "presence": "optional", 1565 }, 1566 map[string]interface{}{ 1567 "name": "optional20-b", 1568 "id": s.AssertedSnapID("optional20-b"), 1569 "presence": "optional", 1570 }}, 1571 }, []*seedwriter.OptionsSnap{ 1572 {Name: "optional20-b"}, 1573 }) 1574 1575 seed20, err := seed.Open(s.SeedDir, sysLabel) 1576 c.Assert(err, IsNil) 1577 1578 err = seed20.LoadAssertions(s.db, s.commitTo) 1579 c.Assert(err, IsNil) 1580 1581 err = seed20.LoadMeta(s.perfTimings) 1582 c.Assert(err, IsNil) 1583 1584 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1585 1586 essSnaps := seed20.EssentialSnaps() 1587 c.Check(essSnaps, HasLen, 4) 1588 1589 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1590 { 1591 Path: s.expectedPath("snapd"), 1592 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1593 EssentialType: snap.TypeSnapd, 1594 Essential: true, 1595 Required: true, 1596 Channel: "latest/stable", 1597 }, { 1598 Path: s.expectedPath("pc-kernel"), 1599 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1600 EssentialType: snap.TypeKernel, 1601 Essential: true, 1602 Required: true, 1603 Channel: "20", 1604 }, { 1605 Path: s.expectedPath("core20"), 1606 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1607 EssentialType: snap.TypeBase, 1608 Essential: true, 1609 Required: true, 1610 Channel: "latest/stable", 1611 }, { 1612 Path: s.expectedPath("pc"), 1613 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1614 EssentialType: snap.TypeGadget, 1615 Essential: true, 1616 Required: true, 1617 Channel: "20", 1618 }, 1619 }) 1620 1621 runSnaps, err := seed20.ModeSnaps("run") 1622 c.Assert(err, IsNil) 1623 c.Check(runSnaps, HasLen, 1) 1624 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1625 { 1626 Path: s.expectedPath("optional20-b"), 1627 SideInfo: &s.AssertedSnapInfo("optional20-b").SideInfo, 1628 Required: false, 1629 Channel: "latest/stable", 1630 }, 1631 }) 1632 } 1633 1634 func (s *seed20Suite) TestLoadMetaCore20OptionalSnapsLocal(c *C) { 1635 s.makeSnap(c, "snapd", "") 1636 s.makeSnap(c, "core20", "") 1637 s.makeSnap(c, "pc-kernel=20", "") 1638 s.makeSnap(c, "pc=20", "") 1639 s.makeSnap(c, "optional20-a", "developerid") 1640 optional20bFn := s.makeLocalSnap(c, "optional20-b") 1641 1642 sysLabel := "20191122" 1643 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1644 "display-name": "my model", 1645 "architecture": "amd64", 1646 "base": "core20", 1647 "grade": "dangerous", 1648 "snaps": []interface{}{ 1649 map[string]interface{}{ 1650 "name": "pc-kernel", 1651 "id": s.AssertedSnapID("pc-kernel"), 1652 "type": "kernel", 1653 "default-channel": "20", 1654 }, 1655 map[string]interface{}{ 1656 "name": "pc", 1657 "id": s.AssertedSnapID("pc"), 1658 "type": "gadget", 1659 "default-channel": "20", 1660 }, 1661 map[string]interface{}{ 1662 "name": "optional20-a", 1663 "id": s.AssertedSnapID("optional20-a"), 1664 "presence": "optional", 1665 }, 1666 map[string]interface{}{ 1667 "name": "optional20-b", 1668 "id": s.AssertedSnapID("optional20-b"), 1669 "presence": "optional", 1670 }}, 1671 }, []*seedwriter.OptionsSnap{ 1672 {Path: optional20bFn}, 1673 }) 1674 1675 seed20, err := seed.Open(s.SeedDir, sysLabel) 1676 c.Assert(err, IsNil) 1677 1678 err = seed20.LoadAssertions(s.db, s.commitTo) 1679 c.Assert(err, IsNil) 1680 1681 err = seed20.LoadMeta(s.perfTimings) 1682 c.Assert(err, IsNil) 1683 1684 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1685 1686 essSnaps := seed20.EssentialSnaps() 1687 c.Check(essSnaps, HasLen, 4) 1688 1689 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1690 { 1691 Path: s.expectedPath("snapd"), 1692 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1693 EssentialType: snap.TypeSnapd, 1694 Essential: true, 1695 Required: true, 1696 Channel: "latest/stable", 1697 }, { 1698 Path: s.expectedPath("pc-kernel"), 1699 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1700 EssentialType: snap.TypeKernel, 1701 Essential: true, 1702 Required: true, 1703 Channel: "20", 1704 }, { 1705 Path: s.expectedPath("core20"), 1706 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1707 EssentialType: snap.TypeBase, 1708 Essential: true, 1709 Required: true, 1710 Channel: "latest/stable", 1711 }, { 1712 Path: s.expectedPath("pc"), 1713 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1714 EssentialType: snap.TypeGadget, 1715 Essential: true, 1716 Required: true, 1717 Channel: "20", 1718 }, 1719 }) 1720 1721 runSnaps, err := seed20.ModeSnaps("run") 1722 c.Assert(err, IsNil) 1723 c.Check(runSnaps, HasLen, 1) 1724 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1725 { 1726 Path: filepath.Join(s.SeedDir, "systems", sysLabel, "snaps", "optional20-b_1.0.snap"), 1727 SideInfo: &snap.SideInfo{RealName: "optional20-b"}, 1728 1729 Required: false, 1730 }, 1731 }) 1732 } 1733 1734 func (s *seed20Suite) TestLoadMetaCore20ExtraSnaps(c *C) { 1735 s.makeSnap(c, "snapd", "") 1736 s.makeSnap(c, "core20", "") 1737 s.makeSnap(c, "pc-kernel=20", "") 1738 s.makeSnap(c, "pc=20", "") 1739 s.makeSnap(c, "core18", "") 1740 s.makeSnap(c, "cont-producer", "developerid") 1741 contConsumerFn := s.makeLocalSnap(c, "cont-consumer") 1742 1743 sysLabel := "20191122" 1744 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1745 "display-name": "my model", 1746 "architecture": "amd64", 1747 "base": "core20", 1748 "grade": "dangerous", 1749 "snaps": []interface{}{ 1750 map[string]interface{}{ 1751 "name": "pc-kernel", 1752 "id": s.AssertedSnapID("pc-kernel"), 1753 "type": "kernel", 1754 "default-channel": "20", 1755 }, 1756 map[string]interface{}{ 1757 "name": "pc", 1758 "id": s.AssertedSnapID("pc"), 1759 "type": "gadget", 1760 "default-channel": "20", 1761 }}, 1762 }, []*seedwriter.OptionsSnap{ 1763 {Name: "cont-producer", Channel: "edge"}, 1764 {Name: "core18"}, 1765 {Path: contConsumerFn}, 1766 }) 1767 1768 seed20, err := seed.Open(s.SeedDir, sysLabel) 1769 c.Assert(err, IsNil) 1770 1771 err = seed20.LoadAssertions(s.db, s.commitTo) 1772 c.Assert(err, IsNil) 1773 1774 err = seed20.LoadMeta(s.perfTimings) 1775 c.Assert(err, IsNil) 1776 1777 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1778 1779 essSnaps := seed20.EssentialSnaps() 1780 c.Check(essSnaps, HasLen, 4) 1781 1782 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1783 { 1784 Path: s.expectedPath("snapd"), 1785 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1786 EssentialType: snap.TypeSnapd, 1787 Essential: true, 1788 Required: true, 1789 Channel: "latest/stable", 1790 }, { 1791 Path: s.expectedPath("pc-kernel"), 1792 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1793 EssentialType: snap.TypeKernel, 1794 Essential: true, 1795 Required: true, 1796 Channel: "20", 1797 }, { 1798 Path: s.expectedPath("core20"), 1799 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1800 EssentialType: snap.TypeBase, 1801 Essential: true, 1802 Required: true, 1803 Channel: "latest/stable", 1804 }, { 1805 Path: s.expectedPath("pc"), 1806 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1807 EssentialType: snap.TypeGadget, 1808 Essential: true, 1809 Required: true, 1810 Channel: "20", 1811 }, 1812 }) 1813 1814 sysSnapsDir := filepath.Join(s.SeedDir, "systems", sysLabel, "snaps") 1815 1816 runSnaps, err := seed20.ModeSnaps("run") 1817 c.Assert(err, IsNil) 1818 c.Check(runSnaps, HasLen, 3) 1819 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1820 { 1821 Path: filepath.Join(sysSnapsDir, "cont-producer_1.snap"), 1822 SideInfo: &s.AssertedSnapInfo("cont-producer").SideInfo, 1823 Channel: "latest/edge", 1824 }, 1825 { 1826 Path: filepath.Join(sysSnapsDir, "core18_1.snap"), 1827 SideInfo: &s.AssertedSnapInfo("core18").SideInfo, 1828 Channel: "latest/stable", 1829 }, 1830 { 1831 Path: filepath.Join(sysSnapsDir, "cont-consumer_1.0.snap"), 1832 SideInfo: &snap.SideInfo{RealName: "cont-consumer"}, 1833 }, 1834 }) 1835 1836 recoverSnaps, err := seed20.ModeSnaps("recover") 1837 c.Assert(err, IsNil) 1838 c.Check(recoverSnaps, HasLen, 0) 1839 } 1840 1841 func (s *seed20Suite) TestLoadMetaCore20NotRunSnaps(c *C) { 1842 s.makeSnap(c, "snapd", "") 1843 s.makeSnap(c, "core20", "") 1844 s.makeSnap(c, "pc-kernel=20", "") 1845 s.makeSnap(c, "pc=20", "") 1846 s.makeSnap(c, "required20", "developerid") 1847 s.makeSnap(c, "optional20-a", "developerid") 1848 s.makeSnap(c, "optional20-b", "developerid") 1849 1850 sysLabel := "20191122" 1851 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 1852 "display-name": "my model", 1853 "architecture": "amd64", 1854 "base": "core20", 1855 "grade": "signed", 1856 "snaps": []interface{}{ 1857 map[string]interface{}{ 1858 "name": "pc-kernel", 1859 "id": s.AssertedSnapID("pc-kernel"), 1860 "type": "kernel", 1861 "default-channel": "20", 1862 }, 1863 map[string]interface{}{ 1864 "name": "pc", 1865 "id": s.AssertedSnapID("pc"), 1866 "type": "gadget", 1867 "default-channel": "20", 1868 }, 1869 map[string]interface{}{ 1870 "name": "required20", 1871 "id": s.AssertedSnapID("required20"), 1872 "modes": []interface{}{"run", "ephemeral"}, 1873 }, 1874 map[string]interface{}{ 1875 "name": "optional20-a", 1876 "id": s.AssertedSnapID("optional20-a"), 1877 "presence": "optional", 1878 "modes": []interface{}{"ephemeral"}, 1879 }, 1880 map[string]interface{}{ 1881 "name": "optional20-b", 1882 "id": s.AssertedSnapID("optional20-b"), 1883 "presence": "optional", 1884 "modes": []interface{}{"install"}, 1885 }}, 1886 }, []*seedwriter.OptionsSnap{ 1887 {Name: "optional20-a"}, 1888 {Name: "optional20-b"}, 1889 }) 1890 1891 seed20, err := seed.Open(s.SeedDir, sysLabel) 1892 c.Assert(err, IsNil) 1893 1894 err = seed20.LoadAssertions(s.db, s.commitTo) 1895 c.Assert(err, IsNil) 1896 1897 err = seed20.LoadMeta(s.perfTimings) 1898 c.Assert(err, IsNil) 1899 1900 c.Check(seed20.UsesSnapdSnap(), Equals, true) 1901 1902 essSnaps := seed20.EssentialSnaps() 1903 c.Check(essSnaps, HasLen, 4) 1904 1905 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 1906 { 1907 Path: s.expectedPath("snapd"), 1908 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 1909 EssentialType: snap.TypeSnapd, 1910 Essential: true, 1911 Required: true, 1912 Channel: "latest/stable", 1913 }, { 1914 Path: s.expectedPath("pc-kernel"), 1915 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 1916 EssentialType: snap.TypeKernel, 1917 Essential: true, 1918 Required: true, 1919 Channel: "20", 1920 }, { 1921 Path: s.expectedPath("core20"), 1922 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 1923 EssentialType: snap.TypeBase, 1924 Essential: true, 1925 Required: true, 1926 Channel: "latest/stable", 1927 }, { 1928 Path: s.expectedPath("pc"), 1929 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 1930 EssentialType: snap.TypeGadget, 1931 Essential: true, 1932 Required: true, 1933 Channel: "20", 1934 }, 1935 }) 1936 1937 runSnaps, err := seed20.ModeSnaps("run") 1938 c.Assert(err, IsNil) 1939 c.Check(runSnaps, HasLen, 1) 1940 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 1941 { 1942 Path: s.expectedPath("required20"), 1943 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1944 Required: true, 1945 Channel: "latest/stable", 1946 }, 1947 }) 1948 1949 installSnaps, err := seed20.ModeSnaps("install") 1950 c.Assert(err, IsNil) 1951 c.Check(installSnaps, HasLen, 3) 1952 c.Check(installSnaps, DeepEquals, []*seed.Snap{ 1953 { 1954 Path: s.expectedPath("required20"), 1955 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1956 Required: true, 1957 Channel: "latest/stable", 1958 }, 1959 { 1960 Path: s.expectedPath("optional20-a"), 1961 SideInfo: &s.AssertedSnapInfo("optional20-a").SideInfo, 1962 Required: false, 1963 Channel: "latest/stable", 1964 }, 1965 { 1966 Path: s.expectedPath("optional20-b"), 1967 SideInfo: &s.AssertedSnapInfo("optional20-b").SideInfo, 1968 Required: false, 1969 Channel: "latest/stable", 1970 }, 1971 }) 1972 1973 recoverSnaps, err := seed20.ModeSnaps("recover") 1974 c.Assert(err, IsNil) 1975 c.Check(recoverSnaps, HasLen, 2) 1976 c.Check(recoverSnaps, DeepEquals, []*seed.Snap{ 1977 { 1978 Path: s.expectedPath("required20"), 1979 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 1980 Required: true, 1981 Channel: "latest/stable", 1982 }, 1983 { 1984 Path: s.expectedPath("optional20-a"), 1985 SideInfo: &s.AssertedSnapInfo("optional20-a").SideInfo, 1986 Required: false, 1987 Channel: "latest/stable", 1988 }, 1989 }) 1990 } 1991 1992 func (s *seed20Suite) TestLoadMetaCore20LocalAssertedSnaps(c *C) { 1993 s.makeSnap(c, "snapd", "") 1994 s.makeSnap(c, "core20", "") 1995 s.makeSnap(c, "pc-kernel=20", "") 1996 s.makeSnap(c, "pc=20", "") 1997 s.makeSnap(c, "required20", "developerid") 1998 1999 sysLabel := "20191209" 2000 s.MakeSeed(c, sysLabel, "my-brand", "my-model", map[string]interface{}{ 2001 "display-name": "my model", 2002 "architecture": "amd64", 2003 "base": "core20", 2004 "grade": "dangerous", 2005 "snaps": []interface{}{ 2006 map[string]interface{}{ 2007 "name": "pc-kernel", 2008 "id": s.AssertedSnapID("pc-kernel"), 2009 "type": "kernel", 2010 "default-channel": "20", 2011 }, 2012 map[string]interface{}{ 2013 "name": "pc", 2014 "id": s.AssertedSnapID("pc"), 2015 "type": "gadget", 2016 "default-channel": "20", 2017 }}, 2018 }, []*seedwriter.OptionsSnap{ 2019 {Path: s.AssertedSnap("pc"), Channel: "edge"}, 2020 {Path: s.AssertedSnap("required20")}, 2021 }) 2022 2023 seed20, err := seed.Open(s.SeedDir, sysLabel) 2024 c.Assert(err, IsNil) 2025 2026 err = seed20.LoadAssertions(s.db, s.commitTo) 2027 c.Assert(err, IsNil) 2028 2029 err = seed20.LoadMeta(s.perfTimings) 2030 c.Assert(err, IsNil) 2031 2032 c.Check(seed20.UsesSnapdSnap(), Equals, true) 2033 2034 essSnaps := seed20.EssentialSnaps() 2035 c.Check(essSnaps, HasLen, 4) 2036 2037 c.Check(essSnaps, DeepEquals, []*seed.Snap{ 2038 { 2039 Path: s.expectedPath("snapd"), 2040 SideInfo: &s.AssertedSnapInfo("snapd").SideInfo, 2041 EssentialType: snap.TypeSnapd, 2042 Essential: true, 2043 Required: true, 2044 Channel: "latest/stable", 2045 }, { 2046 Path: s.expectedPath("pc-kernel"), 2047 SideInfo: &s.AssertedSnapInfo("pc-kernel").SideInfo, 2048 EssentialType: snap.TypeKernel, 2049 Essential: true, 2050 Required: true, 2051 Channel: "20", 2052 }, { 2053 Path: s.expectedPath("core20"), 2054 SideInfo: &s.AssertedSnapInfo("core20").SideInfo, 2055 EssentialType: snap.TypeBase, 2056 Essential: true, 2057 Required: true, 2058 Channel: "latest/stable", 2059 }, { 2060 Path: s.expectedPath("pc"), 2061 SideInfo: &s.AssertedSnapInfo("pc").SideInfo, 2062 EssentialType: snap.TypeGadget, 2063 Essential: true, 2064 Required: true, 2065 Channel: "20/edge", 2066 }, 2067 }) 2068 2069 sysSnapsDir := filepath.Join(s.SeedDir, "systems", sysLabel, "snaps") 2070 2071 runSnaps, err := seed20.ModeSnaps("run") 2072 c.Assert(err, IsNil) 2073 c.Check(runSnaps, HasLen, 1) 2074 c.Check(runSnaps, DeepEquals, []*seed.Snap{ 2075 { 2076 Path: filepath.Join(sysSnapsDir, "required20_1.snap"), 2077 SideInfo: &s.AssertedSnapInfo("required20").SideInfo, 2078 Channel: "latest/stable", 2079 }, 2080 }) 2081 } 2082 2083 func (s *seed20Suite) TestOpenInvalidLabel(c *C) { 2084 invalid := []string{ 2085 // empty string not included, as it's not a UC20 seed 2086 "/bin", 2087 "../../bin/bar", 2088 ":invalid:", 2089 "日本語", 2090 } 2091 for _, label := range invalid { 2092 seed20, err := seed.Open(s.SeedDir, label) 2093 c.Assert(err, ErrorMatches, fmt.Sprintf("invalid seed system label: %q", label)) 2094 c.Assert(seed20, IsNil) 2095 } 2096 }