ops_team 1.21.1 → 2.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/ops +4 -40
- data/build/darwin_amd64/ops +0 -0
- data/build/darwin_arm64/ops +0 -0
- data/build/linux_amd64/ops +0 -0
- metadata +12 -224
- data/Gemfile +0 -30
- data/bin/benchmark +0 -185
- data/bin/print_config +0 -4
- data/bin/print_secrets +0 -4
- data/bin/tag +0 -16
- data/etc/ops.template.yml +0 -13
- data/etc/ruby.template.yml +0 -37
- data/etc/terraform.template.yml +0 -36
- data/lib/action.rb +0 -103
- data/lib/action_list.rb +0 -55
- data/lib/action_suggester.rb +0 -17
- data/lib/app_config.rb +0 -69
- data/lib/builtin.rb +0 -51
- data/lib/builtins/background.rb +0 -46
- data/lib/builtins/background_log.rb +0 -34
- data/lib/builtins/common/up_down.rb +0 -67
- data/lib/builtins/countdown.rb +0 -73
- data/lib/builtins/down.rb +0 -9
- data/lib/builtins/env.rb +0 -21
- data/lib/builtins/envdiff.rb +0 -127
- data/lib/builtins/exec.rb +0 -24
- data/lib/builtins/help.rb +0 -66
- data/lib/builtins/helpers/dependency_handler.rb +0 -27
- data/lib/builtins/helpers/enumerator.rb +0 -34
- data/lib/builtins/init.rb +0 -64
- data/lib/builtins/up.rb +0 -9
- data/lib/builtins/version.rb +0 -17
- data/lib/dependencies/apk.rb +0 -24
- data/lib/dependencies/apt.rb +0 -42
- data/lib/dependencies/brew.rb +0 -22
- data/lib/dependencies/cask.rb +0 -13
- data/lib/dependencies/custom.rb +0 -45
- data/lib/dependencies/dir.rb +0 -22
- data/lib/dependencies/docker.rb +0 -17
- data/lib/dependencies/gem.rb +0 -36
- data/lib/dependencies/helpers/apt_cache_policy.rb +0 -43
- data/lib/dependencies/pip.rb +0 -32
- data/lib/dependencies/snap.rb +0 -32
- data/lib/dependencies/sshkey.rb +0 -121
- data/lib/dependencies/versioned_dependency.rb +0 -25
- data/lib/dependency.rb +0 -69
- data/lib/environment.rb +0 -47
- data/lib/executor.rb +0 -20
- data/lib/forward.rb +0 -15
- data/lib/forwards.rb +0 -16
- data/lib/hook_handler.rb +0 -41
- data/lib/ops.rb +0 -129
- data/lib/options.rb +0 -22
- data/lib/output.rb +0 -71
- data/lib/profiler.rb +0 -47
- data/lib/runner.rb +0 -110
- data/lib/secrets.rb +0 -55
- data/lib/version.rb +0 -38
- data/loader.rb +0 -10
- data/ops_team.gemspec +0 -36
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Dependencies
|
4
|
-
class VersionedDependency < Dependency
|
5
|
-
VERSION_SEPARATOR = " "
|
6
|
-
|
7
|
-
def dep_name
|
8
|
-
name_components[0]
|
9
|
-
end
|
10
|
-
|
11
|
-
def dep_version
|
12
|
-
name_components[1]
|
13
|
-
end
|
14
|
-
|
15
|
-
def versioned?
|
16
|
-
!!dep_version
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def name_components
|
22
|
-
name.split(VERSION_SEPARATOR, 2)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/dependency.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'open3'
|
4
|
-
require 'English'
|
5
|
-
|
6
|
-
class Dependency
|
7
|
-
DESCRIPTION_TYPE_WIDTH = 8
|
8
|
-
|
9
|
-
attr_reader :name
|
10
|
-
|
11
|
-
def initialize(name)
|
12
|
-
@name = name
|
13
|
-
end
|
14
|
-
|
15
|
-
def met?
|
16
|
-
raise NotImplementedError
|
17
|
-
end
|
18
|
-
|
19
|
-
def meet
|
20
|
-
raise NotImplementedError
|
21
|
-
end
|
22
|
-
|
23
|
-
def unmeet
|
24
|
-
raise NotImplementedError
|
25
|
-
end
|
26
|
-
|
27
|
-
# should_meet? can be used to implement dependencies that should only be met on some platforms,
|
28
|
-
# e.g. brew on Macs and apt on Linux
|
29
|
-
# it can be used to base a decision on anything else that can be read from the environment at
|
30
|
-
# runtime
|
31
|
-
def should_meet?
|
32
|
-
true
|
33
|
-
end
|
34
|
-
|
35
|
-
# if true, this type of resource must always have `meet` and `unmeet` called;
|
36
|
-
# useful for resources that can't easily be checked to see if they're met
|
37
|
-
def always_act?
|
38
|
-
false
|
39
|
-
end
|
40
|
-
|
41
|
-
def type
|
42
|
-
self.class.name.split('::').last
|
43
|
-
end
|
44
|
-
|
45
|
-
def success?
|
46
|
-
@executor.nil? ? true : @executor.success?
|
47
|
-
end
|
48
|
-
|
49
|
-
def failure?
|
50
|
-
!success?
|
51
|
-
end
|
52
|
-
|
53
|
-
def output
|
54
|
-
@executor&.output
|
55
|
-
end
|
56
|
-
|
57
|
-
def exit_code
|
58
|
-
@executor&.exit_code
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def execute(cmd)
|
64
|
-
@executor = Executor.new(cmd)
|
65
|
-
@executor.execute
|
66
|
-
|
67
|
-
@executor.success?
|
68
|
-
end
|
69
|
-
end
|
data/lib/environment.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Environment
|
4
|
-
class << self
|
5
|
-
def environment
|
6
|
-
return 'dev' if ENV['environment'].nil? || ENV['environment'].empty?
|
7
|
-
|
8
|
-
ENV['environment']
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(env_hash, config_path)
|
13
|
-
@env_hash = env_hash
|
14
|
-
@config_path = config_path
|
15
|
-
end
|
16
|
-
|
17
|
-
def set_variables
|
18
|
-
set_ops_variables
|
19
|
-
set_environment_aliases
|
20
|
-
set_configured_variables
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def set_ops_variables
|
26
|
-
ENV["OPS_YML_DIR"] = File.dirname(@config_path)
|
27
|
-
ENV["OPS_VERSION"] = Version.version.to_s
|
28
|
-
ENV["OPS_SECRETS_FILE"] = Secrets.app_config_path
|
29
|
-
ENV["OPS_CONFIG_FILE"] = AppConfig.app_config_path
|
30
|
-
end
|
31
|
-
|
32
|
-
def set_environment_aliases
|
33
|
-
environment_aliases.each do |alias_name|
|
34
|
-
ENV[alias_name] = Environment.environment
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def environment_aliases
|
39
|
-
Options.get("environment_aliases") || ['environment']
|
40
|
-
end
|
41
|
-
|
42
|
-
def set_configured_variables
|
43
|
-
@env_hash.each do |key, value|
|
44
|
-
ENV[key] = `echo #{value}`.chomp
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/executor.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Executor
|
4
|
-
attr_reader :output, :exit_code
|
5
|
-
|
6
|
-
def initialize(command)
|
7
|
-
@command = command
|
8
|
-
end
|
9
|
-
|
10
|
-
def execute
|
11
|
-
@output, status = Open3.capture2e(@command)
|
12
|
-
@exit_code = status.exitstatus
|
13
|
-
|
14
|
-
success?
|
15
|
-
end
|
16
|
-
|
17
|
-
def success?
|
18
|
-
@exit_code.nil? ? true : @exit_code.zero?
|
19
|
-
end
|
20
|
-
end
|
data/lib/forward.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Forward
|
4
|
-
def initialize(dir, args)
|
5
|
-
@dir = dir
|
6
|
-
@args = args
|
7
|
-
end
|
8
|
-
|
9
|
-
def run
|
10
|
-
Output.notice("Forwarding 'ops #{@args.join(" ")}' to '#{@dir}/'...")
|
11
|
-
|
12
|
-
Dir.chdir(@dir)
|
13
|
-
Ops.new(@args).run
|
14
|
-
end
|
15
|
-
end
|
data/lib/forwards.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Forwards
|
4
|
-
def initialize(config, args = [])
|
5
|
-
@config = config
|
6
|
-
@args = args
|
7
|
-
end
|
8
|
-
|
9
|
-
def get(name)
|
10
|
-
Forward.new(forwards[name], @args) if forwards[name]
|
11
|
-
end
|
12
|
-
|
13
|
-
def forwards
|
14
|
-
@forwards ||= @config["forwards"] || {}
|
15
|
-
end
|
16
|
-
end
|
data/lib/hook_handler.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class HookHandler
|
4
|
-
class HookConfigError < StandardError; end
|
5
|
-
|
6
|
-
class HookExecError < StandardError; end
|
7
|
-
|
8
|
-
def initialize(config)
|
9
|
-
@config = config
|
10
|
-
end
|
11
|
-
|
12
|
-
def do_hooks(name)
|
13
|
-
raise HookConfigError, "'hooks.#{name}' must be a list" unless hooks(name).is_a?(Array)
|
14
|
-
|
15
|
-
execute_hooks(name)
|
16
|
-
end
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def hooks(name)
|
21
|
-
@config.dig("hooks", name) || []
|
22
|
-
end
|
23
|
-
|
24
|
-
def execute_hooks(name)
|
25
|
-
hooks(name).each do |hook|
|
26
|
-
Output.notice("Running #{name} hook: #{hook}")
|
27
|
-
output, exit_code = execute_hook(hook)
|
28
|
-
|
29
|
-
next if exit_code.zero?
|
30
|
-
|
31
|
-
raise HookExecError, "#{name} hook '#{hook}' failed with exit code #{exit_code}:\n#{output}"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def execute_hook(name)
|
36
|
-
executor = Executor.new(name)
|
37
|
-
executor.execute
|
38
|
-
|
39
|
-
[executor.output, executor.exit_code]
|
40
|
-
end
|
41
|
-
end
|
data/lib/ops.rb
DELETED
@@ -1,129 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
Profiler.measure("ops:requires_external") do
|
5
|
-
require 'yaml'
|
6
|
-
require "rubygems"
|
7
|
-
end
|
8
|
-
|
9
|
-
Profiler.measure("ops:requires_internal") do
|
10
|
-
end
|
11
|
-
|
12
|
-
CONFIG_FILES = ["ops.yaml", "ops.yml"].freeze
|
13
|
-
|
14
|
-
# executes commands based on local `ops.yml`
|
15
|
-
class Ops
|
16
|
-
INVALID_SYNTAX_EXIT_CODE = 64
|
17
|
-
UNKNOWN_ACTION_EXIT_CODE = 65
|
18
|
-
ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
|
19
|
-
MIN_VERSION_NOT_MET_EXIT_CODE = 67
|
20
|
-
ACTION_CONFIG_ERROR_EXIT_CODE = 68
|
21
|
-
BUILTIN_SYNTAX_ERROR_EXIT_CODE = 69
|
22
|
-
ACTION_NOT_ALLOWED_IN_ENV_EXIT_CODE = 70
|
23
|
-
|
24
|
-
RECOMMEND_HELP_TEXT = "Run 'ops help' for a list of builtins and actions."
|
25
|
-
|
26
|
-
class << self
|
27
|
-
def project_name
|
28
|
-
File.basename(::Dir.pwd)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def initialize(argv, config_file: nil)
|
33
|
-
@action_name = argv[0]
|
34
|
-
@args = argv[1..-1]
|
35
|
-
@config_file = config_file || CONFIG_FILES.find { |file| File.exist?(file) } || "ops.yml"
|
36
|
-
|
37
|
-
Options.set(config["options"] || {})
|
38
|
-
end
|
39
|
-
|
40
|
-
# rubocop:disable Metrics/MethodLength
|
41
|
-
# better to have all the rescues in one place
|
42
|
-
def run
|
43
|
-
# "return" is here to allow specs to stub "exit" without executing everything after it
|
44
|
-
return exit(INVALID_SYNTAX_EXIT_CODE) unless syntax_valid?
|
45
|
-
return exit(MIN_VERSION_NOT_MET_EXIT_CODE) unless min_version_met?
|
46
|
-
|
47
|
-
Profiler.measure("runner:run") do
|
48
|
-
runner.run
|
49
|
-
end
|
50
|
-
rescue Runner::UnknownActionError => e
|
51
|
-
Output.error(e.to_s)
|
52
|
-
Output.out(RECOMMEND_HELP_TEXT) unless print_did_you_mean
|
53
|
-
exit(UNKNOWN_ACTION_EXIT_CODE)
|
54
|
-
rescue Runner::ActionConfigError => e
|
55
|
-
Output.error("Error(s) running action '#{@action_name}': #{e}")
|
56
|
-
exit(ACTION_CONFIG_ERROR_EXIT_CODE)
|
57
|
-
rescue Builtin::ArgumentError => e
|
58
|
-
Output.error("Error running builtin '#{@action_name}': #{e}")
|
59
|
-
exit(BUILTIN_SYNTAX_ERROR_EXIT_CODE)
|
60
|
-
rescue AppConfig::ParsingError => e
|
61
|
-
Output.error("Error parsing app config: #{e}")
|
62
|
-
exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
|
63
|
-
rescue Runner::NotAllowedInEnvError => e
|
64
|
-
Output.error("Error running action #{@action_name}: #{e}")
|
65
|
-
exit(ACTION_NOT_ALLOWED_IN_ENV_EXIT_CODE)
|
66
|
-
end
|
67
|
-
# rubocop:enable Metrics/MethodLength
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def syntax_valid?
|
72
|
-
return true unless @action_name.nil?
|
73
|
-
|
74
|
-
Output.error("Usage: ops <action>")
|
75
|
-
Output.out(RECOMMEND_HELP_TEXT)
|
76
|
-
false
|
77
|
-
end
|
78
|
-
|
79
|
-
def print_did_you_mean
|
80
|
-
Output.out("Did you mean '#{runner.suggestions.join(", ")}'?") if runner.suggestions.any?
|
81
|
-
|
82
|
-
runner.suggestions.any?
|
83
|
-
end
|
84
|
-
|
85
|
-
def min_version_met?
|
86
|
-
return true unless min_version
|
87
|
-
|
88
|
-
if Version.min_version_met?(min_version)
|
89
|
-
true
|
90
|
-
else
|
91
|
-
Output.error("ops.yml specifies minimum version of #{min_version}, but ops version is #{Version.version}")
|
92
|
-
false
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def min_version
|
97
|
-
config["min_version"]
|
98
|
-
end
|
99
|
-
|
100
|
-
def runner
|
101
|
-
@runner ||= Runner.new(@action_name, @args, config, config_file_absolute_path)
|
102
|
-
end
|
103
|
-
|
104
|
-
def config
|
105
|
-
@config ||= if config_file_exists?
|
106
|
-
parsed_config_contents
|
107
|
-
else
|
108
|
-
Output.warn("File '#{@config_file}' does not exist.") unless @action_name == "init"
|
109
|
-
{}
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
def parsed_config_contents
|
114
|
-
YAML.load_file(@config_file)
|
115
|
-
rescue StandardError => e
|
116
|
-
Output.warn("Error parsing '#{@config_file}': #{e}")
|
117
|
-
{}
|
118
|
-
end
|
119
|
-
|
120
|
-
def config_file_exists?
|
121
|
-
File.exist?(@config_file)
|
122
|
-
end
|
123
|
-
|
124
|
-
def config_file_absolute_path
|
125
|
-
File.expand_path(@config_file)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
Ops.new(ARGV).run if $PROGRAM_NAME == __FILE__
|
data/lib/options.rb
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Options
|
4
|
-
class << self
|
5
|
-
def get(path)
|
6
|
-
env_var = ENV[env_var(path)]
|
7
|
-
return YAML.safe_load(env_var) unless env_var.nil?
|
8
|
-
|
9
|
-
@options&.dig(*path.split('.'))
|
10
|
-
end
|
11
|
-
|
12
|
-
def set(options)
|
13
|
-
@options = options
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def env_var(path)
|
19
|
-
"OPS__#{path.upcase.gsub(".", "__")}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/output.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'colorize'
|
4
|
-
|
5
|
-
class Output
|
6
|
-
@out = STDOUT
|
7
|
-
@err = STDERR
|
8
|
-
|
9
|
-
STATUS_WIDTH = "50"
|
10
|
-
|
11
|
-
OKAY = "OK"
|
12
|
-
SKIPPED = "SKIPPED"
|
13
|
-
FAILED = "FAILED"
|
14
|
-
|
15
|
-
# used to silence output, e.g. in testing
|
16
|
-
class DummyOutput
|
17
|
-
def print(*_); end
|
18
|
-
|
19
|
-
def puts(*_); end
|
20
|
-
end
|
21
|
-
|
22
|
-
class << self
|
23
|
-
def status(name)
|
24
|
-
@out.print(format("%-#{STATUS_WIDTH}<name>s ", name: name))
|
25
|
-
end
|
26
|
-
|
27
|
-
def okay
|
28
|
-
@out.puts(OKAY.green)
|
29
|
-
end
|
30
|
-
|
31
|
-
def skipped
|
32
|
-
@out.puts(SKIPPED.yellow)
|
33
|
-
end
|
34
|
-
|
35
|
-
def failed
|
36
|
-
@out.puts(FAILED.red)
|
37
|
-
end
|
38
|
-
|
39
|
-
def warn(msg)
|
40
|
-
@err.puts(msg.yellow)
|
41
|
-
end
|
42
|
-
|
43
|
-
alias notice warn
|
44
|
-
|
45
|
-
def error(msg)
|
46
|
-
@err.puts(msg.red)
|
47
|
-
end
|
48
|
-
|
49
|
-
def out(msg)
|
50
|
-
@out.puts(msg)
|
51
|
-
end
|
52
|
-
|
53
|
-
def print(msg)
|
54
|
-
@out.print(msg)
|
55
|
-
end
|
56
|
-
|
57
|
-
def debug(msg)
|
58
|
-
return unless ENV["OPS_DEBUG_OUTPUT"]
|
59
|
-
|
60
|
-
@err.puts(msg.blue)
|
61
|
-
end
|
62
|
-
|
63
|
-
def silence
|
64
|
-
@out = @err = dummy_output
|
65
|
-
end
|
66
|
-
|
67
|
-
def dummy_output
|
68
|
-
@dummy_output ||= DummyOutput.new
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
data/lib/profiler.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Profiler
|
4
|
-
INDENT = " "
|
5
|
-
|
6
|
-
@measurements = {}
|
7
|
-
|
8
|
-
class << self
|
9
|
-
attr_reader :measurements
|
10
|
-
|
11
|
-
def measure(tag)
|
12
|
-
start = time_now
|
13
|
-
result = yield
|
14
|
-
add_measurement(tag, time_now - start)
|
15
|
-
|
16
|
-
result
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_measurement(tag, seconds)
|
20
|
-
return unless profiling?
|
21
|
-
|
22
|
-
@measurements[tag] ||= []
|
23
|
-
|
24
|
-
@measurements[tag] << seconds
|
25
|
-
end
|
26
|
-
|
27
|
-
def summary
|
28
|
-
return unless profiling?
|
29
|
-
|
30
|
-
@summary ||= measurements.reverse_each.each_with_object([]) do |(tag, values), output|
|
31
|
-
output << "#{tag}:\n"
|
32
|
-
values.sort.reverse.each do |value|
|
33
|
-
value_str = format("%.3f", value * 1000)
|
34
|
-
output << format("%<indent>s%9<value>sms\n", indent: INDENT, value: value_str)
|
35
|
-
end
|
36
|
-
end.join
|
37
|
-
end
|
38
|
-
|
39
|
-
def profiling?
|
40
|
-
!ENV["OPS_PROFILE"].nil?
|
41
|
-
end
|
42
|
-
|
43
|
-
def time_now
|
44
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/runner.rb
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Builtins
|
4
|
-
end
|
5
|
-
|
6
|
-
class Runner
|
7
|
-
class UnknownActionError < StandardError; end
|
8
|
-
|
9
|
-
class ActionConfigError < StandardError; end
|
10
|
-
|
11
|
-
class NotAllowedInEnvError < StandardError; end
|
12
|
-
|
13
|
-
def initialize(action_name, args, config, config_path)
|
14
|
-
@action_name = action_name
|
15
|
-
@args = args
|
16
|
-
@config = config
|
17
|
-
@config_path = config_path
|
18
|
-
end
|
19
|
-
|
20
|
-
def run
|
21
|
-
return forward.run if forward
|
22
|
-
|
23
|
-
do_before_all
|
24
|
-
|
25
|
-
return builtin.run if builtin
|
26
|
-
|
27
|
-
raise UnknownActionError, "Unknown action: #{@action_name}" unless action
|
28
|
-
raise ActionConfigError, action.config_errors.join("; ") unless action.config_valid?
|
29
|
-
|
30
|
-
do_before_action
|
31
|
-
|
32
|
-
run_action
|
33
|
-
end
|
34
|
-
|
35
|
-
def suggestions
|
36
|
-
@suggestions ||= ActionSuggester.new(action_list.names + action_list.aliases + builtin_names).check(@action_name)
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def do_before_all
|
42
|
-
AppConfig.load
|
43
|
-
Secrets.load if action&.load_secrets?
|
44
|
-
environment.set_variables
|
45
|
-
end
|
46
|
-
|
47
|
-
def do_before_action
|
48
|
-
return if ENV["OPS_RUNNING"] || action.skip_hooks?("before")
|
49
|
-
|
50
|
-
# this prevents before hooks from running in ops executed by ops
|
51
|
-
ENV["OPS_RUNNING"] = "1"
|
52
|
-
hook_handler.do_hooks("before")
|
53
|
-
end
|
54
|
-
|
55
|
-
def hook_handler
|
56
|
-
@hook_handler ||= HookHandler.new(@config)
|
57
|
-
end
|
58
|
-
|
59
|
-
def builtin
|
60
|
-
Profiler.measure("runner:require_builtin") do
|
61
|
-
@builtin ||= Builtin.class_for(name: @action_name)&.new(@args, @config)
|
62
|
-
end
|
63
|
-
rescue NameError
|
64
|
-
# this means there isn't a builtin with that name in that module
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
|
68
|
-
def builtin_names
|
69
|
-
Builtins.constants.select { |c| Builtins.const_get(c).is_a? Class }.map(&:downcase)
|
70
|
-
end
|
71
|
-
|
72
|
-
def forward
|
73
|
-
@forward ||= Forwards.new(@config, @args).get(@action_name)
|
74
|
-
end
|
75
|
-
|
76
|
-
def run_action
|
77
|
-
unless action.allowed_in_env?(Environment.environment)
|
78
|
-
raise NotAllowedInEnvError, "Action not allowed in #{Environment.environment} environment."
|
79
|
-
end
|
80
|
-
|
81
|
-
unless action.execute_in_env?(Environment.environment)
|
82
|
-
Output.warn("Skipping action '#{action.name}' in environment #{Environment.environment}.")
|
83
|
-
return true
|
84
|
-
end
|
85
|
-
|
86
|
-
Output.notice("Running '#{action}' in environment '#{ENV['environment']}'...")
|
87
|
-
action.run
|
88
|
-
end
|
89
|
-
|
90
|
-
def action
|
91
|
-
return action_list.get(@action_name) if action_list.get(@action_name)
|
92
|
-
return action_list.get_by_alias(@action_name) if action_list.get_by_alias(@action_name)
|
93
|
-
end
|
94
|
-
|
95
|
-
def action_list
|
96
|
-
@action_list ||= begin
|
97
|
-
Output.warn("'ops.yml' has no 'actions' defined.") if @config.any? && @config["actions"].nil?
|
98
|
-
|
99
|
-
ActionList.new(@config["actions"], @args)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def env_vars
|
104
|
-
@config.dig("options", "environment") || {}
|
105
|
-
end
|
106
|
-
|
107
|
-
def environment
|
108
|
-
@environment ||= Environment.new(env_vars, @config_path)
|
109
|
-
end
|
110
|
-
end
|
data/lib/secrets.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'json'
|
4
|
-
require 'open3'
|
5
|
-
|
6
|
-
class Secrets < AppConfig
|
7
|
-
class << self
|
8
|
-
def default_filename
|
9
|
-
config_path_for(Environment.environment)
|
10
|
-
end
|
11
|
-
|
12
|
-
def config_path_for(env)
|
13
|
-
File.exist?(ejson_path_for(env)) ? ejson_path_for(env) : json_path_for(env)
|
14
|
-
end
|
15
|
-
|
16
|
-
def app_config_path
|
17
|
-
expand_path(Options.get("secrets.path") || default_filename)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def ejson_path_for(env)
|
23
|
-
"config/#{env}/secrets.ejson"
|
24
|
-
end
|
25
|
-
|
26
|
-
def json_path_for(env)
|
27
|
-
"config/#{env}/secrets.json"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def initialize(filename = "")
|
32
|
-
@filename = filename.empty? ? Secrets.default_filename : actual_filename_for(filename)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def actual_filename_for(filename)
|
38
|
-
File.exist?(filename) ? filename : filename.sub(".ejson", ".json")
|
39
|
-
end
|
40
|
-
|
41
|
-
def file_contents
|
42
|
-
@file_contents ||= @filename.match(/\.ejson$/) ? ejson_contents : super
|
43
|
-
end
|
44
|
-
|
45
|
-
def ejson_contents
|
46
|
-
@ejson_contents ||= begin
|
47
|
-
out, err, _status = Open3.capture3("ejson decrypt #{@filename}")
|
48
|
-
|
49
|
-
# TODO: err is only nil in testing, but I can't figure out why the stubbing isn't working
|
50
|
-
raise ParsingError, "#{@filename}: #{err}" unless err.nil? || err.empty?
|
51
|
-
|
52
|
-
out
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
data/lib/version.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "rubygems"
|
4
|
-
|
5
|
-
class Version
|
6
|
-
GEMSPEC_FILE = "#{__dir__}/../ops_team.gemspec"
|
7
|
-
|
8
|
-
class << self
|
9
|
-
# these class methods exist because I don't want to have to call `Version.new.version` elsewhere
|
10
|
-
def version
|
11
|
-
new.send(:version)
|
12
|
-
end
|
13
|
-
|
14
|
-
def min_version_met?(min_version)
|
15
|
-
new.send(:min_version_met?, min_version)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
# these instance methods exist so that I don't have to clear class variables between tests
|
22
|
-
def version
|
23
|
-
unless gemspec
|
24
|
-
Output.error("Unable to load gemspec at '#{GEMSPEC_FILE}")
|
25
|
-
return nil
|
26
|
-
end
|
27
|
-
|
28
|
-
gemspec.version
|
29
|
-
end
|
30
|
-
|
31
|
-
def min_version_met?(min_version)
|
32
|
-
Gem::Version.new(version) >= Gem::Version.new(min_version)
|
33
|
-
end
|
34
|
-
|
35
|
-
def gemspec
|
36
|
-
@gemspec ||= Gem::Specification.load(GEMSPEC_FILE)
|
37
|
-
end
|
38
|
-
end
|