blufin-lib 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 774f67cc50886880722c063c20fd1fb52ccaed60
4
- data.tar.gz: d1dedaab78501e5d450154c63c94cb8bd41dd6f5
3
+ metadata.gz: 2e5791167393d7968f07af6998fd44e3e01682b0
4
+ data.tar.gz: 7d86180cd83561d70d074d2d1c7e7b4d10145e71
5
5
  SHA512:
6
- metadata.gz: 6f0fed9cfde5fce8f27905542207704f53fb71aac5b739083fe6815f4a30b321ad60741840a75956ae36c071df6ddba627725009ab68f814faba9fe262c4f4a7
7
- data.tar.gz: 0f68ef145d50f94c60fc270efbf8ad98c8a586e9e727508a2ea6de97f7b281701b581ced9b1652fa7850719ad794184b6027fc656e10fdae954107b3223dde6f
6
+ metadata.gz: 466b61784d9767ca6d7e32b4277f809dd7b1b79c6f97b9dc183274392d064a102451abbdaf20b9c710223b9c5565b4ed223db7b79f242081ffb7540fc3786ae3
7
+ data.tar.gz: d3bc26127ee11355383cf88b8a3eca92ab406196cd449ddfbd2430dd9f4235795cb3bd8bcec80e91bb47081ecd0d1ce47094895247f2e48b6d13f8d9e5aa6f18
data/lib/blufin-lib.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  module Blufin
2
2
 
3
3
  autoload :Arrays, 'core/arrays'
4
+ autoload :AWS, 'core/aws'
4
5
  autoload :Base, 'core/base'
5
6
  autoload :Config, 'core/config'
6
7
  autoload :DateTimeUtils, 'core/datetime_utils'
data/lib/core/aws.rb ADDED
@@ -0,0 +1,44 @@
1
+ module Blufin
2
+
3
+ module AWS
4
+
5
+ # Pulls a file from S3 and saves it to the /tmp folder.
6
+ # To avoid making multiple calls, caching is turned on by default.
7
+ # @return string (path to tmp file).
8
+ def self.download_s3_data(bucket_name, bucket_path, file: nil, profile: nil, region: nil, use_cache: true)
9
+ raise RuntimeError, 'profile cannot be nil.' if profile.nil?
10
+ raise RuntimeError, 'region cannot be nil.' if region.nil?
11
+ bucket_path = Blufin::Strings::remove_surrounding_slashes(bucket_path).strip
12
+ bucket_path_tmp = bucket_path.length > 0 ? "-#{bucket_path.gsub('/', '-')}" : ''
13
+ bucket_path_s3 = bucket_path.length > 0 ? "/#{bucket_path}" : ''
14
+ unless file.nil?
15
+ bucket_path_tmp = "#{bucket_path_tmp}-#{file}"
16
+ bucket_path_s3 = "#{bucket_path_s3}/#{file}"
17
+ end
18
+ tmp_location = "/tmp/awx-s3-cache-#{bucket_name}#{bucket_path_tmp}"
19
+ # If path/file exists and we're using cached values, simply return.
20
+ if file.nil?
21
+ return tmp_location if Blufin::Files::path_exists(tmp_location) && use_cache && Blufin::Files::get_files_in_dir(tmp_location).any?
22
+ else
23
+ return tmp_location if Blufin::Files::file_exists(tmp_location) && use_cache
24
+ end
25
+ begin
26
+ # Clear out all (possibly stale) files.
27
+ raise RuntimeError unless Blufin::Terminal::execute_proc("Wiping temp-folder: #{Blufin::Terminal::format_directory(tmp_location)}", Proc.new {
28
+ system("rm -rf #{tmp_location}") if file.nil?
29
+ system("rm #{tmp_location}") unless file.nil?
30
+ Blufin::Files::create_directory(tmp_location)
31
+ }, verbose: true)
32
+ raise RuntimeError unless Blufin::Terminal::execute("aws s3 cp s3://#{bucket_name}#{bucket_path_s3} #{tmp_location} --recursive --profile #{profile} --region #{region}", verbose: true)
33
+ tmp_location
34
+ rescue
35
+ system("rm -rf #{tmp_location}") if file.nil?
36
+ system("rm #{tmp_location}") unless file.nil?
37
+ Blufin::Terminal::error("Unable to download from S3 bucket: #{Blufin::Terminal::format_highlight("s3://#{bucket_name}#{bucket_path_s3}")}", "Either the bucket doesn't exist, you don't have permissions or something else is wrong...", true, false)
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
data/lib/core/projects.rb CHANGED
@@ -2,79 +2,75 @@ module Blufin
2
2
 
3
3
  class Projects
4
4
 
5
- SCHEMA_FILE = "#{Blufin::Base::get_base_path}#{Blufin::Base::OPT_PATH}/awx/project-schema.yml"
6
- SCRIPT_RUN = 'run'
7
- SCRIPT_TEST = 'test'
8
- SCRIPT_BUILD = 'build'
9
- SCRIPT_DEPLOY = 'deploy'
10
- RUN_SCRIPTS = 'RunScripts'
11
- TEST_SCRIPTS = 'TestScripts'
12
- BUILD_SCRIPTS = 'BuildScripts'
13
- DEPLOY_SCRIPTS = 'DeployScripts'
14
- DEPLOYMENT_ID = 'Id'
15
- TYPE = 'Type'
16
- PROJECT = 'Project'
17
- REPO_ROOT = 'RepoRoot'
18
- REPO_PATH = 'RepoPath'
19
- PORT_RANGE = 'PortRange'
20
- RUN = 'Run'
21
- TEST = 'Test'
22
- BUILD = 'Build'
23
- DEPLOY = 'Deploy'
24
- SERVERS = 'Servers'
25
- REGION = 'Region'
26
- STACK = 'Stack'
27
- ENVIRONMENTS = 'Environments'
28
- TARGETS = 'Targets'
29
- COMMANDS = 'Commands'
30
- API = 'API'
31
- TITLE = 'Title'
32
- ALIAS = 'Alias'
33
- DOMAIN = 'Domain'
5
+ SCHEMA_FILE = "#{Blufin::Base::get_base_path}#{Blufin::Base::OPT_PATH}/awx/project-schema.yml"
6
+ SCRIPT_RUN = 'run'
7
+ SCRIPT_TEST = 'test'
8
+ SCRIPT_BUILD = 'build'
9
+ SCRIPT_DEPLOY = 'deploy'
10
+ RUN_SCRIPTS = 'RunScripts'
11
+ TEST_SCRIPTS = 'TestScripts'
12
+ BUILD_SCRIPTS = 'BuildScripts'
13
+ ID = 'Id'
14
+ PROJECT_ID = 'ProjectId'
15
+ PROJECT = 'Project'
16
+ TYPE = 'Type'
17
+ REPOSITORY = 'Repository'
18
+ DEPLOYMENT = 'Deployment'
19
+ DEPLOYMENT_BUCKET = 'Bucket'
20
+ DEPLOYMENT_FILES = 'Files'
21
+ RUN = 'Run'
22
+ TEST = 'Test'
23
+ BUILD = 'Build'
24
+ COMMANDS = 'Commands'
25
+ API = 'API'
26
+ CRON = 'Cron'
27
+ WORKER = 'Worker'
28
+ LAMBDA = 'Lambda'
29
+ TITLE = 'Title'
30
+ ALIAS = 'Alias'
31
+ DOMAIN = 'Domain'
34
32
  PROJECT_NAME_PASCAL_CASE = 'ProjectNamePascalCase'
35
- PROJECT_NAME = 'ProjectName'
36
- TYPE_ALEXA = 'alexa'
37
- TYPE_API = 'api'
38
- TYPE_LAMBDA = 'lambda'
39
- TYPE_UI = 'ui'
40
- VALID_TYPES = [
33
+ PROJECT_NAME = 'ProjectName'
34
+ PORT = 'Port'
35
+ PORTS = 'Ports'
36
+ STAGE = 'Stage'
37
+ TYPE_ALEXA = 'alexa'
38
+ TYPE_API = 'api'
39
+ TYPE_LAMBDA = 'lambda'
40
+ TYPE_UI = 'ui'
41
+ VALID_TYPES = [
41
42
  TYPE_ALEXA,
42
43
  TYPE_API,
43
44
  TYPE_LAMBDA,
44
45
  TYPE_UI,
45
46
  ]
46
47
 
47
- @@projects = nil
48
+ @@projects = nil
48
49
  @@project_names = []
49
- @@scripts = nil
50
- @@deployments = nil
51
- @@apis = nil
52
- @@environments = []
50
+ @@scripts = nil
51
+ @@apis = nil
52
+ @@lambdas = nil
53
53
 
54
- # Takes a Hash that should have the APIs, Lambdas and UIs keys in the root.
54
+ # Takes a Hash that needs to have a 'Projects' key.
55
55
  # This can come from both .awx.yml['Profiles'] or .blufin.yml (root).
56
56
  # @return void
57
- def self.init(hash, file)
57
+ def self.init(projects)
58
58
  raise RuntimeError, 'Cannot run Blufin::Projects::init() more than once.' unless @@projects.nil? && @@scripts.nil?
59
+ raise RuntimeError, "Need either a Local or S3Bucket key, found neither: #{projects.keys}" unless projects.has_key?('Local') || projects.has_key?('S3Bucket')
59
60
  @@projects = {}
60
- @@scripts = {}
61
- if hash.has_key?('Projects')
62
- projects = hash['Projects']
63
- # Throw error if we have multiple sources defined, can only have 1.
64
- Blufin::Terminal::error("Found multiple sources for #{Blufin::Terminal::format_highlight(UIs)} property in: #{Blufin::Terminal::format_directory(file)}. Can #{Blufin::Terminal::format_highlight('only have one')} of the following, not both:", [Blufin::Terminal::format_invalid('Local'), Blufin::Terminal::format_invalid('S3Bucket')], true) if projects.has_key?('Local') && projects.has_key?('S3Bucket')
65
- if projects.has_key?('Local')
66
- source_file = File.expand_path(projects['Local']['File'])
67
- # Throw error if source file doesn't exist.
68
- Blufin::Terminal::error("Cannot find source file: #{Blufin::Terminal::format_directory(source_file)}") unless Blufin::Files::file_exists(source_file)
69
- # Validate the source file against the expected schema.
70
- process_source_file(source_file)
71
- elsif projects.has_key?('S3Bucket')
61
+ @@scripts = {}
62
+ if projects.has_key?('Local')
63
+ source_file = File.expand_path(projects['Local']['File'])
64
+ # Throw error if source file doesn't exist.
65
+ Blufin::Terminal::error("Cannot find source file: #{Blufin::Terminal::format_directory(source_file)}") unless Blufin::Files::file_exists(source_file)
66
+ # Validate the source file against the expected schema.
67
+ process_source_file(source_file)
68
+ elsif projects.has_key?('S3Bucket')
72
69
 
73
- # TODO - Finish this once we start running this on an EC2 instance (build/deploy server).
74
- # TODO - Whatever file we validate should be available on disk locally.
75
- # TODO - If the source is an S3 bucket, pull it down into a /tmp folder (on EC2 instance) and validate from there.
70
+ # TODO - Finish this once we start running this on an EC2 instance (build/deploy server).
71
+ # TODO - Whatever file we validate should be available on disk locally.
72
+ # TODO - If the source is an S3 bucket, pull it down into a /tmp folder (on EC2 instance) and validate from there.
76
73
 
77
- end
78
74
  end
79
75
  end
80
76
 
@@ -102,38 +98,10 @@ module Blufin
102
98
  @@apis
103
99
  end
104
100
 
105
- # Gets Environments(s).
106
- # @return Array
107
- def self.get_environments
108
- @@environments
109
- end
110
-
111
- # Get matching deployments for parameters.
101
+ # Gets Lambda(s).
112
102
  # @return Hash
113
- def self.get_deployments(project, stack, region, environment)
114
- if @@deployments.nil?
115
- @@deployments = {}
116
- if @@projects.is_a?(Hash) && @@projects.has_key?(project)
117
- project = @@projects[project]
118
- project.each do |deployment_id, data|
119
- if data.is_a?(Hash) && data.has_key?(SERVERS)
120
- servers = data[SERVERS]
121
- if servers.is_a?(Array)
122
- servers.each do |server|
123
- if server.has_key?(REGION) && server[REGION] == region
124
- if server.has_key?(STACK) && server[STACK] == stack
125
- if server.has_key?(ENVIRONMENTS) && server[ENVIRONMENTS].include?(environment)
126
- @@deployments[deployment_id] = data
127
- end
128
- end
129
- end
130
- end
131
- end
132
- end
133
- end
134
- end
135
- end
136
- @@deployments
103
+ def self.get_lambdas
104
+ @@lambdas
137
105
  end
138
106
 
139
107
  # Maps root-level property to enum.
@@ -145,8 +113,6 @@ module Blufin
145
113
  return TEST_SCRIPTS
146
114
  elsif [BUILD_SCRIPTS, BUILD].include?(script_type)
147
115
  return BUILD_SCRIPTS
148
- elsif [DEPLOY_SCRIPTS, DEPLOY].include?(script_type)
149
- return DEPLOY_SCRIPTS
150
116
  else
151
117
  raise RuntimeError, "Unhandled script type: #{script_type}"
152
118
  end
@@ -175,13 +141,13 @@ module Blufin
175
141
  end
176
142
 
177
143
  # Buffer script(s).
178
- [RUN_SCRIPTS, TEST_SCRIPTS, BUILD_SCRIPTS, DEPLOY_SCRIPTS].each do |script_type|
144
+ [RUN_SCRIPTS, TEST_SCRIPTS, BUILD_SCRIPTS].each do |script_type|
179
145
  if file_parsed.has_key?(script_type)
180
146
  if file_parsed[script_type].is_a?(Array)
181
- script_key = script_key_mapper(script_type)
147
+ script_key = script_key_mapper(script_type)
182
148
  @@scripts[script_key] = {} unless @@scripts.has_key?(script_key)
183
149
  file_parsed[script_type].each do |script|
184
- script_id = script[DEPLOYMENT_ID]
150
+ script_id = script[ID]
185
151
  # Throw error if duplicate script is found for type.
186
152
  Blufin::Terminal::error("#{Blufin::Terminal::format_highlight("#{script_type} - #{script_id}")} \xe2\x80\x94 Duplicate script found: #{Blufin::Terminal::format_invalid(script_id)}") if @@scripts[script_key].has_key?(script_id)
187
153
  @@scripts[script_key][script_id] = script
@@ -205,112 +171,102 @@ module Blufin
205
171
  file_parsed['Projects'].each do |project|
206
172
  # Validate keys are in specific order.
207
173
  expected = {
208
- DEPLOYMENT_ID => true,
209
- TYPE => true,
210
- PROJECT => true,
211
- REPO_ROOT => true,
212
- REPO_PATH => true,
213
- PORT_RANGE => false,
214
- RUN => false,
215
- TEST => false,
216
- BUILD => false,
217
- DEPLOY => false,
218
- SERVERS => false,
219
- API => false
174
+ PROJECT_ID => true,
175
+ PROJECT => true,
176
+ TYPE => true,
177
+ REPOSITORY => true,
178
+ RUN => false,
179
+ TEST => false,
180
+ BUILD => false,
181
+ API => false,
182
+ LAMBDA => false,
183
+ DEPLOYMENT => false
220
184
  }
221
185
  Blufin::Validate::assert_valid_keys(expected, project.keys, source_file)
222
- project_id = project[DEPLOYMENT_ID]
186
+ project_id = project[PROJECT_ID]
223
187
  project_name = project[PROJECT]
224
188
  project_type = project[TYPE]
225
-
226
189
  @@project_names << project_name
227
-
228
190
  # Validate Type.
229
191
  Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Invalid Project Type: #{Blufin::Terminal::format_invalid(project_type)}. Valid types are:", VALID_TYPES, true) unless VALID_TYPES.include?(project_type)
230
192
  # Validate Script(s).
231
- [RUN, TEST, BUILD, DEPLOY].each do |script_type|
193
+ [RUN, TEST, BUILD].each do |script_type|
232
194
  if project.has_key?(script_type)
233
195
  # Validate the LAMBDA functions don't need build scripts.
234
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Project type: #{Blufin::Terminal::format_highlight(TYPE_LAMBDA)} cannot have #{Blufin::Terminal::format_invalid(script_type)} property.", 'This type of project does not support this.', true) if [BUILD].include?(script_type) && project_type == TYPE_LAMBDA
235
- if project[script_type].is_a?(Array)
236
- script_key = script_key_mapper(script_type)
196
+ Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Project type: #{Blufin::Terminal::format_highlight(TYPE_LAMBDA)} does not require #{Blufin::Terminal::format_invalid(script_type)} script(s).", 'This type of project does not support this.', true) if [BUILD].include?(script_type) && project_type == TYPE_LAMBDA
197
+ if project[script_type].is_a?(Hash)
198
+ script_key = script_key_mapper(script_type)
237
199
  valid_scripts = []
238
200
  valid_scripts = @@scripts[script_key].keys if @@scripts.has_key?(script_key)
239
- project[script_type].each do |script|
240
- script_name = script['Script']
241
- unless valid_scripts.include?(script_name)
242
- error = valid_scripts.any? ? 'Valid values are:' : "There currently are no #{script_key} script(s) defined."
243
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 #{Blufin::Terminal::format_highlight(script_type)} \xe2\x80\x94 Invalid script reference: #{Blufin::Terminal::format_invalid(script_name)}. #{error}", valid_scripts)
244
- end
201
+ script = project[script_type]
202
+ script_name = script['Script']
203
+ unless valid_scripts.include?(script_name)
204
+ error = valid_scripts.any? ? 'Valid values are:' : "There currently are no #{script_key} script(s) defined."
205
+ Blufin::Terminal::error("#{project_id} \xe2\x80\x94 #{Blufin::Terminal::format_highlight(script_type)} \xe2\x80\x94 Invalid script reference: #{Blufin::Terminal::format_invalid(script_name)}. #{error}", valid_scripts)
245
206
  end
246
207
  end
247
208
  end
248
209
  end
249
- # Validate Server(s) and create new 'Targets' Hash from it.
250
- if project.has_key?(SERVERS)
251
- targets = {}
252
- project[SERVERS].each do |server|
253
- region = server['Region']
254
- stack = server['Stack']
255
- environments = server['Environments']
256
- environments.each do |environment|
257
- targets[environment] = {} unless targets.has_key?(environment)
258
- targets[environment] = {
259
- :region => region,
260
- :stack => stack,
261
- }
262
- @@environments << environment
263
- end
264
- end
265
- project[TARGETS] = targets
210
+
211
+ # Validate Deployment property.
212
+ if project.has_key?(DEPLOYMENT)
213
+ expected = {
214
+ DEPLOYMENT_BUCKET => true,
215
+ DEPLOYMENT_FILES => true
216
+ }
217
+ Blufin::Validate::assert_valid_keys(expected, project[DEPLOYMENT].keys, source_file)
266
218
  end
267
- # Validate APIs and build @@api Hash.
219
+
220
+ # Validate API property.
268
221
  if project_type == TYPE_API
269
- # Make sure we have the API & PortRange properties.
222
+ # Make sure we have the API property.
270
223
  Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(API)}", "This property is required for project(s) with type: #{API}", true) unless project.has_key?(API)
271
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(PORT_RANGE)}", "This property is required for project(s) with type: #{API}", true) unless project.has_key?(PORT_RANGE)
272
224
  # Validate keys are in specific order.
273
225
  expected = {
274
- TITLE => true,
275
- ALIAS => true,
276
- DOMAIN => true,
277
- PROJECT_NAME => true,
278
- PROJECT_NAME_PASCAL_CASE => true
226
+ TITLE => true,
227
+ ALIAS => true,
228
+ DOMAIN => true,
229
+ PROJECT_NAME => true,
230
+ PROJECT_NAME_PASCAL_CASE => true,
231
+ PORTS => true
279
232
  }
280
233
  Blufin::Validate::assert_valid_keys(expected, project[API].keys, source_file)
281
- @@apis = {} if @@apis.nil?
282
- @@apis[project[DEPLOYMENT_ID]] = {
283
- REPO_ROOT => project[REPO_ROOT],
284
- TITLE => project[API][TITLE],
285
- ALIAS => project[API][ALIAS],
286
- PROJECT_NAME => project[API][PROJECT_NAME],
287
- PROJECT_NAME_PASCAL_CASE => project[API][PROJECT_NAME_PASCAL_CASE],
288
- DOMAIN => project[API][DOMAIN],
289
- PORT_RANGE => project[PORT_RANGE]
234
+ expected_ports = {
235
+ API => true,
236
+ CRON => true,
237
+ WORKER => true
290
238
  }
239
+ Blufin::Validate::assert_valid_keys(expected_ports, project[API][PORTS].keys, source_file)
240
+ validate_ports([project[API][PORTS][API], project[API][PORTS][CRON], project[API][PORTS][WORKER]], project_id, used_ports)
241
+ # Add ports to used_ports.
242
+ used_ports[project[API][PORTS][API]] = project_id
243
+ used_ports[project[API][PORTS][CRON]] = project_id
244
+ used_ports[project[API][PORTS][WORKER]] = project_id
245
+ @@apis = {} if @@apis.nil?
246
+ @@apis[project[PROJECT_ID]] = project[API]
291
247
  else
292
248
  # Make sure we DON'T have the API key.
293
249
  Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(API)}", "This property is only allowed for project(s) with type: #{API}", true) if project.has_key?(API)
294
250
  end
295
251
 
296
- # Validate the ports range.
297
- if project.has_key?(PORT_RANGE)
298
- port_range = project[PORT_RANGE].strip
299
- # Make sure Port Range is in format: XXXX-XXXX
300
- port_range_regex = /^\d{4}-\d{4}$/
301
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Port Range does not match regex: #{Blufin::Terminal::format_invalid(port_range)}", "Must match regex: #{port_range_regex}", true) unless port_range =~ port_range_regex
302
- prs = port_range.split('-')
303
- raise RuntimeError, "Expected port range to have exactly one hyphen (-), instead got: #{port_range}" unless prs.length == 2
304
- # Make sure port range spans exactly 20 ports (by having a difference of 19).
305
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Port Range either doesn't span 20 ports or is not in correct, numerical order: #{Blufin::Terminal::format_invalid(port_range)}") unless prs[1].to_i - prs[0].to_i == 19
306
- # Make sure none of the ports conflict with other projects.
307
- (prs[0].to_i..prs[1].to_i).each do |i|
308
- if used_ports.has_key?(i)
309
- Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Port overlap detected for range: #{Blufin::Terminal::format_invalid(port_range)}", ["The conflicting project is: #{used_ports[i]}"])
310
- end
311
- end
252
+ # Validate Lambda property.
253
+ if project_type == TYPE_LAMBDA
254
+ # Make sure we have the Lambda
255
+ Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Missing property: #{Blufin::Terminal::format_highlight(LAMBDA)}", "This property is required for project(s) with type: #{LAMBDA}", true) unless project.has_key?(LAMBDA)
256
+ # Validate keys are in specific order.
257
+ expected = {
258
+ PORT => true,
259
+ STAGE => true
260
+ }
261
+ Blufin::Validate::assert_valid_keys(expected, project[LAMBDA].keys, source_file)
262
+ validate_ports([project[LAMBDA][PORT]], project_id, used_ports)
312
263
  # Add ports to used_ports.
313
- (prs[0].to_i..prs[1].to_i).each { |i| used_ports[i] = "#{Blufin::Terminal::format_highlight(project_id)} \xe2\x80\x94 #{port_range}" }
264
+ used_ports[project[LAMBDA][PORT]] = project_id
265
+ @@lambdas = {} if @@lambdas.nil?
266
+ @@lambdas[project[PROJECT_ID]] = project[LAMBDA]
267
+ else
268
+ # Make sure we DON'T have the Lambda key.
269
+ Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Property not supported: #{Blufin::Terminal::format_invalid(LAMBDA)}", "This property is only allowed for project(s) with type: #{LAMBDA}", true) if project.has_key?(LAMBDA)
314
270
  end
315
271
 
316
272
  @@projects[project_name] = {} unless @@projects.has_key?(project_name)
@@ -318,9 +274,18 @@ module Blufin
318
274
  @@projects[project_name][project_id] = project
319
275
 
320
276
  end
277
+ @@project_names.uniq!
278
+ @@project_names.sort!
279
+ end
280
+ end
321
281
 
322
- @@project_names.uniq!.sort!
323
- @@environments.uniq!.sort!
282
+ # Validate the ports. Make sure none of the ports conflict with other projects.
283
+ # @return void
284
+ def self.validate_ports(ports, project_id, used_ports)
285
+ ports.each do |port|
286
+ if used_ports.has_key?(port)
287
+ Blufin::Terminal::error("#{project_id} \xe2\x80\x94 Duplicate port detected: #{Blufin::Terminal::format_invalid(port)} ", ["The conflicting project is: #{Blufin::Terminal::format_highlight(used_ports[port])}"])
288
+ end
324
289
 
325
290
  end
326
291
 
data/lib/core/strings.rb CHANGED
@@ -89,8 +89,12 @@ module Blufin
89
89
  # Generate Random string.
90
90
  # Currently returns something like: 1ec6c763
91
91
  # @return String
92
- def self.random_string
93
- "#{SecureRandom.uuid.split('-')[0].downcase}#{SecureRandom.uuid.split('-')[0].downcase}"
92
+ def self.random_string(x = 1)
93
+ rs = ''
94
+ x.times do
95
+ rs = "#{rs}#{SecureRandom.uuid.split('-')[0].downcase}"
96
+ end
97
+ rs
94
98
  end
95
99
 
96
100
  private
data/lib/core/terminal.rb CHANGED
@@ -12,15 +12,15 @@ module Blufin
12
12
 
13
13
  extend Columnist
14
14
 
15
- MSG_INFO = 'info'
16
- MSG_WARNING = 'warning'
17
- MSG_ERROR = 'error'
18
- MSG_TODO = 'todo'
19
- MSG_AUTOMATIC = 'automatic'
20
- MSG_GENERATED = 'generated'
21
- MSG_PROCESSED = 'processed'
22
- MSG_PROGRESS = 'progress'
23
- MSG_CUSTOM = 'custom'
15
+ MSG_INFO = 'info'
16
+ MSG_WARNING = 'warning'
17
+ MSG_ERROR = 'error'
18
+ MSG_TODO = 'todo'
19
+ MSG_AUTOMATIC = 'automatic'
20
+ MSG_GENERATED = 'generated'
21
+ MSG_PROCESSED = 'processed'
22
+ MSG_PROGRESS = 'progress'
23
+ MSG_CUSTOM = 'custom'
24
24
  MSG_CUSTOM_AUTO_PAD = 'custom_auto_pad'
25
25
 
26
26
  # Runs a series of commands in the terminal.
@@ -79,8 +79,8 @@ module Blufin
79
79
  # See: https://github.com/piotrmurach/tty-spinner/blob/master/lib/tty/spinner/formats.rb (for spinner options).
80
80
  # @return void
81
81
  def self.execute(command, path = nil, capture: false, verbose: true, text: nil)
82
- text = text.is_a?(String) ? text : command
83
- t1 = Time.now
82
+ text = text.is_a?(String) ? text : command
83
+ t1 = Time.now
84
84
  spinner = TTY::Spinner.new("[:spinner] \x1B[38;5;208m#{text}#{!path.nil? ? " \x1B[38;5;246m\xe2\x86\x92 \x1B[38;5;240m#{path}" : nil}\x1B[0m", format: :dots) if verbose
85
85
  spinner.auto_spin if verbose
86
86
  path = File.expand_path('~/') if path.nil?
@@ -89,7 +89,7 @@ module Blufin
89
89
  else
90
90
  res = system("cd #{path} && #{command} > /tmp/execute-output")
91
91
  end
92
- t2 = Time.now
92
+ t2 = Time.now
93
93
  delta = "#{'%.3f' % (t2 - t1).abs}s"
94
94
  if res || capture
95
95
  spinner.success("\x1B[38;5;246m\xe2\x86\x92 \x1B[38;5;46mComplete \x1B[38;5;240m(#{delta})\x1B[0m\x1B[0m") if verbose
@@ -108,12 +108,12 @@ module Blufin
108
108
  def self.execute_proc(title, proc, verbose: true)
109
109
  raise RuntimeError, "Expected String, instead got:#{title.class}" unless title.is_a?(String)
110
110
  raise RuntimeError, "Expected proc to be an instance of Proc, instead got: #{proc.class}" unless proc.is_a?(Proc)
111
- t1 = Time.now
111
+ t1 = Time.now
112
112
  spinner = nil
113
113
  spinner = TTY::Spinner.new("[:spinner] \x1B[38;5;208m#{title}\x1B[0m", format: :dots) if verbose
114
114
  spinner.auto_spin if verbose
115
- res = proc.call
116
- t2 = Time.now
115
+ res = proc.call
116
+ t2 = Time.now
117
117
  delta = "#{'%.3f' % (t2 - t1).abs}s"
118
118
  spinner.success("\x1B[38;5;246m\xe2\x86\x92 \x1B[38;5;46mComplete \x1B[38;5;240m(#{delta})\x1B[0m\x1B[0m") if verbose && res
119
119
  spinner.error("\x1B[38;5;246m\xe2\x86\x92 \x1B[38;5;196mFailed (#{delta})\x1B[0m") if verbose && !res
@@ -159,7 +159,7 @@ module Blufin
159
159
  # Displays error and exits script by default.
160
160
  # @return void
161
161
  def self.abort(title = nil, message = nil, exit_script = true, preceding_blank_line = false)
162
- title = 'Abandon ship!' if title.nil?
162
+ title = 'Abandon ship!' if title.nil?
163
163
  message = "You have chosen to \x1B[38;5;196mABORT\x1B[38;5;240m the script." if message.nil?
164
164
  Blufin::Terminal::error(title, message, exit_script, preceding_blank_line, 'ABORT')
165
165
  end
@@ -250,7 +250,7 @@ module Blufin
250
250
  # Returns command name in consistent, uniform manner.
251
251
  # @return String
252
252
  def self.format_command(command_name)
253
- "\x1B[38;5;220m#{command_name}\x1B[0m"
253
+ "\x1B[38;5;70m$ \x1B[38;5;240m#{command_name}\x1B[0m"
254
254
  end
255
255
 
256
256
  # Returns directory name in consistent, uniform manner.
@@ -284,16 +284,16 @@ module Blufin
284
284
  def self.format_highlight(highlighted_text, capitalize = false, target: nil)
285
285
  case target
286
286
  when 'cf' # CloudFormation
287
- color = 82
287
+ color = 82
288
288
  color_end = "\x1B[38;5;246m"
289
289
  when 'cf-ctt' # CloudFormation (Creation Time Title)
290
- color = 196
290
+ color = 196
291
291
  color_end = "\x1B[38;5;246m"
292
292
  when 'cf-ct' # CloudFormation (Creation Time)
293
- color = 82
293
+ color = 82
294
294
  color_end = "\x1B[38;5;246m"
295
295
  else
296
- color = 117
296
+ color = 117
297
297
  color_end = "\x1B[0m"
298
298
  end
299
299
  if capitalize
@@ -326,7 +326,7 @@ module Blufin
326
326
  # Gives a prompt where 'y/Y' will return TRUE, 'n/N' will return false, and ANY other key will do nothing.
327
327
  # @return void
328
328
  def self.prompt_yes_no(title = nil, message = nil, confirmation_message = nil, preceding_blank_line = true)
329
- title = 'Please confirm YES or NO.' if title.nil?
329
+ title = 'Please confirm YES or NO.' if title.nil?
330
330
  confirmation_message = 'Would you like to continue?' if confirmation_message.nil?
331
331
  puts if preceding_blank_line
332
332
  puts " \x1B[38;5;231m\x1B[48;5;55m Confirm \x1B[0m #{title.nil? ? '' : "\xe2\x86\x92 "}#{title}\n"
@@ -423,16 +423,26 @@ module Blufin
423
423
  if options[0].is_a?(String)
424
424
  prompt.select(display_prompt_text(question), options, per_page: per_page)
425
425
  elsif options[0].is_a?(Hash)
426
- prompt.select(display_prompt_text(question), per_page: per_page) do |menu|
427
- options.each do |option|
428
- raise RuntimeError, "Expected option to be Hash, instead got: (#{option.class}) #{option.inspect}" unless option.is_a?(Hash)
429
- raise RuntimeError, 'Option is missing key => :text' unless option.has_key?(:text)
430
- raise RuntimeError, 'Option is missing key => :value' unless option.has_key?(:value)
431
- raise RuntimeError, "Expected :disabled option to be String, instead got: #{option[:disabled].class}" if option.has_key?(:disabled) && !option[:disabled].is_a?(String) && !option[:disabled].nil?
426
+ options_fixed = []
427
+ options.each do |option|
428
+ raise RuntimeError, "Expected option to be Hash, instead got: (#{option.class}) #{option.inspect}" unless option.is_a?(Hash)
429
+ raise RuntimeError, 'Option is missing key => :text' unless option.has_key?(:text)
430
+ raise RuntimeError, 'Option is missing key => :value' unless option.has_key?(:value)
431
+ raise RuntimeError, "Expected :disabled option to be String, instead got: #{option[:disabled].class}" if option.has_key?(:disabled) && !option[:disabled].is_a?(String) && !option[:disabled].nil?
432
+ v = option[:value]
433
+ v = 'true' if option[:value].is_a?(TrueClass)
434
+ v = 'false' if option[:value].is_a?(FalseClass)
435
+ options_fixed << {:text => option[:text], :value => v}
436
+ end
437
+ result = prompt.select(display_prompt_text(question), per_page: per_page) do |menu|
438
+ options_fixed.each do |option|
432
439
  menu.choice option[:text], option[:value] unless option.has_key?(:disabled)
433
440
  menu.choice option[:text], option[:value], disabled: "\x1B[38;5;196m#{option[:disabled]}\x1B[0m" if option.has_key?(:disabled)
434
441
  end
435
442
  end
443
+ return true if result == 'true'
444
+ return false if result == 'false'
445
+ return result
436
446
  else
437
447
  raise RuntimeError, "Expected options Array to consist of either Strings or Hashes, instead got: #{options.inspect}"
438
448
  end
@@ -493,8 +503,8 @@ module Blufin
493
503
  def self.prompt_expand(question, options)
494
504
  raise RuntimeError, "Expected Array, instead got #{options.class}" unless options.is_a?(Array)
495
505
  options.each do |option|
496
- found_key = false
497
- found_name = false
506
+ found_key = false
507
+ found_name = false
498
508
  found_value = false
499
509
  option.each do |k, v|
500
510
  case k
@@ -560,11 +570,11 @@ module Blufin
560
570
  # @return void
561
571
  def self.print_files_written(array_of_paths_or_files, message = nil, limit = 10, preceding_blank_line = true)
562
572
  raise RuntimeError, "Expected Array of files, instead got: #{array_of_paths_or_files.class}" unless array_of_paths_or_files.is_a?(Array)
563
- message = "Wrote the following #{Blufin::Terminal::format_highlight('files/directories')}" if message.nil?
564
- limit = limit.nil? ? 99999999999 : limit.to_i
573
+ message = "Wrote the following #{Blufin::Terminal::format_highlight('files/directories')}" if message.nil?
574
+ limit = limit.nil? ? 99999999999 : limit.to_i
565
575
  file_output = []
566
- file_count = 0
567
- file_more = 0
576
+ file_count = 0
577
+ file_more = 0
568
578
  array_of_paths_or_files.compact!
569
579
  array_of_paths_or_files.sort!
570
580
  array_of_paths_or_files.each do |path_or_file|
@@ -594,13 +604,13 @@ module Blufin
594
604
  # @return void
595
605
  def self.code_highlight(string, type, indent = 5)
596
606
  raise RuntimeError, "Expected String, instead got:#{string.class}" unless string.is_a?(String)
597
- type = type.downcase
607
+ type = type.downcase
598
608
  types = {
599
- 'yml' => Rouge::Lexers::YAML.new,
609
+ 'yml' => Rouge::Lexers::YAML.new,
600
610
  'json' => Rouge::Lexers::JSON.new
601
611
  }
602
612
  raise RuntimeError, "Lexer not defined for type: #{type}" unless types.has_key?(type)
603
- repeat = ' ' * indent
613
+ repeat = ' ' * indent
604
614
  formatter = Rouge::Formatters::Terminal256.new
605
615
  formatter.format(types[type].lex(string)).split("\n").each do |line|
606
616
  puts "#{repeat}#{line}"
@@ -619,14 +629,9 @@ module Blufin
619
629
  else
620
630
  messages = message.split("\n")
621
631
  end
622
- table(:border => false) do
623
- messages.each do |line|
624
- new_line = line.nil? ? '' : line.to_s.gsub("\x1B[0m", "\x1B[38;5;240m")
625
- row do
626
- column('', :align => 'left', :width => 4)
627
- column("\x1B[38;5;240m#{new_line}\x1B[0m", :align => 'left', :width => 180)
628
- end
629
- end
632
+ messages.each do |line|
633
+ new_line = line.nil? ? '' : line.to_s.gsub("\x1B[0m", "\x1B[38;5;240m")
634
+ puts " \x1B[38;5;240m#{new_line}\x1B[0m"
630
635
  end
631
636
  puts
632
637
  end
data/lib/core/tools.rb CHANGED
@@ -102,6 +102,42 @@ module Blufin
102
102
  end
103
103
  end
104
104
 
105
+ # Returns a value based on OS. If any of the values are nil, throws an Exception.
106
+ # Linux supports both LINUX and UNIX enums.
107
+ # @return string
108
+ def self.value_based_on_os(mac: nil, windows: nil, linux: nil)
109
+ begin
110
+ case Blufin::Tools::os
111
+ when Blufin::Tools::OS_WINDOWS
112
+ raise RuntimeError if windows.nil?
113
+ return windows
114
+ when Blufin::Tools::OS_MAC
115
+ raise RuntimeError if mac.nil?
116
+ return mac
117
+ when Blufin::Tools::OS_LINUX
118
+ raise RuntimeError if linux.nil?
119
+ return linux
120
+ when Blufin::Tools::OS_UNIX
121
+ raise RuntimeError if linux.nil?
122
+ return linux
123
+ else
124
+ raise RuntimeError
125
+ end
126
+ rescue => e
127
+ Blufin::Terminal::error("This command/operation is not yet supported on: #{Blufin::Terminal::format_highlight(Blufin::Tools::os)}", e.split("\n"), true)
128
+ end
129
+ end
130
+
131
+ # Throws uniform error for non-supported os'.
132
+ # @return void
133
+ def self.os_not_supported(array_of_os)
134
+ raise RuntimeError, "Expected Array, instead got: #{array_of_os.class}" unless array_of_os.is_a?(Array)
135
+ array_of_os.each { |os| raise RuntimeError, "Unsupported OS value: #{Blufin::Terminal::format_invalid(os)}" unless [OS_MAC, OS_WINDOWS, OS_LINUX, OS_UNIX].include?(os) }
136
+ current_os = os
137
+ if array_of_os.include?(current_os)
138
+ Blufin::Terminal::error("#{Blufin::Terminal::format_highlight(current_os.capitalize)} is not supported to run this command/operation.", 'Someone needs to program it and make it compatible.')
139
+ end
140
+ end
105
141
 
106
142
  end
107
143
 
data/lib/core/validate.rb CHANGED
@@ -9,7 +9,6 @@ module Blufin
9
9
  # @return null - If errors, will raise exception.
10
10
  def self.assert_valid_keys(expected, actual, description)
11
11
  raise RuntimeError, "Expected Hash, instead got: #{expected.class}" unless expected.is_a?(Hash)
12
- raise RuntimeError, "Expected Array, instead got: #{actual.class}" unless actual.is_a?(Array)
13
12
  errors = []
14
13
  required_keys = []
15
14
  optional_keys = []
@@ -48,4 +47,5 @@ module Blufin
48
47
  end
49
48
 
50
49
  end
50
+
51
51
  end
data/lib/version.rb CHANGED
@@ -1 +1 @@
1
- BLUFIN_LIB_VERSION = '1.6.1'
1
+ BLUFIN_LIB_VERSION = '1.7.0'
@@ -36,85 +36,66 @@ mapping:
36
36
  required: yes
37
37
  sequence:
38
38
  - type: str
39
- DeployScripts:
40
- type: seq
41
- sequence:
42
- - type: map
43
- mapping:
44
- Id:
45
- required: yes
46
- Commands:
47
- type: seq
48
- required: yes
49
- sequence:
50
- - type: str
51
39
  Projects:
52
40
  type: seq
53
41
  required: yes
54
42
  sequence:
55
43
  - type: map
56
44
  mapping:
57
- Id:
58
- required: yes
59
- Type:
45
+ ProjectId:
60
46
  required: yes
61
47
  Project:
62
48
  required: yes
63
- RepoRoot:
64
- required: yes
65
- RepoPath:
49
+ Type:
66
50
  required: yes
67
- PortRange:
51
+ Repository:
52
+ type: map
53
+ mapping:
54
+ Local:
55
+ Remote:
56
+ required: yes
57
+ ProjectRoot:
58
+ required: yes
68
59
  Run:
69
- type: seq
70
- sequence:
71
- - type: map
72
- mapping:
73
- Path:
74
- required: yes
75
- Script:
76
- required: yes
60
+ type: map
61
+ mapping:
62
+ Path:
63
+ required: yes
64
+ Script:
65
+ required: yes
77
66
  Test:
78
- type: seq
79
- sequence:
80
- - type: map
81
- mapping:
82
- Path:
83
- required: yes
84
- Script:
85
- required: yes
67
+ type: map
68
+ mapping:
69
+ Path:
70
+ required: yes
71
+ Script:
72
+ required: yes
86
73
  Build:
87
- type: seq
88
- sequence:
89
- - type: map
90
- mapping:
91
- Path:
92
- required: yes
93
- Script:
94
- required: yes
95
- Deploy:
96
- type: seq
97
- sequence:
98
- - type: map
99
- mapping:
100
- Path:
101
- required: yes
102
- Script:
103
- required: yes
104
- Servers:
105
- type: seq
106
- sequence:
107
- - type: map
108
- mapping:
109
- Region:
110
- required: yes
111
- Stack:
112
- required: yes
113
- Environments:
114
- type: seq
115
- required: yes
116
- sequence:
117
- - type: str
74
+ type: map
75
+ mapping:
76
+ Path:
77
+ required: yes
78
+ Script:
79
+ required: yes
80
+ Deployment:
81
+ type: map
82
+ mapping:
83
+ Bucket:
84
+ type: map
85
+ required: yes
86
+ mapping:
87
+ Name:
88
+ required: yes
89
+ Region:
90
+ required: yes
91
+ Files:
92
+ type: seq
93
+ required: yes
94
+ sequence:
95
+ - type: map
96
+ mapping:
97
+ Path:
98
+ Files:
118
99
  API:
119
100
  type: map
120
101
  mapping:
@@ -127,4 +108,25 @@ mapping:
127
108
  ProjectName:
128
109
  required: yes
129
110
  ProjectNamePascalCase:
111
+ required: yes
112
+ Ports:
113
+ type: map
114
+ required: yes
115
+ mapping:
116
+ API:
117
+ type: number
118
+ required: yes
119
+ Cron:
120
+ type: number
121
+ required: yes
122
+ Worker:
123
+ type: number
124
+ required: yes
125
+ Lambda:
126
+ type: map
127
+ mapping:
128
+ Port:
129
+ type: number
130
+ required: yes
131
+ Stage:
130
132
  required: yes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blufin-lib
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Albert Rannetsperger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-09 00:00:00.000000000 Z
11
+ date: 2019-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -130,6 +130,7 @@ extra_rdoc_files: []
130
130
  files:
131
131
  - lib/blufin-lib.rb
132
132
  - lib/core/arrays.rb
133
+ - lib/core/aws.rb
133
134
  - lib/core/base.rb
134
135
  - lib/core/config.rb
135
136
  - lib/core/datetime_utils.rb
@@ -158,7 +159,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
159
  requirements:
159
160
  - - ">="
160
161
  - !ruby/object:Gem::Version
161
- version: '2.0'
162
+ version: '2.3'
162
163
  required_rubygems_version: !ruby/object:Gem::Requirement
163
164
  requirements:
164
165
  - - ">="
@@ -166,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
167
  version: '0'
167
168
  requirements: []
168
169
  rubyforge_project:
169
- rubygems_version: 2.6.12
170
+ rubygems_version: 2.5.1
170
171
  signing_key:
171
172
  specification_version: 4
172
173
  summary: Blufin Lib