mirror of
https://github.com/NVIDIA/nvidia-container-toolkit
synced 2024-11-22 08:18:32 +00:00
Handle case where symlink already exists in create-symlinks hook
Signed-off-by: Christopher Desiniotis <cdesiniotis@nvidia.com>
This commit is contained in:
parent
23f1ba3e93
commit
92779e71b3
@ -17,6 +17,7 @@
|
|||||||
package symlinks
|
package symlinks
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -25,6 +26,7 @@ import (
|
|||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
|
||||||
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/symlinks"
|
||||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/oci"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,8 +123,17 @@ func (m command) run(c *cli.Context, cfg *config) error {
|
|||||||
func (m command) createLink(containerRoot string, targetPath string, link string) error {
|
func (m command) createLink(containerRoot string, targetPath string, link string) error {
|
||||||
linkPath := filepath.Join(containerRoot, link)
|
linkPath := filepath.Join(containerRoot, link)
|
||||||
|
|
||||||
|
exists, err := doesLinkExist(targetPath, linkPath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to check if link exists: %w", err)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
m.logger.Debugf("Link %s already exists", linkPath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
m.logger.Infof("Symlinking %v to %v", linkPath, targetPath)
|
m.logger.Infof("Symlinking %v to %v", linkPath, targetPath)
|
||||||
err := os.MkdirAll(filepath.Dir(linkPath), 0755)
|
err = os.MkdirAll(filepath.Dir(linkPath), 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create directory: %v", err)
|
return fmt.Errorf("failed to create directory: %v", err)
|
||||||
}
|
}
|
||||||
@ -133,3 +144,19 @@ func (m command) createLink(containerRoot string, targetPath string, link string
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// doesLinkExist returns true if link exists and points to target.
|
||||||
|
// An error is returned if link exists but points to a different target.
|
||||||
|
func doesLinkExist(target string, link string) (bool, error) {
|
||||||
|
currentTarget, err := symlinks.Resolve(link)
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to resolve existing symlink %s: %w", link, err)
|
||||||
|
}
|
||||||
|
if currentTarget == target {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return true, fmt.Errorf("unexpected link target: %s", currentTarget)
|
||||||
|
}
|
||||||
|
@ -12,6 +12,36 @@ import (
|
|||||||
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/symlinks"
|
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup/symlinks"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestDoesLinkExist(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
|
||||||
|
require.NoError(
|
||||||
|
t,
|
||||||
|
makeFs(tmpDir,
|
||||||
|
dirOrLink{path: "/a/b/c", target: "d"},
|
||||||
|
dirOrLink{path: "/a/b/e", target: "/a/b/f"},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
exists, err := doesLinkExist("d", filepath.Join(tmpDir, "/a/b/c"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, exists)
|
||||||
|
|
||||||
|
exists, err = doesLinkExist("/a/b/f", filepath.Join(tmpDir, "/a/b/e"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, exists)
|
||||||
|
|
||||||
|
_, err = doesLinkExist("different-target", filepath.Join(tmpDir, "/a/b/c"))
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = doesLinkExist("/a/b/d", filepath.Join(tmpDir, "/a/b/c"))
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
exists, err = doesLinkExist("foo", filepath.Join(tmpDir, "/a/b/does-not-exist"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.False(t, exists)
|
||||||
|
}
|
||||||
|
|
||||||
func TestCreateLinkRelativePath(t *testing.T) {
|
func TestCreateLinkRelativePath(t *testing.T) {
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
hostRoot := filepath.Join(tmpDir, "/host-root/")
|
hostRoot := filepath.Join(tmpDir, "/host-root/")
|
||||||
@ -56,12 +86,28 @@ func TestCreateLinkAlreadyExists(t *testing.T) {
|
|||||||
|
|
||||||
// nvidia-cdi-hook create-symlinks --link libfoo.so.1::/lib/libfoo.so
|
// nvidia-cdi-hook create-symlinks --link libfoo.so.1::/lib/libfoo.so
|
||||||
err := getTestCommand().createLink(containerRoot, "libfoo.so.1", "/lib/libfoo.so")
|
err := getTestCommand().createLink(containerRoot, "libfoo.so.1", "/lib/libfoo.so")
|
||||||
require.Error(t, err)
|
require.NoError(t, err)
|
||||||
target, err := symlinks.Resolve(filepath.Join(containerRoot, "lib/libfoo.so"))
|
target, err := symlinks.Resolve(filepath.Join(containerRoot, "lib/libfoo.so"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, "libfoo.so.1", target)
|
require.Equal(t, "libfoo.so.1", target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateLinkAlreadyExistsDifferentTarget(t *testing.T) {
|
||||||
|
tmpDir := t.TempDir()
|
||||||
|
hostRoot := filepath.Join(tmpDir, "/host-root/")
|
||||||
|
containerRoot := filepath.Join(tmpDir, "/container-root")
|
||||||
|
|
||||||
|
require.NoError(t, makeFs(hostRoot))
|
||||||
|
require.NoError(t, makeFs(containerRoot, dirOrLink{path: "/lib/libfoo.so", target: "different-target"}))
|
||||||
|
|
||||||
|
// nvidia-cdi-hook create-symlinks --link libfoo.so.1::/lib/libfoo.so
|
||||||
|
err := getTestCommand().createLink(containerRoot, "libfoo.so.1", "/lib/libfoo.so")
|
||||||
|
require.Error(t, err)
|
||||||
|
target, err := symlinks.Resolve(filepath.Join(containerRoot, "lib/libfoo.so"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, "different-target", target)
|
||||||
|
}
|
||||||
|
|
||||||
type dirOrLink struct {
|
type dirOrLink struct {
|
||||||
path string
|
path string
|
||||||
target string
|
target string
|
||||||
|
Loading…
Reference in New Issue
Block a user