ops_team 0.1.1
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 +7 -0
- data/Gemfile +20 -0
- data/bin/ops +8 -0
- data/bin/tag +16 -0
- data/etc/ops.template.yml +11 -0
- data/etc/ruby.template.yml +29 -0
- data/etc/terraform.template.yml +26 -0
- data/lib/action.rb +18 -0
- data/lib/builtin.rb +12 -0
- data/lib/builtins/down.rb +46 -0
- data/lib/builtins/env.rb +18 -0
- data/lib/builtins/helpers/dependency_handler.rb +33 -0
- data/lib/builtins/init.rb +51 -0
- data/lib/builtins/up.rb +47 -0
- data/lib/dependencies/apk.rb +26 -0
- data/lib/dependencies/apt.rb +24 -0
- data/lib/dependencies/brew.rb +24 -0
- data/lib/dependencies/cask.rb +15 -0
- data/lib/dependencies/custom.rb +21 -0
- data/lib/dependencies/docker.rb +19 -0
- data/lib/dependencies/gem.rb +27 -0
- data/lib/dependencies/terraform.rb +23 -0
- data/lib/dependency.rb +59 -0
- data/lib/ops.rb +96 -0
- data/lib/options.rb +13 -0
- data/lib/output.rb +63 -0
- data/loader.rb +4 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fa5c498bf634206ab5ef4e53313731fb1ab8ee71456051d03f0b50d7b98f71ab
|
4
|
+
data.tar.gz: 6167a9ec3c12915fe62f3ccc3de1ce2a7f22351d32a7b2c10d8bb2b3c6da291d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0273b1834ceb76c119328e45574ba27a924bb9ba50334661ad78ffebee8883f6efa0de75f8a97536d351103e36c64accd29ac1ae68892085828600b1c85de2fb
|
7
|
+
data.tar.gz: f021f9ea483736c3e13692d58f9284c105117fac4b1b873dd8918b9e5b123b4bd900c8b4735805a1b7f5f149c4ff8fb5c9a5f5efafb5e75644c1c3e9ebbf5001
|
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
|
+
|
7
|
+
gem "colorize"
|
8
|
+
gem "require_all"
|
9
|
+
|
10
|
+
group :test do
|
11
|
+
gem "fuubar"
|
12
|
+
gem "rspec"
|
13
|
+
end
|
14
|
+
|
15
|
+
group :development do
|
16
|
+
gem "pry"
|
17
|
+
gem "pry-byebug"
|
18
|
+
gem "rerun"
|
19
|
+
gem "rubocop"
|
20
|
+
end
|
data/bin/ops
ADDED
data/bin/tag
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# tags a commit, asking for input when needed
|
3
|
+
|
4
|
+
if [ -n "$1" ]; then
|
5
|
+
tag="$1"
|
6
|
+
else
|
7
|
+
tag=$(grep -o "'[0-9.]*'" ops_team.gemspec | sed "s/'//g")
|
8
|
+
if [ -z "$tag" ]; then
|
9
|
+
read -p "Enter tag value: " tag
|
10
|
+
fi
|
11
|
+
fi
|
12
|
+
|
13
|
+
comment="Tagging $tag for release"
|
14
|
+
echo "Tagging '$tag' with comment '$comment'..."
|
15
|
+
git tag -a "$tag" -m "$comment"
|
16
|
+
git push origin "$tag"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
dependencies:
|
2
|
+
gem:
|
3
|
+
- bundler
|
4
|
+
- rerun
|
5
|
+
custom:
|
6
|
+
- bundle
|
7
|
+
actions:
|
8
|
+
start:
|
9
|
+
command: echo update me
|
10
|
+
stop:
|
11
|
+
command: echo update me too
|
12
|
+
test:
|
13
|
+
command: rspec
|
14
|
+
alias: t
|
15
|
+
test-watch:
|
16
|
+
command: rerun -x ops test
|
17
|
+
alias: tw
|
18
|
+
lint:
|
19
|
+
command: bundle exec rubocop --safe-auto-correct
|
20
|
+
alias: l
|
21
|
+
build:
|
22
|
+
command: gem build *.gemspec
|
23
|
+
alias: b
|
24
|
+
install:
|
25
|
+
command: gem install `ls -t *.gem | head -n1`
|
26
|
+
alias: i
|
27
|
+
build-and-install:
|
28
|
+
command: ops build && ops install
|
29
|
+
alias: bi
|
@@ -0,0 +1,26 @@
|
|
1
|
+
dependencies:
|
2
|
+
brew:
|
3
|
+
- terraform
|
4
|
+
apt:
|
5
|
+
- terraform
|
6
|
+
custom:
|
7
|
+
- terraform init
|
8
|
+
actions:
|
9
|
+
apply:
|
10
|
+
command: terraform apply
|
11
|
+
alias: a
|
12
|
+
apply-auto-approve:
|
13
|
+
command: terraform apply --auto-approve
|
14
|
+
alias: aa
|
15
|
+
destroy:
|
16
|
+
command: terraform destroy
|
17
|
+
alias: d
|
18
|
+
destroy-auto-approve:
|
19
|
+
command: terraform destroy --auto-approve
|
20
|
+
alias: dd
|
21
|
+
plan:
|
22
|
+
command: terraform plan
|
23
|
+
alias: p
|
24
|
+
graph:
|
25
|
+
command: terraform graph
|
26
|
+
alias: g
|
data/lib/action.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# represents one action to be performed in the shell
|
4
|
+
# can assemble a command line from a command and args
|
5
|
+
class Action
|
6
|
+
def initialize(command, args)
|
7
|
+
@command = command
|
8
|
+
@args = args
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
Kernel.exec(to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"#{@command} #{@args.join(' ')}"
|
17
|
+
end
|
18
|
+
end
|
data/lib/builtin.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'require_all'
|
4
|
+
require_rel "../dependencies"
|
5
|
+
|
6
|
+
require 'builtin'
|
7
|
+
require 'builtins/helpers/dependency_handler'
|
8
|
+
|
9
|
+
module Builtins
|
10
|
+
class Down < Builtin
|
11
|
+
def run
|
12
|
+
# TODO: return a success/failure status to the caller
|
13
|
+
unmeet_dependencies
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def dependency_handler
|
19
|
+
Helpers::DependencyHandler.new(@config["dependencies"])
|
20
|
+
end
|
21
|
+
|
22
|
+
def unmeet_dependencies
|
23
|
+
dependency_handler.dependencies.each do |dependency|
|
24
|
+
# don't even output anything for dependencies that shouldn't be considered on this machine
|
25
|
+
next unless dependency.should_meet?
|
26
|
+
|
27
|
+
Output.status("[#{dependency.type}] #{dependency.name}")
|
28
|
+
|
29
|
+
unmeet_dependency(dependency)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def unmeet_dependency(dependency)
|
34
|
+
# TODO: make this simpler, and factor in `should_meet?` above, too
|
35
|
+
dependency.unmeet if dependency.met? || dependency.always_act?
|
36
|
+
|
37
|
+
if dependency.success?
|
38
|
+
Output.okay
|
39
|
+
else
|
40
|
+
Output.failed
|
41
|
+
Output.error("Error unmeeting #{dependency.type} dependency '#{dependency.name}':")
|
42
|
+
puts(dependency.output)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/builtins/env.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'builtin'
|
4
|
+
require 'output'
|
5
|
+
|
6
|
+
module Builtins
|
7
|
+
class Env < Builtin
|
8
|
+
def run
|
9
|
+
Output.print(environment)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def environment
|
15
|
+
ENV['environment'] || 'dev'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'builtin'
|
4
|
+
require 'output'
|
5
|
+
|
6
|
+
require 'require_all'
|
7
|
+
require_rel "../../dependencies"
|
8
|
+
|
9
|
+
module Builtins
|
10
|
+
module Helpers
|
11
|
+
class DependencyHandler
|
12
|
+
def initialize(dependency_set)
|
13
|
+
@dependency_set = dependency_set
|
14
|
+
end
|
15
|
+
|
16
|
+
def dependencies
|
17
|
+
return [] unless @dependency_set
|
18
|
+
|
19
|
+
@dependency_set.map do |type, names|
|
20
|
+
dependencies_for(type, names)
|
21
|
+
end.flatten
|
22
|
+
end
|
23
|
+
|
24
|
+
def dependencies_for(type, names)
|
25
|
+
dependency_class = Dependencies.const_get(type.capitalize.to_sym)
|
26
|
+
|
27
|
+
names.map { |name| dependency_class.new(name) }
|
28
|
+
rescue NameError
|
29
|
+
Output.error("No way to handle dependencies of type '#{type}'; ignoring.")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'builtin'
|
6
|
+
require 'output'
|
7
|
+
|
8
|
+
module Builtins
|
9
|
+
class Init < Builtin
|
10
|
+
OPS_YML = "ops.yml"
|
11
|
+
TEMPLATE_DIR = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "etc"))
|
12
|
+
OPS_YML_TEMPLATE = File.join(TEMPLATE_DIR, "%<template_name>s.template.yml")
|
13
|
+
DEFAULT_TEMPLATE_NAME = "ops"
|
14
|
+
|
15
|
+
def run
|
16
|
+
if File.exist?(OPS_YML)
|
17
|
+
Output.error("File '#{OPS_YML} exists; not initializing.")
|
18
|
+
else
|
19
|
+
Output.out("Creating '#{OPS_YML} from template...")
|
20
|
+
FileUtils.cp(template_path, OPS_YML)
|
21
|
+
end
|
22
|
+
rescue SystemCallError
|
23
|
+
Output.error(template_not_found_message)
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def template_name_arg
|
30
|
+
@args[0]
|
31
|
+
end
|
32
|
+
|
33
|
+
def template_path
|
34
|
+
format(OPS_YML_TEMPLATE, template_name: template_name_arg || DEFAULT_TEMPLATE_NAME)
|
35
|
+
end
|
36
|
+
|
37
|
+
def template_name_list
|
38
|
+
@template_name_list ||= Dir.entries(TEMPLATE_DIR).map do |name|
|
39
|
+
name.match(/^([^.]*).template.yml/)&.captures&.first
|
40
|
+
end.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def template_not_found_message
|
44
|
+
<<~MESSAGE
|
45
|
+
Template '#{template_path} does not exist.
|
46
|
+
\nValid template names are:
|
47
|
+
- #{template_name_list.join("\n - ")}\n
|
48
|
+
MESSAGE
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/builtins/up.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'require_all'
|
4
|
+
require_rel "../dependencies"
|
5
|
+
|
6
|
+
require 'builtin'
|
7
|
+
require 'builtins/helpers/dependency_handler'
|
8
|
+
require 'output'
|
9
|
+
|
10
|
+
module Builtins
|
11
|
+
class Up < Builtin
|
12
|
+
def run
|
13
|
+
# TODO: return a success/failure status to the caller
|
14
|
+
meet_dependencies
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def dependency_handler
|
20
|
+
Helpers::DependencyHandler.new(@config["dependencies"])
|
21
|
+
end
|
22
|
+
|
23
|
+
def meet_dependencies
|
24
|
+
dependency_handler.dependencies.each do |dependency|
|
25
|
+
# don't even output anything for dependencies that shouldn't be considered on this machine
|
26
|
+
next unless dependency.should_meet?
|
27
|
+
|
28
|
+
Output.status("[#{dependency.type}] #{dependency.name}")
|
29
|
+
|
30
|
+
meet_dependency(dependency)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def meet_dependency(dependency)
|
35
|
+
# TODO: make this simpler, and factor in `should_meet?` above, too
|
36
|
+
dependency.meet if !dependency.met? || dependency.always_act?
|
37
|
+
|
38
|
+
if dependency.success?
|
39
|
+
Output.okay
|
40
|
+
else
|
41
|
+
Output.failed
|
42
|
+
Output.error("Error meeting #{dependency.type} dependency '#{dependency.name}':")
|
43
|
+
puts(dependency.output)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'English'
|
4
|
+
|
5
|
+
require 'dependency'
|
6
|
+
|
7
|
+
module Dependencies
|
8
|
+
class Apk < Dependency
|
9
|
+
def met?
|
10
|
+
execute("apk info | grep -q #{name}")
|
11
|
+
end
|
12
|
+
|
13
|
+
def meet
|
14
|
+
execute("apk add #{name}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def unmeet
|
18
|
+
# do nothing; we don't want to uninstall packages and reinstall them every time
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def should_meet?
|
23
|
+
system("which apk")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
|
5
|
+
module Dependencies
|
6
|
+
class Apt < Dependency
|
7
|
+
def met?
|
8
|
+
execute("dpkg-query --show --showformat '${db:Status-Status}\n' #{name} | grep -q ^installed")
|
9
|
+
end
|
10
|
+
|
11
|
+
def meet
|
12
|
+
execute("apt-get install -y #{name}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unmeet
|
16
|
+
# do nothing; we don't want to uninstall packages and reinstall them every time
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def should_meet?
|
21
|
+
`uname`.chomp == "Linux"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
|
5
|
+
module Dependencies
|
6
|
+
class Brew < Dependency
|
7
|
+
def met?
|
8
|
+
execute("brew list #{name}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def meet
|
12
|
+
execute("brew install #{name}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unmeet
|
16
|
+
# do nothing; we don't want to uninstall packages and reinstall them every time
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def should_meet?
|
21
|
+
`uname`.chomp == "Darwin"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
|
5
|
+
module Dependencies
|
6
|
+
class Custom < Dependency
|
7
|
+
def met?
|
8
|
+
# we always want to try to meet this dependency
|
9
|
+
false
|
10
|
+
end
|
11
|
+
|
12
|
+
def meet
|
13
|
+
# this dependency is just a custom, idempotent command
|
14
|
+
execute(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def unmeet
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
|
5
|
+
module Dependencies
|
6
|
+
class Docker < Dependency
|
7
|
+
def met?
|
8
|
+
execute("cd #{name} && docker-compose ps | grep -q ' Up '")
|
9
|
+
end
|
10
|
+
|
11
|
+
def meet
|
12
|
+
execute("cd #{name} && docker-compose up -d")
|
13
|
+
end
|
14
|
+
|
15
|
+
def unmeet
|
16
|
+
execute("cd #{name} && docker-compose down")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
require 'options'
|
5
|
+
|
6
|
+
module Dependencies
|
7
|
+
class Gem < Dependency
|
8
|
+
def met?
|
9
|
+
execute("gem list -i '^#{name}$'")
|
10
|
+
end
|
11
|
+
|
12
|
+
def meet
|
13
|
+
if Options.get("gem.use_sudo")
|
14
|
+
execute("sudo gem install #{name}")
|
15
|
+
elsif Options.get("gem.user_install")
|
16
|
+
execute("gem install --user-install #{name}")
|
17
|
+
else
|
18
|
+
execute("gem install #{name}")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def unmeet
|
23
|
+
# do nothing; we don't want to uninstall packages and reinstall them every time
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dependency'
|
4
|
+
|
5
|
+
module Dependencies
|
6
|
+
class Terraform < Dependency
|
7
|
+
def met?
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def always_act?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def meet
|
16
|
+
execute("cd #{name} && terraform init && terraform apply -input=false --auto-approve")
|
17
|
+
end
|
18
|
+
|
19
|
+
def unmeet
|
20
|
+
execute("cd #{name} && terraform destroy -input=false --auto-approve")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/dependency.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'open3'
|
4
|
+
require 'English'
|
5
|
+
|
6
|
+
require 'output'
|
7
|
+
|
8
|
+
class Dependency
|
9
|
+
DESCRIPTION_TYPE_WIDTH = 8
|
10
|
+
|
11
|
+
attr_reader :name, :output, :exit_code
|
12
|
+
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
end
|
16
|
+
|
17
|
+
def met?
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def meet
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
def unmeet
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
29
|
+
# should_meet? can be used to implement dependencies that should only be met on some platforms,
|
30
|
+
# e.g. brew on Macs and apt on Linux
|
31
|
+
# it can be used to base a decision on anything else that can be read from the environment at
|
32
|
+
# runtime
|
33
|
+
def should_meet?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
# if true, this type of resource must always have `meet` and `unmeet` called;
|
38
|
+
# useful for resources that can't easily be checked to see if they're met
|
39
|
+
def always_act?
|
40
|
+
false
|
41
|
+
end
|
42
|
+
|
43
|
+
def type
|
44
|
+
self.class.name.split('::').last
|
45
|
+
end
|
46
|
+
|
47
|
+
def success?
|
48
|
+
@exit_code.nil? ? true : @exit_code.zero?
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def execute(cmd)
|
54
|
+
@output, status = Open3.capture2e(cmd)
|
55
|
+
@exit_code = status.exitstatus
|
56
|
+
|
57
|
+
success?
|
58
|
+
end
|
59
|
+
end
|
data/lib/ops.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'require_all'
|
6
|
+
|
7
|
+
require 'action'
|
8
|
+
require 'output'
|
9
|
+
require 'options'
|
10
|
+
require_rel "builtins"
|
11
|
+
|
12
|
+
# executes commands defined in local `ops.yml`
|
13
|
+
class Ops
|
14
|
+
class UnknownActionError < StandardError; end
|
15
|
+
|
16
|
+
CONFIG_FILE = "ops.yml"
|
17
|
+
|
18
|
+
INVALID_SYNTAX_EXIT_CODE = 1
|
19
|
+
|
20
|
+
def initialize(argv)
|
21
|
+
@action_name = argv[0]
|
22
|
+
@args = argv[1..-1]
|
23
|
+
|
24
|
+
Options.set(config["options"] || {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
exit(INVALID_SYNTAX_EXIT_CODE) unless syntax_valid?
|
29
|
+
|
30
|
+
return builtin.run if builtin
|
31
|
+
|
32
|
+
Output.warn("Running '#{action}' from #{CONFIG_FILE}...")
|
33
|
+
action.run
|
34
|
+
rescue UnknownActionError => e
|
35
|
+
Output.error("Error: #{e}")
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def syntax_valid?
|
41
|
+
if @action_name.nil?
|
42
|
+
# TODO: output to stderr
|
43
|
+
puts "Usage: ops <action>"
|
44
|
+
false
|
45
|
+
else
|
46
|
+
true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def builtin
|
51
|
+
@builtin ||= Builtins.const_get(builtin_class_name).new(@args, config)
|
52
|
+
rescue NameError
|
53
|
+
# this means there isn't a builtin with that name in that module
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def builtin_class_name
|
58
|
+
@action_name.capitalize.to_sym
|
59
|
+
end
|
60
|
+
|
61
|
+
def action
|
62
|
+
@action ||= Action.new(command, @args)
|
63
|
+
end
|
64
|
+
|
65
|
+
def command
|
66
|
+
@command ||= begin
|
67
|
+
return actions[@action_name]["command"] if actions[@action_name]
|
68
|
+
return aliases[@action_name]["command"] if aliases[@action_name]
|
69
|
+
|
70
|
+
raise UnknownActionError, "Unknown action: #{@action_name}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def actions
|
75
|
+
config["actions"]
|
76
|
+
end
|
77
|
+
|
78
|
+
def config
|
79
|
+
@config ||= begin
|
80
|
+
Output.warn("File '#{CONFIG_FILE}' does not exist.") unless File.exist?(CONFIG_FILE)
|
81
|
+
YAML.load_file(CONFIG_FILE)
|
82
|
+
rescue StandardError
|
83
|
+
{}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def aliases
|
88
|
+
@aliases ||= begin
|
89
|
+
actions.each_with_object({}) do |(_name, body), alias_hash|
|
90
|
+
alias_hash[body["alias"]] = body if body.include?("alias")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Ops.new(ARGV).run if $PROGRAM_NAME == __FILE__
|
data/lib/options.rb
ADDED
data/lib/output.rb
ADDED
@@ -0,0 +1,63 @@
|
|
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
|
+
def error(msg)
|
44
|
+
@err.puts(msg.red)
|
45
|
+
end
|
46
|
+
|
47
|
+
def out(msg)
|
48
|
+
@out.puts(msg)
|
49
|
+
end
|
50
|
+
|
51
|
+
def print(msg)
|
52
|
+
@out.print(msg)
|
53
|
+
end
|
54
|
+
|
55
|
+
def silence
|
56
|
+
@out = @err = dummy_output
|
57
|
+
end
|
58
|
+
|
59
|
+
def dummy_output
|
60
|
+
@dummy_output ||= DummyOutput.new
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/loader.rb
ADDED
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ops_team
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- nickthecook@gmail.com
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.8.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.8'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: require_all
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.1'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.1.6
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.1'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.1.6
|
53
|
+
description:
|
54
|
+
email:
|
55
|
+
executables:
|
56
|
+
- ops
|
57
|
+
extensions: []
|
58
|
+
extra_rdoc_files: []
|
59
|
+
files:
|
60
|
+
- Gemfile
|
61
|
+
- bin/ops
|
62
|
+
- bin/tag
|
63
|
+
- etc/ops.template.yml
|
64
|
+
- etc/ruby.template.yml
|
65
|
+
- etc/terraform.template.yml
|
66
|
+
- lib/action.rb
|
67
|
+
- lib/builtin.rb
|
68
|
+
- lib/builtins/down.rb
|
69
|
+
- lib/builtins/env.rb
|
70
|
+
- lib/builtins/helpers/dependency_handler.rb
|
71
|
+
- lib/builtins/init.rb
|
72
|
+
- lib/builtins/up.rb
|
73
|
+
- lib/dependencies/apk.rb
|
74
|
+
- lib/dependencies/apt.rb
|
75
|
+
- lib/dependencies/brew.rb
|
76
|
+
- lib/dependencies/cask.rb
|
77
|
+
- lib/dependencies/custom.rb
|
78
|
+
- lib/dependencies/docker.rb
|
79
|
+
- lib/dependencies/gem.rb
|
80
|
+
- lib/dependencies/terraform.rb
|
81
|
+
- lib/dependency.rb
|
82
|
+
- lib/ops.rb
|
83
|
+
- lib/options.rb
|
84
|
+
- lib/output.rb
|
85
|
+
- loader.rb
|
86
|
+
homepage:
|
87
|
+
licenses:
|
88
|
+
- GPL-3.0-only
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubygems_version: 3.0.3
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: ops_team handles basic operations tasks for your project, driven by YAML
|
109
|
+
config
|
110
|
+
test_files: []
|