ops_team 0.1.7 → 0.2.4
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/bin/print_config +4 -0
- data/bin/print_secrets +4 -0
- data/etc/ops.template.yml +2 -0
- data/etc/ruby.template.yml +8 -0
- data/etc/terraform.template.yml +7 -0
- data/lib/action.rb +34 -3
- data/lib/app_config.rb +38 -0
- data/lib/builtin.rb +6 -0
- data/lib/builtins/down.rb +7 -1
- data/lib/builtins/env.rb +6 -2
- data/lib/builtins/help.rb +42 -0
- data/lib/builtins/init.rb +6 -0
- data/lib/builtins/up.rb +7 -1
- data/lib/builtins/version.rb +32 -0
- data/lib/environment.rb +21 -0
- data/lib/ops.rb +32 -14
- data/lib/secrets.rb +28 -0
- data/ops_team.gemspec +28 -0
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb200091bd81044096f650bc1647958dd129b12b14c309516b7e7ce0324e8889
|
4
|
+
data.tar.gz: 0edf7442cd2106ac2de48b6c14d16510111fa10759fe320aaea1856f366c8703
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0379eecf548037718aebf63b722f9571f21410daafd13a6b9ae893cfe7d3fbd3c0a58c40ea10dd1ac35d52c1de580894a774859755185dd8c32eb130db6d31fc'
|
7
|
+
data.tar.gz: 6e08799eb7cf0c196c88e93ecd68f7d48beedd803291d07b362750c9d738785736e9db49ca3c02d180544efa731f7064d5b5537016db8427b826e8057e4a2210
|
data/bin/print_config
ADDED
data/bin/print_secrets
ADDED
data/etc/ops.template.yml
CHANGED
data/etc/ruby.template.yml
CHANGED
@@ -7,23 +7,31 @@ dependencies:
|
|
7
7
|
actions:
|
8
8
|
start:
|
9
9
|
command: echo update me
|
10
|
+
description: starts the app
|
10
11
|
stop:
|
11
12
|
command: echo update me too
|
13
|
+
description: stops the app
|
12
14
|
test:
|
13
15
|
command: rspec
|
14
16
|
alias: t
|
17
|
+
description: runs unit tests
|
15
18
|
test-watch:
|
16
19
|
command: rerun -x ops test
|
17
20
|
alias: tw
|
21
|
+
description: runs unit tests every time a file changes
|
18
22
|
lint:
|
19
23
|
command: bundle exec rubocop --safe-auto-correct
|
20
24
|
alias: l
|
25
|
+
description: runs rubocop with safe autocorrect
|
21
26
|
build:
|
22
27
|
command: gem build *.gemspec
|
23
28
|
alias: b
|
29
|
+
description: builds the gem
|
24
30
|
install:
|
25
31
|
command: gem install `ls -t *.gem | head -n1`
|
26
32
|
alias: i
|
33
|
+
description: installs the gem
|
27
34
|
build-and-install:
|
28
35
|
command: ops build && ops install
|
29
36
|
alias: bi
|
37
|
+
description: builds and installs the gem
|
data/etc/terraform.template.yml
CHANGED
@@ -9,21 +9,28 @@ actions:
|
|
9
9
|
apply:
|
10
10
|
command: terraform apply
|
11
11
|
alias: a
|
12
|
+
description: runs 'terraform apply'
|
12
13
|
apply-auto-approve:
|
13
14
|
command: terraform apply --auto-approve
|
14
15
|
alias: aa
|
16
|
+
description: runs 'terraform apply' with auto-approve
|
15
17
|
destroy:
|
16
18
|
command: terraform destroy
|
17
19
|
alias: d
|
20
|
+
description: runs 'terraform destroy'
|
18
21
|
destroy-auto-approve:
|
19
22
|
command: terraform destroy --auto-approve
|
20
23
|
alias: dd
|
24
|
+
description: runs 'terraform destroy' with auto-approve
|
21
25
|
plan:
|
22
26
|
command: terraform plan
|
23
27
|
alias: p
|
28
|
+
description: runs 'terraform plan'
|
24
29
|
graph:
|
25
30
|
command: terraform graph | dot -T pdf -o resource_graph.pdf
|
26
31
|
alias: g
|
32
|
+
description: runs 'terraform graph'
|
27
33
|
open-graph:
|
28
34
|
command: ops graph && open resource_graph.pdf
|
29
35
|
alias: og
|
36
|
+
description: opens the terraform graph with the OS 'open' command
|
data/lib/action.rb
CHANGED
@@ -1,18 +1,49 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'secrets'
|
4
|
+
|
3
5
|
# represents one action to be performed in the shell
|
4
6
|
# can assemble a command line from a command and args
|
5
7
|
class Action
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
+
def initialize(config, args, options)
|
9
|
+
@config = config
|
8
10
|
@args = args
|
11
|
+
@options = options
|
9
12
|
end
|
10
13
|
|
11
14
|
def run
|
15
|
+
load_secrets if load_secrets?
|
16
|
+
|
12
17
|
Kernel.exec(to_s)
|
13
18
|
end
|
14
19
|
|
15
20
|
def to_s
|
16
|
-
"#{
|
21
|
+
"#{command} #{@args.join(' ')}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def alias
|
25
|
+
@config["alias"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def command
|
29
|
+
@config["command"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def description
|
33
|
+
@config["description"]
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def load_secrets?
|
39
|
+
@config["load_secrets"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_secrets
|
43
|
+
Secrets.new(secrets_file).load
|
44
|
+
end
|
45
|
+
|
46
|
+
def secrets_file
|
47
|
+
`echo #{@options&.dig("secrets", "path")}`.chomp
|
17
48
|
end
|
18
49
|
end
|
data/lib/app_config.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class AppConfig
|
4
|
+
def initialize(filename = "")
|
5
|
+
@filename = filename.empty? ? default_filename : filename
|
6
|
+
end
|
7
|
+
|
8
|
+
def load
|
9
|
+
config['environment']&.each do |key, value|
|
10
|
+
ENV[key] = value
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def default_filename
|
17
|
+
"config/#{environment}/config.json"
|
18
|
+
end
|
19
|
+
|
20
|
+
def config
|
21
|
+
@config ||= file_contents ? JSON.parse(file_contents) : {}
|
22
|
+
rescue JSON::ParserError => e
|
23
|
+
Output.error("Error parsing config data: #{e}")
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_contents
|
28
|
+
@file_contents ||= begin
|
29
|
+
File.open(@filename).read
|
30
|
+
rescue Errno::ENOENT
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def environment
|
36
|
+
ENV['environment']
|
37
|
+
end
|
38
|
+
end
|
data/lib/builtin.rb
CHANGED
data/lib/builtins/down.rb
CHANGED
@@ -8,6 +8,12 @@ require 'builtins/helpers/dependency_handler'
|
|
8
8
|
|
9
9
|
module Builtins
|
10
10
|
class Down < Builtin
|
11
|
+
class << self
|
12
|
+
def description
|
13
|
+
"stops dependent services listed in ops.yml"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
def run
|
12
18
|
# TODO: return a success/failure status to the caller
|
13
19
|
unmeet_dependencies
|
@@ -39,7 +45,7 @@ module Builtins
|
|
39
45
|
else
|
40
46
|
Output.failed
|
41
47
|
Output.error("Error unmeeting #{dependency.type} dependency '#{dependency.name}':")
|
42
|
-
|
48
|
+
Output.out(dependency.output)
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
data/lib/builtins/env.rb
CHANGED
@@ -5,12 +5,16 @@ require 'output'
|
|
5
5
|
|
6
6
|
module Builtins
|
7
7
|
class Env < Builtin
|
8
|
+
class << self
|
9
|
+
def description
|
10
|
+
"prints the current environment, e.g. 'dev', 'production', 'staging', etc."
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
def run
|
9
15
|
Output.print(environment)
|
10
16
|
end
|
11
17
|
|
12
|
-
private
|
13
|
-
|
14
18
|
def environment
|
15
19
|
ENV['environment']
|
16
20
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'colorize'
|
4
|
+
|
5
|
+
require 'builtin'
|
6
|
+
|
7
|
+
module Builtins
|
8
|
+
class Help < Builtin
|
9
|
+
class << self
|
10
|
+
def description
|
11
|
+
"displays available builtins and actions"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
Output.out("Builtins:")
|
17
|
+
Output.out(" #{builtins.join("\n ")}")
|
18
|
+
Output.out("")
|
19
|
+
Output.out("Actions:")
|
20
|
+
Output.out(" #{actions.join("\n ")}")
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def builtins
|
26
|
+
builtin_class_names.map do |class_name|
|
27
|
+
description = Builtins.const_get(class_name).description
|
28
|
+
format("%<name>-35s %<desc>s", name: class_name.downcase.to_s.yellow, desc: description)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def builtin_class_names
|
33
|
+
Builtins.constants.select { |c| Builtins.const_get(c).is_a? Class }
|
34
|
+
end
|
35
|
+
|
36
|
+
def actions
|
37
|
+
@config["actions"].map do |name, value|
|
38
|
+
format("%<name>-35s %<desc>s", name: name.yellow, desc: value["description"] || value["command"])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/builtins/init.rb
CHANGED
@@ -12,6 +12,12 @@ module Builtins
|
|
12
12
|
OPS_YML_TEMPLATE = File.join(TEMPLATE_DIR, "%<template_name>s.template.yml")
|
13
13
|
DEFAULT_TEMPLATE_NAME = "ops"
|
14
14
|
|
15
|
+
class << self
|
16
|
+
def description
|
17
|
+
"creates an ops.yml file from a template"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
15
21
|
def run
|
16
22
|
if File.exist?(OPS_YML)
|
17
23
|
Output.error("File '#{OPS_YML} exists; not initializing.")
|
data/lib/builtins/up.rb
CHANGED
@@ -9,6 +9,12 @@ require 'output'
|
|
9
9
|
|
10
10
|
module Builtins
|
11
11
|
class Up < Builtin
|
12
|
+
class << self
|
13
|
+
def description
|
14
|
+
"attempts to meet dependencies listed in ops.yml"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
12
18
|
def run
|
13
19
|
# TODO: return a success/failure status to the caller
|
14
20
|
meet_dependencies
|
@@ -40,7 +46,7 @@ module Builtins
|
|
40
46
|
else
|
41
47
|
Output.failed
|
42
48
|
Output.error("Error meeting #{dependency.type} dependency '#{dependency.name}':")
|
43
|
-
|
49
|
+
Output.out(dependency.output)
|
44
50
|
end
|
45
51
|
end
|
46
52
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
|
5
|
+
require "output"
|
6
|
+
|
7
|
+
module Builtins
|
8
|
+
class Version < Builtin
|
9
|
+
GEMSPEC_FILE = "#{__dir__}/../../ops_team.gemspec"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def description
|
13
|
+
"prints the version of ops that is running"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
unless gemspec
|
19
|
+
Output.error("Unable to load gemspec at '#{GEMSPEC_FILE}")
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
Output.out(gemspec.version)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def gemspec
|
29
|
+
@gemspec ||= Gem::Specification.load(GEMSPEC_FILE)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/environment.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Environment
|
4
|
+
def initialize(env_hash)
|
5
|
+
@env_hash = env_hash
|
6
|
+
end
|
7
|
+
|
8
|
+
def set_variables
|
9
|
+
@env_hash.each do |key, value|
|
10
|
+
ENV[key] = value
|
11
|
+
end
|
12
|
+
|
13
|
+
ENV['environment'] = environment
|
14
|
+
end
|
15
|
+
|
16
|
+
def environment
|
17
|
+
return 'dev' if ENV['environment'].nil? || ENV['environment'].empty?
|
18
|
+
|
19
|
+
ENV['environment']
|
20
|
+
end
|
21
|
+
end
|
data/lib/ops.rb
CHANGED
@@ -7,9 +7,10 @@ require 'require_all'
|
|
7
7
|
require 'action'
|
8
8
|
require 'output'
|
9
9
|
require 'options'
|
10
|
+
require 'environment'
|
10
11
|
require_rel "builtins"
|
11
12
|
|
12
|
-
# executes commands
|
13
|
+
# executes commands based on local `ops.yml`
|
13
14
|
class Ops
|
14
15
|
class UnknownActionError < StandardError; end
|
15
16
|
|
@@ -27,7 +28,8 @@ class Ops
|
|
27
28
|
def run
|
28
29
|
exit(INVALID_SYNTAX_EXIT_CODE) unless syntax_valid?
|
29
30
|
|
30
|
-
|
31
|
+
environment.set_variables
|
32
|
+
app_config.load
|
31
33
|
|
32
34
|
return builtin.run if builtin
|
33
35
|
|
@@ -61,20 +63,16 @@ class Ops
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def action
|
64
|
-
@
|
65
|
-
|
66
|
-
|
67
|
-
def command
|
68
|
-
@command ||= begin
|
69
|
-
return actions[@action_name]["command"] if actions[@action_name]
|
70
|
-
return aliases[@action_name]["command"] if aliases[@action_name]
|
66
|
+
return actions[@action_name] if actions[@action_name]
|
67
|
+
return aliases[@action_name] if aliases[@action_name]
|
71
68
|
|
72
|
-
|
73
|
-
end
|
69
|
+
raise UnknownActionError, "Unknown action: #{@action_name}"
|
74
70
|
end
|
75
71
|
|
76
72
|
def actions
|
77
|
-
config["actions"]
|
73
|
+
config["actions"].transform_values do |config|
|
74
|
+
Action.new(config, @args, action_options)
|
75
|
+
end
|
78
76
|
end
|
79
77
|
|
80
78
|
def config
|
@@ -88,11 +86,31 @@ class Ops
|
|
88
86
|
|
89
87
|
def aliases
|
90
88
|
@aliases ||= begin
|
91
|
-
actions.each_with_object({}) do |(_name,
|
92
|
-
alias_hash[
|
89
|
+
actions.each_with_object({}) do |(_name, action), alias_hash|
|
90
|
+
alias_hash[action.alias] = action if action.alias
|
93
91
|
end
|
94
92
|
end
|
95
93
|
end
|
94
|
+
|
95
|
+
def action_options
|
96
|
+
@action_options ||= @config.dig("options", "actions")
|
97
|
+
end
|
98
|
+
|
99
|
+
def env_vars
|
100
|
+
@config.dig("options", "environment") || {}
|
101
|
+
end
|
102
|
+
|
103
|
+
def environment
|
104
|
+
@environment ||= Environment.new(env_vars)
|
105
|
+
end
|
106
|
+
|
107
|
+
def app_config_file
|
108
|
+
`echo #{@options&.dig("config", "path")}`.chomp
|
109
|
+
end
|
110
|
+
|
111
|
+
def app_config
|
112
|
+
@app_config ||= AppConfig.new(app_config_file)
|
113
|
+
end
|
96
114
|
end
|
97
115
|
|
98
116
|
Ops.new(ARGV).run if $PROGRAM_NAME == __FILE__
|
data/lib/secrets.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require 'output'
|
6
|
+
require 'app_config'
|
7
|
+
|
8
|
+
class Secrets < AppConfig
|
9
|
+
private
|
10
|
+
|
11
|
+
def default_filename
|
12
|
+
return default_ejson_filename if File.exist?(default_ejson_filename)
|
13
|
+
|
14
|
+
default_json_filename
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_ejson_filename
|
18
|
+
"config/#{environment}/secrets.ejson"
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_json_filename
|
22
|
+
"config/#{environment}/secrets.json"
|
23
|
+
end
|
24
|
+
|
25
|
+
def file_contents
|
26
|
+
@file_contents ||= @filename.match(/\.ejson$/) ? `ejson decrypt #{@filename}` : super
|
27
|
+
end
|
28
|
+
end
|
data/ops_team.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'ops_team'
|
5
|
+
s.version = '0.2.4'
|
6
|
+
s.authors = [
|
7
|
+
'nickthecook@gmail.com'
|
8
|
+
]
|
9
|
+
s.date = '2020-05-29'
|
10
|
+
s.summary = 'ops_team handles basic operations tasks for your project, driven by YAML config'
|
11
|
+
s.homepage = 'https://github.com/nickthecook/ops'
|
12
|
+
s.files = Dir[
|
13
|
+
'Gemfile',
|
14
|
+
'bin/*',
|
15
|
+
'lib/*',
|
16
|
+
'etc/*',
|
17
|
+
'lib/builtins/*',
|
18
|
+
'lib/builtins/helpers/*',
|
19
|
+
'lib/dependencies/*',
|
20
|
+
'loader.rb',
|
21
|
+
'ops_team.gemspec'
|
22
|
+
]
|
23
|
+
s.executables << 'ops'
|
24
|
+
s.required_ruby_version = '~> 2.5'
|
25
|
+
s.add_runtime_dependency 'colorize', '~> 0.8', '>= 0.8.1'
|
26
|
+
s.add_runtime_dependency 'require_all', '~> 1.1', '>= 1.1.6'
|
27
|
+
s.license = 'GPL-3.0-only'
|
28
|
+
end
|
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.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nickthecook@gmail.com
|
@@ -59,17 +59,22 @@ extra_rdoc_files: []
|
|
59
59
|
files:
|
60
60
|
- Gemfile
|
61
61
|
- bin/ops
|
62
|
+
- bin/print_config
|
63
|
+
- bin/print_secrets
|
62
64
|
- bin/tag
|
63
65
|
- etc/ops.template.yml
|
64
66
|
- etc/ruby.template.yml
|
65
67
|
- etc/terraform.template.yml
|
66
68
|
- lib/action.rb
|
69
|
+
- lib/app_config.rb
|
67
70
|
- lib/builtin.rb
|
68
71
|
- lib/builtins/down.rb
|
69
72
|
- lib/builtins/env.rb
|
73
|
+
- lib/builtins/help.rb
|
70
74
|
- lib/builtins/helpers/dependency_handler.rb
|
71
75
|
- lib/builtins/init.rb
|
72
76
|
- lib/builtins/up.rb
|
77
|
+
- lib/builtins/version.rb
|
73
78
|
- lib/dependencies/apk.rb
|
74
79
|
- lib/dependencies/apt.rb
|
75
80
|
- lib/dependencies/brew.rb
|
@@ -80,10 +85,13 @@ files:
|
|
80
85
|
- lib/dependencies/gem.rb
|
81
86
|
- lib/dependencies/terraform.rb
|
82
87
|
- lib/dependency.rb
|
88
|
+
- lib/environment.rb
|
83
89
|
- lib/ops.rb
|
84
90
|
- lib/options.rb
|
85
91
|
- lib/output.rb
|
92
|
+
- lib/secrets.rb
|
86
93
|
- loader.rb
|
94
|
+
- ops_team.gemspec
|
87
95
|
homepage: https://github.com/nickthecook/ops
|
88
96
|
licenses:
|
89
97
|
- GPL-3.0-only
|