orca 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +7 -3
- data/lib/orca/execution_context.rb +12 -1
- data/lib/orca/extensions/file_sync.rb +45 -34
- data/lib/orca/logger.rb +8 -0
- data/lib/orca/node.rb +30 -4
- data/lib/orca/package.rb +6 -1
- data/lib/orca/runner.rb +3 -2
- data/orca.gemspec +11 -1
- metadata +22 -37
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5fcffb2207cfa9357796ee92e79328b2268c1c14
|
4
|
+
data.tar.gz: ed2fb3ccc171ea17523d225e3ba18d19588a1d87
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1552c2835538232aaae979a6eddaa52e448958df9c1499d78016932b3ec05b6ebcd1d26528eef49c47e29de66e49fcd46fb365fc39ee787802b79062d6d7ef4d
|
7
|
+
data.tar.gz: b98462cfca875e9b585d989ccbf035eeb14b329e56846a6913e8f9380714b8178d4946f117be306932d83723aac31dbec426c6cc7f12433030767fa828ae5fa3
|
data/README.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
>### Deprecation Notice
|
2
|
+
>This project was an old experiment into alternative immutable sever provisioning methods. Things have since moved on and the introduction of contain based toolchains like Docker have made it's need obsolete.
|
3
|
+
>If you still require usage of the orca gem please lock your gem version to `0.4.0` as the `orca` name will shortly be handed over to another gem maintainer.
|
4
|
+
|
1
5
|
Orca
|
2
6
|
====
|
3
7
|
|
@@ -11,7 +15,7 @@ If you've found yourself stuck in the gap between deployment tools like Capistra
|
|
11
15
|
What problem does Orca try to solve?
|
12
16
|
------------------------------------
|
13
17
|
|
14
|
-
All too often you need to get a new server up and running to a known state so that you can get an app deployed. Before Orca there were
|
18
|
+
All too often you need to get a new server up and running to a known state so that you can get an app deployed. Before Orca there were broadly 4 options...
|
15
19
|
|
16
20
|
1. Start from scratch and hand install all the packages, files, permissions, etc. Yourself via trial and error over SSH.
|
17
21
|
2. Use a deployment tool like Capistrano to codeify your shell scripts into semi-reusable steps.
|
@@ -64,7 +68,7 @@ Command Line Usage
|
|
64
68
|
|
65
69
|
To get started from within your projct you can run...
|
66
70
|
|
67
|
-
orca init
|
71
|
+
orca init
|
68
72
|
|
69
73
|
This will create a config/orca.rb file for you to get started with.
|
70
74
|
|
@@ -92,7 +96,7 @@ You can also directly trigger actions from the CLI like so...
|
|
92
96
|
Options, all commands support the following optional parameters...
|
93
97
|
|
94
98
|
--demonstrate | dont actually run the commands on the server just pretend like you are
|
95
|
-
--sequential | dont attempt to run commands
|
99
|
+
--sequential | dont attempt to run commands across multiple nodes in parrallel
|
96
100
|
--throw | throw a stack trace rather than pretty printing errors
|
97
101
|
--file | path to the orca.rb file to load, defaults to ./orca/orca.rb
|
98
102
|
--verbose | print all SSH output, useful for debugging but can be rather long
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "open3"
|
2
2
|
|
3
3
|
class Orca::ExecutionContext
|
4
|
-
attr_reader :node
|
4
|
+
attr_reader :node, :log
|
5
5
|
|
6
6
|
def initialize(node, log)
|
7
7
|
@node = node
|
@@ -13,6 +13,17 @@ class Orca::ExecutionContext
|
|
13
13
|
instance_eval(&blk)
|
14
14
|
end
|
15
15
|
|
16
|
+
def as(user, &blk)
|
17
|
+
for_user(user).apply(blk)
|
18
|
+
end
|
19
|
+
|
20
|
+
def for_user(user)
|
21
|
+
return self if user.nil? || user == node.user
|
22
|
+
new_node = @node.for_user(user)
|
23
|
+
new_log = @log.clone_for_node(new_node)
|
24
|
+
self.class.new(new_node, new_log)
|
25
|
+
end
|
26
|
+
|
16
27
|
def run_local(cmd)
|
17
28
|
@log.local(cmd)
|
18
29
|
stdout, stderr, status = Open3.capture3(cmd)
|
@@ -11,51 +11,56 @@ class Orca::FileSync
|
|
11
11
|
@parent = parent
|
12
12
|
@config = config
|
13
13
|
@after_apply = blk
|
14
|
-
raise ArgumentError.new('A file :source or template must be provided') unless
|
15
|
-
raise ArgumentError.new('A file :destination must be provided') unless
|
14
|
+
raise ArgumentError.new('A file :source or template must be provided') unless @config[:source] or @config[:template]
|
15
|
+
raise ArgumentError.new('A file :destination must be provided') unless @config[:destination]
|
16
16
|
end
|
17
17
|
|
18
|
-
def local_path
|
19
|
-
@config[:source]
|
18
|
+
def local_path(context)
|
19
|
+
value_for context, @config[:source]
|
20
20
|
end
|
21
21
|
|
22
|
-
def template_path
|
23
|
-
@config[:template]
|
22
|
+
def template_path(context)
|
23
|
+
value_for context, @config[:template]
|
24
24
|
end
|
25
25
|
|
26
|
-
def local_path_for_node(
|
27
|
-
return local_path if
|
28
|
-
Orca::Template.new(node, template_path).render_to_tempfile
|
26
|
+
def local_path_for_node(context)
|
27
|
+
return local_path(context) if @config[:source]
|
28
|
+
Orca::Template.new(context.node, template_path(context)).render_to_tempfile
|
29
29
|
end
|
30
30
|
|
31
|
-
def remote_path
|
32
|
-
@config[:destination]
|
31
|
+
def remote_path(context)
|
32
|
+
value_for context, @config[:destination]
|
33
33
|
end
|
34
34
|
|
35
|
-
def permissions
|
36
|
-
@config[:permissions]
|
35
|
+
def permissions(context)
|
36
|
+
value_for context, @config[:permissions]
|
37
37
|
end
|
38
38
|
|
39
|
-
def user
|
40
|
-
@config[:user]
|
39
|
+
def user(context)
|
40
|
+
value_for context, @config[:user]
|
41
41
|
end
|
42
42
|
|
43
|
-
def group
|
44
|
-
@config[:group]
|
43
|
+
def group(context)
|
44
|
+
value_for context, @config[:group]
|
45
45
|
end
|
46
46
|
|
47
|
-
def create_dir
|
48
|
-
@config[:create_dir] || @config[:create_dirs]
|
47
|
+
def create_dir(context)
|
48
|
+
value_for context, (@config[:create_dir] || @config[:create_dirs])
|
49
49
|
end
|
50
50
|
|
51
51
|
def package_name(suffix)
|
52
|
-
|
52
|
+
name = @config[:name]
|
53
|
+
if name.nil? && !@config[:destination].is_a?(String)
|
54
|
+
raise ArgumentError.new("You must provide a :name option unless :destination is a String")
|
55
|
+
end
|
56
|
+
name ||= @config[:destination]
|
57
|
+
"file-#{suffix}[#{name}]"
|
53
58
|
end
|
54
59
|
|
55
60
|
def configure
|
56
61
|
fs = self
|
57
62
|
add_content_package
|
58
|
-
add_permissions_package unless permissions.nil? and user.nil? and group.nil?
|
63
|
+
add_permissions_package unless @config[:permissions].nil? and @config[:user].nil? and @config[:group].nil?
|
59
64
|
end
|
60
65
|
|
61
66
|
def run_after_apply(context)
|
@@ -66,24 +71,24 @@ class Orca::FileSync
|
|
66
71
|
fs = self
|
67
72
|
add_package('content') do |package|
|
68
73
|
package.command :apply do
|
69
|
-
if fs.create_dir
|
70
|
-
mk_dir = fs.create_dir == true ? File.dirname(fs.remote_path) : fs.create_dir
|
74
|
+
if fs.create_dir(self)
|
75
|
+
mk_dir = fs.create_dir(self) == true ? File.dirname(fs.remote_path(self)) : fs.create_dir(self)
|
71
76
|
sudo("mkdir -p #{mk_dir}")
|
72
|
-
sudo("chown #{fs.user}:#{fs.group || fs.user} #{mk_dir}") if fs.user
|
77
|
+
sudo("chown #{fs.user(self)}:#{fs.group(self) || fs.user(self)} #{mk_dir}") if fs.user(self)
|
73
78
|
end
|
74
|
-
local_file = local(fs.local_path_for_node(
|
79
|
+
local_file = local(fs.local_path_for_node(self))
|
75
80
|
tmp_path = "orca-upload-#{local_file.hash}"
|
76
81
|
local_file.copy_to(remote(tmp_path))
|
77
|
-
sudo("mv #{tmp_path} #{fs.remote_path}")
|
82
|
+
sudo("mv #{tmp_path} #{fs.remote_path(self)}")
|
78
83
|
fs.run_after_apply(self)
|
79
84
|
end
|
80
85
|
|
81
86
|
package.command :remove do
|
82
|
-
remote(fs.remote_path).delete!
|
87
|
+
remote(fs.remote_path(self)).delete!
|
83
88
|
end
|
84
89
|
|
85
90
|
package.command :validate do
|
86
|
-
local(fs.local_path_for_node(
|
91
|
+
local(fs.local_path_for_node(self)).matches?(remote(fs.remote_path(self)))
|
87
92
|
end
|
88
93
|
end
|
89
94
|
end
|
@@ -92,16 +97,16 @@ class Orca::FileSync
|
|
92
97
|
fs = self
|
93
98
|
add_package('permissions') do |package|
|
94
99
|
package.command :apply do
|
95
|
-
remote(fs.remote_path).set_owner(fs.user, fs.group) unless fs.user.nil? and fs.group.nil?
|
96
|
-
remote(fs.remote_path).set_permissions(fs.permissions) unless fs.permissions.nil?
|
100
|
+
remote(fs.remote_path(self)).set_owner(fs.user(self), fs.group(self)) unless fs.user(self).nil? and fs.group(self).nil?
|
101
|
+
remote(fs.remote_path(self)).set_permissions(fs.permissions(self)) unless fs.permissions(self).nil?
|
97
102
|
fs.run_after_apply(self)
|
98
103
|
end
|
99
104
|
|
100
105
|
package.command :validate do
|
101
|
-
r_file = remote(fs.remote_path)
|
102
|
-
valid = r_file.permissions == fs.permissions
|
103
|
-
valid = valid && r_file.user == fs.user if fs.user
|
104
|
-
valid = valid && r_file.group == fs.group if fs.group
|
106
|
+
r_file = remote(fs.remote_path(self))
|
107
|
+
valid = r_file.permissions == fs.permissions(self)
|
108
|
+
valid = valid && r_file.user == fs.user(self) if fs.user(self)
|
109
|
+
valid = valid && r_file.group == fs.group(self) if fs.group(self)
|
105
110
|
valid
|
106
111
|
end
|
107
112
|
end
|
@@ -113,4 +118,10 @@ class Orca::FileSync
|
|
113
118
|
@parent.triggers(package.name)
|
114
119
|
package
|
115
120
|
end
|
121
|
+
|
122
|
+
def value_for(context, option)
|
123
|
+
return nil if option.nil?
|
124
|
+
return context.instance_exec(&option) if option.respond_to?(:call)
|
125
|
+
option
|
126
|
+
end
|
116
127
|
end
|
data/lib/orca/logger.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
class Orca::Logger
|
2
|
+
attr_accessor :node
|
3
|
+
|
2
4
|
def initialize(node, package)
|
3
5
|
@node = node
|
4
6
|
set_package(package)
|
5
7
|
end
|
6
8
|
|
9
|
+
def clone_for_node(node)
|
10
|
+
copy = self.dup
|
11
|
+
copy.node = node
|
12
|
+
copy
|
13
|
+
end
|
14
|
+
|
7
15
|
def set_package(package)
|
8
16
|
@package = package.to_s
|
9
17
|
end
|
data/lib/orca/node.rb
CHANGED
@@ -2,7 +2,7 @@ require 'net/ssh'
|
|
2
2
|
require 'net/sftp'
|
3
3
|
|
4
4
|
class Orca::Node
|
5
|
-
attr_reader :name, :host
|
5
|
+
attr_reader :name, :host, :user
|
6
6
|
|
7
7
|
def self.find(name)
|
8
8
|
return name if name.is_a?(Orca::Node)
|
@@ -19,8 +19,10 @@ class Orca::Node
|
|
19
19
|
@name = name
|
20
20
|
@host = host
|
21
21
|
@options = options
|
22
|
+
@user = @options[:user] || 'root'
|
22
23
|
@connection = nil
|
23
24
|
@history = []
|
25
|
+
@user_nodes = {}
|
24
26
|
Orca::Node.register(self)
|
25
27
|
end
|
26
28
|
|
@@ -85,17 +87,35 @@ class Orca::Node
|
|
85
87
|
@log = log
|
86
88
|
end
|
87
89
|
|
90
|
+
def for_user(new_user)
|
91
|
+
new_user = new_user.to_s
|
92
|
+
return self if self.user == new_user
|
93
|
+
return @user_nodes[new_user] if @user_nodes[new_user]
|
94
|
+
new_node = self.dup
|
95
|
+
new_node.prepare_connection_for_user!(new_user)
|
96
|
+
@user_nodes[new_user] = new_node
|
97
|
+
new_node
|
98
|
+
end
|
99
|
+
|
100
|
+
def prepare_connection_for_user!(new_user)
|
101
|
+
@user = new_user
|
102
|
+
@connection = nil
|
103
|
+
@user_nodes = {}
|
104
|
+
@history = []
|
105
|
+
end
|
106
|
+
|
88
107
|
def connection
|
89
|
-
return @connection if @connection
|
90
|
-
@connection = Net::SSH.start(@host, (@
|
108
|
+
return @connection if @connection && !@connection.closed?
|
109
|
+
@connection = Net::SSH.start(@host, (@user), options_for_ssh)
|
91
110
|
end
|
92
111
|
|
93
112
|
def disconnect
|
94
113
|
@connection.close if @connection && !@connection.closed?
|
114
|
+
@user_nodes.values.each {|n| n.disconnect }
|
95
115
|
end
|
96
116
|
|
97
117
|
def to_s
|
98
|
-
"#{name}(#{host})"
|
118
|
+
"#{name}(#{user}@#{host})"
|
99
119
|
end
|
100
120
|
|
101
121
|
private
|
@@ -114,6 +134,7 @@ class Orca::Node
|
|
114
134
|
end
|
115
135
|
|
116
136
|
def really_execute(cmd, opts={})
|
137
|
+
cmd = prefixed_command(cmd)
|
117
138
|
log.execute(cmd.cyan)
|
118
139
|
output = ""
|
119
140
|
connection.exec! cmd do |channel, stream, data|
|
@@ -136,4 +157,9 @@ class Orca::Node
|
|
136
157
|
return nil unless results && results.size > 0
|
137
158
|
results.last[:output]
|
138
159
|
end
|
160
|
+
|
161
|
+
def prefixed_command(cmd)
|
162
|
+
return cmd unless @options[:prefix]
|
163
|
+
@options[:prefix] + cmd
|
164
|
+
end
|
139
165
|
end
|
data/lib/orca/package.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
class Orca::Package
|
2
|
-
attr_reader :name, :dependancies, :actions, :children
|
2
|
+
attr_reader :name, :dependancies, :actions, :children, :user
|
3
3
|
|
4
4
|
def initialize(name)
|
5
5
|
@name = name
|
6
|
+
@user = nil
|
6
7
|
@dependancies = []
|
7
8
|
@children = []
|
8
9
|
@actions = {}
|
@@ -34,6 +35,10 @@ class Orca::Package
|
|
34
35
|
command(:remove, &definition)
|
35
36
|
end
|
36
37
|
|
38
|
+
def as(user)
|
39
|
+
@user = user
|
40
|
+
end
|
41
|
+
|
37
42
|
def action(name, &definition)
|
38
43
|
@actions[name] = definition
|
39
44
|
end
|
data/lib/orca/runner.rb
CHANGED
@@ -67,10 +67,11 @@ class Orca::Runner
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def exec(pkg, command_name)
|
70
|
-
@log.set_package(pkg)
|
71
|
-
@log.command(command_name)
|
72
70
|
context = @perform ? Orca::ExecutionContext.new(@node, @log) : Orca::MockExecutionContext.new(@node, @log)
|
73
71
|
cmds = pkg.command(command_name)
|
72
|
+
context = context.for_user(pkg.user) if pkg.user
|
73
|
+
context.log.set_package(pkg)
|
74
|
+
context.log.command(command_name)
|
74
75
|
cmds.map {|cmd| context.apply(cmd) }
|
75
76
|
end
|
76
77
|
|
data/orca.gemspec
CHANGED
@@ -10,10 +10,20 @@ Gem::Specification.new do |gem|
|
|
10
10
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
11
11
|
gem.name = "orca"
|
12
12
|
gem.require_paths = ["lib"]
|
13
|
-
gem.version = '0.4.
|
13
|
+
gem.version = '0.4.1'
|
14
14
|
gem.add_dependency('colored')
|
15
15
|
gem.add_dependency('net-ssh')
|
16
16
|
gem.add_dependency('net-sftp')
|
17
17
|
gem.add_dependency('thor')
|
18
18
|
gem.add_dependency('tilt')
|
19
|
+
gem.post_install_message = %Q[
|
20
|
+
===================================
|
21
|
+
The `orca` gem has been deprecated!
|
22
|
+
-----------------------------------
|
23
|
+
This gem name is likely to be used
|
24
|
+
for other purposes, you should lock
|
25
|
+
your gemfile to version 0.4.0 for
|
26
|
+
continued usage of this gem.
|
27
|
+
===================================
|
28
|
+
]
|
19
29
|
end
|
metadata
CHANGED
@@ -1,94 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: orca
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Andy Kent
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-12-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: colored
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: net-ssh
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: net-sftp
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: thor
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - ">="
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - ">="
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: tilt
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - ">="
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - ">="
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
description: Orca is a super simple way to build and configure servers
|
@@ -99,7 +88,7 @@ executables:
|
|
99
88
|
extensions: []
|
100
89
|
extra_rdoc_files: []
|
101
90
|
files:
|
102
|
-
- .gitignore
|
91
|
+
- ".gitignore"
|
103
92
|
- Gemfile
|
104
93
|
- Gemfile.lock
|
105
94
|
- LICENSE
|
@@ -138,33 +127,29 @@ files:
|
|
138
127
|
- test/test_helper.rb
|
139
128
|
homepage: ''
|
140
129
|
licenses: []
|
141
|
-
|
130
|
+
metadata: {}
|
131
|
+
post_install_message: "\n===================================\nThe `orca` gem has been
|
132
|
+
deprecated!\n-----------------------------------\nThis gem name is likely to be
|
133
|
+
used\nfor other purposes, you should lock\nyour gemfile to version 0.4.0 for\ncontinued
|
134
|
+
usage of this gem.\n===================================\n "
|
142
135
|
rdoc_options: []
|
143
136
|
require_paths:
|
144
137
|
- lib
|
145
138
|
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
-
none: false
|
147
139
|
requirements:
|
148
|
-
- -
|
140
|
+
- - ">="
|
149
141
|
- !ruby/object:Gem::Version
|
150
142
|
version: '0'
|
151
|
-
segments:
|
152
|
-
- 0
|
153
|
-
hash: -951848962071421734
|
154
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
-
none: false
|
156
144
|
requirements:
|
157
|
-
- -
|
145
|
+
- - ">="
|
158
146
|
- !ruby/object:Gem::Version
|
159
147
|
version: '0'
|
160
|
-
segments:
|
161
|
-
- 0
|
162
|
-
hash: -951848962071421734
|
163
148
|
requirements: []
|
164
149
|
rubyforge_project:
|
165
|
-
rubygems_version:
|
150
|
+
rubygems_version: 2.4.5.1
|
166
151
|
signing_key:
|
167
|
-
specification_version:
|
152
|
+
specification_version: 4
|
168
153
|
summary: Simplified Machine Building
|
169
154
|
test_files:
|
170
155
|
- test/dsl_test.rb
|