gopkg.in/ubuntu-core/snappy.v0@v0.0.0-20210902073436-25a8614f10a6/overlord/snapstate/aliasesv2_test.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 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 snapstate_test 21 22 import ( 23 "fmt" 24 "sort" 25 "strings" 26 27 . "gopkg.in/check.v1" 28 29 "github.com/snapcore/snapd/overlord/snapstate" 30 "github.com/snapcore/snapd/overlord/snapstate/backend" 31 "github.com/snapcore/snapd/overlord/state" 32 "github.com/snapcore/snapd/snap" 33 "github.com/snapcore/snapd/snap/snaptest" 34 ) 35 36 func target(at *snapstate.AliasTarget) string { 37 if at.Manual != "" { 38 return at.Manual 39 } 40 return at.Auto 41 } 42 43 func (s *snapmgrTestSuite) TestApplyAliasesChange(c *C) { 44 auto1 := &snapstate.AliasTarget{ 45 Auto: "cmd1", 46 } 47 48 auto2 := &snapstate.AliasTarget{ 49 Auto: "cmd2", 50 } 51 52 manual1 := &snapstate.AliasTarget{ 53 Manual: "cmd1", 54 } 55 56 manual2 := &snapstate.AliasTarget{ 57 Manual: "manual2", 58 Auto: "cmd1", 59 } 60 61 scenarios := []struct { 62 autoDisabled bool 63 newAutoDisabled bool 64 target *snapstate.AliasTarget 65 newTarget *snapstate.AliasTarget 66 ops string 67 }{ 68 {false, false, nil, auto1, "add"}, 69 {false, true, auto1, auto1, "rm"}, 70 {false, false, auto1, auto2, "rm add"}, 71 {false, false, auto1, nil, "rm"}, 72 {false, false, nil, manual1, "add"}, 73 {true, true, nil, manual1, "add"}, 74 {false, true, auto1, manual2, "rm add"}, 75 {false, false, manual2, nil, "rm"}, 76 {false, false, manual2, auto1, "rm add"}, 77 {false, false, manual1, auto1, ""}, 78 {true, false, manual1, auto1, ""}, 79 } 80 81 for _, scenario := range scenarios { 82 prevAliases := make(map[string]*snapstate.AliasTarget) 83 if scenario.target != nil { 84 prevAliases["myalias"] = scenario.target 85 } 86 newAliases := make(map[string]*snapstate.AliasTarget) 87 if scenario.newTarget != nil { 88 newAliases["myalias"] = scenario.newTarget 89 } 90 91 add1, rm1, err := snapstate.ApplyAliasesChange("alias-snap1", scenario.autoDisabled, prevAliases, scenario.newAutoDisabled, newAliases, s.fakeBackend, false) 92 c.Assert(err, IsNil) 93 94 var add, rm []*backend.Alias 95 if strings.Contains(scenario.ops, "rm") { 96 rm = []*backend.Alias{{Name: "myalias", Target: fmt.Sprintf("alias-snap1.%s", target(scenario.target))}} 97 } 98 99 if strings.Contains(scenario.ops, "add") { 100 add = []*backend.Alias{{Name: "myalias", Target: fmt.Sprintf("alias-snap1.%s", target(scenario.newTarget))}} 101 } 102 103 expected := fakeOps{ 104 { 105 op: "update-aliases", 106 rmAliases: rm, 107 aliases: add, 108 }, 109 } 110 111 // start with an easier-to-read error if this fails: 112 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops(), Commentf("%v", scenario)) 113 c.Assert(s.fakeBackend.ops, DeepEquals, expected, Commentf("%v", scenario)) 114 115 c.Check(add1, DeepEquals, add) 116 c.Check(rm1, DeepEquals, rm) 117 118 s.fakeBackend.ops = nil 119 } 120 } 121 122 func (s *snapmgrTestSuite) TestApplyAliasesChangeMulti(c *C) { 123 prevAliases := map[string]*snapstate.AliasTarget{ 124 "myalias0": {Auto: "cmd0"}, 125 } 126 newAliases := map[string]*snapstate.AliasTarget{ 127 "myalias1": {Auto: "alias-snap1"}, 128 } 129 130 _, _, err := snapstate.ApplyAliasesChange("alias-snap1", false, prevAliases, false, newAliases, s.fakeBackend, false) 131 c.Assert(err, IsNil) 132 133 expected := fakeOps{ 134 { 135 op: "update-aliases", 136 rmAliases: []*backend.Alias{{Name: "myalias0", Target: "alias-snap1.cmd0"}}, 137 aliases: []*backend.Alias{{Name: "myalias1", Target: "alias-snap1"}}, 138 }, 139 } 140 141 // start with an easier-to-read error if this fails: 142 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 143 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 144 } 145 146 func (s *snapmgrTestSuite) TestAutoAliasesDelta(c *C) { 147 snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) { 148 c.Check(info.InstanceName(), Equals, "alias-snap") 149 return map[string]string{ 150 "alias1": "cmd1", 151 "alias2": "cmd2", 152 "alias4": "cmd4", 153 "alias5": "cmd5", 154 "alias6": "cmd6b", 155 }, nil 156 } 157 158 s.state.Lock() 159 defer s.state.Unlock() 160 161 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 162 Sequence: []*snap.SideInfo{ 163 {RealName: "alias-snap", Revision: snap.R(11)}, 164 }, 165 Current: snap.R(11), 166 Active: true, 167 Aliases: map[string]*snapstate.AliasTarget{ 168 "alias1": {Manual: "cmdx", Auto: "cmd1"}, 169 "alias2": {Auto: "cmd2"}, 170 "alias3": {Auto: "cmd3"}, 171 "alias6": {Auto: "cmd6"}, 172 }, 173 }) 174 175 changed, dropped, err := snapstate.AutoAliasesDelta(s.state, []string{"alias-snap"}) 176 c.Assert(err, IsNil) 177 178 c.Check(changed, HasLen, 1) 179 which := changed["alias-snap"] 180 sort.Strings(which) 181 c.Check(which, DeepEquals, []string{"alias4", "alias5", "alias6"}) 182 183 c.Check(dropped, DeepEquals, map[string][]string{ 184 "alias-snap": {"alias3"}, 185 }) 186 } 187 188 func (s *snapmgrTestSuite) TestAutoAliasesDeltaAll(c *C) { 189 seen := make(map[string]bool) 190 snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) { 191 seen[info.InstanceName()] = true 192 if info.InstanceName() == "alias-snap" { 193 return map[string]string{ 194 "alias1": "cmd1", 195 "alias2": "cmd2", 196 "alias4": "cmd4", 197 "alias5": "cmd5", 198 }, nil 199 } 200 return nil, nil 201 } 202 203 s.state.Lock() 204 defer s.state.Unlock() 205 206 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 207 Sequence: []*snap.SideInfo{ 208 {RealName: "alias-snap", Revision: snap.R(11)}, 209 }, 210 Current: snap.R(11), 211 Active: true, 212 }) 213 snapstate.Set(s.state, "other-snap", &snapstate.SnapState{ 214 Sequence: []*snap.SideInfo{ 215 {RealName: "other-snap", Revision: snap.R(2)}, 216 }, 217 Current: snap.R(2), 218 Active: true, 219 }) 220 221 changed, dropped, err := snapstate.AutoAliasesDelta(s.state, nil) 222 c.Assert(err, IsNil) 223 224 c.Check(changed, HasLen, 1) 225 which := changed["alias-snap"] 226 sort.Strings(which) 227 c.Check(which, DeepEquals, []string{"alias1", "alias2", "alias4", "alias5"}) 228 229 c.Check(dropped, HasLen, 0) 230 231 c.Check(seen, DeepEquals, map[string]bool{ 232 "core": true, 233 "alias-snap": true, 234 "other-snap": true, 235 }) 236 } 237 238 func (s *snapmgrTestSuite) TestAutoAliasesDeltaOverManual(c *C) { 239 snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) { 240 c.Check(info.InstanceName(), Equals, "alias-snap") 241 return map[string]string{ 242 "alias1": "cmd1", 243 "alias2": "cmd2", 244 }, nil 245 } 246 247 s.state.Lock() 248 defer s.state.Unlock() 249 250 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 251 Sequence: []*snap.SideInfo{ 252 {RealName: "alias-snap", Revision: snap.R(11)}, 253 }, 254 Current: snap.R(11), 255 Active: true, 256 Aliases: map[string]*snapstate.AliasTarget{ 257 "alias1": {Manual: "manual1"}, 258 }, 259 }) 260 261 changed, dropped, err := snapstate.AutoAliasesDelta(s.state, []string{"alias-snap"}) 262 c.Assert(err, IsNil) 263 264 c.Check(changed, HasLen, 1) 265 which := changed["alias-snap"] 266 sort.Strings(which) 267 c.Check(which, DeepEquals, []string{"alias1", "alias2"}) 268 269 c.Check(dropped, HasLen, 0) 270 } 271 272 func (s *snapmgrTestSuite) TestRefreshAliases(c *C) { 273 s.state.Lock() 274 defer s.state.Unlock() 275 276 snapstate.AutoAliases = func(st *state.State, info *snap.Info) (map[string]string, error) { 277 c.Check(info.InstanceName(), Equals, "alias-snap") 278 return map[string]string{ 279 "alias1": "cmd1", 280 "alias2": "cmd2", 281 "alias4": "cmd4", 282 "alias5": "cmd5", 283 }, nil 284 } 285 286 info := snaptest.MockInfo(c, ` 287 name: alias-snap 288 version: 0 289 apps: 290 cmd1: 291 cmd2: 292 cmd3: 293 cmd4: 294 `, &snap.SideInfo{SnapID: "snap-id"}) 295 296 new, err := snapstate.RefreshAliases(s.state, info, nil) 297 c.Assert(err, IsNil) 298 c.Check(new, DeepEquals, map[string]*snapstate.AliasTarget{ 299 "alias1": {Auto: "cmd1"}, 300 "alias2": {Auto: "cmd2"}, 301 "alias4": {Auto: "cmd4"}, 302 }) 303 304 new, err = snapstate.RefreshAliases(s.state, info, map[string]*snapstate.AliasTarget{ 305 "alias1": {Auto: "cmd1old"}, 306 "alias5": {Auto: "cmd5"}, 307 "alias6": {Auto: "cmd6"}, 308 "alias4": {Manual: "cmd3", Auto: "cmd4"}, 309 "manual3": {Manual: "cmd3"}, 310 "manual7": {Manual: "cmd7"}, 311 }) 312 c.Assert(err, IsNil) 313 c.Check(new, DeepEquals, map[string]*snapstate.AliasTarget{ 314 "alias1": {Auto: "cmd1"}, 315 "alias2": {Auto: "cmd2"}, 316 "alias4": {Manual: "cmd3", Auto: "cmd4"}, 317 "manual3": {Manual: "cmd3"}, 318 }) 319 } 320 321 func (s *snapmgrTestSuite) TestCheckAliasesConflictsAgainstAliases(c *C) { 322 s.state.Lock() 323 defer s.state.Unlock() 324 325 snapstate.Set(s.state, "other-snap1", &snapstate.SnapState{ 326 Sequence: []*snap.SideInfo{ 327 {RealName: "other-snap", Revision: snap.R(2)}, 328 }, 329 Current: snap.R(2), 330 Active: true, 331 AutoAliasesDisabled: true, 332 Aliases: map[string]*snapstate.AliasTarget{ 333 "alias1": {Auto: "cmd1"}, 334 "alias2": {Auto: "cmd2"}, 335 }, 336 }) 337 338 snapstate.Set(s.state, "other-snap2", &snapstate.SnapState{ 339 Sequence: []*snap.SideInfo{ 340 {RealName: "other-snap", Revision: snap.R(2)}, 341 }, 342 Current: snap.R(2), 343 Active: true, 344 AutoAliasesDisabled: false, 345 Aliases: map[string]*snapstate.AliasTarget{ 346 "alias2": {Auto: "cmd2"}, 347 "alias3": {Auto: "cmd3"}, 348 }, 349 }) 350 351 snapst3 := snapstate.SnapState{ 352 Sequence: []*snap.SideInfo{ 353 {RealName: "other-snap", Revision: snap.R(2)}, 354 }, 355 Current: snap.R(2), 356 Active: true, 357 AutoAliasesDisabled: true, 358 Aliases: map[string]*snapstate.AliasTarget{ 359 "alias4": {Manual: "cmd8"}, 360 "alias5": {Auto: "cmd5"}, 361 }, 362 } 363 snapstate.Set(s.state, "other-snap3", &snapst3) 364 365 confl, err := snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 366 "alias1": {Auto: "cmd1"}, 367 "alias5": {Auto: "cmd5"}, 368 }, nil) 369 c.Check(err, IsNil) 370 c.Check(confl, IsNil) 371 372 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 373 "alias1": {Auto: "cmd1"}, 374 "alias2": {Auto: "cmd2"}, 375 "alias3": {Auto: "cmd3"}, 376 "alias4": {Auto: "cmd4"}, 377 }, nil) 378 c.Check(err, FitsTypeOf, &snapstate.AliasConflictError{}) 379 c.Check(confl, HasLen, 2) 380 which := confl["other-snap2"] 381 sort.Strings(which) 382 c.Check(which, DeepEquals, []string{"alias2", "alias3"}) 383 c.Check(confl["other-snap3"], DeepEquals, []string{"alias4"}) 384 385 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", true, map[string]*snapstate.AliasTarget{ 386 "alias1": {Auto: "cmd1"}, 387 "alias2": {Auto: "cmd2"}, 388 "alias3": {Auto: "cmd3"}, 389 "alias4": {Auto: "cmd4"}, 390 }, nil) 391 c.Check(err, IsNil) 392 c.Check(confl, IsNil) 393 394 confl, err = snapstate.CheckAliasesConflicts(s.state, "other-snap4", false, map[string]*snapstate.AliasTarget{ 395 "alias2": {Manual: "cmd12"}, 396 }, nil) 397 c.Check(err, FitsTypeOf, &snapstate.AliasConflictError{}) 398 c.Check(confl, HasLen, 1) 399 which = confl["other-snap2"] 400 sort.Strings(which) 401 c.Check(which, DeepEquals, []string{"alias2"}) 402 403 snapst3En := snapst3 404 snapst3En.AutoAliasesDisabled = false 405 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 406 "alias1": {Auto: "cmd1"}, 407 "alias5": {Auto: "cmd5"}, 408 }, map[string]*snapstate.SnapState{ 409 "other-snap3": &snapst3En, 410 }) 411 c.Check(err, FitsTypeOf, &snapstate.AliasConflictError{}) 412 c.Check(confl, HasLen, 1) 413 which = confl["other-snap3"] 414 sort.Strings(which) 415 c.Check(which, DeepEquals, []string{"alias5"}) 416 } 417 418 func (s *snapmgrTestSuite) TestAliasConflictError(c *C) { 419 e := &snapstate.AliasConflictError{Snap: "foo", Conflicts: map[string][]string{ 420 "bar": {"baz"}, 421 }} 422 c.Check(e, ErrorMatches, `cannot enable alias "baz" for "foo", already enabled for "bar"`) 423 424 e = &snapstate.AliasConflictError{Snap: "foo", Conflicts: map[string][]string{ 425 "bar": {"baz1", "baz2"}, 426 }} 427 c.Check(e, ErrorMatches, `cannot enable aliases "baz1", "baz2" for "foo", already enabled for "bar"`) 428 429 e = &snapstate.AliasConflictError{Snap: "foo", Conflicts: map[string][]string{ 430 "bar1": {"baz1"}, 431 "bar2": {"baz2"}, 432 }} 433 c.Check(e, ErrorMatches, `cannot enable alias "baz." for "foo", already enabled for "bar." nor alias "baz." already enabled for "bar."`) 434 } 435 436 func (s *snapmgrTestSuite) TestCheckAliasesConflictsAgainstSnaps(c *C) { 437 s.state.Lock() 438 defer s.state.Unlock() 439 440 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 441 Active: true, 442 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 443 Current: snap.R(7), 444 SnapType: "app", 445 }) 446 447 confl, err := snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 448 "alias1": {Auto: "cmd1"}, 449 }, nil) 450 c.Check(err, IsNil) 451 c.Check(confl, IsNil) 452 453 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 454 "alias1": {Auto: "cmd1"}, 455 "some-snap": {Auto: "cmd1"}, 456 }, nil) 457 c.Check(err, ErrorMatches, `cannot enable alias "some-snap" for "alias-snap", it conflicts with the command namespace of installed snap "some-snap"`) 458 c.Check(confl, IsNil) 459 460 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", true, map[string]*snapstate.AliasTarget{ 461 "alias1": {Auto: "cmd1"}, 462 "some-snap": {Auto: "cmd1"}, 463 }, nil) 464 c.Check(err, IsNil) 465 c.Check(confl, IsNil) 466 467 confl, err = snapstate.CheckAliasesConflicts(s.state, "alias-snap", false, map[string]*snapstate.AliasTarget{ 468 "alias1": {Auto: "cmd1"}, 469 "some-snap.foo": {Auto: "cmd1"}, 470 }, nil) 471 c.Check(err, ErrorMatches, `cannot enable alias "some-snap.foo" for "alias-snap", it conflicts with the command namespace of installed snap "some-snap"`) 472 c.Check(confl, IsNil) 473 } 474 475 func (s *snapmgrTestSuite) TestDisableAliases(c *C) { 476 aliases := map[string]*snapstate.AliasTarget{ 477 "alias1": {Auto: "cmd1"}, 478 "alias2": {Auto: "cmd2"}, 479 "alias3": {Manual: "manual3", Auto: "cmd3"}, 480 "alias4": {Manual: "manual4"}, 481 } 482 483 dis, manuals := snapstate.DisableAliases(aliases) 484 c.Check(dis, DeepEquals, map[string]*snapstate.AliasTarget{ 485 "alias1": {Auto: "cmd1"}, 486 "alias2": {Auto: "cmd2"}, 487 "alias3": {Auto: "cmd3"}, 488 }) 489 c.Check(manuals, DeepEquals, map[string]string{ 490 "alias3": "manual3", 491 "alias4": "manual4", 492 }) 493 494 aliases = map[string]*snapstate.AliasTarget{ 495 "alias1": {Auto: "cmd1"}, 496 "alias2": {Auto: "cmd2"}, 497 } 498 dis, manuals = snapstate.DisableAliases(aliases) 499 c.Check(dis, DeepEquals, map[string]*snapstate.AliasTarget{ 500 "alias1": {Auto: "cmd1"}, 501 "alias2": {Auto: "cmd2"}, 502 }) 503 c.Check(manuals, DeepEquals, map[string]string(nil)) 504 } 505 506 func (s *snapmgrTestSuite) TestAliasTasks(c *C) { 507 s.state.Lock() 508 defer s.state.Unlock() 509 510 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 511 Sequence: []*snap.SideInfo{ 512 {RealName: "some-snap", Revision: snap.R(11)}, 513 }, 514 Current: snap.R(11), 515 Active: true, 516 }) 517 snapstate.Set(s.state, "some-snap_instance", &snapstate.SnapState{ 518 Sequence: []*snap.SideInfo{ 519 {RealName: "some-snap", Revision: snap.R(11)}, 520 }, 521 Current: snap.R(11), 522 Active: true, 523 InstanceKey: "instance", 524 }) 525 526 ts, err := snapstate.Alias(s.state, "some-snap", "cmd1", "alias1") 527 c.Assert(err, IsNil) 528 529 c.Assert(s.state.TaskCount(), Equals, len(ts.Tasks())) 530 c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ 531 "alias", 532 }) 533 534 ts, err = snapstate.Alias(s.state, "some-snap_instance", "cmd1", "alias1") 535 c.Assert(err, IsNil) 536 537 c.Assert(s.state.TaskCount(), Equals, 2) 538 c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ 539 "alias", 540 }) 541 542 var snapsup snapstate.SnapSetup 543 tasks := ts.Tasks() 544 c.Assert(tasks, HasLen, 1) 545 err = tasks[0].Get("snap-setup", &snapsup) 546 c.Assert(err, IsNil) 547 c.Check(snapsup.InstanceKey, Equals, "instance") 548 c.Check(snapsup.InstanceName(), Equals, "some-snap_instance") 549 } 550 551 type changedAlias struct { 552 Snap string `json:"snap"` 553 App string `json:"app"` 554 Alias string `json:"alias"` 555 } 556 557 type traceData struct { 558 Added []*changedAlias `json:"aliases-added,omitempty"` 559 Removed []*changedAlias `json:"aliases-removed,omitempty"` 560 } 561 562 func (s *snapmgrTestSuite) TestAliasRunThrough(c *C) { 563 s.state.Lock() 564 defer s.state.Unlock() 565 566 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 567 Sequence: []*snap.SideInfo{ 568 {RealName: "alias-snap", Revision: snap.R(11)}, 569 }, 570 Current: snap.R(11), 571 Active: true, 572 }) 573 574 chg := s.state.NewChange("alias", "manual alias") 575 ts, err := snapstate.Alias(s.state, "alias-snap", "cmd1", "alias1") 576 c.Assert(err, IsNil) 577 chg.AddAll(ts) 578 579 s.state.Unlock() 580 defer s.se.Stop() 581 s.settle(c) 582 s.state.Lock() 583 584 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 585 expected := fakeOps{ 586 { 587 op: "update-aliases", 588 aliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd1"}}, 589 }, 590 } 591 // start with an easier-to-read error if this fails: 592 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 593 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 594 595 var snapst snapstate.SnapState 596 err = snapstate.Get(s.state, "alias-snap", &snapst) 597 c.Assert(err, IsNil) 598 599 c.Check(snapst.AutoAliasesDisabled, Equals, false) 600 c.Check(snapst.AliasesPending, Equals, false) 601 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 602 "alias1": {Manual: "cmd1"}, 603 }) 604 605 var trace traceData 606 err = chg.Get("api-data", &trace) 607 c.Assert(err, IsNil) 608 c.Check(trace, DeepEquals, traceData{ 609 Added: []*changedAlias{{Snap: "alias-snap", App: "cmd1", Alias: "alias1"}}, 610 }) 611 } 612 613 func (s *snapmgrTestSuite) TestParallelInstanceAliasRunThrough(c *C) { 614 s.state.Lock() 615 defer s.state.Unlock() 616 617 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 618 Sequence: []*snap.SideInfo{ 619 {RealName: "alias-snap", Revision: snap.R(11)}, 620 }, 621 Current: snap.R(11), 622 Active: true, 623 }) 624 snapstate.Set(s.state, "alias-snap_foo", &snapstate.SnapState{ 625 Sequence: []*snap.SideInfo{ 626 {RealName: "alias-snap", Revision: snap.R(11)}, 627 }, 628 Current: snap.R(11), 629 Active: true, 630 InstanceKey: "foo", 631 }) 632 633 chg := s.state.NewChange("alias", "manual alias") 634 ts, err := snapstate.Alias(s.state, "alias-snap_foo", "cmd1", "alias1") 635 c.Assert(err, IsNil) 636 chg.AddAll(ts) 637 638 s.state.Unlock() 639 defer s.se.Stop() 640 s.settle(c) 641 s.state.Lock() 642 643 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 644 expected := fakeOps{ 645 { 646 op: "update-aliases", 647 aliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap_foo.cmd1"}}, 648 }, 649 } 650 // start with an easier-to-read error if this fails: 651 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 652 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 653 654 var snapst snapstate.SnapState 655 err = snapstate.Get(s.state, "alias-snap_foo", &snapst) 656 c.Assert(err, IsNil) 657 658 c.Check(snapst.AutoAliasesDisabled, Equals, false) 659 c.Check(snapst.AliasesPending, Equals, false) 660 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 661 "alias1": {Manual: "cmd1"}, 662 }) 663 664 // snap without instance key is unchanged 665 err = snapstate.Get(s.state, "alias-snap", &snapst) 666 c.Assert(err, IsNil) 667 c.Check(snapst.Aliases, HasLen, 0) 668 669 var trace traceData 670 err = chg.Get("api-data", &trace) 671 c.Assert(err, IsNil) 672 c.Check(trace, DeepEquals, traceData{ 673 Added: []*changedAlias{{Snap: "alias-snap_foo", App: "cmd1", Alias: "alias1"}}, 674 }) 675 } 676 677 func (s *snapmgrTestSuite) TestAliasNoTarget(c *C) { 678 s.state.Lock() 679 defer s.state.Unlock() 680 681 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 682 Sequence: []*snap.SideInfo{ 683 {RealName: "some-snap", Revision: snap.R(11)}, 684 }, 685 Current: snap.R(11), 686 Active: true, 687 }) 688 689 chg := s.state.NewChange("alias", "manual alias") 690 ts, err := snapstate.Alias(s.state, "some-snap", "cmdno", "alias1") 691 c.Assert(err, IsNil) 692 chg.AddAll(ts) 693 694 s.state.Unlock() 695 s.se.Ensure() 696 s.se.Wait() 697 s.state.Lock() 698 699 c.Check(chg.Status(), Equals, state.ErrorStatus) 700 c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "some-snap", target application "cmdno" does not exist.*`) 701 } 702 703 func (s *snapmgrTestSuite) TestAliasTargetIsDaemon(c *C) { 704 s.state.Lock() 705 defer s.state.Unlock() 706 707 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 708 Sequence: []*snap.SideInfo{ 709 {RealName: "alias-snap", Revision: snap.R(11)}, 710 }, 711 Current: snap.R(11), 712 Active: true, 713 }) 714 715 chg := s.state.NewChange("alias", "manual alias") 716 ts, err := snapstate.Alias(s.state, "alias-snap", "cmddaemon", "alias1") 717 c.Assert(err, IsNil) 718 chg.AddAll(ts) 719 720 s.state.Unlock() 721 s.se.Ensure() 722 s.se.Wait() 723 s.state.Lock() 724 725 c.Check(chg.Status(), Equals, state.ErrorStatus) 726 c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "alias-snap", target application "cmddaemon" is a daemon.*`) 727 } 728 729 func (s *snapmgrTestSuite) TestAliasInvalidAlias(c *C) { 730 s.state.Lock() 731 defer s.state.Unlock() 732 733 _, err := snapstate.Alias(s.state, "some-snap", "cmd", ".alias") 734 c.Assert(err, ErrorMatches, `invalid alias name: ".alias"`) 735 } 736 737 func (s *snapmgrTestSuite) TestAliasOverAutoRunThrough(c *C) { 738 s.state.Lock() 739 defer s.state.Unlock() 740 741 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 742 Sequence: []*snap.SideInfo{ 743 {RealName: "alias-snap", Revision: snap.R(11)}, 744 }, 745 Current: snap.R(11), 746 Active: true, 747 Aliases: map[string]*snapstate.AliasTarget{ 748 "alias1": {Auto: "cmd1"}, 749 "alias2": {Auto: "cmd2"}, 750 }, 751 }) 752 753 chg := s.state.NewChange("alias", "manual alias") 754 ts, err := snapstate.Alias(s.state, "alias-snap", "cmd5", "alias1") 755 c.Assert(err, IsNil) 756 chg.AddAll(ts) 757 758 s.state.Unlock() 759 defer s.se.Stop() 760 s.settle(c) 761 s.state.Lock() 762 763 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 764 expected := fakeOps{ 765 { 766 op: "update-aliases", 767 rmAliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd1"}}, 768 aliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd5"}}, 769 }, 770 } 771 // start with an easier-to-read error if this fails: 772 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 773 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 774 775 var snapst snapstate.SnapState 776 err = snapstate.Get(s.state, "alias-snap", &snapst) 777 c.Assert(err, IsNil) 778 779 c.Check(snapst.AutoAliasesDisabled, Equals, false) 780 c.Check(snapst.AliasesPending, Equals, false) 781 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 782 "alias1": {Manual: "cmd5", Auto: "cmd1"}, 783 "alias2": {Auto: "cmd2"}, 784 }) 785 } 786 787 func (s *snapmgrTestSuite) TestAliasUpdateChangeConflict(c *C) { 788 s.state.Lock() 789 defer s.state.Unlock() 790 791 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 792 Active: true, 793 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 794 Current: snap.R(7), 795 SnapType: "app", 796 }) 797 798 ts, err := snapstate.Alias(s.state, "some-snap", "cmd1", "alias1") 799 c.Assert(err, IsNil) 800 // need a change to make the tasks visible 801 s.state.NewChange("alias", "...").AddAll(ts) 802 803 _, err = snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 804 c.Assert(err, ErrorMatches, `snap "some-snap" has "alias" change in progress`) 805 } 806 807 func (s *snapmgrTestSuite) TestUpdateAliasChangeConflict(c *C) { 808 s.state.Lock() 809 defer s.state.Unlock() 810 811 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 812 Active: true, 813 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 814 Current: snap.R(7), 815 SnapType: "app", 816 }) 817 818 ts, err := snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 819 c.Assert(err, IsNil) 820 // need a change to make the tasks visible 821 s.state.NewChange("update", "...").AddAll(ts) 822 823 _, err = snapstate.Alias(s.state, "some-snap", "cmd1", "alias1") 824 c.Assert(err, ErrorMatches, `snap "some-snap" has "update" change in progress`) 825 } 826 827 func (s *snapmgrTestSuite) TestAliasAliasConflict(c *C) { 828 s.state.Lock() 829 defer s.state.Unlock() 830 831 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 832 Sequence: []*snap.SideInfo{ 833 {RealName: "alias-snap", Revision: snap.R(11)}, 834 }, 835 Current: snap.R(11), 836 Active: true, 837 }) 838 snapstate.Set(s.state, "other-snap", &snapstate.SnapState{ 839 Sequence: []*snap.SideInfo{ 840 {RealName: "other-snap", Revision: snap.R(2)}, 841 }, 842 Current: snap.R(2), 843 Active: true, 844 Aliases: map[string]*snapstate.AliasTarget{ 845 "alias1": {Auto: "cmd1"}, 846 }, 847 }) 848 849 chg := s.state.NewChange("alias", "alias") 850 ts, err := snapstate.Alias(s.state, "alias-snap", "cmd5", "alias1") 851 c.Assert(err, IsNil) 852 chg.AddAll(ts) 853 854 s.state.Unlock() 855 s.se.Ensure() 856 s.se.Wait() 857 s.state.Lock() 858 859 c.Check(chg.Status(), Equals, state.ErrorStatus) 860 c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "alias-snap", already enabled for "other-snap".*`) 861 } 862 863 func (s *snapmgrTestSuite) TestParallelInstanceAliasConflict(c *C) { 864 s.state.Lock() 865 defer s.state.Unlock() 866 867 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 868 Sequence: []*snap.SideInfo{ 869 {RealName: "alias-snap", Revision: snap.R(11)}, 870 }, 871 Current: snap.R(11), 872 Active: true, 873 Aliases: map[string]*snapstate.AliasTarget{ 874 "alias2": {Auto: "cmd2"}, 875 }, 876 }) 877 snapstate.Set(s.state, "alias-snap_foo", &snapstate.SnapState{ 878 Sequence: []*snap.SideInfo{ 879 {RealName: "alias-snap", Revision: snap.R(11)}, 880 }, 881 Current: snap.R(11), 882 Active: true, 883 InstanceKey: "foo", 884 Aliases: map[string]*snapstate.AliasTarget{ 885 "alias1": {Auto: "cmd1"}, 886 }, 887 }) 888 889 chg := s.state.NewChange("alias", "alias") 890 // conflicts with aliases of alias-snap_foo 891 ts, err := snapstate.Alias(s.state, "alias-snap", "cmd5", "alias1") 892 c.Assert(err, IsNil) 893 chg.AddAll(ts) 894 895 s.state.Unlock() 896 s.se.Ensure() 897 s.se.Wait() 898 s.state.Lock() 899 900 c.Check(chg.Status(), Equals, state.ErrorStatus) 901 c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias1" for "alias-snap", already enabled for "alias-snap_foo".*`) 902 903 chg = s.state.NewChange("alias", "alias") 904 // conflicts with aliases of alias-snap 905 ts, err = snapstate.Alias(s.state, "alias-snap_foo", "cmd5", "alias2") 906 c.Assert(err, IsNil) 907 chg.AddAll(ts) 908 909 s.state.Unlock() 910 s.se.Ensure() 911 s.se.Wait() 912 s.state.Lock() 913 914 c.Check(chg.Status(), Equals, state.ErrorStatus) 915 c.Check(chg.Err(), ErrorMatches, `(?s).*cannot enable alias "alias2" for "alias-snap_foo", already enabled for "alias-snap".*`) 916 } 917 918 func (s *snapmgrTestSuite) TestDisableAllAliasesTasks(c *C) { 919 s.state.Lock() 920 defer s.state.Unlock() 921 922 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 923 Sequence: []*snap.SideInfo{ 924 {RealName: "some-snap", Revision: snap.R(11)}, 925 }, 926 Current: snap.R(11), 927 Active: true, 928 }) 929 930 ts, err := snapstate.DisableAllAliases(s.state, "some-snap") 931 c.Assert(err, IsNil) 932 933 c.Assert(s.state.TaskCount(), Equals, len(ts.Tasks())) 934 c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ 935 "disable-aliases", 936 }) 937 } 938 939 func (s *snapmgrTestSuite) TestDisableAllAliasesRunThrough(c *C) { 940 s.state.Lock() 941 defer s.state.Unlock() 942 943 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 944 Sequence: []*snap.SideInfo{ 945 {RealName: "alias-snap", Revision: snap.R(11)}, 946 }, 947 Current: snap.R(11), 948 Active: true, 949 Aliases: map[string]*snapstate.AliasTarget{ 950 "alias1": {Manual: "cmd5", Auto: "cmd1"}, 951 "alias2": {Auto: "cmd2"}, 952 "alias3": {Manual: "cmd3"}, 953 }, 954 }) 955 956 chg := s.state.NewChange("unalias", "unalias") 957 ts, err := snapstate.DisableAllAliases(s.state, "alias-snap") 958 c.Assert(err, IsNil) 959 chg.AddAll(ts) 960 961 s.state.Unlock() 962 defer s.se.Stop() 963 s.settle(c) 964 s.state.Lock() 965 966 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 967 expected := fakeOps{ 968 { 969 op: "update-aliases", 970 rmAliases: []*backend.Alias{ 971 {Name: "alias1", Target: "alias-snap.cmd5"}, 972 {Name: "alias2", Target: "alias-snap.cmd2"}, 973 {Name: "alias3", Target: "alias-snap.cmd3"}, 974 }, 975 }, 976 } 977 // start with an easier-to-read error if this fails: 978 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 979 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 980 981 var snapst snapstate.SnapState 982 err = snapstate.Get(s.state, "alias-snap", &snapst) 983 c.Assert(err, IsNil) 984 985 c.Check(snapst.AutoAliasesDisabled, Equals, true) 986 c.Check(snapst.AliasesPending, Equals, false) 987 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 988 "alias1": {Auto: "cmd1"}, 989 "alias2": {Auto: "cmd2"}, 990 }) 991 992 var trace traceData 993 err = chg.Get("api-data", &trace) 994 c.Assert(err, IsNil) 995 c.Check(trace.Added, HasLen, 0) 996 c.Check(trace.Removed, HasLen, 3) 997 } 998 999 func (s *snapmgrTestSuite) TestParallelInstanceDisableAllAliasesRunThrough(c *C) { 1000 s.state.Lock() 1001 defer s.state.Unlock() 1002 1003 snapstate.Set(s.state, "alias-snap_instance", &snapstate.SnapState{ 1004 Sequence: []*snap.SideInfo{ 1005 {RealName: "alias-snap", Revision: snap.R(11)}, 1006 }, 1007 Current: snap.R(11), 1008 Active: true, 1009 Aliases: map[string]*snapstate.AliasTarget{ 1010 "alias1": {Auto: "cmd1"}, 1011 "alias2": {Auto: "cmd2"}, 1012 "alias3": {Manual: "cmd3"}, 1013 }, 1014 InstanceKey: "instance", 1015 }) 1016 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1017 Sequence: []*snap.SideInfo{ 1018 {RealName: "alias-snap", Revision: snap.R(11)}, 1019 }, 1020 Current: snap.R(11), 1021 Active: true, 1022 Aliases: map[string]*snapstate.AliasTarget{ 1023 "alias1": {Manual: "cmd6"}, 1024 "alias2": {Manual: "cmd7"}, 1025 }, 1026 }) 1027 1028 chg := s.state.NewChange("unalias", "unalias") 1029 ts, err := snapstate.DisableAllAliases(s.state, "alias-snap_instance") 1030 c.Assert(err, IsNil) 1031 chg.AddAll(ts) 1032 1033 s.state.Unlock() 1034 defer s.se.Stop() 1035 s.settle(c) 1036 s.state.Lock() 1037 1038 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1039 expected := fakeOps{ 1040 { 1041 op: "update-aliases", 1042 rmAliases: []*backend.Alias{ 1043 {Name: "alias1", Target: "alias-snap_instance.cmd1"}, 1044 {Name: "alias2", Target: "alias-snap_instance.cmd2"}, 1045 {Name: "alias3", Target: "alias-snap_instance.cmd3"}, 1046 }, 1047 }, 1048 } 1049 // start with an easier-to-read error if this fails: 1050 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1051 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1052 1053 var snapst snapstate.SnapState 1054 err = snapstate.Get(s.state, "alias-snap_instance", &snapst) 1055 c.Assert(err, IsNil) 1056 1057 c.Check(snapst.AutoAliasesDisabled, Equals, true) 1058 c.Check(snapst.AliasesPending, Equals, false) 1059 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1060 "alias1": {Auto: "cmd1"}, 1061 "alias2": {Auto: "cmd2"}, 1062 }) 1063 1064 var trace traceData 1065 err = chg.Get("api-data", &trace) 1066 c.Assert(err, IsNil) 1067 c.Check(trace.Added, HasLen, 0) 1068 c.Check(trace.Removed, HasLen, 3) 1069 1070 // non _instance instance is unchanged 1071 err = snapstate.Get(s.state, "alias-snap", &snapst) 1072 c.Assert(err, IsNil) 1073 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1074 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1075 "alias1": {Manual: "cmd6"}, 1076 "alias2": {Manual: "cmd7"}, 1077 }) 1078 } 1079 1080 func (s *snapmgrTestSuite) TestRemoveManualAliasTasks(c *C) { 1081 s.state.Lock() 1082 defer s.state.Unlock() 1083 1084 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1085 Sequence: []*snap.SideInfo{ 1086 {RealName: "alias-snap", Revision: snap.R(11)}, 1087 }, 1088 Current: snap.R(11), 1089 Active: true, 1090 Aliases: map[string]*snapstate.AliasTarget{ 1091 "alias1": {Manual: "cmd5"}, 1092 }, 1093 }) 1094 1095 ts, snapName, err := snapstate.RemoveManualAlias(s.state, "alias1") 1096 c.Assert(err, IsNil) 1097 c.Check(snapName, Equals, "alias-snap") 1098 1099 c.Assert(s.state.TaskCount(), Equals, len(ts.Tasks())) 1100 c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ 1101 "unalias", 1102 }) 1103 task := ts.Tasks()[0] 1104 var alias string 1105 err = task.Get("alias", &alias) 1106 c.Assert(err, IsNil) 1107 c.Check(alias, Equals, "alias1") 1108 } 1109 1110 func (s *snapmgrTestSuite) TestRemoveManualAliasRunThrough(c *C) { 1111 s.state.Lock() 1112 defer s.state.Unlock() 1113 1114 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1115 Sequence: []*snap.SideInfo{ 1116 {RealName: "alias-snap", Revision: snap.R(11)}, 1117 }, 1118 Current: snap.R(11), 1119 Active: true, 1120 Aliases: map[string]*snapstate.AliasTarget{ 1121 "alias1": {Manual: "cmd5"}, 1122 }, 1123 }) 1124 1125 chg := s.state.NewChange("alias", "manual alias") 1126 ts, _, err := snapstate.RemoveManualAlias(s.state, "alias1") 1127 c.Assert(err, IsNil) 1128 chg.AddAll(ts) 1129 1130 s.state.Unlock() 1131 defer s.se.Stop() 1132 s.settle(c) 1133 s.state.Lock() 1134 1135 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1136 expected := fakeOps{ 1137 { 1138 op: "update-aliases", 1139 rmAliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd5"}}, 1140 }, 1141 } 1142 // start with an easier-to-read error if this fails: 1143 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1144 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1145 1146 var snapst snapstate.SnapState 1147 err = snapstate.Get(s.state, "alias-snap", &snapst) 1148 c.Assert(err, IsNil) 1149 1150 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1151 c.Check(snapst.AliasesPending, Equals, false) 1152 c.Check(snapst.Aliases, HasLen, 0) 1153 1154 var trace traceData 1155 err = chg.Get("api-data", &trace) 1156 c.Assert(err, IsNil) 1157 c.Check(trace, DeepEquals, traceData{ 1158 Removed: []*changedAlias{{Snap: "alias-snap", App: "cmd5", Alias: "alias1"}}, 1159 }) 1160 } 1161 1162 func (s *snapmgrTestSuite) TestRemoveManualAliasOverAutoRunThrough(c *C) { 1163 s.state.Lock() 1164 defer s.state.Unlock() 1165 1166 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1167 Sequence: []*snap.SideInfo{ 1168 {RealName: "alias-snap", Revision: snap.R(11)}, 1169 }, 1170 Current: snap.R(11), 1171 Active: true, 1172 Aliases: map[string]*snapstate.AliasTarget{ 1173 "alias1": {Manual: "cmd5", Auto: "cmd1"}, 1174 }, 1175 }) 1176 1177 chg := s.state.NewChange("alias", "manual alias") 1178 ts, _, err := snapstate.RemoveManualAlias(s.state, "alias1") 1179 c.Assert(err, IsNil) 1180 chg.AddAll(ts) 1181 1182 s.state.Unlock() 1183 defer s.se.Stop() 1184 s.settle(c) 1185 s.state.Lock() 1186 1187 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1188 expected := fakeOps{ 1189 { 1190 op: "update-aliases", 1191 rmAliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd5"}}, 1192 aliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap.cmd1"}}, 1193 }, 1194 } 1195 // start with an easier-to-read error if this fails: 1196 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1197 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1198 1199 var snapst snapstate.SnapState 1200 err = snapstate.Get(s.state, "alias-snap", &snapst) 1201 c.Assert(err, IsNil) 1202 1203 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1204 c.Check(snapst.AliasesPending, Equals, false) 1205 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1206 "alias1": {Auto: "cmd1"}, 1207 }) 1208 } 1209 1210 func (s *snapmgrTestSuite) TestParallelInstanceRemoveManualAliasRunThrough(c *C) { 1211 s.state.Lock() 1212 defer s.state.Unlock() 1213 1214 snapstate.Set(s.state, "alias-snap_instance", &snapstate.SnapState{ 1215 Sequence: []*snap.SideInfo{ 1216 {RealName: "alias-snap", Revision: snap.R(11)}, 1217 }, 1218 Current: snap.R(11), 1219 Active: true, 1220 Aliases: map[string]*snapstate.AliasTarget{ 1221 "alias1": {Manual: "cmd2", Auto: "cmd1"}, 1222 }, 1223 InstanceKey: "instance", 1224 }) 1225 1226 chg := s.state.NewChange("alias", "manual alias") 1227 ts, _, err := snapstate.RemoveManualAlias(s.state, "alias1") 1228 c.Assert(err, IsNil) 1229 chg.AddAll(ts) 1230 1231 s.state.Unlock() 1232 defer s.se.Stop() 1233 s.settle(c) 1234 s.state.Lock() 1235 1236 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1237 expected := fakeOps{ 1238 { 1239 op: "update-aliases", 1240 rmAliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap_instance.cmd2"}}, 1241 aliases: []*backend.Alias{{Name: "alias1", Target: "alias-snap_instance.cmd1"}}, 1242 }, 1243 } 1244 // start with an easier-to-read error if this fails: 1245 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1246 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1247 1248 var snapst snapstate.SnapState 1249 err = snapstate.Get(s.state, "alias-snap_instance", &snapst) 1250 c.Assert(err, IsNil) 1251 1252 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1253 c.Check(snapst.AliasesPending, Equals, false) 1254 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1255 "alias1": {Auto: "cmd1"}, 1256 }) 1257 } 1258 1259 func (s *snapmgrTestSuite) TestRemoveManualAliasNoAlias(c *C) { 1260 s.state.Lock() 1261 defer s.state.Unlock() 1262 1263 _, _, err := snapstate.RemoveManualAlias(s.state, "alias1") 1264 c.Assert(err, ErrorMatches, `cannot find manual alias "alias1" in any snap`) 1265 } 1266 1267 func (s *snapmgrTestSuite) TestUpdateDisableAllAliasesChangeConflict(c *C) { 1268 s.state.Lock() 1269 defer s.state.Unlock() 1270 1271 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1272 Active: true, 1273 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1274 Current: snap.R(7), 1275 SnapType: "app", 1276 Aliases: map[string]*snapstate.AliasTarget{ 1277 "alias1": {Manual: "cmd5"}, 1278 }, 1279 }) 1280 1281 ts, err := snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1282 c.Assert(err, IsNil) 1283 // need a change to make the tasks visible 1284 s.state.NewChange("update", "...").AddAll(ts) 1285 1286 _, err = snapstate.DisableAllAliases(s.state, "some-snap") 1287 c.Assert(err, ErrorMatches, `snap "some-snap" has "update" change in progress`) 1288 } 1289 1290 func (s *snapmgrTestSuite) TestUpdateRemoveManualAliasChangeConflict(c *C) { 1291 s.state.Lock() 1292 defer s.state.Unlock() 1293 1294 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1295 Active: true, 1296 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1297 Current: snap.R(7), 1298 SnapType: "app", 1299 Aliases: map[string]*snapstate.AliasTarget{ 1300 "alias1": {Manual: "cmd5"}, 1301 }, 1302 }) 1303 1304 ts, err := snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1305 c.Assert(err, IsNil) 1306 // need a change to make the tasks visible 1307 s.state.NewChange("update", "...").AddAll(ts) 1308 1309 _, _, err = snapstate.RemoveManualAlias(s.state, "alias1") 1310 c.Assert(err, ErrorMatches, `snap "some-snap" has "update" change in progress`) 1311 } 1312 1313 func (s *snapmgrTestSuite) TestDisableAllAliasesUpdateChangeConflict(c *C) { 1314 s.state.Lock() 1315 defer s.state.Unlock() 1316 1317 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1318 Active: true, 1319 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1320 Current: snap.R(7), 1321 SnapType: "app", 1322 }) 1323 1324 ts, err := snapstate.DisableAllAliases(s.state, "some-snap") 1325 c.Assert(err, IsNil) 1326 // need a change to make the tasks visible 1327 s.state.NewChange("alias", "...").AddAll(ts) 1328 1329 _, err = snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1330 c.Assert(err, ErrorMatches, `snap "some-snap" has "alias" change in progress`) 1331 } 1332 1333 func (s *snapmgrTestSuite) TestRemoveManualAliasUpdateChangeConflict(c *C) { 1334 s.state.Lock() 1335 defer s.state.Unlock() 1336 1337 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1338 Active: true, 1339 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1340 Current: snap.R(7), 1341 SnapType: "app", 1342 Aliases: map[string]*snapstate.AliasTarget{ 1343 "alias1": {Manual: "cmd5"}, 1344 }, 1345 }) 1346 1347 ts, _, err := snapstate.RemoveManualAlias(s.state, "alias1") 1348 c.Assert(err, IsNil) 1349 // need a change to make the tasks visible 1350 s.state.NewChange("unalias", "...").AddAll(ts) 1351 1352 _, err = snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1353 c.Assert(err, ErrorMatches, `snap "some-snap" has "unalias" change in progress`) 1354 } 1355 1356 func (s *snapmgrTestSuite) TestPreferTasks(c *C) { 1357 s.state.Lock() 1358 defer s.state.Unlock() 1359 1360 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1361 Sequence: []*snap.SideInfo{ 1362 {RealName: "some-snap", Revision: snap.R(11)}, 1363 }, 1364 Current: snap.R(11), 1365 Active: true, 1366 }) 1367 1368 ts, err := snapstate.Prefer(s.state, "some-snap") 1369 c.Assert(err, IsNil) 1370 1371 c.Assert(s.state.TaskCount(), Equals, len(ts.Tasks())) 1372 c.Assert(taskKinds(ts.Tasks()), DeepEquals, []string{ 1373 "prefer-aliases", 1374 }) 1375 } 1376 1377 func (s *snapmgrTestSuite) TestPreferRunThrough(c *C) { 1378 s.state.Lock() 1379 defer s.state.Unlock() 1380 1381 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1382 Sequence: []*snap.SideInfo{ 1383 {RealName: "alias-snap", Revision: snap.R(11)}, 1384 }, 1385 Current: snap.R(11), 1386 Active: true, 1387 AutoAliasesDisabled: true, 1388 Aliases: map[string]*snapstate.AliasTarget{ 1389 "alias1": {Auto: "cmd1"}, 1390 "alias2": {Auto: "cmd2"}, 1391 }, 1392 }) 1393 1394 chg := s.state.NewChange("prefer", "prefer") 1395 ts, err := snapstate.Prefer(s.state, "alias-snap") 1396 c.Assert(err, IsNil) 1397 chg.AddAll(ts) 1398 1399 s.state.Unlock() 1400 defer s.se.Stop() 1401 s.settle(c) 1402 s.state.Lock() 1403 1404 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1405 expected := fakeOps{ 1406 { 1407 op: "update-aliases", 1408 aliases: []*backend.Alias{ 1409 {Name: "alias1", Target: "alias-snap.cmd1"}, 1410 {Name: "alias2", Target: "alias-snap.cmd2"}, 1411 }, 1412 }, 1413 } 1414 // start with an easier-to-read error if this fails: 1415 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1416 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1417 1418 var snapst snapstate.SnapState 1419 err = snapstate.Get(s.state, "alias-snap", &snapst) 1420 c.Assert(err, IsNil) 1421 1422 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1423 c.Check(snapst.AliasesPending, Equals, false) 1424 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1425 "alias1": {Auto: "cmd1"}, 1426 "alias2": {Auto: "cmd2"}, 1427 }) 1428 } 1429 1430 func (s *snapmgrTestSuite) TestParallelInstancePreferRunThrough(c *C) { 1431 s.state.Lock() 1432 defer s.state.Unlock() 1433 1434 snapstate.Set(s.state, "alias-snap", &snapstate.SnapState{ 1435 Sequence: []*snap.SideInfo{ 1436 {RealName: "alias-snap", Revision: snap.R(11)}, 1437 }, 1438 Current: snap.R(11), 1439 Active: true, 1440 Aliases: map[string]*snapstate.AliasTarget{ 1441 "alias1": {Auto: "cmd1"}, 1442 "alias2": {Auto: "cmd2"}, 1443 }, 1444 }) 1445 snapstate.Set(s.state, "alias-snap_instance", &snapstate.SnapState{ 1446 Sequence: []*snap.SideInfo{ 1447 {RealName: "alias-snap", Revision: snap.R(11)}, 1448 }, 1449 Current: snap.R(11), 1450 Active: true, 1451 AutoAliasesDisabled: true, 1452 Aliases: map[string]*snapstate.AliasTarget{ 1453 "alias1": {Auto: "cmd1"}, 1454 "alias2": {Auto: "cmd2"}, 1455 }, 1456 }) 1457 1458 chg := s.state.NewChange("prefer", "prefer") 1459 ts, err := snapstate.Prefer(s.state, "alias-snap_instance") 1460 c.Assert(err, IsNil) 1461 chg.AddAll(ts) 1462 1463 s.state.Unlock() 1464 defer s.se.Stop() 1465 s.settle(c) 1466 s.state.Lock() 1467 1468 c.Assert(chg.Status(), Equals, state.DoneStatus, Commentf("%v", chg.Err())) 1469 expected := fakeOps{ 1470 { 1471 op: "update-aliases", 1472 rmAliases: []*backend.Alias{ 1473 {Name: "alias1", Target: "alias-snap.cmd1"}, 1474 {Name: "alias2", Target: "alias-snap.cmd2"}, 1475 }, 1476 }, 1477 { 1478 op: "update-aliases", 1479 aliases: []*backend.Alias{ 1480 {Name: "alias1", Target: "alias-snap_instance.cmd1"}, 1481 {Name: "alias2", Target: "alias-snap_instance.cmd2"}, 1482 }, 1483 }, 1484 } 1485 // start with an easier-to-read error if this fails: 1486 c.Assert(s.fakeBackend.ops.Ops(), DeepEquals, expected.Ops()) 1487 c.Assert(s.fakeBackend.ops, DeepEquals, expected) 1488 1489 var snapst snapstate.SnapState 1490 err = snapstate.Get(s.state, "alias-snap_instance", &snapst) 1491 c.Assert(err, IsNil) 1492 // _instance aliases are preferred now 1493 c.Check(snapst.AutoAliasesDisabled, Equals, false) 1494 c.Check(snapst.AliasesPending, Equals, false) 1495 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1496 "alias1": {Auto: "cmd1"}, 1497 "alias2": {Auto: "cmd2"}, 1498 }) 1499 1500 err = snapstate.Get(s.state, "alias-snap", &snapst) 1501 c.Assert(err, IsNil) 1502 c.Check(snapst.AutoAliasesDisabled, Equals, true) 1503 c.Check(snapst.AliasesPending, Equals, false) 1504 c.Check(snapst.Aliases, DeepEquals, map[string]*snapstate.AliasTarget{ 1505 "alias1": {Auto: "cmd1"}, 1506 "alias2": {Auto: "cmd2"}, 1507 }) 1508 1509 } 1510 1511 func (s *snapmgrTestSuite) TestUpdatePreferChangeConflict(c *C) { 1512 s.state.Lock() 1513 defer s.state.Unlock() 1514 1515 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1516 Active: true, 1517 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1518 Current: snap.R(7), 1519 SnapType: "app", 1520 AutoAliasesDisabled: true, 1521 Aliases: map[string]*snapstate.AliasTarget{ 1522 "alias1": {Auto: "cmd1"}, 1523 }, 1524 }) 1525 1526 ts, err := snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1527 c.Assert(err, IsNil) 1528 // need a change to make the tasks visible 1529 s.state.NewChange("update", "...").AddAll(ts) 1530 1531 _, err = snapstate.Prefer(s.state, "some-snap") 1532 c.Assert(err, ErrorMatches, `snap "some-snap" has "update" change in progress`) 1533 } 1534 1535 func (s *snapmgrTestSuite) TestPreferUpdateChangeConflict(c *C) { 1536 s.state.Lock() 1537 defer s.state.Unlock() 1538 1539 snapstate.Set(s.state, "some-snap", &snapstate.SnapState{ 1540 Active: true, 1541 Sequence: []*snap.SideInfo{{RealName: "some-snap", SnapID: "some-snap-id", Revision: snap.R(7)}}, 1542 Current: snap.R(7), 1543 SnapType: "app", 1544 AutoAliasesDisabled: true, 1545 Aliases: map[string]*snapstate.AliasTarget{ 1546 "alias1": {Auto: "cmd1"}, 1547 }, 1548 }) 1549 1550 ts, err := snapstate.Prefer(s.state, "some-snap") 1551 c.Assert(err, IsNil) 1552 // need a change to make the tasks visible 1553 s.state.NewChange("prefer", "...").AddAll(ts) 1554 1555 _, err = snapstate.Update(s.state, "some-snap", nil, s.user.ID, snapstate.Flags{}) 1556 c.Assert(err, ErrorMatches, `snap "some-snap" has "prefer" change in progress`) 1557 }