firespring_dev_commands 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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +83 -0
  4. data/lib/firespring_dev_commands/audit/report/item.rb +33 -0
  5. data/lib/firespring_dev_commands/audit/report/levels.rb +36 -0
  6. data/lib/firespring_dev_commands/audit/report.rb +49 -0
  7. data/lib/firespring_dev_commands/aws/account/info.rb +15 -0
  8. data/lib/firespring_dev_commands/aws/account.rb +164 -0
  9. data/lib/firespring_dev_commands/aws/cloudformation/parameters.rb +26 -0
  10. data/lib/firespring_dev_commands/aws/cloudformation.rb +188 -0
  11. data/lib/firespring_dev_commands/aws/codepipeline.rb +96 -0
  12. data/lib/firespring_dev_commands/aws/credentials.rb +136 -0
  13. data/lib/firespring_dev_commands/aws/login.rb +131 -0
  14. data/lib/firespring_dev_commands/aws/parameter.rb +32 -0
  15. data/lib/firespring_dev_commands/aws/profile.rb +55 -0
  16. data/lib/firespring_dev_commands/aws/s3.rb +42 -0
  17. data/lib/firespring_dev_commands/aws.rb +10 -0
  18. data/lib/firespring_dev_commands/boolean.rb +7 -0
  19. data/lib/firespring_dev_commands/common.rb +112 -0
  20. data/lib/firespring_dev_commands/daterange.rb +171 -0
  21. data/lib/firespring_dev_commands/docker/compose.rb +271 -0
  22. data/lib/firespring_dev_commands/docker/status.rb +38 -0
  23. data/lib/firespring_dev_commands/docker.rb +276 -0
  24. data/lib/firespring_dev_commands/dotenv.rb +6 -0
  25. data/lib/firespring_dev_commands/env.rb +38 -0
  26. data/lib/firespring_dev_commands/eol/product_version.rb +86 -0
  27. data/lib/firespring_dev_commands/eol.rb +58 -0
  28. data/lib/firespring_dev_commands/git/info.rb +13 -0
  29. data/lib/firespring_dev_commands/git.rb +420 -0
  30. data/lib/firespring_dev_commands/jira/issue.rb +33 -0
  31. data/lib/firespring_dev_commands/jira/project.rb +13 -0
  32. data/lib/firespring_dev_commands/jira/user/type.rb +20 -0
  33. data/lib/firespring_dev_commands/jira/user.rb +31 -0
  34. data/lib/firespring_dev_commands/jira.rb +78 -0
  35. data/lib/firespring_dev_commands/logger.rb +8 -0
  36. data/lib/firespring_dev_commands/node/audit.rb +39 -0
  37. data/lib/firespring_dev_commands/node.rb +107 -0
  38. data/lib/firespring_dev_commands/php/audit.rb +71 -0
  39. data/lib/firespring_dev_commands/php.rb +109 -0
  40. data/lib/firespring_dev_commands/rake.rb +24 -0
  41. data/lib/firespring_dev_commands/ruby/audit.rb +30 -0
  42. data/lib/firespring_dev_commands/ruby.rb +113 -0
  43. data/lib/firespring_dev_commands/second.rb +22 -0
  44. data/lib/firespring_dev_commands/tar/pax_header.rb +49 -0
  45. data/lib/firespring_dev_commands/tar/type_flag.rb +49 -0
  46. data/lib/firespring_dev_commands/tar.rb +149 -0
  47. data/lib/firespring_dev_commands/templates/aws.rb +84 -0
  48. data/lib/firespring_dev_commands/templates/base_interface.rb +54 -0
  49. data/lib/firespring_dev_commands/templates/ci.rb +138 -0
  50. data/lib/firespring_dev_commands/templates/docker/application.rb +177 -0
  51. data/lib/firespring_dev_commands/templates/docker/default.rb +200 -0
  52. data/lib/firespring_dev_commands/templates/docker/node/application.rb +145 -0
  53. data/lib/firespring_dev_commands/templates/docker/php/application.rb +190 -0
  54. data/lib/firespring_dev_commands/templates/docker/ruby/application.rb +146 -0
  55. data/lib/firespring_dev_commands/templates/eol.rb +23 -0
  56. data/lib/firespring_dev_commands/templates/git.rb +147 -0
  57. data/lib/firespring_dev_commands/version.rb +11 -0
  58. data/lib/firespring_dev_commands.rb +21 -0
  59. metadata +436 -0
@@ -0,0 +1,171 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+
4
+ module Dev
5
+ # Module containing methods for calculating start/stop dates for given ranges
6
+ module DateRange
7
+ # Class contains methods for calculating a date range with an hourly interval
8
+ class Hourly
9
+ attr_accessor :date
10
+
11
+ def initialize(date = nil)
12
+ @date = date || DateTime.now
13
+ end
14
+
15
+ # The hour interval previous to the current date
16
+ def previous
17
+ raise 'not implemented'
18
+ end
19
+
20
+ # The hour interval for the current date
21
+ def current
22
+ raise 'not implemented'
23
+ end
24
+
25
+ # The hour interval after the current date
26
+ def next
27
+ raise 'not implemented'
28
+ end
29
+ end
30
+
31
+ # Class contains methods for calculating a date range with an daily interval
32
+ class Daily
33
+ attr_accessor :date
34
+
35
+ def initialize(date = nil)
36
+ @date = date || DateTime.now
37
+ end
38
+
39
+ # The daily interval previous to the current date
40
+ def previous
41
+ @date = date.beginning_of_day - 1
42
+ current
43
+ end
44
+
45
+ # The daily interval for the current date
46
+ def current
47
+ start = date.beginning_of_day
48
+ stop = date.end_of_day
49
+ [start, stop]
50
+ end
51
+
52
+ # The daily interval after the current date
53
+ def next
54
+ @date = date.end_of_day + 1
55
+ current
56
+ end
57
+ end
58
+
59
+ # Class contains methods for calculating a date range with an weekly interval
60
+ class Weekly
61
+ attr_accessor :date
62
+
63
+ def initialize(date = nil)
64
+ @date = date || DateTime.now
65
+ end
66
+
67
+ # The weekly interval previous to the current date
68
+ def previous
69
+ @date = date.beginning_of_week - 1
70
+ current
71
+ end
72
+
73
+ # The weekly interval for the current date
74
+ def current
75
+ start = date.beginning_of_week
76
+ stop = date.end_of_week
77
+ [start, stop]
78
+ end
79
+
80
+ # The weekly interval after the current date
81
+ def next
82
+ @date = date.end_of_week + 1
83
+ current
84
+ end
85
+ end
86
+
87
+ # Class contains methods for calculating a date range with an monthly interval
88
+ class Monthly
89
+ attr_accessor :date
90
+
91
+ def initialize(date = nil)
92
+ @date = date || DateTime.now
93
+ end
94
+
95
+ # The monthly interval previous to the current date
96
+ def previous
97
+ @date = date.beginning_of_month - 1
98
+ current
99
+ end
100
+
101
+ # The monthly interval for the current date
102
+ def current
103
+ start = date.beginning_of_month
104
+ stop = date.end_of_month
105
+ [start, stop]
106
+ end
107
+
108
+ # The monthly interval after the current date
109
+ def next
110
+ @date = date.end_of_month + 1
111
+ current
112
+ end
113
+ end
114
+
115
+ # Class contains methods for calculating a date range with an quarterly interval
116
+ class Quarterly
117
+ attr_accessor :date
118
+
119
+ def initialize(date = nil)
120
+ @date = date || DateTime.now
121
+ end
122
+
123
+ # The quarterly interval previous to the current date
124
+ def previous
125
+ @date = date.beginning_of_quarter - 1
126
+ current
127
+ end
128
+
129
+ # The quarterly interval for the current date
130
+ def current
131
+ start = date.beginning_of_quarter
132
+ stop = date.end_of_quarter
133
+ [start, stop]
134
+ end
135
+
136
+ # The quarterly interval after the current date
137
+ def next
138
+ @date = date.end_of_quarter + 1
139
+ current
140
+ end
141
+ end
142
+
143
+ # Class contains methods for calculating a date range with an yearly interval
144
+ class Yearly
145
+ attr_accessor :date
146
+
147
+ def initialize(date = nil)
148
+ @date = date || DateTime.now
149
+ end
150
+
151
+ # The yearly interval previous to the current date
152
+ def previous
153
+ @date = date.beginning_of_year - 1
154
+ current
155
+ end
156
+
157
+ # The yearly interval for the current date
158
+ def current
159
+ start = date.beginning_of_year
160
+ stop = date.end_of_year
161
+ [start, stop]
162
+ end
163
+
164
+ # The yearly interval after the current date
165
+ def next
166
+ @date = date.end_of_year + 1
167
+ current
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,271 @@
1
+ # Change http timeouts to 1hr
2
+ ENV['COMPOSE_HTTP_TIMEOUT'] = '3600'
3
+ ENV['DOCKER_BUILDKIT'] = '1'
4
+ ENV['COMPOSE_DOCKER_CLI_BUILD'] = '1'
5
+
6
+ module Dev
7
+ class Docker
8
+ # Class containing methods for interfacing with the docker compose cli
9
+ class Compose
10
+ # Config object for setting top level docker compose config options
11
+ Config = Struct.new(:project_dir, :project_name, :compose_files, :min_version, :max_version) do
12
+ def initialize
13
+ self.project_dir = DEV_COMMANDS_ROOT_DIR
14
+ self.project_name = DEV_COMMANDS_PROJECT_NAME
15
+ self.compose_files = ["#{DEV_COMMANDS_ROOT_DIR}/docker-compose.yml"]
16
+ self.min_version = nil
17
+ self.max_version = nil
18
+ end
19
+ end
20
+
21
+ class << self
22
+ # Instantiates a new top level config object if one hasn't already been created
23
+ # Yields that config object to any given block
24
+ # Returns the resulting config object
25
+ def config
26
+ @config ||= Config.new
27
+ yield(@config) if block_given?
28
+ @config
29
+ end
30
+
31
+ # Alias the config method to configure for a slightly clearer access syntax
32
+ alias_method :configure, :config
33
+
34
+ # Returns the version of the docker-compose executable on the system
35
+ def version
36
+ @version ||= `#{EXECUTABLE_NAME} --version`.match(/version v?([0-9.]+)/)[1]
37
+ end
38
+ end
39
+
40
+ # @todo Change this to "docker compose" when everyone is off v1
41
+ # The name of the docker compose executable
42
+ EXECUTABLE_NAME = 'docker-compose'.freeze
43
+
44
+ attr_accessor :capture, :compose_files, :environment, :options, :project_dir, :project_name, :services, :user, :volumes
45
+
46
+ def initialize(
47
+ compose_files: self.class.config.compose_files,
48
+ environment: [],
49
+ options: [],
50
+ project_dir: self.class.config.project_dir,
51
+ project_name: self.class.config.project_name,
52
+ services: [],
53
+ user: nil,
54
+ volumes: [],
55
+ capture: false
56
+ )
57
+ @compose_files = Array(compose_files)
58
+ @environment = environment
59
+ @options = Array(options)
60
+ @project_dir = project_dir
61
+ @project_name = project_name
62
+ @services = Array(services)
63
+ @user = user
64
+ @volumes = Array(volumes)
65
+ @capture = capture
66
+ check_version
67
+ end
68
+
69
+ # Checks the min and max version against the current docker version if they have been configured
70
+ def check_version
71
+ min_version = self.class.config.min_version
72
+ raise "requires #{EXECUTABLE_NAME} version >= #{min_version} (found #{self.class.version})" if min_version &&
73
+ !Dev::Common.new.version_greater_than(min_version, self.class.version)
74
+
75
+ max_version = self.class.config.max_version
76
+ raise "requires #{EXECUTABLE_NAME} version < #{max_version} (found #{self.class.version})" if max_version &&
77
+ Dev::Common.new.version_greater_than(max_version, self.class.version)
78
+ end
79
+
80
+ # Pull in supported env settings and call build
81
+ # Specify PULL=true to force compose to pull all backing images as part of the build
82
+ # Specify NO_CACHE=true to force compose to build from scratch rather than using build cache
83
+ def build
84
+ merge_options('--parallel')
85
+ merge_env_pull_option
86
+ merge_env_cache_option
87
+ execute_command(build_command('build'))
88
+ end
89
+
90
+ # Pull in supported env settings and call up
91
+ # Specify BUILD=true to force/allow service builds before startup
92
+ # Specify NO_DEPS=true to only start the given service and ignore starting it's dependencies
93
+ # Specify DETACHED=false to not detach from the started processes
94
+ def up
95
+ merge_env_build_option
96
+ merge_env_deps_option
97
+ merge_env_detach_option
98
+ execute_command(build_command('up'))
99
+ end
100
+
101
+ # Exec into a running container and run the given shell commands
102
+ # Default to running 'bash' which will start a terminal in the running container
103
+ def sh(shell_commands = ['bash'])
104
+ execute_command(build_command('exec', *shell_commands))
105
+ end
106
+
107
+ # Pull in supported env settings and call logs
108
+ # Specify NO_FOLLOW=true if you want to print current logs and exist
109
+ # Specify TAIL to pass tail options to the logs command
110
+ def logs
111
+ merge_env_follow_option
112
+ merge_env_tail_option
113
+ execute_command(build_command('logs'))
114
+ end
115
+
116
+ # Pull in supported env settings and call down
117
+ # Specify REMOVE_VOLUMES=true to also remove any unused volumes when the containers are stopped
118
+ def down
119
+ merge_env_volumes_option
120
+ execute_command(build_command('down'))
121
+ end
122
+
123
+ # Pull in supported env settings and call stop
124
+ def stop
125
+ execute_command(build_command('stop'))
126
+ end
127
+
128
+ # Call the compose exec method passing the given args after it
129
+ def exec(*args)
130
+ execute_command(build_command('exec', *args))
131
+ end
132
+
133
+ # Call the compose run method passing the given args after it
134
+ def run(*args)
135
+ execute_command(build_command('run', *args))
136
+ end
137
+
138
+ # Call the compose push method
139
+ def push
140
+ execute_command(build_command('push'))
141
+ end
142
+
143
+ # Call the compose pull method
144
+ def pull
145
+ execute_command(build_command('pull'))
146
+ end
147
+
148
+ # Get the first container matching the given name
149
+ # If prefix is specified then this method will filter for compose services in the given project only
150
+ # If status is specified then this method will filter containers in the given status only
151
+ def container_by_name(service_name, prefix = nil, status: [Docker::Status::RUNNING])
152
+ prefix ||= project_name
153
+ containers = ::Docker::Container.all(filters: {status: Array(status), label: ["com.docker.compose.service=#{service_name}"]}.to_json)
154
+ containers.each do |container|
155
+ container&.info&.dig('Names')&.each do |name|
156
+ return container if name.start_with?("/#{prefix}")
157
+ end
158
+ end
159
+
160
+ raise "Container not found for #{service_name} with prefix #{prefix}"
161
+ end
162
+
163
+ # Gets the dynamic port which was assigned to the compose service on the original private port
164
+ def mapped_public_port(service_name, private_port)
165
+ container = container_by_name(service_name)
166
+ port_mapping = container.info['Ports'].find { |it| it['PrivatePort'] == private_port }
167
+ port_mapping['PublicPort']
168
+ end
169
+
170
+ # Merge --no-cache option if nocache is set to true and no existing cache options are present
171
+ private def merge_env_cache_option
172
+ return if @options.any? { |it| it.include?('cache') }
173
+
174
+ merge_options('--no-cache') if ENV['NO_CACHE'].to_s.strip == 'true'
175
+ end
176
+
177
+ # Merge --pull option if PULL is set to true and no existing pull options are present
178
+ private def merge_env_pull_option
179
+ return if @options.any? { |it| it.include?('pull') }
180
+
181
+ merge_options('--pull') if ENV['PULL'].to_s.strip == 'true'
182
+ end
183
+
184
+ # Merge --no-build option unless BUILD is set to true and no existing build options are present
185
+ private def merge_env_build_option
186
+ return if @options.any? { |it| it.include?('build') }
187
+
188
+ merge_options('--no-build') unless ENV['BUILD'].to_s.strip == 'true'
189
+ end
190
+
191
+ # Merge --no-deps option if NO_DEPS is set to true and no existing deps options are present
192
+ private def merge_env_deps_option
193
+ return if @options.any? { |it| it.include?('deps') }
194
+
195
+ merge_options('--no-deps') if ENV['NO_DEPS'].to_s.strip == 'true'
196
+ end
197
+
198
+ # Merge --detach option unless DETACHED is set to false and no existing detach options are present
199
+ private def merge_env_detach_option
200
+ return if @options.any? { |it| it.include?('detach') }
201
+
202
+ merge_options('--detach') unless ENV['DETACHED'].to_s.strip == 'false'
203
+ end
204
+
205
+ # Merge -f option unless NO_FOLLOW is set to true and no existing follow options are present
206
+ private def merge_env_follow_option
207
+ return if @options.any? { |it| it.include?('follow') }
208
+
209
+ merge_options('-f') unless ENV['NO_FOLLOW'].to_s.strip == 'true'
210
+ end
211
+
212
+ # Merge --tail option unless TAIL is empty and no existing tail options are present
213
+ private def merge_env_tail_option
214
+ return if @options.any? { |it| it.include?('tail') }
215
+
216
+ merge_options('--tail', ENV.fetch('TAIL', nil)) unless ENV['tail'].to_s.strip.empty?
217
+ end
218
+
219
+ # Merge --volumes option if REMOVE_VOLUMES is set to true and no existing volume options are present
220
+ private def merge_env_volumes_option
221
+ return if @options.any? { |it| it.include?('volume') }
222
+
223
+ merge_options('--volumes') if ENV['REMOVE_VOLUMES'].to_s.strip == 'true'
224
+ end
225
+
226
+ # Merges two arrays removing nested structure and duplicate keys
227
+ private def merge_options(*opts)
228
+ @options = (@options + Array(opts)).flatten.uniq
229
+ end
230
+
231
+ # Build the compose command with the given inputs
232
+ private def build_command(action, *cmd)
233
+ command = [EXECUTABLE_NAME]
234
+ command << '--project-directory' << project_dir
235
+ command << '-p' << project_name if project_name
236
+ Array(compose_files).compact.each { |file| command << '-f' << file }
237
+ command << action
238
+
239
+ Array(environment).compact.each do |value|
240
+ command << '-e'
241
+ command << normalize_command_line_arg(value)
242
+ end
243
+
244
+ Array(volumes).compact.each do |volume|
245
+ command << '-v'
246
+ command << normalize_command_line_arg(volume, ':')
247
+ end
248
+
249
+ command << '-u' << user if user
250
+ command.concat(Array(options).compact)
251
+ command.concat(Array(services).compact)
252
+ command.concat(Array(cmd).flatten.compact)
253
+ command
254
+ end
255
+
256
+ # Normalize the command line inputs for various complex input possibilities
257
+ # Possible argument types are Array, Hash, or String
258
+ private def normalize_command_line_arg(arg, separator = '=')
259
+ return "#{arg.first}#{separator}#{arg.last}" if arg.is_a?(Array)
260
+
261
+ arg.to_s
262
+ end
263
+
264
+ # Print the compose command that will be executed and then execute it
265
+ private def execute_command(command)
266
+ LOG.debug " > #{command.join(' ')}"
267
+ ::Dev::Common.new.run_command(command, capture: capture)
268
+ end
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,38 @@
1
+ module Dev
2
+ class Docker
3
+ # Class containing constants for docker status names and groups
4
+ class Status
5
+ # Docker created status name
6
+ CREATED = :created
7
+
8
+ # Docker restarting status name
9
+ RESTARTING = :restarting
10
+
11
+ # Docker running status name
12
+ RUNNING = :running
13
+
14
+ # Docker removing status name
15
+ REMOVING = :removing
16
+
17
+ # Docker paused status name
18
+ PAUSED = :paused
19
+
20
+ # Docker exited status name
21
+ EXITED = :exited
22
+
23
+ # Docker dead status name
24
+ DEAD = :dead
25
+
26
+ # Array containing all available docker statuses
27
+ ALL = [
28
+ CREATED,
29
+ RESTARTING,
30
+ RUNNING,
31
+ REMOVING,
32
+ PAUSED,
33
+ EXITED,
34
+ DEAD
35
+ ].freeze
36
+ end
37
+ end
38
+ end