builderator 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 48baf4bb78a9121f6268913550ac1cdf5157aa1c
4
+ data.tar.gz: 761c4a044264ad1109a534ab41a382076d2298bc
5
+ SHA512:
6
+ metadata.gz: 988210a27ccc466c5b0d1fa5548aae42524043b6c31fe290cbbf27e2d13d42f094b1552662befa899c7b047906b60e9153e71afb88598b3d2598ae5c337b5bbd
7
+ data.tar.gz: 20a6c23658cd4e12f583319512b42609fe6aa5fb0f894d56d01283248839c9f97223aaf69a22c381d6f573de514e41a2619f5b7799c8e9706349783e37ff318b
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,16 @@
1
+ AllCops:
2
+ Exclude:
3
+ - libraries/**/*
4
+ - spec/**/*
5
+ - metadata.rb
6
+
7
+ Encoding:
8
+ Enabled: false
9
+ LineLength:
10
+ Enabled: false
11
+ HashSyntax:
12
+ Enabled: false
13
+ RescueModifier:
14
+ Enabled: false
15
+ MethodLength:
16
+ Max: 24
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in builderator.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 John Manero
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Builderator
2
+ __Tools to make CI Packer builds awesome__
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'builderator'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install builderator
19
+
20
+ ## Usage
21
+
22
+ Run `bundle exec thor build help`
23
+
24
+ ## Contributing
25
+
26
+ 1. Fork it ( https://github.com/[my-github-username]/builderator/fork )
27
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
28
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
29
+ 4. Push to the branch (`git push origin my-new-feature`)
30
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/Thorfile ADDED
@@ -0,0 +1 @@
1
+ require 'thor-scmversion'
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.10
data/bin/build ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ unless ENV.include?('BUNDLE_GEMFILE')
3
+ puts ''
4
+ puts ' / \\'
5
+ puts ' | ^ |'
6
+ puts " ಠ _ ಠ It looks like you're trying to run Builderator outside of Bundler!"
7
+ puts ' || || This is aggressively discouraged! Please re-run your command'
8
+ puts ' || || prepended with `bundle exec`'
9
+ puts ' || ||'
10
+ puts ' | | See http://bundler.io/ for help setting up Bundler and creating a Gemfile'
11
+ puts ' \\/'
12
+ puts ''
13
+ exit 1
14
+ end
15
+
16
+ require_relative '../lib/builderator/tasks'
17
+ Builderator::Tasks::CLI.start(ARGV)
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'builderator/metadata'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'builderator'
8
+ spec.version = Builderator::VERSION
9
+ spec.authors = ['John Manero']
10
+ spec.email = ['jmanero@rapid7.com']
11
+ spec.summary = 'Tools to make CI Packer builds awesome'
12
+ spec.description = Builderator::DESCRIPTION
13
+ spec.homepage = 'https://github.com/rapid7/builderator'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = Dir[File.join(Builderator::PATH, 'bin/*')].map { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'rake', '~> 10.0'
22
+
23
+ spec.add_dependency 'aws-sdk', '~> 2.0'
24
+ spec.add_dependency 'bundler', '~> 1.7.0'
25
+ spec.add_dependency 'berkshelf', '~> 3.2'
26
+ spec.add_dependency 'chef', '~> 12.0'
27
+ spec.add_dependency 'thor', '~> 0.19.0'
28
+ spec.add_dependency 'thor-scmversion', '1.7.0'
29
+ end
data/docs/clean.md ADDED
@@ -0,0 +1,21 @@
1
+ build-clean
2
+ ===========
3
+ Tasks to delete/deregister abandoned EC2 resources
4
+
5
+ ### Options
6
+ * `--commit` Execute cleanup task. Default behavior is to display resources that would be removed
7
+ * `--filter KEY VALUE [KEY VALUE []]` Key/value pairs to filter resources. Valid keys include tags and native resource properties (See `describe` responses in the Ruby AWS-SDK)
8
+
9
+ ### Commands
10
+ * `configs` Delete launch configurations that are not associated with an autoscaling group.
11
+
12
+ * `images` Delete images that are not associated with a launch configuration, a running instance, or are tagged as the 'parent' of an image that qualifies for any of the previous three conditions. Additionally, a fixed number of images can be retained per ordered groups.
13
+
14
+ **Options**
15
+ * `--group-by KEY [KEY []]` Tags/properties to group images by for pruning
16
+ * `--sort-by KEY` Tag/property to sort grouped images on (Default: creation_date)
17
+ * `--keep N` Number of images in each group to keep (Default: 0)
18
+
19
+ * `snapshots` Delete snapshots that are not associated with existing volumes or images.
20
+
21
+ * `volumes` Delete volumes that are not attached to instances.
@@ -0,0 +1,4 @@
1
+ require 'builderator/metadata'
2
+
3
+ module Builderator
4
+ end
@@ -0,0 +1,64 @@
1
+ require 'aws-sdk'
2
+ require 'date'
3
+
4
+ require_relative '../util'
5
+
6
+ module Builderator
7
+ module Control
8
+ ##
9
+ # Find AMI IDs to use for sources
10
+ ##
11
+ module AMI
12
+ ## Account IDs of public image owners
13
+ module Owners
14
+ SELF = 'self'.freeze
15
+ UBUNTU = '099720109477'.freeze
16
+ end
17
+
18
+ ## Filter fields defined in http://docs.aws.amazon.com/sdkforruby/api/Aws/EC2/Builderator::Util.ec2.html#describe_images-instance_method
19
+ FILTERS = %w(architecture block-device-mapping.delete-on-termination
20
+ block-device-mapping.device-name block-device-mapping.snapshot-id
21
+ block-device-mapping.volume-size block-device-mapping.volume-type
22
+ description hypervisor image-id image-type is-public kernel-id
23
+ manifest-location name owner-alias owner-id platform product-code
24
+ product-code.type ramdisk-id root-device-name root-device-type
25
+ state state-reason-code state-reason-message virtualization-type).freeze
26
+
27
+ class << self
28
+ def search(filters = {})
29
+ [].tap do |images|
30
+ Builderator::Util.ec2.describe_images(search_options(filters)).each { |page| images.push(*page.images) }
31
+ end
32
+ end
33
+
34
+ def latest(filters)
35
+ search(filters).sort do |a, b|
36
+ DateTime.iso8601(b.creation_date) <=> DateTime.iso8601(a.creation_date)
37
+ end.first
38
+ end
39
+
40
+ private
41
+
42
+ def search_options(filters)
43
+ {}.tap do |options|
44
+ options[:image_ids] = Util.to_array(filters.delete(:image_id)) if filters.include?(:image_id)
45
+ options[:owners] = Util.to_array(filters.delete(:owner) { 'self' })
46
+
47
+ rfilters = [].tap do |f|
48
+ filters.each do |k, v|
49
+ next if v.nil?
50
+
51
+ f << {
52
+ :name => FILTERS.include?(k.to_s) ? k : "tag:#{ k }",
53
+ :values => Util.to_array(v)
54
+ }
55
+ end
56
+ end
57
+
58
+ options[:filters] = rfilters unless rfilters.empty?
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,134 @@
1
+ require_relative '../model'
2
+ require_relative '../util'
3
+
4
+ module Builderator
5
+ module Control
6
+ ##
7
+ # Control logic for cleanup tasks
8
+ ##
9
+ module Clean
10
+ class << self
11
+
12
+ def options(arg = nil)
13
+ return @options unless arg.is_a?(Hash)
14
+
15
+ @options = arg.clone
16
+
17
+ Util.region(@options.delete('region'))
18
+ @commit = @options.delete('commit') { false }
19
+ @limit = @options.delete('limit') { true }
20
+
21
+ @options
22
+ end
23
+
24
+ def configs!
25
+ resources = Model.launch_configs.unused(options)
26
+
27
+ limit!(Model::LaunchConfigs, 'Cleanup Launch Configurations', resources, &Proc.new)
28
+ aborted!(&Proc.new)
29
+
30
+ resources.each do |l, _|
31
+ yield :remove, "Launch Configuration #{ l }", :red
32
+ Model.launch_configs.resources.delete(l)
33
+
34
+ next unless commit?
35
+ # puts "delete_launch_configuration(:launch_configuration_name => #{l})"
36
+ Util.asg.delete_launch_configuration(:launch_configuration_name => l)
37
+ end
38
+ rescue Aws::AutoScaling::Errors::ServiceError => e
39
+ exceptions << Util::AwsException.new('Cleanup Launch Configurations', e)
40
+ yield(*exceptions.last.status)
41
+ end
42
+
43
+ def images!
44
+ resources = Model.images.unused(options)
45
+
46
+ limit!(Model::Images, 'Cleanup Images', resources, &Proc.new)
47
+ aborted!(&Proc.new)
48
+
49
+ resources.each do |i, image|
50
+ yield :remove, "Image #{ i } (#{ image[:properties]['name'] })", :red
51
+ Model.images.resources.delete(i)
52
+
53
+ next unless commit?
54
+ puts "deregister_image(:image_id => #{i})"
55
+ # Util.ec2.deregister_image(:image_id => i)
56
+ end
57
+ rescue Aws::EC2::Errors::ServiceError => e
58
+ exceptions << Util::AwsException.new('Cleanup Images', e)
59
+ yield(*exceptions.last.status)
60
+ end
61
+
62
+ def snapshots!
63
+ resources = Model.snapshots.unused
64
+
65
+ limit!(Model::Snapshots, 'Cleanup Snapshots', resources, &Proc.new)
66
+ aborted!(&Proc.new)
67
+
68
+ resources.each do |s, _|
69
+ yield :remove, "Snapshot #{ s }", :red
70
+ Model.snapshots.resources.delete(s)
71
+
72
+ next unless commit?
73
+ puts "delete_snapshot(:snapshot_id => #{s})"
74
+ # Util.ec2.delete_snapshot(:snapshot_id => s)
75
+ end
76
+ rescue Aws::EC2::Errors::ServiceError => e
77
+ exceptions << Util::AwsException.new('Cleanup Snapshots', e)
78
+ yield(*exceptions.last.status)
79
+ end
80
+
81
+ def volumes!
82
+ resources = Model.volumes.unused
83
+
84
+ limit!(Model::Volumes, 'Cleanup Volumes', resources, &Proc.new)
85
+ aborted!(&Proc.new)
86
+
87
+ resources.each do |v, _|
88
+ yield :remove, "Volume #{ v }", :red
89
+ Model.volumes.resources.delete(v)
90
+
91
+ next unless commit?
92
+ puts "delete_volume(:volume_id => #{v})"
93
+ # Util.ec2.delete_volume(:volume_id => v)
94
+ end
95
+ rescue Aws::EC2::Errors::ServiceError => e
96
+ exceptions << Util::AwsException.new('Cleanup Volumes', e)
97
+ yield(*exceptions.last.status)
98
+ end
99
+
100
+ def commit?
101
+ @commit && !@abort
102
+ end
103
+
104
+ def limit?
105
+ @limit
106
+ end
107
+
108
+ def aborted?
109
+ @commit && @abort
110
+ end
111
+
112
+ def exceptions
113
+ @exceptions ||= []
114
+ end
115
+
116
+ private
117
+
118
+ def aborted!
119
+ yield :aborted, 'The following resources will NOT be removed because'\
120
+ ' safty constraints have not been met!', :yellow if aborted?
121
+ end
122
+
123
+ def limit!(klass, task, resources)
124
+ return unless limit? && (resources.size >= klass::LIMIT)
125
+
126
+ exceptions << Util::LimitException.new(klass, task, resources)
127
+ @abort = true
128
+
129
+ yield(*exceptions.last.status)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,5 @@
1
+ module Builderator
2
+ PATH = File.expand_path('../../..', __FILE__)
3
+ VERSION = IO.read(File.join(PATH, 'VERSION')) rescue '0.0.1'
4
+ DESCRIPTION = IO.read(File.join(PATH, 'README.md')) rescue 'README.md not found!'
5
+ end
@@ -0,0 +1,46 @@
1
+ module Builderator
2
+ module Model
3
+ ##
4
+ # Shared model interface
5
+ ##
6
+ class Base
7
+ attr_reader :resources
8
+ LIMIT = 4
9
+
10
+ def initialize(*args)
11
+ fetch(*args)
12
+ end
13
+
14
+ def fetch
15
+ @resources = {}
16
+ end
17
+
18
+ def find(filters = {})
19
+ Util.filter(resources, filters)
20
+ end
21
+
22
+ def select(set = [])
23
+ resources.select { |k, _| set.include?(k) }
24
+ end
25
+
26
+ def reject(set = [])
27
+ resources.reject { |k, _| set.include?(k) }
28
+ end
29
+
30
+ def in_use(options = {})
31
+ find(options.fetch('filters', {}))
32
+ end
33
+
34
+ def unused(options = {})
35
+ Util.filter(reject(in_use(options)), options.fetch('filters', {}))
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ require_relative './model/images'
42
+ require_relative './model/instances'
43
+ require_relative './model/launch_configs'
44
+ require_relative './model/scaling_groups'
45
+ require_relative './model/snapshots'
46
+ require_relative './model/volumes'