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