Sebastiaan van Stijn
2024-06-04 11:33:43 +02:00
parent dbdd3601eb
commit 9358f84668
146 changed files with 2661 additions and 1102 deletions

20
vendor/github.com/docker/cli/AUTHORS generated vendored
View File

@@ -26,6 +26,7 @@ Akhil Mohan <akhil.mohan@mayadata.io>
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Akim Demaille <akim.demaille@docker.com>
Alan Thompson <cloojure@gmail.com>
Alano Terblanche <alano.terblanche@docker.com>
Albert Callarisa <shark234@gmail.com>
Alberto Roura <mail@albertoroura.com>
Albin Kerouanton <albinker@gmail.com>
@@ -65,6 +66,7 @@ Andrew Hsu <andrewhsu@docker.com>
Andrew Macpherson <hopscotch23@gmail.com>
Andrew McDonnell <bugs@andrewmcdonnell.net>
Andrew Po <absourd.noise@gmail.com>
Andrew-Zipperer <atzipperer@gmail.com>
Andrey Petrov <andrey.petrov@shazow.net>
Andrii Berehuliak <berkusandrew@gmail.com>
André Martins <aanm90@gmail.com>
@@ -124,11 +126,13 @@ Bryan Bess <squarejaw@bsbess.com>
Bryan Boreham <bjboreham@gmail.com>
Bryan Murphy <bmurphy1976@gmail.com>
bryfry <bryon.fryer@gmail.com>
Calvin Liu <flycalvin@qq.com>
Cameron Spear <cameronspear@gmail.com>
Cao Weiwei <cao.weiwei30@zte.com.cn>
Carlo Mion <mion00@gmail.com>
Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos de Paula <me@carlosedp.com>
Casey Korver <casey@korver.dev>
Ce Gao <ce.gao@outlook.com>
Cedric Davies <cedricda@microsoft.com>
Cezar Sa Espinola <cezarsa@gmail.com>
@@ -160,6 +164,8 @@ Christophe Vidal <kriss@krizalys.com>
Christopher Biscardi <biscarch@sketcht.com>
Christopher Crone <christopher.crone@docker.com>
Christopher Jones <tophj@linux.vnet.ibm.com>
Christopher Petito <47751006+krissetto@users.noreply.github.com>
Christopher Petito <chrisjpetito@gmail.com>
Christopher Svensson <stoffus@stoffus.com>
Christy Norman <christy@linux.vnet.ibm.com>
Chun Chen <ramichen@tencent.com>
@@ -212,6 +218,7 @@ David Cramer <davcrame@cisco.com>
David Dooling <dooling@gmail.com>
David Gageot <david@gageot.net>
David Karlsson <david.karlsson@docker.com>
David le Blanc <systemmonkey42@users.noreply.github.com>
David Lechner <david@lechnology.com>
David Scott <dave@recoil.org>
David Sheets <dsheets@docker.com>
@@ -298,6 +305,7 @@ Gang Qiao <qiaohai8866@gmail.com>
Gary Schaetz <gary@schaetzkc.com>
Genki Takiuchi <genki@s21g.com>
George MacRorie <gmacr31@gmail.com>
George Margaritis <gmargaritis@protonmail.com>
George Xie <georgexsh@gmail.com>
Gianluca Borello <g.borello@gmail.com>
Gildas Cuisinier <gildas.cuisinier@gcuisinier.net>
@@ -306,6 +314,7 @@ Gleb Stsenov <gleb.stsenov@gmail.com>
Goksu Toprak <goksu.toprak@docker.com>
Gou Rao <gou@portworx.com>
Govind Rai <raigovind93@gmail.com>
Grace Choi <grace.54109@gmail.com>
Graeme Wiebe <graeme.wiebe@gmail.com>
Grant Reaber <grant.reaber@gmail.com>
Greg Pflaum <gpflaum@users.noreply.github.com>
@@ -386,6 +395,7 @@ Jezeniel Zapanta <jpzapanta22@gmail.com>
Jian Zhang <zhangjian.fnst@cn.fujitsu.com>
Jie Luo <luo612@zju.edu.cn>
Jilles Oldenbeuving <ojilles@gmail.com>
Jim Chen <njucjc@gmail.com>
Jim Galasyn <jim.galasyn@docker.com>
Jim Lin <b04705003@ntu.edu.tw>
Jimmy Leger <jimmy.leger@gmail.com>
@@ -416,6 +426,7 @@ John Willis <john.willis@docker.com>
Jon Johnson <jonjohnson@google.com>
Jon Zeolla <zeolla@gmail.com>
Jonatas Baldin <jonatas.baldin@gmail.com>
Jonathan A. Sternberg <jonathansternberg@gmail.com>
Jonathan Boulle <jonathanboulle@gmail.com>
Jonathan Lee <jonjohn1232009@gmail.com>
Jonathan Lomas <jonathan@floatinglomas.ca>
@@ -470,6 +481,7 @@ Kevin Woblick <mail@kovah.de>
khaled souf <khaled.souf@gmail.com>
Kim Eik <kim@heldig.org>
Kir Kolyshkin <kolyshkin@gmail.com>
Kirill A. Korinsky <kirill@korins.ky>
Kotaro Yoshimatsu <kotaro.yoshimatsu@gmail.com>
Krasi Georgiev <krasi@vip-consult.solutions>
Kris-Mikael Krister <krismikael@protonmail.com>
@@ -530,6 +542,7 @@ Marco Vedovati <mvedovati@suse.com>
Marcus Martins <marcus@docker.com>
Marianna Tessel <mtesselh@gmail.com>
Marius Ileana <marius.ileana@gmail.com>
Marius Meschter <marius@meschter.me>
Marius Sturm <marius@graylog.com>
Mark Oates <fl0yd@me.com>
Marsh Macy <marsma@microsoft.com>
@@ -538,6 +551,7 @@ Mary Anthony <mary.anthony@docker.com>
Mason Fish <mason.fish@docker.com>
Mason Malone <mason.malone@gmail.com>
Mateusz Major <apkd@users.noreply.github.com>
Mathias Duedahl <64321057+Lussebullen@users.noreply.github.com>
Mathieu Champlon <mathieu.champlon@docker.com>
Mathieu Rollet <matletix@gmail.com>
Matt Gucci <matt9ucci@gmail.com>
@@ -547,6 +561,7 @@ Matthew Heon <mheon@redhat.com>
Matthieu Hauglustaine <matt.hauglustaine@gmail.com>
Mauro Porras P <mauroporrasp@gmail.com>
Max Shytikov <mshytikov@gmail.com>
Max-Julian Pogner <max-julian@pogner.at>
Maxime Petazzoni <max@signalfuse.com>
Maximillian Fan Xavier <maximillianfx@gmail.com>
Mei ChunTao <mei.chuntao@zte.com.cn>
@@ -610,6 +625,7 @@ Nathan McCauley <nathan.mccauley@docker.com>
Neil Peterson <neilpeterson@outlook.com>
Nick Adcock <nick.adcock@docker.com>
Nick Santos <nick.santos@docker.com>
Nick Sieger <nick@nicksieger.com>
Nico Stapelbroek <nstapelbroek@gmail.com>
Nicola Kabar <nicolaka@gmail.com>
Nicolas Borboën <ponsfrilus@gmail.com>
@@ -704,6 +720,7 @@ Rory Hunter <roryhunter2@gmail.com>
Ross Boucher <rboucher@gmail.com>
Rubens Figueiredo <r.figueiredo.52@gmail.com>
Rui Cao <ruicao@alauda.io>
Rui JingAn <quiterace@gmail.com>
Ryan Belgrave <rmb1993@gmail.com>
Ryan Detzel <ryan.detzel@gmail.com>
Ryan Stelly <ryan.stelly@live.com>
@@ -797,6 +814,7 @@ Tim Hockin <thockin@google.com>
Tim Sampson <tim@sampson.fi>
Tim Smith <timbot@google.com>
Tim Waugh <twaugh@redhat.com>
Tim Welsh <timothy.welsh@docker.com>
Tim Wraight <tim.wraight@tangentlabs.co.uk>
timfeirg <kkcocogogo@gmail.com>
Timothy Hobbs <timothyhobbs@seznam.cz>
@@ -880,9 +898,11 @@ Zhang Wei <zhangwei555@huawei.com>
Zhang Wentao <zhangwentao234@huawei.com>
ZhangHang <stevezhang2014@gmail.com>
zhenghenghuo <zhenghenghuo@zju.edu.cn>
Zhiwei Liang <zliang@akamai.com>
Zhou Hao <zhouhao@cn.fujitsu.com>
Zhoulin Xie <zhoulin.xie@daocloud.io>
Zhu Guihua <zhugh.fnst@cn.fujitsu.com>
Zhuo Zhi <h.dwwwwww@gmail.com>
Álex González <agonzalezro@gmail.com>
Álvaro Lázaro <alvaro.lazaro.g@gmail.com>
Átila Camurça Alves <camurca.home@gmail.com>

View File

@@ -14,6 +14,6 @@ United States and other governments.
It is your responsibility to ensure that your use and/or transfer does not
violate applicable laws.
For more information, please see https://www.bis.doc.gov
For more information, see https://www.bis.doc.gov
See also https://www.apache.org/dev/crypto.html and/or seek legal counsel.

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package manager

View File

@@ -1,6 +1,7 @@
package manager
import (
"context"
"encoding/json"
"strings"
@@ -28,29 +29,36 @@ type HookPluginData struct {
// a main CLI command was executed. It calls the hook subcommand for all
// present CLI plugins that declare support for hooks in their metadata and
// parses/prints their responses.
func RunCLICommandHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
func RunCLICommandHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, cmdErrorMessage string) {
commandName := strings.TrimPrefix(subCommand.CommandPath(), rootCmd.Name()+" ")
flags := getCommandFlags(subCommand)
runHooks(dockerCli, rootCmd, subCommand, commandName, flags, cmdErrorMessage)
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, cmdErrorMessage)
}
// RunPluginHooks is the entrypoint for the hooks execution flow
// after a plugin command was just executed by the CLI.
func RunPluginHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, args []string) {
func RunPluginHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, args []string) {
commandName := strings.Join(args, " ")
flags := getNaiveFlags(args)
runHooks(dockerCli, rootCmd, subCommand, commandName, flags, "")
runHooks(ctx, dockerCli, rootCmd, subCommand, commandName, flags, "")
}
func runHooks(dockerCli command.Cli, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
nextSteps := invokeAndCollectHooks(dockerCli, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
func runHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCommand *cobra.Command, invokedCommand string, flags map[string]string, cmdErrorMessage string) {
nextSteps := invokeAndCollectHooks(ctx, dockerCli, rootCmd, subCommand, invokedCommand, flags, cmdErrorMessage)
hooks.PrintNextSteps(dockerCli.Err(), nextSteps)
}
func invokeAndCollectHooks(dockerCli command.Cli, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
func invokeAndCollectHooks(ctx context.Context, dockerCli command.Cli, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string {
// check if the context was cancelled before invoking hooks
select {
case <-ctx.Done():
return nil
default:
}
pluginsCfg := dockerCli.ConfigFile().Plugins
if pluginsCfg == nil {
return nil
@@ -68,7 +76,7 @@ func invokeAndCollectHooks(dockerCli command.Cli, rootCmd, subCmd *cobra.Command
continue
}
hookReturn, err := p.RunHook(HookPluginData{
hookReturn, err := p.RunHook(ctx, HookPluginData{
RootCmd: match,
Flags: flags,
CommandError: cmdErrorMessage,

View File

@@ -49,6 +49,16 @@ func IsNotFound(err error) bool {
return ok
}
// getPluginDirs returns the platform-specific locations to search for plugins
// in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs [config.Path] (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs.
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
func getPluginDirs(cfg *configfile.ConfigFile) ([]string, error) {
var pluginDirs []string

View File

@@ -2,7 +2,19 @@
package manager
// defaultSystemPluginDirs are the platform-specific locations to search
// for plugins in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs config-directory (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs (as defined below).
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
var defaultSystemPluginDirs = []string{
"/usr/local/lib/docker/cli-plugins", "/usr/local/libexec/docker/cli-plugins",
"/usr/lib/docker/cli-plugins", "/usr/libexec/docker/cli-plugins",
"/usr/local/lib/docker/cli-plugins",
"/usr/local/libexec/docker/cli-plugins",
"/usr/lib/docker/cli-plugins",
"/usr/libexec/docker/cli-plugins",
}

View File

@@ -5,6 +5,16 @@ import (
"path/filepath"
)
// defaultSystemPluginDirs are the platform-specific locations to search
// for plugins in order of preference.
//
// Plugin-discovery is performed in the following order of preference:
//
// 1. The "cli-plugins" directory inside the CLIs config-directory (usually "~/.docker/cli-plugins").
// 2. Additional plugin directories as configured through [ConfigFile.CLIPluginsExtraDirs].
// 3. Platform-specific defaultSystemPluginDirs (as defined below).
//
// [ConfigFile.CLIPluginsExtraDirs]: https://pkg.go.dev/github.com/docker/cli@v26.1.4+incompatible/cli/config/configfile#ConfigFile.CLIPluginsExtraDirs
var defaultSystemPluginDirs = []string{
filepath.Join(os.Getenv("ProgramData"), "Docker", "cli-plugins"),
filepath.Join(os.Getenv("ProgramFiles"), "Docker", "cli-plugins"),

View File

@@ -1,6 +1,7 @@
package manager
import (
"context"
"encoding/json"
"os"
"os/exec"
@@ -105,13 +106,13 @@ func newPlugin(c Candidate, cmds []*cobra.Command) (Plugin, error) {
// RunHook executes the plugin's hooks command
// and returns its unprocessed output.
func (p *Plugin) RunHook(hookData HookPluginData) ([]byte, error) {
func (p *Plugin) RunHook(ctx context.Context, hookData HookPluginData) ([]byte, error) {
hDataBytes, err := json.Marshal(hookData)
if err != nil {
return nil, wrapAsPluginError(err, "failed to marshall hook data")
}
pCmd := exec.Command(p.Path, p.Name, HookSubcommandName, string(hDataBytes))
pCmd := exec.CommandContext(ctx, p.Path, p.Name, HookSubcommandName, string(hDataBytes))
pCmd.Env = os.Environ()
pCmd.Env = append(pCmd.Env, ReexecEnvvar+"="+os.Args[0])
hookCmdOutput, err := pCmd.Output()

View File

@@ -36,13 +36,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
var err error
persistentPreRunOnce.Do(func() {
cmdContext := cmd.Context()
// TODO: revisit and make sure this check makes sense
// see: https://github.com/docker/cli/pull/4599#discussion_r1422487271
if cmdContext == nil {
cmdContext = context.TODO()
}
ctx, cancel := context.WithCancel(cmdContext)
ctx, cancel := context.WithCancel(cmd.Context())
cmd.SetContext(ctx)
// Set up the context to cancel based on signalling via CLI socket.
socket.ConnectAndWait(cancel)
@@ -51,6 +45,7 @@ func RunPlugin(dockerCli *command.DockerCli, plugin *cobra.Command, meta manager
if os.Getenv("DOCKER_CLI_PLUGIN_USE_DIAL_STDIO") != "" {
opts = append(opts, withPluginClientConn(plugin.Name()))
}
opts = append(opts, command.WithEnableGlobalMeterProvider(), command.WithEnableGlobalTracerProvider())
err = tcmd.Initialize(opts...)
ogRunE := cmd.RunE
if ogRunE == nil {

View File

@@ -9,6 +9,8 @@ import (
"os"
"runtime"
"sync"
"github.com/sirupsen/logrus"
)
// EnvKey represents the well-known environment variable used to pass the
@@ -30,6 +32,7 @@ func NewPluginServer(h func(net.Conn)) (*PluginServer, error) {
if err != nil {
return nil, err
}
logrus.Trace("Plugin server listening on ", l.Addr())
if h == nil {
h = func(net.Conn) {}
@@ -92,6 +95,7 @@ func (pl *PluginServer) Addr() net.Addr {
//
// The error value is that of the underlying [net.Listner.Close] call.
func (pl *PluginServer) Close() error {
logrus.Trace("Closing plugin server")
// Close connections first to ensure the connections get io.EOF instead
// of a connection reset.
pl.closeAllConns()
@@ -107,6 +111,10 @@ func (pl *PluginServer) closeAllConns() {
pl.mu.Lock()
defer pl.mu.Unlock()
if pl.closed {
return
}
// Prevent new connections from being accepted.
pl.closed = true

View File

@@ -54,7 +54,7 @@ func setupCommonRootCommand(rootCmd *cobra.Command) (*cliflags.ClientOptions, *c
rootCmd.SetHelpCommand(helpCommand)
rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "please use --help")
rootCmd.PersistentFlags().MarkShorthandDeprecated("help", "use --help")
rootCmd.PersistentFlags().Lookup("help").Hidden = true
rootCmd.Annotations = map[string]string{

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package command
@@ -44,7 +44,7 @@ const defaultInitTimeout = 2 * time.Second
type Streams interface {
In() *streams.In
Out() *streams.Out
Err() io.Writer
Err() *streams.Out
}
// Cli represents the docker command line client.
@@ -75,7 +75,7 @@ type DockerCli struct {
options *cliflags.ClientOptions
in *streams.In
out *streams.Out
err io.Writer
err *streams.Out
client client.APIClient
serverInfo ServerInfo
contentTrust bool
@@ -92,6 +92,8 @@ type DockerCli struct {
// this may be replaced by explicitly passing a context to functions that
// need it.
baseCtx context.Context
enableGlobalMeter, enableGlobalTracer bool
}
// DefaultVersion returns api.defaultVersion.
@@ -124,7 +126,7 @@ func (cli *DockerCli) Out() *streams.Out {
}
// Err returns the writer used for stderr
func (cli *DockerCli) Err() io.Writer {
func (cli *DockerCli) Err() *streams.Out {
return cli.err
}
@@ -184,9 +186,18 @@ func (cli *DockerCli) BuildKitEnabled() (bool, error) {
if _, ok := aliasMap["builder"]; ok {
return true, nil
}
// otherwise, assume BuildKit is enabled but
// not if wcow reported from server side
return cli.ServerInfo().OSType != "windows", nil
si := cli.ServerInfo()
if si.BuildkitVersion == types.BuilderBuildKit {
// The daemon advertised BuildKit as the preferred builder; this may
// be either a Linux daemon or a Windows daemon with experimental
// BuildKit support enabled.
return true, nil
}
// otherwise, assume BuildKit is enabled for Linux, but disabled for
// Windows / WCOW, which does not yet support BuildKit by default.
return si.OSType != "windows", nil
}
// HooksEnabled returns whether plugin hooks are enabled.
@@ -275,8 +286,12 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
}
// TODO(krissetto): pass ctx to the funcs instead of using this
cli.createGlobalMeterProvider(cli.baseCtx)
cli.createGlobalTracerProvider(cli.baseCtx)
if cli.enableGlobalMeter {
cli.createGlobalMeterProvider(cli.baseCtx)
}
if cli.enableGlobalTracer {
cli.createGlobalTracerProvider(cli.baseCtx)
}
return nil
}
@@ -315,7 +330,7 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {
if s == nil {
return docker.Endpoint{}, fmt.Errorf("no context store initialized")
return docker.Endpoint{}, errors.New("no context store initialized")
}
ctxMeta, err := s.GetMetadata(contextName)
if err != nil {
@@ -546,7 +561,7 @@ func getServerHost(hosts []string, tlsOptions *tlsconfig.Options) (string, error
case 1:
host = hosts[0]
default:
return "", errors.New("Please specify only one -H")
return "", errors.New("Specify only one -H")
}
return dopts.ParseHost(tlsOptions != nil, host)

View File

@@ -23,7 +23,7 @@ func WithStandardStreams() CLIOption {
stdin, stdout, stderr := term.StdStreams()
cli.in = streams.NewIn(stdin)
cli.out = streams.NewOut(stdout)
cli.err = stderr
cli.err = streams.NewOut(stderr)
return nil
}
}
@@ -40,8 +40,9 @@ func WithBaseContext(ctx context.Context) CLIOption {
// WithCombinedStreams uses the same stream for the output and error streams.
func WithCombinedStreams(combined io.Writer) CLIOption {
return func(cli *DockerCli) error {
cli.out = streams.NewOut(combined)
cli.err = combined
s := streams.NewOut(combined)
cli.out = s
cli.err = s
return nil
}
}
@@ -65,7 +66,7 @@ func WithOutputStream(out io.Writer) CLIOption {
// WithErrorStream sets a cli error stream.
func WithErrorStream(err io.Writer) CLIOption {
return func(cli *DockerCli) error {
cli.err = err
cli.err = streams.NewOut(err)
return nil
}
}

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package command

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package command

View File

@@ -1,51 +0,0 @@
package command
import (
"sync"
"github.com/docker/docker/api/types/events"
"github.com/sirupsen/logrus"
)
// EventHandler is abstract interface for user to customize
// own handle functions of each type of events
//
// Deprecated: EventHandler is no longer used, and will be removed in the next release.
type EventHandler interface {
Handle(action events.Action, h func(events.Message))
Watch(c <-chan events.Message)
}
// InitEventHandler initializes and returns an EventHandler
//
// Deprecated: InitEventHandler is no longer used, and will be removed in the next release.
func InitEventHandler() EventHandler {
return &eventHandler{handlers: make(map[events.Action]func(events.Message))}
}
type eventHandler struct {
handlers map[events.Action]func(events.Message)
mu sync.Mutex
}
func (w *eventHandler) Handle(action events.Action, h func(events.Message)) {
w.mu.Lock()
w.handlers[action] = h
w.mu.Unlock()
}
// Watch ranges over the passed in event chan and processes the events based on the
// handlers created for a given action.
// To stop watching, close the event chan.
func (w *eventHandler) Watch(c <-chan events.Message) {
for e := range c {
w.mu.Lock()
h, exists := w.handlers[e.Action]
w.mu.Unlock()
if !exists {
continue
}
logrus.Debugf("event handler: received event: %v", e)
go h(e)
}
}

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package formatter

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package formatter

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package formatter

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package formatter

View File

@@ -106,7 +106,7 @@ type Writer struct {
cell cell // current incomplete cell; cell.width is up to buf[pos] excluding ignored sections
endChar byte // terminating char of escaped sequence (Escape for escapes, '>', ';' for HTML tags/entities, or 0)
lines [][]cell // list of lines; each line is a list of cells
widths []int // list of column widths in runes - re-used during formatting
widths []int // list of column widths in runes - reused during formatting
}
// addLine adds a new line.
@@ -115,7 +115,7 @@ type Writer struct {
func (b *Writer) addLine(flushed bool) {
// Grow slice instead of appending,
// as that gives us an opportunity
// to re-use an existing []cell.
// to reuse an existing []cell.
if n := len(b.lines) + 1; n <= cap(b.lines) {
b.lines = b.lines[:n]
b.lines[n-1] = b.lines[n-1][:0]
@@ -159,7 +159,7 @@ func (b *Writer) reset() {
// - the sizes and widths of processed text are kept in the lines list
// which contains a list of cells for each line
// - the widths list is a temporary list with current widths used during
// formatting; it is kept in Writer because it's re-used
// formatting; it is kept in Writer because it's reused
//
// |<---------- size ---------->|
// | |

View File

@@ -2,6 +2,7 @@ package command
import (
"bufio"
"context"
"fmt"
"io"
"os"
@@ -10,6 +11,7 @@ import (
"github.com/distribution/reference"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/credentials"
configtypes "github.com/docker/cli/cli/config/types"
"github.com/docker/cli/cli/hints"
"github.com/docker/cli/cli/streams"
@@ -27,14 +29,21 @@ const patSuggest = "You can log in with your password or a Personal Access " +
// RegistryAuthenticationPrivilegedFunc returns a RequestPrivilegeFunc from the specified registry index info
// for the given command.
func RegistryAuthenticationPrivilegedFunc(cli Cli, index *registrytypes.IndexInfo, cmdName string) types.RequestPrivilegeFunc {
return func() (string, error) {
fmt.Fprintf(cli.Out(), "\nPlease login prior to %s:\n", cmdName)
return func(ctx context.Context) (string, error) {
fmt.Fprintf(cli.Out(), "\nLogin prior to %s:\n", cmdName)
indexServer := registry.GetAuthConfigKey(index)
isDefaultRegistry := indexServer == registry.IndexServer
authConfig, err := GetDefaultAuthConfig(cli.ConfigFile(), true, indexServer, isDefaultRegistry)
if err != nil {
fmt.Fprintf(cli.Err(), "Unable to retrieve stored credentials for %s, error: %s.\n", indexServer, err)
}
select {
case <-ctx.Done():
return "", ctx.Err()
default:
}
err = ConfigureAuth(cli, "", "", &authConfig, isDefaultRegistry)
if err != nil {
return "", err
@@ -63,7 +72,7 @@ func ResolveAuthConfig(cfg *configfile.ConfigFile, index *registrytypes.IndexInf
// If credentials for given serverAddress exists in the credential store, the configuration will be populated with values in it
func GetDefaultAuthConfig(cfg *configfile.ConfigFile, checkCredStore bool, serverAddress string, isDefaultRegistry bool) (registrytypes.AuthConfig, error) {
if !isDefaultRegistry {
serverAddress = registry.ConvertToHostname(serverAddress)
serverAddress = credentials.ConvertToHostname(serverAddress)
}
authconfig := configtypes.AuthConfig{}
var err error

View File

@@ -1,11 +1,10 @@
// FIXME(jsternberg): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package command
import (
"context"
"fmt"
"net/url"
"os"
"path"
@@ -85,7 +84,7 @@ func dockerExporterOTLPEndpoint(cli Cli) (endpoint string, secure bool) {
// needs the scheme to use the correct resolver.
//
// We'll just handle this in a special way and add the unix:// back to the endpoint.
endpoint = fmt.Sprintf("unix://%s", path.Join(u.Host, u.Path))
endpoint = "unix://" + path.Join(u.Host, u.Path)
case "https":
secure = true
fallthrough

View File

@@ -0,0 +1,25 @@
package command
// WithEnableGlobalMeterProvider configures the DockerCli to create a new
// MeterProvider from the initialized DockerCli struct, and set it as
// the global meter provider.
//
// WARNING: For internal use, don't depend on this.
func WithEnableGlobalMeterProvider() CLIOption {
return func(cli *DockerCli) error {
cli.enableGlobalMeter = true
return nil
}
}
// WithEnableGlobalTracerProvider configures the DockerCli to create a new
// TracerProvider from the initialized DockerCli struct, and set it as
// the global tracer provider.
//
// WARNING: For internal use, don't depend on this.
func WithEnableGlobalTracerProvider() CLIOption {
return func(cli *DockerCli) error {
cli.enableGlobalTracer = true
return nil
}
}

View File

@@ -7,7 +7,6 @@ import (
"time"
"github.com/docker/cli/cli/version"
"github.com/moby/term"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"go.opentelemetry.io/otel/attribute"
@@ -101,12 +100,10 @@ func startCobraCommandTimer(mp metric.MeterProvider, attrs []attribute.KeyValue)
}
func stdioAttributes(streams Streams) []attribute.KeyValue {
// we don't wrap stderr, but we do wrap in/out
_, stderrTty := term.GetFdInfo(streams.Err())
return []attribute.KeyValue{
attribute.Bool("command.stdin.isatty", streams.In().IsTerminal()),
attribute.Bool("command.stdout.isatty", streams.Out().IsTerminal()),
attribute.Bool("command.stderr.isatty", stderrTty),
attribute.Bool("command.stderr.isatty", streams.Err().IsTerminal()),
}
}

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package command
@@ -9,11 +9,9 @@ import (
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"runtime"
"strings"
"syscall"
"github.com/docker/cli/cli/streams"
"github.com/docker/docker/api/types/filters"
@@ -103,11 +101,6 @@ func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, m
result := make(chan bool)
// Catch the termination signal and exit the prompt gracefully.
// The caller is responsible for properly handling the termination.
notifyCtx, notifyCancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer notifyCancel()
go func() {
var res bool
scanner := bufio.NewScanner(ins)
@@ -121,8 +114,7 @@ func PromptForConfirmation(ctx context.Context, ins io.Reader, outs io.Writer, m
}()
select {
case <-notifyCtx.Done():
// print a newline on termination
case <-ctx.Done():
_, _ = fmt.Fprintln(outs, "")
return false, ErrPromptTerminated
case r := <-result:

View File

@@ -4,14 +4,15 @@ import (
"fmt"
"io"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/config/credentials"
"github.com/docker/cli/cli/config/types"
"github.com/docker/docker/pkg/homedir"
"github.com/pkg/errors"
)
@@ -42,12 +43,38 @@ func resetConfigDir() {
initConfigDir = new(sync.Once)
}
// getHomeDir returns the home directory of the current user with the help of
// environment variables depending on the target operating system.
// Returned path should be used with "path/filepath" to form new paths.
//
// On non-Windows platforms, it falls back to nss lookups, if the home
// directory cannot be obtained from environment-variables.
//
// If linking statically with cgo enabled against glibc, ensure the
// osusergo build tag is used.
//
// If needing to do nss lookups, do not disable cgo or set osusergo.
//
// getHomeDir is a copy of [pkg/homedir.Get] to prevent adding docker/docker
// as dependency for consumers that only need to read the config-file.
//
// [pkg/homedir.Get]: https://pkg.go.dev/github.com/docker/docker@v26.1.4+incompatible/pkg/homedir#Get
func getHomeDir() string {
home, _ := os.UserHomeDir()
if home == "" && runtime.GOOS != "windows" {
if u, err := user.Current(); err == nil {
return u.HomeDir
}
}
return home
}
// Dir returns the directory the configuration file is stored in
func Dir() string {
initConfigDir.Do(func() {
configDir = os.Getenv(EnvOverrideConfigDir)
if configDir == "" {
configDir = filepath.Join(homedir.Get(), configFileDir)
configDir = filepath.Join(getHomeDir(), configFileDir)
}
})
return configDir
@@ -75,7 +102,7 @@ func Path(p ...string) (string, error) {
}
// LoadFromReader is a convenience function that creates a ConfigFile object from
// a reader
// a reader. It returns an error if configData is malformed.
func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
configFile := configfile.ConfigFile{
AuthConfigs: make(map[string]types.AuthConfig),
@@ -84,8 +111,14 @@ func LoadFromReader(configData io.Reader) (*configfile.ConfigFile, error) {
return &configFile, err
}
// Load reads the configuration files in the given directory, and sets up
// the auth config information and returns values.
// Load reads the configuration file ([ConfigFileName]) from the given directory.
// If no directory is given, it uses the default [Dir]. A [*configfile.ConfigFile]
// is returned containing the contents of the configuration file, or a default
// struct if no configfile exists in the given location.
//
// Load returns an error if a configuration file exists in the given location,
// but cannot be read, or is malformed. Consumers must handle errors to prevent
// overwriting an existing configuration file.
func Load(configDir string) (*configfile.ConfigFile, error) {
if configDir == "" {
configDir = Dir()
@@ -100,29 +133,37 @@ func load(configDir string) (*configfile.ConfigFile, error) {
file, err := os.Open(filename)
if err != nil {
if os.IsNotExist(err) {
//
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
// It is OK for no configuration file to be present, in which
// case we return a default struct.
return configFile, nil
}
// if file is there but we can't stat it for any reason other
// than it doesn't exist then stop
return configFile, nil
// Any other error happening when failing to read the file must be returned.
return configFile, errors.Wrap(err, "loading config file")
}
defer file.Close()
err = configFile.LoadFromReader(file)
if err != nil {
err = errors.Wrap(err, filename)
err = errors.Wrapf(err, "loading config file: %s: ", filename)
}
return configFile, err
}
// LoadDefaultConfigFile attempts to load the default config file and returns
// an initialized ConfigFile struct if none is found.
// a reference to the ConfigFile struct. If none is found or when failing to load
// the configuration file, it initializes a default ConfigFile struct. If no
// credentials-store is set in the configuration file, it attempts to discover
// the default store to use for the current platform.
//
// Important: LoadDefaultConfigFile prints a warning to stderr when failing to
// load the configuration file, but otherwise ignores errors. Consumers should
// consider using [Load] (and [credentials.DetectDefaultStore]) to detect errors
// when updating the configuration file, to prevent discarding a (malformed)
// configuration file.
func LoadDefaultConfigFile(stderr io.Writer) *configfile.ConfigFile {
configFile, err := load(Dir())
if err != nil {
_, _ = fmt.Fprintf(stderr, "WARNING: Error loading config file: %v\n", err)
// FIXME(thaJeztah): we should not proceed here to prevent overwriting existing (but malformed) config files; see https://github.com/docker/cli/issues/5075
_, _ = fmt.Fprintln(stderr, "WARNING: Error", err)
}
if !configFile.ContainsAuth() {
configFile.CredentialsStore = credentials.DetectDefaultStore(configFile.CredentialsStore)

View File

@@ -1,6 +1,7 @@
package credentials
import (
"net/url"
"strings"
"github.com/docker/cli/cli/config/types"
@@ -68,14 +69,14 @@ func (c *fileStore) IsFileStore() bool {
// ConvertToHostname converts a registry url which has http|https prepended
// to just an hostname.
// Copied from github.com/docker/docker/registry.ConvertToHostname to reduce dependencies.
func ConvertToHostname(url string) string {
stripped := url
if strings.HasPrefix(url, "http://") {
stripped = strings.TrimPrefix(url, "http://")
} else if strings.HasPrefix(url, "https://") {
stripped = strings.TrimPrefix(url, "https://")
func ConvertToHostname(maybeURL string) string {
stripped := maybeURL
if strings.Contains(stripped, "://") {
u, err := url.Parse(stripped)
if err == nil && u.Hostname() != "" {
return u.Hostname()
}
}
hostName, _, _ := strings.Cut(stripped, "/")
return hostName
}

View File

@@ -149,7 +149,7 @@ func (c *commandConn) handleEOF(err error) error {
c.stderrMu.Lock()
stderr := c.stderr.String()
c.stderrMu.Unlock()
return errors.Errorf("command %v has exited with %v, please make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=%s", c.cmd.Args, werr, stderr)
return errors.Errorf("command %v has exited with %v, make sure the URL is valid, and Docker 18.09 or later is installed on the remote host: stderr=%s", c.cmd.Args, werr, stderr)
}
func ignorableCloseError(err error) bool {

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package store

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package store

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package store
@@ -14,7 +14,7 @@ type NamedTypeGetter struct {
typeGetter TypeGetter
}
// EndpointTypeGetter returns a NamedTypeGetter with the spcecified name and getter
// EndpointTypeGetter returns a NamedTypeGetter with the specified name and getter
func EndpointTypeGetter(name string, getter TypeGetter) NamedTypeGetter {
return NamedTypeGetter{
name: name,

View File

@@ -2,7 +2,6 @@ package store
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
@@ -162,7 +161,7 @@ func newNotFoundError(ref string) *notFoundError {
}
func (n *notFoundError) Error() string {
return fmt.Sprintf("No such manifest: %s", n.object)
return "No such manifest: " + n.object
}
// NotFound interface

View File

@@ -101,23 +101,23 @@ func (c *client) MountBlob(ctx context.Context, sourceRef reference.Canonical, t
func (c *client) PutManifest(ctx context.Context, ref reference.Named, manifest distribution.Manifest) (digest.Digest, error) {
repoEndpoint, err := newDefaultRepositoryEndpoint(ref, c.insecureRegistry)
if err != nil {
return digest.Digest(""), err
return "", err
}
repoEndpoint.actions = trust.ActionsPushAndPull
repo, err := c.getRepositoryForReference(ctx, ref, repoEndpoint)
if err != nil {
return digest.Digest(""), err
return "", err
}
manifestService, err := repo.Manifests(ctx)
if err != nil {
return digest.Digest(""), err
return "", err
}
_, opts, err := getManifestOptionsFromReference(ref)
if err != nil {
return digest.Digest(""), err
return "", err
}
dgst, err := manifestService.Put(ctx, manifest, opts...)

View File

@@ -1,7 +1,6 @@
package client
import (
"fmt"
"net"
"net/http"
"time"
@@ -83,7 +82,6 @@ func getHTTPTransport(authConfig registrytypes.AuthConfig, endpoint registry.API
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: endpoint.TLSConfig,
@@ -126,7 +124,7 @@ type existingTokenHandler struct {
}
func (th *existingTokenHandler) AuthorizeRequest(req *http.Request, _ map[string]string) error {
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", th.token))
req.Header.Set("Authorization", "Bearer "+th.token)
return nil
}

View File

@@ -270,7 +270,7 @@ func (c *client) iterateEndpoints(ctx context.Context, namedRef reference.Named,
return newNotFoundError(namedRef.String())
}
// allEndpoints returns a list of endpoints ordered by priority (v2, https, v1).
// allEndpoints returns a list of endpoints ordered by priority (v2, http).
func allEndpoints(namedRef reference.Named, insecure bool) ([]registry.APIEndpoint, error) {
repoInfo, err := registry.ParseRepositoryInfo(namedRef)
if err != nil {

View File

@@ -119,7 +119,6 @@ func GetNotaryRepository(in io.Reader, out io.Writer, userAgent string, repoInfo
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
TLSClientConfig: cfg,

View File

@@ -2,6 +2,7 @@ package opts
import (
"encoding/csv"
"errors"
"fmt"
"os"
"strconv"
@@ -68,7 +69,7 @@ func (o *ConfigOpt) Set(value string) error {
}
if options.ConfigName == "" {
return fmt.Errorf("source is required")
return errors.New("source is required")
}
if options.File.Name == "" {
options.File.Name = options.ConfigName

View File

@@ -18,7 +18,7 @@ type ErrBadKey struct {
}
func (e ErrBadKey) Error() string {
return fmt.Sprintf("poorly formatted environment: %s", e.msg)
return "poorly formatted environment: " + e.msg
}
func parseKeyValueFile(filename string, emptyFn func(string) (string, bool)) ([]string, error) {

View File

@@ -165,11 +165,11 @@ func (m *MountOpt) Set(value string) error {
}
if mount.Type == "" {
return fmt.Errorf("type is required")
return errors.New("type is required")
}
if mount.Target == "" {
return fmt.Errorf("target is required")
return errors.New("target is required")
}
if mount.VolumeOptions != nil && mount.Type != mounttypes.TypeVolume {

View File

@@ -2,6 +2,7 @@ package opts
import (
"encoding/csv"
"errors"
"fmt"
"regexp"
"strings"
@@ -83,11 +84,11 @@ func (n *NetworkOpt) Set(value string) error { //nolint:gocyclo
}
netOpt.DriverOpts[key] = val
default:
return fmt.Errorf("invalid field key %s", key)
return errors.New("invalid field key " + key)
}
}
if len(netOpt.Target) == 0 {
return fmt.Errorf("network name/id is not specified")
return errors.New("network name/id is not specified")
}
} else {
netOpt.Target = value
@@ -126,7 +127,7 @@ func parseDriverOpt(driverOpt string) (string, string, error) {
// TODO(thaJeztah): should value be converted to lowercase as well, or only the key?
key, value, ok := strings.Cut(strings.ToLower(driverOpt), "=")
if !ok || key == "" {
return "", "", fmt.Errorf("invalid key value pair format in driver options")
return "", "", errors.New("invalid key value pair format in driver options")
}
key = strings.TrimSpace(key)
value = strings.TrimSpace(value)

View File

@@ -401,7 +401,7 @@ func ParseCPUs(value string) (int64, error) {
}
nano := cpu.Mul(cpu, big.NewRat(1e9, 1))
if !nano.IsInt() {
return 0, fmt.Errorf("value is too precise")
return 0, errors.New("value is too precise")
}
return nano.Num().Int64(), nil
}
@@ -409,14 +409,14 @@ func ParseCPUs(value string) (int64, error) {
// ParseLink parses and validates the specified string as a link format (name:alias)
func ParseLink(val string) (string, string, error) {
if val == "" {
return "", "", fmt.Errorf("empty string specified for links")
return "", "", errors.New("empty string specified for links")
}
// We expect two parts, but restrict to three to allow detecting invalid formats.
arr := strings.SplitN(val, ":", 3)
// TODO(thaJeztah): clean up this logic!!
if len(arr) > 2 {
return "", "", fmt.Errorf("bad format for links: %s", val)
return "", "", errors.New("bad format for links: " + val)
}
// TODO(thaJeztah): this should trim the "/" prefix as well??
if len(arr) == 1 {

View File

@@ -1,7 +1,7 @@
package opts
import (
"fmt"
"errors"
"os"
"strconv"
"strings"
@@ -81,12 +81,12 @@ func ParseRestartPolicy(policy string) (container.RestartPolicy, error) {
p := container.RestartPolicy{}
k, v, ok := strings.Cut(policy, ":")
if ok && k == "" {
return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: no policy provided before colon")
return container.RestartPolicy{}, errors.New("invalid restart policy format: no policy provided before colon")
}
if v != "" {
count, err := strconv.Atoi(v)
if err != nil {
return container.RestartPolicy{}, fmt.Errorf("invalid restart policy format: maximum retry count must be an integer")
return container.RestartPolicy{}, errors.New("invalid restart policy format: maximum retry count must be an integer")
}
p.MaximumRetryCount = count
}

View File

@@ -2,6 +2,7 @@ package opts
import (
"encoding/csv"
"errors"
"fmt"
"net"
"regexp"
@@ -102,7 +103,7 @@ func (p *PortOpt) Set(value string) error {
for _, portBindings := range portBindingMap {
for _, portBinding := range portBindings {
if portBinding.HostIP != "" {
return fmt.Errorf("hostip is not supported")
return errors.New("hostip is not supported")
}
}
}

View File

@@ -2,6 +2,7 @@ package opts
import (
"encoding/csv"
"errors"
"fmt"
"os"
"strconv"
@@ -62,12 +63,12 @@ func (o *SecretOpt) Set(value string) error {
options.File.Mode = os.FileMode(m)
default:
return fmt.Errorf("invalid field in secret request: %s", key)
return errors.New("invalid field in secret request: " + key)
}
}
if options.SecretName == "" {
return fmt.Errorf("source is required")
return errors.New("source is required")
}
if options.File.Name == "" {
options.File.Name = options.SecretName

View File

@@ -4,24 +4,27 @@ import (
"fmt"
"sort"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-units"
)
// UlimitOpt defines a map of Ulimits
type UlimitOpt struct {
values *map[string]*units.Ulimit
values *map[string]*container.Ulimit
}
// NewUlimitOpt creates a new UlimitOpt. Ulimits are not validated.
func NewUlimitOpt(ref *map[string]*units.Ulimit) *UlimitOpt {
func NewUlimitOpt(ref *map[string]*container.Ulimit) *UlimitOpt {
// TODO(thaJeztah): why do we need a map with pointers here?
if ref == nil {
ref = &map[string]*units.Ulimit{}
ref = &map[string]*container.Ulimit{}
}
return &UlimitOpt{ref}
}
// Set validates a Ulimit and sets its name as a key in UlimitOpt
func (o *UlimitOpt) Set(val string) error {
// FIXME(thaJeztah): these functions also need to be moved over from go-units.
l, err := units.ParseUlimit(val)
if err != nil {
return err
@@ -43,8 +46,8 @@ func (o *UlimitOpt) String() string {
}
// GetList returns a slice of pointers to Ulimits. Values are sorted by name.
func (o *UlimitOpt) GetList() []*units.Ulimit {
ulimits := make([]*units.Ulimit, 0, len(*o.values))
func (o *UlimitOpt) GetList() []*container.Ulimit {
ulimits := make([]*container.Ulimit, 0, len(*o.values))
for _, v := range *o.values {
ulimits = append(ulimits, v)
}

View File

@@ -1,5 +1,5 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.19
//go:build go1.21
package templates