Merge branch 'CNT-2967/add-version-string' into 'main'

Add --version support for the CLIs

See merge request nvidia/container-toolkit/container-toolkit!151
This commit is contained in:
Evan Lezar 2022-05-13 11:02:34 +00:00
commit b2902cc04a
13 changed files with 159 additions and 38 deletions

View File

@ -38,8 +38,6 @@ EXAMPLE_TARGETS := $(patsubst %,example-%, $(EXAMPLES))
CMDS := $(patsubst ./cmd/%/,%,$(sort $(dir $(wildcard ./cmd/*/)))) CMDS := $(patsubst ./cmd/%/,%,$(sort $(dir $(wildcard ./cmd/*/))))
CMD_TARGETS := $(patsubst %,cmd-%, $(CMDS)) CMD_TARGETS := $(patsubst %,cmd-%, $(CMDS))
$(info CMD_TARGETS=$(CMD_TARGETS))
CHECK_TARGETS := assert-fmt vet lint ineffassign misspell CHECK_TARGETS := assert-fmt vet lint ineffassign misspell
MAKE_TARGETS := binaries build check fmt lint-internal test examples cmds coverage generate $(CHECK_TARGETS) MAKE_TARGETS := binaries build check fmt lint-internal test examples cmds coverage generate $(CHECK_TARGETS)
@ -48,6 +46,12 @@ TARGETS := $(MAKE_TARGETS) $(EXAMPLE_TARGETS) $(CMD_TARGETS)
DOCKER_TARGETS := $(patsubst %,docker-%, $(TARGETS)) DOCKER_TARGETS := $(patsubst %,docker-%, $(TARGETS))
.PHONY: $(TARGETS) $(DOCKER_TARGETS) .PHONY: $(TARGETS) $(DOCKER_TARGETS)
ifeq ($(VERSION),)
CLI_VERSION = $(LIB_VERSION)$(if $(LIB_TAG),-$(LIB_TAG))
else
CLI_VERSION = $(VERSION)
endif
GOOS ?= linux GOOS ?= linux
binaries: cmds binaries: cmds
@ -56,7 +60,7 @@ cmd-%: COMMAND_BUILD_OPTIONS = -o $(PREFIX)/$(*)
endif endif
cmds: $(CMD_TARGETS) cmds: $(CMD_TARGETS)
$(CMD_TARGETS): cmd-%: $(CMD_TARGETS): cmd-%:
GOOS=$(GOOS) go build -ldflags "-s -w" $(COMMAND_BUILD_OPTIONS) $(MODULE)/cmd/$(*) GOOS=$(GOOS) go build -ldflags "-s -w -X github.com/NVIDIA/nvidia-container-toolkit/internal/info.gitCommit=$(GIT_COMMIT) -X github.com/NVIDIA/nvidia-container-toolkit/internal/info.version=$(CLI_VERSION)" $(COMMAND_BUILD_OPTIONS) $(MODULE)/cmd/$(*)
build: build:
GOOS=$(GOOS) go build ./... GOOS=$(GOOS) go build ./...

View File

@ -49,7 +49,10 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
level, logLevelError := configFromArgs.getLevel(logLevel) level, logLevelError := configFromArgs.getLevel(logLevel)
var logFiles []*os.File var logFiles []*os.File
var argLogFileError error
// We don't create log files if the version argument is supplied
if !configFromArgs.version {
configLogFile, err := createLogFile(filename) configLogFile, err := createLogFile(filename)
if err != nil { if err != nil {
return logger, fmt.Errorf("error opening debug log file: %v", err) return logger, fmt.Errorf("error opening debug log file: %v", err)
@ -58,10 +61,12 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
logFiles = append(logFiles, configLogFile) logFiles = append(logFiles, configLogFile)
} }
argLogFile, argLogFileError := createLogFile(configFromArgs.file) argLogFile, err := createLogFile(configFromArgs.file)
if argLogFile != nil { if argLogFile != nil {
logFiles = append(logFiles, argLogFile) logFiles = append(logFiles, argLogFile)
} }
argLogFileError = err
}
l := &Logger{ l := &Logger{
Logger: logrus.New(), Logger: logrus.New(),
@ -69,18 +74,6 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
logFiles: logFiles, logFiles: logFiles,
} }
if len(logFiles) == 0 {
l.SetOutput(io.Discard)
} else if len(logFiles) == 1 {
l.SetOutput(logFiles[0])
} else {
var writers []io.Writer
for _, f := range logFiles {
writers = append(writers, f)
}
l.SetOutput(io.MultiWriter(writers...))
}
l.SetLevel(level) l.SetLevel(level)
if level == logrus.DebugLevel { if level == logrus.DebugLevel {
logrus.SetReportCaller(true) logrus.SetReportCaller(true)
@ -102,6 +95,18 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
l.SetFormatter(new(logrus.JSONFormatter)) l.SetFormatter(new(logrus.JSONFormatter))
} }
if len(logFiles) == 0 {
l.SetOutput(io.Discard)
} else if len(logFiles) == 1 {
l.SetOutput(logFiles[0])
} else if len(logFiles) > 1 {
var writers []io.Writer
for _, f := range logFiles {
writers = append(writers, f)
}
l.SetOutput(io.MultiWriter(writers...))
}
if logLevelError != nil { if logLevelError != nil {
l.Warn(logLevelError) l.Warn(logLevelError)
} }
@ -113,9 +118,9 @@ func UpdateLogger(filename string, logLevel string, argv []string) (*Logger, err
return l, nil return l, nil
} }
// CloseFile closes the log file (if any) and resets the logger output to what it // Reset closes the log file (if any) and resets the logger output to what it
// was before UpdateLogger was called. // was before UpdateLogger was called.
func (l *Logger) CloseFile() error { func (l *Logger) Reset() error {
defer func() { defer func() {
previous := l.previousLogger previous := l.previousLogger
if previous == nil { if previous == nil {
@ -156,6 +161,7 @@ type loggerConfig struct {
file string file string
format string format string
debug bool debug bool
version bool
} }
func (c loggerConfig) getLevel(logLevel string) (logrus.Level, error) { func (c loggerConfig) getLevel(logLevel string) (logrus.Level, error) {
@ -182,15 +188,24 @@ func parseArgs(args []string) loggerConfig {
found := make(map[string]bool) found := make(map[string]bool)
for i := 0; i < len(args); i++ { for i := 0; i < len(args); i++ {
if len(found) == 3 { if len(found) == 4 {
break break
} }
param := args[i] param := args[i]
parts := strings.SplitN(param, "=", 2) parts := strings.SplitN(param, "=", 2)
trimmed := strings.TrimPrefix(parts[0], "--") trimmed := strings.TrimLeft(parts[0], "-")
if !strings.HasPrefix(parts[0], "--") { // If this is not a flag we continue
if parts[0] == trimmed {
continue
}
// Check the version flag
if trimmed == "version" {
c.version = true
found["version"] = true
// For the version flag we don't process any other flags
continue continue
} }

View File

@ -3,10 +3,20 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"strings"
"github.com/NVIDIA/nvidia-container-toolkit/internal/config" "github.com/NVIDIA/nvidia-container-toolkit/internal/config"
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
"github.com/opencontainers/runtime-spec/specs-go"
) )
// version must be set by go build's -X main.version= option in the Makefile.
var version = "unknown"
// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""
var logger = NewLogger() var logger = NewLogger()
func main() { func main() {
@ -20,6 +30,11 @@ func main() {
// run is an entry point that allows for idiomatic handling of errors // run is an entry point that allows for idiomatic handling of errors
// when calling from the main function. // when calling from the main function.
func run(argv []string) (rerr error) { func run(argv []string) (rerr error) {
printVersion := hasVersionFlag(argv)
if printVersion {
fmt.Printf("%v version %v\n", "NVIDIA Container Runtime", info.GetVersionString(fmt.Sprintf("spec: %v", specs.Version)))
}
cfg, err := config.GetConfig() cfg, err := config.GetConfig()
if err != nil { if err != nil {
return fmt.Errorf("error loading config: %v", err) return fmt.Errorf("error loading config: %v", err)
@ -33,6 +48,7 @@ func run(argv []string) (rerr error) {
if err != nil { if err != nil {
return fmt.Errorf("failed to set up logger: %v", err) return fmt.Errorf("failed to set up logger: %v", err)
} }
defer logger.Reset()
logger.Debugf("Command line arguments: %v", argv) logger.Debugf("Command line arguments: %v", argv)
runtime, err := newNVIDIAContainerRuntime(logger.Logger, cfg, argv) runtime, err := newNVIDIAContainerRuntime(logger.Logger, cfg, argv)
@ -40,5 +56,29 @@ func run(argv []string) (rerr error) {
return fmt.Errorf("failed to create NVIDIA Container Runtime: %v", err) return fmt.Errorf("failed to create NVIDIA Container Runtime: %v", err)
} }
if printVersion {
fmt.Print("\n")
}
return runtime.Exec(argv) return runtime.Exec(argv)
} }
// TODO: This should be refactored / combined with parseArgs in logger.
func hasVersionFlag(args []string) bool {
for i := 0; i < len(args); i++ {
param := args[i]
parts := strings.SplitN(param, "=", 2)
trimmed := strings.TrimLeft(parts[0], "-")
// If this is not a flag we continue
if parts[0] == trimmed {
continue
}
// Check the version flag
if trimmed == "version" {
return true
}
}
return false
}

View File

@ -19,6 +19,7 @@ import (
var ( var (
debugflag = flag.Bool("debug", false, "enable debug output") debugflag = flag.Bool("debug", false, "enable debug output")
versionflag = flag.Bool("version", false, "enable version output")
configflag = flag.String("config", "", "configuration file") configflag = flag.String("config", "", "configuration file")
) )
@ -159,6 +160,11 @@ func main() {
flag.Usage = usage flag.Usage = usage
flag.Parse() flag.Parse()
if *versionflag {
fmt.Printf("%v version %v\n", "NVIDIA Container Runtime Hook", info.GetVersionString())
return
}
args := flag.Args() args := flag.Args()
if len(args) == 0 { if len(args) == 0 {
flag.Usage() flag.Usage()

View File

@ -20,12 +20,11 @@ import (
"os" "os"
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/hook" "github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk/hook"
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2" cli "github.com/urfave/cli/v2"
) )
var version string
var logger = log.New() var logger = log.New()
// config defines the options that can be set for the CLI through config files, // config defines the options that can be set for the CLI through config files,
@ -41,10 +40,11 @@ func main() {
// Create the top-level CLI // Create the top-level CLI
c := cli.NewApp() c := cli.NewApp()
c.Name = "NVIDIA Container Toolkit CLI"
c.UseShortOptionHandling = true c.UseShortOptionHandling = true
c.EnableBashCompletion = true c.EnableBashCompletion = true
c.Usage = "Tools to configure the NVIDIA Container Toolkit" c.Usage = "Tools to configure the NVIDIA Container Toolkit"
c.Version = version c.Version = info.GetVersionString()
// Setup the flags for this command // Setup the flags for this command
c.Flags = []cli.Flag{ c.Flags = []cli.Flag{

View File

@ -41,6 +41,8 @@ RUN mkdir -p $DIST_DIR /dist
WORKDIR $GOPATH/src/nvidia-container-toolkit WORKDIR $GOPATH/src/nvidia-container-toolkit
COPY . . COPY . .
ARG GIT_COMMIT
ENV GIT_COMMIT ${GIT_COMMIT}
RUN make PREFIX=${DIST_DIR} cmds RUN make PREFIX=${DIST_DIR} cmds
ARG CONFIG_TOML_SUFFIX ARG CONFIG_TOML_SUFFIX

View File

@ -41,6 +41,8 @@ RUN mkdir -p $DIST_DIR /dist
WORKDIR $GOPATH/src/nvidia-container-toolkit WORKDIR $GOPATH/src/nvidia-container-toolkit
COPY . . COPY . .
ARG GIT_COMMIT
ENV GIT_COMMIT ${GIT_COMMIT}
RUN make PREFIX=${DIST_DIR} cmds RUN make PREFIX=${DIST_DIR} cmds
ARG CONFIG_TOML_SUFFIX ARG CONFIG_TOML_SUFFIX

View File

@ -48,6 +48,8 @@ RUN mkdir -p $DIST_DIR /dist
WORKDIR $GOPATH/src/nvidia-container-toolkit WORKDIR $GOPATH/src/nvidia-container-toolkit
COPY . . COPY . .
ARG GIT_COMMIT
ENV GIT_COMMIT ${GIT_COMMIT}
RUN make PREFIX=${DIST_DIR} cmds RUN make PREFIX=${DIST_DIR} cmds
ARG CONFIG_TOML_SUFFIX ARG CONFIG_TOML_SUFFIX

View File

@ -39,6 +39,8 @@ RUN mkdir -p $DIST_DIR /dist
WORKDIR $GOPATH/src/nvidia-container-toolkit WORKDIR $GOPATH/src/nvidia-container-toolkit
COPY . . COPY . .
ARG GIT_COMMIT
ENV GIT_COMMIT ${GIT_COMMIT}
RUN make PREFIX=${DIST_DIR} cmds RUN make PREFIX=${DIST_DIR} cmds
# Hook for Project Atomic's fork of Docker: https://github.com/projectatomic/docker/tree/docker-1.13.1-rhel#add-dockerhooks-exec-custom-hooks-for-prestartpoststop-containerspatch # Hook for Project Atomic's fork of Docker: https://github.com/projectatomic/docker/tree/docker-1.13.1-rhel#add-dockerhooks-exec-custom-hooks-for-prestartpoststop-containerspatch

View File

@ -46,6 +46,8 @@ RUN mkdir -p $DIST_DIR /dist
WORKDIR $GOPATH/src/nvidia-container-toolkit WORKDIR $GOPATH/src/nvidia-container-toolkit
COPY . . COPY . .
ARG GIT_COMMIT
ENV GIT_COMMIT ${GIT_COMMIT}
RUN make PREFIX=${DIST_DIR} cmds RUN make PREFIX=${DIST_DIR} cmds
ARG CONFIG_TOML_SUFFIX ARG CONFIG_TOML_SUFFIX

View File

@ -131,6 +131,7 @@ docker-build-%:
--build-arg PKG_VERS="$(LIB_VERSION)" \ --build-arg PKG_VERS="$(LIB_VERSION)" \
--build-arg PKG_REV="$(PKG_REV)" \ --build-arg PKG_REV="$(PKG_REV)" \
--build-arg CONFIG_TOML_SUFFIX="$(CONFIG_TOML_SUFFIX)" \ --build-arg CONFIG_TOML_SUFFIX="$(CONFIG_TOML_SUFFIX)" \
--build-arg GIT_COMMIT="$(GIT_COMMIT)" \
--tag $(BUILDIMAGE) \ --tag $(BUILDIMAGE) \
--file $(DOCKERFILE) . --file $(DOCKERFILE) .
$(DOCKER) run \ $(DOCKER) run \

43
internal/info/version.go Normal file
View File

@ -0,0 +1,43 @@
/**
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# 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 info
import "strings"
// version must be set by go build's -X main.version= option in the Makefile.
var version = "unknown"
// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""
// GetVersionParts returns the different version components
func GetVersionParts() []string {
v := []string{version}
if gitCommit != "" {
v = append(v, "commit: "+gitCommit)
}
return v
}
// GetVersionString returns the string representation of the version
func GetVersionString(more ...string) string {
v := append(GetVersionParts(), more...)
return strings.Join(v, "\n")
}

View File

@ -26,3 +26,5 @@ LIBNVIDIA_CONTAINER0_VERSION := 0.10.0+jetpack
CUDA_VERSION := 11.6.0 CUDA_VERSION := 11.6.0
GOLANG_VERSION := 1.17.8 GOLANG_VERSION := 1.17.8
GIT_COMMIT ?= $(shell git describe --dirty --long --always 2> /dev/null || echo "")