pleaserun 0.0.3 → 0.0.4
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 +7 -0
- data/.rubocop.yml +49 -0
- data/CHANGELOG.asciidoc +8 -0
- data/LICENSE +13 -0
- data/lib/pleaserun/cli.rb +27 -21
- data/lib/pleaserun/configurable.rb +47 -16
- data/lib/pleaserun/detector.rb +33 -17
- data/lib/pleaserun/mustache_methods.rb +1 -0
- data/lib/pleaserun/namespace.rb +2 -0
- data/lib/pleaserun/platform/base.rb +10 -2
- data/lib/pleaserun/platform/launchd.rb +6 -4
- data/lib/pleaserun/platform/runit.rb +5 -2
- data/lib/pleaserun/platform/systemd.rb +6 -5
- data/lib/pleaserun/platform/sysv.rb +5 -3
- data/lib/pleaserun/platform/upstart.rb +5 -3
- data/pleaserun.gemspec +1 -1
- data/spec/pleaserun/configurable_spec.rb +8 -4
- data/spec/pleaserun/mustache_methods_spec.rb +2 -1
- data/spec/pleaserun/platform/launchd_spec.rb +14 -13
- data/spec/pleaserun/platform/systemd_spec.rb +1 -6
- data/spec/pleaserun/platform/sysv_spec.rb +1 -3
- data/spec/pleaserun/platform/upstart_spec.rb +1 -6
- data/spec/testenv.rb +14 -8
- data/test/test.rb +26 -7
- metadata +22 -35
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9ed4accac8b94375fd217a37c253a3e2b71dc9d6
|
4
|
+
data.tar.gz: 1ded3b7e8379b7c58cf3c26e237122c7e6b8853e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ecab9e1a4f3b9c1822c51fb22ec65c23bd829094d92db453fb12fa9c578a96a25952a1d483a1ec101566e0d4013de7a0a9687cff521e1857750d03bafee2bc5d
|
7
|
+
data.tar.gz: 7937ec96541fb798bf3f887ce543df6f2d99b0f06ea395a3b84566644a668706f9ceaf70d5cd04eadc16c2d6ab7e310d083fd362435a69f77f6bb2f80044a710
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# Let's not argue over this...
|
2
|
+
StringLiterals:
|
3
|
+
Enabled: false
|
4
|
+
|
5
|
+
# I can't find a reason for raise vs fail.
|
6
|
+
SignalException:
|
7
|
+
Enabled: false
|
8
|
+
|
9
|
+
# I can't find a reason to prefer 'map' when 'collect' is what I mean.
|
10
|
+
# I'm collecting things from a list. Maybe someone can help me understand the
|
11
|
+
# semantics here.
|
12
|
+
CollectionMethods:
|
13
|
+
Enabled: false
|
14
|
+
|
15
|
+
# Why do you even *SEE* trailing whitespace? Because your editor was
|
16
|
+
# misconfigured to highlight trailing whitespace, right? Maybe turn that off?
|
17
|
+
# ;)
|
18
|
+
TrailingWhitespace:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
# Line length is another weird problem that somehow in the past 40 years of
|
22
|
+
# computing we don't seem to have solved. It's a display problem :(
|
23
|
+
LineLength:
|
24
|
+
Max: 9000
|
25
|
+
|
26
|
+
# %w() vs [ "x", "y", ... ]
|
27
|
+
# The complaint is on lib/pleaserun/detector.rb's map of OS=>Runner,
|
28
|
+
# i'll ignore it.
|
29
|
+
WordArray:
|
30
|
+
MinSize: 5
|
31
|
+
|
32
|
+
# A 20-line method isn't too bad.
|
33
|
+
MethodLength:
|
34
|
+
Max: 20
|
35
|
+
|
36
|
+
# Hash rockets (=>) forever. Why? Not all of my hash keys are static symbols.
|
37
|
+
HashSyntax:
|
38
|
+
EnforcedStyle: hash_rockets
|
39
|
+
|
40
|
+
# I prefer explicit return. It makes it clear in the code that the
|
41
|
+
# code author intended to return a value from a method.
|
42
|
+
RedundantReturn:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
# My view on a readable case statement seems to disagree with
|
46
|
+
# what rubocop wants and it doesn't let me configure it other than
|
47
|
+
# enable/disable.
|
48
|
+
CaseIndentation:
|
49
|
+
Enabled: false
|
data/CHANGELOG.asciidoc
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014 Jordan Sissel contributors.
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/lib/pleaserun/cli.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "English" # for $CHILD_STATUS
|
1
2
|
require "pleaserun/namespace"
|
2
3
|
require "clamp"
|
3
4
|
require "cabin"
|
@@ -5,7 +6,10 @@ require "stud/temporary"
|
|
5
6
|
|
6
7
|
require "pleaserun/platform/base"
|
7
8
|
|
8
|
-
|
9
|
+
# The CLI interface to pleaserun.
|
10
|
+
#
|
11
|
+
# This is invoked by `bin/pleaserun`.
|
12
|
+
class PleaseRun::CLI < Clamp::Command # rubocop:disable ClassLength
|
9
13
|
class Error < StandardError; end
|
10
14
|
class ConfigurationError < Error; end
|
11
15
|
class PlatformLoadError < Error; end
|
@@ -13,7 +17,7 @@ class PleaseRun::CLI < Clamp::Command
|
|
13
17
|
|
14
18
|
option ["-p", "--platform"], "PLATFORM", "The name of the platform to target, such as sysv, upstart, etc"
|
15
19
|
option ["-v", "--version"], "VERSION", "The version of the platform to target, such as 'lsb-3.1' for sysv or '1.5' for upstart",
|
16
|
-
|
20
|
+
:default => "default", :attribute_name => :target_version
|
17
21
|
|
18
22
|
option "--log", "LOGFILE", "The path to use for writing pleaserun logs."
|
19
23
|
option "--json", :flag, "Output a result in JSON. Intended to be consumed by other programs. This will emit the file contents and install actions as a JSON object."
|
@@ -24,20 +28,25 @@ class PleaseRun::CLI < Clamp::Command
|
|
24
28
|
option "--debug", :flag, "Debug-level logging"
|
25
29
|
option "--quiet", :flag, "Only errors or worse will be logged"
|
26
30
|
|
27
|
-
|
31
|
+
# TODO(sissel): Make options based on other platforms
|
32
|
+
|
33
|
+
# Make program and args attributes into parameters
|
34
|
+
base = PleaseRun::Platform::Base
|
35
|
+
|
36
|
+
# Get the Base platform's attributes and make them available as flags
|
37
|
+
# through clamp.
|
38
|
+
#
|
39
|
+
# This has the effect of any 'attribute :foo, ...' becoming 'option "--foo",
|
40
|
+
# ...' in the CLI.
|
41
|
+
base.attributes.each do |facet|
|
28
42
|
# Skip program and args which we don't want to make into flags.
|
29
43
|
next if [:program, :args, :target_version].include?(facet.name)
|
30
44
|
|
31
45
|
# Turn the attribute name into a flag.
|
32
46
|
option "--#{facet.name}", facet.name.to_s.upcase, facet.description,
|
33
|
-
|
47
|
+
:attribute_name => facet.name
|
34
48
|
end
|
35
49
|
|
36
|
-
# TODO(sissel): Make options based on other platforms
|
37
|
-
|
38
|
-
# Make program and args attributes into parameters
|
39
|
-
base = PleaseRun::Platform::Base
|
40
|
-
|
41
50
|
# Load the 'program' attribute from the Base class and use it as the first
|
42
51
|
# cli parameter.
|
43
52
|
program = base.attributes.find { |f| f.name == :program }
|
@@ -51,7 +60,7 @@ class PleaseRun::CLI < Clamp::Command
|
|
51
60
|
|
52
61
|
parameter "[ARGS] ...", args.description, :attribute_name => args.name
|
53
62
|
|
54
|
-
def help
|
63
|
+
def help # rubocop:disable MethodLength
|
55
64
|
return <<-HELP
|
56
65
|
Welcome to pleaserun!
|
57
66
|
|
@@ -90,6 +99,7 @@ are made. If it fails, nagios will not start. Yay!
|
|
90
99
|
|
91
100
|
#{super}
|
92
101
|
HELP
|
102
|
+
# rubocop:enable MethodLength
|
93
103
|
end
|
94
104
|
|
95
105
|
def execute
|
@@ -104,7 +114,7 @@ are made. If it fails, nagios will not start. Yay!
|
|
104
114
|
|
105
115
|
if name.nil?
|
106
116
|
self.name = File.basename(program)
|
107
|
-
@logger.warn("No name given, setting reasonable default", :name =>
|
117
|
+
@logger.warn("No name given, setting reasonable default", :name => name)
|
108
118
|
end
|
109
119
|
|
110
120
|
# Load the platform implementation
|
@@ -158,15 +168,14 @@ are made. If it fails, nagios will not start. Yay!
|
|
158
168
|
errors = []
|
159
169
|
|
160
170
|
runner.files.each do |path, content, perms|
|
161
|
-
#
|
171
|
+
# TODO(sissel): Force-set default file permissions if not provided?
|
172
|
+
# perms ||= (0666 ^ File.umask)
|
162
173
|
fullpath = install? ? path : File.join(tmp, path)
|
163
174
|
success = write(fullpath, content, perms)
|
164
175
|
errors << fullpath unless success
|
165
176
|
end
|
166
177
|
|
167
|
-
if errors.any?
|
168
|
-
raise FileWritingFailure, "Errors occurred while writing files"
|
169
|
-
end
|
178
|
+
raise FileWritingFailure, "Errors occurred while writing files" if errors.any?
|
170
179
|
|
171
180
|
# TODO(sissel): Refactor this to be less lines of code or put into methods.
|
172
181
|
if runner.install_actions.any?
|
@@ -174,9 +183,7 @@ are made. If it fails, nagios will not start. Yay!
|
|
174
183
|
runner.install_actions.each do |action|
|
175
184
|
@logger.info("Running install action", :action => action)
|
176
185
|
system(action)
|
177
|
-
|
178
|
-
@logger.warn("Install action failed", :action => action, :code => $?.exitstatus)
|
179
|
-
end
|
186
|
+
@logger.warn("Install action failed", :action => action, :code => $CHILD_STATUS.exitstatus) unless $CHILD_STATUS.success?
|
180
187
|
end # each install action
|
181
188
|
else
|
182
189
|
path = File.join(tmp, "install_actions.sh")
|
@@ -188,6 +195,7 @@ are made. If it fails, nagios will not start. Yay!
|
|
188
195
|
end
|
189
196
|
end
|
190
197
|
end # if runner.install_actions.any?
|
198
|
+
return 0
|
191
199
|
end # def run_human
|
192
200
|
|
193
201
|
def write(fullpath, content, perms)
|
@@ -229,9 +237,7 @@ are made. If it fails, nagios will not start. Yay!
|
|
229
237
|
require(platform_lib)
|
230
238
|
|
231
239
|
const = PleaseRun::Platform.constants.find { |c| c.to_s.downcase == v.downcase }
|
232
|
-
if const.nil?
|
233
|
-
raise PlatformLoadError, "Could not find platform named '#{v}' after loading library '#{platform_lib}'. This is probably a bug."
|
234
|
-
end
|
240
|
+
raise PlatformLoadError, "Could not find platform named '#{v}' after loading library '#{platform_lib}'. This is probably a bug." if const.nil?
|
235
241
|
|
236
242
|
return PleaseRun::Platform.const_get(const)
|
237
243
|
rescue LoadError => e
|
@@ -45,9 +45,17 @@ module PleaseRun::Configurable
|
|
45
45
|
end
|
46
46
|
end # def configurable_setup
|
47
47
|
|
48
|
+
# A mixin to extend a class with whenever a class includes
|
49
|
+
# PleaseRun::Configurable.
|
50
|
+
#
|
51
|
+
# This class provides class-level 'attribute' method intended for use in
|
52
|
+
# defining attributes as well as a class-level 'attributes' method for
|
53
|
+
# listing attributes defined in this class. Finally, a helper
|
54
|
+
# 'all_attributes' method is provided to get all attributes defined by this
|
55
|
+
# class and any ancestors.
|
48
56
|
module ClassMixin
|
49
57
|
# Define an attribute on this class.
|
50
|
-
def attribute(name, description, options={}, &validator)
|
58
|
+
def attribute(name, description, options = {}, &validator)
|
51
59
|
facet = Facet.new(name, description, options, &validator)
|
52
60
|
attributes << facet
|
53
61
|
|
@@ -72,11 +80,35 @@ module PleaseRun::Configurable
|
|
72
80
|
end
|
73
81
|
|
74
82
|
def all_attributes
|
75
|
-
return ancestors.select { |a| a.respond_to?(:attributes) }.collect{ |a| a.attributes }.flatten
|
83
|
+
return ancestors.select { |a| a.respond_to?(:attributes) }.collect { |a| a.attributes }.flatten
|
76
84
|
end # def attributes
|
77
85
|
end # def ClassMixin
|
78
86
|
|
79
|
-
|
87
|
+
# A DSL for describing a facet.
|
88
|
+
#
|
89
|
+
# For example:
|
90
|
+
#
|
91
|
+
# Facet.new(:temperature, "The temperature value") do
|
92
|
+
# validate do |v|
|
93
|
+
# fail "Temperature must be a number" unless v.is_a?(Numeric)
|
94
|
+
# end
|
95
|
+
# munge do |v|
|
96
|
+
# Float(v)
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# Both validation and munge blocks are optional.
|
101
|
+
#
|
102
|
+
# The 'validate' block is expcted to fail if the value given to the
|
103
|
+
# facet is not valid.
|
104
|
+
#
|
105
|
+
# The 'munge' block is intended to help you coerce a value. For example, if
|
106
|
+
# you take "1234" from the user input (for example, as a command line flag
|
107
|
+
# value), you could use 'munge' to convert it to a number, as above.
|
108
|
+
#
|
109
|
+
# Munge is invoked *before* validation. Munge can fail if an invalid
|
110
|
+
# value is given.
|
111
|
+
class FacetDSL
|
80
112
|
def initialize(facet, &block)
|
81
113
|
@facet = facet
|
82
114
|
instance_eval(&block)
|
@@ -85,16 +117,25 @@ module PleaseRun::Configurable
|
|
85
117
|
def validate(&block)
|
86
118
|
@facet.validator = block
|
87
119
|
end
|
120
|
+
|
88
121
|
def munge(&block)
|
89
122
|
@facet.munger = block
|
90
123
|
end
|
91
124
|
end
|
92
125
|
|
126
|
+
# A generalized facet/property/container for a single value.
|
127
|
+
#
|
128
|
+
# Supports naming and text descriptions of this thing.
|
129
|
+
#
|
130
|
+
# Also supports value validation and munging on assignment to help
|
131
|
+
# you more easily accept user input from a variety of sources and
|
132
|
+
# keep the validation and value munging concerns near the value itself.
|
93
133
|
class Facet
|
94
134
|
attr_reader :name
|
95
135
|
attr_reader :description
|
136
|
+
attr_writer :validator, :munger
|
96
137
|
|
97
|
-
def initialize(name, description, options={}, &
|
138
|
+
def initialize(name, description, options = {}, &facet_dsl)
|
98
139
|
insist { name }.is_a?(Symbol)
|
99
140
|
insist { description }.is_a?(String)
|
100
141
|
insist { options }.is_a?(Hash)
|
@@ -103,21 +144,11 @@ module PleaseRun::Configurable
|
|
103
144
|
@description = description
|
104
145
|
@options = options
|
105
146
|
|
106
|
-
|
147
|
+
FacetDSL.new(self, &facet_dsl) if block_given?
|
107
148
|
|
108
|
-
if @options[:default]
|
109
|
-
validate(@options[:default])
|
110
|
-
end
|
149
|
+
validate(@options[:default]) if @options[:default]
|
111
150
|
end # def initialize
|
112
151
|
|
113
|
-
def validator=(callback)
|
114
|
-
@validator = callback
|
115
|
-
end # def validator=
|
116
|
-
|
117
|
-
def munger=(callback)
|
118
|
-
@munger = callback
|
119
|
-
end # def munger=
|
120
|
-
|
121
152
|
def value=(v)
|
122
153
|
v = @munger.call(v) if @munger
|
123
154
|
validate(v)
|
data/lib/pleaserun/detector.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
require "cabin"
|
2
|
+
|
3
|
+
# Detect the operating system and version, and based on that information,
|
4
|
+
# choose the most appropriate runner platform.
|
5
|
+
# TODO(sissel): Make this a module, not a class.
|
2
6
|
class PleaseRun::Detector
|
3
7
|
class UnknownSystem < StandardError; end
|
4
8
|
|
9
|
+
# A mapping of of [os, version] => [runner, version]
|
5
10
|
MAPPING = {
|
6
11
|
["ubuntu", "12.04"] => ["upstart", "1.5"],
|
7
12
|
["ubuntu", "12.10"] => ["upstart", "1.5"],
|
8
13
|
["ubuntu", "13.04"] => ["upstart", "1.5"],
|
9
14
|
["ubuntu", "13.10"] => ["upstart", "1.5"],
|
10
|
-
["debian", "7"] => [
|
11
|
-
["debian", "6"] => [
|
12
|
-
["fedora", "18"] => [
|
13
|
-
["fedora", "19"] => [
|
14
|
-
["fedora", "20"] => [
|
15
|
+
["debian", "7"] => ["sysv", "lsb-3.1"],
|
16
|
+
["debian", "6"] => ["sysv", "lsb-3.1"],
|
17
|
+
["fedora", "18"] => ["systemd", "default"],
|
18
|
+
["fedora", "19"] => ["systemd", "default"],
|
19
|
+
["fedora", "20"] => ["systemd", "default"],
|
20
|
+
["mac_os_x", "10.9"] => [ "launchd", "10.9"]
|
15
21
|
}
|
16
22
|
|
17
23
|
def self.detect
|
@@ -23,14 +29,18 @@ class PleaseRun::Detector
|
|
23
29
|
begin
|
24
30
|
platform, version = detect_facter
|
25
31
|
rescue LoadError
|
32
|
+
raise UnknownSystem
|
26
33
|
end
|
27
34
|
end
|
28
35
|
|
29
|
-
|
30
|
-
system = MAPPING[ [platform, version] ]
|
36
|
+
system = lookup([platform, version])
|
31
37
|
raise UnknownSystem if system.nil?
|
32
38
|
return system
|
33
|
-
end # def detect
|
39
|
+
end # def self.detect
|
40
|
+
|
41
|
+
def self.lookup(platform_and_version)
|
42
|
+
return MAPPING[platform_and_version]
|
43
|
+
end # def self.lookup
|
34
44
|
|
35
45
|
def self.detect_ohai
|
36
46
|
require "ohai/system"
|
@@ -40,19 +50,25 @@ class PleaseRun::Detector
|
|
40
50
|
ohai.all_plugins
|
41
51
|
|
42
52
|
platform = ohai["platform"]
|
43
|
-
|
44
|
-
version = case platform
|
45
|
-
# Take '6.0.8' and make it just '6' since debian never makes major
|
46
|
-
# changes in a minor release
|
47
|
-
when "debian" ; platform_version[/^[0-9]+/]
|
48
|
-
else ; platform_version
|
49
|
-
end # case platform
|
53
|
+
version = ohai["platform_version"]
|
50
54
|
|
51
|
-
return platform, version
|
55
|
+
return platform, normalize_version(platform, version)
|
52
56
|
end # def detect_ohai
|
53
57
|
|
58
|
+
def self.normalize_version(platform, version)
|
59
|
+
case platform
|
60
|
+
# Take '6.0.8' and make it just '6' since debian never makes major
|
61
|
+
# changes in a minor release
|
62
|
+
when "debian"
|
63
|
+
return version[/^[0-9]+/]
|
64
|
+
when "mac_os_x"
|
65
|
+
return version[/^[0-9]+\.[0-9]+/]
|
66
|
+
# TODO(sissel): Any other edge cases?
|
67
|
+
end
|
68
|
+
return version
|
69
|
+
end
|
70
|
+
|
54
71
|
def self.detect_facter
|
55
72
|
require "facter"
|
56
73
|
end
|
57
|
-
|
58
74
|
end
|
data/lib/pleaserun/namespace.rb
CHANGED
@@ -4,6 +4,14 @@ require "pleaserun/mustache_methods"
|
|
4
4
|
|
5
5
|
require "insist" # gem 'insist'
|
6
6
|
|
7
|
+
# Base class for all platforms.
|
8
|
+
#
|
9
|
+
# This class provides all the general attributes common
|
10
|
+
# among all process runners.
|
11
|
+
#
|
12
|
+
# For example, pretty much every runner (upstart, runit, sysv, etc) has
|
13
|
+
# concepts for the 'name' of a thing, what program it runs, what user
|
14
|
+
# to run as, etc.
|
7
15
|
class PleaseRun::Platform::Base
|
8
16
|
include PleaseRun::Configurable
|
9
17
|
include PleaseRun::MustacheMethods
|
@@ -112,7 +120,7 @@ class PleaseRun::Platform::Base
|
|
112
120
|
]
|
113
121
|
|
114
122
|
possibilities.each do |path|
|
115
|
-
next
|
123
|
+
next unless File.readable?(path) && File.file?(path)
|
116
124
|
return render(File.read(path))
|
117
125
|
end
|
118
126
|
|
@@ -128,7 +136,7 @@ class PleaseRun::Platform::Base
|
|
128
136
|
#
|
129
137
|
# This renders `str` through Mustache and replaces spaces with underscores.
|
130
138
|
def safe_filename(str)
|
131
|
-
return render(str).gsub(" ","_")
|
139
|
+
return render(str).gsub(" ", "_")
|
132
140
|
end # def safe_filename
|
133
141
|
|
134
142
|
# The default install_actions is none.
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require "pleaserun/platform/base"
|
2
2
|
require "pleaserun/namespace"
|
3
3
|
|
4
|
-
|
4
|
+
# The platform implementation for Apple's launchd.
|
5
|
+
#
|
6
|
+
# OS X users, this is for you!
|
7
|
+
class PleaseRun::Platform::Launchd < PleaseRun::Platform::Base
|
5
8
|
# Returns the file path to write this launchd config
|
6
9
|
def daemons_path
|
7
10
|
# Quoting launchctl(1):
|
@@ -11,12 +14,12 @@ class PleaseRun::Platform::LaunchD < PleaseRun::Platform::Base
|
|
11
14
|
|
12
15
|
def files
|
13
16
|
return Enumerator::Generator.new do |out|
|
14
|
-
out.yield
|
17
|
+
out.yield(daemons_path, render_template("program.plist"))
|
15
18
|
end
|
16
19
|
end # def files
|
17
20
|
|
18
21
|
def install_actions
|
19
|
-
return [
|
22
|
+
return ["launchctl load #{daemons_path}"]
|
20
23
|
end # def install_actions
|
21
24
|
|
22
25
|
def xml_args
|
@@ -24,4 +27,3 @@ class PleaseRun::Platform::LaunchD < PleaseRun::Platform::Base
|
|
24
27
|
return args.collect { |a| "<string>#{a}</string>" }.join("\n ")
|
25
28
|
end # def xml_args
|
26
29
|
end
|
27
|
-
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'pleaserun/namespace'
|
2
2
|
require "pleaserun/platform/base"
|
3
3
|
|
4
|
+
# The platform implementation for runit
|
5
|
+
#
|
6
|
+
# Learn what runit is here: http://smarden.org/runit/
|
4
7
|
class PleaseRun::Platform::Runit < PleaseRun::Platform::Base
|
5
8
|
attribute :service_path, "The path runit service directory",
|
6
9
|
:default => "/service" do |path|
|
@@ -11,8 +14,8 @@ class PleaseRun::Platform::Runit < PleaseRun::Platform::Base
|
|
11
14
|
|
12
15
|
def files
|
13
16
|
return Enumerator::Generator.new do |enum|
|
14
|
-
enum.yield
|
15
|
-
enum.yield
|
17
|
+
enum.yield(safe_filename("{{ service_path }}/{{ name }}/run"), render_template('run'))
|
18
|
+
enum.yield(safe_filename("{{ service_path }}/{{ name}}/log/run"), render_template('log'))
|
16
19
|
end
|
17
20
|
end
|
18
21
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'pleaserun/namespace'
|
2
2
|
require "pleaserun/platform/base"
|
3
3
|
|
4
|
+
# The platform implementation for systemd.
|
5
|
+
#
|
6
|
+
# If you use Fedora 18+ or CentOS/RHEL 7+, this is for you.
|
4
7
|
class PleaseRun::Platform::Systemd < PleaseRun::Platform::Base
|
5
8
|
def files
|
6
9
|
begin
|
@@ -11,14 +14,12 @@ class PleaseRun::Platform::Systemd < PleaseRun::Platform::Base
|
|
11
14
|
end
|
12
15
|
|
13
16
|
return Enumerator::Generator.new do |enum|
|
14
|
-
enum.yield
|
15
|
-
if prestart
|
16
|
-
enum.yield [ safe_filename("/lib/systemd/system/{{{ name }}}-prestart.sh"), render_template("prestart.sh"), 0755 ]
|
17
|
-
end
|
17
|
+
enum.yield(safe_filename("/lib/systemd/system/{{{ name }}}.service"), render_template("program.service"))
|
18
|
+
enum.yield(safe_filename("/lib/systemd/system/{{{ name }}}-prestart.sh"), render_template("prestart.sh"), 0755) if prestart
|
18
19
|
end
|
19
20
|
end # def files
|
20
21
|
|
21
22
|
def install_actions
|
22
|
-
return [
|
23
|
+
return ["systemctl --system daemon-reload"]
|
23
24
|
end
|
24
25
|
end # class PleaseRun::Platform::Systemd
|
@@ -1,12 +1,14 @@
|
|
1
1
|
require "pleaserun/platform/base"
|
2
2
|
require "pleaserun/namespace"
|
3
3
|
|
4
|
+
# The System V-style init system implementation.
|
5
|
+
#
|
6
|
+
# This will generate the familiar /etc/init.d/ scripts.
|
4
7
|
class PleaseRun::Platform::SYSV < PleaseRun::Platform::Base
|
5
8
|
def files
|
6
9
|
return Enumerator::Generator.new do |out|
|
7
|
-
out.yield
|
8
|
-
out.yield
|
10
|
+
out.yield(safe_filename("/etc/init.d/{{ name }}"), render_template("init.d"), 0755)
|
11
|
+
out.yield(safe_filename("/etc/default/{{ name }}"), render_template("default"))
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
12
|
-
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require "pleaserun/platform/base"
|
2
2
|
|
3
|
+
# The Upstart platform implementation.
|
4
|
+
#
|
5
|
+
# If you use Ubuntu (8.10 to present) or CentOS 6 this is for you.
|
3
6
|
class PleaseRun::Platform::Upstart < PleaseRun::Platform::Base
|
4
7
|
def files
|
5
8
|
return Enumerator::Generator.new do |out|
|
6
|
-
out.yield
|
7
|
-
out.yield
|
9
|
+
out.yield(safe_filename("/etc/init/{{ name }}.conf"), render_template("init.conf"))
|
10
|
+
out.yield(safe_filename("/etc/init.d/{{ name }}"), render_template("init.d.sh"), 0755)
|
8
11
|
end
|
9
12
|
end
|
10
13
|
end
|
11
|
-
|
data/pleaserun.gemspec
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
require "testenv"
|
2
2
|
require "pleaserun/configurable"
|
3
3
|
|
4
|
+
# rubocop complains that 'insist { ... } == ...' is Void. It's wrong, in this
|
5
|
+
# case, so let's disable that check.
|
6
|
+
# rubocop:disable Void
|
7
|
+
|
4
8
|
describe PleaseRun::Configurable::Facet do
|
5
9
|
subject { PleaseRun::Configurable::Facet }
|
6
10
|
|
@@ -86,8 +90,8 @@ describe PleaseRun::Configurable::Facet do
|
|
86
90
|
end
|
87
91
|
|
88
92
|
facet.value = "hello"
|
89
|
-
insist { facet.value } == [
|
90
|
-
insist { order } == [
|
93
|
+
insist { facet.value } == ["hello"]
|
94
|
+
insist { order } == [:munge, :validate]
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
@@ -119,7 +123,7 @@ describe PleaseRun::Configurable::Facet do
|
|
119
123
|
|
120
124
|
it "fails if default is invalid" do
|
121
125
|
insist do
|
122
|
-
|
126
|
+
subject.new(:name, "description", :default => 4) do
|
123
127
|
validate do |v|
|
124
128
|
insist { v } != 4
|
125
129
|
end
|
@@ -128,7 +132,7 @@ describe PleaseRun::Configurable::Facet do
|
|
128
132
|
end
|
129
133
|
|
130
134
|
it "succeeds if default is valid" do
|
131
|
-
|
135
|
+
subject.new(:name, "description", :default => 4) do
|
132
136
|
validate do |v|
|
133
137
|
insist { v } == 4
|
134
138
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "testenv"
|
2
2
|
require "pleaserun/mustache_methods"
|
3
3
|
|
4
|
+
# Fixture for use in testing PleaseRun::MustacheMethods
|
4
5
|
class MustacheMethodTester
|
5
6
|
include PleaseRun::MustacheMethods
|
6
7
|
|
@@ -9,7 +10,7 @@ class MustacheMethodTester
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def args
|
12
|
-
[
|
13
|
+
["hello world", "fancy pants"]
|
13
14
|
end
|
14
15
|
|
15
16
|
def render(s)
|
@@ -1,14 +1,15 @@
|
|
1
|
+
require "English" # for $CHILD_STATUS
|
1
2
|
require "testenv"
|
2
3
|
require "pleaserun/platform/launchd"
|
3
4
|
|
4
|
-
describe PleaseRun::Platform::
|
5
|
+
describe PleaseRun::Platform::Launchd do
|
5
6
|
it "inherits correctly" do
|
6
|
-
insist { PleaseRun::Platform::
|
7
|
+
insist { PleaseRun::Platform::Launchd.ancestors }.include?(PleaseRun::Platform::Base)
|
7
8
|
end
|
8
9
|
|
9
10
|
context "#files" do
|
10
11
|
subject do
|
11
|
-
runner = PleaseRun::Platform::
|
12
|
+
runner = PleaseRun::Platform::Launchd.new("10.9")
|
12
13
|
runner.name = "fancypants"
|
13
14
|
next runner
|
14
15
|
end
|
@@ -22,7 +23,7 @@ describe PleaseRun::Platform::LaunchD do
|
|
22
23
|
|
23
24
|
context "#install_actions" do
|
24
25
|
subject do
|
25
|
-
runner = PleaseRun::Platform::
|
26
|
+
runner = PleaseRun::Platform::Launchd.new("10.9")
|
26
27
|
runner.name = "fancypants"
|
27
28
|
next runner
|
28
29
|
end
|
@@ -40,20 +41,20 @@ describe PleaseRun::Platform::LaunchD do
|
|
40
41
|
end
|
41
42
|
|
42
43
|
context "as the super user", :if => partytime do
|
43
|
-
subject { PleaseRun::Platform::
|
44
|
+
subject { PleaseRun::Platform::Launchd.new("10.9") }
|
44
45
|
|
45
46
|
before do
|
46
47
|
subject.name = "example"
|
47
48
|
subject.user = "root"
|
48
49
|
subject.program = "/bin/sh"
|
49
|
-
subject.args = [
|
50
|
+
subject.args = ["-c", "echo hello world; sleep 5"]
|
50
51
|
|
51
52
|
subject.files.each do |path, content|
|
52
53
|
File.write(path, content)
|
53
54
|
end
|
54
55
|
subject.install_actions.each do |command|
|
55
56
|
system(command)
|
56
|
-
raise "Command failed: #{command}" unless
|
57
|
+
raise "Command failed: #{command}" unless $CHILD_STATUS.success?
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -65,28 +66,28 @@ describe PleaseRun::Platform::LaunchD do
|
|
65
66
|
end
|
66
67
|
|
67
68
|
# Remove the logs, too.
|
68
|
-
[
|
69
|
+
["/var/log/#{subject.name}.out", "/var/log/#{subject.name}.err"].each do |log|
|
69
70
|
File.unlink(log) if File.exist?(log)
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
73
74
|
it "should install" do
|
74
75
|
system_quiet("launchctl list #{subject.name}")
|
75
|
-
insist {
|
76
|
+
insist { $CHILD_STATUS }.success?
|
76
77
|
end
|
77
78
|
|
78
79
|
it "should start" do
|
79
80
|
system_quiet("launchctl start #{subject.name}")
|
80
|
-
insist {
|
81
|
+
insist { $CHILD_STATUS }.success?
|
81
82
|
system_quiet("launchctl list #{subject.name}")
|
82
|
-
insist {
|
83
|
+
insist { $CHILD_STATUS }.success?
|
83
84
|
end
|
84
85
|
|
85
86
|
it "should stop" do
|
86
87
|
system_quiet("launchctl start #{subject.name}")
|
87
|
-
insist {
|
88
|
+
insist { $CHILD_STATUS }.success?
|
88
89
|
system_quiet("launchctl stop #{subject.name}")
|
89
|
-
insist {
|
90
|
+
insist { $CHILD_STATUS }.success?
|
90
91
|
end
|
91
92
|
end
|
92
93
|
end # real tests
|
@@ -54,7 +54,7 @@ describe PleaseRun::Platform::Systemd do
|
|
54
54
|
subject.name = "hurray"
|
55
55
|
subject.user = "root"
|
56
56
|
subject.program = "/bin/sh"
|
57
|
-
subject.args = [
|
57
|
+
subject.args = ["-c", "echo hello world; sleep 5"]
|
58
58
|
activate(subject)
|
59
59
|
|
60
60
|
# monkeypatch StartLimitInterval=0 into the .service file to avoid
|
@@ -71,11 +71,6 @@ describe PleaseRun::Platform::Systemd do
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
#it "should install" do
|
75
|
-
#system("systemctl status #{subject.name}")
|
76
|
-
#status_stopped
|
77
|
-
#end
|
78
|
-
|
79
74
|
it "should start" do
|
80
75
|
starts
|
81
76
|
status_running
|
@@ -42,7 +42,7 @@ describe PleaseRun::Platform::SYSV do
|
|
42
42
|
subject.name = "example"
|
43
43
|
subject.user = "root"
|
44
44
|
subject.program = "/bin/ping"
|
45
|
-
subject.args = [
|
45
|
+
subject.args = ["127.0.0.1"]
|
46
46
|
|
47
47
|
activate(subject)
|
48
48
|
end
|
@@ -54,8 +54,6 @@ describe PleaseRun::Platform::SYSV do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# TODO(sissel): Remove the logs, too.
|
57
|
-
#log = "/var/log/example.log"
|
58
|
-
#File.unlink(log) if File.exist?(log)
|
59
57
|
end
|
60
58
|
|
61
59
|
it "should install" do
|
@@ -57,7 +57,7 @@ describe PleaseRun::Platform::Upstart do
|
|
57
57
|
subject.name = "example"
|
58
58
|
subject.user = "root"
|
59
59
|
subject.program = "/bin/sh"
|
60
|
-
subject.args = [
|
60
|
+
subject.args = ["-c", "echo hello world; sleep 5"]
|
61
61
|
activate(subject)
|
62
62
|
end
|
63
63
|
|
@@ -72,11 +72,6 @@ describe PleaseRun::Platform::Upstart do
|
|
72
72
|
File.unlink(log) if File.exist?(log)
|
73
73
|
end
|
74
74
|
|
75
|
-
#it "should install" do
|
76
|
-
#system("initctl status #{subject.name}")
|
77
|
-
#status_stopped
|
78
|
-
#end
|
79
|
-
|
80
75
|
it "should start" do
|
81
76
|
starts
|
82
77
|
|
data/spec/testenv.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require "English" # for $CHILD_STATUS
|
1
2
|
require "pleaserun/namespace"
|
2
3
|
require "insist"
|
3
4
|
|
@@ -15,7 +16,7 @@ end
|
|
15
16
|
|
16
17
|
def sh(command)
|
17
18
|
system_quiet(command)
|
18
|
-
return
|
19
|
+
return $CHILD_STATUS
|
19
20
|
end
|
20
21
|
|
21
22
|
def program?(name)
|
@@ -27,39 +28,44 @@ def program?(name)
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def activate(pleaserun)
|
30
|
-
pleaserun.files.each do |path, content, mode=nil|
|
31
|
+
pleaserun.files.each do |path, content, mode = nil|
|
31
32
|
File.write(path, content)
|
32
33
|
File.chmod(mode, path) if mode
|
33
34
|
end
|
34
35
|
pleaserun.install_actions.each do |command|
|
35
36
|
system(command)
|
36
|
-
raise "Command failed: #{command}" unless
|
37
|
+
raise "Command failed: #{command}" unless $CHILD_STATUS.success?
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
41
|
+
# Helper methods to provide during rspec tests.
|
40
42
|
module Helpers
|
41
43
|
def starts
|
42
|
-
system_quiet(start)
|
44
|
+
system_quiet(start)
|
45
|
+
insist { $CHILD_STATUS }.success?
|
43
46
|
status_running
|
44
47
|
end
|
45
48
|
|
46
49
|
def stops
|
47
|
-
system_quiet(stop)
|
50
|
+
system_quiet(stop)
|
51
|
+
insist { $CHILD_STATUS }.success?
|
48
52
|
status_stopped
|
49
53
|
end
|
50
54
|
|
51
55
|
def status_running
|
52
|
-
system_quiet(status)
|
56
|
+
system_quiet(status)
|
57
|
+
insist { $CHILD_STATUS }.success?
|
53
58
|
end
|
54
59
|
|
55
60
|
def status_stopped
|
56
|
-
system_quiet(status)
|
61
|
+
system_quiet(status)
|
62
|
+
reject { $CHILD_STATUS }.success?
|
57
63
|
end
|
58
64
|
|
59
65
|
def restarts
|
60
66
|
starts
|
61
67
|
system_quiet(restart)
|
62
|
-
insist {
|
68
|
+
insist { $CHILD_STATUS }.success?
|
63
69
|
status_running
|
64
70
|
end
|
65
71
|
end
|
data/test/test.rb
CHANGED
@@ -35,9 +35,17 @@ end
|
|
35
35
|
results = ARGV.collect { tag, success, out, err = queue.pop }
|
36
36
|
successes = results.count { |tag, success, out, err| success }
|
37
37
|
failures = results.count { |tag, success, out, err| !success }
|
38
|
-
total_tests = 0
|
39
38
|
tests = results.collect { |tag, success, out, err|
|
40
|
-
|
39
|
+
#require "pry"
|
40
|
+
#binding.pry
|
41
|
+
begin
|
42
|
+
JSON.parse(File.read(out).split("\n").last[/{.*$/])["examples"].each { |r| r["tag"] = tag }
|
43
|
+
rescue TypeError
|
44
|
+
puts "Failed to parse json"
|
45
|
+
puts :out => File.read(out)
|
46
|
+
puts :err => File.read(err)
|
47
|
+
raise
|
48
|
+
end
|
41
49
|
}.flatten
|
42
50
|
|
43
51
|
duration = Time.now - start
|
@@ -45,14 +53,25 @@ duration = Time.now - start
|
|
45
53
|
test_successes = tests.count { |t| t["status"] == "passed" }
|
46
54
|
test_failures = tests.count { |t| t["status"] == "failed" }
|
47
55
|
|
56
|
+
#require "pry"
|
57
|
+
#tests.pry
|
58
|
+
tests.each do |result|
|
59
|
+
next if result["status"] == "passed"
|
60
|
+
|
61
|
+
case result["status"]
|
62
|
+
when "failed"
|
63
|
+
puts "#{result["tag"]}: #{result["full_description"]}"
|
64
|
+
exception = result["exception"]
|
65
|
+
puts " #{exception["class"]}: #{exception["message"]}"
|
66
|
+
when "pending"
|
67
|
+
puts "#{result["tag"]}: PENDING: #{result["full_description"]}"
|
68
|
+
end
|
69
|
+
puts " #{result["file_path"]}:#{result["line_number"]}"
|
70
|
+
end
|
71
|
+
|
48
72
|
puts "Tests: #{test_successes} ok, #{test_failures} failures; Platforms: #{successes} ok, #{failures} failures;, Duration: #{sprintf("%0.3f", duration)} seconds"
|
49
73
|
|
50
74
|
results.each do |tag, success, out, err|
|
51
|
-
# print only on failure *or* if only one container is run
|
52
|
-
if !success || results.size == 1
|
53
|
-
puts File.read(err).gsub(/^/, "#{tag}/stderr: ")
|
54
|
-
puts File.read(out).gsub(/^/, "#{tag}/stdout: ")
|
55
|
-
end
|
56
75
|
File.delete(err)
|
57
76
|
File.delete(out)
|
58
77
|
end
|
metadata
CHANGED
@@ -1,116 +1,102 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pleaserun
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Jordan Sissel
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-05 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: cabin
|
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: clamp
|
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: cabin
|
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: stud
|
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: mustache
|
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
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: insist
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :runtime
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: ohai
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
101
|
- - ~>
|
116
102
|
- !ruby/object:Gem::Version
|
@@ -118,7 +104,6 @@ dependencies:
|
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
108
|
- - ~>
|
124
109
|
- !ruby/object:Gem::Version
|
@@ -132,9 +117,12 @@ extensions: []
|
|
132
117
|
extra_rdoc_files: []
|
133
118
|
files:
|
134
119
|
- .gitignore
|
120
|
+
- .rubocop.yml
|
121
|
+
- CHANGELOG.asciidoc
|
135
122
|
- Gemfile
|
136
123
|
- Gemfile.lock
|
137
124
|
- Guardfile
|
125
|
+
- LICENSE
|
138
126
|
- Makefile
|
139
127
|
- README.md
|
140
128
|
- bin/pleaserun
|
@@ -177,27 +165,26 @@ files:
|
|
177
165
|
homepage:
|
178
166
|
licenses:
|
179
167
|
- Apache 2.0
|
168
|
+
metadata: {}
|
180
169
|
post_install_message:
|
181
170
|
rdoc_options: []
|
182
171
|
require_paths:
|
183
172
|
- lib
|
184
173
|
- lib
|
185
174
|
required_ruby_version: !ruby/object:Gem::Requirement
|
186
|
-
none: false
|
187
175
|
requirements:
|
188
|
-
- -
|
176
|
+
- - '>='
|
189
177
|
- !ruby/object:Gem::Version
|
190
178
|
version: '0'
|
191
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
192
|
-
none: false
|
193
180
|
requirements:
|
194
|
-
- -
|
181
|
+
- - '>='
|
195
182
|
- !ruby/object:Gem::Version
|
196
183
|
version: '0'
|
197
184
|
requirements: []
|
198
185
|
rubyforge_project:
|
199
|
-
rubygems_version: 1.
|
186
|
+
rubygems_version: 2.1.11
|
200
187
|
signing_key:
|
201
|
-
specification_version:
|
188
|
+
specification_version: 4
|
202
189
|
summary: pleaserun
|
203
190
|
test_files: []
|