Merge pull request #46887 from thaJeztah/minimum_api_version
daemon: raise default minimum API version to v1.24
This commit is contained in:
commit
6af9204938
11 changed files with 138 additions and 24 deletions
|
@ -1,6 +0,0 @@
|
|||
//go:build !windows
|
||||
|
||||
package api // import "github.com/docker/docker/api"
|
||||
|
||||
// MinVersion represents Minimum REST API version supported
|
||||
const MinVersion = "1.12"
|
|
@ -1,8 +0,0 @@
|
|||
package api // import "github.com/docker/docker/api"
|
||||
|
||||
// MinVersion represents Minimum REST API version supported
|
||||
// Technically the first daemon API version released on Windows is v1.25 in
|
||||
// engine version 1.13. However, some clients are explicitly using downlevel
|
||||
// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive.
|
||||
// Hence also allowing 1.24 on Windows.
|
||||
const MinVersion string = "1.24"
|
|
@ -15,7 +15,8 @@ import (
|
|||
func TestMiddlewares(t *testing.T) {
|
||||
srv := &Server{}
|
||||
|
||||
srv.UseMiddleware(middleware.NewVersionMiddleware("0.1omega2", api.DefaultVersion, api.MinVersion))
|
||||
const apiMinVersion = "1.12"
|
||||
srv.UseMiddleware(middleware.NewVersionMiddleware("0.1omega2", api.DefaultVersion, apiMinVersion))
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, "/containers/json", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
|
|
@ -90,6 +90,13 @@ import (
|
|||
// [Go stdlib]: https://github.com/golang/go/blob/6244b1946bc2101b01955468f1be502dbadd6807/src/net/http/transport.go#L558-L569
|
||||
const DummyHost = "api.moby.localhost"
|
||||
|
||||
// fallbackAPIVersion is the version to fallback to if API-version negotiation
|
||||
// fails. This version is the highest version of the API before API-version
|
||||
// negotiation was introduced. If negotiation fails (or no API version was
|
||||
// included in the API response), we assume the API server uses the most
|
||||
// recent version before negotiation was introduced.
|
||||
const fallbackAPIVersion = "1.24"
|
||||
|
||||
// Client is the API client that performs all operations
|
||||
// against a docker server.
|
||||
type Client struct {
|
||||
|
@ -329,7 +336,7 @@ func (cli *Client) NegotiateAPIVersionPing(pingResponse types.Ping) {
|
|||
func (cli *Client) negotiateAPIVersionPing(pingResponse types.Ping) {
|
||||
// default to the latest version before versioning headers existed
|
||||
if pingResponse.APIVersion == "" {
|
||||
pingResponse.APIVersion = "1.24"
|
||||
pingResponse.APIVersion = fallbackAPIVersion
|
||||
}
|
||||
|
||||
// if the client is not initialized with a version, start with the latest supported version
|
||||
|
|
|
@ -520,6 +520,20 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
|
|||
conf.LogLevel = opts.LogLevel
|
||||
conf.LogFormat = log.OutputFormat(opts.LogFormat)
|
||||
|
||||
// The DOCKER_MIN_API_VERSION env-var allows overriding the minimum API
|
||||
// version provided by the daemon within constraints of the minimum and
|
||||
// maximum (current) supported API versions.
|
||||
//
|
||||
// API versions older than [config.defaultMinAPIVersion] are deprecated and
|
||||
// to be removed in a future release. The "DOCKER_MIN_API_VERSION" env-var
|
||||
// should only be used for exceptional cases.
|
||||
if ver := os.Getenv("DOCKER_MIN_API_VERSION"); ver != "" {
|
||||
if err := config.ValidateMinAPIVersion(ver); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid DOCKER_MIN_API_VERSION")
|
||||
}
|
||||
conf.MinAPIVersion = ver
|
||||
}
|
||||
|
||||
if flags.Changed(FlagTLS) {
|
||||
conf.TLS = &opts.TLS
|
||||
}
|
||||
|
@ -689,7 +703,7 @@ func initMiddlewares(s *apiserver.Server, cfg *config.Config, pluginStore plugin
|
|||
exp := middleware.NewExperimentalMiddleware(cfg.Experimental)
|
||||
s.UseMiddleware(exp)
|
||||
|
||||
vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, api.MinVersion)
|
||||
vm := middleware.NewVersionMiddleware(v, api.DefaultVersion, cfg.MinAPIVersion)
|
||||
s.UseMiddleware(vm)
|
||||
|
||||
if cfg.CorsHeaders != "" {
|
||||
|
|
|
@ -10,16 +10,17 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/pflag"
|
||||
"golang.org/x/text/encoding"
|
||||
"golang.org/x/text/encoding/unicode"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -53,7 +54,11 @@ const (
|
|||
DefaultContainersNamespace = "moby"
|
||||
// DefaultPluginNamespace is the name of the default containerd namespace used for plugins.
|
||||
DefaultPluginNamespace = "plugins.moby"
|
||||
|
||||
// defaultMinAPIVersion is the minimum API version supported by the API.
|
||||
// This version can be overridden through the "DOCKER_MIN_API_VERSION"
|
||||
// environment variable. The minimum allowed version is determined
|
||||
// by [minAPIVersion].
|
||||
defaultMinAPIVersion = "1.24"
|
||||
// SeccompProfileDefault is the built-in default seccomp profile.
|
||||
SeccompProfileDefault = "builtin"
|
||||
// SeccompProfileUnconfined is a special profile name for seccomp to use an
|
||||
|
@ -247,6 +252,17 @@ type CommonConfig struct {
|
|||
|
||||
// CDISpecDirs is a list of directories in which CDI specifications can be found.
|
||||
CDISpecDirs []string `json:"cdi-spec-dirs,omitempty"`
|
||||
|
||||
// The minimum API version provided by the daemon. Defaults to [defaultMinAPIVersion].
|
||||
//
|
||||
// The DOCKER_MIN_API_VERSION allows overriding the minimum API version within
|
||||
// constraints of the minimum and maximum (current) supported API versions.
|
||||
//
|
||||
// API versions older than [defaultMinAPIVersion] are deprecated and
|
||||
// to be removed in a future release. The "DOCKER_MIN_API_VERSION" env
|
||||
// var should only be used for exceptional cases, and the MinAPIVersion
|
||||
// field is therefore not included in the JSON representation.
|
||||
MinAPIVersion string `json:"-"`
|
||||
}
|
||||
|
||||
// Proxies holds the proxies that are configured for the daemon.
|
||||
|
@ -290,6 +306,7 @@ func New() (*Config, error) {
|
|||
ContainerdNamespace: DefaultContainersNamespace,
|
||||
ContainerdPluginNamespace: DefaultPluginNamespace,
|
||||
DefaultRuntime: StockRuntimeName,
|
||||
MinAPIVersion: defaultMinAPIVersion,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -583,6 +600,25 @@ func findConfigurationConflicts(config map[string]interface{}, flags *pflag.Flag
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidateMinAPIVersion verifies if the given API version is within the
|
||||
// range supported by the daemon. It is used to validate a custom minimum
|
||||
// API version set through DOCKER_MIN_API_VERSION.
|
||||
func ValidateMinAPIVersion(ver string) error {
|
||||
if ver == "" {
|
||||
return errors.New(`value is empty`)
|
||||
}
|
||||
if strings.EqualFold(ver[0:1], "v") {
|
||||
return errors.New(`API version must be provided without "v" prefix`)
|
||||
}
|
||||
if versions.LessThan(ver, minAPIVersion) {
|
||||
return errors.Errorf(`minimum supported API version is %s: %s`, minAPIVersion, ver)
|
||||
}
|
||||
if versions.GreaterThan(ver, api.DefaultVersion) {
|
||||
return errors.Errorf(`maximum supported API version is %s: %s`, api.DefaultVersion, ver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate validates some specific configs.
|
||||
// such as config.DNS, config.Labels, config.DNSSearch,
|
||||
// as well as config.MaxConcurrentDownloads, config.MaxConcurrentUploads and config.MaxDownloadAttempts.
|
||||
|
|
|
@ -29,6 +29,9 @@ const (
|
|||
// StockRuntimeName is the reserved name/alias used to represent the
|
||||
// OCI runtime being shipped with the docker daemon package.
|
||||
StockRuntimeName = "runc"
|
||||
|
||||
// minAPIVersion represents Minimum REST API version supported
|
||||
minAPIVersion = "1.12"
|
||||
)
|
||||
|
||||
// BridgeConfig stores all the parameters for both the bridge driver and the default bridge network.
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/libnetwork/ipamutils"
|
||||
"github.com/docker/docker/opts"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
@ -502,6 +503,62 @@ func TestValidateConfiguration(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestValidateMinAPIVersion(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
doc string
|
||||
input string
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
doc: "empty",
|
||||
expectedErr: "value is empty",
|
||||
},
|
||||
{
|
||||
doc: "with prefix",
|
||||
input: "v1.43",
|
||||
expectedErr: `API version must be provided without "v" prefix`,
|
||||
},
|
||||
{
|
||||
doc: "major only",
|
||||
input: "1",
|
||||
expectedErr: `minimum supported API version is`,
|
||||
},
|
||||
{
|
||||
doc: "too low",
|
||||
input: "1.0",
|
||||
expectedErr: `minimum supported API version is`,
|
||||
},
|
||||
{
|
||||
doc: "minor too high",
|
||||
input: "1.99",
|
||||
expectedErr: `maximum supported API version is`,
|
||||
},
|
||||
{
|
||||
doc: "major too high",
|
||||
input: "9.0",
|
||||
expectedErr: `maximum supported API version is`,
|
||||
},
|
||||
{
|
||||
doc: "current version",
|
||||
input: api.DefaultVersion,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
err := ValidateMinAPIVersion(tc.input)
|
||||
if tc.expectedErr != "" {
|
||||
assert.Check(t, is.ErrorContains(err, tc.expectedErr))
|
||||
} else {
|
||||
assert.Check(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestConfigInvalidDNS(t *testing.T) {
|
||||
tests := []struct {
|
||||
doc string
|
||||
|
|
|
@ -13,6 +13,13 @@ const (
|
|||
// default value. On Windows keep this empty so the value is auto-detected
|
||||
// based on other options.
|
||||
StockRuntimeName = ""
|
||||
|
||||
// minAPIVersion represents Minimum REST API version supported
|
||||
// Technically the first daemon API version released on Windows is v1.25 in
|
||||
// engine version 1.13. However, some clients are explicitly using downlevel
|
||||
// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive.
|
||||
// Hence also allowing 1.24 on Windows.
|
||||
minAPIVersion string = "1.24"
|
||||
)
|
||||
|
||||
// BridgeConfig is meant to store all the parameters for both the bridge driver and the default bridge network. On
|
||||
|
|
|
@ -113,7 +113,7 @@ func (daemon *Daemon) SystemVersion(ctx context.Context) (types.Version, error)
|
|||
Details: map[string]string{
|
||||
"GitCommit": dockerversion.GitCommit,
|
||||
"ApiVersion": api.DefaultVersion,
|
||||
"MinAPIVersion": api.MinVersion,
|
||||
"MinAPIVersion": cfg.MinAPIVersion,
|
||||
"GoVersion": runtime.Version(),
|
||||
"Os": runtime.GOOS,
|
||||
"Arch": runtime.GOARCH,
|
||||
|
@ -128,7 +128,7 @@ func (daemon *Daemon) SystemVersion(ctx context.Context) (types.Version, error)
|
|||
Version: dockerversion.Version,
|
||||
GitCommit: dockerversion.GitCommit,
|
||||
APIVersion: api.DefaultVersion,
|
||||
MinAPIVersion: api.MinVersion,
|
||||
MinAPIVersion: cfg.MinAPIVersion,
|
||||
GoVersion: runtime.Version(),
|
||||
Os: runtime.GOOS,
|
||||
Arch: runtime.GOARCH,
|
||||
|
|
|
@ -46,6 +46,9 @@ export DOCKER_ALLOW_SCHEMA1_PUSH_DONOTUSE=1
|
|||
export DOCKER_GRAPHDRIVER=${DOCKER_GRAPHDRIVER:-vfs}
|
||||
export DOCKER_USERLANDPROXY=${DOCKER_USERLANDPROXY:-true}
|
||||
|
||||
# Allow testing old API versions
|
||||
export DOCKER_MIN_API_VERSION=1.12
|
||||
|
||||
# example usage: DOCKER_STORAGE_OPTS="dm.basesize=20G,dm.loopdatasize=200G"
|
||||
storage_params=""
|
||||
if [ -n "$DOCKER_STORAGE_OPTS" ]; then
|
||||
|
|
Loading…
Add table
Reference in a new issue