dream-ops 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +21 -8
- data/lib/dream-ops.rb +17 -9
- data/lib/dream-ops/cli.rb +14 -41
- data/lib/dream-ops/deployment/base.rb +39 -3
- data/lib/dream-ops/deployment/opsworks.rb +80 -31
- data/lib/dream-ops/errors.rb +31 -1
- data/lib/dream-ops/formatters/human.rb +1 -1
- data/lib/dream-ops/logger.rb +18 -0
- data/lib/dream-ops/mixin/logging.rb +12 -0
- data/lib/dream-ops/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe5971e39855c322c3680d7495452950f6e129ac
|
4
|
+
data.tar.gz: 6d7b6cd6b14ae02429694879aa34d7656ecd2228
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04e7efd3f5108eb2f547265bee1b326a1523d4e19b8cd49eea62b0d45c7331509ec380d5a7d4e996312bf6d90fcd3665226d4fa220fb8f81644e93d24be31ac5
|
7
|
+
data.tar.gz: 642468eaabb2ec607aa1c3415dc21052884927d6e8835bca5849a9d08eee1edf966cc66db02993962a34438b73f0649f776ca786c077f23e89ee43b03cda8d22
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# DreamOps
|
2
|
+
[![Gem Version](https://img.shields.io/gem/v/dream-ops.svg)][gem]
|
2
3
|
|
3
|
-
|
4
|
+
[gem]: https://rubygems.org/gems/dream-ops
|
4
5
|
|
5
|
-
|
6
|
+
CLI for Dream projects based on the [berkshelf](https://github.com/berkshelf/berkshelf) project.
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
@@ -22,7 +23,23 @@ Or install it yourself as:
|
|
22
23
|
|
23
24
|
## Usage
|
24
25
|
|
25
|
-
|
26
|
+
```bash
|
27
|
+
dream help
|
28
|
+
```
|
29
|
+
|
30
|
+
### Deploying to OpsWorks
|
31
|
+
|
32
|
+
```bash
|
33
|
+
dream deploy opsworks --stacks 08137c03-1e85-4787-b82c-cb825638cdfa
|
34
|
+
Stack: nodeapp
|
35
|
+
--- Cookbook: chef-nodeapp
|
36
|
+
--- Apps: ["nodeapp"]
|
37
|
+
...Building cookbook [chef-nodeapp]
|
38
|
+
...Deploying cookbook [chef-nodeapp]
|
39
|
+
...Updating custom cookbooks [stack="nodeapp"]
|
40
|
+
...Running setup command [stack="nodeapp"]
|
41
|
+
...Deploying [stack="nodeapp"] [app="nodeapp"]
|
42
|
+
```
|
26
43
|
|
27
44
|
## Development
|
28
45
|
|
@@ -32,8 +49,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
49
|
|
33
50
|
## Contributing
|
34
51
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dream-ops.
|
36
|
-
|
37
|
-
## License
|
38
|
-
|
39
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
52
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dream-ops.
|
data/lib/dream-ops.rb
CHANGED
@@ -11,24 +11,28 @@ end
|
|
11
11
|
require "berkshelf"
|
12
12
|
require "thor"
|
13
13
|
|
14
|
-
Berkshelf.ui.mute!
|
15
|
-
|
16
14
|
module DreamOps
|
17
15
|
|
18
16
|
require_relative "dream-ops/version"
|
19
17
|
require_relative "dream-ops/errors"
|
20
18
|
|
21
|
-
|
19
|
+
module Mixin
|
20
|
+
autoload :Logging, "dream-ops/mixin/logging"
|
21
|
+
end
|
22
|
+
|
23
|
+
autoload :Shell, "dream-ops/shell"
|
22
24
|
|
23
|
-
autoload :BaseFormatter,
|
24
|
-
autoload :HumanFormatter,
|
25
|
-
# autoload :JsonFormatter,
|
26
|
-
# autoload :NullFormatter,
|
25
|
+
autoload :BaseFormatter, "dream-ops/formatters/base"
|
26
|
+
autoload :HumanFormatter, "dream-ops/formatters/human"
|
27
|
+
# autoload :JsonFormatter, "dream-ops/formatters/json"
|
28
|
+
# autoload :NullFormatter, "dream-ops/formatters/null"
|
27
29
|
|
28
|
-
autoload :BaseDeployer,
|
30
|
+
autoload :BaseDeployer, "dream-ops/deployment/base"
|
29
31
|
autoload :OpsWorksDeployer, "dream-ops/deployment/opsworks"
|
30
32
|
|
31
33
|
class << self
|
34
|
+
include Mixin::Logging
|
35
|
+
|
32
36
|
# @return [DreamOps::Shell]
|
33
37
|
def ui
|
34
38
|
@ui ||= DreamOps::Shell.new
|
@@ -57,4 +61,8 @@ module DreamOps
|
|
57
61
|
end
|
58
62
|
end
|
59
63
|
|
60
|
-
require_relative "dream-ops/cli"
|
64
|
+
require_relative "dream-ops/cli"
|
65
|
+
require_relative "dream-ops/logger"
|
66
|
+
|
67
|
+
Ridley.logger = DreamOps.logger
|
68
|
+
DreamOps.logger.level = Logger::WARN
|
data/lib/dream-ops/cli.rb
CHANGED
@@ -27,12 +27,8 @@ module DreamOps
|
|
27
27
|
@kernel.exit(0)
|
28
28
|
rescue DreamOps::DreamOpsError => e
|
29
29
|
DreamOps.ui.error e
|
30
|
-
DreamOps.ui.error "\t" + e.backtrace.join("\n\t") if ENV["
|
30
|
+
DreamOps.ui.error "\t" + e.backtrace.join("\n\t") if ENV["DREAMOPS_DEBUG"]
|
31
31
|
@kernel.exit(e.status_code)
|
32
|
-
# rescue Ridley::Errors::RidleyError => e
|
33
|
-
# DreamOps.ui.error "#{e.class} #{e}"
|
34
|
-
# DreamOps.ui.error "\t" + e.backtrace.join("\n\t") if ENV["BERKSHELF_DEBUG"]
|
35
|
-
# @kernel.exit(47)
|
36
32
|
end
|
37
33
|
end
|
38
34
|
|
@@ -56,17 +52,11 @@ module DreamOps
|
|
56
52
|
def initialize(*args)
|
57
53
|
super(*args)
|
58
54
|
|
59
|
-
# if @options[:config]
|
60
|
-
# unless File.exist?(@options[:config])
|
61
|
-
# raise ConfigNotFound.new(:berkshelf, @options[:config])
|
62
|
-
# end
|
63
|
-
|
64
|
-
# DreamOps.config = DreamOps::Config.from_file(@options[:config])
|
65
|
-
# end
|
66
|
-
|
67
55
|
if @options[:debug]
|
68
|
-
ENV["
|
56
|
+
ENV["DREAMOPS_DEBUG"] = "true"
|
69
57
|
DreamOps.logger.level = ::Logger::DEBUG
|
58
|
+
else
|
59
|
+
Berkshelf.ui.mute!
|
70
60
|
end
|
71
61
|
|
72
62
|
if @options[:quiet]
|
@@ -77,19 +67,13 @@ module DreamOps
|
|
77
67
|
@options = options.dup # unfreeze frozen options Hash from Thor
|
78
68
|
end
|
79
69
|
|
80
|
-
namespace "
|
70
|
+
namespace "dream-ops"
|
81
71
|
|
82
|
-
map "ls" => :list
|
83
|
-
map "book" => :cookbook
|
72
|
+
# map "ls" => :list
|
84
73
|
map ["ver", "-v", "--version"] => :version
|
85
74
|
|
86
|
-
default_task :
|
75
|
+
default_task :version
|
87
76
|
|
88
|
-
class_option :config,
|
89
|
-
type: :string,
|
90
|
-
desc: "Path to DreamOps configuration to use.",
|
91
|
-
aliases: "-c",
|
92
|
-
banner: "PATH"
|
93
77
|
class_option :format,
|
94
78
|
type: :string,
|
95
79
|
default: "human",
|
@@ -115,8 +99,9 @@ module DreamOps
|
|
115
99
|
method_option :stacks,
|
116
100
|
type: :array,
|
117
101
|
desc: "Only these stack IDs.",
|
118
|
-
aliases: "-s"
|
119
|
-
|
102
|
+
aliases: "-s",
|
103
|
+
required: true
|
104
|
+
desc "deploy [TYPE]", "Deploys to specified targets"
|
120
105
|
def deploy(type)
|
121
106
|
deployer = nil
|
122
107
|
|
@@ -125,26 +110,14 @@ module DreamOps
|
|
125
110
|
deployer = OpsWorksDeployer.new
|
126
111
|
stack_ids = options[:stacks]
|
127
112
|
args = [*stack_ids]
|
113
|
+
else
|
114
|
+
DreamOps.ui.error "Deployment of type '#{type}' is not supported"
|
115
|
+
exit(1)
|
128
116
|
end
|
129
117
|
|
130
118
|
if !deployer.nil?
|
131
119
|
deployer.deploy(*args)
|
132
120
|
end
|
133
121
|
end
|
134
|
-
|
135
|
-
# tasks["cookbook"].options = DreamOps::CookbookGenerator.class_options
|
136
|
-
|
137
|
-
private
|
138
|
-
|
139
|
-
# Print a list of the given cookbooks. This is used by various
|
140
|
-
# methods like {list} and {contingent}.
|
141
|
-
#
|
142
|
-
# @param [Array<CachedCookbook>] cookbooks
|
143
|
-
#
|
144
|
-
def print_list(cookbooks)
|
145
|
-
Array(cookbooks).sort.each do |cookbook|
|
146
|
-
DreamOps.formatter.msg " * #{cookbook.cookbook_name} (#{cookbook.version})"
|
147
|
-
end
|
148
|
-
end
|
149
122
|
end
|
150
|
-
end
|
123
|
+
end
|
@@ -20,13 +20,47 @@ module DreamOps
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
#
|
23
|
+
# This method MUST be implemented by subclasses.
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
26
|
+
# a hash containing cookbooks that need to be built/updated
|
27
|
+
# and deploy targets
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
# {
|
31
|
+
# :cookbooks => [
|
32
|
+
# {
|
33
|
+
# :bucket => "chef-app",
|
34
|
+
# :cookbook_key => "chef-app-dev.zip",
|
35
|
+
# :sha_key => "chef-app-dev_SHA.txt",
|
36
|
+
# :name => "chef-app",
|
37
|
+
# :path => "./chef",
|
38
|
+
# :local_sha => "7bfa19491170563f422a321c144800f4435323b1",
|
39
|
+
# :remote_sha => ""
|
40
|
+
# }
|
41
|
+
# ],
|
42
|
+
# deploy_targets: [
|
43
|
+
# #<Hash>,
|
44
|
+
# #<Hash>
|
45
|
+
# ]
|
46
|
+
# }
|
24
47
|
deployer_method :analyze
|
48
|
+
|
49
|
+
# This method MUST be implemented by subclasses.
|
50
|
+
#
|
51
|
+
# @param [Hash] cookbook
|
52
|
+
# a hash containing the cookbook details
|
25
53
|
deployer_method :deploy_cookbook
|
54
|
+
|
55
|
+
|
56
|
+
# This method MUST be implemented by subclasses.
|
57
|
+
#
|
58
|
+
# @param [Hash] target
|
59
|
+
# a hash containing the deploy target details
|
26
60
|
deployer_method :deploy_target
|
27
61
|
|
28
62
|
# It may turn out that cookbook building will be different for different
|
29
|
-
# deployments, but for now all deployments build them the same way.
|
63
|
+
# deployments, but for now all deployments will build them the same way.
|
30
64
|
def build_cookbook(cookbook)
|
31
65
|
berksfile = Berkshelf::Berksfile.from_file(File.join(cookbook[:path], "Berksfile"))
|
32
66
|
berksfile.vendor("berks-cookbooks")
|
@@ -69,11 +103,13 @@ module DreamOps
|
|
69
103
|
deploy_threads.each do |t|
|
70
104
|
begin
|
71
105
|
t.join
|
72
|
-
rescue DreamOps::
|
106
|
+
rescue DreamOps::DreamOpsError
|
107
|
+
DreamOps.ui.error "#{$!}"
|
73
108
|
deploy_success = deploy_success && false
|
74
109
|
end
|
75
110
|
end
|
76
111
|
|
112
|
+
# If ANY deploy threads failed, exit with failure
|
77
113
|
exit(1) if !deploy_success
|
78
114
|
end
|
79
115
|
end
|
@@ -6,13 +6,48 @@ Aws.use_bundled_cert!
|
|
6
6
|
module DreamOps
|
7
7
|
class OpsWorksDeployer < BaseDeployer
|
8
8
|
|
9
|
-
#
|
9
|
+
# Analyze the OpsWorks stacks for deployment
|
10
|
+
#
|
11
|
+
# @return [Hash]
|
12
|
+
# a hash containing cookbooks that need to be built/updated
|
13
|
+
# and deploy targets
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# {
|
17
|
+
# :cookbooks => [
|
18
|
+
# {
|
19
|
+
# :bucket => "chef-app",
|
20
|
+
# :cookbook_key => "chef-app-dev.zip",
|
21
|
+
# :sha_key => "chef-app-dev_SHA.txt",
|
22
|
+
# :name => "chef-app",
|
23
|
+
# :path => "./chef",
|
24
|
+
# :local_sha => "7bfa19491170563f422a321c144800f4435323b1",
|
25
|
+
# :remote_sha => ""
|
26
|
+
# }
|
27
|
+
# ],
|
28
|
+
# deploy_targets: [
|
29
|
+
# {
|
30
|
+
# :stack => #<Stack: name="my-stack">,
|
31
|
+
# :apps => [
|
32
|
+
# #<App: name="my-app"
|
33
|
+
# ],
|
34
|
+
# :cookbook => {
|
35
|
+
# :bucket => "chef-app",
|
36
|
+
# :cookbook_key => "chef-app-dev.zip",
|
37
|
+
# :sha_key => "chef-app-dev_SHA.txt",
|
38
|
+
# :name => "chef-app",
|
39
|
+
# :path => "./chef",
|
40
|
+
# :local_sha => "7bfa19491170563f422a321c144800f4435323b1",
|
41
|
+
# :remote_sha => ""
|
42
|
+
# }
|
43
|
+
# }
|
44
|
+
# ]
|
45
|
+
# }
|
10
46
|
def analyze(stack_ids)
|
11
47
|
begin
|
12
48
|
@opsworks = Aws::OpsWorks::Client.new
|
13
49
|
stacks = @opsworks.describe_stacks({ stack_ids: stack_ids, }).stacks
|
14
50
|
rescue => e
|
15
|
-
DreamOps.ui.error "Failed to fetch OpsWorks stacks\n"
|
16
51
|
DreamOps.ui.error "#{$!}"
|
17
52
|
exit(1)
|
18
53
|
end
|
@@ -42,8 +77,6 @@ module DreamOps
|
|
42
77
|
return result
|
43
78
|
end
|
44
79
|
|
45
|
-
################## OpsWorks specific methods ##################
|
46
|
-
|
47
80
|
# Retrieves stack apps and gets all information about remote/local cookbook
|
48
81
|
def analyze_stack(stack)
|
49
82
|
cookbook = nil
|
@@ -118,13 +151,8 @@ module DreamOps
|
|
118
151
|
# If this stack has a new cookbook
|
119
152
|
if !target[:cookbook].nil?
|
120
153
|
if __cookbook_in_array(target[:cookbook], cookbooks)
|
121
|
-
|
122
|
-
|
123
|
-
update_custom_cookbooks(target[:stack])
|
124
|
-
rescue Aws::OpsWorks::Errors::ValidationException
|
125
|
-
DreamOps.ui.error "Stack \"#{target[:stack].name}\" has no running instances."
|
126
|
-
__bail_with_fatal_error
|
127
|
-
end
|
154
|
+
# Grab a fresh copy of the cookbook on all instances in the stack
|
155
|
+
update_custom_cookbooks(target[:stack])
|
128
156
|
|
129
157
|
# Re-run the setup step for all layers
|
130
158
|
setup(target[:stack])
|
@@ -133,22 +161,27 @@ module DreamOps
|
|
133
161
|
|
134
162
|
# Deploy all apps for stack
|
135
163
|
target[:apps].each do |app|
|
136
|
-
|
137
|
-
deploy_app(app, target[:stack])
|
138
|
-
rescue Aws::OpsWorks::Errors::ValidationException
|
139
|
-
DreamOps.ui.error "Stack \"#{target[:stack].name}\" has no running instances."
|
140
|
-
__bail_with_fatal_error
|
141
|
-
end
|
164
|
+
deploy_app(app, target[:stack])
|
142
165
|
end
|
143
166
|
end
|
144
167
|
|
145
168
|
def update_custom_cookbooks(stack)
|
146
169
|
DreamOps.ui.info "...Updating custom cookbooks [stack=\"#{stack.name}\"]"
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
170
|
+
begin
|
171
|
+
response = @opsworks.create_deployment({
|
172
|
+
stack_id: stack.stack_id,
|
173
|
+
command: { name: "update_custom_cookbooks" }
|
174
|
+
})
|
175
|
+
rescue Aws::OpsWorks::Errors::ValidationException
|
176
|
+
bail_with_fatal_error(NoRunningInstancesError.new(stack))
|
177
|
+
end
|
178
|
+
|
179
|
+
status = wait_for_deployment(response.deployment_id)
|
180
|
+
if status != 'successful'
|
181
|
+
bail_with_fatal_error(OpsWorksCommandFailedError.new(
|
182
|
+
stack, response.deployment_id, 'update_custom_cookbooks')
|
183
|
+
)
|
184
|
+
end
|
152
185
|
end
|
153
186
|
|
154
187
|
def setup(stack)
|
@@ -157,17 +190,33 @@ module DreamOps
|
|
157
190
|
stack_id: stack.stack_id,
|
158
191
|
command: { name: "setup" }
|
159
192
|
})
|
160
|
-
|
193
|
+
|
194
|
+
status = wait_for_deployment(response.deployment_id)
|
195
|
+
if status != 'successful'
|
196
|
+
bail_with_fatal_error(OpsWorksCommandFailedError.new(
|
197
|
+
stack, response.deployment_id, 'setup')
|
198
|
+
)
|
199
|
+
end
|
161
200
|
end
|
162
201
|
|
163
202
|
def deploy_app(app, stack)
|
164
203
|
DreamOps.ui.info "...Deploying [stack=\"#{stack.name}\"] [app=\"#{app.name}\"]"
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
204
|
+
begin
|
205
|
+
response = @opsworks.create_deployment({
|
206
|
+
stack_id: stack.stack_id,
|
207
|
+
app_id: app.app_id,
|
208
|
+
command: { name: "deploy" }
|
209
|
+
})
|
210
|
+
rescue Aws::OpsWorks::Errors::ValidationException
|
211
|
+
bail_with_fatal_error(NoRunningInstancesError.new(stack))
|
212
|
+
end
|
213
|
+
|
214
|
+
status = wait_for_deployment(response.deployment_id)
|
215
|
+
if status != 'successful'
|
216
|
+
bail_with_fatal_error(OpsWorksCommandFailedError.new(
|
217
|
+
stack, response.deployment_id, 'deploy')
|
218
|
+
)
|
219
|
+
end
|
171
220
|
end
|
172
221
|
|
173
222
|
def get_deployment_status(deployment_id)
|
@@ -188,8 +237,8 @@ module DreamOps
|
|
188
237
|
return status
|
189
238
|
end
|
190
239
|
|
191
|
-
def
|
192
|
-
raise
|
240
|
+
def bail_with_fatal_error(ex)
|
241
|
+
raise ex
|
193
242
|
Thread.exit
|
194
243
|
end
|
195
244
|
|
data/lib/dream-ops/errors.rb
CHANGED
@@ -11,5 +11,35 @@ module DreamOps
|
|
11
11
|
alias_method :message, :to_s
|
12
12
|
end
|
13
13
|
|
14
|
-
class
|
14
|
+
class NoRunningInstancesError < DreamOpsError
|
15
|
+
set_status_code(10)
|
16
|
+
|
17
|
+
def initialize(stack)
|
18
|
+
@stack = stack
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"Stack \"#{@stack.name}\" has no running instances."
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class OpsWorksCommandFailedError < DreamOpsError
|
27
|
+
set_status_code(11)
|
28
|
+
|
29
|
+
def initialize(stack, deployment_id, command)
|
30
|
+
@stack = stack
|
31
|
+
@deployment_id = deployment_id
|
32
|
+
@command = command
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
[
|
37
|
+
"Stack \"#{@stack.name}\" failed running command '#{@command}'. To view the failure log, visit:",
|
38
|
+
"",
|
39
|
+
"https://console.aws.amazon.com/opsworks/home?region=#{@stack.region}#/stack/#{@stack.stack_id}/deployments/#{@deployment_id}",
|
40
|
+
].join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :message, :to_s
|
44
|
+
end
|
15
45
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module DreamOps
|
2
|
+
class Logger < Ridley::Logging::Logger
|
3
|
+
alias_method :fatal, :error
|
4
|
+
|
5
|
+
def deprecate(message)
|
6
|
+
trace = caller.join("\n\t")
|
7
|
+
warn "DEPRECATION WARNING: #{message}\n\t#{trace}"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Log an exception and its backtrace to FATAL
|
11
|
+
#
|
12
|
+
# @param [Exception] ex
|
13
|
+
def exception(ex)
|
14
|
+
fatal("#{ex.class}: #{ex}")
|
15
|
+
fatal(ex.backtrace.join("\n")) unless ex.backtrace.nil?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/dream-ops/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dream-ops
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Allen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-07-
|
11
|
+
date: 2017-07-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -152,6 +152,8 @@ files:
|
|
152
152
|
- lib/dream-ops/errors.rb
|
153
153
|
- lib/dream-ops/formatters/base.rb
|
154
154
|
- lib/dream-ops/formatters/human.rb
|
155
|
+
- lib/dream-ops/logger.rb
|
156
|
+
- lib/dream-ops/mixin/logging.rb
|
155
157
|
- lib/dream-ops/shell.rb
|
156
158
|
- lib/dream-ops/utils/zip.rb
|
157
159
|
- lib/dream-ops/version.rb
|
@@ -175,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
177
|
version: 2.0.0
|
176
178
|
requirements: []
|
177
179
|
rubyforge_project:
|
178
|
-
rubygems_version: 2.
|
180
|
+
rubygems_version: 2.6.12
|
179
181
|
signing_key:
|
180
182
|
specification_version: 4
|
181
183
|
summary: This is the summary
|