devkitkat 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +13 -11
- data/README.md +2 -2
- data/bin/devkitkat +1 -1
- data/devkitkat.gemspec +2 -1
- data/lib/devkitkat/command.rb +6 -8
- data/lib/devkitkat/config.rb +33 -20
- data/lib/devkitkat/processor.rb +48 -0
- data/lib/devkitkat/service/concerns/service_initializer.rb +17 -0
- data/lib/devkitkat/service/driver/base.rb +23 -0
- data/lib/devkitkat/service/driver/docker/container.rb +163 -0
- data/lib/devkitkat/service/driver/docker/image.rb +33 -0
- data/lib/devkitkat/service/driver/docker.rb +45 -0
- data/lib/devkitkat/service/driver/none.rb +19 -0
- data/lib/devkitkat/service/executor/logger.rb +22 -0
- data/lib/devkitkat/service/executor/scripter.rb +48 -0
- data/lib/devkitkat/service/executor/variables.rb +82 -0
- data/lib/devkitkat/service/executor.rb +102 -0
- data/lib/devkitkat/service/predefined_command/add_example.rb +33 -0
- data/lib/devkitkat/service/predefined_command/add_git_ignore.rb +29 -0
- data/lib/devkitkat/service/predefined_command/add_script.rb +35 -0
- data/lib/devkitkat/service/predefined_command/add_shared_script.rb +21 -0
- data/lib/devkitkat/service/predefined_command/base.rb +17 -0
- data/lib/devkitkat/service/predefined_command/clean.rb +22 -0
- data/lib/devkitkat/service/predefined_command/clone.rb +25 -0
- data/lib/devkitkat/service/predefined_command/exec.rb +18 -0
- data/lib/devkitkat/service/predefined_command/poop.rb +17 -0
- data/lib/devkitkat/service/predefined_command/pull.rb +19 -0
- data/lib/devkitkat/service/predefined_command/reconfigure.rb +26 -0
- data/lib/devkitkat/service/predefined_command/show_variables.rb +17 -0
- data/lib/devkitkat/service.rb +13 -214
- data/lib/devkitkat/version.rb +1 -1
- data/lib/devkitkat.rb +12 -5
- metadata +41 -12
- data/docs/READ.md +0 -1
- data/docs/config/READ.md +0 -1
- data/docs/machine/READ.md +0 -1
- data/docs/service/READ.md +0 -1
- data/lib/devkitkat/executor/docker.rb +0 -154
- data/lib/devkitkat/executor/local.rb +0 -25
- data/lib/devkitkat/executor.rb +0 -62
- data/lib/devkitkat/main.rb +0 -50
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 19d4a68e881590b167d09fb7564e53f0e6b337386ad4de76043d4ed5c1d8d3ab
         | 
| 4 | 
            +
              data.tar.gz: 5d1150ee9dcdd3820b60d8f460da8d69ed9eef314f13626da409d8481e78d7e3
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: eee0fd0f5ab8ebea39250f607ec29871f2f860305d601a1c161caf87c5b97066a6f26cecc019bd88797e9a6210b7a678b1eac793422d308b40fdfba2ce5a669b
         | 
| 7 | 
            +
              data.tar.gz: 5c133cd5b4d58a45711ee7192b39980a0519e5d786377674d2399ff0f43b57f8dc4cb72044ba2c0b3bfb535d6e38b47f72ca4e19158a3c04845e885aa4918eac
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,36 +1,37 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                devkitkat (0.1. | 
| 4 | 
            +
                devkitkat (0.1.22)
         | 
| 5 5 | 
             
                  activesupport (~> 6.0.0)
         | 
| 6 6 | 
             
                  colorize (~> 0.8.1)
         | 
| 7 7 | 
             
                  docker-api (~> 1.34.2)
         | 
| 8 8 | 
             
                  parallel (~> 1.17.0)
         | 
| 9 9 | 
             
                  pry (~> 0.12.2)
         | 
| 10 10 | 
             
                  pry-nav
         | 
| 11 | 
            +
                  require_all (~> 3.0.0)
         | 
| 11 12 | 
             
                  ruby-progressbar (~> 1.10.1)
         | 
| 12 13 |  | 
| 13 14 | 
             
            GEM
         | 
| 14 15 | 
             
              remote: https://rubygems.org/
         | 
| 15 16 | 
             
              specs:
         | 
| 16 | 
            -
                activesupport (6.0. | 
| 17 | 
            +
                activesupport (6.0.2.2)
         | 
| 17 18 | 
             
                  concurrent-ruby (~> 1.0, >= 1.0.2)
         | 
| 18 19 | 
             
                  i18n (>= 0.7, < 2)
         | 
| 19 20 | 
             
                  minitest (~> 5.1)
         | 
| 20 21 | 
             
                  tzinfo (~> 1.1)
         | 
| 21 | 
            -
                  zeitwerk (~> 2. | 
| 22 | 
            +
                  zeitwerk (~> 2.2)
         | 
| 22 23 | 
             
                coderay (1.1.2)
         | 
| 23 24 | 
             
                colorize (0.8.1)
         | 
| 24 | 
            -
                concurrent-ruby (1.1. | 
| 25 | 
            +
                concurrent-ruby (1.1.6)
         | 
| 25 26 | 
             
                diff-lcs (1.3)
         | 
| 26 27 | 
             
                docker-api (1.34.2)
         | 
| 27 28 | 
             
                  excon (>= 0.47.0)
         | 
| 28 29 | 
             
                  multi_json
         | 
| 29 | 
            -
                excon (0. | 
| 30 | 
            -
                i18n (1. | 
| 30 | 
            +
                excon (0.73.0)
         | 
| 31 | 
            +
                i18n (1.8.2)
         | 
| 31 32 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 32 33 | 
             
                method_source (0.9.2)
         | 
| 33 | 
            -
                minitest (5. | 
| 34 | 
            +
                minitest (5.14.0)
         | 
| 34 35 | 
             
                multi_json (1.14.1)
         | 
| 35 36 | 
             
                parallel (1.17.0)
         | 
| 36 37 | 
             
                pry (0.12.2)
         | 
| @@ -38,7 +39,8 @@ GEM | |
| 38 39 | 
             
                  method_source (~> 0.9.0)
         | 
| 39 40 | 
             
                pry-nav (0.3.0)
         | 
| 40 41 | 
             
                  pry (>= 0.9.10, < 0.13.0)
         | 
| 41 | 
            -
                rake ( | 
| 42 | 
            +
                rake (12.3.3)
         | 
| 43 | 
            +
                require_all (3.0.0)
         | 
| 42 44 | 
             
                rspec (3.8.0)
         | 
| 43 45 | 
             
                  rspec-core (~> 3.8.0)
         | 
| 44 46 | 
             
                  rspec-expectations (~> 3.8.0)
         | 
| @@ -56,9 +58,9 @@ GEM | |
| 56 58 | 
             
                  rspec (>= 3.0)
         | 
| 57 59 | 
             
                ruby-progressbar (1.10.1)
         | 
| 58 60 | 
             
                thread_safe (0.3.6)
         | 
| 59 | 
            -
                tzinfo (1.2. | 
| 61 | 
            +
                tzinfo (1.2.7)
         | 
| 60 62 | 
             
                  thread_safe (~> 0.1)
         | 
| 61 | 
            -
                zeitwerk (2. | 
| 63 | 
            +
                zeitwerk (2.3.0)
         | 
| 62 64 |  | 
| 63 65 | 
             
            PLATFORMS
         | 
| 64 66 | 
             
              ruby
         | 
| @@ -66,7 +68,7 @@ PLATFORMS | |
| 66 68 | 
             
            DEPENDENCIES
         | 
| 67 69 | 
             
              bundler (~> 1.17)
         | 
| 68 70 | 
             
              devkitkat!
         | 
| 69 | 
            -
              rake (~>  | 
| 71 | 
            +
              rake (~> 12.3.3)
         | 
| 70 72 | 
             
              rspec (~> 3.0)
         | 
| 71 73 | 
             
              rspec-temp_dir (~> 1.1.0)
         | 
| 72 74 |  | 
    
        data/README.md
    CHANGED
    
    | @@ -264,11 +264,11 @@ To install this gem onto your local machine, run `bundle exec rake install`. To | |
| 264 264 |  | 
| 265 265 | 
             
            **Execute only fast tests**
         | 
| 266 266 |  | 
| 267 | 
            -
            `bundle exec rspec  | 
| 267 | 
            +
            `bundle exec rspec -t ~slow`
         | 
| 268 268 |  | 
| 269 269 | 
             
            **Execute only slow tests**
         | 
| 270 270 |  | 
| 271 | 
            -
            `bundle exec rspec  | 
| 271 | 
            +
            `bundle exec rspec -t slow`
         | 
| 272 272 |  | 
| 273 273 | 
             
            ## Contributing
         | 
| 274 274 |  | 
    
        data/bin/devkitkat
    CHANGED
    
    
    
        data/devkitkat.gemspec
    CHANGED
    
    | @@ -24,7 +24,7 @@ Gem::Specification.new do |spec| | |
| 24 24 | 
             
              spec.require_paths = ["lib"]
         | 
| 25 25 |  | 
| 26 26 | 
             
              spec.add_development_dependency "bundler", "~> 1.17"
         | 
| 27 | 
            -
              spec.add_development_dependency "rake", "~>  | 
| 27 | 
            +
              spec.add_development_dependency "rake", "~> 12.3.3"
         | 
| 28 28 | 
             
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 29 29 | 
             
              spec.add_development_dependency "rspec-temp_dir", "~> 1.1.0"
         | 
| 30 30 | 
             
              spec.add_runtime_dependency "pry", "~> 0.12.2"
         | 
| @@ -34,4 +34,5 @@ Gem::Specification.new do |spec| | |
| 34 34 | 
             
              spec.add_runtime_dependency "ruby-progressbar", "~> 1.10.1"
         | 
| 35 35 | 
             
              spec.add_runtime_dependency "colorize", "~> 0.8.1"
         | 
| 36 36 | 
             
              spec.add_runtime_dependency "docker-api", "~> 1.34.2"
         | 
| 37 | 
            +
              spec.add_runtime_dependency "require_all", "~> 3.0.0"
         | 
| 37 38 | 
             
            end
         | 
    
        data/lib/devkitkat/command.rb
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'optparse'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Devkitkat
         | 
| 2 4 | 
             
              class Command
         | 
| 3 5 | 
             
                attr_reader :options, :script, :target, :args
         | 
| @@ -28,18 +30,14 @@ module Devkitkat | |
| 28 30 | 
             
                  options[:quiet]
         | 
| 29 31 | 
             
                end
         | 
| 30 32 |  | 
| 31 | 
            -
                def tmp_dir
         | 
| 32 | 
            -
                  File.join(kit_root, '.devkitkat')
         | 
| 33 | 
            -
                end
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def create_tmp_dir
         | 
| 36 | 
            -
                  FileUtils.mkdir_p(tmp_dir)
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 33 | 
             
                def kit_root
         | 
| 40 34 | 
             
                  options[:root_path] || Dir.pwd
         | 
| 41 35 | 
             
                end
         | 
| 42 36 |  | 
| 37 | 
            +
                def name
         | 
| 38 | 
            +
                  script.tr('-', '_')
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 43 41 | 
             
                private
         | 
| 44 42 |  | 
| 45 43 | 
             
                def option_parser
         | 
    
        data/lib/devkitkat/config.rb
    CHANGED
    
    | @@ -1,9 +1,10 @@ | |
| 1 | 
            +
            require 'yaml'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Devkitkat
         | 
| 2 4 | 
             
              class Config
         | 
| 3 5 | 
             
                DEVKITKAT_FILE_NAME = '.devkitkat.yml'
         | 
| 4 6 | 
             
                HIDDEN_SERVICES = %w[system]
         | 
| 5 7 | 
             
                DEFAULT_APPLICATION_NAME = 'devkitkat'
         | 
| 6 | 
            -
                DEFAULT_IMAGE = 'registry.gitlab.com/dosuken123/thin-gdk/thin-gdk-monolith:master'
         | 
| 7 8 |  | 
| 8 9 | 
             
                attr_reader :devkitkat_yml, :kit_root
         | 
| 9 10 |  | 
| @@ -18,34 +19,46 @@ module Devkitkat | |
| 18 19 |  | 
| 19 20 | 
             
                def resolve!(target, exclude: nil)
         | 
| 20 21 | 
             
                  services = if target.nil? || target == 'system'
         | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 22 | 
            +
                              %w[system]
         | 
| 23 | 
            +
                            elsif target == 'all'
         | 
| 24 | 
            +
                              all_services
         | 
| 25 | 
            +
                            elsif group = find_group(target)
         | 
| 26 | 
            +
                              services_for_group(group)
         | 
| 27 | 
            +
                            elsif services = find_comma_separated_services(target)
         | 
| 27 28 | 
             
                              services
         | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 29 | 
            +
                            elsif service = find_service(target)
         | 
| 30 | 
            +
                              [service]
         | 
| 31 | 
            +
                            else
         | 
| 32 | 
            +
                              raise_error(target)
         | 
| 33 | 
            +
                            end
         | 
| 33 34 |  | 
| 34 35 | 
             
                  services = services - exclude if exclude
         | 
| 35 36 |  | 
| 36 37 | 
             
                  services
         | 
| 37 38 | 
             
                end
         | 
| 38 39 |  | 
| 39 | 
            -
                def  | 
| 40 | 
            -
                   | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
                   | 
| 40 | 
            +
                def machine_driver
         | 
| 41 | 
            +
                  devkitkat_yml.dig('machine', 'driver') || 'none'
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def machine_location
         | 
| 45 | 
            +
                  devkitkat_yml.dig('machine', 'location') || 'local'
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def machine_image
         | 
| 49 | 
            +
                  devkitkat_yml.dig('machine', 'image')
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                def machine_extra_hosts
         | 
| 53 | 
            +
                  devkitkat_yml.dig('machine', 'extra_hosts')
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                def machine_network_mode
         | 
| 57 | 
            +
                  devkitkat_yml.dig('machine', 'network_mode')
         | 
| 45 58 | 
             
                end
         | 
| 46 59 |  | 
| 47 | 
            -
                def  | 
| 48 | 
            -
                  devkitkat_yml. | 
| 60 | 
            +
                def extra_write_accesses
         | 
| 61 | 
            +
                  devkitkat_yml.dig('machine', 'extra_write_accesses')
         | 
| 49 62 | 
             
                end
         | 
| 50 63 |  | 
| 51 64 | 
             
                def application
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            require 'parallel'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Devkitkat
         | 
| 4 | 
            +
              class Processor
         | 
| 5 | 
            +
                attr_reader :services, :config, :command
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(services, command, config)
         | 
| 8 | 
            +
                  @services = services
         | 
| 9 | 
            +
                  @command = command
         | 
| 10 | 
            +
                  @config = config
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def execute
         | 
| 14 | 
            +
                  results = []
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  print_log_paths
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  if services.count == 1
         | 
| 19 | 
            +
                    # If the target is only one, it could be console access (TTY)
         | 
| 20 | 
            +
                    # so we can't run in parallel.
         | 
| 21 | 
            +
                    results << services.first.execute
         | 
| 22 | 
            +
                  else
         | 
| 23 | 
            +
                    results = Parallel.map(services, progress: 'Executing', in_processes: 8) do |service|
         | 
| 24 | 
            +
                      service.execute.tap do |success|
         | 
| 25 | 
            +
                        raise Parallel::Kill unless success
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  results&.all? { |result| result == true } || terminate_process_group!
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                private
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def terminate_process_group!
         | 
| 36 | 
            +
                  pgid = Process.getpgid(Process.pid)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  Process.kill('TERM', -pgid)
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def print_log_paths
         | 
| 42 | 
            +
                  return if command.interactive? || command.quiet?
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  log_paths = services.map(&:log_path)
         | 
| 45 | 
            +
                  puts %Q{See the log at \n#{log_paths.join("\n")}}
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            require 'active_support/core_ext/module/delegation'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Devkitkat
         | 
| 4 | 
            +
              class Service
         | 
| 5 | 
            +
                module Concerns
         | 
| 6 | 
            +
                  module ServiceInitializer
         | 
| 7 | 
            +
                    attr_reader :service
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    delegate :config, :command, to: :service
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def initialize(service)
         | 
| 12 | 
            +
                      @service = service
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module Devkitkat
         | 
| 2 | 
            +
              class Service
         | 
| 3 | 
            +
                class Driver
         | 
| 4 | 
            +
                  class Base
         | 
| 5 | 
            +
                    include Concerns::ServiceInitializer
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    PreparationError = Class.new(StandardError)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def prepare
         | 
| 10 | 
            +
                      raise NotImplementedError
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def cleanup
         | 
| 14 | 
            +
                      raise NotImplementedError
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    def execute(script_file)
         | 
| 18 | 
            +
                      raise NotImplementedError
         | 
| 19 | 
            +
                    end
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -0,0 +1,163 @@ | |
| 1 | 
            +
            module Devkitkat
         | 
| 2 | 
            +
              class Service
         | 
| 3 | 
            +
                class Driver
         | 
| 4 | 
            +
                  class Docker < Base
         | 
| 5 | 
            +
                    class Container
         | 
| 6 | 
            +
                      include Concerns::ServiceInitializer
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                      ROOT_IN_CONTAINER = '/devkitkat'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                      attr_reader :container
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      def start
         | 
| 13 | 
            +
                        if @container = find
         | 
| 14 | 
            +
                          container.start
         | 
| 15 | 
            +
                        else
         | 
| 16 | 
            +
                          @container = create
         | 
| 17 | 
            +
                          container.start
         | 
| 18 | 
            +
                          create_host_user
         | 
| 19 | 
            +
                        end
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      def stop
         | 
| 23 | 
            +
                        raise 'Container has not started yet' unless container
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                        container.stop
         | 
| 26 | 
            +
                      end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                      def exec(cmds, params = {})
         | 
| 29 | 
            +
                        params.merge!(user: user_name)
         | 
| 30 | 
            +
                        safe_exec(cmds, params)
         | 
| 31 | 
            +
                      end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                      def exec_as_host(cmds, params = {})
         | 
| 34 | 
            +
                        safe_exec(cmds, params)
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                      private
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                      def safe_exec(cmds, params)
         | 
| 40 | 
            +
                        params.merge!(wait: 604800) # Default timeout is 1 minute, so setting 1 week instead
         | 
| 41 | 
            +
                        stdout_messages, stderr_messages, exit_code =
         | 
| 42 | 
            +
                          container.exec(cmds, params)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                        if exit_code != 0 || command.debug?
         | 
| 45 | 
            +
                          puts "#{self.class.name} - #{__callee__}: stdout_messages: #{stdout_messages} stderr_messages: #{stderr_messages} exit_code: #{exit_code}"
         | 
| 46 | 
            +
                        end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                        exit_code == 0 ? true : false
         | 
| 49 | 
            +
                      rescue ::Docker::Error::ConflictError => e
         | 
| 50 | 
            +
                        puts "#{self.class.name} - #{__callee__}: #{e.message}"
         | 
| 51 | 
            +
                        false
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                      def image
         | 
| 55 | 
            +
                        config.machine_image
         | 
| 56 | 
            +
                      end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                      def name
         | 
| 59 | 
            +
                        @name ||=
         | 
| 60 | 
            +
                          "#{config.application}-#{service.name}-#{Digest::SHA1.hexdigest(command.kit_root)[8..12]}"
         | 
| 61 | 
            +
                      end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                      def find
         | 
| 64 | 
            +
                        ::Docker::Container.get(name)
         | 
| 65 | 
            +
                      rescue ::Docker::Error::NotFoundError
         | 
| 66 | 
            +
                        nil
         | 
| 67 | 
            +
                      end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                      def create
         | 
| 70 | 
            +
                        ::Docker::Container.create(create_parameter)
         | 
| 71 | 
            +
                      end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                      def create_parameter
         | 
| 74 | 
            +
                        params = {
         | 
| 75 | 
            +
                          'Cmd' => %w[tail -f],
         | 
| 76 | 
            +
                          'Image' => image,
         | 
| 77 | 
            +
                          'name' => name,
         | 
| 78 | 
            +
                          'HostConfig' => {
         | 
| 79 | 
            +
                            'Binds' => all_mounts
         | 
| 80 | 
            +
                          }
         | 
| 81 | 
            +
                        }
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                        if service.port
         | 
| 84 | 
            +
                          params.deep_merge!(
         | 
| 85 | 
            +
                            'ExposedPorts' => { "#{service.port}/tcp" => {} },
         | 
| 86 | 
            +
                            'HostConfig' => {
         | 
| 87 | 
            +
                              'PortBindings' => {
         | 
| 88 | 
            +
                                "#{service.port}/tcp" => [{ 'HostPort' => service.port.to_s }]
         | 
| 89 | 
            +
                              }
         | 
| 90 | 
            +
                            }
         | 
| 91 | 
            +
                          )
         | 
| 92 | 
            +
                        end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                        if config.machine_extra_hosts
         | 
| 95 | 
            +
                          params.deep_merge!('HostConfig' => { 'ExtraHosts' => config.machine_extra_hosts })
         | 
| 96 | 
            +
                        end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                        if config.machine_network_mode
         | 
| 99 | 
            +
                          params.deep_merge!('HostConfig' => { 'NetworkMode' => config.machine_network_mode })
         | 
| 100 | 
            +
                        end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                        params
         | 
| 103 | 
            +
                      end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                      def all_mounts
         | 
| 106 | 
            +
                        config.all_services.map do |service_name|
         | 
| 107 | 
            +
                          service = Service.new(service_name, config, command)
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                          FileUtils.mkdir_p(service.dir)
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                          if self.service.name == service_name || service.system? || allowed_by_extra_write_accesses?(service)
         | 
| 112 | 
            +
                            "#{service.dir}:#{ROOT_IN_CONTAINER}/services/#{service.name}"
         | 
| 113 | 
            +
                          else
         | 
| 114 | 
            +
                            "#{service.dir}:#{ROOT_IN_CONTAINER}/services/#{service.name}:ro"
         | 
| 115 | 
            +
                          end
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
                      end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                      def allowed_by_extra_write_accesses?(service)
         | 
| 120 | 
            +
                        config.extra_write_accesses&.any? do |access|
         | 
| 121 | 
            +
                          from, _, to = access.split(':')
         | 
| 122 | 
            +
                          self.service.name == from && service.name == to
         | 
| 123 | 
            +
                        end
         | 
| 124 | 
            +
                      end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                      def user_name
         | 
| 127 | 
            +
                        'devkitkat'
         | 
| 128 | 
            +
                      end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                      def group_id
         | 
| 131 | 
            +
                        @group_id ||= `id -u`.delete("\n")
         | 
| 132 | 
            +
                      end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                      def user_id
         | 
| 135 | 
            +
                        @user_id ||= `id -g`
         | 
| 136 | 
            +
                      end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                      def create_host_user
         | 
| 139 | 
            +
                        prepare!(['addgroup', '--gid', group_id, user_name])
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                        prepare!(['adduser',
         | 
| 142 | 
            +
                          '--uid', user_id,
         | 
| 143 | 
            +
                          '--gid', group_id,
         | 
| 144 | 
            +
                          '--shell', '/bin/bash',
         | 
| 145 | 
            +
                          '--home', ROOT_IN_CONTAINER,
         | 
| 146 | 
            +
                          '--gecos', '',
         | 
| 147 | 
            +
                          '--disabled-password',
         | 
| 148 | 
            +
                          user_name])
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                        prepare!(['chown', "#{user_name}:#{user_name}", ROOT_IN_CONTAINER])
         | 
| 151 | 
            +
                        prepare!(['chown', '-R', "#{user_name}:#{user_name}", "#{ROOT_IN_CONTAINER}/services/#{service.name}"])
         | 
| 152 | 
            +
                      end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                      def prepare!(cmds, params = {})
         | 
| 155 | 
            +
                        unless exec_as_host(cmds, params)
         | 
| 156 | 
            +
                          raise Driver::Base::PreparationError, "Failed to execute command in container. cmds: #{cmds}"
         | 
| 157 | 
            +
                        end
         | 
| 158 | 
            +
                      end
         | 
| 159 | 
            +
                    end
         | 
| 160 | 
            +
                  end
         | 
| 161 | 
            +
                end
         | 
| 162 | 
            +
              end
         | 
| 163 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            module Devkitkat
         | 
| 2 | 
            +
              class Service
         | 
| 3 | 
            +
                class Driver
         | 
| 4 | 
            +
                  class Docker < Base
         | 
| 5 | 
            +
                    class Image
         | 
| 6 | 
            +
                      include Concerns::ServiceInitializer
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                      def pull
         | 
| 9 | 
            +
                        image_exist? || pull_image
         | 
| 10 | 
            +
                      end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      private
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                      def pull_image
         | 
| 15 | 
            +
                        puts "Pulling image #{image}..."
         | 
| 16 | 
            +
                        ::Docker::Image.create('fromImage' => image)
         | 
| 17 | 
            +
                        puts "Pulled image #{image}..."
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                      def image_exist?
         | 
| 21 | 
            +
                        ::Docker::Image.get(image)
         | 
| 22 | 
            +
                      rescue
         | 
| 23 | 
            +
                        false
         | 
| 24 | 
            +
                      end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      def image
         | 
| 27 | 
            +
                        config.machine_image
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require 'docker'
         | 
| 2 | 
            +
            require_relative 'docker/container'
         | 
| 3 | 
            +
            require_relative 'docker/image'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Devkitkat
         | 
| 6 | 
            +
              class Service
         | 
| 7 | 
            +
                class Driver
         | 
| 8 | 
            +
                  class Docker < Base
         | 
| 9 | 
            +
                    def prepare
         | 
| 10 | 
            +
                      image.pull
         | 
| 11 | 
            +
                      container.start
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    def execute(script_file)
         | 
| 15 | 
            +
                      new_path = rewrite_root_path!(script_file)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                      container.exec([new_path])
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    def cleanup
         | 
| 21 | 
            +
                      container.stop
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    private
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def rewrite_root_path!(script_file)
         | 
| 27 | 
            +
                      content = File.read(script_file)
         | 
| 28 | 
            +
                      new_content = content.gsub(command.kit_root, Container::ROOT_IN_CONTAINER)
         | 
| 29 | 
            +
                      File.write(script_file, new_content)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                      relative_path = script_file.delete_prefix(command.kit_root)
         | 
| 32 | 
            +
                      File.join(Container::ROOT_IN_CONTAINER, relative_path)
         | 
| 33 | 
            +
                    end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    def container
         | 
| 36 | 
            +
                      @container ||= Container.new(service)
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    def image
         | 
| 40 | 
            +
                      @image ||= Image.new(service)
         | 
| 41 | 
            +
                    end
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
            end
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            module Devkitkat
         | 
| 2 | 
            +
              class Service
         | 
| 3 | 
            +
                class Executor
         | 
| 4 | 
            +
                  class Logger
         | 
| 5 | 
            +
                    include Concerns::ServiceInitializer
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    def to_script
         | 
| 8 | 
            +
                      "exec > #{service.log_path} 2>&1"
         | 
| 9 | 
            +
                    end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def available?
         | 
| 12 | 
            +
                      !command.interactive?
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def new_file
         | 
| 16 | 
            +
                      FileUtils.rm_f(service.log_path)
         | 
| 17 | 
            +
                      FileUtils.mkdir_p(service.log_dir)
         | 
| 18 | 
            +
                    end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -0,0 +1,48 @@ | |
| 1 | 
            +
            module Devkitkat
         | 
| 2 | 
            +
              class Service
         | 
| 3 | 
            +
                class Executor
         | 
| 4 | 
            +
                  class Scripter
         | 
| 5 | 
            +
                    include Concerns::ServiceInitializer
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                    SCRIPT_HEADER = <<~EOS
         | 
| 8 | 
            +
                      #!/bin/bash
         | 
| 9 | 
            +
                    EOS
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    def file_path
         | 
| 12 | 
            +
                      File.join(service.dir, "script-#{service.name}-#{command.script}")
         | 
| 13 | 
            +
                    end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                    def new_file
         | 
| 16 | 
            +
                      delete_file
         | 
| 17 | 
            +
                      create_file
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      yield
         | 
| 20 | 
            +
                    ensure
         | 
| 21 | 
            +
                      delete_file
         | 
| 22 | 
            +
                    end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    def write(cmd)  
         | 
| 25 | 
            +
                      File.open(file_path, 'a') do |stream|
         | 
| 26 | 
            +
                        stream.write(cmd + "\n")
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    private
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    def create_file
         | 
| 33 | 
            +
                      ensure_service_root_dir
         | 
| 34 | 
            +
                      File.write(file_path, SCRIPT_HEADER)
         | 
| 35 | 
            +
                      File.chmod(0777, file_path)
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    def delete_file
         | 
| 39 | 
            +
                      FileUtils.rm_f(file_path)
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    def ensure_service_root_dir
         | 
| 43 | 
            +
                      FileUtils.mkdir_p(service.root_dir)
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
            end
         |