func (*SymlinkSuite) TestReplace(c *gc.C) { target, err := symlink.GetLongPathAsString(c.MkDir()) c.Assert(err, gc.IsNil) target_second, err := symlink.GetLongPathAsString(c.MkDir()) c.Assert(err, gc.IsNil) link := filepath.Join(target, "link") _, err = os.Stat(target) c.Assert(err, gc.IsNil) _, err = os.Stat(target_second) c.Assert(err, gc.IsNil) err = symlink.New(target, link) c.Assert(err, gc.IsNil) link_target, err := symlink.Read(link) c.Assert(err, gc.IsNil) c.Assert(link_target, gc.Equals, filepath.FromSlash(target)) err = symlink.Replace(link, target_second) c.Assert(err, gc.IsNil) link_target, err = symlink.Read(link) c.Assert(err, gc.IsNil) c.Assert(link_target, gc.Equals, filepath.FromSlash(target_second)) }
func (s *ToolsSuite) TestEnsureJujucSymlinks(c *gc.C) { jujudPath := filepath.Join(s.toolsDir, names.Jujud) err := ioutil.WriteFile(jujudPath, []byte("assume sane"), 0755) c.Assert(err, gc.IsNil) assertLink := func(path string) time.Time { target, err := symlink.Read(path) c.Assert(err, gc.IsNil) c.Assert(target, gc.Equals, jujudPath) fi, err := os.Lstat(path) c.Assert(err, gc.IsNil) return fi.ModTime() } // Check that EnsureJujucSymlinks writes appropriate symlinks. err = uniter.EnsureJujucSymlinks(s.toolsDir) c.Assert(err, gc.IsNil) mtimes := map[string]time.Time{} for _, name := range jujuc.CommandNames() { tool := filepath.Join(s.toolsDir, name) mtimes[tool] = assertLink(tool) } // Check that EnsureJujucSymlinks doesn't overwrite things that don't need to be. err = uniter.EnsureJujucSymlinks(s.toolsDir) c.Assert(err, gc.IsNil) for tool, mtime := range mtimes { c.Assert(assertLink(tool), gc.Equals, mtime) } }
// gitManifest returns every file path in the supplied directory, *except* for: // * paths below .git, because we don't need to track every file: we just // want them all gone // * charmURLPath, because we don't ever want to remove that: that's how // the manifestDeployer keeps track of what version it's upgrading from. // All paths are slash-separated, to match the bundle manifest format. func gitManifest(linkPath string) (set.Strings, error) { dirPath, err := symlink.Read(linkPath) if err != nil { return nil, err } manifest := make(set.Strings) err = filepath.Walk(dirPath, func(path string, fileInfo os.FileInfo, err error) error { if err != nil { return err } relPath, err := filepath.Rel(dirPath, path) if err != nil { return err } switch relPath { case ".", CharmURLPath: return nil case ".git": err = filepath.SkipDir } manifest.Add(filepath.ToSlash(relPath)) return err }) return manifest, err }
func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) { if runtime.GOOS == "windows" { // Cannot make symlink to nonexistent file on windows or // create a file point a symlink to it then remove it c.Skip("Cannot test this on windows") } stm, _, _ := s.primeAgent(c, state.JobManageModel) a := s.newAgent(c, stm) defer a.Stop() // Pre-create the symlinks, but pointing to the incorrect location. links := []string{jujuRun, jujuDumpLogs} a.rootDir = c.MkDir() for _, link := range links { fullLink := utils.EnsureBaseDir(a.rootDir, link) c.Assert(os.MkdirAll(filepath.Dir(fullLink), os.FileMode(0755)), jc.ErrorIsNil) c.Assert(symlink.New("/nowhere/special", fullLink), jc.ErrorIsNil, gc.Commentf(link)) } // Start the agent and wait for it be running. _, done := s.waitForOpenState(c, a) // juju-run symlink should have been recreated. for _, link := range links { fullLink := utils.EnsureBaseDir(a.rootDir, link) linkTarget, err := symlink.Read(fullLink) c.Assert(err, jc.ErrorIsNil) c.Assert(linkTarget, gc.Not(gc.Equals), "/nowhere/special", gc.Commentf(link)) } s.waitStopped(c, state.JobManageModel, a, done) }
// collectGitOrphans deletes all repos in dataPath except the one pointed to by // a git deployer's "current" symlink. // Errors are generally ignored; some are logged. If current does not exist, *all* // repos are orphans, and all will be deleted; this should only be the case when // converting a gitDeployer to a manifestDeployer. func collectGitOrphans(dataPath string) { current, err := symlink.Read(filepath.Join(dataPath, gitCurrentPath)) if os.IsNotExist(err) { logger.Debugf("no current staging repo") } else if err != nil { logger.Warningf("cannot read current staging repo: %v", err) return } else if !filepath.IsAbs(current) { current = filepath.Join(dataPath, current) } orphans, err := filepath.Glob(filepath.Join(dataPath, fmt.Sprintf("%s*", gitUpdatePrefix))) if err != nil { return } installOrphans, err := filepath.Glob(filepath.Join(dataPath, fmt.Sprintf("%s*", gitInstallPrefix))) if err != nil { return } orphans = append(orphans, installOrphans...) for _, repoPath := range orphans { if repoPath != dataPath && repoPath != current { if err = os.RemoveAll(repoPath); err != nil { logger.Warningf("failed to remove orphan repo at %s: %s", repoPath, err) } } } }
func (s *MachineSuite) TestMachineAgentSymlinkJujuRunExists(c *gc.C) { err := symlink.New("/nowhere/special", jujuRun) c.Assert(err, gc.IsNil) _, err = os.Stat(jujuRun) c.Assert(err, jc.Satisfies, os.IsNotExist) s.assertJobWithAPI(c, state.JobManageEnviron, func(conf agent.Config, st *api.State) { // juju-run should have been recreated _, err := os.Stat(jujuRun) c.Assert(err, gc.IsNil) link, err := symlink.Read(jujuRun) c.Assert(err, gc.IsNil) c.Assert(link, gc.Not(gc.Equals), "/nowhere/special") }) }
func (*SymlinkSuite) TestCreateSymLink(c *gc.C) { target, err := symlink.GetLongPathAsString(c.MkDir()) c.Assert(err, gc.IsNil) link := filepath.Join(target, "link") _, err = os.Stat(target) c.Assert(err, gc.IsNil) err = symlink.New(target, link) c.Assert(err, gc.IsNil) link, err = symlink.Read(link) c.Assert(err, gc.IsNil) c.Assert(link, gc.Equals, filepath.FromSlash(target)) }
func (s *LxcSuite) TestCreateContainer(c *gc.C) { manager := s.makeManager(c, "test") instance := containertesting.CreateContainer(c, manager, "1/lxc/0") name := string(instance.Id()) // Check our container config files: initial lxc.conf, the // run-time effective config, and cloud-init userdata. lxcConfContents, err := ioutil.ReadFile(filepath.Join(s.ContainerDir, name, "lxc.conf")) c.Assert(err, jc.ErrorIsNil) c.Assert(string(lxcConfContents), jc.Contains, "lxc.network.link = nic42") lxcConfContents, err = ioutil.ReadFile(lxc.ContainerConfigFilename(name)) c.Assert(err, jc.ErrorIsNil) c.Assert(string(lxcConfContents), jc.Contains, "lxc.network.link = nic42") cloudInitFilename := filepath.Join(s.ContainerDir, name, "cloud-init") data := containertesting.AssertCloudInit(c, cloudInitFilename) x := make(map[interface{}]interface{}) err = goyaml.Unmarshal(data, &x) c.Assert(err, jc.ErrorIsNil) var scripts []string for _, s := range x["runcmd"].([]interface{}) { scripts = append(scripts, s.(string)) } c.Assert(scripts[len(scripts)-3:], gc.DeepEquals, []string{ "start jujud-machine-1-lxc-0", "rm $bin/tools.tar.gz && rm $bin/juju2.3.4-quantal-amd64.sha256", "ifconfig", }) // Check the mount point has been created inside the container. c.Assert(filepath.Join(s.LxcDir, name, "rootfs", agent.DefaultPaths.LogDir), jc.IsDirectory) // Check that the config file is linked in the restart dir. expectedLinkLocation := filepath.Join(s.RestartDir, name+".conf") expectedTarget := filepath.Join(s.LxcDir, name, "config") linkInfo, err := os.Lstat(expectedLinkLocation) c.Assert(err, jc.ErrorIsNil) c.Assert(linkInfo.Mode()&os.ModeSymlink, gc.Equals, os.ModeSymlink) location, err := symlink.Read(expectedLinkLocation) c.Assert(err, jc.ErrorIsNil) c.Assert(location, gc.Equals, expectedTarget) }
func checkCleanup(c *gc.C, d charm.Deployer) { // Only one update dir should exist and be pointed to by the 'current' // symlink since extra ones should have been cleaned up by // cleanupOrphans. deployerPath := charm.GitDeployerDataPath(d) updateDirs, err := filepath.Glob(filepath.Join(deployerPath, "update-*")) c.Assert(err, jc.ErrorIsNil) c.Assert(updateDirs, gc.HasLen, 1) deployerCurrent := charm.GitDeployerCurrent(d) current, err := symlink.Read(deployerCurrent.Path()) c.Assert(err, jc.ErrorIsNil) c.Assert(updateDirs[0], gc.Equals, current) // No install dirs should be left behind since the one created is // renamed to the target path. installDirs, err := filepath.Glob(filepath.Join(deployerPath, "install-*")) c.Assert(err, jc.ErrorIsNil) c.Assert(installDirs, gc.HasLen, 0) }
func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) { oldTools := &coretools.Tools{ Version: version.MustParseBinary("1.2.3-quantal-amd64"), } stor := s.Conn.Environ.Storage() newTools := envtesting.PrimeTools(c, stor, s.DataDir(), version.MustParseBinary("5.4.3-precise-amd64")) s.PatchValue(&version.Current, newTools.Version) err := envtools.MergeAndWriteMetadata(stor, coretools.List{newTools}, envtools.DoNotWriteMirrors) c.Assert(err, gc.IsNil) ugErr := &upgrader.UpgradeReadyError{ AgentName: "anAgent", OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), } err = ugErr.ChangeAgentTools() c.Assert(err, gc.IsNil) link, err := symlink.Read(agenttools.ToolsDir(s.DataDir(), "anAgent")) c.Assert(err, gc.IsNil) c.Assert(link, gc.Equals, newTools.Version.String()) }
func (s *UpgraderSuite) TestChangeAgentTools(c *gc.C) { oldTools := &coretools.Tools{ Version: version.MustParseBinary("1.2.3-quantal-amd64"), } stor := s.DefaultToolsStorage newToolsBinary := "5.4.3-precise-amd64" newTools := envtesting.PrimeTools(c, stor, s.DataDir(), s.Environ.Config().AgentStream(), version.MustParseBinary(newToolsBinary)) s.PatchValue(&version.Current, newTools.Version) err := envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{newTools}, envtools.DoNotWriteMirrors) c.Assert(err, jc.ErrorIsNil) ugErr := &upgrader.UpgradeReadyError{ AgentName: "anAgent", OldTools: oldTools.Version, NewTools: newTools.Version, DataDir: s.DataDir(), } err = ugErr.ChangeAgentTools() c.Assert(err, jc.ErrorIsNil) target := agenttools.ToolsDir(s.DataDir(), newToolsBinary) link, err := symlink.Read(agenttools.ToolsDir(s.DataDir(), "anAgent")) c.Assert(err, jc.ErrorIsNil) c.Assert(link, jc.SamePath, target) }
func (a *MachineAgent) createSymlink(target, link string) error { fullLink := utils.EnsureBaseDir(a.rootDir, link) currentTarget, err := symlink.Read(fullLink) if err != nil && !os.IsNotExist(err) { return err } else if err == nil { // Link already in place - check it. if currentTarget == target { // Link already points to the right place - nothing to do. return nil } // Link points to the wrong place - delete it. if err := os.Remove(fullLink); err != nil { return err } } if err := os.MkdirAll(filepath.Dir(fullLink), os.FileMode(0755)); err != nil { return err } return symlink.New(target, fullLink) }
// EnsureSymlinks creates a symbolic link to jujuc within dir for each // hook command. If the commands already exist, this operation does nothing. // If dir is a symbolic link, it will be dereferenced first. func EnsureSymlinks(dir string) (err error) { logger.Infof("ensure jujuc symlinks in %s", dir) defer func() { if err != nil { err = errors.Annotatef(err, "cannot initialize hook commands in %q", dir) } }() isSymlink, err := symlink.IsSymlink(dir) if err != nil { return err } if isSymlink { link, err := symlink.Read(dir) if err != nil { return err } if !filepath.IsAbs(link) { logger.Infof("%s is relative", link) link = filepath.Join(filepath.Dir(dir), link) } dir = link logger.Infof("was a symlink, now looking at %s", dir) } jujudPath := filepath.Join(dir, names.Jujud) logger.Debugf("jujud path %s", jujudPath) for _, name := range CommandNames() { // The link operation fails when the target already exists, // so this is a no-op when the command names already // exist. err := symlink.New(jujudPath, filepath.Join(dir, name)) if err != nil && !os.IsExist(err) { return err } } return nil }