singel 0.2.1 → 0.2.2

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 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