prima-twig 1.2.6 → 1.3.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/twig-packer-builder +84 -0
- data/bin/twig-update-ami +48 -114
- data/lib/prima_aws_client.rb +26 -0
- metadata +14 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94183c3b380822569fa755c6cd914da1eb15d36378d93a8faf827cf8b2a8a119
|
4
|
+
data.tar.gz: 865c21d79254b4b4ad2e8034d665f74301585fd50f4fd20b019e0c6bde977183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7604f33c35162fde446fb5e91e92451745d7eab126d09f417c36c835254949f2690c77c3f4ebbd8248c885c6c19b7786498da0cfbfe44adcb798b5641e53613f
|
7
|
+
data.tar.gz: 24f093ea1a89deef5debd86afdf69b5dbb43f5f1a6aef9bc68f8a8a0b9e2e938baee20ba897116d8a2d66e5e8d7b8d60a9e1f6af267973003e7357c34d138884
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require_relative '../lib/prima_twig'
|
5
|
+
require 'launchy'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
class TwigPackerBuilder
|
9
|
+
include Command
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
output 'Checking for new gem releases...'
|
13
|
+
unless `gem outdated`.lines.grep(/^prima-twig \(.*\)/).empty?
|
14
|
+
exec "gem update prima-twig && twig update-ami #{ARGV.join ' '}"
|
15
|
+
end
|
16
|
+
@templates_path = "#{Dir.pwd}/amis"
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute!(args)
|
20
|
+
@template_name = args[0]
|
21
|
+
@env = args[1]
|
22
|
+
@country = args[2]
|
23
|
+
|
24
|
+
File.open("#{Dir.pwd}/ami_state.yml", 'r') do |f|
|
25
|
+
@config = YAML.load(f.read)
|
26
|
+
end
|
27
|
+
|
28
|
+
@country_conf = @config['countries'].detect { |country| country['name'] == @country }
|
29
|
+
stop_if(@country_conf.nil?, "Cannot find country #{@country} inside ami_state.yml, exiting...".red)
|
30
|
+
|
31
|
+
@ami_conf = @country_conf['amis'].detect { |ami| ami['template'] == @template_name and ami['env'] == @env }
|
32
|
+
stop_if(@ami_conf.nil?, "Cannot find an ami in #{@country} generated from #{@template_name} and env #{@env} inside ami_state.yml, exiting...".red)
|
33
|
+
|
34
|
+
output "Starting update process with #{@template_name} in env #{@env} in country #{@country}".light_green
|
35
|
+
output 'running packer (this could take some time)'.light_green
|
36
|
+
new_ami_id = execute_packer
|
37
|
+
stop_if(new_ami_id.to_s.empty?, 'Failed to generate AMI!'.red)
|
38
|
+
|
39
|
+
output "new ami id: #{new_ami_id}".light_green
|
40
|
+
output "ami id that can be replaced: #{@ami_conf['id']}".light_green
|
41
|
+
output "you can run \"aws-vault exec YOUR_CONTRY_PROFILE -- twig-update-ami #{@ami_conf['id']} #{new_ami_id}\" to update all stacks".light_green
|
42
|
+
output 'Done'.light_green
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def execute_packer
|
48
|
+
execute_command "AWS_MAX_ATTEMPTS=90 AWS_POLL_DELAY_SECONDS=60 packer build -var env=#{@env} -var teams_mapping=#{@ami_conf['teams_mapping']} -var country=#{@country} -var aws_account=#{@country_conf['aws_account']} -machine-readable #{@templates_path}/#{@template_name} | tee build.log"
|
49
|
+
|
50
|
+
`grep 'artifact,0,id' build.log | cut -d, -f6 | cut -d: -f2`.sub(/\n/, '')
|
51
|
+
end
|
52
|
+
|
53
|
+
def help_content
|
54
|
+
<<-HELP
|
55
|
+
|
56
|
+
twig-packer-builder
|
57
|
+
===========
|
58
|
+
|
59
|
+
Creates AMIs using umami's templates
|
60
|
+
|
61
|
+
Synopsis
|
62
|
+
--------
|
63
|
+
|
64
|
+
twig-packer-builder
|
65
|
+
|
66
|
+
Description
|
67
|
+
-----------
|
68
|
+
|
69
|
+
from umami main folder run
|
70
|
+
`aws-vault exec AWS_PROFILE_WITH_ACCESS_TO_COMMON_ACCOUNT -- twig-update-ami ${AMI_TEMPLATE} ${ENV} ${COUNTRY}`
|
71
|
+
|
72
|
+
Subcommand for Twig: <http://rondevera.github.io/twig/>
|
73
|
+
HELP
|
74
|
+
end
|
75
|
+
|
76
|
+
args = ARGV.dup
|
77
|
+
|
78
|
+
if args.include?('--help')
|
79
|
+
puts help_content
|
80
|
+
exit
|
81
|
+
end
|
82
|
+
|
83
|
+
TwigPackerBuilder.new.execute!(args)
|
84
|
+
end
|
data/bin/twig-update-ami
CHANGED
@@ -1,164 +1,105 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
|
-
require_relative '../lib/prima_twig
|
5
|
-
require_relative '../lib/prima_aws_client
|
4
|
+
require_relative '../lib/prima_twig'
|
5
|
+
require_relative '../lib/prima_aws_client'
|
6
6
|
require 'launchy'
|
7
|
-
require '
|
8
|
-
require 'aws-sdk-s3'
|
7
|
+
require 'yaml'
|
9
8
|
|
10
9
|
class TwigUpdateAmi
|
11
10
|
include Command
|
12
11
|
include PrimaAwsClient
|
12
|
+
|
13
13
|
def initialize
|
14
|
-
output '
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
14
|
+
output 'Checking for new gem releases...'
|
15
|
+
unless `gem outdated`.lines.grep(/^prima-twig \(.*\)/).empty?
|
16
|
+
exec "gem update prima-twig && twig update-ami #{ARGV.join ' '}"
|
17
|
+
end
|
18
|
+
@state_path = "#{Dir.pwd}/ami_state.yml"
|
19
19
|
end
|
20
20
|
|
21
21
|
def execute!(args)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def update_amis(ami_template, ami_id, ami_name, ami_description, env)
|
28
|
-
output "updating instance definition #{ami_template}".light_green
|
29
|
-
Dir.chdir 'ami'
|
30
|
-
update_instance_name(ami_id, ami_name, ami_description, ami_template)
|
31
|
-
output 'running packer update (this could take some time)'.light_green
|
32
|
-
ami_mappings = JSON.parse(@s3.get_object(bucket: @s3_bucket, key: "ami/ami-mappings.json")["body"].read())
|
33
|
-
|
34
|
-
ami_mapping = nil
|
35
|
-
ami_mappings.each do |item|
|
36
|
-
if item['ami_template'].eql?(ami_template) and item['env'].eql?(env)
|
37
|
-
ami_mapping = item
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
stop_if(ami_mapping == nil, "No AMI found with parameters #{ami_template} and #{env}")
|
22
|
+
old_ami = args[0]
|
23
|
+
new_ami = args[1]
|
42
24
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
stop_if(new_ami_id.to_s.empty?, 'Failed to generate AMI!'.red)
|
47
|
-
output "new ami id: #{new_ami_id}"
|
48
|
-
|
49
|
-
output 'searching for ami to update...'
|
50
|
-
old_amis = update_ami_mappings(ami_mappings, ami_template, env, new_ami_id)
|
51
|
-
stop_if(old_amis.empty?, "No ami to update! No #{ami_template} in env #{env}, exiting".yellow)
|
52
|
-
|
53
|
-
output "retrieving stacks that uses old ami ids: #{old_amis}"
|
54
|
-
exports = list_exports()
|
55
|
-
stacks = get_stacks_from_exports(exports, old_amis)
|
56
|
-
stop_if(stacks.empty?, "No stack to update found! This means that ami-mapping file is not in sync, please check manually")
|
25
|
+
output "retrieving stacks that uses old ami #{old_ami}".light_green
|
26
|
+
stacks = get_stacks_from_exports(list_exports, old_ami)
|
27
|
+
stop_if(stacks.empty?, 'No stack to update! Please check manually'.red)
|
57
28
|
|
58
29
|
stacks.each do |stack|
|
59
|
-
output "processing stack #{stack}"
|
30
|
+
output "processing stack #{stack}".light_green
|
60
31
|
if stack.include?('qa')
|
61
|
-
output "skipping stack #{stack} because is a qa"
|
32
|
+
output "skipping stack #{stack} because is a qa".yellow
|
62
33
|
next
|
63
34
|
else
|
64
35
|
stack_parameters = get_stack_parameters(stack)
|
65
|
-
stack_parameters = update_stack_parameters(stack_parameters,
|
66
|
-
|
67
|
-
|
68
|
-
stack_template = File.read("./cloudformation/stacks/batch/compute-environment-offsite-backups.yml")
|
69
|
-
else
|
70
|
-
stack_template = File.read("./cloudformation/stacks/batch/compute-environment.yml")
|
71
|
-
end
|
72
|
-
else
|
73
|
-
stack_parameters = update_stack_parameters(stack_parameters, "DesiredCapacity", get_desired_capacity(stack).to_s)
|
74
|
-
stack_template = File.read("./cloudformation/stacks/asg/#{stack.to_s.split("/")[1]}.yml")
|
36
|
+
stack_parameters = update_stack_parameters(stack_parameters, 'AMIID', new_ami)
|
37
|
+
unless stack.include?('batch')
|
38
|
+
stack_parameters = update_stack_parameters(stack_parameters, 'DesiredCapacity', get_desired_capacity(stack).to_s)
|
75
39
|
end
|
76
|
-
|
40
|
+
|
41
|
+
update_stack_reuse_template(stack, stack_parameters)
|
77
42
|
end
|
78
43
|
end
|
79
44
|
|
80
45
|
stacks.each do |stack|
|
81
|
-
if stack.include?('qa')
|
82
|
-
|
46
|
+
next if stack.include?('qa')
|
47
|
+
|
48
|
+
wait_for_stack_ready(stack, %w[CREATE_FAILED ROLLBACK_IN_PROGRESS ROLLBACK_FAILED DELETE_IN_PROGRESS DELETE_FAILED DELETE_COMPLETE UPDATE_ROLLBACK_FAILED UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS UPDATE_ROLLBACK_COMPLETE ROLLBACK_COMPLETE])
|
49
|
+
end
|
50
|
+
|
51
|
+
output 'Saving new ami in ami_state.yml'.light_green
|
52
|
+
File.open(@state_path, 'r') do |f|
|
53
|
+
@config = YAML.load(f.read)
|
54
|
+
end
|
55
|
+
|
56
|
+
@config['countries'].each do |country|
|
57
|
+
country['amis'].each do |ami|
|
58
|
+
ami['id'] = new_ami if ami['id'] == old_ami
|
83
59
|
end
|
84
|
-
wait_for_stack_ready(stack, ['CREATE_FAILED', 'ROLLBACK_IN_PROGRESS', 'ROLLBACK_FAILED', 'DELETE_IN_PROGRESS', 'DELETE_FAILED', 'DELETE_COMPLETE', 'UPDATE_ROLLBACK_FAILED', 'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS', 'UPDATE_ROLLBACK_COMPLETE', 'ROLLBACK_COMPLETE'])
|
85
60
|
end
|
86
61
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
f.write(mapping_file)
|
91
|
-
@s3.put_object(bucket: @s3_bucket, key: "ami/ami-mappings.json", body: mapping_file)
|
62
|
+
File.open(@state_path, 'w+') do |f|
|
63
|
+
yaml = YAML.dump(@config)
|
64
|
+
f.write(yaml)
|
92
65
|
end
|
93
66
|
|
94
|
-
output 'Update finished! ( ͡° ͜ʖ ͡°)'
|
67
|
+
output 'Update finished! ( ͡° ͜ʖ ͡°)'.light_green
|
95
68
|
end
|
96
69
|
|
97
|
-
|
70
|
+
private
|
71
|
+
|
72
|
+
def get_stacks_from_exports(exports, old_ami)
|
98
73
|
stacks = []
|
99
|
-
|
100
|
-
|
101
|
-
if export.value.eql?(old_ami)
|
102
|
-
stacks.insert(0,export.exporting_stack_id)
|
103
|
-
end
|
104
|
-
end
|
74
|
+
exports.each do |export|
|
75
|
+
stacks.insert(0, export.exporting_stack_id) if export.value.eql?(old_ami)
|
105
76
|
end
|
106
77
|
stacks
|
107
78
|
end
|
108
79
|
|
109
|
-
def update_ami_mappings(mappings, ami_template, env, new_ami_id)
|
110
|
-
old_values = []
|
111
|
-
mappings.each do |item|
|
112
|
-
if item['ami_template'].eql?(ami_template) and item['env'].eql?(env)
|
113
|
-
old_values.insert(0,item['ami_id'])
|
114
|
-
item['ami_id'] = new_ami_id
|
115
|
-
end
|
116
|
-
end
|
117
|
-
old_values.uniq
|
118
|
-
end
|
119
|
-
|
120
80
|
def update_stack_parameters(stack_parameters, key, value)
|
121
81
|
stack_parameters.each do |param|
|
122
|
-
if param.parameter_key == key
|
123
|
-
param.parameter_value = value
|
124
|
-
end
|
82
|
+
param.parameter_value = value if param.parameter_key == key
|
125
83
|
end
|
126
84
|
stack_parameters
|
127
85
|
end
|
128
86
|
|
129
|
-
def update_instance_name(ami_id, ami_name, ami_description, ecs_json_path)
|
130
|
-
ecs_json = JSON.parse File.read(ecs_json_path)
|
131
|
-
|
132
|
-
ecs_json['builders'][0]['source_ami'] = ami_id
|
133
|
-
ecs_json['builders'][0]['ami_name'] = ami_name
|
134
|
-
ecs_json['builders'][0]['ami_description'] = ami_description
|
135
|
-
|
136
|
-
File.open ecs_json_path, 'w' do |f|
|
137
|
-
f.write(JSON.pretty_generate(ecs_json))
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
87
|
def get_desired_capacity(stack_name)
|
142
88
|
stack_outputs = get_stack_outputs(stack_name)
|
143
89
|
stack_outputs.each do |out|
|
144
|
-
if out.export_name.include?('EC2Fleet')
|
90
|
+
if out.export_name.include?('EC2Fleet') || out.export_name.include?('AutoScalingGroup') || out.export_name.include?('NodeGroup')
|
145
91
|
return get_autoscaling_capacity(out.output_value)
|
146
92
|
end
|
147
93
|
end
|
148
94
|
end
|
149
95
|
|
150
|
-
def update_packer(json_filename, env, teams, country)
|
151
|
-
execute_command "AWS_MAX_ATTEMPTS=90 AWS_POLL_DELAY_SECONDS=60 packer build -var datadog_apikey=`biscuit get -f ../configs/secrets/common.yml common_production_apikey_datadog` -var github_token=`biscuit get -f ../configs/secrets/common.yml common_private_repo_github_token` -var drone_key=\"`biscuit get -f ../configs/secrets/common.yml drone_license_key`\" -var env=#{env} -var teams_mapping=#{teams} -var country=#{country} -machine-readable ./#{json_filename} | tee build.log"
|
152
|
-
`grep 'artifact,0,id' build.log | cut -d, -f6 | cut -d: -f2`.sub(/\n/, '')
|
153
|
-
end
|
154
|
-
|
155
96
|
def help_content
|
156
97
|
<<-HELP
|
157
98
|
|
158
99
|
twig-update-ami
|
159
100
|
===========
|
160
101
|
|
161
|
-
Updates
|
102
|
+
Updates AutoScalingGroups/BatchComputeEnvs with a new AMI
|
162
103
|
|
163
104
|
Synopsis
|
164
105
|
--------
|
@@ -168,8 +109,8 @@ class TwigUpdateAmi
|
|
168
109
|
Description
|
169
110
|
-----------
|
170
111
|
|
171
|
-
from
|
172
|
-
`twig-update-ami ${
|
112
|
+
from tsunami main folder run
|
113
|
+
`aws-vault exec AWS_PROFILE_WITH_ACCESS_TO_COUNTRY_ACCOUNT -- twig-update-ami ${OLD_AMI} ${NEW_AMI}`
|
173
114
|
|
174
115
|
Subcommand for Twig: <http://rondevera.github.io/twig/>
|
175
116
|
Author: Eugenio Laghi <https://github.com/eugeniolaghi>
|
@@ -177,13 +118,6 @@ class TwigUpdateAmi
|
|
177
118
|
HELP
|
178
119
|
end
|
179
120
|
|
180
|
-
class ::Hash
|
181
|
-
def deep_merge(second)
|
182
|
-
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
|
183
|
-
self.merge(second.to_h, &merger)
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
121
|
args = ARGV.dup
|
188
122
|
|
189
123
|
if args.include?('--help')
|
data/lib/prima_aws_client.rb
CHANGED
@@ -175,6 +175,32 @@ module PrimaAwsClient
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
+
def update_stack_reuse_template(stack_name, parameters = [], tags = [], role = nil)
|
179
|
+
cf_args = {
|
180
|
+
stack_name: stack_name,
|
181
|
+
use_previous_template: true,
|
182
|
+
parameters: parameters,
|
183
|
+
tags: tags,
|
184
|
+
capabilities: ['CAPABILITY_IAM']
|
185
|
+
}
|
186
|
+
|
187
|
+
if role != nil then
|
188
|
+
cf_args.merge!(role_arn: role)
|
189
|
+
end
|
190
|
+
|
191
|
+
begin
|
192
|
+
cf_client.update_stack(cf_args)
|
193
|
+
rescue Aws::CloudFormation::Errors::Throttling => e
|
194
|
+
output 'Throttling, retrying in 15 seconds'.red
|
195
|
+
sleep 15
|
196
|
+
update_stack(stack_name, template_body, parameters = [], tags = [])
|
197
|
+
rescue Aws::CloudFormation::Errors::ValidationError => e
|
198
|
+
raise e
|
199
|
+
else
|
200
|
+
output "L'update dello stack #{stack_name} è stato avviato".green
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
178
204
|
def stack_exists?(stack_name)
|
179
205
|
begin
|
180
206
|
cf_client.describe_stacks(stack_name: stack_name)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prima-twig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matteo Giachino
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2020-
|
17
|
+
date: 2020-11-16 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: aws-sdk-autoscaling
|
@@ -73,21 +73,21 @@ dependencies:
|
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: '1'
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
|
-
name: aws-sdk-
|
76
|
+
name: aws-sdk-core
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
79
|
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
81
|
+
version: '3'
|
82
82
|
type: :runtime
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
88
|
+
version: '3'
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
|
-
name: aws-sdk-
|
90
|
+
name: aws-sdk-ec2
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
93
|
- - "~>"
|
@@ -101,7 +101,7 @@ dependencies:
|
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '1'
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
|
-
name: aws-sdk-
|
104
|
+
name: aws-sdk-ecs
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
@@ -115,7 +115,7 @@ dependencies:
|
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: '1'
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
|
-
name: aws-sdk-
|
118
|
+
name: aws-sdk-elasticloadbalancingv2
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
121
|
- - "~>"
|
@@ -129,19 +129,19 @@ dependencies:
|
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '1'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
|
-
name: aws-sdk-
|
132
|
+
name: aws-sdk-s3
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
134
134
|
requirements:
|
135
135
|
- - "~>"
|
136
136
|
- !ruby/object:Gem::Version
|
137
|
-
version: '
|
137
|
+
version: '1'
|
138
138
|
type: :runtime
|
139
139
|
prerelease: false
|
140
140
|
version_requirements: !ruby/object:Gem::Requirement
|
141
141
|
requirements:
|
142
142
|
- - "~>"
|
143
143
|
- !ruby/object:Gem::Version
|
144
|
-
version: '
|
144
|
+
version: '1'
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
146
|
name: colorize
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -286,11 +286,13 @@ description: Our tools to manage git and github
|
|
286
286
|
email: matteo.giachino@prima.it
|
287
287
|
executables:
|
288
288
|
- twig-feature
|
289
|
+
- twig-packer-builder
|
289
290
|
- twig-update-ami
|
290
291
|
extensions: []
|
291
292
|
extra_rdoc_files: []
|
292
293
|
files:
|
293
294
|
- bin/twig-feature
|
295
|
+
- bin/twig-packer-builder
|
294
296
|
- bin/twig-update-ami
|
295
297
|
- lib/command.rb
|
296
298
|
- lib/prima_aws_client.rb
|
@@ -314,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
314
316
|
- !ruby/object:Gem::Version
|
315
317
|
version: '0'
|
316
318
|
requirements: []
|
317
|
-
rubygems_version: 3.0.
|
319
|
+
rubygems_version: 3.0.3
|
318
320
|
signing_key:
|
319
321
|
specification_version: 4
|
320
322
|
summary: The Prima twig toolbelt
|