File: docker.rb

package info (click to toggle)
ruby-train 3.2.28-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 1,116 kB
  • sloc: ruby: 9,246; sh: 17; makefile: 8
file content (101 lines) | stat: -rw-r--r-- 2,524 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
require "docker"

module Train::Transports
  class Docker < Train.plugin(1)
    name "docker"

    include_options Train::Extras::CommandWrapper
    option :host, required: true

    def connection(state = {}, &block)
      opts = merge_options(options, state || {})
      validate_options(opts)

      if @connection && @connection_options == opts
        reuse_connection(&block)
      else
        create_new_connection(opts, &block)
      end
    end

    private

    # Creates a new Docker connection instance and save it for potential future
    # reuse.
    #
    # @param options [Hash] connection options
    # @return [Docker::Connection] a Docker connection instance
    # @api private
    def create_new_connection(options, &block)
      if @connection
        logger.debug("[Docker] shutting previous connection #{@connection}")
        @connection.close
      end

      @connection_options = options
      @connection = Connection.new(options, &block)
    end

    # Return the last saved Docker connection instance.
    #
    # @return [Docker::Connection] a Docker connection instance
    # @api private
    def reuse_connection
      logger.debug("[Docker] reusing existing connection #{@connection}")
      yield @connection if block_given?
      @connection
    end
  end
end

class Train::Transports::Docker
  class Connection < BaseConnection
    def initialize(conf)
      super(conf)
      @id = options[:host]
      @container = ::Docker::Container.get(@id) ||
        raise("Can't find Docker container #{@id}")
      @cmd_wrapper = nil
      @cmd_wrapper = CommandWrapper.load(self, @options)
    end

    def close
      # nothing to do at the moment
    end

    def uri
      if @container.nil?
        "docker://#{@id}"
      else
        "docker://#{@container.id}"
      end
    end

    private

    def file_via_connection(path)
      if os.aix?
        Train::File::Remote::Aix.new(self, path)
      elsif os.solaris?
        Train::File::Remote::Unix.new(self, path)
      else
        Train::File::Remote::Linux.new(self, path)
      end
    end

    def run_command_via_connection(cmd, &_data_handler)
      cmd = @cmd_wrapper.run(cmd) unless @cmd_wrapper.nil?
      stdout, stderr, exit_status = @container.exec(
        [
          "/bin/sh", "-c", cmd
        ]
      )
      CommandResult.new(stdout.join, stderr.join, exit_status)
    rescue ::Docker::Error::DockerError => _
      raise
    rescue => _
      # @TODO: differentiate any other error
      raise
    end
  end
end