linecook 0.6.2 → 1.0.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/History +139 -0
- data/HowTo/Control Virtual Machines +106 -0
- data/HowTo/Generate Scripts +263 -0
- data/HowTo/Run Scripts +87 -0
- data/HowTo/Setup Virtual Machines +76 -0
- data/License.txt +1 -1
- data/README +78 -59
- data/bin/linecook +12 -5
- data/bin/linecook_run +45 -0
- data/bin/linecook_scp +50 -0
- data/lib/linecook.rb +1 -3
- data/lib/linecook/attributes.rb +49 -12
- data/lib/linecook/commands.rb +9 -4
- data/lib/linecook/commands/build.rb +69 -0
- data/lib/linecook/commands/command.rb +13 -3
- data/lib/linecook/commands/command_error.rb +6 -0
- data/lib/linecook/commands/env.rb +74 -8
- data/lib/linecook/commands/helper.rb +271 -24
- data/lib/linecook/commands/init.rb +10 -6
- data/lib/linecook/commands/package.rb +36 -18
- data/lib/linecook/commands/run.rb +66 -0
- data/lib/linecook/commands/snapshot.rb +114 -0
- data/lib/linecook/commands/ssh.rb +39 -0
- data/lib/linecook/commands/start.rb +34 -0
- data/lib/linecook/commands/state.rb +32 -0
- data/lib/linecook/commands/stop.rb +22 -0
- data/lib/linecook/commands/vbox_command.rb +130 -0
- data/lib/linecook/cookbook.rb +112 -55
- data/lib/linecook/package.rb +293 -109
- data/lib/linecook/proxy.rb +19 -0
- data/lib/linecook/recipe.rb +321 -62
- data/lib/linecook/template.rb +7 -101
- data/lib/linecook/test.rb +196 -141
- data/lib/linecook/test/command_parser.rb +75 -0
- data/lib/linecook/test/file_test.rb +153 -35
- data/lib/linecook/test/shell_test.rb +176 -0
- data/lib/linecook/utils.rb +25 -7
- data/lib/linecook/version.rb +4 -4
- data/templates/Rakefile +44 -47
- data/templates/_gitignore +1 -1
- data/templates/attributes/project_name.rb +4 -4
- data/templates/config/ssh +15 -0
- data/templates/files/help.txt +1 -0
- data/templates/helpers/project_name/assert_content_equal.erb +15 -0
- data/templates/helpers/project_name/create_dir.erb +9 -0
- data/templates/helpers/project_name/create_file.erb +8 -0
- data/templates/helpers/project_name/install_file.erb +8 -0
- data/templates/packages/abox.yml +4 -0
- data/templates/recipes/abox.rb +22 -0
- data/templates/recipes/abox_test.rb +14 -0
- data/templates/templates/todo.txt.erb +3 -0
- data/templates/test/project_name_test.rb +19 -0
- data/templates/test/test_helper.rb +14 -0
- metadata +43 -41
- data/cookbook +0 -0
- data/lib/linecook/commands/helpers.rb +0 -28
- data/lib/linecook/commands/vbox.rb +0 -85
- data/lib/linecook/helper.rb +0 -117
- data/lib/linecook/shell.rb +0 -11
- data/lib/linecook/shell/posix.rb +0 -145
- data/lib/linecook/shell/test.rb +0 -254
- data/lib/linecook/shell/unix.rb +0 -117
- data/lib/linecook/shell/utils.rb +0 -138
- data/templates/README +0 -90
- data/templates/files/file.txt +0 -1
- data/templates/helpers/project_name/echo.erb +0 -5
- data/templates/recipes/project_name.rb +0 -20
- data/templates/scripts/project_name.yml +0 -7
- data/templates/templates/template.txt.erb +0 -3
- data/templates/vbox/setup/virtual_box +0 -86
- data/templates/vbox/ssh/id_rsa +0 -27
- data/templates/vbox/ssh/id_rsa.pub +0 -1
@@ -0,0 +1,176 @@
|
|
1
|
+
require 'linecook/test/regexp_escape'
|
2
|
+
require 'linecook/test/command_parser'
|
3
|
+
|
4
|
+
module Linecook
|
5
|
+
module Test
|
6
|
+
module ShellTest
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
@notify_method_name = true
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns true if the ENV variable 'VERBOSE' is true. When verbose,
|
14
|
+
# ShellTest prints the expanded commands of sh_test to $stdout.
|
15
|
+
def verbose?
|
16
|
+
verbose = ENV['VERBOSE']
|
17
|
+
verbose && verbose =~ /^true$/i ? true : false
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sets the specified ENV variables and returns the *current* env.
|
21
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
22
|
+
# the new env variables are simply added to the existing set.
|
23
|
+
def set_env(env={}, replace=false)
|
24
|
+
current_env = {}
|
25
|
+
ENV.each_pair do |key, value|
|
26
|
+
current_env[key] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
ENV.clear if replace
|
30
|
+
|
31
|
+
env.each_pair do |key, value|
|
32
|
+
if value.nil?
|
33
|
+
ENV.delete(key)
|
34
|
+
else
|
35
|
+
ENV[key] = value
|
36
|
+
end
|
37
|
+
end if env
|
38
|
+
|
39
|
+
current_env
|
40
|
+
end
|
41
|
+
|
42
|
+
# Sets the specified ENV variables for the duration of the block.
|
43
|
+
# If replace is true, current ENV variables are replaced; otherwise
|
44
|
+
# the new env variables are simply added to the existing set.
|
45
|
+
#
|
46
|
+
# Returns the block return.
|
47
|
+
def with_env(env={}, replace=false)
|
48
|
+
current_env = nil
|
49
|
+
begin
|
50
|
+
current_env = set_env(env, replace)
|
51
|
+
yield
|
52
|
+
ensure
|
53
|
+
if current_env
|
54
|
+
set_env(current_env, true)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def sh(cmd)
|
60
|
+
if @notify_method_name && verbose?
|
61
|
+
@notify_method_name = false
|
62
|
+
puts
|
63
|
+
puts method_name
|
64
|
+
end
|
65
|
+
|
66
|
+
start = Time.now
|
67
|
+
result = `#{cmd}`
|
68
|
+
finish = Time.now
|
69
|
+
|
70
|
+
if verbose?
|
71
|
+
elapsed = "%.3f" % [finish-start]
|
72
|
+
puts " (#{elapsed}s) #{cmd}"
|
73
|
+
end
|
74
|
+
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
def assert_script(script, options={})
|
79
|
+
_assert_script outdent(script), options
|
80
|
+
end
|
81
|
+
|
82
|
+
def _assert_script(script, options={})
|
83
|
+
commands = CommandParser.new(options).parse(script)
|
84
|
+
commands.each do |cmd, output, status|
|
85
|
+
result = sh(cmd)
|
86
|
+
|
87
|
+
_assert_output_equal(output, result, cmd) if output
|
88
|
+
assert_equal(status, $?.exitstatus, cmd) if status
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_script_match(script, options={})
|
93
|
+
_assert_script_match outdent(script), options
|
94
|
+
end
|
95
|
+
|
96
|
+
def _assert_script_match(script, options={})
|
97
|
+
commands = CommandParser.new(options).parse(script)
|
98
|
+
commands.each do |cmd, output, status|
|
99
|
+
result = sh(cmd)
|
100
|
+
|
101
|
+
_assert_alike(output, result, cmd) if output
|
102
|
+
assert_equal(status, $?.exitstatus, cmd) if status
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Asserts whether or not the a and b strings are equal, with a more
|
107
|
+
# readable output than assert_equal for large strings (especially large
|
108
|
+
# strings with significant whitespace).
|
109
|
+
def assert_output_equal(a, b, msg=nil)
|
110
|
+
_assert_output_equal outdent(a), b, msg
|
111
|
+
end
|
112
|
+
|
113
|
+
def _assert_output_equal(a, b, msg=nil)
|
114
|
+
if a == b
|
115
|
+
assert true
|
116
|
+
else
|
117
|
+
flunk %Q{
|
118
|
+
#{msg}
|
119
|
+
==================== expected output ====================
|
120
|
+
#{whitespace_escape(a)}
|
121
|
+
======================== but was ========================
|
122
|
+
#{whitespace_escape(b)}
|
123
|
+
=========================================================
|
124
|
+
}
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Asserts whether or not b is like a (which should be a Regexp), and
|
129
|
+
# provides a more readable output in the case of a failure as compared
|
130
|
+
# with assert_match.
|
131
|
+
#
|
132
|
+
# If a is a string it is turned into a RegexpEscape.
|
133
|
+
def assert_alike(a, b, msg=nil)
|
134
|
+
a = outdent(a) if a.kind_of?(String)
|
135
|
+
_assert_alike a, b, msg
|
136
|
+
end
|
137
|
+
|
138
|
+
def _assert_alike(a, b, msg=nil)
|
139
|
+
if a.kind_of?(String)
|
140
|
+
a = RegexpEscape.new(a)
|
141
|
+
end
|
142
|
+
|
143
|
+
if b =~ a
|
144
|
+
assert true
|
145
|
+
else
|
146
|
+
flunk %Q{
|
147
|
+
#{msg}
|
148
|
+
================= expected output like ==================
|
149
|
+
#{whitespace_escape(a)}
|
150
|
+
======================== but was ========================
|
151
|
+
#{whitespace_escape(b)}
|
152
|
+
=========================================================
|
153
|
+
}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# helper for stripping indentation off a string
|
158
|
+
def outdent(str)
|
159
|
+
str =~ /\A(?:\s*?\n)( *)(.*)\z/m ? $2.gsub!(/^ {0,#{$1.length}}/, '') : str
|
160
|
+
end
|
161
|
+
|
162
|
+
# helper for formatting escaping whitespace into readable text
|
163
|
+
def whitespace_escape(str)
|
164
|
+
str.to_s.gsub(/\s/) do |match|
|
165
|
+
case match
|
166
|
+
when "\n" then "\\n\n"
|
167
|
+
when "\t" then "\\t"
|
168
|
+
when "\r" then "\\r"
|
169
|
+
when "\f" then "\\f"
|
170
|
+
else match
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
data/lib/linecook/utils.rb
CHANGED
@@ -1,17 +1,35 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
1
3
|
module Linecook
|
2
4
|
module Utils
|
3
5
|
module_function
|
4
6
|
|
5
|
-
def
|
6
|
-
|
7
|
+
def load_config(path)
|
8
|
+
(path ? YAML.load_file(path) : nil) || {}
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def arrayify(obj)
|
12
|
+
case obj
|
13
|
+
when nil then []
|
14
|
+
when String then obj.split(':')
|
15
|
+
else obj
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def hashify(obj)
|
20
|
+
case obj
|
21
|
+
when Hash then obj
|
22
|
+
when nil then {}
|
23
|
+
when Array
|
24
|
+
hash = {}
|
25
|
+
obj.each {|entry| hash[entry] = entry }
|
26
|
+
hash
|
27
|
+
|
28
|
+
when String
|
29
|
+
hashify obj.split(':')
|
30
|
+
|
31
|
+
else nil
|
13
32
|
end
|
14
|
-
attrs
|
15
33
|
end
|
16
34
|
|
17
35
|
def deep_merge(a, b)
|
data/lib/linecook/version.rb
CHANGED
data/templates/Rakefile
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
2
4
|
|
3
5
|
#
|
4
6
|
# Gem tasks
|
5
7
|
#
|
6
8
|
|
7
|
-
require 'rake/rdoctask'
|
8
|
-
require 'rake/gempackagetask'
|
9
|
-
|
10
9
|
def gemspec
|
11
|
-
@gemspec ||=
|
10
|
+
@gemspec ||= begin
|
11
|
+
gemspec_path = File.expand_path('../<%= project_name %>.gemspec', __FILE__)
|
12
|
+
eval(File.read(gemspec_path), TOPLEVEL_BINDING)
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
Rake::GemPackageTask.new(gemspec) do |pkg|
|
@@ -72,56 +74,40 @@ end
|
|
72
74
|
# Linecook Helpers
|
73
75
|
#
|
74
76
|
|
75
|
-
|
76
|
-
|
77
|
+
package = ENV['PACKAGE']
|
78
|
+
force = (ENV['FORCE'] == 'true')
|
77
79
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
Dir.glob("#{helpers_dir}/**/*").each do |source|
|
82
|
-
next if File.directory?(source)
|
83
|
-
(sources[File.dirname(source)] ||= []) << source
|
80
|
+
desc "build helpers and packages"
|
81
|
+
task :build => :bundle do
|
82
|
+
sh "bundle exec linecook build #{force ? '--force ' : nil}#{package}"
|
84
83
|
end
|
85
84
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
file target => sources + [dir] do
|
91
|
-
system "bundle exec linecook helper '#{name}' --force"
|
92
|
-
end
|
93
|
-
|
94
|
-
helpers << target
|
85
|
+
desc "run packages"
|
86
|
+
task :run => :build do
|
87
|
+
sh "bundle exec linecook run #{package}"
|
95
88
|
end
|
96
89
|
|
97
|
-
desc "
|
98
|
-
task :
|
99
|
-
|
100
|
-
|
101
|
-
# Linecook Scripts
|
102
|
-
#
|
90
|
+
desc "start each vm at CURRENT"
|
91
|
+
task :start => :bundle do
|
92
|
+
sh 'bundle exec linecook start --socket --snapshot CURRENT'
|
93
|
+
end
|
103
94
|
|
104
|
-
|
105
|
-
|
95
|
+
desc "snapshot each vm to a new CURRENT"
|
96
|
+
task :snapshot => :bundle do
|
97
|
+
sh 'bundle exec linecook snapshot CURRENT'
|
98
|
+
end
|
106
99
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
file target => dependencies + [source] + helpers do
|
113
|
-
sh "bundle exec linecook package '#{source}' '#{target}' --force"
|
114
|
-
end
|
115
|
-
|
116
|
-
desc "generate the script: #{name}"
|
117
|
-
task name => target
|
118
|
-
end
|
119
|
-
|
120
|
-
task :scripts => target
|
100
|
+
desc "reset each vm to BASE"
|
101
|
+
task :reset_base => :bundle do
|
102
|
+
sh 'bundle exec linecook snapshot --reset BASE'
|
103
|
+
sh 'bundle exec linecook snapshot CURRENT'
|
104
|
+
sh 'bundle exec linecook start --socket --snapshot CURRENT'
|
121
105
|
end
|
122
106
|
|
123
|
-
desc "
|
124
|
-
task :
|
107
|
+
desc "stop each vm"
|
108
|
+
task :stop => :bundle do
|
109
|
+
sh 'bundle exec linecook stop'
|
110
|
+
end
|
125
111
|
|
126
112
|
#
|
127
113
|
# Test tasks
|
@@ -130,9 +116,10 @@ task :scripts
|
|
130
116
|
desc 'Default: Run tests.'
|
131
117
|
task :default => :test
|
132
118
|
|
133
|
-
desc 'Run the tests'
|
134
|
-
task :
|
119
|
+
desc 'Run the tests assuming each vm is setup'
|
120
|
+
task :quicktest => :build do
|
135
121
|
tests = Dir.glob('test/**/*_test.rb')
|
122
|
+
tests.delete_if {|test| test =~ /_test\/test_/ }
|
136
123
|
|
137
124
|
if ENV['RCOV'] == 'true'
|
138
125
|
FileUtils.rm_rf File.expand_path('../coverage', __FILE__)
|
@@ -142,6 +129,16 @@ task :test => :helpers do
|
|
142
129
|
end
|
143
130
|
end
|
144
131
|
|
132
|
+
desc 'Run the tests'
|
133
|
+
task :test do
|
134
|
+
begin
|
135
|
+
Rake::Task["start"].invoke
|
136
|
+
Rake::Task["quicktest"].invoke
|
137
|
+
ensure
|
138
|
+
Rake::Task["stop"].execute(nil)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
145
142
|
desc 'Run rcov'
|
146
143
|
task :rcov do
|
147
144
|
ENV['RCOV'] = 'true'
|
data/templates/_gitignore
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Define default recipe attributes here
|
2
|
-
#
|
3
|
-
attrs['<%= project_name %>']['
|
4
|
-
attrs['<%= project_name %>']['
|
1
|
+
# Define default recipe attributes here.
|
2
|
+
# (note string keys are usually better than symbols)
|
3
|
+
attrs['<%= project_name %>']['year'] = Time.now.year
|
4
|
+
attrs['<%= project_name %>']['resolutions'] = []
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Declare hosts for packages - the vm name can be specified in a special
|
2
|
+
# comment following the Host declaration (defaults to the host).
|
3
|
+
Host abox # [abox]
|
4
|
+
Port 2220
|
5
|
+
|
6
|
+
# Define global configs here. By default tests run vs this default host.
|
7
|
+
Host *
|
8
|
+
HostName localhost
|
9
|
+
User linecook
|
10
|
+
Port 2220
|
11
|
+
UserKnownHostsFile /dev/null
|
12
|
+
StrictHostKeyChecking no
|
13
|
+
IdentitiesOnly yes
|
14
|
+
ControlMaster auto
|
15
|
+
ControlPath /tmp/socket-%r@%h:%p
|
@@ -0,0 +1 @@
|
|
1
|
+
* https://github.com/pinnacol/linecook
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Asserts the content of the file is as expected. Prints a diff and exits 1 if
|
2
|
+
the content is not as expected.
|
3
|
+
(expected, file)
|
4
|
+
--
|
5
|
+
expected='<%= '<' %>%= expected.rstrip %<%= '>' %>'
|
6
|
+
actual=$(cat <%= '<' %>%= file %<%= '>' %>)
|
7
|
+
|
8
|
+
echo "Check file: <%= '<' %>%= file %<%= '>' %>"
|
9
|
+
if [ "$actual" != "$expected" ]
|
10
|
+
then
|
11
|
+
echo "[$0] unequal output: <%= '<' %>%= file %<%= '>' %>" >&2
|
12
|
+
diff <(cat <<< "$expected") <(cat <<< "$actual") >&2
|
13
|
+
exit 1
|
14
|
+
fi
|
15
|
+
|