ops_team 0.10.0 → 0.11.0.pre

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
  SHA256:
3
- metadata.gz: 047c3860b15eb79d392d3616d822530752746acee221a309b3ad0fbe35a7c4fa
4
- data.tar.gz: db149bdce3d9777ec2416ba7489a0cea00bb268d8d82ce3c22ec4326b6a9c7e9
3
+ metadata.gz: d3a9e4bdba561a28f5b282b09ab717b8445053d68ba715337df0bf7bd294abec
4
+ data.tar.gz: 7fc1110839291c7912c376597d32a4fcb048952e734dc586c2bf40476a53ec93
5
5
  SHA512:
6
- metadata.gz: 3ee633e1ba692622711b0d9b6d2a5e4357dd0dbcfdad22567b858616328d2548a0ee8be45c9aa90517f17f15451dad2ff720cb02314829c0feab41164a4d5e4b
7
- data.tar.gz: 7b03cdd354652f5c68ca1b430a1540136e08f33498a29021e4ed6fa9147779b82104c6ece6878d16b5c7530af1491f75aad23b7fe2c4db6ae0bf669f17276e5f
6
+ metadata.gz: 97707fa40c98bae65bc8919da37fd2a366090213fb8fd260339c9489da725779f3d763e06f708d51f70fb03273fa99cb4596f44d663c935515f4b82d3a9d94cf
7
+ data.tar.gz: 9907f1bcc2b41a4ec0b5e119ffad24c443d76e726b6aca9bec1529d8be6576889a362fd8f56d9cc123fcca8bbe242f30c17b6bf39fb4684e7b745b716532cc28
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class AppConfig
4
+ class ParsingError < StandardError; end
5
+
4
6
  class << self
5
7
  def load
6
8
  new(app_config_path).load
@@ -36,8 +38,7 @@ class AppConfig
36
38
  def config
37
39
  @config ||= file_contents ? YAML.safe_load(file_contents) : {}
38
40
  rescue YAML::SyntaxError => e
39
- Output.error("Error parsing config data: #{e}")
40
- {}
41
+ raise ParsingError, "Error parsing config data: #{e}"
41
42
  end
42
43
 
43
44
  def file_contents
@@ -52,6 +52,8 @@ module Builtins
52
52
  end
53
53
 
54
54
  def actions
55
+ return [] unless @config["actions"]
56
+
55
57
  @config["actions"].map do |name, value|
56
58
  format("%<name>-35s %<desc>s",
57
59
  name: name.yellow,
@@ -32,12 +32,18 @@ module Builtins
32
32
 
33
33
  private
34
34
 
35
- def template_name_arg
35
+ def template_name
36
36
  @args[0]
37
37
  end
38
38
 
39
39
  def template_path
40
- format(OPS_YML_TEMPLATE, template_name: template_name_arg || DEFAULT_TEMPLATE_NAME)
40
+ return template_name if template_name && File.exist?(template_name)
41
+
42
+ builtin_template_path
43
+ end
44
+
45
+ def builtin_template_path
46
+ format(OPS_YML_TEMPLATE, template_name: template_name || DEFAULT_TEMPLATE_NAME)
41
47
  end
42
48
 
43
49
  def template_name_list
@@ -20,7 +20,7 @@ module Dependencies
20
20
  end
21
21
 
22
22
  def should_meet?
23
- `uname`.chomp == "Linux" && system("which apk &>/dev/null")
23
+ `uname`.chomp == "Linux" && system("which apk")
24
24
  end
25
25
  end
26
26
  end
@@ -23,7 +23,7 @@ module Dependencies
23
23
  end
24
24
 
25
25
  def should_meet?
26
- `uname`.chomp == "Linux" && system("which apt-get &>/dev/null")
26
+ `uname`.chomp == "Linux" && system("which apt-get")
27
27
  end
28
28
 
29
29
  private
@@ -45,7 +45,7 @@ module Dependencies
45
45
  end
46
46
 
47
47
  def sudo_string
48
- return "" if ENV['USER'] == "root" || Options.get("apt.use_sudo") == false
48
+ return "" if ENV['USER'] == "root" || `whoami` == "root" || Options.get("apt.use_sudo") == false
49
49
 
50
50
  "sudo "
51
51
  end
@@ -35,18 +35,6 @@ module Dependencies
35
35
  match.nil? ? nil : match[1]
36
36
  end
37
37
 
38
- def version_lines
39
- @version_lines ||= begin
40
- version_table_index = apt_cache_lines.find_index { |line| line.match?(/Version table:/) }
41
-
42
- apt_cache_lines[version_table_index..-1].each_with_object([]) do |line, versions|
43
- next unless line.match(/ *(\*\*\*)? .*/)
44
-
45
- versions << line
46
- end
47
- end
48
- end
49
-
50
38
  def apt_cache_lines
51
39
  @apt_cache_lines ||= `apt-cache policy #{name}`.split("\n")
52
40
  end
@@ -4,11 +4,12 @@ require 'open3'
4
4
  require 'English'
5
5
 
6
6
  require 'output'
7
+ require 'executor'
7
8
 
8
9
  class Dependency
9
10
  DESCRIPTION_TYPE_WIDTH = 8
10
11
 
11
- attr_reader :name, :output, :exit_code
12
+ attr_reader :name
12
13
 
13
14
  def initialize(name)
14
15
  @name = name
@@ -45,15 +46,23 @@ class Dependency
45
46
  end
46
47
 
47
48
  def success?
48
- @exit_code.nil? ? true : @exit_code.zero?
49
+ @executor&.success?
50
+ end
51
+
52
+ def output
53
+ @executor&.output
54
+ end
55
+
56
+ def exit_code
57
+ @executor&.exit_code
49
58
  end
50
59
 
51
60
  private
52
61
 
53
62
  def execute(cmd)
54
- @output, status = Open3.capture2e(cmd)
55
- @exit_code = status.exitstatus
63
+ @executor = Executor.new(cmd)
64
+ @executor.execute
56
65
 
57
- success?
66
+ @executor.success?
58
67
  end
59
68
  end
@@ -6,6 +6,7 @@ class Environment
6
6
  end
7
7
 
8
8
  def set_variables
9
+ set_ops_variables
9
10
  set_environment_aliases
10
11
  set_configured_variables
11
12
  end
@@ -18,6 +19,10 @@ class Environment
18
19
 
19
20
  private
20
21
 
22
+ def set_ops_variables
23
+ ENV["OPS_YML_DIR"] = Dir.pwd
24
+ end
25
+
21
26
  def set_environment_aliases
22
27
  environment_aliases.each do |alias_name|
23
28
  ENV[alias_name] = environment
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Executor
4
+ attr_reader :output, :exit_code
5
+
6
+ class << self
7
+ def execute(command)
8
+ @output, status = Open3.capture2e(command)
9
+ @exit_code = status.exitstatus
10
+
11
+ [@output, @exit_code]
12
+ end
13
+ end
14
+
15
+ def initialize(command)
16
+ @command = command
17
+ end
18
+
19
+ def execute
20
+ @output, status = Open3.capture2e(@command)
21
+ @exit_code = status.exitstatus
22
+
23
+ success?
24
+ end
25
+
26
+ def success?
27
+ @exit_code.nil? ? true : @exit_code.zero?
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class HookHandler
4
+ class HookConfigError < StandardError; end
5
+ class HookExecError < StandardError; end
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def do_hooks(name)
12
+ raise HookConfigError, "'hooks.#{name}' must be a list" unless hooks(name).is_a?(Array)
13
+
14
+ execute_hooks(name)
15
+ end
16
+
17
+ private
18
+
19
+ def hooks(name)
20
+ @config.dig("hooks", name) || []
21
+ end
22
+
23
+ def execute_hooks(name)
24
+ hooks(name).each do |hook|
25
+ output, exit_code = Executor.execute(hook)
26
+
27
+ next if exit_code.zero?
28
+
29
+ raise HookExecError, "#{name} hook '#{hook}' failed with exit code #{exit_code}:\n#{output}"
30
+ end
31
+ end
32
+ end
data/lib/ops.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  require 'yaml'
5
5
  require 'require_all'
6
6
 
7
+ require 'hook_handler'
7
8
  require 'action'
8
9
  require 'output'
9
10
  require 'options'
@@ -18,6 +19,7 @@ class Ops
18
19
 
19
20
  INVALID_SYNTAX_EXIT_CODE = 64
20
21
  UNKNOWN_ACTION_EXIT_CODE = 65
22
+ ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
21
23
 
22
24
  class << self
23
25
  def project_name
@@ -53,13 +55,25 @@ class Ops
53
55
  end
54
56
 
55
57
  def run_action
56
- environment.set_variables
57
- AppConfig.load
58
+ do_before_run_action
58
59
 
59
60
  return builtin.run if builtin
60
61
 
61
62
  Output.notice("Running '#{action}' from #{CONFIG_FILE} in environment '#{ENV['environment']}'...")
62
63
  action.run
64
+ rescue AppConfig::ParsingError => e
65
+ Output.error("Error parsing app config: #{e}")
66
+ exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
67
+ end
68
+
69
+ def do_before_run_action
70
+ environment.set_variables
71
+ AppConfig.load
72
+ hook_handler.do_hooks("before")
73
+ end
74
+
75
+ def hook_handler
76
+ @hook_handler ||= HookHandler.new(config)
63
77
  end
64
78
 
65
79
  def builtin
@@ -94,7 +108,8 @@ class Ops
94
108
  @config ||= begin
95
109
  Output.warn("File '#{CONFIG_FILE}' does not exist.") unless File.exist?(CONFIG_FILE)
96
110
  YAML.load_file(CONFIG_FILE)
97
- rescue StandardError
111
+ rescue StandardError => e
112
+ Output.warn("Error parsing '#{CONFIG_FILE}': #{e}")
98
113
  {}
99
114
  end
100
115
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require 'open3'
4
5
 
5
6
  require 'output'
6
7
  require 'app_config'
@@ -38,6 +39,19 @@ class Secrets < AppConfig
38
39
  end
39
40
 
40
41
  def file_contents
41
- @file_contents ||= @filename.match(/\.ejson$/) ? `ejson decrypt #{@filename}` : super
42
+ @file_contents ||= begin
43
+ @filename.match(/\.ejson$/) ? ejson_contents : super
44
+ end
45
+ end
46
+
47
+ def ejson_contents
48
+ @ejson_contents ||= begin
49
+ out, err, _status = Open3.capture3("ejson decrypt #{@filename}")
50
+
51
+ # TODO: err is only nil in testing, but I can't figure out why the stubbing isn't working
52
+ raise ParsingError, "Error decrypting EJSON file: #{err}" unless err.nil? || err.empty?
53
+
54
+ out
55
+ end
42
56
  end
43
57
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'ops_team'
5
- s.version = '0.10.0'
5
+ s.version = '0.11.0.pre'
6
6
  s.authors = [
7
7
  'nickthecook@gmail.com'
8
8
  ]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ops_team
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - nickthecook@gmail.com
@@ -170,6 +170,8 @@ files:
170
170
  - lib/dependencies/sshkey.rb
171
171
  - lib/dependency.rb
172
172
  - lib/environment.rb
173
+ - lib/executor.rb
174
+ - lib/hook_handler.rb
173
175
  - lib/ops.rb
174
176
  - lib/options.rb
175
177
  - lib/output.rb
@@ -191,9 +193,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
191
193
  version: '2.5'
192
194
  required_rubygems_version: !ruby/object:Gem::Requirement
193
195
  requirements:
194
- - - ">="
196
+ - - ">"
195
197
  - !ruby/object:Gem::Version
196
- version: '0'
198
+ version: 1.3.1
197
199
  requirements: []
198
200
  rubygems_version: 3.0.3
199
201
  signing_key: