Class: Wip::ComposeFile

Inherits:
Object
  • Object
show all
Defined in:
lib/wip/compose_file.rb

Overview

Parses compose.yml/docker-compose.yml into the shape mode: compose-native needs to drive wslc directly, in place of an external compose-for-wslc binary (see ComposeBridge/mode: compose).

This exists only because wslc has no native Compose support yet (tracked upstream in microsoft/WSL#40948). Delete this file — and its hooks in config.rb, cli.rb, doctor.rb and initializer.rb (see README "Compose mode (native)") — once wslc ships that support, or a compose-for-wslc tool reliably supports run.

Defined Under Namespace

Classes: Service

Constant Summary collapse

SERVICE_KEYS =
%w[image build command environment ports volumes working_dir user depends_on].freeze
IGNORED_SERVICE_KEYS =

Real Compose keys that read as meaningful here but have nothing to map onto: TTY/stdin allocation is already decided per invocation (see CommandBuilder#tty?), not fixed per service; there's no per-service network to join beyond the one project network network (config.rb) already puts every service on; wslc run/exec has no restart-policy or capability flag to forward restart:/cap_add: to; and profiles: gates which services a real docker compose up starts by default, which doesn't apply here since wip never starts "every service" — only compose.service and whatever it reaches via depends_on.

%w[tty stdin_open networks restart cap_add profiles].freeze
BUILD_KEYS =
%w[context dockerfile args].freeze
SUPPORTED_CONDITIONS =
%w[service_started].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(services, path:) ⇒ ComposeFile

Returns a new instance of ComposeFile.



47
48
49
50
51
52
# File 'lib/wip/compose_file.rb', line 47

def initialize(services, path:)
  @path = path
  @services = services.to_h { |name, entry| [name.to_s, build_service(name.to_s, entry)] }
  validate_depends_on!
  @order = topological_order
end

Class Method Details

.load(path, env: {}) ⇒ Object

env interpolates compose.yml's $VAR references the way docker compose does, so values like user: ${USER_ID}:${GROUP_ID} reach wslc already substituted instead of literally (see Config#compose_interpolation_env for what's passed in).



36
37
38
39
40
41
42
43
44
45
# File 'lib/wip/compose_file.rb', line 36

def self.load(path, env: {})
  raw = VariableInterpolation.tree(YAML.safe_load_file(path, aliases: true), env)
  raise ConfigError, "#{path}: services: must be a mapping" unless raw.is_a?(Hash) && raw['services'].is_a?(Hash)

  new(raw['services'], path: path)
rescue Psych::Exception => e
  raise ConfigError, "Could not parse #{path}: #{e.message}"
rescue Errno::ENOENT
  raise ConfigError, "Compose file not found: #{path}"
end

Instance Method Details

#build_specsObject

name => dockerfile:, tag: for every service with a build:.



57
58
59
60
61
62
63
64
# File 'lib/wip/compose_file.rb', line 57

def build_specs
  @order.filter_map do |name|
    service = @services.fetch(name)
    next unless service.build

    [name, service.build.merge('tag' => image_tag(name, service))]
  end.to_h
end

#service_names_in_dependency_orderObject



54
# File 'lib/wip/compose_file.rb', line 54

def service_names_in_dependency_order = @order.dup

#to_dependencies_hashObject

Shaped like Config::DEPENDENCY_DEFAULTS expects: image/command/env/ports/volumes/workdir, in dependency order so callers iterating sidecars start them before their dependents.



68
69
70
71
72
73
74
75
# File 'lib/wip/compose_file.rb', line 68

def to_dependencies_hash
  @order.to_h do |name|
    service = @services.fetch(name)
    [name, { 'image' => service.build ? image_tag(name, service) : service.image, 'command' => service.command,
             'env' => service.env, 'ports' => service.ports, 'volumes' => service.volumes,
             'workdir' => service.workdir, 'user' => service.user }]
  end
end