dapp 0.31.28 → 0.32.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.
- checksums.yaml +4 -4
- data/bin/dapp +1 -23
- data/lib/dapp/dapp/dappfile.rb +2 -2
- data/lib/dapp/dapp/sentry.rb +0 -1
- data/lib/dapp/dimg/builder/ansible.rb +3 -1
- data/lib/dapp/dimg/builder/base.rb +2 -2
- data/lib/dapp/dimg/config/directive/shell/dimg.rb +1 -1
- data/lib/dapp/dimg/dapp/command/cleanup_repo.rb +40 -26
- data/lib/dapp/dimg/dapp/dappfile.rb +1 -1
- data/lib/dapp/dimg/dimg.rb +1 -0
- data/lib/dapp/dimg/docker_registry/base/authorization.rb +1 -16
- data/lib/dapp/helper/sha256.rb +1 -1
- data/lib/dapp/kube/kubernetes/client.rb +0 -6
- data/lib/dapp/kube/kubernetes/manager/deployment.rb +18 -30
- data/lib/dapp/version.rb +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7836539f8a917786c4db7778853720687f41b3dc80eaaddee4b7e9cf13a7e8f5
|
4
|
+
data.tar.gz: 84eec391c97ddebb98732b6dc8729f606a7cbbb2c5eaf1c4b398e4a22de30736
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e44e256557b647a045f379df38c06f88ad2911a49e691112e3ce3d970ccc4afcf8f09d2f0381478924f41560d50c58bd8fb66ce97951a4a68ae280548ef70e70
|
7
|
+
data.tar.gz: 37d984525171b58ba24a6ea18a208b87f4e50de784ed8098958c9df0c2eb9893cc3b12ec95b4f2d17ebde90c7785299dd563f1c9168dbc0f8e02aefda1d3b108
|
data/bin/dapp
CHANGED
@@ -74,29 +74,7 @@ set_gitlab_cancel_handler if ENV["GITLAB_CI"]
|
|
74
74
|
begin
|
75
75
|
begin
|
76
76
|
begin
|
77
|
-
|
78
|
-
Dapp::CLI.new.run
|
79
|
-
ensure
|
80
|
-
if Time.now.to_date < Date.parse("2019-11-01")
|
81
|
-
STDERR.puts
|
82
|
-
STDERR.puts ::Paint["###################################################################", :red, :bold]
|
83
|
-
STDERR.puts ::Paint["### DEPRECATION WARNING! ###", :red, :bold]
|
84
|
-
STDERR.puts ::Paint["### Dapp will be deprecated for use starting with 01.11.2019! ###", :red, :bold]
|
85
|
-
STDERR.puts ::Paint["### Please port your project to werf: ###", :red, :bold]
|
86
|
-
STDERR.puts ::Paint["### https://werf.io ###", :red, :bold]
|
87
|
-
STDERR.puts ::Paint["###################################################################", :red, :bold]
|
88
|
-
STDERR.puts
|
89
|
-
else
|
90
|
-
STDERR.puts
|
91
|
-
STDERR.puts ::Paint["######################################################################", :red, :bold]
|
92
|
-
STDERR.puts ::Paint["### DEPRECATION WARNING! ###", :red, :bold]
|
93
|
-
STDERR.puts ::Paint["### Dapp is deprecated for use and will not receive any support! ###", :red, :bold]
|
94
|
-
STDERR.puts ::Paint["### Please port your project to werf: ###", :red, :bold]
|
95
|
-
STDERR.puts ::Paint["### https://werf.io ###", :red, :bold]
|
96
|
-
STDERR.puts ::Paint["######################################################################", :red, :bold]
|
97
|
-
STDERR.puts
|
98
|
-
end
|
99
|
-
end
|
77
|
+
Dapp::CLI.new.run
|
100
78
|
rescue Dapp::Error::Base => e
|
101
79
|
unless (message = Dapp::Helper::NetStatus.before_error_message(e)).empty?
|
102
80
|
$stderr.puts(message)
|
data/lib/dapp/dapp/dappfile.rb
CHANGED
@@ -126,12 +126,12 @@ module Dapp
|
|
126
126
|
return if File.exists? dappfile_yml_bin_path
|
127
127
|
|
128
128
|
log_process("Downloading dappfile-yml dapp dependency") do
|
129
|
-
location = URI("https://dl.bintray.com/dapp
|
129
|
+
location = URI("https://dl.bintray.com/flant/dapp/#{::Dapp::VERSION}/dappfile-yml")
|
130
130
|
|
131
131
|
tmp_bin_path = File.join(self.class.tmp_base_dir, "dappfile-yml-#{SecureRandom.uuid}")
|
132
132
|
::Dapp::Downloader.download(location, tmp_bin_path, show_progress: true, progress_titile: dappfile_yml_bin_path)
|
133
133
|
|
134
|
-
checksum_location = URI("https://dl.bintray.com/dapp
|
134
|
+
checksum_location = URI("https://dl.bintray.com/flant/dapp/#{::Dapp::VERSION}/dappfile-yml.sha")
|
135
135
|
tmp_bin_checksum_path = tmp_bin_path + ".checksum"
|
136
136
|
::Dapp::Downloader.download(checksum_location, tmp_bin_checksum_path)
|
137
137
|
|
data/lib/dapp/dapp/sentry.rb
CHANGED
@@ -50,7 +50,6 @@ module Dapp
|
|
50
50
|
"build-dir" => self.build_dir,
|
51
51
|
"options" => self.options,
|
52
52
|
"env-options" => {
|
53
|
-
"DAPP_FORCE_SAVE_CACHE" => ENV["DAPP_FORCE_SAVE_CACHE"],
|
54
53
|
"DAPP_BIN_DAPPFILE_YML" => ENV["DAPP_BIN_DAPPFILE_YML"],
|
55
54
|
"ANSIBLE_ARGS" => ENV["ANSIBLE_ARGS"],
|
56
55
|
"DAPP_CHEF_DEBUG" => ENV["DAPP_CHEF_DEBUG"],
|
@@ -138,7 +138,9 @@ module Dapp
|
|
138
138
|
|
139
139
|
define_method("#{stage}_checksum") do
|
140
140
|
checksum_args = []
|
141
|
-
|
141
|
+
(dimg.config._ansible[stage.to_s] || []).each do |task|
|
142
|
+
checksum_args << JSON.dump(task["config"])
|
143
|
+
end
|
142
144
|
checksum_args << public_send("#{stage}_version_checksum")
|
143
145
|
_checksum checksum_args
|
144
146
|
end
|
@@ -74,8 +74,8 @@ module Dapp
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def _checksum(*args)
|
77
|
-
return if args.flatten.compact.delete_if { |val| val.respond_to?(:empty?) && val.empty? }.empty?
|
78
|
-
dimg.hashsum
|
77
|
+
return if (format_args = args.flatten.compact.delete_if { |val| val.respond_to?(:empty?) && val.empty? }).empty?
|
78
|
+
dimg.hashsum format_args
|
79
79
|
end
|
80
80
|
end # Builder::Base
|
81
81
|
end # Dimg
|
@@ -25,7 +25,7 @@ module Dapp
|
|
25
25
|
|
26
26
|
define_method "_#{stage}_version" do
|
27
27
|
return [] if (variable = instance_variable_get("@_#{stage}")).nil?
|
28
|
-
variable._version
|
28
|
+
variable._version
|
29
29
|
end
|
30
30
|
end
|
31
31
|
[:before_install, :before_setup, :install, :setup].each(&method(:stage_command_generator))
|
@@ -3,8 +3,8 @@ module Dapp
|
|
3
3
|
module Dapp
|
4
4
|
module Command
|
5
5
|
module CleanupRepo
|
6
|
-
DATE_POLICY = Time.now.to_i - 60 * 60 * 24 * 30
|
7
6
|
GIT_TAGS_LIMIT_POLICY = 10
|
7
|
+
EXPIRY_DATE_PERIOD_POLICY = 60 * 60 * 24 * 30
|
8
8
|
|
9
9
|
def cleanup_repo
|
10
10
|
lock_repo(repo = option_repo) do
|
@@ -87,36 +87,56 @@ module Dapp
|
|
87
87
|
%w(git_tag git_commit).each_with_object([]) do |scheme, dimgs_images|
|
88
88
|
dimgs_images.concat begin
|
89
89
|
detailed_dimgs_images_by_scheme[scheme].select do |dimg|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
git_own_repo.commit_exists?(dimg[:tag])
|
95
|
-
end
|
90
|
+
if scheme == 'git_tag'
|
91
|
+
consistent_git_tags.include?(dimg[:tag])
|
92
|
+
elsif scheme == 'git_commit'
|
93
|
+
git_own_repo.commit_exists?(dimg[:tag])
|
96
94
|
end
|
97
95
|
end
|
98
96
|
end
|
99
97
|
end.tap do |detailed_dimgs_images|
|
100
98
|
sorted_detailed_dimgs_images = detailed_dimgs_images.sort_by { |dimg| dimg[:created_at] }.reverse
|
101
99
|
expired_dimgs_images, not_expired_dimgs_images = sorted_detailed_dimgs_images.partition do |dimg_image|
|
102
|
-
dimg_image[:created_at] <
|
100
|
+
dimg_image[:created_at] < expiry_date_policy
|
103
101
|
end
|
104
102
|
|
105
|
-
log_step_with_indent(:"date policy (before #{DateTime.strptime(
|
103
|
+
log_step_with_indent(:"date policy (before #{DateTime.strptime(expiry_date_policy.to_s, '%s')})") do
|
106
104
|
expired_dimgs_images.each { |dimg| delete_repo_image(registry, dimg) }
|
107
105
|
end
|
108
106
|
|
109
107
|
{}.tap do |images_by_dimg|
|
110
108
|
not_expired_dimgs_images.each { |dimg| (images_by_dimg[dimg[:dimg]] ||= []) << dimg }
|
111
109
|
images_by_dimg.each do |dimg, images|
|
112
|
-
log_step_with_indent(:"limit policy (> #{
|
113
|
-
images[
|
114
|
-
end unless images[
|
110
|
+
log_step_with_indent(:"limit policy (> #{git_tag_limit_policy}) (`#{dimg || "nameless"}` dimg)") do
|
111
|
+
images[git_tag_limit_policy..-1].each { |dimg| delete_repo_image(registry, dimg) }
|
112
|
+
end unless images[git_tag_limit_policy..-1].nil?
|
115
113
|
end
|
116
114
|
end
|
117
115
|
end
|
118
116
|
end
|
119
117
|
|
118
|
+
def expiry_date_policy
|
119
|
+
@expiry_date_policy = begin
|
120
|
+
expiry_date_period_policy = policy_value('EXPIRY_DATE_PERIOD_POLICY', default: EXPIRY_DATE_PERIOD_POLICY)
|
121
|
+
Time.now.to_i - expiry_date_period_policy
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def git_tag_limit_policy
|
126
|
+
@git_tag_limit_policy ||= policy_value('GIT_TAGS_LIMIT_POLICY', default: GIT_TAGS_LIMIT_POLICY)
|
127
|
+
end
|
128
|
+
|
129
|
+
def policy_value(env_key, default:)
|
130
|
+
return default if (val = ENV[env_key]).nil?
|
131
|
+
|
132
|
+
if val.to_i.to_s == val
|
133
|
+
val.to_i
|
134
|
+
else
|
135
|
+
log_warning("WARNING: `#{env_key}` value `#{val}` is ignored (using default value `#{default}`)!")
|
136
|
+
default
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
120
140
|
def git_tag_by_consistent_git_tag(consistent_git_tag)
|
121
141
|
git_tag_by_consistent_tag_name[consistent_git_tag]
|
122
142
|
end
|
@@ -180,65 +200,59 @@ module Dapp
|
|
180
200
|
# pod items[] spec containers[] image
|
181
201
|
def pod_images(client)
|
182
202
|
client.pod_list['items'].map do |item|
|
183
|
-
|
203
|
+
item['spec']['containers'].map{ |cont| cont['image'] }
|
184
204
|
end
|
185
205
|
end
|
186
206
|
|
187
207
|
# cronjob items[] spec jobTemplate spec template spec containers[] image
|
188
208
|
def cronjob_images(client)
|
189
209
|
client.cronjob_list['items'].map do |item|
|
190
|
-
|
210
|
+
item['spec']['jobTemplate']['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
191
211
|
end
|
192
212
|
end
|
193
213
|
|
194
214
|
# daemonsets items[] spec template spec containers[] image
|
195
215
|
def daemonset_images(client)
|
196
216
|
client.daemonset_list['items'].map do |item|
|
197
|
-
|
217
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
198
218
|
end
|
199
219
|
end
|
200
220
|
|
201
221
|
# deployment items[] spec template spec containers[] image
|
202
222
|
def deployment_images(client)
|
203
223
|
client.deployment_list['items'].map do |item|
|
204
|
-
|
224
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
205
225
|
end
|
206
226
|
end
|
207
227
|
|
208
228
|
# job items[] spec template spec containers[] image
|
209
229
|
def job_images(client)
|
210
230
|
client.job_list['items'].map do |item|
|
211
|
-
|
231
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
212
232
|
end
|
213
233
|
end
|
214
234
|
|
215
235
|
# replicasets items[] spec template spec containers[] image
|
216
236
|
def replicaset_images(client)
|
217
237
|
client.replicaset_list['items'].map do |item|
|
218
|
-
|
238
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
219
239
|
end
|
220
240
|
end
|
221
241
|
|
222
242
|
# replicasets items[] spec template spec containers[] image
|
223
243
|
def statefulset_images(client)
|
224
244
|
client.statefulset_list['items'].map do |item|
|
225
|
-
|
245
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
226
246
|
end
|
227
247
|
end
|
228
248
|
|
229
249
|
# replicationcontroller items[] spec template spec containers[] image
|
230
250
|
def replicationcontroller_images(client)
|
231
251
|
client.replicationcontroller_list['items'].map do |item|
|
232
|
-
|
252
|
+
item['spec']['template']['spec']['containers'].map{ |cont| cont['image'] }
|
233
253
|
end
|
234
254
|
end
|
235
255
|
|
236
|
-
def images_from_pod_spec(pod_spec)
|
237
|
-
containers = Array(pod_spec['spec']['containers'])
|
238
|
-
initContainers = Array(pod_spec['spec']['initContainers'])
|
239
|
-
(containers + initContainers).map { |cont| cont['image'] }
|
240
|
-
end
|
241
|
-
|
242
256
|
def without_kube?
|
243
257
|
!!options[:without_kube]
|
244
258
|
end
|
data/lib/dapp/dimg/dimg.rb
CHANGED
@@ -145,6 +145,7 @@ module Dapp
|
|
145
145
|
|
146
146
|
def build_export_image!(image_name, scheme_name:)
|
147
147
|
Image::Dimg.image_by_name(name: image_name, from: last_stage.image, dapp: dapp).tap do |export_image|
|
148
|
+
export_image.untag! if export_image.built?
|
148
149
|
export_image.add_service_change_label(:'dapp-tag-scheme' => scheme_name)
|
149
150
|
export_image.add_service_change_label(:'dapp-dimg' => true)
|
150
151
|
export_image.build!
|
@@ -29,25 +29,10 @@ module Dapp
|
|
29
29
|
[:realm, :service, :scope].map do |option|
|
30
30
|
/#{option}="([[^"].]*)/ =~ header
|
31
31
|
next unless Regexp.last_match(1)
|
32
|
-
|
33
|
-
option_value = begin
|
34
|
-
if option == :scope
|
35
|
-
handle_scope_option(Regexp.last_match(1))
|
36
|
-
else
|
37
|
-
Regexp.last_match(1)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
[option, option_value]
|
32
|
+
[option, Regexp.last_match(1)]
|
42
33
|
end.compact.to_h
|
43
34
|
end
|
44
35
|
|
45
|
-
def handle_scope_option(resourcescope)
|
46
|
-
resource_type, resource_name, actions = resourcescope.split(":")
|
47
|
-
actions = actions.split(",").map { |action| action == "delete" ? "*" : action }.join(",")
|
48
|
-
[resource_type, resource_name, actions].join(":")
|
49
|
-
end
|
50
|
-
|
51
36
|
def authorization_auth
|
52
37
|
@authorization_auth ||= begin
|
53
38
|
if ::Dapp::Dapp.options_with_docker_credentials?
|
data/lib/dapp/helper/sha256.rb
CHANGED
@@ -35,12 +35,6 @@ module Dapp
|
|
35
35
|
'/apis/batch/v1' => [:job, ],
|
36
36
|
'/apis/batch/v1beta1' => [:cronjob, ],
|
37
37
|
},
|
38
|
-
'1.11' => {
|
39
|
-
'/api/v1' => [:service, :replicationcontroller, :pod, :podtemplate, ],
|
40
|
-
'/apis/apps/v1' => [:daemonset, :deployment, :replicaset, :statefulset, ],
|
41
|
-
'/apis/batch/v1' => [:job, ],
|
42
|
-
'/apis/batch/v1beta1' => [:cronjob, ],
|
43
|
-
},
|
44
38
|
'stable' => {
|
45
39
|
'/api/v1' => [:service, :replicationcontroller, :pod, :podtemplate, ],
|
46
40
|
'/apis/batch/v1' => [:job, ],
|
@@ -50,11 +50,12 @@ module Dapp
|
|
50
50
|
|
51
51
|
dapp.log_step("[#{Time.now}] Poll deployment '#{d.name}' status")
|
52
52
|
dapp.with_log_indent do
|
53
|
-
dapp.log_info("
|
54
|
-
dapp.log_info("Updated replicas: #{_field_value_for_log(d.status['updatedReplicas'])}")
|
55
|
-
dapp.log_info("Available replicas: #{_field_value_for_log(d.status['availableReplicas'])}")
|
56
|
-
dapp.log_info("Unavailable replicas: #{_field_value_for_log(d.status['unavailableReplicas'])}")
|
53
|
+
dapp.log_info("Target replicas: #{_field_value_for_log(d.replicas)}")
|
54
|
+
dapp.log_info("Updated replicas: #{_field_value_for_log(d.status['updatedReplicas'])} / #{_field_value_for_log(d.replicas)}")
|
55
|
+
dapp.log_info("Available replicas: #{_field_value_for_log(d.status['availableReplicas'])} / #{_field_value_for_log(d.replicas)}")
|
57
56
|
dapp.log_info("Ready replicas: #{_field_value_for_log(d.status['readyReplicas'])} / #{_field_value_for_log(d.replicas)}")
|
57
|
+
dapp.log_info("Old deployment.kubernetes.io/revision: #{_field_value_for_log(@revision_before_deploy)}")
|
58
|
+
dapp.log_info("Current deployment.kubernetes.io/revision: #{_field_value_for_log(d_revision)}")
|
58
59
|
end
|
59
60
|
|
60
61
|
rs = nil
|
@@ -83,16 +84,6 @@ module Dapp
|
|
83
84
|
end
|
84
85
|
|
85
86
|
if rs
|
86
|
-
dapp.with_log_indent do
|
87
|
-
dapp.log_step("Current ReplicaSet '#{rs.name}' status")
|
88
|
-
dapp.with_log_indent do
|
89
|
-
dapp.log_info("Replicas: #{_field_value_for_log(rs.status['replicas'])}")
|
90
|
-
dapp.log_info("Fully labeled replicas: #{_field_value_for_log(rs.status['fullyLabeledReplicas'])}")
|
91
|
-
dapp.log_info("Available replicas: #{_field_value_for_log(rs.status['availableReplicas'])}")
|
92
|
-
dapp.log_info("Ready replicas: #{_field_value_for_log(rs.status['readyReplicas'])} / #{_field_value_for_log(d.replicas)}")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
87
|
# Pod'ы связанные с активным ReplicaSet
|
97
88
|
rs_pods = dapp.kubernetes.pod_list['items']
|
98
89
|
.map {|spec| Kubernetes::Client::Resource::Pod.new(spec)}
|
@@ -177,14 +168,19 @@ module Dapp
|
|
177
168
|
end # with_log_indent
|
178
169
|
end
|
179
170
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
171
|
+
if d_revision && d.replicas
|
172
|
+
if d.replicas == 0
|
173
|
+
break
|
174
|
+
else
|
175
|
+
break if begin
|
176
|
+
d.status['updatedReplicas'] &&
|
177
|
+
d.status['availableReplicas'] &&
|
178
|
+
d.status['readyReplicas'] &&
|
179
|
+
(d.status['updatedReplicas'] >= d.replicas) &&
|
180
|
+
(d.status['availableReplicas'] >= d.replicas) &&
|
181
|
+
(d.status['readyReplicas'] >= d.replicas)
|
182
|
+
end
|
183
|
+
end
|
188
184
|
end
|
189
185
|
|
190
186
|
sleep 5
|
@@ -193,14 +189,6 @@ module Dapp
|
|
193
189
|
end
|
194
190
|
end
|
195
191
|
|
196
|
-
def is_deployment_ready(d)
|
197
|
-
d.status.key?("readyReplicas") && d.status["readyReplicas"] >= d.replicas
|
198
|
-
end
|
199
|
-
|
200
|
-
def is_replicaset_ready(d, rs)
|
201
|
-
rs.status.key?("readyReplicas") && rs.status["readyReplicas"] >= d.replicas
|
202
|
-
end
|
203
|
-
|
204
192
|
private
|
205
193
|
|
206
194
|
def _field_value_for_log(value)
|
data/lib/dapp/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.32.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dmitry Stolyarov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mixlib-shellout
|
@@ -234,14 +234,14 @@ dependencies:
|
|
234
234
|
requirements:
|
235
235
|
- - "~>"
|
236
236
|
- !ruby/object:Gem::Version
|
237
|
-
version: '
|
237
|
+
version: '1.7'
|
238
238
|
type: :development
|
239
239
|
prerelease: false
|
240
240
|
version_requirements: !ruby/object:Gem::Requirement
|
241
241
|
requirements:
|
242
242
|
- - "~>"
|
243
243
|
- !ruby/object:Gem::Version
|
244
|
-
version: '
|
244
|
+
version: '1.7'
|
245
245
|
- !ruby/object:Gem::Dependency
|
246
246
|
name: rake
|
247
247
|
requirement: !ruby/object:Gem::Requirement
|
@@ -744,7 +744,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
744
744
|
version: 2.5.0
|
745
745
|
requirements: []
|
746
746
|
rubyforge_project:
|
747
|
-
rubygems_version: 2.7.
|
747
|
+
rubygems_version: 2.7.7
|
748
748
|
signing_key:
|
749
749
|
specification_version: 4
|
750
750
|
summary: Build docker packaged apps using chef or shell
|