blufin-lib 1.6.1 → 1.7.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 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