ops_team 0.14.1 → 0.16.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 +4 -4
- data/lib/action.rb +14 -0
- data/lib/app_config.rb +9 -9
- data/lib/builtin.rb +2 -0
- data/lib/builtins/envdiff.rb +129 -0
- data/lib/dependencies/apt.rb +10 -4
- data/lib/environment.rb +13 -7
- data/lib/ops.rb +11 -0
- data/lib/secrets.rb +17 -13
- data/ops_team.gemspec +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c264a310257b2d0178a78efaaa347405c8734a527195d3546ffe635ec00633d
|
4
|
+
data.tar.gz: 9c111521daed660115eff1628d5a0390673bb57f1d1e4a245f80a23ee64bc3fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5febca01da575199794b09fc4607f23951b194a55903093b92e2fcfe0e03722990973fa8961ab85334a19c982d69aca161d8dc11d9a4d9d0fd84cc1dddc9a63
|
7
|
+
data.tar.gz: 40022c898ba9bb313b15567bd8a768adcdead145fde33b1e88b9534af2bbdf37bf7ecc30c8604cfc34dc8f5771ac688c08b0d5bc600f6ff3c56a251ead0ec504
|
data/lib/action.rb
CHANGED
@@ -36,6 +36,20 @@ class Action
|
|
36
36
|
@config["skip_#{name}_hooks"]
|
37
37
|
end
|
38
38
|
|
39
|
+
def config_valid?
|
40
|
+
config_errors.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
def config_errors
|
44
|
+
@config_errors ||= begin
|
45
|
+
errors = []
|
46
|
+
|
47
|
+
errors << "No 'command' specified in 'action'." unless @config['command']
|
48
|
+
|
49
|
+
errors
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
39
53
|
private
|
40
54
|
|
41
55
|
def load_secrets?
|
data/lib/app_config.rb
CHANGED
@@ -8,6 +8,14 @@ class AppConfig
|
|
8
8
|
new(app_config_path).load
|
9
9
|
end
|
10
10
|
|
11
|
+
def default_filename
|
12
|
+
config_path_for(Environment.environment)
|
13
|
+
end
|
14
|
+
|
15
|
+
def config_path_for(env)
|
16
|
+
"config/#{env}/config.json"
|
17
|
+
end
|
18
|
+
|
11
19
|
private
|
12
20
|
|
13
21
|
def app_config_path
|
@@ -20,7 +28,7 @@ class AppConfig
|
|
20
28
|
end
|
21
29
|
|
22
30
|
def initialize(filename = "")
|
23
|
-
@filename = filename.empty? ? default_filename : filename
|
31
|
+
@filename = filename.empty? ? AppConfig.default_filename : filename
|
24
32
|
end
|
25
33
|
|
26
34
|
def load
|
@@ -31,10 +39,6 @@ class AppConfig
|
|
31
39
|
|
32
40
|
private
|
33
41
|
|
34
|
-
def default_filename
|
35
|
-
"config/#{environment}/config.json"
|
36
|
-
end
|
37
|
-
|
38
42
|
def config
|
39
43
|
@config ||= file_contents ? YAML.safe_load(file_contents) : {}
|
40
44
|
rescue YAML::SyntaxError => e
|
@@ -48,8 +52,4 @@ class AppConfig
|
|
48
52
|
nil
|
49
53
|
end
|
50
54
|
end
|
51
|
-
|
52
|
-
def environment
|
53
|
-
ENV['environment']
|
54
|
-
end
|
55
55
|
end
|
data/lib/builtin.rb
CHANGED
@@ -0,0 +1,129 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'builtin'
|
4
|
+
|
5
|
+
module Builtins
|
6
|
+
class EnvDiff < Builtin
|
7
|
+
class << self
|
8
|
+
def description
|
9
|
+
"compares keys present in config and secrets between different environments"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
check_args
|
15
|
+
|
16
|
+
if source_only_keys.empty? && dest_only_keys.empty?
|
17
|
+
Output.out("Environments '#{source_env}' and '#{dest_env}' define the same #{source_keys.length} key(s).")
|
18
|
+
return
|
19
|
+
end
|
20
|
+
|
21
|
+
output_key_summary(source_only_keys, source_env, dest_env) if source_only_keys.any?
|
22
|
+
output_key_summary(dest_only_keys, dest_env, source_env) if dest_only_keys.any?
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def output_key_summary(keys, in_env, not_in_env)
|
28
|
+
Output.warn("Environment '#{in_env}' defines keys that '#{not_in_env}' does not:\n")
|
29
|
+
keys.each do |key|
|
30
|
+
Output.warn(" - #{key}")
|
31
|
+
end
|
32
|
+
Output.out("")
|
33
|
+
end
|
34
|
+
|
35
|
+
def source_only_keys
|
36
|
+
@source_only_keys ||= source_keys - dest_keys
|
37
|
+
end
|
38
|
+
|
39
|
+
def dest_only_keys
|
40
|
+
@dest_only_keys ||= dest_keys - source_keys
|
41
|
+
end
|
42
|
+
|
43
|
+
def source_keys
|
44
|
+
@source_keys ||= keys_for(source_env)
|
45
|
+
end
|
46
|
+
|
47
|
+
def dest_keys
|
48
|
+
@dest_keys ||= keys_for(dest_env)
|
49
|
+
end
|
50
|
+
|
51
|
+
def keys_for(env)
|
52
|
+
tagged_config_keys_for(env) + tagged_secrets_keys_for(env)
|
53
|
+
end
|
54
|
+
|
55
|
+
def tagged_config_keys_for(env)
|
56
|
+
config_keys_for(env).map do |key|
|
57
|
+
"[CONFIG] #{key}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def tagged_secrets_keys_for(env)
|
62
|
+
secrets_keys_for(env).map do |key|
|
63
|
+
"[SECRET] #{key}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def config_keys_for(env)
|
68
|
+
(config_for(env)["environment"]&.keys || []) - ignored_keys
|
69
|
+
end
|
70
|
+
|
71
|
+
def secrets_keys_for(env)
|
72
|
+
(secrets_for(env)["environment"]&.keys || []) - ignored_keys
|
73
|
+
end
|
74
|
+
|
75
|
+
def config_for(env)
|
76
|
+
YAML.load_file(config_path_for(env))
|
77
|
+
end
|
78
|
+
|
79
|
+
def secrets_for(env)
|
80
|
+
YAML.load_file(secrets_path_for(env))
|
81
|
+
end
|
82
|
+
|
83
|
+
def check_args
|
84
|
+
raise Builtin::ArgumentError, "Usage: ops envdiff <env_one> <env_two>" unless args.length == 2
|
85
|
+
|
86
|
+
check_environment(source_env)
|
87
|
+
check_environment(dest_env)
|
88
|
+
end
|
89
|
+
|
90
|
+
def source_env
|
91
|
+
args[0]
|
92
|
+
end
|
93
|
+
|
94
|
+
def dest_env
|
95
|
+
args[1]
|
96
|
+
end
|
97
|
+
|
98
|
+
def check_environment(name)
|
99
|
+
raise_missing_file_error(config_path_for(name)) unless config_file_exists?(name)
|
100
|
+
raise_missing_file_error(secrets_path_for(name)) unless secrets_file_exists?(name)
|
101
|
+
end
|
102
|
+
|
103
|
+
def raise_missing_file_error(path)
|
104
|
+
raise Builtin::ArgumentError, "File '#{path}' does not exist."
|
105
|
+
end
|
106
|
+
|
107
|
+
def config_file_exists?(env)
|
108
|
+
File.exist?(config_path_for(env))
|
109
|
+
end
|
110
|
+
|
111
|
+
def secrets_file_exists?(env)
|
112
|
+
File.exist?(secrets_path_for(env))
|
113
|
+
end
|
114
|
+
|
115
|
+
def config_path_for(env)
|
116
|
+
AppConfig.config_path_for(env)
|
117
|
+
end
|
118
|
+
|
119
|
+
def secrets_path_for(env)
|
120
|
+
Secrets.config_path_for(env)
|
121
|
+
end
|
122
|
+
|
123
|
+
def ignored_keys
|
124
|
+
Options.get("envdiff.ignored_keys") || []
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
Envdiff = EnvDiff
|
129
|
+
end
|
data/lib/dependencies/apt.rb
CHANGED
@@ -6,13 +6,19 @@ require 'dependencies/helpers/apt_cache_policy'
|
|
6
6
|
module Dependencies
|
7
7
|
class Apt < VersionedDependency
|
8
8
|
def met?
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
if versioned?
|
10
|
+
apt_cache_policy.installed_version == dep_version
|
11
|
+
else
|
12
|
+
apt_cache_policy.installed?
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
def meet
|
15
|
-
|
17
|
+
if versioned?
|
18
|
+
execute("#{sudo_string}apt-get install -y #{dep_name}=#{dep_version}")
|
19
|
+
else
|
20
|
+
execute("#{sudo_string}apt-get install -y #{name}")
|
21
|
+
end
|
16
22
|
end
|
17
23
|
|
18
24
|
def unmeet
|
data/lib/environment.rb
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'version'
|
4
|
+
require 'secrets'
|
5
|
+
require 'app_config'
|
4
6
|
|
5
7
|
class Environment
|
8
|
+
class << self
|
9
|
+
def environment
|
10
|
+
return 'dev' if ENV['environment'].nil? || ENV['environment'].empty?
|
11
|
+
|
12
|
+
ENV['environment']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def initialize(env_hash)
|
7
17
|
@env_hash = env_hash
|
8
18
|
end
|
@@ -13,22 +23,18 @@ class Environment
|
|
13
23
|
set_configured_variables
|
14
24
|
end
|
15
25
|
|
16
|
-
def environment
|
17
|
-
return 'dev' if ENV['environment'].nil? || ENV['environment'].empty?
|
18
|
-
|
19
|
-
ENV['environment']
|
20
|
-
end
|
21
|
-
|
22
26
|
private
|
23
27
|
|
24
28
|
def set_ops_variables
|
25
29
|
ENV["OPS_YML_DIR"] = Dir.pwd
|
26
30
|
ENV["OPS_VERSION"] = Version.version.to_s
|
31
|
+
ENV["OPS_SECRETS_FILE"] = Secrets.config_path_for(Environment.environment)
|
32
|
+
ENV["OPS_CONFIG_FILE"] = AppConfig.config_path_for(Environment.environment)
|
27
33
|
end
|
28
34
|
|
29
35
|
def set_environment_aliases
|
30
36
|
environment_aliases.each do |alias_name|
|
31
|
-
ENV[alias_name] = environment
|
37
|
+
ENV[alias_name] = Environment.environment
|
32
38
|
end
|
33
39
|
end
|
34
40
|
|
data/lib/ops.rb
CHANGED
@@ -19,6 +19,7 @@ require_rel "builtins"
|
|
19
19
|
# executes commands based on local `ops.yml`
|
20
20
|
class Ops
|
21
21
|
class UnknownActionError < StandardError; end
|
22
|
+
class ActionConfigError < StandardError; end
|
22
23
|
|
23
24
|
CONFIG_FILE = "ops.yml"
|
24
25
|
|
@@ -26,6 +27,8 @@ class Ops
|
|
26
27
|
UNKNOWN_ACTION_EXIT_CODE = 65
|
27
28
|
ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
|
28
29
|
MIN_VERSION_NOT_MET_EXIT_CODE = 67
|
30
|
+
ACTION_CONFIG_ERROR_EXIT_CODE = 68
|
31
|
+
BUILTIN_SYNTAX_ERROR_EXIT_CODE = 69
|
29
32
|
|
30
33
|
RECOMMEND_HELP_TEXT = "Run 'ops help' for a list of builtins and actions."
|
31
34
|
|
@@ -52,6 +55,9 @@ class Ops
|
|
52
55
|
Output.error(e.to_s)
|
53
56
|
Output.out(RECOMMEND_HELP_TEXT) unless print_did_you_mean
|
54
57
|
exit(UNKNOWN_ACTION_EXIT_CODE)
|
58
|
+
rescue ActionConfigError => e
|
59
|
+
Output.error("Error(s) running action '#{@action_name}': #{e}")
|
60
|
+
exit(ACTION_CONFIG_ERROR_EXIT_CODE)
|
55
61
|
end
|
56
62
|
|
57
63
|
private
|
@@ -98,9 +104,14 @@ class Ops
|
|
98
104
|
|
99
105
|
return builtin.run if builtin
|
100
106
|
|
107
|
+
raise ActionConfigError, action.config_errors.join("; ") unless action.config_valid?
|
108
|
+
|
101
109
|
do_before_action
|
102
110
|
Output.notice("Running '#{action}' from #{CONFIG_FILE} in environment '#{ENV['environment']}'...")
|
103
111
|
action.run
|
112
|
+
rescue Builtin::ArgumentError => e
|
113
|
+
Output.error("Error running builtin '#{@action_name}': #{e}")
|
114
|
+
exit(BUILTIN_SYNTAX_ERROR_EXIT_CODE)
|
104
115
|
rescue AppConfig::ParsingError => e
|
105
116
|
Output.error("Error parsing app config: #{e}")
|
106
117
|
exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
|
data/lib/secrets.rb
CHANGED
@@ -9,31 +9,35 @@ require 'options'
|
|
9
9
|
|
10
10
|
class Secrets < AppConfig
|
11
11
|
class << self
|
12
|
+
def default_filename
|
13
|
+
config_path_for(Environment.environment)
|
14
|
+
end
|
15
|
+
|
16
|
+
def config_path_for(env)
|
17
|
+
File.exist?(ejson_path_for(env)) ? ejson_path_for(env) : json_path_for(env)
|
18
|
+
end
|
19
|
+
|
12
20
|
private
|
13
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
|
+
|
14
30
|
def app_config_path
|
15
31
|
expand_path(Options.get("secrets.path"))
|
16
32
|
end
|
17
33
|
end
|
18
34
|
|
19
35
|
def initialize(filename = "")
|
20
|
-
@filename = filename.empty? ? default_filename : actual_filename_for(filename)
|
36
|
+
@filename = filename.empty? ? Secrets.default_filename : actual_filename_for(filename)
|
21
37
|
end
|
22
38
|
|
23
39
|
private
|
24
40
|
|
25
|
-
def default_filename
|
26
|
-
File.exist?(default_ejson_filename) ? default_ejson_filename : default_json_filename
|
27
|
-
end
|
28
|
-
|
29
|
-
def default_ejson_filename
|
30
|
-
"config/#{environment}/secrets.ejson"
|
31
|
-
end
|
32
|
-
|
33
|
-
def default_json_filename
|
34
|
-
"config/#{environment}/secrets.json"
|
35
|
-
end
|
36
|
-
|
37
41
|
def actual_filename_for(filename)
|
38
42
|
File.exist?(filename) ? filename : filename.sub(".ejson", ".json")
|
39
43
|
end
|
data/ops_team.gemspec
CHANGED
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.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nickthecook@gmail.com
|
@@ -154,6 +154,7 @@ files:
|
|
154
154
|
- lib/builtins/background_log.rb
|
155
155
|
- lib/builtins/down.rb
|
156
156
|
- lib/builtins/env.rb
|
157
|
+
- lib/builtins/envdiff.rb
|
157
158
|
- lib/builtins/exec.rb
|
158
159
|
- lib/builtins/help.rb
|
159
160
|
- lib/builtins/helpers/dependency_handler.rb
|