nucleon 0.1.0

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.
data/README.rdoc ADDED
@@ -0,0 +1,26 @@
1
+ = coral_gem
2
+
3
+ This gem provides starter scaffolding for further development. It is
4
+ scaffolding but it is functional.
5
+
6
+ == Contributing to coral_gem
7
+
8
+ * Check out the latest {major}.{minor} branch to make sure the feature hasn't
9
+ been implemented or the bug hasn't been fixed yet.
10
+ * Check out the issue tracker to make sure someone already hasn't requested
11
+ it and/or contributed it.
12
+ * Fork the project.
13
+ * Start a feature/bugfix branch.
14
+ * Commit and push until you are happy with your contribution.
15
+ * Make sure to add tests for it. This is important so I don't break it in a
16
+ future version unintentionally.
17
+ * Please try not to mess with the Rakefile, version, or history. If you want
18
+ to have your own version, or is otherwise necessary, that is fine, but
19
+ please isolate to its own commit so I can cherry-pick around it.
20
+
21
+ == Copyright
22
+
23
+ Licensed under GPLv3. See LICENSE.txt for further details.
24
+
25
+ Copyright (c) 2013 Adrian Webb <adrian.webb@coraltech.net>
26
+ Coral Technology Group LLC
data/Rakefile ADDED
@@ -0,0 +1,76 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'bundler'
6
+ require 'jeweler'
7
+ require 'rspec/core/rake_task'
8
+ require 'rdoc/task'
9
+ require 'yard'
10
+
11
+ require './lib/nucleon.rb'
12
+
13
+ #-------------------------------------------------------------------------------
14
+ # Dependencies
15
+
16
+ begin
17
+ Bundler.setup(:default, :development)
18
+ rescue Bundler::BundlerError => e
19
+ $stderr.puts e.message
20
+ $stderr.puts "Run `bundle install` to install missing gems"
21
+ exit e.status_code
22
+ end
23
+
24
+ #-------------------------------------------------------------------------------
25
+ # Gem specification
26
+
27
+ Jeweler::Tasks.new do |gem|
28
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
29
+ gem.name = "nucleon"
30
+ gem.homepage = "http://github.com/coralnexus/nucleon"
31
+ gem.rubyforge_project = 'nucleon'
32
+ gem.license = "GPLv3"
33
+ gem.email = "adrian.webb@coralnexus.com"
34
+ gem.authors = ["Adrian Webb"]
35
+ gem.summary = %Q{Framework that provides a simple foundation for building distributively configured, extremely pluggable and extendable, and easily parallel Ruby applications}
36
+ gem.description = %Q{Framework that provides a simple foundation for building distributively configured, extremely pluggable and extendable, and easily parallel Ruby applications}
37
+ gem.required_ruby_version = '>= 1.8.1'
38
+ gem.has_rdoc = true
39
+ gem.rdoc_options << '--title' << 'Nucleon' <<
40
+ '--main' << 'README.rdoc' <<
41
+ '--line-numbers'
42
+
43
+ # Dependencies defined in Gemfile
44
+ end
45
+ Jeweler::RubygemsDotOrgTasks.new
46
+
47
+ #-------------------------------------------------------------------------------
48
+ # Testing
49
+
50
+ RSpec::Core::RakeTask.new(:spec, :tag) do |spec, task_args|
51
+ options = []
52
+ options << "--tag #{task_args[:tag]}" if task_args.is_a?(Array) && ! task_args[:tag].to_s.empty?
53
+ spec.rspec_opts = options.join(' ')
54
+ end
55
+
56
+ task :default => :spec
57
+
58
+ #-------------------------------------------------------------------------------
59
+ # Documentation
60
+
61
+ version = Nucleon::VERSION
62
+ doc_title = "nucleon #{version}"
63
+
64
+ Rake::RDocTask.new do |rdoc|
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = doc_title
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
71
+ #---
72
+
73
+ YARD::Rake::YardocTask.new do |ydoc|
74
+ ydoc.files = [ 'README*', 'lib/**/*.rb' ]
75
+ ydoc.options = [ "--output-dir yardoc", "--title '#{doc_title}'" ]
76
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/nucleon.rb ADDED
@@ -0,0 +1,172 @@
1
+
2
+ #*******************************************************************************
3
+ # Nucleon
4
+ #
5
+ # Framework that provides a simple foundation for building distributively
6
+ # configured, extremely pluggable and extendable, and easily parallel
7
+ # applications.
8
+ #
9
+ # Author:: Adrian Webb (mailto:adrian.webb@coralnexus.com)
10
+ # License:: GPLv3
11
+
12
+ #-------------------------------------------------------------------------------
13
+ # Global namespace
14
+
15
+ module Kernel
16
+
17
+ def dbg(data, label = '')
18
+ # Invocations of this function should NOT be committed to the project
19
+ require 'pp'
20
+
21
+ puts '>>----------------------'
22
+ unless label.empty?
23
+ puts label
24
+ puts '---'
25
+ end
26
+ pp data
27
+ puts '<<'
28
+ end
29
+
30
+ #---
31
+
32
+ def nucleon_locate(command)
33
+ command = command.to_s
34
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
35
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
36
+ exts.each do |ext|
37
+ exe = File.join(path, "#{command}#{ext}")
38
+ return exe if File.executable?(exe)
39
+ end
40
+ end
41
+ return nil
42
+ end
43
+
44
+ #---
45
+
46
+ def nucleon_require(base_dir, name)
47
+ name = name.to_s
48
+ top_level_file = File.join(base_dir, "#{name}.rb")
49
+
50
+ require top_level_file if File.exists?(top_level_file)
51
+
52
+ directory = File.join(base_dir, name)
53
+
54
+ if File.directory?(directory)
55
+ Dir.glob(File.join(directory, '**', '*.rb')).each do |sub_file|
56
+ require sub_file
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ #-------------------------------------------------------------------------------
63
+ # Top level properties
64
+
65
+ lib_dir = File.dirname(__FILE__)
66
+ core_dir = File.join(lib_dir, 'nucleon')
67
+ mixin_dir = File.join(core_dir, 'mixin')
68
+ mixin_config_dir = File.join(mixin_dir, 'config')
69
+ mixin_action_dir = File.join(mixin_dir, 'action')
70
+ macro_dir = File.join(mixin_dir, 'macro')
71
+ util_dir = File.join(core_dir, 'util')
72
+ mod_dir = File.join(core_dir, 'mod')
73
+ plugin_dir = File.join(core_dir, 'plugin')
74
+
75
+ #-------------------------------------------------------------------------------
76
+ # Coral requirements
77
+
78
+ git_location = nucleon_locate('git')
79
+
80
+ $:.unshift(lib_dir) unless $:.include?(lib_dir) || $:.include?(File.expand_path(lib_dir))
81
+
82
+ #---
83
+
84
+ require 'rubygems'
85
+
86
+ require 'pp'
87
+ require 'i18n'
88
+ require 'log4r'
89
+ require 'log4r/configurator'
90
+ require 'base64'
91
+ require 'deep_merge'
92
+ require 'facter'
93
+ require 'yaml'
94
+ require 'multi_json'
95
+ require 'digest/sha1'
96
+ require 'optparse'
97
+ require 'thread' # Eventually depreciated
98
+ require 'celluloid'
99
+ require 'celluloid/autostart'
100
+
101
+ #---
102
+
103
+ # TODO: Make this dynamically settable
104
+
105
+ I18n.enforce_available_locales = false
106
+ I18n.load_path << File.expand_path(File.join('..', 'locales', 'en.yml'), lib_dir)
107
+
108
+ #---
109
+
110
+ if git_location
111
+ require 'grit'
112
+ nucleon_require(util_dir, :git)
113
+ end
114
+
115
+ #---
116
+
117
+ # Object modifications (100% pure monkey patches)
118
+ Dir.glob(File.join(mod_dir, '*.rb')).each do |file|
119
+ require file
120
+ end
121
+
122
+ #---
123
+
124
+ # Mixins for classes
125
+ Dir.glob(File.join(mixin_dir, '*.rb')).each do |file|
126
+ require file
127
+ end
128
+ Dir.glob(File.join(mixin_config_dir, '*.rb')).each do |file|
129
+ require file
130
+ end
131
+ Dir.glob(File.join(mixin_action_dir, '*.rb')).each do |file|
132
+ require file
133
+ end
134
+ Dir.glob(File.join(macro_dir, '*.rb')).each do |file|
135
+ require file
136
+ end
137
+
138
+ #---
139
+
140
+ # Include bootstrap classes
141
+ nucleon_require(core_dir, :errors)
142
+ nucleon_require(core_dir, :codes)
143
+ nucleon_require(util_dir, :data)
144
+ nucleon_require(core_dir, :config)
145
+ nucleon_require(util_dir, :interface)
146
+ nucleon_require(core_dir, :core)
147
+
148
+ #---
149
+
150
+ # Include core utilities
151
+ [ :liquid,
152
+ :cli,
153
+ :disk,
154
+ :package,
155
+ :shell
156
+ ].each do |name|
157
+ nucleon_require(util_dir, name)
158
+ end
159
+
160
+ # Include core systems
161
+ nucleon_require(core_dir, :facade)
162
+ nucleon_require(core_dir, :gems)
163
+ nucleon_require(core_dir, :manager)
164
+ nucleon_require(plugin_dir, :base)
165
+ nucleon_require(core_dir, :plugin)
166
+
167
+ #-------------------------------------------------------------------------------
168
+ # Basic information
169
+
170
+ module Nucleon
171
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
172
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,232 @@
1
+ en:
2
+ nucleon:
3
+ errors:
4
+ batch_error: |-
5
+ An issue was encountered during batch processing
6
+ core:
7
+ util:
8
+ cli:
9
+ options:
10
+ help: |-
11
+ Display help information for this command
12
+ log_level: |-
13
+ Set the logging level for this execution run
14
+ encoded: |-
15
+ Optional encoded parameter set that contains default action settings (machine use only)
16
+ parse:
17
+ error: |-
18
+ There was a problem with the command arguments given
19
+ batch:
20
+ unexpected_error: |
21
+ There was a problem with batch %{process}: %{message}
22
+ coral_error: |
23
+ There was a problem with batch %{process}: %{message}
24
+ mixins:
25
+ project:
26
+ options:
27
+ provider: |-
28
+ Coral plugin provider to use for this project (default %{default_value})
29
+ reference: |-
30
+ Project URL or reference string to set as primary remote (default %{default_value})
31
+ revision: |-
32
+ Revision or branch to load (default %{default_value})
33
+ commit:
34
+ options:
35
+ commit: |-
36
+ Commit any uncommitted changes (default %{default_value})
37
+ empty: |-
38
+ Allow commits with no changes (default %{default_value})
39
+ message: |-
40
+ Commit message (defaults to auto generated commit information)
41
+ author: |-
42
+ Author of the changes being committed if different from the committer
43
+ propogate: |-
44
+ Propogate commits throughout the project tree (default %{default_value})
45
+ push:
46
+ options:
47
+ push: |-
48
+ Push changes to remote server (default %{default_value})
49
+ propogate: |-
50
+ Propogate pushes to the remote throughout the project tree (default %{default_value})
51
+ remote: |-
52
+ Remote name to push to (default %{default_value})
53
+ revision: |-
54
+ Branch to push (default %{default_value})
55
+ node:
56
+ options:
57
+ parallel: |-
58
+ Enable parallelism of node action execution (default %{default_value})
59
+ net_provider: |-
60
+ Coral network provider to use for managing cloud nodes (default %{default_value})
61
+ node_provider: |-
62
+ Default to using a specific node provider but individual node references can override (default %{default_value})
63
+ nodes: |-
64
+ Optional nodes on which to execute this action
65
+ errors:
66
+ network_provider: |-
67
+ Network plugin provider %{value} is not loaded >> Pick from the following: %{choices}
68
+ node_provider: |-
69
+ Node plugin provider %{value} is not loaded >> Pick from the following: %{choices}
70
+ nodes: |-
71
+ Node reference %{value} failed to parse or provider %{provider} isn't loaded (%{name})
72
+ keypair:
73
+ options:
74
+ private_key: |-
75
+ Optional existing private SSH key to use for SSH communication (new keys are generated by default)
76
+ require_password: |-
77
+ Require and prompt for a password for generated keys (default %{default_value})
78
+ key_type: |-
79
+ Type of SSH key to generate (default %{default_value})
80
+ key_bits: |-
81
+ Strength of generated key encryption in bits (default %{default_value})
82
+ key_comment: |-
83
+ Optional key comment (attached at the end of the public key)
84
+ errors:
85
+ private_key_not_found: |-
86
+ Private key %{value} not found
87
+ private_key_parse_error: |-
88
+ Private key %{value} failed to parse and can not be accepted as a valid private SSH key
89
+ key_type: |-
90
+ SSH key type %{value} not supported >> Pick from the following: %{choices}
91
+ key_bits: |-
92
+ Encryption strength must be greater than %{required} bits (%{value} specified)
93
+ no_password: |-
94
+ Password verification of private key was terminated (verification required to use encrypted SSH keys)
95
+ exec:
96
+ help:
97
+ usage: |-
98
+ Usage
99
+ header: |-
100
+ Available actions
101
+ footer: |-
102
+ For help on any individual action run `coral <action> -h`
103
+ errors:
104
+ missing_argument: |-
105
+ Argument <%{name}> must be specified
106
+ actions:
107
+ extract:
108
+ options:
109
+ path: |-
110
+ Base path in which to extract the encoded data
111
+ encoded: |-
112
+ Encoded data to be extracted into the base path
113
+ errors:
114
+ path: |-
115
+ "Base path for extracted files must be an existing directory"
116
+ encoded: |-
117
+ "Data is either not properly encoded or is empty %{value}"
118
+ create:
119
+ options:
120
+ reference: |-
121
+ Git repository URL of Coral cloud to start project from (default %{default_value})
122
+ revision: |-
123
+ Revision or branch to initialize the project with (default %{default_value})
124
+ path: |-
125
+ Project path (default %{default_value})
126
+ start: |-
127
+ Creating a new Coral cloud at %{path} from %{reference}
128
+ add:
129
+ options:
130
+ sub_reference: |-
131
+ Repository URL of Coral component (module or library) to include in the project
132
+ sub_path: |-
133
+ Subproject path
134
+ editable: |-
135
+ Whether or not this sub project should be added as an editable remote (default %{default_value})
136
+ start: |-
137
+ Adding new subproject from %{sub_reference} at %{sub_path}
138
+ remove:
139
+ options:
140
+ sub_path: |-
141
+ Subproject path
142
+ start: |-
143
+ Removing existing subproject at %{sub_path}
144
+ update:
145
+ start: |-
146
+ Starting update run from provider %{project_provider} (ref: %{reference} rev: %{revision})
147
+ provision: |-
148
+ Running provisioning updates on %{node_name} from node provider %{node_provider}
149
+ save:
150
+ options:
151
+ files: |-
152
+ Optional space separated list of files to save
153
+ start: |-
154
+ Saving project changes with provider %{project_provider} (ref: %{reference} rev: %{revision})
155
+ images:
156
+ options:
157
+ match_case: |-
158
+ Match case on any search terms given when searching for images (default %{default_value})
159
+ require_all: |-
160
+ Require all search terms to be present in image descriptions to be included (default %{default_value})
161
+ provider: |-
162
+ Node provider to retrieve images for
163
+ search: |-
164
+ Optional array of search terms to filter image results
165
+ start: |-
166
+ Retrieving a list of defined images from %{node_provider}
167
+ results: |-
168
+ Total of %{images} images found
169
+ machines:
170
+ options:
171
+ node_provider: |-
172
+ Node provider to retrieve machine types
173
+ start: |-
174
+ Retrieving a list of available machines from %{node_provider}
175
+ results: |-
176
+ Total of %{machines} machine types found
177
+ spawn:
178
+ options:
179
+ parallel: |-
180
+ Enable or disable parallelism of node creation (default %{default_value})
181
+ seed: |-
182
+ Coral project reference with cloud project to seed new machines with (default %{default_value})
183
+ region: |-
184
+ Machine provider region in which to create the machines (defaults to first defined in provider)
185
+ machine_type: |-
186
+ Provider ID of machine type to create (defaults to first defined in provider - usually smallest)
187
+ provider: |-
188
+ Create machines with this node provider
189
+ image: |-
190
+ Provider ID of operating system image on which to initialize the new machines
191
+ hostnames: |-
192
+ Hostnames of machines to create on provider infrastructure
193
+ start: |-
194
+ Spawning new machines on %{provider}
195
+ bootstrap:
196
+ options:
197
+ bootstrap_path: |-
198
+ Bootstrap script top level local directory (default %{default_value})
199
+ bootstrap_init: |-
200
+ Gateway bootstrap script within the bootstrap project directory (default %{default_value})
201
+ bootstrap_glob: |-
202
+ Path glob to use in searching bootstrap scripts for remote execution (default %{default_value})
203
+ auth_files: |-
204
+ Any additional authorization or state files to pass to the node during bootstrap (relative to local home)
205
+ home_env_var: |-
206
+ Home directory environment variable on remote server (default %{default_value})
207
+ home: |-
208
+ Specified home directory on remote server (default %{default_value})
209
+ bootstrap_nodes: |-
210
+ Node references to bootstrap
211
+ errors:
212
+ bootstrap_path: |-
213
+ Bootstrap path must be an existing directory
214
+ auth_files: |-
215
+ Authorization file %{value} does not exist on the local system
216
+ bootstrap_nodes: |-
217
+ Provider %{node_provider} node %{name} is not a valid node to bootstrap (%{value} given)
218
+ start: |-
219
+ Starting bootstrap of machine %{hostname} (%{id})
220
+ success: |-
221
+ Machine %{hostname} (%{id}) successfully bootstrapped
222
+ exec:
223
+ options:
224
+ command: |-
225
+ Command line executable and arguments to execute on machine
226
+ seed:
227
+ options:
228
+ home: |-
229
+ Home directory in which to initialize the deploy SSH keys (default %default_value})
230
+ errors:
231
+ project_reference: |-
232
+ Project reference %{value} failed to parse or provider %{provider} isn't loaded >> Possible providers: %{choices}
data/nucleon.gemspec ADDED
@@ -0,0 +1,109 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "nucleon"
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Adrian Webb"]
12
+ s.date = "2014-02-19"
13
+ s.description = "Framework that provides a simple foundation for building distributively configured, extremely pluggable and extendable, and easily parallel Ruby applications"
14
+ s.email = "adrian.webb@coralnexus.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/nucleon.rb",
28
+ "locales/en.yml",
29
+ "nucleon.gemspec",
30
+ "spec/coral_mock_input.rb",
31
+ "spec/coral_test_kernel.rb",
32
+ "spec/spec_helper.rb"
33
+ ]
34
+ s.homepage = "http://github.com/coralnexus/nucleon"
35
+ s.licenses = ["GPLv3"]
36
+ s.rdoc_options = ["--title", "Nucleon", "--main", "README.rdoc", "--line-numbers"]
37
+ s.require_paths = ["lib"]
38
+ s.required_ruby_version = Gem::Requirement.new(">= 1.8.1")
39
+ s.rubyforge_project = "nucleon"
40
+ s.rubygems_version = "1.8.11"
41
+ s.summary = "Framework that provides a simple foundation for building distributively configured, extremely pluggable and extendable, and easily parallel Ruby applications"
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<log4r>, ["~> 1.1"])
48
+ s.add_runtime_dependency(%q<i18n>, ["~> 0.6"])
49
+ s.add_runtime_dependency(%q<deep_merge>, ["~> 1.0"])
50
+ s.add_runtime_dependency(%q<celluloid>, ["~> 0.15"])
51
+ s.add_runtime_dependency(%q<sshkey>, ["~> 1.6"])
52
+ s.add_runtime_dependency(%q<hiera>, ["~> 1.3"])
53
+ s.add_runtime_dependency(%q<multi_json>, ["~> 1.7"])
54
+ s.add_runtime_dependency(%q<grit>, ["~> 2.5"])
55
+ s.add_runtime_dependency(%q<octokit>, ["~> 2.7"])
56
+ s.add_runtime_dependency(%q<netrc>, ["~> 0.7"])
57
+ s.add_runtime_dependency(%q<fog>, ["~> 1.20"])
58
+ s.add_runtime_dependency(%q<rgen>, ["~> 0.6"])
59
+ s.add_runtime_dependency(%q<facter>, ["~> 1.7"])
60
+ s.add_runtime_dependency(%q<puppet>, ["~> 3.2"])
61
+ s.add_development_dependency(%q<bundler>, ["~> 1.2"])
62
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0"])
63
+ s.add_development_dependency(%q<rspec>, ["~> 2.10"])
64
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
65
+ s.add_development_dependency(%q<yard>, ["~> 0.8"])
66
+ else
67
+ s.add_dependency(%q<log4r>, ["~> 1.1"])
68
+ s.add_dependency(%q<i18n>, ["~> 0.6"])
69
+ s.add_dependency(%q<deep_merge>, ["~> 1.0"])
70
+ s.add_dependency(%q<celluloid>, ["~> 0.15"])
71
+ s.add_dependency(%q<sshkey>, ["~> 1.6"])
72
+ s.add_dependency(%q<hiera>, ["~> 1.3"])
73
+ s.add_dependency(%q<multi_json>, ["~> 1.7"])
74
+ s.add_dependency(%q<grit>, ["~> 2.5"])
75
+ s.add_dependency(%q<octokit>, ["~> 2.7"])
76
+ s.add_dependency(%q<netrc>, ["~> 0.7"])
77
+ s.add_dependency(%q<fog>, ["~> 1.20"])
78
+ s.add_dependency(%q<rgen>, ["~> 0.6"])
79
+ s.add_dependency(%q<facter>, ["~> 1.7"])
80
+ s.add_dependency(%q<puppet>, ["~> 3.2"])
81
+ s.add_dependency(%q<bundler>, ["~> 1.2"])
82
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
83
+ s.add_dependency(%q<rspec>, ["~> 2.10"])
84
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
85
+ s.add_dependency(%q<yard>, ["~> 0.8"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<log4r>, ["~> 1.1"])
89
+ s.add_dependency(%q<i18n>, ["~> 0.6"])
90
+ s.add_dependency(%q<deep_merge>, ["~> 1.0"])
91
+ s.add_dependency(%q<celluloid>, ["~> 0.15"])
92
+ s.add_dependency(%q<sshkey>, ["~> 1.6"])
93
+ s.add_dependency(%q<hiera>, ["~> 1.3"])
94
+ s.add_dependency(%q<multi_json>, ["~> 1.7"])
95
+ s.add_dependency(%q<grit>, ["~> 2.5"])
96
+ s.add_dependency(%q<octokit>, ["~> 2.7"])
97
+ s.add_dependency(%q<netrc>, ["~> 0.7"])
98
+ s.add_dependency(%q<fog>, ["~> 1.20"])
99
+ s.add_dependency(%q<rgen>, ["~> 0.6"])
100
+ s.add_dependency(%q<facter>, ["~> 1.7"])
101
+ s.add_dependency(%q<puppet>, ["~> 3.2"])
102
+ s.add_dependency(%q<bundler>, ["~> 1.2"])
103
+ s.add_dependency(%q<jeweler>, ["~> 2.0"])
104
+ s.add_dependency(%q<rspec>, ["~> 2.10"])
105
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
106
+ s.add_dependency(%q<yard>, ["~> 0.8"])
107
+ end
108
+ end
109
+
@@ -0,0 +1,29 @@
1
+
2
+ class MockInput
3
+
4
+ #-----------------------------------------------------------------------------
5
+ # Constructor / Destructor
6
+
7
+ def initialize(strings)
8
+ if strings.is_a?(String)
9
+ strings = [ strings ]
10
+ end
11
+ @strings = strings
12
+ end
13
+
14
+ #---
15
+
16
+ def self.with(strings)
17
+ $stdin = self.new(strings)
18
+ yield
19
+ ensure
20
+ $stdin = STDIN
21
+ end
22
+
23
+ #-----------------------------------------------------------------------------
24
+ # Accessors / Modifiers
25
+
26
+ def gets
27
+ return @strings.shift
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+
2
+ module Kernel
3
+
4
+ #-----------------------------------------------------------------------------
5
+ # Utilities
6
+
7
+ def capture
8
+ out = StringIO.new
9
+ $stdout = out
10
+
11
+ error = StringIO.new
12
+ $stderr = error
13
+
14
+ # Go do stuff!
15
+ yield
16
+ return out, error
17
+
18
+ ensure
19
+ $stdout = STDOUT
20
+ $stderr = STDERR
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+
2
+ require 'rspec'
3
+ require 'stringio'
4
+ require 'nucleon'
5
+
6
+ require 'coral_test_kernel'
7
+ require 'coral_mock_input'
8
+
9
+ #-------------------------------------------------------------------------------
10
+
11
+ RSpec.configure do |config|
12
+ config.mock_framework = :rspec
13
+ config.color_enabled = true
14
+ config.formatter = 'documentation'
15
+ end