Skip to content

Commit

Permalink
Merge pull request NVIDIA#765 from elezar/use-logger-in-toolkit-install
Browse files Browse the repository at this point in the history
Simplify standalone installer
  • Loading branch information
elezar authored Jan 22, 2025
2 parents 6375e83 + 6bd292e commit c22f3bd
Show file tree
Hide file tree
Showing 29 changed files with 393 additions and 267 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/operator"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container/operator"
)

const (
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (
testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/containerd"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

func TestUpdateV1ConfigDefaultRuntime(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (
testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/containerd"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ import (
log "github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/containerd"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import (
log "github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/crio"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/ocihook"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/toml"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import (
log "github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/docker"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import (

"github.com/stretchr/testify/require"

"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/pkg/config/engine/docker"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
)

func TestUpdateConfigDefaultRuntime(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import (

"github.com/urfave/cli/v2"

"github.com/NVIDIA/nvidia-container-toolkit/tools/container"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container/runtime/containerd"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container/runtime/crio"
"github.com/NVIDIA/nvidia-container-toolkit/tools/container/runtime/docker"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/runtime/containerd"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/runtime/crio"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/runtime/docker"
)

const (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"path/filepath"
"sort"
"strings"

log "github.com/sirupsen/logrus"
)

type executableTarget struct {
Expand All @@ -33,6 +31,7 @@ type executableTarget struct {
}

type executable struct {
fileInstaller
source string
target executableTarget
env map[string]string
Expand All @@ -43,21 +42,21 @@ type executable struct {
// install installs an executable component of the NVIDIA container toolkit. The source executable
// is copied to a `.real` file and a wapper is created to set up the environment as required.
func (e executable) install(destFolder string) (string, error) {
log.Infof("Installing executable '%v' to %v", e.source, destFolder)
e.logger.Infof("Installing executable '%v' to %v", e.source, destFolder)

dotfileName := e.dotfileName()

installedDotfileName, err := installFileToFolderWithName(destFolder, dotfileName, e.source)
installedDotfileName, err := e.installFileToFolderWithName(destFolder, dotfileName, e.source)
if err != nil {
return "", fmt.Errorf("error installing file '%v' as '%v': %v", e.source, dotfileName, err)
}
log.Infof("Installed '%v'", installedDotfileName)
e.logger.Infof("Installed '%v'", installedDotfileName)

wrapperFilename, err := e.installWrapper(destFolder, installedDotfileName)
if err != nil {
return "", fmt.Errorf("error wrapping '%v': %v", installedDotfileName, err)
}
log.Infof("Installed wrapper '%v'", wrapperFilename)
e.logger.Infof("Installed wrapper '%v'", wrapperFilename)

return wrapperFilename, nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ import (
"strings"
"testing"

testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"
)

func TestWrapper(t *testing.T) {
logger, _ := testlog.NewNullLogger()

const shebang = "#! /bin/sh"
const destFolder = "/dest/folder"
const dotfileName = "source.real"
Expand Down Expand Up @@ -98,6 +101,8 @@ func TestWrapper(t *testing.T) {
for i, tc := range testCases {
buf := &bytes.Buffer{}

tc.e.logger = logger

err := tc.e.writeWrapperTo(buf, destFolder, dotfileName)
require.NoError(t, err)

Expand All @@ -107,6 +112,8 @@ func TestWrapper(t *testing.T) {
}

func TestInstallExecutable(t *testing.T) {
logger, _ := testlog.NewNullLogger()

inputFolder, err := os.MkdirTemp("", "")
require.NoError(t, err)
defer os.RemoveAll(inputFolder)
Expand All @@ -121,6 +128,9 @@ func TestInstallExecutable(t *testing.T) {
require.NoError(t, sourceFile.Close())

e := executable{
fileInstaller: fileInstaller{
logger: logger,
},
source: source,
target: executableTarget{
dotfileName: "input.real",
Expand Down
95 changes: 95 additions & 0 deletions cmd/nvidia-ctk-installer/container/toolkit/file-installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
# Copyright 2024 NVIDIA CORPORATION
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/

package toolkit

import (
"fmt"
"io"
"os"
"path/filepath"

"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
)

type fileInstaller struct {
logger logger.Interface
// sourceRoot specifies the root that is searched for the components to install.
sourceRoot string
}

// installFileToFolder copies a source file to a destination folder.
// The path of the input file is ignored.
// e.g. installFileToFolder("/some/path/file.txt", "/output/path")
// will result in a file "/output/path/file.txt" being generated
func (t *fileInstaller) installFileToFolder(destFolder string, src string) (string, error) {
name := filepath.Base(src)
return t.installFileToFolderWithName(destFolder, name, src)
}

// cp src destFolder/name
func (t *fileInstaller) installFileToFolderWithName(destFolder string, name, src string) (string, error) {
dest := filepath.Join(destFolder, name)
err := t.installFile(dest, src)
if err != nil {
return "", fmt.Errorf("error copying '%v' to '%v': %v", src, dest, err)
}
return dest, nil
}

// installFile copies a file from src to dest and maintains
// file modes
func (t *fileInstaller) installFile(dest string, src string) error {
src = filepath.Join(t.sourceRoot, src)
t.logger.Infof("Installing '%v' to '%v'", src, dest)

source, err := os.Open(src)
if err != nil {
return fmt.Errorf("error opening source: %v", err)
}
defer source.Close()

destination, err := os.Create(dest)
if err != nil {
return fmt.Errorf("error creating destination: %v", err)
}
defer destination.Close()

_, err = io.Copy(destination, source)
if err != nil {
return fmt.Errorf("error copying file: %v", err)
}

err = applyModeFromSource(dest, src)
if err != nil {
return fmt.Errorf("error setting destination file mode: %v", err)
}
return nil
}

// applyModeFromSource sets the file mode for a destination file
// to match that of a specified source file
func applyModeFromSource(dest string, src string) error {
sourceInfo, err := os.Stat(src)
if err != nil {
return fmt.Errorf("error getting file info for '%v': %v", src, err)
}
err = os.Chmod(dest, sourceInfo.Mode())
if err != nil {
return fmt.Errorf("error setting mode for '%v': %v", dest, err)
}
return nil
}
40 changes: 40 additions & 0 deletions cmd/nvidia-ctk-installer/container/toolkit/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
# Copyright 2024 NVIDIA CORPORATION
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
**/

package toolkit

import "github.com/NVIDIA/nvidia-container-toolkit/internal/logger"

// An Option provides a mechanism to configure an Installer.
type Option func(*Installer)

func WithLogger(logger logger.Interface) Option {
return func(i *Installer) {
i.logger = logger
}
}

func WithToolkitRoot(toolkitRoot string) Option {
return func(i *Installer) {
i.toolkitRoot = toolkitRoot
}
}

func WithSourceRoot(sourceRoot string) Option {
return func(i *Installer) {
i.sourceRoot = sourceRoot
}
}
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"fmt"
"path/filepath"

"github.com/NVIDIA/nvidia-container-toolkit/tools/container/operator"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/operator"
)

const (
Expand All @@ -29,10 +29,10 @@ const (

// installContainerRuntimes sets up the NVIDIA container runtimes, copying the executables
// and implementing the required wrapper
func installContainerRuntimes(sourceRoot string, toolkitDir string) error {
func (t *Installer) installContainerRuntimes(toolkitDir string) error {
runtimes := operator.GetRuntimes()
for _, runtime := range runtimes {
r := newNvidiaContainerRuntimeInstaller(filepath.Join(sourceRoot, runtime.Path))
r := t.newNvidiaContainerRuntimeInstaller(runtime.Path)

_, err := r.install(toolkitDir)
if err != nil {
Expand All @@ -46,17 +46,17 @@ func installContainerRuntimes(sourceRoot string, toolkitDir string) error {
// This installer will copy the specified source executable to the toolkit directory.
// The executable is copied to a file with the same name as the source, but with a ".real" suffix and a wrapper is
// created to allow for the configuration of the runtime environment.
func newNvidiaContainerRuntimeInstaller(source string) *executable {
func (t *Installer) newNvidiaContainerRuntimeInstaller(source string) *executable {
wrapperName := filepath.Base(source)
dotfileName := wrapperName + ".real"
target := executableTarget{
dotfileName: dotfileName,
wrapperName: wrapperName,
}
return newRuntimeInstaller(source, target, nil)
return t.newRuntimeInstaller(source, target, nil)
}

func newRuntimeInstaller(source string, target executableTarget, env map[string]string) *executable {
func (t *Installer) newRuntimeInstaller(source string, target executableTarget, env map[string]string) *executable {
preLines := []string{
"",
"cat /proc/modules | grep -e \"^nvidia \" >/dev/null 2>&1",
Expand All @@ -74,10 +74,11 @@ func newRuntimeInstaller(source string, target executableTarget, env map[string]
}

r := executable{
source: source,
target: target,
env: runtimeEnv,
preLines: preLines,
fileInstaller: t.fileInstaller,
source: source,
target: target,
env: runtimeEnv,
preLines: preLines,
}

return &r
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ import (
"strings"
"testing"

testlog "github.com/sirupsen/logrus/hooks/test"
"github.com/stretchr/testify/require"
)

func TestNvidiaContainerRuntimeInstallerWrapper(t *testing.T) {
r := newNvidiaContainerRuntimeInstaller(nvidiaContainerRuntimeSource)
logger, _ := testlog.NewNullLogger()
i := Installer{
fileInstaller: fileInstaller{
logger: logger,
},
}
r := i.newNvidiaContainerRuntimeInstaller(nvidiaContainerRuntimeSource)

const shebang = "#! /bin/sh"
const destFolder = "/dest/folder"
Expand Down
Loading

0 comments on commit c22f3bd

Please sign in to comment.