firespring_dev_commands 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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