github.com/itscaro/cli@v0.0.0-20190705081621-c9db0fe93829/cli/compose/loader/full-struct_test.go (about)

     1  package loader
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"time"
     7  
     8  	"github.com/docker/cli/cli/compose/types"
     9  )
    10  
    11  func fullExampleConfig(workingDir, homeDir string) *types.Config {
    12  	return &types.Config{
    13  		Version:  "3.8",
    14  		Services: services(workingDir, homeDir),
    15  		Networks: networks(),
    16  		Volumes:  volumes(),
    17  		Configs:  configs(workingDir),
    18  		Secrets:  secrets(workingDir),
    19  		Extras: map[string]interface{}{
    20  			"x-foo": "bar",
    21  			"x-bar": "baz",
    22  			"x-nested": map[string]interface{}{
    23  				"foo": "bar",
    24  				"bar": "baz",
    25  			},
    26  		},
    27  	}
    28  }
    29  
    30  func services(workingDir, homeDir string) []types.ServiceConfig {
    31  	return []types.ServiceConfig{
    32  		{
    33  			Name: "foo",
    34  
    35  			Build: types.BuildConfig{
    36  				Context:    "./dir",
    37  				Dockerfile: "Dockerfile",
    38  				Args:       map[string]*string{"foo": strPtr("bar")},
    39  				Target:     "foo",
    40  				Network:    "foo",
    41  				CacheFrom:  []string{"foo", "bar"},
    42  				Labels:     map[string]string{"FOO": "BAR"},
    43  			},
    44  			CapAdd:       []string{"ALL"},
    45  			CapDrop:      []string{"NET_ADMIN", "SYS_ADMIN"},
    46  			CgroupParent: "m-executor-abcd",
    47  			Command:      []string{"bundle", "exec", "thin", "-p", "3000"},
    48  			Configs: []types.ServiceConfigObjConfig{
    49  				{
    50  					Source: "config1",
    51  				},
    52  				{
    53  					Source: "config2",
    54  					Target: "/my_config",
    55  					UID:    "103",
    56  					GID:    "103",
    57  					Mode:   uint32Ptr(0440),
    58  				},
    59  			},
    60  			ContainerName: "my-web-container",
    61  			DependsOn:     []string{"db", "redis"},
    62  			Deploy: types.DeployConfig{
    63  				Mode:     "replicated",
    64  				Replicas: uint64Ptr(6),
    65  				Labels:   map[string]string{"FOO": "BAR"},
    66  				RollbackConfig: &types.UpdateConfig{
    67  					Parallelism:     uint64Ptr(3),
    68  					Delay:           types.Duration(10 * time.Second),
    69  					FailureAction:   "continue",
    70  					Monitor:         types.Duration(60 * time.Second),
    71  					MaxFailureRatio: 0.3,
    72  					Order:           "start-first",
    73  				},
    74  				UpdateConfig: &types.UpdateConfig{
    75  					Parallelism:     uint64Ptr(3),
    76  					Delay:           types.Duration(10 * time.Second),
    77  					FailureAction:   "continue",
    78  					Monitor:         types.Duration(60 * time.Second),
    79  					MaxFailureRatio: 0.3,
    80  					Order:           "start-first",
    81  				},
    82  				Resources: types.Resources{
    83  					Limits: &types.Resource{
    84  						NanoCPUs:    "0.001",
    85  						MemoryBytes: 50 * 1024 * 1024,
    86  					},
    87  					Reservations: &types.Resource{
    88  						NanoCPUs:    "0.0001",
    89  						MemoryBytes: 20 * 1024 * 1024,
    90  						GenericResources: []types.GenericResource{
    91  							{
    92  								DiscreteResourceSpec: &types.DiscreteGenericResource{
    93  									Kind:  "gpu",
    94  									Value: 2,
    95  								},
    96  							},
    97  							{
    98  								DiscreteResourceSpec: &types.DiscreteGenericResource{
    99  									Kind:  "ssd",
   100  									Value: 1,
   101  								},
   102  							},
   103  						},
   104  					},
   105  				},
   106  				RestartPolicy: &types.RestartPolicy{
   107  					Condition:   "on-failure",
   108  					Delay:       durationPtr(5 * time.Second),
   109  					MaxAttempts: uint64Ptr(3),
   110  					Window:      durationPtr(2 * time.Minute),
   111  				},
   112  				Placement: types.Placement{
   113  					Constraints: []string{"node=foo"},
   114  					MaxReplicas: uint64(5),
   115  					Preferences: []types.PlacementPreferences{
   116  						{
   117  							Spread: "node.labels.az",
   118  						},
   119  					},
   120  				},
   121  				EndpointMode: "dnsrr",
   122  			},
   123  			Devices:    []string{"/dev/ttyUSB0:/dev/ttyUSB0"},
   124  			DNS:        []string{"8.8.8.8", "9.9.9.9"},
   125  			DNSSearch:  []string{"dc1.example.com", "dc2.example.com"},
   126  			DomainName: "foo.com",
   127  			Entrypoint: []string{"/code/entrypoint.sh", "-p", "3000"},
   128  			Environment: map[string]*string{
   129  				"FOO": strPtr("foo_from_env_file"),
   130  				"BAR": strPtr("bar_from_env_file_2"),
   131  				"BAZ": strPtr("baz_from_service_def"),
   132  				"QUX": strPtr("qux_from_environment"),
   133  			},
   134  			EnvFile: []string{
   135  				"./example1.env",
   136  				"./example2.env",
   137  			},
   138  			Expose: []string{"3000", "8000"},
   139  			ExternalLinks: []string{
   140  				"redis_1",
   141  				"project_db_1:mysql",
   142  				"project_db_1:postgresql",
   143  			},
   144  			ExtraHosts: []string{
   145  				"somehost:162.242.195.82",
   146  				"otherhost:50.31.209.229",
   147  			},
   148  			Extras: map[string]interface{}{
   149  				"x-bar": "baz",
   150  				"x-foo": "bar",
   151  			},
   152  			HealthCheck: &types.HealthCheckConfig{
   153  				Test:        types.HealthCheckTest([]string{"CMD-SHELL", "echo \"hello world\""}),
   154  				Interval:    durationPtr(10 * time.Second),
   155  				Timeout:     durationPtr(1 * time.Second),
   156  				Retries:     uint64Ptr(5),
   157  				StartPeriod: durationPtr(15 * time.Second),
   158  			},
   159  			Hostname: "foo",
   160  			Image:    "redis",
   161  			Ipc:      "host",
   162  			Labels: map[string]string{
   163  				"com.example.description": "Accounting webapp",
   164  				"com.example.number":      "42",
   165  				"com.example.empty-label": "",
   166  			},
   167  			Links: []string{
   168  				"db",
   169  				"db:database",
   170  				"redis",
   171  			},
   172  			Logging: &types.LoggingConfig{
   173  				Driver: "syslog",
   174  				Options: map[string]string{
   175  					"syslog-address": "tcp://192.168.0.42:123",
   176  				},
   177  			},
   178  			MacAddress:  "02:42:ac:11:65:43",
   179  			NetworkMode: "container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b",
   180  			Networks: map[string]*types.ServiceNetworkConfig{
   181  				"some-network": {
   182  					Aliases:     []string{"alias1", "alias3"},
   183  					Ipv4Address: "",
   184  					Ipv6Address: "",
   185  				},
   186  				"other-network": {
   187  					Ipv4Address: "172.16.238.10",
   188  					Ipv6Address: "2001:3984:3989::10",
   189  				},
   190  				"other-other-network": nil,
   191  			},
   192  			Pid: "host",
   193  			Ports: []types.ServicePortConfig{
   194  				//"3000",
   195  				{
   196  					Mode:     "ingress",
   197  					Target:   3000,
   198  					Protocol: "tcp",
   199  				},
   200  				{
   201  					Mode:     "ingress",
   202  					Target:   3001,
   203  					Protocol: "tcp",
   204  				},
   205  				{
   206  					Mode:     "ingress",
   207  					Target:   3002,
   208  					Protocol: "tcp",
   209  				},
   210  				{
   211  					Mode:     "ingress",
   212  					Target:   3003,
   213  					Protocol: "tcp",
   214  				},
   215  				{
   216  					Mode:     "ingress",
   217  					Target:   3004,
   218  					Protocol: "tcp",
   219  				},
   220  				{
   221  					Mode:     "ingress",
   222  					Target:   3005,
   223  					Protocol: "tcp",
   224  				},
   225  				//"8000:8000",
   226  				{
   227  					Mode:      "ingress",
   228  					Target:    8000,
   229  					Published: 8000,
   230  					Protocol:  "tcp",
   231  				},
   232  				//"9090-9091:8080-8081",
   233  				{
   234  					Mode:      "ingress",
   235  					Target:    8080,
   236  					Published: 9090,
   237  					Protocol:  "tcp",
   238  				},
   239  				{
   240  					Mode:      "ingress",
   241  					Target:    8081,
   242  					Published: 9091,
   243  					Protocol:  "tcp",
   244  				},
   245  				//"49100:22",
   246  				{
   247  					Mode:      "ingress",
   248  					Target:    22,
   249  					Published: 49100,
   250  					Protocol:  "tcp",
   251  				},
   252  				//"127.0.0.1:8001:8001",
   253  				{
   254  					Mode:      "ingress",
   255  					Target:    8001,
   256  					Published: 8001,
   257  					Protocol:  "tcp",
   258  				},
   259  				//"127.0.0.1:5000-5010:5000-5010",
   260  				{
   261  					Mode:      "ingress",
   262  					Target:    5000,
   263  					Published: 5000,
   264  					Protocol:  "tcp",
   265  				},
   266  				{
   267  					Mode:      "ingress",
   268  					Target:    5001,
   269  					Published: 5001,
   270  					Protocol:  "tcp",
   271  				},
   272  				{
   273  					Mode:      "ingress",
   274  					Target:    5002,
   275  					Published: 5002,
   276  					Protocol:  "tcp",
   277  				},
   278  				{
   279  					Mode:      "ingress",
   280  					Target:    5003,
   281  					Published: 5003,
   282  					Protocol:  "tcp",
   283  				},
   284  				{
   285  					Mode:      "ingress",
   286  					Target:    5004,
   287  					Published: 5004,
   288  					Protocol:  "tcp",
   289  				},
   290  				{
   291  					Mode:      "ingress",
   292  					Target:    5005,
   293  					Published: 5005,
   294  					Protocol:  "tcp",
   295  				},
   296  				{
   297  					Mode:      "ingress",
   298  					Target:    5006,
   299  					Published: 5006,
   300  					Protocol:  "tcp",
   301  				},
   302  				{
   303  					Mode:      "ingress",
   304  					Target:    5007,
   305  					Published: 5007,
   306  					Protocol:  "tcp",
   307  				},
   308  				{
   309  					Mode:      "ingress",
   310  					Target:    5008,
   311  					Published: 5008,
   312  					Protocol:  "tcp",
   313  				},
   314  				{
   315  					Mode:      "ingress",
   316  					Target:    5009,
   317  					Published: 5009,
   318  					Protocol:  "tcp",
   319  				},
   320  				{
   321  					Mode:      "ingress",
   322  					Target:    5010,
   323  					Published: 5010,
   324  					Protocol:  "tcp",
   325  				},
   326  			},
   327  			Privileged: true,
   328  			ReadOnly:   true,
   329  			Restart:    "always",
   330  			Secrets: []types.ServiceSecretConfig{
   331  				{
   332  					Source: "secret1",
   333  				},
   334  				{
   335  					Source: "secret2",
   336  					Target: "my_secret",
   337  					UID:    "103",
   338  					GID:    "103",
   339  					Mode:   uint32Ptr(0440),
   340  				},
   341  			},
   342  			SecurityOpt: []string{
   343  				"label=level:s0:c100,c200",
   344  				"label=type:svirt_apache_t",
   345  			},
   346  			StdinOpen:       true,
   347  			StopSignal:      "SIGUSR1",
   348  			StopGracePeriod: durationPtr(20 * time.Second),
   349  			Sysctls: map[string]string{
   350  				"net.core.somaxconn":      "1024",
   351  				"net.ipv4.tcp_syncookies": "0",
   352  			},
   353  			Tmpfs: []string{"/run", "/tmp"},
   354  			Tty:   true,
   355  			Ulimits: map[string]*types.UlimitsConfig{
   356  				"nproc": {
   357  					Single: 65535,
   358  				},
   359  				"nofile": {
   360  					Soft: 20000,
   361  					Hard: 40000,
   362  				},
   363  			},
   364  			User: "someone",
   365  			Volumes: []types.ServiceVolumeConfig{
   366  				{Target: "/var/lib/mysql", Type: "volume"},
   367  				{Source: "/opt/data", Target: "/var/lib/mysql", Type: "bind"},
   368  				{Source: workingDir, Target: "/code", Type: "bind"},
   369  				{Source: filepath.Join(workingDir, "static"), Target: "/var/www/html", Type: "bind"},
   370  				{Source: homeDir + "/configs", Target: "/etc/configs/", Type: "bind", ReadOnly: true},
   371  				{Source: "datavolume", Target: "/var/lib/mysql", Type: "volume"},
   372  				{Source: filepath.Join(workingDir, "opt"), Target: "/opt", Consistency: "cached", Type: "bind"},
   373  				{Target: "/opt", Type: "tmpfs", Tmpfs: &types.ServiceVolumeTmpfs{
   374  					Size: int64(10000),
   375  				}},
   376  			},
   377  			WorkingDir: "/code",
   378  		},
   379  	}
   380  }
   381  
   382  func networks() map[string]types.NetworkConfig {
   383  	return map[string]types.NetworkConfig{
   384  		"some-network": {},
   385  
   386  		"other-network": {
   387  			Driver: "overlay",
   388  			DriverOpts: map[string]string{
   389  				"foo": "bar",
   390  				"baz": "1",
   391  			},
   392  			Ipam: types.IPAMConfig{
   393  				Driver: "overlay",
   394  				Config: []*types.IPAMPool{
   395  					{Subnet: "172.16.238.0/24"},
   396  					{Subnet: "2001:3984:3989::/64"},
   397  				},
   398  			},
   399  			Labels: map[string]string{
   400  				"foo": "bar",
   401  			},
   402  		},
   403  
   404  		"external-network": {
   405  			Name:     "external-network",
   406  			External: types.External{External: true},
   407  		},
   408  
   409  		"other-external-network": {
   410  			Name:     "my-cool-network",
   411  			External: types.External{External: true},
   412  			Extras: map[string]interface{}{
   413  				"x-bar": "baz",
   414  				"x-foo": "bar",
   415  			},
   416  		},
   417  	}
   418  }
   419  
   420  func volumes() map[string]types.VolumeConfig {
   421  	return map[string]types.VolumeConfig{
   422  		"some-volume": {},
   423  		"other-volume": {
   424  			Driver: "flocker",
   425  			DriverOpts: map[string]string{
   426  				"foo": "bar",
   427  				"baz": "1",
   428  			},
   429  			Labels: map[string]string{
   430  				"foo": "bar",
   431  			},
   432  		},
   433  		"another-volume": {
   434  			Name:   "user_specified_name",
   435  			Driver: "vsphere",
   436  			DriverOpts: map[string]string{
   437  				"foo": "bar",
   438  				"baz": "1",
   439  			},
   440  		},
   441  		"external-volume": {
   442  			Name:     "external-volume",
   443  			External: types.External{External: true},
   444  		},
   445  		"other-external-volume": {
   446  			Name:     "my-cool-volume",
   447  			External: types.External{External: true},
   448  		},
   449  		"external-volume3": {
   450  			Name:     "this-is-volume3",
   451  			External: types.External{External: true},
   452  			Extras: map[string]interface{}{
   453  				"x-bar": "baz",
   454  				"x-foo": "bar",
   455  			},
   456  		},
   457  	}
   458  }
   459  
   460  func configs(workingDir string) map[string]types.ConfigObjConfig {
   461  	return map[string]types.ConfigObjConfig{
   462  		"config1": {
   463  			File: filepath.Join(workingDir, "config_data"),
   464  			Labels: map[string]string{
   465  				"foo": "bar",
   466  			},
   467  		},
   468  		"config2": {
   469  			Name:     "my_config",
   470  			External: types.External{External: true},
   471  		},
   472  		"config3": {
   473  			Name:     "config3",
   474  			External: types.External{External: true},
   475  		},
   476  		"config4": {
   477  			Name: "foo",
   478  			File: workingDir,
   479  			Extras: map[string]interface{}{
   480  				"x-bar": "baz",
   481  				"x-foo": "bar",
   482  			},
   483  		},
   484  	}
   485  }
   486  
   487  func secrets(workingDir string) map[string]types.SecretConfig {
   488  	return map[string]types.SecretConfig{
   489  		"secret1": {
   490  			File: filepath.Join(workingDir, "secret_data"),
   491  			Labels: map[string]string{
   492  				"foo": "bar",
   493  			},
   494  		},
   495  		"secret2": {
   496  			Name:     "my_secret",
   497  			External: types.External{External: true},
   498  		},
   499  		"secret3": {
   500  			Name:     "secret3",
   501  			External: types.External{External: true},
   502  		},
   503  		"secret4": {
   504  			Name: "bar",
   505  			File: workingDir,
   506  			Extras: map[string]interface{}{
   507  				"x-bar": "baz",
   508  				"x-foo": "bar",
   509  			},
   510  		},
   511  	}
   512  }
   513  
   514  func fullExampleYAML(workingDir string) string {
   515  	return fmt.Sprintf(`version: "3.8"
   516  services:
   517    foo:
   518      build:
   519        context: ./dir
   520        dockerfile: Dockerfile
   521        args:
   522          foo: bar
   523        labels:
   524          FOO: BAR
   525        cache_from:
   526        - foo
   527        - bar
   528        network: foo
   529        target: foo
   530      cap_add:
   531      - ALL
   532      cap_drop:
   533      - NET_ADMIN
   534      - SYS_ADMIN
   535      cgroup_parent: m-executor-abcd
   536      command:
   537      - bundle
   538      - exec
   539      - thin
   540      - -p
   541      - "3000"
   542      configs:
   543      - source: config1
   544      - source: config2
   545        target: /my_config
   546        uid: "103"
   547        gid: "103"
   548        mode: 288
   549      container_name: my-web-container
   550      depends_on:
   551      - db
   552      - redis
   553      deploy:
   554        mode: replicated
   555        replicas: 6
   556        labels:
   557          FOO: BAR
   558        update_config:
   559          parallelism: 3
   560          delay: 10s
   561          failure_action: continue
   562          monitor: 1m0s
   563          max_failure_ratio: 0.3
   564          order: start-first
   565        rollback_config:
   566          parallelism: 3
   567          delay: 10s
   568          failure_action: continue
   569          monitor: 1m0s
   570          max_failure_ratio: 0.3
   571          order: start-first
   572        resources:
   573          limits:
   574            cpus: "0.001"
   575            memory: "52428800"
   576          reservations:
   577            cpus: "0.0001"
   578            memory: "20971520"
   579            generic_resources:
   580            - discrete_resource_spec:
   581                kind: gpu
   582                value: 2
   583            - discrete_resource_spec:
   584                kind: ssd
   585                value: 1
   586        restart_policy:
   587          condition: on-failure
   588          delay: 5s
   589          max_attempts: 3
   590          window: 2m0s
   591        placement:
   592          constraints:
   593          - node=foo
   594          preferences:
   595          - spread: node.labels.az
   596          max_replicas_per_node: 5
   597        endpoint_mode: dnsrr
   598      devices:
   599      - /dev/ttyUSB0:/dev/ttyUSB0
   600      dns:
   601      - 8.8.8.8
   602      - 9.9.9.9
   603      dns_search:
   604      - dc1.example.com
   605      - dc2.example.com
   606      domainname: foo.com
   607      entrypoint:
   608      - /code/entrypoint.sh
   609      - -p
   610      - "3000"
   611      environment:
   612        BAR: bar_from_env_file_2
   613        BAZ: baz_from_service_def
   614        FOO: foo_from_env_file
   615        QUX: qux_from_environment
   616      env_file:
   617      - ./example1.env
   618      - ./example2.env
   619      expose:
   620      - "3000"
   621      - "8000"
   622      external_links:
   623      - redis_1
   624      - project_db_1:mysql
   625      - project_db_1:postgresql
   626      extra_hosts:
   627      - somehost:162.242.195.82
   628      - otherhost:50.31.209.229
   629      hostname: foo
   630      healthcheck:
   631        test:
   632        - CMD-SHELL
   633        - echo "hello world"
   634        timeout: 1s
   635        interval: 10s
   636        retries: 5
   637        start_period: 15s
   638      image: redis
   639      ipc: host
   640      labels:
   641        com.example.description: Accounting webapp
   642        com.example.empty-label: ""
   643        com.example.number: "42"
   644      links:
   645      - db
   646      - db:database
   647      - redis
   648      logging:
   649        driver: syslog
   650        options:
   651          syslog-address: tcp://192.168.0.42:123
   652      mac_address: 02:42:ac:11:65:43
   653      network_mode: container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b
   654      networks:
   655        other-network:
   656          ipv4_address: 172.16.238.10
   657          ipv6_address: 2001:3984:3989::10
   658        other-other-network: null
   659        some-network:
   660          aliases:
   661          - alias1
   662          - alias3
   663      pid: host
   664      ports:
   665      - mode: ingress
   666        target: 3000
   667        protocol: tcp
   668      - mode: ingress
   669        target: 3001
   670        protocol: tcp
   671      - mode: ingress
   672        target: 3002
   673        protocol: tcp
   674      - mode: ingress
   675        target: 3003
   676        protocol: tcp
   677      - mode: ingress
   678        target: 3004
   679        protocol: tcp
   680      - mode: ingress
   681        target: 3005
   682        protocol: tcp
   683      - mode: ingress
   684        target: 8000
   685        published: 8000
   686        protocol: tcp
   687      - mode: ingress
   688        target: 8080
   689        published: 9090
   690        protocol: tcp
   691      - mode: ingress
   692        target: 8081
   693        published: 9091
   694        protocol: tcp
   695      - mode: ingress
   696        target: 22
   697        published: 49100
   698        protocol: tcp
   699      - mode: ingress
   700        target: 8001
   701        published: 8001
   702        protocol: tcp
   703      - mode: ingress
   704        target: 5000
   705        published: 5000
   706        protocol: tcp
   707      - mode: ingress
   708        target: 5001
   709        published: 5001
   710        protocol: tcp
   711      - mode: ingress
   712        target: 5002
   713        published: 5002
   714        protocol: tcp
   715      - mode: ingress
   716        target: 5003
   717        published: 5003
   718        protocol: tcp
   719      - mode: ingress
   720        target: 5004
   721        published: 5004
   722        protocol: tcp
   723      - mode: ingress
   724        target: 5005
   725        published: 5005
   726        protocol: tcp
   727      - mode: ingress
   728        target: 5006
   729        published: 5006
   730        protocol: tcp
   731      - mode: ingress
   732        target: 5007
   733        published: 5007
   734        protocol: tcp
   735      - mode: ingress
   736        target: 5008
   737        published: 5008
   738        protocol: tcp
   739      - mode: ingress
   740        target: 5009
   741        published: 5009
   742        protocol: tcp
   743      - mode: ingress
   744        target: 5010
   745        published: 5010
   746        protocol: tcp
   747      privileged: true
   748      read_only: true
   749      restart: always
   750      secrets:
   751      - source: secret1
   752      - source: secret2
   753        target: my_secret
   754        uid: "103"
   755        gid: "103"
   756        mode: 288
   757      security_opt:
   758      - label=level:s0:c100,c200
   759      - label=type:svirt_apache_t
   760      stdin_open: true
   761      stop_grace_period: 20s
   762      stop_signal: SIGUSR1
   763      sysctls:
   764        net.core.somaxconn: "1024"
   765        net.ipv4.tcp_syncookies: "0"
   766      tmpfs:
   767      - /run
   768      - /tmp
   769      tty: true
   770      ulimits:
   771        nofile:
   772          soft: 20000
   773          hard: 40000
   774        nproc: 65535
   775      user: someone
   776      volumes:
   777      - type: volume
   778        target: /var/lib/mysql
   779      - type: bind
   780        source: /opt/data
   781        target: /var/lib/mysql
   782      - type: bind
   783        source: /foo
   784        target: /code
   785      - type: bind
   786        source: %s
   787        target: /var/www/html
   788      - type: bind
   789        source: /bar/configs
   790        target: /etc/configs/
   791        read_only: true
   792      - type: volume
   793        source: datavolume
   794        target: /var/lib/mysql
   795      - type: bind
   796        source: %s
   797        target: /opt
   798        consistency: cached
   799      - type: tmpfs
   800        target: /opt
   801        tmpfs:
   802          size: 10000
   803      working_dir: /code
   804      x-bar: baz
   805      x-foo: bar
   806  networks:
   807    external-network:
   808      name: external-network
   809      external: true
   810    other-external-network:
   811      name: my-cool-network
   812      external: true
   813      x-bar: baz
   814      x-foo: bar
   815    other-network:
   816      driver: overlay
   817      driver_opts:
   818        baz: "1"
   819        foo: bar
   820      ipam:
   821        driver: overlay
   822        config:
   823        - subnet: 172.16.238.0/24
   824        - subnet: 2001:3984:3989::/64
   825      labels:
   826        foo: bar
   827    some-network: {}
   828  volumes:
   829    another-volume:
   830      name: user_specified_name
   831      driver: vsphere
   832      driver_opts:
   833        baz: "1"
   834        foo: bar
   835    external-volume:
   836      name: external-volume
   837      external: true
   838    external-volume3:
   839      name: this-is-volume3
   840      external: true
   841      x-bar: baz
   842      x-foo: bar
   843    other-external-volume:
   844      name: my-cool-volume
   845      external: true
   846    other-volume:
   847      driver: flocker
   848      driver_opts:
   849        baz: "1"
   850        foo: bar
   851      labels:
   852        foo: bar
   853    some-volume: {}
   854  secrets:
   855    secret1:
   856      file: %s/secret_data
   857      labels:
   858        foo: bar
   859    secret2:
   860      name: my_secret
   861      external: true
   862    secret3:
   863      name: secret3
   864      external: true
   865    secret4:
   866      name: bar
   867      file: %s
   868      x-bar: baz
   869      x-foo: bar
   870  configs:
   871    config1:
   872      file: %s/config_data
   873      labels:
   874        foo: bar
   875    config2:
   876      name: my_config
   877      external: true
   878    config3:
   879      name: config3
   880      external: true
   881    config4:
   882      name: foo
   883      file: %s
   884      x-bar: baz
   885      x-foo: bar
   886  x-bar: baz
   887  x-foo: bar
   888  x-nested:
   889    bar: baz
   890    foo: bar
   891  `,
   892  		filepath.Join(workingDir, "static"),
   893  		filepath.Join(workingDir, "opt"),
   894  		workingDir,
   895  		workingDir,
   896  		workingDir,
   897  		workingDir)
   898  }
   899  
   900  func fullExampleJSON(workingDir string) string {
   901  	return fmt.Sprintf(`{
   902    "configs": {
   903      "config1": {
   904        "file": "%s/config_data",
   905        "external": false,
   906        "labels": {
   907          "foo": "bar"
   908        }
   909      },
   910      "config2": {
   911        "name": "my_config",
   912        "external": true
   913      },
   914      "config3": {
   915        "name": "config3",
   916        "external": true
   917      },
   918      "config4": {
   919        "name": "foo",
   920        "file": "%s",
   921        "external": false
   922      }
   923    },
   924    "networks": {
   925      "external-network": {
   926        "name": "external-network",
   927        "ipam": {},
   928        "external": true
   929      },
   930      "other-external-network": {
   931        "name": "my-cool-network",
   932        "ipam": {},
   933        "external": true
   934      },
   935      "other-network": {
   936        "driver": "overlay",
   937        "driver_opts": {
   938          "baz": "1",
   939          "foo": "bar"
   940        },
   941        "ipam": {
   942          "driver": "overlay",
   943          "config": [
   944            {
   945              "subnet": "172.16.238.0/24"
   946            },
   947            {
   948              "subnet": "2001:3984:3989::/64"
   949            }
   950          ]
   951        },
   952        "external": false,
   953        "labels": {
   954          "foo": "bar"
   955        }
   956      },
   957      "some-network": {
   958        "ipam": {},
   959        "external": false
   960      }
   961    },
   962    "secrets": {
   963      "secret1": {
   964        "file": "%s/secret_data",
   965        "external": false,
   966        "labels": {
   967          "foo": "bar"
   968        }
   969      },
   970      "secret2": {
   971        "name": "my_secret",
   972        "external": true
   973      },
   974      "secret3": {
   975        "name": "secret3",
   976        "external": true
   977      },
   978      "secret4": {
   979        "name": "bar",
   980        "file": "%s",
   981        "external": false
   982      }
   983    },
   984    "services": {
   985      "foo": {
   986        "build": {
   987          "context": "./dir",
   988          "dockerfile": "Dockerfile",
   989          "args": {
   990            "foo": "bar"
   991          },
   992          "labels": {
   993            "FOO": "BAR"
   994          },
   995          "cache_from": [
   996            "foo",
   997            "bar"
   998          ],
   999          "network": "foo",
  1000          "target": "foo"
  1001        },
  1002        "cap_add": [
  1003          "ALL"
  1004        ],
  1005        "cap_drop": [
  1006          "NET_ADMIN",
  1007          "SYS_ADMIN"
  1008        ],
  1009        "cgroup_parent": "m-executor-abcd",
  1010        "command": [
  1011          "bundle",
  1012          "exec",
  1013          "thin",
  1014          "-p",
  1015          "3000"
  1016        ],
  1017        "configs": [
  1018          {
  1019            "source": "config1"
  1020          },
  1021          {
  1022            "source": "config2",
  1023            "target": "/my_config",
  1024            "uid": "103",
  1025            "gid": "103",
  1026            "mode": 288
  1027          }
  1028        ],
  1029        "container_name": "my-web-container",
  1030        "credential_spec": {},
  1031        "depends_on": [
  1032          "db",
  1033          "redis"
  1034        ],
  1035        "deploy": {
  1036          "mode": "replicated",
  1037          "replicas": 6,
  1038          "labels": {
  1039            "FOO": "BAR"
  1040          },
  1041          "update_config": {
  1042            "parallelism": 3,
  1043            "delay": "10s",
  1044            "failure_action": "continue",
  1045            "monitor": "1m0s",
  1046            "max_failure_ratio": 0.3,
  1047            "order": "start-first"
  1048          },
  1049          "rollback_config": {
  1050            "parallelism": 3,
  1051            "delay": "10s",
  1052            "failure_action": "continue",
  1053            "monitor": "1m0s",
  1054            "max_failure_ratio": 0.3,
  1055            "order": "start-first"
  1056          },
  1057          "resources": {
  1058            "limits": {
  1059              "cpus": "0.001",
  1060              "memory": "52428800"
  1061            },
  1062            "reservations": {
  1063              "cpus": "0.0001",
  1064              "memory": "20971520",
  1065              "generic_resources": [
  1066                {
  1067                  "discrete_resource_spec": {
  1068                    "kind": "gpu",
  1069                    "value": 2
  1070                  }
  1071                },
  1072                {
  1073                  "discrete_resource_spec": {
  1074                    "kind": "ssd",
  1075                    "value": 1
  1076                  }
  1077                }
  1078              ]
  1079            }
  1080          },
  1081          "restart_policy": {
  1082            "condition": "on-failure",
  1083            "delay": "5s",
  1084            "max_attempts": 3,
  1085            "window": "2m0s"
  1086          },
  1087          "placement": {
  1088            "constraints": [
  1089              "node=foo"
  1090            ],
  1091            "preferences": [
  1092              {
  1093                "spread": "node.labels.az"
  1094              }
  1095            ],
  1096            "max_replicas_per_node": 5
  1097          },
  1098          "endpoint_mode": "dnsrr"
  1099        },
  1100        "devices": [
  1101          "/dev/ttyUSB0:/dev/ttyUSB0"
  1102        ],
  1103        "dns": [
  1104          "8.8.8.8",
  1105          "9.9.9.9"
  1106        ],
  1107        "dns_search": [
  1108          "dc1.example.com",
  1109          "dc2.example.com"
  1110        ],
  1111        "domainname": "foo.com",
  1112        "entrypoint": [
  1113          "/code/entrypoint.sh",
  1114          "-p",
  1115          "3000"
  1116        ],
  1117        "environment": {
  1118          "BAR": "bar_from_env_file_2",
  1119          "BAZ": "baz_from_service_def",
  1120          "FOO": "foo_from_env_file",
  1121          "QUX": "qux_from_environment"
  1122        },
  1123        "env_file": [
  1124          "./example1.env",
  1125          "./example2.env"
  1126        ],
  1127        "expose": [
  1128          "3000",
  1129          "8000"
  1130        ],
  1131        "external_links": [
  1132          "redis_1",
  1133          "project_db_1:mysql",
  1134          "project_db_1:postgresql"
  1135        ],
  1136        "extra_hosts": [
  1137          "somehost:162.242.195.82",
  1138          "otherhost:50.31.209.229"
  1139        ],
  1140        "hostname": "foo",
  1141        "healthcheck": {
  1142          "test": [
  1143            "CMD-SHELL",
  1144            "echo \"hello world\""
  1145          ],
  1146          "timeout": "1s",
  1147          "interval": "10s",
  1148          "retries": 5,
  1149          "start_period": "15s"
  1150        },
  1151        "image": "redis",
  1152        "ipc": "host",
  1153        "labels": {
  1154          "com.example.description": "Accounting webapp",
  1155          "com.example.empty-label": "",
  1156          "com.example.number": "42"
  1157        },
  1158        "links": [
  1159          "db",
  1160          "db:database",
  1161          "redis"
  1162        ],
  1163        "logging": {
  1164          "driver": "syslog",
  1165          "options": {
  1166            "syslog-address": "tcp://192.168.0.42:123"
  1167          }
  1168        },
  1169        "mac_address": "02:42:ac:11:65:43",
  1170        "network_mode": "container:0cfeab0f748b9a743dc3da582046357c6ef497631c1a016d28d2bf9b4f899f7b",
  1171        "networks": {
  1172          "other-network": {
  1173            "ipv4_address": "172.16.238.10",
  1174            "ipv6_address": "2001:3984:3989::10"
  1175          },
  1176          "other-other-network": null,
  1177          "some-network": {
  1178            "aliases": [
  1179              "alias1",
  1180              "alias3"
  1181            ]
  1182          }
  1183        },
  1184        "pid": "host",
  1185        "ports": [
  1186          {
  1187            "mode": "ingress",
  1188            "target": 3000,
  1189            "protocol": "tcp"
  1190          },
  1191          {
  1192            "mode": "ingress",
  1193            "target": 3001,
  1194            "protocol": "tcp"
  1195          },
  1196          {
  1197            "mode": "ingress",
  1198            "target": 3002,
  1199            "protocol": "tcp"
  1200          },
  1201          {
  1202            "mode": "ingress",
  1203            "target": 3003,
  1204            "protocol": "tcp"
  1205          },
  1206          {
  1207            "mode": "ingress",
  1208            "target": 3004,
  1209            "protocol": "tcp"
  1210          },
  1211          {
  1212            "mode": "ingress",
  1213            "target": 3005,
  1214            "protocol": "tcp"
  1215          },
  1216          {
  1217            "mode": "ingress",
  1218            "target": 8000,
  1219            "published": 8000,
  1220            "protocol": "tcp"
  1221          },
  1222          {
  1223            "mode": "ingress",
  1224            "target": 8080,
  1225            "published": 9090,
  1226            "protocol": "tcp"
  1227          },
  1228          {
  1229            "mode": "ingress",
  1230            "target": 8081,
  1231            "published": 9091,
  1232            "protocol": "tcp"
  1233          },
  1234          {
  1235            "mode": "ingress",
  1236            "target": 22,
  1237            "published": 49100,
  1238            "protocol": "tcp"
  1239          },
  1240          {
  1241            "mode": "ingress",
  1242            "target": 8001,
  1243            "published": 8001,
  1244            "protocol": "tcp"
  1245          },
  1246          {
  1247            "mode": "ingress",
  1248            "target": 5000,
  1249            "published": 5000,
  1250            "protocol": "tcp"
  1251          },
  1252          {
  1253            "mode": "ingress",
  1254            "target": 5001,
  1255            "published": 5001,
  1256            "protocol": "tcp"
  1257          },
  1258          {
  1259            "mode": "ingress",
  1260            "target": 5002,
  1261            "published": 5002,
  1262            "protocol": "tcp"
  1263          },
  1264          {
  1265            "mode": "ingress",
  1266            "target": 5003,
  1267            "published": 5003,
  1268            "protocol": "tcp"
  1269          },
  1270          {
  1271            "mode": "ingress",
  1272            "target": 5004,
  1273            "published": 5004,
  1274            "protocol": "tcp"
  1275          },
  1276          {
  1277            "mode": "ingress",
  1278            "target": 5005,
  1279            "published": 5005,
  1280            "protocol": "tcp"
  1281          },
  1282          {
  1283            "mode": "ingress",
  1284            "target": 5006,
  1285            "published": 5006,
  1286            "protocol": "tcp"
  1287          },
  1288          {
  1289            "mode": "ingress",
  1290            "target": 5007,
  1291            "published": 5007,
  1292            "protocol": "tcp"
  1293          },
  1294          {
  1295            "mode": "ingress",
  1296            "target": 5008,
  1297            "published": 5008,
  1298            "protocol": "tcp"
  1299          },
  1300          {
  1301            "mode": "ingress",
  1302            "target": 5009,
  1303            "published": 5009,
  1304            "protocol": "tcp"
  1305          },
  1306          {
  1307            "mode": "ingress",
  1308            "target": 5010,
  1309            "published": 5010,
  1310            "protocol": "tcp"
  1311          }
  1312        ],
  1313        "privileged": true,
  1314        "read_only": true,
  1315        "restart": "always",
  1316        "secrets": [
  1317          {
  1318            "source": "secret1"
  1319          },
  1320          {
  1321            "source": "secret2",
  1322            "target": "my_secret",
  1323            "uid": "103",
  1324            "gid": "103",
  1325            "mode": 288
  1326          }
  1327        ],
  1328        "security_opt": [
  1329          "label=level:s0:c100,c200",
  1330          "label=type:svirt_apache_t"
  1331        ],
  1332        "stdin_open": true,
  1333        "stop_grace_period": "20s",
  1334        "stop_signal": "SIGUSR1",
  1335        "sysctls": {
  1336          "net.core.somaxconn": "1024",
  1337          "net.ipv4.tcp_syncookies": "0"
  1338        },
  1339        "tmpfs": [
  1340          "/run",
  1341          "/tmp"
  1342        ],
  1343        "tty": true,
  1344        "ulimits": {
  1345          "nofile": {
  1346            "soft": 20000,
  1347            "hard": 40000
  1348          },
  1349          "nproc": 65535
  1350        },
  1351        "user": "someone",
  1352        "volumes": [
  1353          {
  1354            "type": "volume",
  1355            "target": "/var/lib/mysql"
  1356          },
  1357          {
  1358            "type": "bind",
  1359            "source": "/opt/data",
  1360            "target": "/var/lib/mysql"
  1361          },
  1362          {
  1363            "type": "bind",
  1364            "source": "/foo",
  1365            "target": "/code"
  1366          },
  1367          {
  1368            "type": "bind",
  1369            "source": "%s",
  1370            "target": "/var/www/html"
  1371          },
  1372          {
  1373            "type": "bind",
  1374            "source": "/bar/configs",
  1375            "target": "/etc/configs/",
  1376            "read_only": true
  1377          },
  1378          {
  1379            "type": "volume",
  1380            "source": "datavolume",
  1381            "target": "/var/lib/mysql"
  1382          },
  1383          {
  1384            "type": "bind",
  1385            "source": "%s",
  1386            "target": "/opt",
  1387            "consistency": "cached"
  1388          },
  1389          {
  1390            "type": "tmpfs",
  1391            "target": "/opt",
  1392            "tmpfs": {
  1393              "size": 10000
  1394            }
  1395          }
  1396        ],
  1397        "working_dir": "/code"
  1398      }
  1399    },
  1400    "version": "3.8",
  1401    "volumes": {
  1402      "another-volume": {
  1403        "name": "user_specified_name",
  1404        "driver": "vsphere",
  1405        "driver_opts": {
  1406          "baz": "1",
  1407          "foo": "bar"
  1408        },
  1409        "external": false
  1410      },
  1411      "external-volume": {
  1412        "name": "external-volume",
  1413        "external": true
  1414      },
  1415      "external-volume3": {
  1416        "name": "this-is-volume3",
  1417        "external": true
  1418      },
  1419      "other-external-volume": {
  1420        "name": "my-cool-volume",
  1421        "external": true
  1422      },
  1423      "other-volume": {
  1424        "driver": "flocker",
  1425        "driver_opts": {
  1426          "baz": "1",
  1427          "foo": "bar"
  1428        },
  1429        "external": false,
  1430        "labels": {
  1431          "foo": "bar"
  1432        }
  1433      },
  1434      "some-volume": {
  1435        "external": false
  1436      }
  1437    },
  1438    "x-bar": "baz",
  1439    "x-foo": "bar",
  1440    "x-nested": {
  1441      "bar": "baz",
  1442      "foo": "bar"
  1443    }
  1444  }`,
  1445  		workingDir,
  1446  		workingDir,
  1447  		workingDir,
  1448  		workingDir,
  1449  		filepath.Join(workingDir, "static"),
  1450  		filepath.Join(workingDir, "opt"))
  1451  }