singel 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b044c6a0f921fc3cd684571e5be6c2dd48e7788b
4
- data.tar.gz: 7d5117ca9e6e7a4d9d7f7248d3aca4bc053f877c
3
+ metadata.gz: aaa5865dd1830b229c430c5846b5ef4b28c586b0
4
+ data.tar.gz: 54c9c871c502e99a8e9f9103868ae7355217e1bd
5
5
  SHA512:
6
- metadata.gz: 47c2f627068266abe8fa919e4264aab32829b9335ddcbbb3c982a5c6fa70024c3f795e7b30e94328b5578c5d86cbace13345a3773f94bc8a43cad00d875ce134
7
- data.tar.gz: 23c68854c622fc10268c5e736ea1ade9117ef586ee6f8b422464b3d9846505b73d838813232da42d29c1097395d5efd706f73158e76e7c3deab76c6f386ea5a7
6
+ metadata.gz: d27fb80019dd99723ae69fd2e9c18a2be5316cea852457a8072851b9c84cd67b99157c0db4efb486f7cc5b58d5fbe6087c68a4d8dbb73e0c240a90d597a63483
7
+ data.tar.gz: f61553aed236cdf546ce82fb544213d8ad51d6eb0215e6e02a79c565f87fc14a5b408a79a42f90adbbbbecd9132e578e7ee53beef1ef58bc573c0b0bfa54357f
data/.gitignore CHANGED
@@ -39,3 +39,6 @@ Gemfile.lock
39
39
  # singel related files
40
40
  outputs
41
41
  packer
42
+
43
+ # editor files
44
+ *.swp
data/bin/singel CHANGED
@@ -25,64 +25,14 @@ begin
25
25
  require 'aws-sdk-core'
26
26
  require 'json'
27
27
  require 'pty'
28
+ require 'config.rb'
28
29
  require 'orchestrator.rb'
29
30
  require 'executor.rb'
30
31
  require 'uploader.rb'
31
32
  require 'template.rb'
33
+ require 'string.rb'
32
34
  rescue LoadError => e
33
35
  raise "Missing gem or lib #{e}"
34
36
  end
35
37
 
36
- # add a few methods for manipulating text
37
- class String
38
- def to_green
39
- "\033[32m#{self}\033[0m"
40
- end
41
-
42
- def to_red
43
- "\033[31m#{self}\033[0m"
44
- end
45
-
46
- def indent(double_space_count = 1)
47
- double_space_count.times { insert(0, ' ') }
48
- self
49
- end
50
- end
51
-
52
- def parse_opts
53
- options = { :templates => [], :builders => [], :packer_dir => File.expand_path('./packer') }
54
- banner = "Singel - Unified system image creation using Packer\n\n" \
55
- "Usage: singel [action] [options]\n\n" \
56
- " Actions:\n" \
57
- " build: Build system images\n" \
58
- " list: List available image templates and builder types (AMI, Virtualbox, etc)\n\n" \
59
- " Options:\n"
60
- OptionParser.new do |opts|
61
- opts.banner = banner
62
- opts.on('-t', '--templates t1.json,t2.json', Array, 'Build only the specified comma separated list of templates') do |t|
63
- options[:templates] = t
64
- end
65
- opts.on('-b', '--builders type1,type2', Array, 'Build only the specified comma separated list of builder types') do |b|
66
- options[:builders] = b
67
- end
68
- opts.on('-p', '--packer_dir PATH', 'Path to the packer dir containing templates and other files') do |p|
69
- options[:packer_dir] = File.expand_path(p)
70
- end
71
- opts.on('-h', '--help', 'Displays Help') do
72
- puts opts
73
- exit
74
- end
75
- end.parse!(ARGV)
76
-
77
- options
78
- end
79
-
80
- unless ARGV[0]
81
- puts "You must provide an action for singel to execute on\n".to_red
82
- ARGV << '-h'
83
- end
84
-
85
- # parse the user provided options
86
- options = parse_opts
87
-
88
- SingelOrchestrator.new(options).run
38
+ Singel::SingelOrchestrator.new.run
@@ -0,0 +1,64 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Tim Smith (<tim@cozy.co>)
4
+ # Copyright:: Copyright (c) 2014 Tim Smith
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ module Singel
20
+ # allow fetching the config anywhere in the app
21
+ module Config
22
+ require 'string.rb'
23
+
24
+ # return the config object or parse the options fresh
25
+ def self.config
26
+ @config ||= parse_opts
27
+ end
28
+
29
+ # parse options passed from the command line
30
+ def self.parse_opts
31
+ options = { :templates => [], :builders => [], :packer_dir => File.expand_path('./packer') }
32
+ banner = "Singel - Unified system image creation using Packer\n\n" \
33
+ "Usage: singel [action] [options]\n\n" \
34
+ " Actions:\n" \
35
+ " build: Build system images\n" \
36
+ " list: List available image templates and builder types (AMI, Virtualbox, etc)\n\n" \
37
+ " Options:\n"
38
+ OptionParser.new do |opts|
39
+ opts.banner = banner
40
+ opts.on('-t', '--templates t1.json,t2.json', Array, 'Build only the specified comma separated list of templates') do |t|
41
+ options[:templates] = t
42
+ end
43
+ opts.on('-b', '--builders type1,type2', Array, 'Build only the specified comma separated list of builder types') do |b|
44
+ options[:builders] = b
45
+ end
46
+ opts.on('-p', '--packer_dir PATH', 'Path to the packer dir containing templates and other files') do |p|
47
+ options[:packer_dir] = File.expand_path(p)
48
+ end
49
+ opts.on('-h', '--help', 'Displays Help') do
50
+ puts opts
51
+ exit
52
+ end
53
+ end.parse!(ARGV)
54
+
55
+ options
56
+ end
57
+
58
+ # if no argument was passed or the first arg starts with - (aka it's not actually an action)
59
+ if ARGV[0].nil? || ARGV[0][0] == '-'
60
+ puts "\nYou must provide an action for singel to execute on:\n".to_red
61
+ ARGV << '-h'
62
+ end
63
+ end
64
+ end
@@ -16,47 +16,59 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- # executes packer commands against template object
20
- class PackerExecutor
21
- def initialize(template, builders)
22
- @template = template
23
- @file_path = template.path
24
- @template_builders = template.builders
25
- @specified_builders = builders
26
- end
19
+ module Singel
20
+ # executes packer commands against template object
21
+ class PackerExecutor
22
+ def initialize(template, builders)
23
+ @template = template
24
+ @file_path = template.path
25
+ @template_builders = template.builders
26
+ @specified_builders = builders
27
+ end
27
28
 
28
- # print out the builders for this template
29
- def list
30
- puts File.basename(@file_path, '.json') + ':'
29
+ # print out the builders for this template
30
+ def list
31
+ puts File.basename(@file_path, '.json') + ':'
31
32
 
32
- builders = @template.builders_hash
33
- if builders.empty?
34
- puts '- No builders found'.indent.to_red
35
- else
36
- builders.each_pair do |name, type|
37
- puts "- #{name} (type: #{type})".indent
33
+ builders = @template.builders_hash
34
+ if builders.empty?
35
+ puts '- No builders found'.indent.to_red
36
+ else
37
+ builders.each_pair do |name, type|
38
+ puts "- #{name} (type: #{type})".indent
39
+ end
38
40
  end
39
41
  end
40
- end
41
42
 
42
- def build
43
- puts "Building #{File.basename(@file_path, '.json')}:".to_green
44
- stream_cmd("packer build #{build_options} #{@file_path}")
45
- end
43
+ def build
44
+ puts "Building #{File.basename(@file_path, '.json')}:".to_green
45
+ stream_cmd("packer build #{build_options} #{@file_path}")
46
+ end
46
47
 
47
- # specify the builders if any were passed
48
- def build_options
49
- "-only=#{@specified_builders.join(',')}" unless @specified_builders.empty?
50
- end
48
+ # specify the builders if any were passed
49
+ def build_options
50
+ "-only=#{@specified_builders.join(',')}" unless @specified_builders.empty?
51
+ end
52
+
53
+ def stream_cmd(command)
54
+ PTY.spawn(command) do |r, _w, pid|
55
+ begin
56
+ r.each { |line| print line; }
57
+ rescue Errno::EIO
58
+ # this is an expected behavior when an app is done sending output
59
+ ensure
60
+ Process.wait(pid)
61
+ end
62
+ end
63
+ exit_error unless $CHILD_STATUS == 0
64
+ rescue PTY::ChildExited
65
+ exit_error unless $CHILD_STATUS == 0
66
+ end
51
67
 
52
- def stream_cmd(command)
53
- PTY.spawn(command) do |r, _w, _pid|
54
- begin
55
- r.each { |line| print line; }
56
- rescue Errno::EIO
57
- end
68
+ # throw and error message and exit with and error status
69
+ def exit_error
70
+ puts "An error occured during the packer run.\nSee the above output for more details.".to_red
71
+ exit!
58
72
  end
59
- rescue PTY::ChildExited
60
- puts 'The child process exited!'
61
73
  end
62
74
  end
@@ -16,86 +16,90 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- # class to control validation of configs / prereqs and to
20
- # fire off the individual executor instances to build each template
21
- class SingelOrchestrator
22
- def initialize(options)
23
- @options = options
24
- end
19
+ module Singel
20
+ # class to control validation of configs / prereqs and to
21
+ # fire off the individual executor instances to build each template
22
+ class SingelOrchestrator
23
+ include Singel::Config
25
24
 
26
- # main method used to kick off the run
27
- def run
28
- puts "\nsingel - unified image creation tool"
29
- puts "-----------------------------------------\n\n"
25
+ def initialize
26
+ @options = Singel::Config.config
27
+ end
30
28
 
31
- check_dirs
32
- check_executables
33
- @templates = find_templates
34
- check_aws_keys
29
+ # main method used to kick off the run
30
+ def run
31
+ puts "\nsingel - unified image creation tool"
32
+ puts "-----------------------------------------\n\n"
35
33
 
36
- execute_command(ARGV[0])
37
- end
34
+ check_dirs
35
+ check_executables
36
+ @templates = find_templates
37
+ check_aws_keys
38
38
 
39
- # check to make sure the packer dir exists
40
- def check_dirs
41
- unless Dir.exist?(@options[:packer_dir])
42
- puts "#{@options[:packer_dir]} not present.".to_red
43
- puts "See help for information on specifying an alternate dir.\n".to_red
44
- exit!
39
+ execute_command(ARGV[0])
45
40
  end
46
- end
47
-
48
- # make a test connection using the AWS keys to determine if they're valid
49
- def check_aws_keys
50
- ec2 = Aws::EC2::Client.new(region: 'us-east-1')
51
- ec2.describe_instance_status
52
- rescue
53
- puts 'Could not connect to EC2. Check your local AWS credentials before continuing.'.to_red
54
- exit!
55
- end
56
41
 
57
- # check to make sure the prereq binaries present
58
- def check_executables
59
- { 'Virtualbox' => 'vboxwebsrv', 'Packer' => 'packer' }.each_pair do |name, binary|
60
- `which #{binary} 2>&1`
61
- unless $CHILD_STATUS.success?
62
- puts "Could not find #{name} binary #{binary}. You must install #{name} before continuing.".to_red unless $CHILD_STATUS
42
+ # check to make sure the packer dir exists
43
+ def check_dirs
44
+ unless Dir.exist?(@options[:packer_dir])
45
+ puts "#{@options[:packer_dir]} not present.".to_red
46
+ puts "See help for information on specifying an alternate dir.\n".to_red
63
47
  exit!
64
48
  end
65
49
  end
66
- end
67
50
 
68
- # find the available packer templates on the host
69
- def find_templates
70
- # find packer templates on disk since none were passed via args
71
- if @options[:templates].empty?
72
- templates = []
73
- Dir.foreach(@options[:packer_dir]) do |item|
74
- templates << File.join(@options[:packer_dir], item) if File.extname(item).downcase == '.json'
51
+ # make a test connection using the AWS keys to determine if they're valid
52
+ def check_aws_keys
53
+ ec2 = Aws::EC2::Client.new(region: 'us-east-1')
54
+ ec2.describe_instance_status
55
+ rescue
56
+ puts 'Could not connect to EC2. Check your local AWS credentials before continuing.'.to_red
57
+ exit!
58
+ end
59
+
60
+ # check to make sure the prereq binaries present
61
+ def check_executables
62
+ { 'Virtualbox' => 'vboxwebsrv', 'Packer' => 'packer' }.each_pair do |name, binary|
63
+ `which #{binary} 2>&1`
64
+ unless $CHILD_STATUS.success?
65
+ puts "Could not find #{name} binary #{binary}. You must install #{name} before continuing.".to_red unless $CHILD_STATUS
66
+ exit!
67
+ end
75
68
  end
69
+ end
76
70
 
77
- # throw and error and exist if we still dont find any templates
78
- if templates.empty?
79
- puts "No packer templates found in the 'packer' dir. Cannot continue.".to_red
80
- exit!
71
+ # find the available packer templates on the host
72
+ def find_templates
73
+ # find packer templates on disk since none were passed via args
74
+ if @options[:templates].empty?
75
+ templates = []
76
+ Dir.foreach(@options[:packer_dir]) do |item|
77
+ templates << File.join(@options[:packer_dir], item) if File.extname(item).downcase == '.json'
78
+ end
79
+
80
+ # throw and error and exist if we still dont find any templates
81
+ if templates.empty?
82
+ puts "No packer templates found in the 'packer' dir. Cannot continue.".to_red
83
+ exit!
84
+ end
85
+ templates
86
+ else # parse the arg provided template list
87
+ @options[:templates].map { |x| File.join(@options[:packer_dir], x) }
81
88
  end
82
- templates
83
- else # parse the arg provided template list
84
- @options[:templates].map { |x| File.join(@options[:packer_dir], x) }
85
89
  end
86
- end
87
90
 
88
- # run the passed command per packer template
89
- def execute_command(cmd)
90
- @templates.each do |t|
91
- template = PackerTemplate.new(t)
92
- executor = PackerExecutor.new(template, @options[:builders])
93
- puts "Packer template validation for #{template.path} failed.\n".to_red unless template.validates?
94
- begin
95
- executor.send(cmd)
96
- rescue NoMethodError
97
- puts "Action \"#{cmd}\" not found. Cannot continue".to_red
98
- exit!
91
+ # run the passed command per packer template
92
+ def execute_command(cmd)
93
+ @templates.each do |t|
94
+ template = PackerTemplate.new(t)
95
+ executor = PackerExecutor.new(template, @options[:builders])
96
+ puts "Packer template validation for #{template.path} failed.\n".to_red unless template.validates?
97
+ begin
98
+ executor.send(cmd)
99
+ rescue NoMethodError
100
+ puts "Action \"#{cmd}\" not found. Cannot continue".to_red
101
+ exit!
102
+ end
99
103
  end
100
104
  end
101
105
  end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author:: Tim Smith (<tim@cozy.co>)
4
+ # Copyright:: Copyright (c) 2014 Tim Smith
5
+ # License:: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ # add a few methods for manipulating text
20
+ class String
21
+ def to_green
22
+ "\033[32m#{self}\033[0m"
23
+ end
24
+
25
+ def to_red
26
+ "\033[31m#{self}\033[0m"
27
+ end
28
+
29
+ def indent(double_space_count = 1)
30
+ double_space_count.times { insert(0, ' ') }
31
+ self
32
+ end
33
+ end
@@ -16,38 +16,38 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- require 'json'
19
+ module Singel
20
+ # instance of a single packer template with methods to validate and extract data
21
+ class PackerTemplate
22
+ attr_accessor :path, :name
20
23
 
21
- # instance of a single packer template with methods to validate and extract data
22
- class PackerTemplate
23
- attr_accessor :path, :name
24
-
25
- def initialize(path)
26
- @path = File.expand_path(path)
27
- @name = File.basename(@path, '.json')
28
- @file = File.read(path)
29
- end
24
+ def initialize(path)
25
+ @path = File.expand_path(path)
26
+ @name = File.basename(@path, '.json')
27
+ @file = File.read(path)
28
+ end
30
29
 
31
- def json
32
- @parsed || @parsed = JSON.parse(@file)
33
- end
30
+ def json
31
+ @parsed || @parsed = JSON.parse(@file)
32
+ end
34
33
 
35
- def builders
36
- json['builders'].map { |b| b['name'] }
37
- end
34
+ def builders
35
+ json['builders'].map { |b| b['name'] }
36
+ end
38
37
 
39
- def builders_hash
40
- builders = {}
41
- json['builders'].each do |builder|
42
- builders[builder['name']] = builder['type']
38
+ def builders_hash
39
+ builders = {}
40
+ json['builders'].each do |builder|
41
+ builders[builder['name']] = builder['type']
42
+ end
43
+ builders
43
44
  end
44
- builders
45
- end
46
45
 
47
- # shell out to packer to validate the config files for correctness
48
- def validates?
49
- Dir.chdir(File.dirname(@path))
50
- `packer validate #{@path} 2>&1`
51
- $CHILD_STATUS.success? ? true : false
46
+ # shell out to packer to validate the config files for correctness
47
+ def validates?
48
+ Dir.chdir(File.dirname(@path))
49
+ `packer validate #{@path} 2>&1`
50
+ $CHILD_STATUS.success? ? true : false
51
+ end
52
52
  end
53
53
  end
@@ -16,13 +16,15 @@
16
16
  # See the License for the specific language governing permissions and
17
17
  # limitations under the License.
18
18
 
19
- # uploads the packer artifacts to S3
20
- class SingelUploader
21
- def initialize(template)
22
- @file_path = template
23
- end
19
+ module Singel
20
+ # uploads the packer artifacts to S3
21
+ class SingelUploader
22
+ def initialize(template)
23
+ @file_path = template
24
+ end
24
25
 
25
- def push
26
- puts "- Would be uploading the artifact for #{File.basename(@file_path, '.json')}".to_green.indent
26
+ def push
27
+ puts "- Would be uploading the artifact for #{File.basename(@file_path, '.json')}".to_green.indent
28
+ end
27
29
  end
28
30
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'singel'
3
- s.version = '0.2.1'
3
+ s.version = '0.2.2'
4
4
  s.date = Date.today.to_s
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.extra_rdoc_files = ['README.md', 'LICENSE']
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: singel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-16 00:00:00.000000000 Z
11
+ date: 2015-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-core
@@ -68,8 +68,10 @@ files:
68
68
  - README.md
69
69
  - Rakefile
70
70
  - bin/singel
71
+ - lib/config.rb
71
72
  - lib/executor.rb
72
73
  - lib/orchestrator.rb
74
+ - lib/string.rb
73
75
  - lib/template.rb
74
76
  - lib/uploader.rb
75
77
  - singel.gemspec