From 5cbf3f82d990bf8fcd1620789b3a6327121b230a Mon Sep 17 00:00:00 2001 From: Evan Lezar Date: Thu, 7 Nov 2024 08:42:06 -0800 Subject: [PATCH] [no-relnote] Move fileinstaller to separate file Signed-off-by: Evan Lezar --- tools/container/toolkit/file-installer.go | 95 +++++++++++++++++++ tools/container/toolkit/toolkit.go | 107 ++++------------------ 2 files changed, 115 insertions(+), 87 deletions(-) create mode 100644 tools/container/toolkit/file-installer.go diff --git a/tools/container/toolkit/file-installer.go b/tools/container/toolkit/file-installer.go new file mode 100644 index 00000000..ab003c43 --- /dev/null +++ b/tools/container/toolkit/file-installer.go @@ -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 +} diff --git a/tools/container/toolkit/toolkit.go b/tools/container/toolkit/toolkit.go index 666708dc..a8d4e890 100644 --- a/tools/container/toolkit/toolkit.go +++ b/tools/container/toolkit/toolkit.go @@ -18,7 +18,6 @@ package toolkit import ( "fmt" - "io" "os" "path/filepath" "strings" @@ -80,28 +79,6 @@ type Options struct { optInFeatures cli.StringSlice } -type Installer struct { - fileInstaller - toolkitRoot string -} - -type fileInstaller struct { - logger logger.Interface - sourceRoot string -} - -func NewInstaller(opts ...Option) *Installer { - i := &Installer{} - for _, opt := range opts { - opt(i) - } - - if i.logger == nil { - i.logger = logger.New() - } - return i -} - func Flags(opts *Options) []cli.Flag { flags := []cli.Flag{ &cli.StringFlag{ @@ -234,6 +211,26 @@ func Flags(opts *Options) []cli.Flag { return flags } +// An Installer is used to install the NVIDIA Container Toolkit from the toolkit container. +type Installer struct { + fileInstaller + // toolkitRoot specifies the destination path at which the toolkit is installed. + toolkitRoot string +} + +// NewInstaller creates an installer for the NVIDIA Container Toolkit. +func NewInstaller(opts ...Option) *Installer { + i := &Installer{} + for _, opt := range opts { + opt(i) + } + + if i.logger == nil { + i.logger = logger.New() + } + return i +} + // ValidateOptions checks whether the specified options are valid func (t *Installer) ValidateOptions(opts *Options) error { if t == nil { @@ -280,7 +277,6 @@ func (t *Installer) ValidateOptions(opts *Options) error { } // Install installs the components of the NVIDIA container toolkit. -// The specified sourceRoot is searched for the components to install. // Any existing installation is removed. func (t *Installer) Install(cli *cli.Context, opts *Options) error { if t == nil { @@ -622,69 +618,6 @@ func (t *Installer) installSymlink(toolkitRoot string, link string, target strin return nil } -// 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 -} - // findLibrary searches a set of candidate libraries in the specified root for // a given library name func (t *Installer) findLibrary(libName string) (string, error) {