Skip to content

Commit 3a304b0

Browse files
committed
[no-relnote] Use NVCT_CONFIG_FILE_PATH in toolkit install
Signed-off-by: Evan Lezar <[email protected]>
1 parent 12d91d2 commit 3a304b0

File tree

12 files changed

+453
-43
lines changed

12 files changed

+453
-43
lines changed

cmd/nvidia-ctk-installer/toolkit/installer/directory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type createDirectory struct {
2828
logger logger.Interface
2929
}
3030

31-
func (t *toolkitInstaller) createDirectory() Installer {
31+
func (t *ToolkitInstaller) createDirectory() Installer {
3232
return &createDirectory{
3333
logger: t.logger,
3434
}

cmd/nvidia-ctk-installer/toolkit/installer/executables.go

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,18 @@ import (
2828
log "github.com/sirupsen/logrus"
2929

3030
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/container/operator"
31+
"github.com/NVIDIA/nvidia-container-toolkit/internal/config"
3132
)
3233

3334
type executable struct {
3435
requiresKernelModule bool
3536
path string
3637
symlink string
37-
args []string
3838
env map[string]string
3939
}
4040

41-
func (t *toolkitInstaller) collectExecutables(destDir string) ([]Installer, error) {
42-
configHome := filepath.Join(destDir, ".config")
43-
configDir := filepath.Join(configHome, "nvidia-container-runtime")
44-
configPath := filepath.Join(configDir, "config.toml")
41+
func (t *ToolkitInstaller) collectExecutables(destDir string) ([]Installer, error) {
42+
configFilePath := t.ConfigFilePath(destDir)
4543

4644
executables := []executable{
4745
{
@@ -56,7 +54,7 @@ func (t *toolkitInstaller) collectExecutables(destDir string) ([]Installer, erro
5654
path: runtime.Path,
5755
requiresKernelModule: true,
5856
env: map[string]string{
59-
"XDG_CONFIG_HOME": configHome,
57+
config.FilePathOverrideEnvVar: configFilePath,
6058
},
6159
}
6260
executables = append(executables, e)
@@ -72,7 +70,9 @@ func (t *toolkitInstaller) collectExecutables(destDir string) ([]Installer, erro
7270
executable{
7371
path: "nvidia-container-runtime-hook",
7472
symlink: "nvidia-container-toolkit",
75-
args: []string{fmt.Sprintf("-config %s", configPath)},
73+
env: map[string]string{
74+
config.FilePathOverrideEnvVar: configFilePath,
75+
},
7676
},
7777
)
7878

@@ -94,7 +94,6 @@ func (t *toolkitInstaller) collectExecutables(destDir string) ([]Installer, erro
9494
Source: executablePath,
9595
WrappedExecutable: dotRealFilename,
9696
CheckModules: executable.requiresKernelModule,
97-
Args: executable.args,
9897
Envvars: map[string]string{
9998
"PATH": strings.Join([]string{destDir, "$PATH"}, ":"),
10099
},
@@ -124,7 +123,6 @@ type wrapper struct {
124123
Envvars map[string]string
125124
WrappedExecutable string
126125
CheckModules bool
127-
Args []string
128126
}
129127

130128
type render struct {
@@ -165,9 +163,6 @@ fi
165163
{{$key}}={{$value}} \
166164
{{- end }}
167165
{{ .DestDir }}/{{ .WrappedExecutable }} \
168-
{{- range $arg := .Args }}
169-
{{$arg}} \
170-
{{- end }}
171166
"$@"
172167
`
173168

cmd/nvidia-ctk-installer/toolkit/installer/executables_test.go

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,6 @@ fi
6868
PATH=/foo/bar/baz \
6969
/dest-dir/some-runtime \
7070
"$@"
71-
`,
72-
},
73-
{
74-
description: "args are added",
75-
w: &wrapper{
76-
WrappedExecutable: "some-runtime",
77-
Args: []string{"--config foo", "bar"},
78-
},
79-
expected: `#! /bin/sh
80-
/dest-dir/some-runtime \
81-
--config foo \
82-
bar \
83-
"$@"
8471
`,
8572
},
8673
}

cmd/nvidia-ctk-installer/toolkit/installer/installer.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type Installer interface {
3333
Install(string) error
3434
}
3535

36-
type toolkitInstaller struct {
36+
type ToolkitInstaller struct {
3737
logger logger.Interface
3838
ignoreErrors bool
3939
sourceRoot string
@@ -43,11 +43,11 @@ type toolkitInstaller struct {
4343
ensureTargetDirectory Installer
4444
}
4545

46-
var _ Installer = (*toolkitInstaller)(nil)
46+
var _ Installer = (*ToolkitInstaller)(nil)
4747

4848
// New creates a toolkit installer with the specified options.
49-
func New(opts ...Option) (Installer, error) {
50-
t := &toolkitInstaller{
49+
func New(opts ...Option) (*ToolkitInstaller, error) {
50+
t := &ToolkitInstaller{
5151
sourceRoot: "/",
5252
}
5353
for _, opt := range opts {
@@ -73,7 +73,7 @@ func New(opts ...Option) (Installer, error) {
7373
}
7474

7575
// Install ensures that the required toolkit files are installed in the specified directory.
76-
func (t *toolkitInstaller) Install(destDir string) error {
76+
func (t *ToolkitInstaller) Install(destDir string) error {
7777
var installers []Installer
7878

7979
installers = append(installers, t.ensureTargetDirectory)
@@ -98,6 +98,11 @@ func (t *toolkitInstaller) Install(destDir string) error {
9898
return errs
9999
}
100100

101+
func (t *ToolkitInstaller) ConfigFilePath(destDir string) string {
102+
toolkitConfigDir := filepath.Join(destDir, ".config", "nvidia-container-runtime")
103+
return filepath.Join(toolkitConfigDir, "config.toml")
104+
}
105+
101106
type symlink struct {
102107
linkname string
103108
target string

cmd/nvidia-ctk-installer/toolkit/installer/installer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func TestToolkitInstaller(t *testing.T) {
112112
return nil
113113
},
114114
}
115-
i := toolkitInstaller{
115+
i := ToolkitInstaller{
116116
logger: logger,
117117
artifactRoot: r,
118118
ensureTargetDirectory: createDirectory,

cmd/nvidia-ctk-installer/toolkit/installer/libraries.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
// A predefined set of library candidates are considered, with the first one
2929
// resulting in success being installed to the toolkit folder. The install process
3030
// resolves the symlink for the library and copies the versioned library itself.
31-
func (t *toolkitInstaller) collectLibraries() ([]Installer, error) {
31+
func (t *ToolkitInstaller) collectLibraries() ([]Installer, error) {
3232
requiredLibraries := []string{
3333
"libnvidia-container.so.1",
3434
"libnvidia-container-go.so.1",

cmd/nvidia-ctk-installer/toolkit/installer/options.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,29 @@ package installer
1919

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

22-
type Option func(*toolkitInstaller)
22+
type Option func(*ToolkitInstaller)
2323

2424
func WithLogger(logger logger.Interface) Option {
25-
return func(ti *toolkitInstaller) {
25+
return func(ti *ToolkitInstaller) {
2626
ti.logger = logger
2727
}
2828
}
2929

3030
func WithArtifactRoot(artifactRoot *artifactRoot) Option {
31-
return func(ti *toolkitInstaller) {
31+
return func(ti *ToolkitInstaller) {
3232
ti.artifactRoot = artifactRoot
3333
}
3434
}
3535

3636
func WithIgnoreErrors(ignoreErrors bool) Option {
37-
return func(ti *toolkitInstaller) {
37+
return func(ti *ToolkitInstaller) {
3838
ti.ignoreErrors = ignoreErrors
3939
}
4040
}
4141

4242
// WithSourceRoot sets the root directory for locating artifacts to be installed.
4343
func WithSourceRoot(sourceRoot string) Option {
44-
return func(ti *toolkitInstaller) {
44+
return func(ti *ToolkitInstaller) {
4545
ti.sourceRoot = sourceRoot
4646
}
4747
}

cmd/nvidia-ctk-installer/toolkit/toolkit.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func (t *Installer) Install(cli *cli.Context, opts *Options) error {
316316
t.logger.Errorf("Ignoring error: %v", fmt.Errorf("could not install toolkit components: %w", err))
317317
}
318318

319-
err = t.installToolkitConfig(cli, opts)
319+
err = t.installToolkitConfig(cli, opts, toolkit.ConfigFilePath(t.toolkitRoot))
320320
if err != nil && !opts.ignoreErrors {
321321
return fmt.Errorf("error installing NVIDIA container toolkit config: %v", err)
322322
} else if err != nil {
@@ -343,13 +343,11 @@ func (t *Installer) Install(cli *cli.Context, opts *Options) error {
343343

344344
// installToolkitConfig installs the config file for the NVIDIA container toolkit ensuring
345345
// that the settings are updated to match the desired install and nvidia driver directories.
346-
func (t *Installer) installToolkitConfig(c *cli.Context, opts *Options) error {
347-
toolkitConfigDir := filepath.Join(t.toolkitRoot, ".config", "nvidia-container-runtime")
348-
toolkitConfigPath := filepath.Join(toolkitConfigDir, configFilename)
346+
func (t *Installer) installToolkitConfig(c *cli.Context, opts *Options, toolkitConfigPath string) error {
349347

350348
t.logger.Infof("Installing NVIDIA container toolkit config '%v'", toolkitConfigPath)
351349

352-
err := t.createDirectories(toolkitConfigDir)
350+
err := t.createDirectories(filepath.Dir(toolkitConfigPath))
353351
if err != nil && !opts.ignoreErrors {
354352
return fmt.Errorf("could not create required directories: %v", err)
355353
} else if err != nil {

tools/container/toolkit/executable.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/**
2+
# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
*/
16+
17+
package toolkit
18+
19+
import (
20+
"fmt"
21+
"io"
22+
"os"
23+
"path/filepath"
24+
"sort"
25+
"strings"
26+
27+
log "github.com/sirupsen/logrus"
28+
)
29+
30+
type executableTarget struct {
31+
dotfileName string
32+
wrapperName string
33+
}
34+
35+
type executable struct {
36+
source string
37+
target executableTarget
38+
env map[string]string
39+
preLines []string
40+
}
41+
42+
// install installs an executable component of the NVIDIA container toolkit. The source executable
43+
// is copied to a `.real` file and a wapper is created to set up the environment as required.
44+
func (e executable) install(destFolder string) (string, error) {
45+
log.Infof("Installing executable '%v' to %v", e.source, destFolder)
46+
47+
dotfileName := e.dotfileName()
48+
49+
installedDotfileName, err := installFileToFolderWithName(destFolder, dotfileName, e.source)
50+
if err != nil {
51+
return "", fmt.Errorf("error installing file '%v' as '%v': %v", e.source, dotfileName, err)
52+
}
53+
log.Infof("Installed '%v'", installedDotfileName)
54+
55+
wrapperFilename, err := e.installWrapper(destFolder, installedDotfileName)
56+
if err != nil {
57+
return "", fmt.Errorf("error wrapping '%v': %v", installedDotfileName, err)
58+
}
59+
log.Infof("Installed wrapper '%v'", wrapperFilename)
60+
61+
return wrapperFilename, nil
62+
}
63+
64+
func (e executable) dotfileName() string {
65+
return e.target.dotfileName
66+
}
67+
68+
func (e executable) wrapperName() string {
69+
return e.target.wrapperName
70+
}
71+
72+
func (e executable) installWrapper(destFolder string, dotfileName string) (string, error) {
73+
wrapperPath := filepath.Join(destFolder, e.wrapperName())
74+
wrapper, err := os.Create(wrapperPath)
75+
if err != nil {
76+
return "", fmt.Errorf("error creating executable wrapper: %v", err)
77+
}
78+
defer wrapper.Close()
79+
80+
err = e.writeWrapperTo(wrapper, destFolder, dotfileName)
81+
if err != nil {
82+
return "", fmt.Errorf("error writing wrapper contents: %v", err)
83+
}
84+
85+
err = ensureExecutable(wrapperPath)
86+
if err != nil {
87+
return "", fmt.Errorf("error making wrapper executable: %v", err)
88+
}
89+
return wrapperPath, nil
90+
}
91+
92+
func (e executable) writeWrapperTo(wrapper io.Writer, destFolder string, dotfileName string) error {
93+
r := newReplacements(destDirPattern, destFolder)
94+
95+
// Add the shebang
96+
fmt.Fprintln(wrapper, "#! /bin/sh")
97+
98+
// Add the preceding lines if any
99+
for _, line := range e.preLines {
100+
fmt.Fprintf(wrapper, "%s\n", r.apply(line))
101+
}
102+
103+
// Update the path to include the destination folder
104+
var env map[string]string
105+
if e.env == nil {
106+
env = make(map[string]string)
107+
} else {
108+
env = e.env
109+
}
110+
111+
path, specified := env["PATH"]
112+
if !specified {
113+
path = "$PATH"
114+
}
115+
env["PATH"] = strings.Join([]string{destFolder, path}, ":")
116+
117+
var sortedEnvvars []string
118+
for e := range env {
119+
sortedEnvvars = append(sortedEnvvars, e)
120+
}
121+
sort.Strings(sortedEnvvars)
122+
123+
for _, e := range sortedEnvvars {
124+
v := env[e]
125+
fmt.Fprintf(wrapper, "%s=%s \\\n", e, r.apply(v))
126+
}
127+
// Add the call to the target executable
128+
fmt.Fprintf(wrapper, "%s \\\n", dotfileName)
129+
130+
// Add the script arguments "$@"
131+
fmt.Fprintln(wrapper, "\t\"$@\"")
132+
133+
return nil
134+
}
135+
136+
// ensureExecutable is equivalent to running chmod +x on the specified file
137+
func ensureExecutable(path string) error {
138+
info, err := os.Stat(path)
139+
if err != nil {
140+
return fmt.Errorf("error getting file info for '%v': %v", path, err)
141+
}
142+
executableMode := info.Mode() | 0111
143+
err = os.Chmod(path, executableMode)
144+
if err != nil {
145+
return fmt.Errorf("error setting executable mode for '%v': %v", path, err)
146+
}
147+
return nil
148+
}

0 commit comments

Comments
 (0)