contur 0.0.3
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 +7 -0
- data/.editorconfig +15 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.rubocop.yml +19 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +17 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +166 -0
- data/Rakefile +9 -0
- data/bin/console +8 -0
- data/bin/contur +172 -0
- data/bin/setup +8 -0
- data/contur-logo.png +0 -0
- data/contur.gemspec +40 -0
- data/lib/contur/bindable_hash.rb +16 -0
- data/lib/contur/config/before.rb +30 -0
- data/lib/contur/config/env.rb +29 -0
- data/lib/contur/config/errors.rb +7 -0
- data/lib/contur/config/use.rb +41 -0
- data/lib/contur/config/version.rb +34 -0
- data/lib/contur/config.rb +74 -0
- data/lib/contur/constants.rb +25 -0
- data/lib/contur/controller.rb +227 -0
- data/lib/contur/utils.rb +42 -0
- data/lib/contur/version.rb +4 -0
- data/lib/contur.rb +8 -0
- data/templates/base-docker-container.erb +104 -0
- data/templates/init.sh.erb +19 -0
- metadata +216 -0
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'contur/constants'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Contur
         | 
| 6 | 
            +
              class Config
         | 
| 7 | 
            +
                # Use section
         | 
| 8 | 
            +
                class Use < Hash
         | 
| 9 | 
            +
                  DEFAULTS ||= {
         | 
| 10 | 
            +
                    'php' => Contur::DEFAULT_PHP_VERSION,
         | 
| 11 | 
            +
                    'mysql' => Contur::DEFAULT_MYSQL_VERSION
         | 
| 12 | 
            +
                  }.freeze
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  ALLOWED_VALUES ||= DEFAULTS.keys
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  def initialize(using = {})
         | 
| 17 | 
            +
                    super
         | 
| 18 | 
            +
                    replace(DEFAULTS)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    validate!(using)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    merge!(using) unless using.nil?
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def validate!(using)
         | 
| 26 | 
            +
                    @errors = []
         | 
| 27 | 
            +
                    return unless using.respond_to? :keys
         | 
| 28 | 
            +
                    extra_keys = using.keys - ALLOWED_VALUES
         | 
| 29 | 
            +
                    extra_keys.each do |key|
         | 
| 30 | 
            +
                      @errors << "Unknown key: #{key}"
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  attr_reader :errors
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                  def name
         | 
| 37 | 
            +
                    "Section 'use'"
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Contur
         | 
| 3 | 
            +
              class Config
         | 
| 4 | 
            +
                # Version section
         | 
| 5 | 
            +
                class Version
         | 
| 6 | 
            +
                  ALLOWED_VALUES ||= [1.0].freeze
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  # version is required so no default value
         | 
| 9 | 
            +
                  def initialize(version)
         | 
| 10 | 
            +
                    validate!(version)
         | 
| 11 | 
            +
                    @yaml_version = version
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def inspect
         | 
| 15 | 
            +
                    @yaml_version.to_s
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def validate!(version)
         | 
| 19 | 
            +
                    @errors = []
         | 
| 20 | 
            +
                    if version.nil?
         | 
| 21 | 
            +
                      @errors << 'Required'
         | 
| 22 | 
            +
                      return
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                    @errors << "Unknown value: '#{version}'" unless ALLOWED_VALUES.include? version
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  attr_reader :errors
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def name
         | 
| 30 | 
            +
                    "Section 'version'"
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,74 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'contur/config/before'
         | 
| 3 | 
            +
            require 'contur/config/env'
         | 
| 4 | 
            +
            require 'contur/config/errors'
         | 
| 5 | 
            +
            require 'contur/config/use'
         | 
| 6 | 
            +
            require 'contur/config/version'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            require 'yaml'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            module Contur
         | 
| 11 | 
            +
              # Build configuration object
         | 
| 12 | 
            +
              class Config
         | 
| 13 | 
            +
                attr_reader :path, :raw, :version, :use, :env, :before
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize(path_to_config)
         | 
| 16 | 
            +
                  begin
         | 
| 17 | 
            +
                    @path = path_to_config
         | 
| 18 | 
            +
                    build_config = YAML.load_file(path_to_config)
         | 
| 19 | 
            +
                  rescue Errno::ENOENT
         | 
| 20 | 
            +
                    raise Contur::Config::NotFoundError, "'#{path_to_config}': file not found"
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  @errors = []
         | 
| 24 | 
            +
                  unless build_config
         | 
| 25 | 
            +
                    @errors << 'Build file is empty'
         | 
| 26 | 
            +
                    return
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  @raw = build_config
         | 
| 30 | 
            +
                  @version = Version.new(build_config['version'])
         | 
| 31 | 
            +
                  @use = Use.new(build_config['use'])
         | 
| 32 | 
            +
                  @env = Env.new(build_config['env'])
         | 
| 33 | 
            +
                  @before = Before.new(build_config['before'])
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def init_script
         | 
| 37 | 
            +
                  unless @init_script
         | 
| 38 | 
            +
                    generation_time = "echo \"Generated at: [#{Time.now}]\"\n\n"
         | 
| 39 | 
            +
                    env_script = @env.to_bash_script
         | 
| 40 | 
            +
                    before_script = @before.to_bash_script
         | 
| 41 | 
            +
                    @init_script = generation_time + env_script + before_script
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                  @init_script
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def errors
         | 
| 47 | 
            +
                  all_errors = Array.new(@errors)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  instance_variables.each do |var|
         | 
| 50 | 
            +
                    section = instance_variable_get(var)
         | 
| 51 | 
            +
                    next unless section.respond_to?(:name) && section.respond_to?(:errors)
         | 
| 52 | 
            +
                    section_name = section.send(:name)
         | 
| 53 | 
            +
                    section_errors = section.send(:errors)
         | 
| 54 | 
            +
                    section_errors.each do |err|
         | 
| 55 | 
            +
                      all_errors << "#{section_name}: #{err}"
         | 
| 56 | 
            +
                    end
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  all_errors
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                def inspect
         | 
| 63 | 
            +
                  data = []
         | 
| 64 | 
            +
                  instance_variables.each do |var|
         | 
| 65 | 
            +
                    section = instance_variable_get(var)
         | 
| 66 | 
            +
                    if section.respond_to?(:name)
         | 
| 67 | 
            +
                      section_name = section.send(:name)
         | 
| 68 | 
            +
                      data << "#{section_name}: #{section.inspect}"
         | 
| 69 | 
            +
                    end
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                  data.join("\n")
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'date'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            # Contur main module
         | 
| 6 | 
            +
            module Contur
         | 
| 7 | 
            +
              GEM_ROOT       = File.expand_path(File.join(File.dirname(__FILE__), '../../'))
         | 
| 8 | 
            +
              TEMPLATE_DIR   = "#{Contur::GEM_ROOT}/templates"
         | 
| 9 | 
            +
              DEFAULT_DOMAIN = 'cheppers.com'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              IMAGE_NAME ||= 'contur'
         | 
| 12 | 
            +
              DOCKER_DIR ||= 'docker'
         | 
| 13 | 
            +
              DEFAULT_PHP_VERSION = '5.6'
         | 
| 14 | 
            +
              DEFAULT_MYSQL_VERSION = 'latest'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              DEFAULT_OPTS ||= {
         | 
| 17 | 
            +
                refreshed_at_date: ::Date.today.strftime('%Y-%m-%d'),
         | 
| 18 | 
            +
                php_timezone: 'Europe/Budapest',
         | 
| 19 | 
            +
                php_memory_limit: '256M',
         | 
| 20 | 
            +
                max_upload: '50M',
         | 
| 21 | 
            +
                php_max_file_upload: 200,
         | 
| 22 | 
            +
                php_max_post: '100M',
         | 
| 23 | 
            +
                extra_files: Contur::TEMPLATE_DIR
         | 
| 24 | 
            +
              }.freeze
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,227 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            require 'docker-api'
         | 
| 3 | 
            +
            require 'erb'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'contur/bindable_hash'
         | 
| 6 | 
            +
            require 'contur/config'
         | 
| 7 | 
            +
            require 'contur/utils'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # rubocop:disable Metrics/ClassLength, Lint/AssignmentInCondition
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            # Contur main module
         | 
| 12 | 
            +
            module Contur
         | 
| 13 | 
            +
              # Contur::Controller
         | 
| 14 | 
            +
              class Controller
         | 
| 15 | 
            +
                # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
         | 
| 16 | 
            +
                def self.config(path_to_config = nil)
         | 
| 17 | 
            +
                  # rubocop:disable Style/ClassVars
         | 
| 18 | 
            +
                  @@config ||= nil
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  unless @@config
         | 
| 21 | 
            +
                    @@config = if path_to_config.nil?
         | 
| 22 | 
            +
                                 config_file_name = Dir['.contur.y*ml'].first
         | 
| 23 | 
            +
                                 Contur::Config.new(File.join(Dir.pwd, config_file_name))
         | 
| 24 | 
            +
                               else
         | 
| 25 | 
            +
                                 Contur::Config.new(path_to_config)
         | 
| 26 | 
            +
                               end
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                  @@config
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                def self.image_exist?
         | 
| 32 | 
            +
                  Docker::Image.exist? Contur::IMAGE_NAME
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def self.container?
         | 
| 36 | 
            +
                  Docker::Container.all(
         | 
| 37 | 
            +
                    'filters' => { 'ancestor' => [Contur::IMAGE_NAME] }.to_json, 'all' => true
         | 
| 38 | 
            +
                  ).first
         | 
| 39 | 
            +
                rescue
         | 
| 40 | 
            +
                  nil
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def self.promote
         | 
| 44 | 
            +
                  puts '!!! WIP !!!'
         | 
| 45 | 
            +
                  puts "FQDN: #{Contur::Utils.fqdn}"
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def self.build
         | 
| 49 | 
            +
                  template = load_docker_template(
         | 
| 50 | 
            +
                    'base-docker-container',
         | 
| 51 | 
            +
                    php_memory_limit: '128M'
         | 
| 52 | 
            +
                  )
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  docker_context = generate_docker_archive(template)
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  Docker::Image.build_from_tar(docker_context, t: Contur::IMAGE_NAME) do |r|
         | 
| 57 | 
            +
                    r.each_line do |log|
         | 
| 58 | 
            +
                      if (message = JSON.parse(log)) && message.key?('stream')
         | 
| 59 | 
            +
                        yield message['stream'] if block_given?
         | 
| 60 | 
            +
                      end
         | 
| 61 | 
            +
                    end
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                # rubocop:disable Metrics/PerceivedComplexity, Lint/UnusedMethodArgument, Metrics/MethodLength
         | 
| 66 | 
            +
                def self.run(config_path: nil, webroot: nil, initscripts: nil)
         | 
| 67 | 
            +
                  unless image_exist?
         | 
| 68 | 
            +
                    yield "Image doesn't exist" if block_given?
         | 
| 69 | 
            +
                    return false
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  bind_volumes = []
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  if !webroot.nil? && Dir.exist?(File.expand_path(webroot))
         | 
| 75 | 
            +
                    bind_volumes << "#{webroot}:/www"
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                  if !initscripts.nil? && Dir.exist?(File.expand_path(initscripts))
         | 
| 78 | 
            +
                    bind_volumes << "#{initscripts}:/initscripts"
         | 
| 79 | 
            +
                  end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  if c = container?
         | 
| 82 | 
            +
                    yield 'Removing existing contur container...' if block_given?
         | 
| 83 | 
            +
                    c.remove(force: true)
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                  mysql_container_version = "mysql:#{config.use['mysql']}"
         | 
| 87 | 
            +
                  unless Docker::Image.exist? mysql_container_version
         | 
| 88 | 
            +
                    yield "Downloading #{mysql_container_version}..." if block_given?
         | 
| 89 | 
            +
                    Docker::Image.create('fromImage' => mysql_container_version)
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  mysql_container_name = mysql_container_version.tr(':.', '_')
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                  stop_mysql_containers(except: mysql_container_version)
         | 
| 95 | 
            +
                  begin
         | 
| 96 | 
            +
                    mysql_container = Docker::Container.get(mysql_container_name)
         | 
| 97 | 
            +
                  rescue Docker::Error::NotFoundError
         | 
| 98 | 
            +
                    yield 'Creating MySQL container...' if block_given?
         | 
| 99 | 
            +
                    mysql_container = Docker::Container.create(
         | 
| 100 | 
            +
                      'name' => mysql_container_name,
         | 
| 101 | 
            +
                      'Image' => mysql_container_version,
         | 
| 102 | 
            +
                      'Env' => ['MYSQL_ROOT_PASSWORD=admin']
         | 
| 103 | 
            +
                    )
         | 
| 104 | 
            +
                  ensure
         | 
| 105 | 
            +
                    mysql_container_info = Docker::Container.get(mysql_container.id).info
         | 
| 106 | 
            +
                    unless mysql_container_info['State']['Running']
         | 
| 107 | 
            +
                      yield 'Starting MySQL container...' if block_given?
         | 
| 108 | 
            +
                      mysql_container.start!
         | 
| 109 | 
            +
                      sleep 10
         | 
| 110 | 
            +
                    end
         | 
| 111 | 
            +
                  end
         | 
| 112 | 
            +
                  mysql_container_info = Docker::Container.get(mysql_container.id).info
         | 
| 113 | 
            +
                  unless mysql_container_info['State']['Running']
         | 
| 114 | 
            +
                    yield "Couldn't start MySQL container" if block_given?
         | 
| 115 | 
            +
                    return false
         | 
| 116 | 
            +
                  end
         | 
| 117 | 
            +
                  yield "MySQL container: #{mysql_container.id[0, 10]}" if block_given?
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  yield 'Creating Contur container...' if block_given?
         | 
| 120 | 
            +
                  container = Docker::Container.create(
         | 
| 121 | 
            +
                    'name' => Contur::Utils.generate_conatiner_name,
         | 
| 122 | 
            +
                    'Image' => Contur::IMAGE_NAME,
         | 
| 123 | 
            +
                    'Cmd' => ['/init.sh'],
         | 
| 124 | 
            +
                    'Volumes' => {
         | 
| 125 | 
            +
                      "#{Dir.pwd}/webroot" => {},
         | 
| 126 | 
            +
                      "#{Dir.pwd}/initscripts" => {}
         | 
| 127 | 
            +
                    },
         | 
| 128 | 
            +
                    'ExposedPorts' => {
         | 
| 129 | 
            +
                      '80/tcp' => {}
         | 
| 130 | 
            +
                    },
         | 
| 131 | 
            +
                    'HostConfig' => {
         | 
| 132 | 
            +
                      'Links' => ["#{mysql_container_name}:mysql"],
         | 
| 133 | 
            +
                      'PortBindings' => {
         | 
| 134 | 
            +
                        '80/tcp' => [{ 'HostPort' => '8088' }]
         | 
| 135 | 
            +
                      },
         | 
| 136 | 
            +
                      'Binds' => bind_volumes
         | 
| 137 | 
            +
                    }
         | 
| 138 | 
            +
                  )
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  container.store_file('/init.sh', content: load_init_script, permissions: 0o777)
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                  container.start!
         | 
| 143 | 
            +
                end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                def self.delete_container
         | 
| 146 | 
            +
                  if c = container?
         | 
| 147 | 
            +
                    c.delete(force: true)
         | 
| 148 | 
            +
                    true
         | 
| 149 | 
            +
                  else
         | 
| 150 | 
            +
                    false
         | 
| 151 | 
            +
                  end
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def self.container_id
         | 
| 155 | 
            +
                  return nil unless c = container?
         | 
| 156 | 
            +
                  c.id[0, 10]
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                def self.container_logs
         | 
| 160 | 
            +
                  return nil unless c = container?
         | 
| 161 | 
            +
                  c.logs(stdout: true)
         | 
| 162 | 
            +
                end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                def self.delete_image
         | 
| 165 | 
            +
                  return nil unless image_exist?
         | 
| 166 | 
            +
                  image = Docker::Image.get Contur::IMAGE_NAME
         | 
| 167 | 
            +
                  image.remove(force: true)
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                def self.mysql_containers
         | 
| 171 | 
            +
                  Docker::Container.all.select { |c| c.info['Image'].start_with?('mysql') }
         | 
| 172 | 
            +
                end
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                def self.delete_mysql_containers
         | 
| 175 | 
            +
                  if mysql_containers.empty?
         | 
| 176 | 
            +
                    false
         | 
| 177 | 
            +
                  else
         | 
| 178 | 
            +
                    mysql_containers.each { |c| c.delete(force: true) }
         | 
| 179 | 
            +
                    true
         | 
| 180 | 
            +
                  end
         | 
| 181 | 
            +
                end
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                def self.stop_mysql_containers(except: "\n")
         | 
| 184 | 
            +
                  mysql_containers.select { |c| !c.info['Image'].end_with?(except) }.each(&:stop)
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                private_class_method
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                def self.load_docker_template(template_name, opts = {})
         | 
| 190 | 
            +
                  opts = Contur::DEFAULT_OPTS.merge(opts)
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                  context = BindableHash.new opts
         | 
| 193 | 
            +
                  ::ERB.new(
         | 
| 194 | 
            +
                    File.read("#{Contur::TEMPLATE_DIR}/#{template_name}.erb")
         | 
| 195 | 
            +
                  ).result(context.get_binding)
         | 
| 196 | 
            +
                end
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                def self.load_init_script
         | 
| 199 | 
            +
                  context = BindableHash.new(before_script: config.init_script)
         | 
| 200 | 
            +
                  ::ERB.new(
         | 
| 201 | 
            +
                    File.read("#{Contur::TEMPLATE_DIR}/init.sh.erb")
         | 
| 202 | 
            +
                  ).result(context.get_binding)
         | 
| 203 | 
            +
                end
         | 
| 204 | 
            +
             | 
| 205 | 
            +
                def self.generate_docker_archive(dockerfile_content)
         | 
| 206 | 
            +
                  tar = StringIO.new
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                  Gem::Package::TarWriter.new(tar) do |writer|
         | 
| 209 | 
            +
                    writer.add_file('Dockerfile', 0o644) { |f| f.write(dockerfile_content) }
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  compress_archive(tar)
         | 
| 213 | 
            +
                end
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                def self.compress_archive(tar)
         | 
| 216 | 
            +
                  tar.seek(0)
         | 
| 217 | 
            +
                  gz = StringIO.new(String.new, 'r+b').set_encoding(Encoding::BINARY)
         | 
| 218 | 
            +
                  gz_writer = Zlib::GzipWriter.new(gz)
         | 
| 219 | 
            +
                  gz_writer.write(tar.read)
         | 
| 220 | 
            +
                  tar.close
         | 
| 221 | 
            +
                  gz_writer.finish
         | 
| 222 | 
            +
                  gz.rewind
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                  gz
         | 
| 225 | 
            +
                end
         | 
| 226 | 
            +
              end
         | 
| 227 | 
            +
            end
         | 
    
        data/lib/contur/utils.rb
    ADDED
    
    | @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
            module Contur
         | 
| 3 | 
            +
              # Utils class
         | 
| 4 | 
            +
              class Utils
         | 
| 5 | 
            +
                def self.generate_conatiner_name(prefix: nil, job_name: nil, build_id: nil)
         | 
| 6 | 
            +
                  prefix ||= ENV['CONTAINER_PREFIX']
         | 
| 7 | 
            +
                  prefix = "#{prefix}-" unless prefix.nil? || prefix.empty?
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  job_name ||= ENV['JOB_NAME'] || random_string
         | 
| 10 | 
            +
                  build_id ||= ENV['BUILD_ID'] || "r#{Random.rand(1000)}"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  "#{prefix}#{job_name}-#{build_id}"
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def self.virtual_hostname(prefix: nil, job_name: nil, branch_name: nil)
         | 
| 16 | 
            +
                  prefix ||= ENV['HOST_PREFIX']
         | 
| 17 | 
            +
                  prefix = "#{prefix}." unless prefix.nil? || prefix.empty?
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  job_name ||= ENV['JOB_NAME'] || random_string.downcase
         | 
| 20 | 
            +
                  branch_name ||= (ENV['BRANCH_NAME'] || 'master').gsub(%r{.*/}, '')
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  "#{prefix}#{branch_name}.#{job_name}"
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def self.fqdn(prefix: nil, job_name: nil, branch_name: nil)
         | 
| 26 | 
            +
                  vhost = virtual_hostname(
         | 
| 27 | 
            +
                    prefix: prefix,
         | 
| 28 | 
            +
                    job_name: job_name,
         | 
| 29 | 
            +
                    branch_name: branch_name
         | 
| 30 | 
            +
                  )
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  main_domain = ENV['DOMAIN'] || Contur::DEFAULT_DOMAIN
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  "#{vhost}.#{main_domain}"
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def self.random_string(length: 8)
         | 
| 38 | 
            +
                  o = [('a'..'z'), ('A'..'Z')].map(&:to_a).flatten
         | 
| 39 | 
            +
                  (0...length).map { o[rand(o.length)] }.join
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
    
        data/lib/contur.rb
    ADDED
    
    
| @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            FROM alpine:3.3
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            MAINTAINER 'Cheppers Ltd. <info@cheppers.com> (github:Cheppers)'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ENV REFRESHED_AT <%= refreshed_at_date %>
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            # PHP Configuration
         | 
| 8 | 
            +
            ENV TIMEZONE            <%= php_timezone %>
         | 
| 9 | 
            +
            ENV PHP_MEMORY_LIMIT    <%= php_memory_limit %>
         | 
| 10 | 
            +
            ENV MAX_UPLOAD          <%= max_upload %>
         | 
| 11 | 
            +
            ENV PHP_MAX_FILE_UPLOAD <%= php_max_file_upload %>
         | 
| 12 | 
            +
            ENV PHP_MAX_POST        <%= php_max_post %>
         | 
| 13 | 
            +
            ENV TERM                dumb # for mysql-client
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            # Install packages
         | 
| 16 | 
            +
            RUN apk add --no-cache \
         | 
| 17 | 
            +
                    bash \
         | 
| 18 | 
            +
                    apache2-proxy apache2-utils \
         | 
| 19 | 
            +
                    mysql-client \
         | 
| 20 | 
            +
                    tzdata \
         | 
| 21 | 
            +
                    php-mcrypt \
         | 
| 22 | 
            +
                    php-soap \
         | 
| 23 | 
            +
                    php-openssl \
         | 
| 24 | 
            +
                    php-gmp \
         | 
| 25 | 
            +
                    php-pdo_odbc \
         | 
| 26 | 
            +
                    php-json \
         | 
| 27 | 
            +
                    php-dom \
         | 
| 28 | 
            +
                    php-pdo \
         | 
| 29 | 
            +
                    php-zip \
         | 
| 30 | 
            +
                    php-mysql \
         | 
| 31 | 
            +
                    php-sqlite3 \
         | 
| 32 | 
            +
                    php-apcu \
         | 
| 33 | 
            +
                    php-pdo_pgsql \
         | 
| 34 | 
            +
                    php-bcmath \
         | 
| 35 | 
            +
                    php-gd \
         | 
| 36 | 
            +
                    php-xcache \
         | 
| 37 | 
            +
                    php-odbc \
         | 
| 38 | 
            +
                    php-pdo_mysql \
         | 
| 39 | 
            +
                    php-pdo_sqlite \
         | 
| 40 | 
            +
                    php-gettext \
         | 
| 41 | 
            +
                    php-xmlreader \
         | 
| 42 | 
            +
                    php-xmlrpc \
         | 
| 43 | 
            +
                    php-bz2 \
         | 
| 44 | 
            +
                    php-memcache \
         | 
| 45 | 
            +
                    php-mssql \
         | 
| 46 | 
            +
                    php-iconv \
         | 
| 47 | 
            +
                    php-pdo_dblib \
         | 
| 48 | 
            +
                    php-curl \
         | 
| 49 | 
            +
                    php-ctype \
         | 
| 50 | 
            +
                    php-phar \
         | 
| 51 | 
            +
                    php-fpm
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            # Configure apache proxy (apache because of `.ht` files)
         | 
| 54 | 
            +
            RUN echo \
         | 
| 55 | 
            +
                'ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/www/$1' >> /etc/apache2/httpd.conf && \
         | 
| 56 | 
            +
                echo 'DirectoryIndex /index.php' >> /etc/apache2/httpd.conf && \
         | 
| 57 | 
            +
                sed -ie 's/#ServerName .*/ServerName localhost/i' /etc/apache2/httpd.conf && \
         | 
| 58 | 
            +
                sed -ie 's/#LoadModule slotmem_shm_module/LoadModule slotmem_shm_module/' \
         | 
| 59 | 
            +
                  /etc/apache2/httpd.conf && \
         | 
| 60 | 
            +
                sed -ie 's#/var/www/localhost/htdocs#/www#g' /etc/apache2/httpd.conf && \
         | 
| 61 | 
            +
                sed -ie 's#LoadModule proxy_fdpass_module modules/mod_proxy_fdpass.so##g' /etc/apache2/conf.d/proxy.conf && \
         | 
| 62 | 
            +
                mkdir /run/apache2/
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            # Configure Timezone, important for php
         | 
| 65 | 
            +
            RUN cp /usr/share/zoneinfo/${TIMEZONE} /etc/localtime && \
         | 
| 66 | 
            +
                echo "${TIMEZONE}" > /etc/timezone
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            # Configure PHP-FPM
         | 
| 69 | 
            +
            RUN sed -i "s|;*daemonize\s*=\s*yes|daemonize = no|g" /etc/php/php-fpm.conf && \
         | 
| 70 | 
            +
                sed -ie 's#^listen\s*=\s*.*#listen = 9000#g' \
         | 
| 71 | 
            +
                  /etc/php/php-fpm.conf && \
         | 
| 72 | 
            +
                sed -i "s|;*date.timezone =.*|date.timezone = ${TIMEZONE}|i" \
         | 
| 73 | 
            +
                  /etc/php/php.ini && \
         | 
| 74 | 
            +
                sed -i "s|;*memory_limit =.*|memory_limit = ${PHP_MEMORY_LIMIT}|i" \
         | 
| 75 | 
            +
                  /etc/php/php.ini && \
         | 
| 76 | 
            +
                sed -i "s|;*upload_max_filesize =.*|upload_max_filesize = ${MAX_UPLOAD}|i" \
         | 
| 77 | 
            +
                  /etc/php/php.ini && \
         | 
| 78 | 
            +
                sed -i "s|;*max_file_uploads =.*|max_file_uploads = ${PHP_MAX_FILE_UPLOAD}|i" \
         | 
| 79 | 
            +
                  /etc/php/php.ini && \
         | 
| 80 | 
            +
                sed -i "s|;*post_max_size =.*|post_max_size = ${PHP_MAX_POST}|i" \
         | 
| 81 | 
            +
                  /etc/php/php.ini && \
         | 
| 82 | 
            +
                sed -i "s|;*cgi.fix_pathinfo=.*|cgi.fix_pathinfo= 0|i" /etc/php/php.ini
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            # Install Composer
         | 
| 85 | 
            +
            RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
         | 
| 86 | 
            +
                php -r "if (hash_file('SHA384', 'composer-setup.php') === 'e115a8dc7871f15d853148a7fbac7da27d6c0030b848d9b3dc09e2a0388afed865e6a3d6b3c0fad45c48e2b5fc1196ae') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \
         | 
| 87 | 
            +
                php composer-setup.php --install-dir /usr/bin --filename=composer composer && \
         | 
| 88 | 
            +
                php -r "unlink('composer-setup.php');" && \
         | 
| 89 | 
            +
                chmod +x /usr/bin/composer
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            # Install Drush
         | 
| 92 | 
            +
            RUN php -r "readfile('http://files.drush.org/drush.phar');" > /usr/local/bin/drush && \
         | 
| 93 | 
            +
                php /usr/local/bin/drush core-status && \
         | 
| 94 | 
            +
                chmod +x /usr/local/bin/drush
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            # Codebase
         | 
| 97 | 
            +
            RUN mkdir /www
         | 
| 98 | 
            +
            VOLUME ["/www"]
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            RUN mkdir /initscripts
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            WORKDIR /www
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            EXPOSE 80
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            #!/bin/bash
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # ========== GENERATED SCRIPT ==========
         | 
| 4 | 
            +
            <%= before_script %>
         | 
| 5 | 
            +
            # ========== GENERATED SCRIPT ==========
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            echo "Run InitScripts"
         | 
| 8 | 
            +
            find /initscripts -type f -print -exec {} \;
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            echo "Start Apache2"
         | 
| 11 | 
            +
            /usr/sbin/httpd -d . -f /etc/apache2/httpd.conf
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            if [ ! -f /www/index.php ]; then
         | 
| 14 | 
            +
              echo "Populate '/www' because it's empty"
         | 
| 15 | 
            +
              echo '<?php phpinfo(); ?>' > /www/index.php
         | 
| 16 | 
            +
            fi
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            echo "Start PHP-FPM"
         | 
| 19 | 
            +
            /usr/bin/php-fpm
         |