ops_team 0.14.3 → 0.17.1

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: 39b95630f778d48b40cb40418de7283acb5b5f47aeabe0d01f0580d6b1c93e22
4
- data.tar.gz: 11c608a31bece6e3785bc94c48277c8b2aa6b9227a80517cd7fc46e18b3d5643
3
+ metadata.gz: 1a18acecc72ca3ac11486856bf71b2c082d81e3dfa65931141c20c1bb4ec8bc5
4
+ data.tar.gz: 852ea38c8598ca1ed3d806b3f5a334cd191e6484827f7141a265d1324c15fe9d
5
5
  SHA512:
6
- metadata.gz: 2d891bdf8088dfc4d5c709e6cfe57e4d807aa6993630c6dd1d96335749a475266ecee061b93584e086e5f8f7047e9928f448be1b43237d9ef3bae5f1b2af331c
7
- data.tar.gz: 9c974c476d915087da8752dd0a60236401cc1c058418e42835e196d679ed879c97fb73d82e248be2c625fa6619fca6b9a3915e13fd81cfc56ab521b74938ba33
6
+ metadata.gz: 19c70546affd151d331225af93e807acd07c536eca7f4369a2c36df4961cae845cd0adea9eb7446041d6e45e66a82cd5980f8a5f979393fccf0538406dbc4100
7
+ data.tar.gz: 471c92c6afd006c0073be40773a568823e37f8795ef74f8aa76e54a4b22a47208187af34274ebe54044d5b59f4f41036621893570f79eab41a035694b771198e
@@ -28,11 +28,15 @@ class ActionList
28
28
 
29
29
  private
30
30
 
31
+ def actions_list
32
+ @actions_list ||= []
33
+ end
34
+
31
35
  def process_action_list
32
36
  @actions = {}
33
37
  @aliases = {}
34
38
 
35
- @actions_list.each do |name, config|
39
+ actions_list.each do |name, config|
36
40
  action = Action.new(config, @args)
37
41
 
38
42
  @actions[name] = action
@@ -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
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Builtin
4
+ class ArgumentError < StandardError; end
5
+
4
6
  attr_reader :args, :config
5
7
 
6
8
  class << self
@@ -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
@@ -54,12 +54,18 @@ module Builtins
54
54
  def actions
55
55
  return [] unless @config["actions"]
56
56
 
57
- @config["actions"].map do |name, value|
58
- format("%<name>-35s %<desc>s",
59
- name: name.yellow,
60
- desc: value["description"] || value["command"]
57
+ @config["actions"].map do |name, action_config|
58
+ format("%<name>-40s %<desc>s",
59
+ name: "#{name.yellow} #{alias_string_for(action_config)}",
60
+ desc: action_config["description"] || action_config["command"]
61
61
  )
62
62
  end.sort
63
63
  end
64
+
65
+ def alias_string_for(action_config)
66
+ return "[#{action_config["alias"]}]" if action_config["alias"]
67
+
68
+ ""
69
+ end
64
70
  end
65
71
  end
@@ -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
@@ -28,6 +28,7 @@ class Ops
28
28
  ERROR_LOADING_APP_CONFIG_EXIT_CODE = 66
29
29
  MIN_VERSION_NOT_MET_EXIT_CODE = 67
30
30
  ACTION_CONFIG_ERROR_EXIT_CODE = 68
31
+ BUILTIN_SYNTAX_ERROR_EXIT_CODE = 69
31
32
 
32
33
  RECOMMEND_HELP_TEXT = "Run 'ops help' for a list of builtins and actions."
33
34
 
@@ -108,6 +109,9 @@ class Ops
108
109
  do_before_action
109
110
  Output.notice("Running '#{action}' from #{CONFIG_FILE} in environment '#{ENV['environment']}'...")
110
111
  action.run
112
+ rescue Builtin::ArgumentError => e
113
+ Output.error("Error running builtin '#{@action_name}': #{e}")
114
+ exit(BUILTIN_SYNTAX_ERROR_EXIT_CODE)
111
115
  rescue AppConfig::ParsingError => e
112
116
  Output.error("Error parsing app config: #{e}")
113
117
  exit(ERROR_LOADING_APP_CONFIG_EXIT_CODE)
@@ -157,8 +161,12 @@ class Ops
157
161
 
158
162
  def config
159
163
  @config ||= begin
160
- Output.warn("File '#{CONFIG_FILE}' does not exist.") unless File.exist?(CONFIG_FILE)
161
- YAML.load_file(CONFIG_FILE)
164
+ if File.exist?(CONFIG_FILE)
165
+ YAML.load_file(CONFIG_FILE)
166
+ else
167
+ Output.warn("File '#{CONFIG_FILE}' does not exist.") unless @action_name == "init"
168
+ {}
169
+ end
162
170
  rescue StandardError => e
163
171
  Output.warn("Error parsing '#{CONFIG_FILE}': #{e}")
164
172
  {}
@@ -166,7 +174,7 @@ class Ops
166
174
  end
167
175
 
168
176
  def env_vars
169
- @config.dig("options", "environment") || {}
177
+ config.dig("options", "environment") || {}
170
178
  end
171
179
 
172
180
  def environment
@@ -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
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'ops_team'
5
- s.version = '0.14.3'
5
+ s.version = '0.17.1'
6
6
  s.authors = [
7
7
  'nickthecook@gmail.com'
8
8
  ]
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ops_team
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.3
4
+ version: 0.17.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - nickthecook@gmail.com
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2020-08-12 00:00:00.000000000 Z
@@ -130,8 +130,8 @@ dependencies:
130
130
  - - ">="
131
131
  - !ruby/object:Gem::Version
132
132
  version: 1.1.6
133
- description:
134
- email:
133
+ description:
134
+ email:
135
135
  executables:
136
136
  - ops
137
137
  extensions: []
@@ -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
@@ -186,7 +187,7 @@ homepage: https://github.com/nickthecook/ops
186
187
  licenses:
187
188
  - GPL-3.0-only
188
189
  metadata: {}
189
- post_install_message:
190
+ post_install_message:
190
191
  rdoc_options: []
191
192
  require_paths:
192
193
  - lib
@@ -202,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
202
203
  version: '0'
203
204
  requirements: []
204
205
  rubygems_version: 3.0.3
205
- signing_key:
206
+ signing_key:
206
207
  specification_version: 4
207
208
  summary: ops_team handles basic operations tasks for your project, driven by YAML
208
209
  config