Esempio n. 1
0
func (s *ManifestDeployerSuite) TestUpgradeConflictResolveRetrySameCharm(c *gc.C) {
	// Create base install.
	s.deployCharm(c, 1,
		ft.File{"shared-file", "old", 0755},
		ft.File{"old-file", "old", 0644},
	)

	// Create mock upgrade charm that can (claim to) fail to expand...
	failDeploy := true
	upgradeContent := ft.Entries{
		ft.File{"shared-file", "new", 0755},
		ft.File{"new-file", "new", 0644},
	}
	mockCharm := mockBundle{
		paths: set.NewStrings(upgradeContent.Paths()...),
		expand: func(targetPath string) error {
			upgradeContent.Create(c, targetPath)
			if failDeploy {
				return fmt.Errorf("oh noes")
			}
			return nil
		},
	}
	info := s.addMockCharm(c, 2, mockCharm)
	err := s.deployer.Stage(info, nil)
	c.Assert(err, gc.IsNil)

	// ...and see it fail to expand. We're not too bothered about the actual
	// content of the target dir at this stage, but we do want to check it's
	// still marked as based on the original charm...
	err = s.deployer.Deploy()
	c.Assert(err, gc.Equals, charm.ErrConflict)
	s.assertCharm(c, 1)

	// ...and we want to verify that if we "fix the errors" and redeploy the
	// same charm...
	failDeploy = false
	err = s.deployer.NotifyResolved()
	c.Assert(err, gc.IsNil)
	err = s.deployer.Deploy()
	c.Assert(err, gc.IsNil)

	// ...we end up with the right stuff in play.
	s.assertCharm(c, 2, upgradeContent...)
	ft.Removed{"old-file"}.Check(c, s.targetPath)
}
Esempio n. 2
0
func (s *EntrySuite) TestEntries(c *gc.C) {
	initial := ft.Entries{
		ft.File{"some-file", "content", 0600},
		ft.Dir{"some-dir", 0750},
		ft.Symlink{"some-link", "target"},
		ft.Removed{"missing"},
	}
	expectRemoveds := ft.Entries{
		ft.Removed{"some-file"},
		ft.Removed{"some-dir"},
		ft.Removed{"some-link"},
		ft.Removed{"missing"},
	}
	removeds := initial.AsRemoveds()
	c.Assert(removeds, jc.DeepEquals, expectRemoveds)

	expectPaths := []string{"some-file", "some-dir", "some-link", "missing"}
	c.Assert(initial.Paths(), jc.DeepEquals, expectPaths)
	c.Assert(removeds.Paths(), jc.DeepEquals, expectPaths)

	chainRemoveds := initial.Create(c, s.basePath).Check(c, s.basePath).AsRemoveds()
	c.Assert(chainRemoveds, jc.DeepEquals, expectRemoveds)
	chainRemoveds = chainRemoveds.Create(c, s.basePath).Check(c, s.basePath)
	c.Assert(chainRemoveds, jc.DeepEquals, expectRemoveds)
}
Esempio n. 3
0
func (s *ManifestDeployerSuite) TestUpgradeConflictRevertRetryDifferentCharm(c *gc.C) {
	// Create base install and add a user file.
	s.deployCharm(c, 1,
		ft.File{"shared-file", "old", 0755},
		ft.File{"old-file", "old", 0644},
	)
	userFile := ft.File{"user-file", "user", 0644}.Create(c, s.targetPath)

	// Create a charm upgrade that never works (but still writes a bunch of files),
	// and deploy it.
	badUpgradeContent := ft.Entries{
		ft.File{"shared-file", "bad", 0644},
		ft.File{"bad-file", "bad", 0644},
	}
	badCharm := mockBundle{
		paths: set.NewStrings(badUpgradeContent.Paths()...),
		expand: func(targetPath string) error {
			badUpgradeContent.Create(c, targetPath)
			return fmt.Errorf("oh noes")
		},
	}
	badInfo := s.addMockCharm(c, 2, badCharm)
	err := s.deployer.Stage(badInfo, nil)
	c.Assert(err, gc.IsNil)
	err = s.deployer.Deploy()
	c.Assert(err, gc.Equals, charm.ErrConflict)

	// Notify the Deployer that it'll be expected to revert the changes from
	// the last attempt.
	err = s.deployer.NotifyRevert()
	c.Assert(err, gc.IsNil)

	// Create a charm upgrade that creates a bunch of different files, without
	// error, and deploy it; check user files are preserved, and nothing from
	// charm 1 or 2 is.
	s.deployCharm(c, 3,
		ft.File{"shared-file", "new", 0755},
		ft.File{"new-file", "new", 0644},
	)
	userFile.Check(c, s.targetPath)
	ft.Removed{"old-file"}.Check(c, s.targetPath)
	ft.Removed{"bad-file"}.Check(c, s.targetPath)
}
Esempio n. 4
0
func (s *ManifestDeployerSuite) TestUpgradePreserveUserFiles(c *gc.C) {
	originalCharmContent := ft.Entries{
		ft.File{"charm-file", "to-be-removed", 0644},
		ft.Dir{"charm-dir", 0755},
	}
	s.deployCharm(c, 1, originalCharmContent...)

	// Add user files we expect to keep to the target dir.
	preserveUserContent := ft.Entries{
		ft.File{"user-file", "to-be-preserved", 0644},
		ft.Dir{"user-dir", 0755},
		ft.File{"user-dir/user-file", "also-preserved", 0644},
	}.Create(c, s.targetPath)

	// Add some user files we expect to be removed.
	removeUserContent := ft.Entries{
		ft.File{"charm-dir/user-file", "whoops-removed", 0755},
	}.Create(c, s.targetPath)

	// Add some user files we expect to be replaced.
	ft.Entries{
		ft.File{"replace-file", "original", 0644},
		ft.Dir{"replace-dir", 0755},
		ft.Symlink{"replace-symlink", "replace-file"},
	}.Create(c, s.targetPath)

	// Deploy an upgrade; all new content overwrites the old...
	s.deployCharm(c, 2,
		ft.File{"replace-file", "updated", 0644},
		ft.Dir{"replace-dir", 0755},
		ft.Symlink{"replace-symlink", "replace-dir"},
	)

	// ...and other files are preserved or removed according to
	// source and location.
	preserveUserContent.Check(c, s.targetPath)
	removeUserContent.AsRemoveds().Check(c, s.targetPath)
	originalCharmContent.AsRemoveds().Check(c, s.targetPath)
}