Module: Builderator::Config

Defined in:
lib/builderator/config.rb,
lib/builderator/config/file.rb,
lib/builderator/config/list.rb,
lib/builderator/config/rash.rb,
lib/builderator/config/defaults.rb,
lib/builderator/config/attributes.rb

Overview

:nodoc

Defined Under Namespace

Classes: Attributes, File, List, Rash

Constant Summary collapse

GLOBAL_DEFAULTS =

Global predefined defaults

File.new({}, :source => 'GLOBAL_DEFAULTS') do
  cleanup true
  version '0.0.0'
  build_number 0

  autoversion do |autoversion|
    autoversion.create_tags false
    autoversion.search_tags true
  end

  local do |local|
    local.cookbook_path Util.workspace('cookbooks')
  end

  chef do |chef|
    chef.log_level :info
    chef.staging_directory '/var/chef'
    chef.version = '12.5.1'
  end

  cookbook do |cookbook|
    cookbook.path = '.'
    cookbook.add_source 'https://supermarket.chef.io'
  end

  berkshelf do |berkshelf|
    berkshelf.solver :gecode
  end

  aws.region 'us-east-1'

  profile :default do |profile|
    profile.log_level :info

    profile.vagrant do |vagrant|
      vagrant.ec2 do |ec2|
        ec2.provider :aws

        ec2.box 'dummy'
        ec2.box_url 'https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box'

        ec2.region = 'us-east-1'
        ec2.instance_type 't2.micro'
        ec2.ssh_username 'ubuntu'
        ec2.ssh_host_attribute :public_ip_address
      end

      vagrant.local do |local|
        local.provider :virtualbox

        ## Atlas metadata for Ubuntu cloud-images: https://atlas.hashicorp.com/ubuntu/boxes/trusty64
        local.box 'ubuntu/trusty64'

        local.memory 1024
        local.cpus 2
      end
    end

    profile.packer do |packer|
      packer.build :default do |build|
        build.type 'amazon-ebs'
        build.region = 'us-east-1'
        build.instance_type 'c3.large'
        build.ami_virtualization_type 'hvm'

        build.ssh_username 'ubuntu'

        # Packer default is 300 seconds.  Specify as a string to give units
        # such as s (seconds), ms (milliseconds), ns (nanoseconds), etc.
        # Ints will be interpreted as ns.  Buyer beware.
        build.ssh_timeout '300s'

        build.ami_name [Config.build_name, Config.version, Config.build_number].reject(&:nil?).join('-')
        build.ami_description Config.description
      end
    end
  end

  profile :docker do |profile|
    profile.log_level :info

    profile.packer do |packer|
      packer.build :docker do |build|
        build.type 'docker'
      end
    end
  end

  cleaner do |cleaner|
    cleaner.commit false
    cleaner.force false
    cleaner.filters {}
    cleaner.sort_by 'creation_date'
    cleaner.keep 5

    cleaner.limits do |limits|
      limits.images 24
      limits.launch_configs 48
      limits.snapshots 24
      limits.volumes 8
    end
  end

  generator.project :default do |default|
    default.builderator.version '~> 1.0'

    default.vagrant do |vagrant|
      vagrant.install false
      vagrant.version 'v1.8.0'

      vagrant.plugin 'vagrant-aws'
      vagrant.plugin 'vagrant-omnibus'
    end

    default.resource :berksfile do |berksfile|
      berksfile.path 'Berksfile', 'Berksfile.lock'
      berksfile.action :rm
    end

    default.resource :buildfile do |buildfile|
      buildfile.path 'Buildfile'
      buildfile.action :create
      buildfile.template 'template/Buildfile.erb'
    end

    default.resource :cookbook do |cookbook|
      cookbook.path 'cookbook'
      cookbook.action :rm
    end

    default.resource :gemfile do |gemfile|
      gemfile.path 'Gemfile'
      gemfile.action :create
      gemfile.template 'template/Gemfile.erb'
    end

    default.resource :gitignore do |gitignore|
      gitignore.path '.gitignore'
      gitignore.action :create
      gitignore.template 'template/gitignore.erb'
    end

    default.resource :packerfile do |packerfile|
      packerfile.path 'packer.json', 'packer'
      packerfile.action :rm
    end

    default.resource :rubocop do |rubocop|
      rubocop.path '.rubocop.yml'
      rubocop.action :create
      rubocop.template 'template/rubocop.erb'
    end

    default.resource :readme do |readme|
      readme.path 'README.md'
      readme.action :create
      readme.template 'template/README.md.erb'
    end

    default.resource :thorfile do |thorfile|
      thorfile.path 'Thorfile'
      thorfile.action :rm
    end

    default.resource :vagrantfile do |vagrantfile|
      vagrantfile.path 'Vagrantfile'
      vagrantfile.action :rm
    end
  end
end

Class Method Summary collapse

Class Method Details

.all_layersObject



16
17
18
# File 'lib/builderator/config.rb', line 16

def all_layers
  ([GLOBAL_DEFAULTS, defaults] + layers + [overrides, argv])
end

.append(path) ⇒ Object Also known as: load



32
33
34
# File 'lib/builderator/config.rb', line 32

def append(path)
  layers << File.from_file(path) if ::File.exist?(path)
end

.append_json(path) ⇒ Object Also known as: load_json



37
38
39
# File 'lib/builderator/config.rb', line 37

def append_json(path)
  layers << File.from_json(path) if ::File.exist?(path)
end

.argv(options = {}) ⇒ Object



28
29
30
# File 'lib/builderator/config.rb', line 28

def argv(options = {})
  @argv ||= File.new(options, :source => 'argv')
end

.compile(max_iterations = 6) ⇒ Object Also known as: recompile

The compile method renders a single File instance from all of the configured input layers. It follows the following algorithm:

> ‘DIRTY` is defined as the logical OR of the dirty state of each layer.

Layers are responsible for detecting changes to their own properties
while being compiled.

> LOOP unitl not DIRTY plus 1 iteration

1. Call each layer's own compile method.
2. For each layer, merge it into the COMPILED output.
FAIL if ITERATIONS > LIMIT

> The additional iteration after DIRTY becomes false is to ensure that

any changes to the compiled output during the final merge are passed
back through each layer's compile.


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
# File 'lib/builderator/config.rb', line 67

def compile(max_iterations = 6)
  compiled.unseal
  compile_iterations = 0
  break_break = false

  ## Inject GLOBAL_DEFAULTS before starting compile
  compiled.merge(GLOBAL_DEFAULTS.compile)

  ## Automatically recompile while layers are dirty
  loop do
    fail "Re-compile iteration limit of #{max_iterations} has been exceeded. "\
         "#{all_layers.select(&:dirty).map(&:source).join(', ')} are dirty." if compile_iterations >= max_iterations

    ## Merge layers from lowest to highest. Compile, then merge.
    all_layers.each do |layer|
      layer.compile
    end

    all_layers.each do |layer|
      layer.policies.each { |_, policy| compiled.merge(policy) }

      ## Merge layer after its policy documents to allow overides
      compiled.merge(layer)
    end

    break if break_break && !dirty?

    break_break = !dirty?
    compile_iterations += 1
  end

  ## Don't auto-populate keys anymore
  compiled.seal
end

.compiledObject



107
108
109
# File 'lib/builderator/config.rb', line 107

def compiled
  @compiled ||= File.new({}, :source => 'compiled')
end

.defaultsObject



20
21
22
# File 'lib/builderator/config.rb', line 20

def defaults
  @defaults ||= File.new({}, :source => 'defaults')
end

.dirty?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/builderator/config.rb', line 103

def dirty?
  all_layers.any?(&:dirty)
end

.fetch(key, *args) ⇒ Object Also known as: []



121
122
123
# File 'lib/builderator/config.rb', line 121

def fetch(key, *args)
  compiled.send(key, *args)
end

.layersObject

GLOBAL_DEFAULTS is the lowest-precedence layer, followed by dynamically defined instance-defaults.



12
13
14
# File 'lib/builderator/config.rb', line 12

def layers
  @layers ||= []
end

.method_missing(method_name, *args) ⇒ Object



126
127
128
129
130
# File 'lib/builderator/config.rb', line 126

def method_missing(method_name, *args)
  return super unless compiled.respond_to?(method_name)

  compiled.send(method_name, *args)
end

.overridesObject



24
25
26
# File 'lib/builderator/config.rb', line 24

def overrides
  @overrides ||= File.new({}, :source => 'overrides')
end

.prepend(path) ⇒ Object



42
43
44
# File 'lib/builderator/config.rb', line 42

def prepend(path)
  layers.unshift(File.from_file(path)) if ::File.exist?(path)
end

.prepend_json(path) ⇒ Object



46
47
48
# File 'lib/builderator/config.rb', line 46

def prepend_json(path)
  layers.unshift(File.from_json(path)) if ::File.exist?(path)
end

.reset!Object



111
112
113
114
115
116
117
118
119
# File 'lib/builderator/config.rb', line 111

def reset!
  @layers = []

  @defaults = File.new({}, :source => 'defaults')
  @overrides = File.new({}, :source => 'overrides')
  @argv = File.new({}, :source => 'argv')

  @compiled = File.new({}, :source => 'compiled')
end