add //go:build directives to prevent downgrading to go1.16 language
This is a follow-up to 0e73168b7e6d1d029d76d05b843b1aaec46739a8
This repository is not yet a module (i.e., does not have a `go.mod`). This
is not problematic when building the code in GOPATH or "vendor" mode, but
when using the code as a module-dependency (in module-mode), different semantics
are applied since Go1.21, which switches Go _language versions_ on a per-module,
per-package, or even per-file base.
A condensed summary of that logic [is as follows][1]:
- For modules that have a go.mod containing a go version directive; that
version is considered a minimum _required_ version (starting with the
go1.19.13 and go1.20.8 patch releases: before those, it was only a
recommendation).
- For dependencies that don't have a go.mod (not a module), go language
version go1.16 is assumed.
- Likewise, for modules that have a go.mod, but the file does not have a
go version directive, go language version go1.16 is assumed.
- If a go.work file is present, but does not have a go version directive,
language version go1.17 is assumed.
When switching language versions, Go _downgrades_ the language version,
which means that language features (such as generics, and `any`) are not
available, and compilation fails. For example:
# github.com/docker/cli/cli/context/store
/go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/storeconfig.go:6:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
/go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/store.go:74:12: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
Note that these fallbacks are per-module, per-package, and can even be
per-file, so _(indirect) dependencies_ can still use modern language
features, as long as their respective go.mod has a version specified.
Unfortunately, these failures do not occur when building locally (using
vendor / GOPATH mode), but will affect consumers of the module.
Obviously, this situation is not ideal, and the ultimate solution is to
move to go modules (add a go.mod), but this comes with a non-insignificant
risk in other areas (due to our complex dependency tree).
We can revert to using go1.16 language features only, but this may be
limiting, and may still be problematic when (e.g.) matching signatures
of dependencies.
There is an escape hatch: adding a `//go:build` directive to files that
make use of go language features. From the [go toolchain docs][2]:
> The go line for each module sets the language version the compiler enforces
> when compiling packages in that module. The language version can be changed
> on a per-file basis by using a build constraint.
>
> For example, a module containing code that uses the Go 1.21 language version
> should have a `go.mod` file with a go line such as `go 1.21` or `go 1.21.3`.
> If a specific source file should be compiled only when using a newer Go
> toolchain, adding `//go:build go1.22` to that source file both ensures that
> only Go 1.22 and newer toolchains will compile the file and also changes
> the language version in that file to Go 1.22.
This patch adds `//go:build` directives to those files using recent additions
to the language. It's currently using go1.19 as version to match the version
in our "vendor.mod", but we can consider being more permissive ("any" requires
go1.18 or up), or more "optimistic" (force go1.21, which is the version we
currently use to build).
For completeness sake, note that any file _without_ a `//go:build` directive
will continue to use go1.16 language version when used as a module.
[1]: https://github.com/golang/go/blob/58c28ba286dd0e98fe4cca80f5d64bbcb824a685/src/cmd/go/internal/gover/version.go#L9-L56
[2]; https://go.dev/doc/toolchain#:~:text=The%20go%20line%20for,file%20to%20Go%201.22
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 70216b662dc440faaebab531deb35f0f0c633d17)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-14 07:51:57 -05:00
|
|
|
// 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
|
|
|
|
|
2018-01-29 16:18:43 -05:00
|
|
|
package loader
|
|
|
|
|
|
|
|
import (
|
2018-02-27 10:54:36 -05:00
|
|
|
"fmt"
|
|
|
|
"path/filepath"
|
2018-01-29 16:18:43 -05:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/docker/cli/cli/compose/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func fullExampleConfig(workingDir, homeDir string) *types.Config {
|
|
|
|
return &types.Config{
|
2022-06-06 09:58:32 -04:00
|
|
|
Version: "3.10",
|
2018-01-29 16:18:43 -05:00
|
|
|
Services: services(workingDir, homeDir),
|
|
|
|
Networks: networks(),
|
|
|
|
Volumes: volumes(),
|
2018-06-25 04:51:56 -04:00
|
|
|
Configs: configs(workingDir),
|
|
|
|
Secrets: secrets(workingDir),
|
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-foo": "bar",
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-nested": map[string]interface{}{
|
|
|
|
"foo": "bar",
|
|
|
|
"bar": "baz",
|
|
|
|
},
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func services(workingDir, homeDir string) []types.ServiceConfig {
|
|
|
|
return []types.ServiceConfig{
|
|
|
|
{
|
|
|
|
Name: "foo",
|
|
|
|
|
|
|
|
Build: types.BuildConfig{
|
|
|
|
Context: "./dir",
|
|
|
|
Dockerfile: "Dockerfile",
|
|
|
|
Args: map[string]*string{"foo": strPtr("bar")},
|
|
|
|
Target: "foo",
|
|
|
|
Network: "foo",
|
|
|
|
CacheFrom: []string{"foo", "bar"},
|
2020-05-10 13:40:14 -04:00
|
|
|
ExtraHosts: types.HostsList{
|
|
|
|
"ipv4.example.com:127.0.0.1",
|
|
|
|
"ipv6.example.com:::1",
|
|
|
|
},
|
|
|
|
Labels: map[string]string{"FOO": "BAR"},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
2018-06-01 08:16:18 -04:00
|
|
|
CapAdd: []string{"ALL"},
|
|
|
|
CapDrop: []string{"NET_ADMIN", "SYS_ADMIN"},
|
|
|
|
CgroupParent: "m-executor-abcd",
|
|
|
|
Command: []string{"bundle", "exec", "thin", "-p", "3000"},
|
|
|
|
Configs: []types.ServiceConfigObjConfig{
|
|
|
|
{
|
|
|
|
Source: "config1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Source: "config2",
|
|
|
|
Target: "/my_config",
|
|
|
|
UID: "103",
|
|
|
|
GID: "103",
|
2022-09-30 13:13:22 -04:00
|
|
|
Mode: uint32Ptr(0o440),
|
2018-06-01 08:16:18 -04:00
|
|
|
},
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
ContainerName: "my-web-container",
|
|
|
|
DependsOn: []string{"db", "redis"},
|
|
|
|
Deploy: types.DeployConfig{
|
|
|
|
Mode: "replicated",
|
|
|
|
Replicas: uint64Ptr(6),
|
|
|
|
Labels: map[string]string{"FOO": "BAR"},
|
2018-05-29 05:37:51 -04:00
|
|
|
RollbackConfig: &types.UpdateConfig{
|
|
|
|
Parallelism: uint64Ptr(3),
|
2018-08-29 17:29:39 -04:00
|
|
|
Delay: types.Duration(10 * time.Second),
|
2018-05-29 05:37:51 -04:00
|
|
|
FailureAction: "continue",
|
2018-08-29 17:29:39 -04:00
|
|
|
Monitor: types.Duration(60 * time.Second),
|
2018-05-29 05:37:51 -04:00
|
|
|
MaxFailureRatio: 0.3,
|
|
|
|
Order: "start-first",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
UpdateConfig: &types.UpdateConfig{
|
|
|
|
Parallelism: uint64Ptr(3),
|
2018-08-29 17:29:39 -04:00
|
|
|
Delay: types.Duration(10 * time.Second),
|
2018-01-29 16:18:43 -05:00
|
|
|
FailureAction: "continue",
|
2018-08-29 17:29:39 -04:00
|
|
|
Monitor: types.Duration(60 * time.Second),
|
2018-01-29 16:18:43 -05:00
|
|
|
MaxFailureRatio: 0.3,
|
|
|
|
Order: "start-first",
|
|
|
|
},
|
|
|
|
Resources: types.Resources{
|
2020-05-09 17:08:42 -04:00
|
|
|
Limits: &types.ResourceLimit{
|
2018-01-29 16:18:43 -05:00
|
|
|
NanoCPUs: "0.001",
|
|
|
|
MemoryBytes: 50 * 1024 * 1024,
|
2020-05-09 17:08:42 -04:00
|
|
|
Pids: 100,
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
|
|
|
Reservations: &types.Resource{
|
|
|
|
NanoCPUs: "0.0001",
|
|
|
|
MemoryBytes: 20 * 1024 * 1024,
|
|
|
|
GenericResources: []types.GenericResource{
|
|
|
|
{
|
|
|
|
DiscreteResourceSpec: &types.DiscreteGenericResource{
|
|
|
|
Kind: "gpu",
|
|
|
|
Value: 2,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
DiscreteResourceSpec: &types.DiscreteGenericResource{
|
|
|
|
Kind: "ssd",
|
|
|
|
Value: 1,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
RestartPolicy: &types.RestartPolicy{
|
|
|
|
Condition: "on-failure",
|
|
|
|
Delay: durationPtr(5 * time.Second),
|
|
|
|
MaxAttempts: uint64Ptr(3),
|
|
|
|
Window: durationPtr(2 * time.Minute),
|
|
|
|
},
|
|
|
|
Placement: types.Placement{
|
|
|
|
Constraints: []string{"node=foo"},
|
2018-09-30 10:04:35 -04:00
|
|
|
MaxReplicas: uint64(5),
|
2018-01-29 16:18:43 -05:00
|
|
|
Preferences: []types.PlacementPreferences{
|
|
|
|
{
|
|
|
|
Spread: "node.labels.az",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
EndpointMode: "dnsrr",
|
|
|
|
},
|
|
|
|
Devices: []string{"/dev/ttyUSB0:/dev/ttyUSB0"},
|
|
|
|
DNS: []string{"8.8.8.8", "9.9.9.9"},
|
|
|
|
DNSSearch: []string{"dc1.example.com", "dc2.example.com"},
|
|
|
|
DomainName: "foo.com",
|
|
|
|
Entrypoint: []string{"/code/entrypoint.sh", "-p", "3000"},
|
|
|
|
Environment: map[string]*string{
|
|
|
|
"FOO": strPtr("foo_from_env_file"),
|
|
|
|
"BAR": strPtr("bar_from_env_file_2"),
|
|
|
|
"BAZ": strPtr("baz_from_service_def"),
|
|
|
|
"QUX": strPtr("qux_from_environment"),
|
|
|
|
},
|
|
|
|
EnvFile: []string{
|
|
|
|
"./example1.env",
|
|
|
|
"./example2.env",
|
|
|
|
},
|
|
|
|
Expose: []string{"3000", "8000"},
|
|
|
|
ExternalLinks: []string{
|
|
|
|
"redis_1",
|
|
|
|
"project_db_1:mysql",
|
|
|
|
"project_db_1:postgresql",
|
|
|
|
},
|
|
|
|
ExtraHosts: []string{
|
|
|
|
"somehost:162.242.195.82",
|
|
|
|
"otherhost:50.31.209.229",
|
2020-04-15 03:13:11 -04:00
|
|
|
"host.docker.internal:host-gateway",
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
2018-06-25 04:51:56 -04:00
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
HealthCheck: &types.HealthCheckConfig{
|
|
|
|
Test: types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
|
|
|
|
Interval: durationPtr(10 * time.Second),
|
|
|
|
Timeout: durationPtr(1 * time.Second),
|
|
|
|
Retries: uint64Ptr(5),
|
|
|
|
StartPeriod: durationPtr(15 * time.Second),
|
|
|
|
},
|
|
|
|
Hostname: "foo",
|
|
|
|
Image: "redis",
|
|
|
|
Ipc: "host",
|
|
|
|
Labels: map[string]string{
|
|
|
|
"com.example.description": "Accounting webapp",
|
|
|
|
"com.example.number": "42",
|
|
|
|
"com.example.empty-label": "",
|
|
|
|
},
|
|
|
|
Links: []string{
|
|
|
|
"db",
|
|
|
|
"db:database",
|
|
|
|
"redis",
|
|
|
|
},
|
|
|
|
Logging: &types.LoggingConfig{
|
|
|
|
Driver: "syslog",
|
|
|
|
Options: map[string]string{
|
|
|
|
"syslog-address": "tcp://192.168.0.42:123",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
MacAddress: "02:42:ac:11:65:43",
|
|
|
|
NetworkMode: "container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b",
|
|
|
|
Networks: map[string]*types.ServiceNetworkConfig{
|
|
|
|
"some-network": {
|
|
|
|
Aliases: []string{"alias1", "alias3"},
|
|
|
|
Ipv4Address: "",
|
|
|
|
Ipv6Address: "",
|
|
|
|
},
|
|
|
|
"other-network": {
|
|
|
|
Ipv4Address: "172.16.238.10",
|
|
|
|
Ipv6Address: "2001:3984:3989::10",
|
|
|
|
},
|
|
|
|
"other-other-network": nil,
|
|
|
|
},
|
|
|
|
Pid: "host",
|
|
|
|
Ports: []types.ServicePortConfig{
|
2022-11-16 16:21:16 -05:00
|
|
|
// "3000",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3001,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3002,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3003,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3004,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 3005,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
2022-11-16 16:21:16 -05:00
|
|
|
// "8000:8000",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 8000,
|
|
|
|
Published: 8000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
2022-11-16 16:21:16 -05:00
|
|
|
// "9090-9091:8080-8081",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 8080,
|
|
|
|
Published: 9090,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 8081,
|
|
|
|
Published: 9091,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
2022-11-16 16:21:16 -05:00
|
|
|
// "49100:22",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 22,
|
|
|
|
Published: 49100,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
2022-11-16 16:21:16 -05:00
|
|
|
// "127.0.0.1:8001:8001",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 8001,
|
|
|
|
Published: 8001,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
2022-11-16 16:21:16 -05:00
|
|
|
// "127.0.0.1:5000-5010:5000-5010",
|
2018-01-29 16:18:43 -05:00
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5000,
|
|
|
|
Published: 5000,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5001,
|
|
|
|
Published: 5001,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5002,
|
|
|
|
Published: 5002,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5003,
|
|
|
|
Published: 5003,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5004,
|
|
|
|
Published: 5004,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5005,
|
|
|
|
Published: 5005,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5006,
|
|
|
|
Published: 5006,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5007,
|
|
|
|
Published: 5007,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5008,
|
|
|
|
Published: 5008,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5009,
|
|
|
|
Published: 5009,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Mode: "ingress",
|
|
|
|
Target: 5010,
|
|
|
|
Published: 5010,
|
|
|
|
Protocol: "tcp",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Privileged: true,
|
|
|
|
ReadOnly: true,
|
|
|
|
Restart: "always",
|
2018-06-01 08:16:18 -04:00
|
|
|
Secrets: []types.ServiceSecretConfig{
|
|
|
|
{
|
|
|
|
Source: "secret1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Source: "secret2",
|
|
|
|
Target: "my_secret",
|
|
|
|
UID: "103",
|
|
|
|
GID: "103",
|
2022-09-30 13:13:22 -04:00
|
|
|
Mode: uint32Ptr(0o440),
|
2018-06-01 08:16:18 -04:00
|
|
|
},
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
SecurityOpt: []string{
|
|
|
|
"label=level:s0:c100,c200",
|
|
|
|
"label=type:svirt_apache_t",
|
|
|
|
},
|
|
|
|
StdinOpen: true,
|
|
|
|
StopSignal: "SIGUSR1",
|
2018-08-29 17:29:39 -04:00
|
|
|
StopGracePeriod: durationPtr(20 * time.Second),
|
2019-02-12 10:07:07 -05:00
|
|
|
Sysctls: map[string]string{
|
|
|
|
"net.core.somaxconn": "1024",
|
|
|
|
"net.ipv4.tcp_syncookies": "0",
|
|
|
|
},
|
|
|
|
Tmpfs: []string{"/run", "/tmp"},
|
|
|
|
Tty: true,
|
2018-01-29 16:18:43 -05:00
|
|
|
Ulimits: map[string]*types.UlimitsConfig{
|
|
|
|
"nproc": {
|
|
|
|
Single: 65535,
|
|
|
|
},
|
|
|
|
"nofile": {
|
|
|
|
Soft: 20000,
|
|
|
|
Hard: 40000,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
User: "someone",
|
|
|
|
Volumes: []types.ServiceVolumeConfig{
|
|
|
|
{Target: "/var/lib/mysql", Type: "volume"},
|
|
|
|
{Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"},
|
|
|
|
{Source: workingDir, Target: "/code", Type: "bind"},
|
2018-02-27 10:54:36 -05:00
|
|
|
{Source: filepath.Join(workingDir, "static"), Target: "/var/www/html", Type: "bind"},
|
2018-01-29 16:18:43 -05:00
|
|
|
{Source: homeDir + "/configs", Target: "/etc/configs/", Type: "bind", ReadOnly: true},
|
|
|
|
{Source: "datavolume", Target: "/var/lib/mysql", Type: "volume"},
|
2018-02-27 10:54:36 -05:00
|
|
|
{Source: filepath.Join(workingDir, "opt"), Target: "/opt", Consistency: "cached", Type: "bind"},
|
2018-01-29 16:18:43 -05:00
|
|
|
{Target: "/opt", Type: "tmpfs", Tmpfs: &types.ServiceVolumeTmpfs{
|
|
|
|
Size: int64(10000),
|
|
|
|
}},
|
2022-06-06 09:58:32 -04:00
|
|
|
{Source: "group:mygroup", Target: "/srv", Type: "cluster"},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
|
|
|
WorkingDir: "/code",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func networks() map[string]types.NetworkConfig {
|
|
|
|
return map[string]types.NetworkConfig{
|
|
|
|
"some-network": {},
|
|
|
|
|
|
|
|
"other-network": {
|
|
|
|
Driver: "overlay",
|
|
|
|
DriverOpts: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"baz": "1",
|
|
|
|
},
|
|
|
|
Ipam: types.IPAMConfig{
|
|
|
|
Driver: "overlay",
|
|
|
|
Config: []*types.IPAMPool{
|
|
|
|
{Subnet: "172.16.238.0/24"},
|
|
|
|
{Subnet: "2001:3984:3989::/64"},
|
|
|
|
},
|
|
|
|
},
|
2018-06-01 08:16:18 -04:00
|
|
|
Labels: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
|
|
|
|
|
|
|
"external-network": {
|
|
|
|
Name: "external-network",
|
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
|
|
|
|
"other-external-network": {
|
|
|
|
Name: "my-cool-network",
|
|
|
|
External: types.External{External: true},
|
2018-06-25 04:51:56 -04:00
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func volumes() map[string]types.VolumeConfig {
|
|
|
|
return map[string]types.VolumeConfig{
|
|
|
|
"some-volume": {},
|
|
|
|
"other-volume": {
|
|
|
|
Driver: "flocker",
|
|
|
|
DriverOpts: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"baz": "1",
|
|
|
|
},
|
2018-06-01 08:16:18 -04:00
|
|
|
Labels: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
|
|
|
"another-volume": {
|
|
|
|
Name: "user_specified_name",
|
|
|
|
Driver: "vsphere",
|
|
|
|
DriverOpts: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
"baz": "1",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"external-volume": {
|
|
|
|
Name: "external-volume",
|
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"other-external-volume": {
|
|
|
|
Name: "my-cool-volume",
|
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"external-volume3": {
|
|
|
|
Name: "this-is-volume3",
|
|
|
|
External: types.External{External: true},
|
2018-06-25 04:51:56 -04:00
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
},
|
2022-06-06 09:58:32 -04:00
|
|
|
"cluster-volume": {
|
|
|
|
Driver: "my-csi-driver",
|
|
|
|
Spec: &types.ClusterVolumeSpec{
|
|
|
|
Group: "mygroup",
|
|
|
|
AccessMode: &types.AccessMode{
|
|
|
|
Scope: "single",
|
|
|
|
Sharing: "none",
|
|
|
|
BlockVolume: &types.BlockVolume{},
|
|
|
|
},
|
|
|
|
AccessibilityRequirements: &types.TopologyRequirement{
|
|
|
|
Requisite: []types.Topology{
|
|
|
|
{
|
|
|
|
Segments: types.Mapping{"region": "R1", "zone": "Z1"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Segments: types.Mapping{"region": "R1", "zone": "Z2"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Preferred: []types.Topology{
|
|
|
|
{
|
|
|
|
Segments: types.Mapping{"region": "R1", "zone": "Z1"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CapacityRange: &types.CapacityRange{
|
|
|
|
RequiredBytes: types.UnitBytes(1 * 1024 * 1024 * 1024),
|
|
|
|
LimitBytes: types.UnitBytes(8 * 1024 * 1024 * 1024),
|
|
|
|
},
|
|
|
|
Secrets: []types.VolumeSecret{
|
|
|
|
{Key: "mycsisecret", Secret: "secret1"},
|
|
|
|
{Key: "mycsisecret2", Secret: "secret4"},
|
|
|
|
},
|
|
|
|
Availability: "active",
|
|
|
|
},
|
|
|
|
},
|
2018-01-29 16:18:43 -05:00
|
|
|
}
|
|
|
|
}
|
2018-02-27 10:54:36 -05:00
|
|
|
|
2018-06-25 04:51:56 -04:00
|
|
|
func configs(workingDir string) map[string]types.ConfigObjConfig {
|
2018-06-01 08:16:18 -04:00
|
|
|
return map[string]types.ConfigObjConfig{
|
|
|
|
"config1": {
|
2018-06-25 04:51:56 -04:00
|
|
|
File: filepath.Join(workingDir, "config_data"),
|
2018-06-01 08:16:18 -04:00
|
|
|
Labels: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"config2": {
|
|
|
|
Name: "my_config",
|
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"config3": {
|
2018-06-25 04:51:56 -04:00
|
|
|
Name: "config3",
|
2018-06-01 08:16:18 -04:00
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"config4": {
|
|
|
|
Name: "foo",
|
2018-06-25 04:51:56 -04:00
|
|
|
File: workingDir,
|
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
},
|
2018-06-01 08:16:18 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-25 04:51:56 -04:00
|
|
|
func secrets(workingDir string) map[string]types.SecretConfig {
|
2018-06-01 08:16:18 -04:00
|
|
|
return map[string]types.SecretConfig{
|
|
|
|
"secret1": {
|
2018-06-25 04:51:56 -04:00
|
|
|
File: filepath.Join(workingDir, "secret_data"),
|
2018-06-01 08:16:18 -04:00
|
|
|
Labels: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"secret2": {
|
|
|
|
Name: "my_secret",
|
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"secret3": {
|
2018-06-25 04:51:56 -04:00
|
|
|
Name: "secret3",
|
2018-06-01 08:16:18 -04:00
|
|
|
External: types.External{External: true},
|
|
|
|
},
|
|
|
|
"secret4": {
|
|
|
|
Name: "bar",
|
2018-06-25 04:51:56 -04:00
|
|
|
File: workingDir,
|
|
|
|
Extras: map[string]interface{}{
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
},
|
2018-06-01 08:16:18 -04:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-27 10:54:36 -05:00
|
|
|
func fullExampleYAML(workingDir string) string {
|
2022-06-06 09:58:32 -04:00
|
|
|
return fmt.Sprintf(`version: "3.10"
|
2018-02-27 10:54:36 -05:00
|
|
|
services:
|
|
|
|
foo:
|
|
|
|
build:
|
|
|
|
context: ./dir
|
|
|
|
dockerfile: Dockerfile
|
|
|
|
args:
|
|
|
|
foo: bar
|
|
|
|
labels:
|
|
|
|
FOO: BAR
|
|
|
|
cache_from:
|
|
|
|
- foo
|
|
|
|
- bar
|
2020-05-10 13:40:14 -04:00
|
|
|
extra_hosts:
|
|
|
|
- ipv4.example.com:127.0.0.1
|
|
|
|
- ipv6.example.com:::1
|
2018-02-27 10:54:36 -05:00
|
|
|
network: foo
|
|
|
|
target: foo
|
|
|
|
cap_add:
|
|
|
|
- ALL
|
|
|
|
cap_drop:
|
|
|
|
- NET_ADMIN
|
|
|
|
- SYS_ADMIN
|
|
|
|
cgroup_parent: m-executor-abcd
|
|
|
|
command:
|
|
|
|
- bundle
|
|
|
|
- exec
|
|
|
|
- thin
|
|
|
|
- -p
|
|
|
|
- "3000"
|
2018-06-01 08:16:18 -04:00
|
|
|
configs:
|
|
|
|
- source: config1
|
|
|
|
- source: config2
|
|
|
|
target: /my_config
|
|
|
|
uid: "103"
|
|
|
|
gid: "103"
|
|
|
|
mode: 288
|
2018-02-27 10:54:36 -05:00
|
|
|
container_name: my-web-container
|
|
|
|
depends_on:
|
|
|
|
- db
|
|
|
|
- redis
|
|
|
|
deploy:
|
|
|
|
mode: replicated
|
|
|
|
replicas: 6
|
|
|
|
labels:
|
|
|
|
FOO: BAR
|
|
|
|
update_config:
|
|
|
|
parallelism: 3
|
|
|
|
delay: 10s
|
|
|
|
failure_action: continue
|
|
|
|
monitor: 1m0s
|
|
|
|
max_failure_ratio: 0.3
|
|
|
|
order: start-first
|
2018-05-29 05:37:51 -04:00
|
|
|
rollback_config:
|
|
|
|
parallelism: 3
|
|
|
|
delay: 10s
|
|
|
|
failure_action: continue
|
|
|
|
monitor: 1m0s
|
|
|
|
max_failure_ratio: 0.3
|
|
|
|
order: start-first
|
2018-02-27 10:54:36 -05:00
|
|
|
resources:
|
|
|
|
limits:
|
|
|
|
cpus: "0.001"
|
|
|
|
memory: "52428800"
|
2020-05-09 17:08:42 -04:00
|
|
|
pids: 100
|
2018-02-27 10:54:36 -05:00
|
|
|
reservations:
|
|
|
|
cpus: "0.0001"
|
|
|
|
memory: "20971520"
|
|
|
|
generic_resources:
|
|
|
|
- discrete_resource_spec:
|
|
|
|
kind: gpu
|
|
|
|
value: 2
|
|
|
|
- discrete_resource_spec:
|
|
|
|
kind: ssd
|
|
|
|
value: 1
|
|
|
|
restart_policy:
|
|
|
|
condition: on-failure
|
|
|
|
delay: 5s
|
|
|
|
max_attempts: 3
|
|
|
|
window: 2m0s
|
|
|
|
placement:
|
|
|
|
constraints:
|
|
|
|
- node=foo
|
|
|
|
preferences:
|
|
|
|
- spread: node.labels.az
|
2018-09-30 10:04:35 -04:00
|
|
|
max_replicas_per_node: 5
|
2018-02-27 10:54:36 -05:00
|
|
|
endpoint_mode: dnsrr
|
|
|
|
devices:
|
|
|
|
- /dev/ttyUSB0:/dev/ttyUSB0
|
|
|
|
dns:
|
|
|
|
- 8.8.8.8
|
|
|
|
- 9.9.9.9
|
|
|
|
dns_search:
|
|
|
|
- dc1.example.com
|
|
|
|
- dc2.example.com
|
|
|
|
domainname: foo.com
|
|
|
|
entrypoint:
|
|
|
|
- /code/entrypoint.sh
|
|
|
|
- -p
|
|
|
|
- "3000"
|
|
|
|
environment:
|
|
|
|
BAR: bar_from_env_file_2
|
|
|
|
BAZ: baz_from_service_def
|
|
|
|
FOO: foo_from_env_file
|
|
|
|
QUX: qux_from_environment
|
|
|
|
env_file:
|
|
|
|
- ./example1.env
|
|
|
|
- ./example2.env
|
|
|
|
expose:
|
|
|
|
- "3000"
|
|
|
|
- "8000"
|
|
|
|
external_links:
|
|
|
|
- redis_1
|
|
|
|
- project_db_1:mysql
|
|
|
|
- project_db_1:postgresql
|
|
|
|
extra_hosts:
|
|
|
|
- somehost:162.242.195.82
|
|
|
|
- otherhost:50.31.209.229
|
2020-04-15 03:13:11 -04:00
|
|
|
- host.docker.internal:host-gateway
|
2018-02-27 10:54:36 -05:00
|
|
|
hostname: foo
|
|
|
|
healthcheck:
|
|
|
|
test:
|
|
|
|
- CMD-SHELL
|
|
|
|
- echo "hello world"
|
|
|
|
timeout: 1s
|
|
|
|
interval: 10s
|
|
|
|
retries: 5
|
|
|
|
start_period: 15s
|
|
|
|
image: redis
|
|
|
|
ipc: host
|
|
|
|
labels:
|
|
|
|
com.example.description: Accounting webapp
|
|
|
|
com.example.empty-label: ""
|
|
|
|
com.example.number: "42"
|
|
|
|
links:
|
|
|
|
- db
|
|
|
|
- db:database
|
|
|
|
- redis
|
|
|
|
logging:
|
|
|
|
driver: syslog
|
|
|
|
options:
|
|
|
|
syslog-address: tcp://192.168.0.42:123
|
|
|
|
mac_address: 02:42:ac:11:65:43
|
|
|
|
network_mode: container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b
|
|
|
|
networks:
|
|
|
|
other-network:
|
|
|
|
ipv4_address: 172.16.238.10
|
|
|
|
ipv6_address: 2001:3984:3989::10
|
|
|
|
other-other-network: null
|
|
|
|
some-network:
|
|
|
|
aliases:
|
|
|
|
- alias1
|
|
|
|
- alias3
|
|
|
|
pid: host
|
|
|
|
ports:
|
|
|
|
- mode: ingress
|
|
|
|
target: 3000
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 3001
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 3002
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 3003
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 3004
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 3005
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 8000
|
|
|
|
published: 8000
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 8080
|
|
|
|
published: 9090
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 8081
|
|
|
|
published: 9091
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 22
|
|
|
|
published: 49100
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 8001
|
|
|
|
published: 8001
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5000
|
|
|
|
published: 5000
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5001
|
|
|
|
published: 5001
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5002
|
|
|
|
published: 5002
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5003
|
|
|
|
published: 5003
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5004
|
|
|
|
published: 5004
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5005
|
|
|
|
published: 5005
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5006
|
|
|
|
published: 5006
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5007
|
|
|
|
published: 5007
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5008
|
|
|
|
published: 5008
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5009
|
|
|
|
published: 5009
|
|
|
|
protocol: tcp
|
|
|
|
- mode: ingress
|
|
|
|
target: 5010
|
|
|
|
published: 5010
|
|
|
|
protocol: tcp
|
|
|
|
privileged: true
|
|
|
|
read_only: true
|
|
|
|
restart: always
|
2018-06-01 08:16:18 -04:00
|
|
|
secrets:
|
|
|
|
- source: secret1
|
|
|
|
- source: secret2
|
|
|
|
target: my_secret
|
|
|
|
uid: "103"
|
|
|
|
gid: "103"
|
|
|
|
mode: 288
|
2018-02-27 10:54:36 -05:00
|
|
|
security_opt:
|
|
|
|
- label=level:s0:c100,c200
|
|
|
|
- label=type:svirt_apache_t
|
|
|
|
stdin_open: true
|
|
|
|
stop_grace_period: 20s
|
|
|
|
stop_signal: SIGUSR1
|
2019-02-12 10:07:07 -05:00
|
|
|
sysctls:
|
|
|
|
net.core.somaxconn: "1024"
|
|
|
|
net.ipv4.tcp_syncookies: "0"
|
2018-02-27 10:54:36 -05:00
|
|
|
tmpfs:
|
|
|
|
- /run
|
|
|
|
- /tmp
|
|
|
|
tty: true
|
|
|
|
ulimits:
|
|
|
|
nofile:
|
|
|
|
soft: 20000
|
|
|
|
hard: 40000
|
|
|
|
nproc: 65535
|
|
|
|
user: someone
|
|
|
|
volumes:
|
|
|
|
- type: volume
|
|
|
|
target: /var/lib/mysql
|
|
|
|
- type: bind
|
|
|
|
source: /opt/data
|
|
|
|
target: /var/lib/mysql
|
|
|
|
- type: bind
|
|
|
|
source: /foo
|
|
|
|
target: /code
|
|
|
|
- type: bind
|
|
|
|
source: %s
|
|
|
|
target: /var/www/html
|
|
|
|
- type: bind
|
|
|
|
source: /bar/configs
|
|
|
|
target: /etc/configs/
|
|
|
|
read_only: true
|
|
|
|
- type: volume
|
|
|
|
source: datavolume
|
|
|
|
target: /var/lib/mysql
|
|
|
|
- type: bind
|
|
|
|
source: %s
|
|
|
|
target: /opt
|
|
|
|
consistency: cached
|
|
|
|
- type: tmpfs
|
|
|
|
target: /opt
|
|
|
|
tmpfs:
|
|
|
|
size: 10000
|
2022-06-06 09:58:32 -04:00
|
|
|
- type: cluster
|
|
|
|
source: group:mygroup
|
|
|
|
target: /srv
|
2018-02-27 10:54:36 -05:00
|
|
|
working_dir: /code
|
2018-06-25 04:51:56 -04:00
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
2018-02-27 10:54:36 -05:00
|
|
|
networks:
|
|
|
|
external-network:
|
|
|
|
name: external-network
|
|
|
|
external: true
|
|
|
|
other-external-network:
|
|
|
|
name: my-cool-network
|
|
|
|
external: true
|
2018-06-25 04:51:56 -04:00
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
2018-02-27 10:54:36 -05:00
|
|
|
other-network:
|
|
|
|
driver: overlay
|
|
|
|
driver_opts:
|
|
|
|
baz: "1"
|
|
|
|
foo: bar
|
|
|
|
ipam:
|
|
|
|
driver: overlay
|
|
|
|
config:
|
|
|
|
- subnet: 172.16.238.0/24
|
|
|
|
- subnet: 2001:3984:3989::/64
|
2018-06-01 08:16:18 -04:00
|
|
|
labels:
|
|
|
|
foo: bar
|
2018-02-27 10:54:36 -05:00
|
|
|
some-network: {}
|
|
|
|
volumes:
|
|
|
|
another-volume:
|
|
|
|
name: user_specified_name
|
|
|
|
driver: vsphere
|
|
|
|
driver_opts:
|
|
|
|
baz: "1"
|
|
|
|
foo: bar
|
2022-06-06 09:58:32 -04:00
|
|
|
cluster-volume:
|
|
|
|
driver: my-csi-driver
|
|
|
|
x-cluster-spec:
|
|
|
|
group: mygroup
|
|
|
|
access_mode:
|
|
|
|
scope: single
|
|
|
|
sharing: none
|
|
|
|
block_volume: {}
|
|
|
|
accessibility_requirements:
|
|
|
|
requisite:
|
|
|
|
- segments:
|
|
|
|
region: R1
|
|
|
|
zone: Z1
|
|
|
|
- segments:
|
|
|
|
region: R1
|
|
|
|
zone: Z2
|
|
|
|
preferred:
|
|
|
|
- segments:
|
|
|
|
region: R1
|
|
|
|
zone: Z1
|
|
|
|
capacity_range:
|
|
|
|
required_bytes: "1073741824"
|
|
|
|
limit_bytes: "8589934592"
|
|
|
|
secrets:
|
|
|
|
- key: mycsisecret
|
|
|
|
secret: secret1
|
|
|
|
- key: mycsisecret2
|
|
|
|
secret: secret4
|
|
|
|
availability: active
|
2018-02-27 10:54:36 -05:00
|
|
|
external-volume:
|
|
|
|
name: external-volume
|
|
|
|
external: true
|
|
|
|
external-volume3:
|
|
|
|
name: this-is-volume3
|
|
|
|
external: true
|
2018-06-25 04:51:56 -04:00
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
2018-02-27 10:54:36 -05:00
|
|
|
other-external-volume:
|
|
|
|
name: my-cool-volume
|
|
|
|
external: true
|
|
|
|
other-volume:
|
|
|
|
driver: flocker
|
|
|
|
driver_opts:
|
|
|
|
baz: "1"
|
|
|
|
foo: bar
|
2018-06-01 08:16:18 -04:00
|
|
|
labels:
|
|
|
|
foo: bar
|
2018-02-27 10:54:36 -05:00
|
|
|
some-volume: {}
|
2018-06-01 08:16:18 -04:00
|
|
|
secrets:
|
|
|
|
secret1:
|
2018-06-25 04:51:56 -04:00
|
|
|
file: %s/secret_data
|
2018-06-01 08:16:18 -04:00
|
|
|
labels:
|
|
|
|
foo: bar
|
|
|
|
secret2:
|
|
|
|
name: my_secret
|
|
|
|
external: true
|
|
|
|
secret3:
|
2018-06-25 04:51:56 -04:00
|
|
|
name: secret3
|
2018-06-01 08:16:18 -04:00
|
|
|
external: true
|
|
|
|
secret4:
|
|
|
|
name: bar
|
2018-06-25 04:51:56 -04:00
|
|
|
file: %s
|
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
2018-06-01 08:16:18 -04:00
|
|
|
configs:
|
|
|
|
config1:
|
2018-06-25 04:51:56 -04:00
|
|
|
file: %s/config_data
|
2018-06-01 08:16:18 -04:00
|
|
|
labels:
|
|
|
|
foo: bar
|
|
|
|
config2:
|
|
|
|
name: my_config
|
|
|
|
external: true
|
|
|
|
config3:
|
2018-06-25 04:51:56 -04:00
|
|
|
name: config3
|
2018-06-01 08:16:18 -04:00
|
|
|
external: true
|
|
|
|
config4:
|
|
|
|
name: foo
|
2018-06-25 04:51:56 -04:00
|
|
|
file: %s
|
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
|
|
|
x-bar: baz
|
|
|
|
x-foo: bar
|
|
|
|
x-nested:
|
|
|
|
bar: baz
|
|
|
|
foo: bar
|
|
|
|
`,
|
|
|
|
filepath.Join(workingDir, "static"),
|
|
|
|
filepath.Join(workingDir, "opt"),
|
|
|
|
workingDir,
|
|
|
|
workingDir,
|
|
|
|
workingDir,
|
|
|
|
workingDir)
|
2018-02-27 10:54:36 -05:00
|
|
|
}
|
2018-08-29 17:29:39 -04:00
|
|
|
|
|
|
|
func fullExampleJSON(workingDir string) string {
|
|
|
|
return fmt.Sprintf(`{
|
|
|
|
"configs": {
|
|
|
|
"config1": {
|
|
|
|
"file": "%s/config_data",
|
|
|
|
"external": false,
|
|
|
|
"labels": {
|
|
|
|
"foo": "bar"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"config2": {
|
|
|
|
"name": "my_config",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"config3": {
|
|
|
|
"name": "config3",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"config4": {
|
|
|
|
"name": "foo",
|
|
|
|
"file": "%s",
|
|
|
|
"external": false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"networks": {
|
|
|
|
"external-network": {
|
|
|
|
"name": "external-network",
|
|
|
|
"ipam": {},
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"other-external-network": {
|
|
|
|
"name": "my-cool-network",
|
|
|
|
"ipam": {},
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"other-network": {
|
|
|
|
"driver": "overlay",
|
|
|
|
"driver_opts": {
|
|
|
|
"baz": "1",
|
|
|
|
"foo": "bar"
|
|
|
|
},
|
|
|
|
"ipam": {
|
|
|
|
"driver": "overlay",
|
|
|
|
"config": [
|
|
|
|
{
|
|
|
|
"subnet": "172.16.238.0/24"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"subnet": "2001:3984:3989::/64"
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"external": false,
|
|
|
|
"labels": {
|
|
|
|
"foo": "bar"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"some-network": {
|
|
|
|
"ipam": {},
|
|
|
|
"external": false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"secrets": {
|
|
|
|
"secret1": {
|
|
|
|
"file": "%s/secret_data",
|
|
|
|
"external": false,
|
|
|
|
"labels": {
|
|
|
|
"foo": "bar"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"secret2": {
|
|
|
|
"name": "my_secret",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"secret3": {
|
|
|
|
"name": "secret3",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"secret4": {
|
|
|
|
"name": "bar",
|
|
|
|
"file": "%s",
|
|
|
|
"external": false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"services": {
|
|
|
|
"foo": {
|
|
|
|
"build": {
|
|
|
|
"context": "./dir",
|
|
|
|
"dockerfile": "Dockerfile",
|
|
|
|
"args": {
|
|
|
|
"foo": "bar"
|
|
|
|
},
|
|
|
|
"labels": {
|
|
|
|
"FOO": "BAR"
|
|
|
|
},
|
|
|
|
"cache_from": [
|
|
|
|
"foo",
|
|
|
|
"bar"
|
|
|
|
],
|
2020-05-10 13:40:14 -04:00
|
|
|
"extra_hosts": [
|
|
|
|
"ipv4.example.com:127.0.0.1",
|
|
|
|
"ipv6.example.com:::1"
|
|
|
|
],
|
2018-08-29 17:29:39 -04:00
|
|
|
"network": "foo",
|
|
|
|
"target": "foo"
|
|
|
|
},
|
|
|
|
"cap_add": [
|
|
|
|
"ALL"
|
|
|
|
],
|
|
|
|
"cap_drop": [
|
|
|
|
"NET_ADMIN",
|
|
|
|
"SYS_ADMIN"
|
|
|
|
],
|
|
|
|
"cgroup_parent": "m-executor-abcd",
|
|
|
|
"command": [
|
|
|
|
"bundle",
|
|
|
|
"exec",
|
|
|
|
"thin",
|
|
|
|
"-p",
|
|
|
|
"3000"
|
|
|
|
],
|
|
|
|
"configs": [
|
|
|
|
{
|
|
|
|
"source": "config1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"source": "config2",
|
|
|
|
"target": "/my_config",
|
|
|
|
"uid": "103",
|
|
|
|
"gid": "103",
|
|
|
|
"mode": 288
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"container_name": "my-web-container",
|
|
|
|
"credential_spec": {},
|
|
|
|
"depends_on": [
|
|
|
|
"db",
|
|
|
|
"redis"
|
|
|
|
],
|
|
|
|
"deploy": {
|
|
|
|
"mode": "replicated",
|
|
|
|
"replicas": 6,
|
|
|
|
"labels": {
|
|
|
|
"FOO": "BAR"
|
|
|
|
},
|
|
|
|
"update_config": {
|
|
|
|
"parallelism": 3,
|
|
|
|
"delay": "10s",
|
|
|
|
"failure_action": "continue",
|
|
|
|
"monitor": "1m0s",
|
|
|
|
"max_failure_ratio": 0.3,
|
|
|
|
"order": "start-first"
|
|
|
|
},
|
|
|
|
"rollback_config": {
|
|
|
|
"parallelism": 3,
|
|
|
|
"delay": "10s",
|
|
|
|
"failure_action": "continue",
|
|
|
|
"monitor": "1m0s",
|
|
|
|
"max_failure_ratio": 0.3,
|
|
|
|
"order": "start-first"
|
|
|
|
},
|
|
|
|
"resources": {
|
|
|
|
"limits": {
|
|
|
|
"cpus": "0.001",
|
2020-05-09 17:08:42 -04:00
|
|
|
"memory": "52428800",
|
|
|
|
"pids": 100
|
2018-08-29 17:29:39 -04:00
|
|
|
},
|
|
|
|
"reservations": {
|
|
|
|
"cpus": "0.0001",
|
|
|
|
"memory": "20971520",
|
|
|
|
"generic_resources": [
|
|
|
|
{
|
|
|
|
"discrete_resource_spec": {
|
|
|
|
"kind": "gpu",
|
|
|
|
"value": 2
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"discrete_resource_spec": {
|
|
|
|
"kind": "ssd",
|
|
|
|
"value": 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"restart_policy": {
|
|
|
|
"condition": "on-failure",
|
|
|
|
"delay": "5s",
|
|
|
|
"max_attempts": 3,
|
|
|
|
"window": "2m0s"
|
|
|
|
},
|
|
|
|
"placement": {
|
|
|
|
"constraints": [
|
|
|
|
"node=foo"
|
|
|
|
],
|
|
|
|
"preferences": [
|
|
|
|
{
|
|
|
|
"spread": "node.labels.az"
|
|
|
|
}
|
2018-09-30 10:04:35 -04:00
|
|
|
],
|
|
|
|
"max_replicas_per_node": 5
|
2018-08-29 17:29:39 -04:00
|
|
|
},
|
|
|
|
"endpoint_mode": "dnsrr"
|
|
|
|
},
|
|
|
|
"devices": [
|
|
|
|
"/dev/ttyUSB0:/dev/ttyUSB0"
|
|
|
|
],
|
|
|
|
"dns": [
|
|
|
|
"8.8.8.8",
|
|
|
|
"9.9.9.9"
|
|
|
|
],
|
|
|
|
"dns_search": [
|
|
|
|
"dc1.example.com",
|
|
|
|
"dc2.example.com"
|
|
|
|
],
|
|
|
|
"domainname": "foo.com",
|
|
|
|
"entrypoint": [
|
|
|
|
"/code/entrypoint.sh",
|
|
|
|
"-p",
|
|
|
|
"3000"
|
|
|
|
],
|
|
|
|
"environment": {
|
|
|
|
"BAR": "bar_from_env_file_2",
|
|
|
|
"BAZ": "baz_from_service_def",
|
|
|
|
"FOO": "foo_from_env_file",
|
|
|
|
"QUX": "qux_from_environment"
|
|
|
|
},
|
|
|
|
"env_file": [
|
|
|
|
"./example1.env",
|
|
|
|
"./example2.env"
|
|
|
|
],
|
|
|
|
"expose": [
|
|
|
|
"3000",
|
|
|
|
"8000"
|
|
|
|
],
|
|
|
|
"external_links": [
|
|
|
|
"redis_1",
|
|
|
|
"project_db_1:mysql",
|
|
|
|
"project_db_1:postgresql"
|
|
|
|
],
|
|
|
|
"extra_hosts": [
|
|
|
|
"somehost:162.242.195.82",
|
2020-04-15 03:13:11 -04:00
|
|
|
"otherhost:50.31.209.229",
|
|
|
|
"host.docker.internal:host-gateway"
|
2018-08-29 17:29:39 -04:00
|
|
|
],
|
|
|
|
"hostname": "foo",
|
|
|
|
"healthcheck": {
|
|
|
|
"test": [
|
|
|
|
"CMD-SHELL",
|
|
|
|
"echo \"hello world\""
|
|
|
|
],
|
|
|
|
"timeout": "1s",
|
|
|
|
"interval": "10s",
|
|
|
|
"retries": 5,
|
|
|
|
"start_period": "15s"
|
|
|
|
},
|
|
|
|
"image": "redis",
|
|
|
|
"ipc": "host",
|
|
|
|
"labels": {
|
|
|
|
"com.example.description": "Accounting webapp",
|
|
|
|
"com.example.empty-label": "",
|
|
|
|
"com.example.number": "42"
|
|
|
|
},
|
|
|
|
"links": [
|
|
|
|
"db",
|
|
|
|
"db:database",
|
|
|
|
"redis"
|
|
|
|
],
|
|
|
|
"logging": {
|
|
|
|
"driver": "syslog",
|
|
|
|
"options": {
|
|
|
|
"syslog-address": "tcp://192.168.0.42:123"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"mac_address": "02:42:ac:11:65:43",
|
|
|
|
"network_mode": "container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b",
|
|
|
|
"networks": {
|
|
|
|
"other-network": {
|
|
|
|
"ipv4_address": "172.16.238.10",
|
|
|
|
"ipv6_address": "2001:3984:3989::10"
|
|
|
|
},
|
|
|
|
"other-other-network": null,
|
|
|
|
"some-network": {
|
|
|
|
"aliases": [
|
|
|
|
"alias1",
|
|
|
|
"alias3"
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"pid": "host",
|
|
|
|
"ports": [
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3000,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3001,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3002,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3003,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3004,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 3005,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 8000,
|
|
|
|
"published": 8000,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 8080,
|
|
|
|
"published": 9090,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 8081,
|
|
|
|
"published": 9091,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 22,
|
|
|
|
"published": 49100,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 8001,
|
|
|
|
"published": 8001,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5000,
|
|
|
|
"published": 5000,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5001,
|
|
|
|
"published": 5001,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5002,
|
|
|
|
"published": 5002,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5003,
|
|
|
|
"published": 5003,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5004,
|
|
|
|
"published": 5004,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5005,
|
|
|
|
"published": 5005,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5006,
|
|
|
|
"published": 5006,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5007,
|
|
|
|
"published": 5007,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5008,
|
|
|
|
"published": 5008,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5009,
|
|
|
|
"published": 5009,
|
|
|
|
"protocol": "tcp"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"mode": "ingress",
|
|
|
|
"target": 5010,
|
|
|
|
"published": 5010,
|
|
|
|
"protocol": "tcp"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"privileged": true,
|
|
|
|
"read_only": true,
|
|
|
|
"restart": "always",
|
|
|
|
"secrets": [
|
|
|
|
{
|
|
|
|
"source": "secret1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"source": "secret2",
|
|
|
|
"target": "my_secret",
|
|
|
|
"uid": "103",
|
|
|
|
"gid": "103",
|
|
|
|
"mode": 288
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"security_opt": [
|
|
|
|
"label=level:s0:c100,c200",
|
|
|
|
"label=type:svirt_apache_t"
|
|
|
|
],
|
|
|
|
"stdin_open": true,
|
|
|
|
"stop_grace_period": "20s",
|
|
|
|
"stop_signal": "SIGUSR1",
|
2019-02-12 10:07:07 -05:00
|
|
|
"sysctls": {
|
|
|
|
"net.core.somaxconn": "1024",
|
|
|
|
"net.ipv4.tcp_syncookies": "0"
|
|
|
|
},
|
2018-08-29 17:29:39 -04:00
|
|
|
"tmpfs": [
|
|
|
|
"/run",
|
|
|
|
"/tmp"
|
|
|
|
],
|
|
|
|
"tty": true,
|
|
|
|
"ulimits": {
|
|
|
|
"nofile": {
|
|
|
|
"soft": 20000,
|
|
|
|
"hard": 40000
|
|
|
|
},
|
|
|
|
"nproc": 65535
|
|
|
|
},
|
|
|
|
"user": "someone",
|
|
|
|
"volumes": [
|
|
|
|
{
|
|
|
|
"type": "volume",
|
|
|
|
"target": "/var/lib/mysql"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "bind",
|
|
|
|
"source": "/opt/data",
|
|
|
|
"target": "/var/lib/mysql"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "bind",
|
|
|
|
"source": "/foo",
|
|
|
|
"target": "/code"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "bind",
|
|
|
|
"source": "%s",
|
|
|
|
"target": "/var/www/html"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "bind",
|
|
|
|
"source": "/bar/configs",
|
|
|
|
"target": "/etc/configs/",
|
|
|
|
"read_only": true
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "volume",
|
|
|
|
"source": "datavolume",
|
|
|
|
"target": "/var/lib/mysql"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "bind",
|
|
|
|
"source": "%s",
|
|
|
|
"target": "/opt",
|
|
|
|
"consistency": "cached"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "tmpfs",
|
|
|
|
"target": "/opt",
|
|
|
|
"tmpfs": {
|
|
|
|
"size": 10000
|
|
|
|
}
|
2022-06-06 09:58:32 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
"type": "cluster",
|
|
|
|
"source": "group:mygroup",
|
|
|
|
"target": "/srv"
|
2018-08-29 17:29:39 -04:00
|
|
|
}
|
|
|
|
],
|
|
|
|
"working_dir": "/code"
|
|
|
|
}
|
|
|
|
},
|
2022-06-06 09:58:32 -04:00
|
|
|
"version": "3.10",
|
2018-08-29 17:29:39 -04:00
|
|
|
"volumes": {
|
|
|
|
"another-volume": {
|
|
|
|
"name": "user_specified_name",
|
|
|
|
"driver": "vsphere",
|
|
|
|
"driver_opts": {
|
|
|
|
"baz": "1",
|
|
|
|
"foo": "bar"
|
|
|
|
},
|
|
|
|
"external": false
|
|
|
|
},
|
2022-06-06 09:58:32 -04:00
|
|
|
"cluster-volume": {
|
|
|
|
"driver": "my-csi-driver",
|
|
|
|
"external": false,
|
|
|
|
"x-cluster-spec": {
|
|
|
|
"group": "mygroup",
|
|
|
|
"access_mode": {
|
|
|
|
"scope": "single",
|
|
|
|
"sharing": "none",
|
|
|
|
"block_volume": {}
|
|
|
|
},
|
|
|
|
"accessibility_requirements": {
|
|
|
|
"requisite": [
|
|
|
|
{
|
|
|
|
"segments": {
|
|
|
|
"region": "R1",
|
|
|
|
"zone": "Z1"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"segments": {
|
|
|
|
"region": "R1",
|
|
|
|
"zone": "Z2"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"preferred": [
|
|
|
|
{
|
|
|
|
"segments": {
|
|
|
|
"region": "R1",
|
|
|
|
"zone": "Z1"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
"capacity_range": {
|
|
|
|
"required_bytes": "1073741824",
|
|
|
|
"limit_bytes": "8589934592"
|
|
|
|
},
|
|
|
|
"secrets": [
|
|
|
|
{
|
|
|
|
"key": "mycsisecret",
|
|
|
|
"secret": "secret1"
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"key": "mycsisecret2",
|
|
|
|
"secret": "secret4"
|
|
|
|
}
|
|
|
|
],
|
|
|
|
"availability": "active"
|
|
|
|
}
|
|
|
|
},
|
2018-08-29 17:29:39 -04:00
|
|
|
"external-volume": {
|
|
|
|
"name": "external-volume",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"external-volume3": {
|
|
|
|
"name": "this-is-volume3",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"other-external-volume": {
|
|
|
|
"name": "my-cool-volume",
|
|
|
|
"external": true
|
|
|
|
},
|
|
|
|
"other-volume": {
|
|
|
|
"driver": "flocker",
|
|
|
|
"driver_opts": {
|
|
|
|
"baz": "1",
|
|
|
|
"foo": "bar"
|
|
|
|
},
|
|
|
|
"external": false,
|
|
|
|
"labels": {
|
|
|
|
"foo": "bar"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"some-volume": {
|
|
|
|
"external": false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"x-bar": "baz",
|
|
|
|
"x-foo": "bar",
|
|
|
|
"x-nested": {
|
|
|
|
"bar": "baz",
|
|
|
|
"foo": "bar"
|
|
|
|
}
|
|
|
|
}`,
|
|
|
|
workingDir,
|
|
|
|
workingDir,
|
|
|
|
workingDir,
|
|
|
|
workingDir,
|
|
|
|
filepath.Join(workingDir, "static"),
|
|
|
|
filepath.Join(workingDir, "opt"))
|
|
|
|
}
|