github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/agent/tools/symlinks.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package tools 5 6 import ( 7 "os" 8 "path/filepath" 9 10 "github.com/juju/errors" 11 "github.com/juju/utils/v3/symlink" 12 13 "github.com/juju/juju/juju/names" 14 ) 15 16 // EnsureSymlinks creates a symbolic link to jujud within dir for each 17 // command. If the commands already exist, this operation does nothing. 18 // If dir is a symbolic link, it will be dereferenced first. 19 func EnsureSymlinks(jujuDir, dir string, commands []string) (err error) { 20 logger.Infof("ensure jujuc symlinks in %s", dir) 21 defer func() { 22 if err != nil { 23 err = errors.Annotatef(err, "cannot initialize commands in %q", dir) 24 } 25 }() 26 isSymlink, err := symlink.IsSymlink(jujuDir) 27 if err != nil { 28 return err 29 } 30 if isSymlink { 31 link, err := symlink.Read(jujuDir) 32 if err != nil { 33 return err 34 } 35 if !filepath.IsAbs(link) { 36 logger.Infof("%s is relative", link) 37 link = filepath.Join(filepath.Dir(dir), link) 38 } 39 jujuDir = link 40 logger.Infof("was a symlink, now looking at %s", jujuDir) 41 } 42 43 jujucPath := filepath.Join(jujuDir, names.Jujuc) 44 targetPath := jujucPath 45 if _, err := os.Stat(jujucPath); os.IsNotExist(err) { 46 jujudPath := filepath.Join(jujuDir, names.Jujud) 47 logger.Debugf("jujuc not found at %s using jujud path %s", jujucPath, jujudPath) 48 targetPath = jujudPath 49 } 50 logger.Debugf("target tools path %s", targetPath) 51 for _, name := range commands { 52 // The link operation fails when the target already exists, 53 // so this is a no-op when the command names already 54 // exist. 55 err := symlink.New(targetPath, filepath.Join(dir, name)) 56 if err != nil && !os.IsExist(err) { 57 return err 58 } 59 } 60 return nil 61 }