require 'shellwords' class Array def deep_compact map do |value| value = value.deep_compact if value.respond_to?(:deep_compact) value end.compact.yield_self do |x| x.empty? ? nil : x end end end class Hash def deep_compact transform_values do |value| value = value.deep_compact if value.respond_to?(:deep_compact) value end.compact.yield_self do |x| x.empty? ? nil : x end end end module Siren class Compose module HashInitialize def initialize (data = {}) data.each do |key, value| self.__send__("#{key}=", value) end end end end end require_relative "service" module Siren class Compose class RestartPolicy < Struct.new(:condition, :delay, :max_attempts, :window) include HashInitialize end class RollbackConfig < Struct.new(:parallelism, :delay, :failure_action, :monitor, :max_failure_ratio, :order) include HashInitialize end class UpdateConfig < Struct.new(:parallelism, :delay, :failure_action, :monitor, :max_failure_ratio, :order) include HashInitialize end class Deploy < Struct.new(:endpoint_mode, :labels, :mode, :placement, :replicas, :resources, :restart_policy, :rollback_config, :update_config) include HashInitialize def restart_policy= (data) data = RestartPolicy.new(data) end def rollback_config= (data) data = RollbackConfig.new(data) end def update_config= (data) data = UpdateConfig.new(data) end end # restart_policy: object( # condition: string(["none", "on-failure", "any"]), # delay: duration, # max_attemtps: integer, # window: duration, # ), # rollback_config: object( # parallelism: integer, # delay: duration, # failure_action: string(["continue", "pause"]), # monitor: duration, # max_failure_ratio: number, # order: string(["stop-first", "start-first"]), # ), # update_config: object( # parallelism: integer, # delay: duration, # failure_action: string(["continue", "pause", "rollback"]), # monitor: duration, # max_failure_ratio: number, # order: string(["stop-first", "start-first"]), # ), # deploy: object( # endpoint_mode: string(["vip", "dnsrr"]), # labels: hashlike, # mode: string(["global", "replicated"]), # placement: object( # constraints: array(string), # preferences: array(object(spread: string)), # ), # replicas: integer, # resources: object( # limits: resources, # reservations: resources, # ), Volume = Struct.new(:compose, :driver, :driver_opts, :external, :labels, :name) Network = Struct.new(:compose, :driver, :driver_opts, :external, :labels, :name, :attachable, :ipam, :internal) Config = Struct.new(:compose, :file, :external, :name) Secret = Struct.new(:compose, :file, :external, :name) end end # version: string(/[0-9]+(\.[0-9]+)?/), # services: hash( # build: any(string, object( # context: string, # dockerfile: string, # args: hashlike, # cache_from: array(string), # labels: hashlike, # shm_size: string, # target: string) # ), # command: any(string, array(string)), # configs: array(any(string, object( # source: string, target: string, uid: any(string, integer), gid: any(string, integer), mode: any(string, integer) # ))), # container_name: string, # credential_spec: any(object(file: string), object(registry: string), object(config: string)), # deploy: object( # endpoint_mode: string(["vip", "dnsrr"]), # labels: hashlike, # mode: string(["global", "replicated"]), # placement: object( # constraints: array(string), # preferences: array(object(spread: string)), # ), # replicas: integer, # resources: object( # limits: resources, # reservations: resources, # ), # restart_policy: object( # condition: string(["none", "on-failure", "any"]), # delay: duration, # max_attemtps: integer, # window: duration, # ), # rollback_config: object( # parallelism: integer, # delay: duration, # failure_action: string(["continue", "pause"]), # monitor: duration, # max_failure_ratio: number, # order: string(["stop-first", "start-first"]), # ), # update_config: object( # parallelism: integer, # delay: duration, # failure_action: string(["continue", "pause", "rollback"]), # monitor: duration, # max_failure_ratio: number, # order: string(["stop-first", "start-first"]), # ), # ), # dns: any(string, array(string)), # dns_search: any(string, array(string)), # entrypoint: any(string, array(string)), # environment: hashlike, # expose: array(string), # extra_hosts: array(string), # healthcheck: object( # test: any(string, array(string)), # interval: duration, # timeout: duration, # retries: integer, # start_period: duration, # ), # image: string, # init: bool, # labels: hashlike, # logging: object( # driver: string, # options: hash(string), # ), # networks: any(array(string), hash(object(aliases: array(string), ipv4_address: string, ipv6_address: string))), # pid: string("host"), # ports: array(any(string, object(target: integer, published: integer, protocol: string(["tcp", "udp"]), mode: string(["host", "ingress"])))), # secrets: array(any(string, object(source: string, target: string, uid: integer, gid: integer, mode: integer))), # stop_grace_period: duration, # stop_signal: string(/^SIG/), # sysctls: hashlike, # ulimits: hash(any(integer, object(soft: integer, hard: integer))), # volumes: array(any(string, # object(type: string(["volume", "bind", "tmpfs", "npipe"]), # source: string, target: string, read_only: boolean, # consistency: string(["consistent", "cached", "delegated"]), # volume: object(nocopy: boolean), bind: object(propagation: string), # tmpfs: object(size: bytesize)), # )), # domainname: string, # hostname: string, # ipc: string, # mac_address: string, # privileged: boolean, # read_only: boolean, # shm_size: bytesize, # stdin_open: boolean, # tty: boolean, # user: any(string, integer), # working_dir: string, # ), # volumes: hash(any(null, object(driver: string, driver_opts: hash(string), external: boolean, labels: hashlike, name: string))), # networks: hash(any(null, object( # driver: string, # driver_opts: hash(string), # external: any(boolean, object(name: string)), # attachable: boolean, # ipam: object( # driver: string, # config: array(object(subnet: string)) # ), # internal: boolean, # labels: hashlike, # name: string, # ))), # configs: hash(object(file: string, external: any(boolean, object(name: string)))), # secrets: hash(object(file: string, external: boolean, name: string)),