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  }