careacademy-runbook 1.2.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.
Files changed (104) hide show
  1. checksums.yaml +7 -0
  2. data/.dockerignore +17 -0
  3. data/.github/workflows/ruby.yml +43 -0
  4. data/.gitignore +16 -0
  5. data/.rspec +2 -0
  6. data/.ruby-gemset +1 -0
  7. data/.ruby-version +1 -0
  8. data/Appraisals +8 -0
  9. data/CHANGELOG.md +143 -0
  10. data/CODE_OF_CONDUCT.md +74 -0
  11. data/Gemfile +6 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +1272 -0
  14. data/Rakefile +12 -0
  15. data/TODO.md +316 -0
  16. data/bin/console +16 -0
  17. data/bin/setup +8 -0
  18. data/dockerfiles/Dockerfile-runbook +18 -0
  19. data/dockerfiles/Dockerfile-sshd +4 -0
  20. data/examples/hooks_runbook.rb +72 -0
  21. data/examples/layout_runbook.rb +26 -0
  22. data/examples/restart_nginx.rb +26 -0
  23. data/examples/simple_runbook.rb +41 -0
  24. data/examples/suppress_capture_output.rb +47 -0
  25. data/exe/runbook +5 -0
  26. data/gemfiles/.bundle/config +2 -0
  27. data/gemfiles/activesupport_5.gemfile +7 -0
  28. data/gemfiles/activesupport_6.gemfile +7 -0
  29. data/images/runbook_anatomy_diagram.png +0 -0
  30. data/images/runbook_example.gif +0 -0
  31. data/images/runbook_execution_modes.png +0 -0
  32. data/lib/hacks/ssh_kit.rb +58 -0
  33. data/lib/runbook/airbrussh_context.rb +25 -0
  34. data/lib/runbook/cli.rb +115 -0
  35. data/lib/runbook/cli_base.rb +38 -0
  36. data/lib/runbook/configuration.rb +120 -0
  37. data/lib/runbook/dsl.rb +21 -0
  38. data/lib/runbook/entities/book.rb +17 -0
  39. data/lib/runbook/entities/section.rb +7 -0
  40. data/lib/runbook/entities/setup.rb +7 -0
  41. data/lib/runbook/entities/step.rb +7 -0
  42. data/lib/runbook/entity.rb +129 -0
  43. data/lib/runbook/errors.rb +7 -0
  44. data/lib/runbook/extensions/add.rb +14 -0
  45. data/lib/runbook/extensions/description.rb +14 -0
  46. data/lib/runbook/extensions/sections.rb +19 -0
  47. data/lib/runbook/extensions/setup.rb +17 -0
  48. data/lib/runbook/extensions/shared_variables.rb +51 -0
  49. data/lib/runbook/extensions/ssh_config.rb +78 -0
  50. data/lib/runbook/extensions/statements.rb +31 -0
  51. data/lib/runbook/extensions/steps.rb +24 -0
  52. data/lib/runbook/extensions/tmux.rb +13 -0
  53. data/lib/runbook/generator.rb +38 -0
  54. data/lib/runbook/generators/base.rb +45 -0
  55. data/lib/runbook/generators/dsl_extension/dsl_extension.rb +29 -0
  56. data/lib/runbook/generators/dsl_extension/templates/dsl_extension.tt +25 -0
  57. data/lib/runbook/generators/generator/generator.rb +43 -0
  58. data/lib/runbook/generators/generator/templates/generator.tt +53 -0
  59. data/lib/runbook/generators/project/project.rb +301 -0
  60. data/lib/runbook/generators/project/templates/Gemfile.tt +6 -0
  61. data/lib/runbook/generators/project/templates/README.md.tt +29 -0
  62. data/lib/runbook/generators/project/templates/Runbookfile.tt +11 -0
  63. data/lib/runbook/generators/project/templates/base_file.rb.tt +8 -0
  64. data/lib/runbook/generators/runbook/runbook.rb +22 -0
  65. data/lib/runbook/generators/runbook/templates/runbook.tt +20 -0
  66. data/lib/runbook/generators/statement/statement.rb +18 -0
  67. data/lib/runbook/generators/statement/templates/statement.tt +34 -0
  68. data/lib/runbook/helpers/format_helper.rb +11 -0
  69. data/lib/runbook/helpers/ssh_kit_helper.rb +143 -0
  70. data/lib/runbook/helpers/tmux_helper.rb +176 -0
  71. data/lib/runbook/hooks.rb +88 -0
  72. data/lib/runbook/initializer.rb +85 -0
  73. data/lib/runbook/node.rb +33 -0
  74. data/lib/runbook/run.rb +290 -0
  75. data/lib/runbook/runner.rb +66 -0
  76. data/lib/runbook/runs/ssh_kit.rb +193 -0
  77. data/lib/runbook/statement.rb +20 -0
  78. data/lib/runbook/statements/ask.rb +12 -0
  79. data/lib/runbook/statements/assert.rb +34 -0
  80. data/lib/runbook/statements/capture.rb +14 -0
  81. data/lib/runbook/statements/capture_all.rb +14 -0
  82. data/lib/runbook/statements/command.rb +11 -0
  83. data/lib/runbook/statements/confirm.rb +10 -0
  84. data/lib/runbook/statements/description.rb +9 -0
  85. data/lib/runbook/statements/download.rb +12 -0
  86. data/lib/runbook/statements/layout.rb +10 -0
  87. data/lib/runbook/statements/note.rb +10 -0
  88. data/lib/runbook/statements/notice.rb +10 -0
  89. data/lib/runbook/statements/ruby_command.rb +9 -0
  90. data/lib/runbook/statements/tmux_command.rb +11 -0
  91. data/lib/runbook/statements/upload.rb +12 -0
  92. data/lib/runbook/statements/wait.rb +10 -0
  93. data/lib/runbook/toolbox.rb +37 -0
  94. data/lib/runbook/util/repo.rb +57 -0
  95. data/lib/runbook/util/runbook.rb +43 -0
  96. data/lib/runbook/util/sticky_hash.rb +26 -0
  97. data/lib/runbook/util/stored_pose.rb +55 -0
  98. data/lib/runbook/version.rb +3 -0
  99. data/lib/runbook/view.rb +24 -0
  100. data/lib/runbook/viewer.rb +24 -0
  101. data/lib/runbook/views/markdown.rb +117 -0
  102. data/lib/runbook.rb +140 -0
  103. data/runbook.gemspec +53 -0
  104. metadata +419 -0
@@ -0,0 +1,10 @@
1
+ module Runbook::Statements
2
+ class Layout < Runbook::Statement
3
+ attr_reader :structure
4
+
5
+ def initialize(structure)
6
+ @structure = structure
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,10 @@
1
+ module Runbook::Statements
2
+ class Note < Runbook::Statement
3
+ attr_reader :msg
4
+
5
+ def initialize(msg)
6
+ @msg = msg
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,10 @@
1
+ module Runbook::Statements
2
+ class Notice < Runbook::Statement
3
+ attr_reader :msg
4
+
5
+ def initialize(msg)
6
+ @msg = msg
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,9 @@
1
+ module Runbook::Statements
2
+ class RubyCommand < Runbook::Statement
3
+ attr_reader :block
4
+
5
+ def initialize(&block)
6
+ @block = block
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module Runbook::Statements
2
+ class TmuxCommand < Runbook::Statement
3
+ attr_reader :cmd, :pane
4
+
5
+ def initialize(cmd, pane)
6
+ @cmd = cmd
7
+ @pane = pane
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,12 @@
1
+ module Runbook::Statements
2
+ class Upload < Runbook::Statement
3
+ attr_reader :from, :to, :options, :ssh_config
4
+
5
+ def initialize(from, to:, ssh_config: nil, options: {})
6
+ @from = from
7
+ @to = to
8
+ @ssh_config = ssh_config
9
+ @options = options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Runbook::Statements
2
+ class Wait < Runbook::Statement
3
+ attr_reader :time
4
+
5
+ def initialize(time)
6
+ @time = time
7
+ end
8
+ end
9
+ end
10
+
@@ -0,0 +1,37 @@
1
+ module Runbook
2
+ class Toolbox
3
+ attr_reader :prompt
4
+
5
+ def initialize
6
+ @prompt = TTY::Prompt.new
7
+ end
8
+
9
+ def ask(msg, default: nil, echo: true)
10
+ prompt.ask(msg, default: default, echo: echo)
11
+ end
12
+
13
+ def expand(msg, choices)
14
+ prompt.expand(msg, choices)
15
+ end
16
+
17
+ def yes?(msg)
18
+ prompt.yes?(msg)
19
+ end
20
+
21
+ def output(msg)
22
+ prompt.say(msg)
23
+ end
24
+
25
+ def warn(msg)
26
+ prompt.warn(msg)
27
+ end
28
+
29
+ def error(msg)
30
+ prompt.error(msg)
31
+ end
32
+
33
+ def exit(return_value)
34
+ super(return_value)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,57 @@
1
+ module Runbook::Util
2
+ module Repo
3
+ FILE_ID = "data"
4
+ FILE_PERMISSIONS = 0600
5
+
6
+ def self.load(metadata)
7
+ title = metadata[:book_title]
8
+ file = _file(title)
9
+ if File.exist?(file)
10
+ msg = "Repo file #{file} detected. Loading previous state..."
11
+ metadata[:toolbox].output(msg)
12
+ metadata[:repo] = ::YAML::load_file(file)
13
+ end
14
+ end
15
+
16
+ def self.save(repo, book_title:)
17
+ File.open(_file(book_title), 'w', FILE_PERMISSIONS) do |f|
18
+ f.write(repo.to_yaml)
19
+ end
20
+ end
21
+
22
+ def self.delete(title)
23
+ FileUtils.rm_f(_file(title))
24
+ end
25
+
26
+ def self._file(book_title)
27
+ "#{Dir.tmpdir}/runbook_#{FILE_ID}_#{ENV["USER"]}_#{_slug(book_title)}.yml"
28
+ end
29
+
30
+ def self._slug(title)
31
+ title.titleize.gsub(/[\/\s]+/, "").underscore.dasherize
32
+ end
33
+
34
+ def self.register_save_repo_hook(base)
35
+ base.register_hook(
36
+ :save_repo_hook,
37
+ :after,
38
+ Object,
39
+ ) do |object, metadata|
40
+ repo = metadata[:repo]
41
+ title = metadata[:book_title]
42
+ Runbook::Util::Repo.save(repo, book_title: title)
43
+ end
44
+ end
45
+
46
+ def self.register_delete_stored_repo_hook(base)
47
+ base.register_hook(
48
+ :delete_stored_repo_hook,
49
+ :after,
50
+ Runbook::Entities::Book,
51
+ ) do |object, metadata|
52
+ title = metadata[:book_title]
53
+ Runbook::Util::Repo.delete(title)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,43 @@
1
+ module Runbook
2
+ def self.entities
3
+ _child_classes(Runbook::Entities)
4
+ end
5
+
6
+ def self.statements
7
+ _child_classes(Runbook::Statements)
8
+ end
9
+
10
+ def self.runs
11
+ _child_modules(Runbook::Runs)
12
+ end
13
+
14
+ def self.views
15
+ _child_modules(Runbook::Views)
16
+ end
17
+
18
+ def self.generators
19
+ _child_classes(Runbook::Generators)
20
+ end
21
+
22
+ def self.deprecator
23
+ return @deprecator if @deprecator
24
+ major_version = Gem::Version.new(Runbook::VERSION).segments[0]
25
+ next_major_version = major_version + 1
26
+ @deprecator = ActiveSupport::Deprecation.new(
27
+ "#{next_major_version}.0",
28
+ "Runbook"
29
+ )
30
+ end
31
+
32
+ def self._child_classes(mod)
33
+ mod.constants.map { |const|
34
+ "#{mod.to_s}::#{const}".constantize
35
+ }.select { |const| const.is_a?(Class) }
36
+ end
37
+
38
+ def self._child_modules(mod)
39
+ mod.constants.map { |const|
40
+ "#{mod.to_s}::#{const}".constantize
41
+ }.select { |const| const.is_a?(Module) }
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module Runbook::Util
2
+ class StickyHash < Hash
3
+ def [](key)
4
+ value = super
5
+ value.is_a?(Glue) ? value.val : value
6
+ end
7
+
8
+ def []=(key, value)
9
+ assoc = self.assoc(key)
10
+ if assoc.nil? || ! assoc[1].is_a?(Glue)
11
+ super
12
+ else
13
+ assoc[1].val = value
14
+ end
15
+ end
16
+ end
17
+
18
+ class Glue
19
+ attr_accessor :val
20
+
21
+ def initialize(val)
22
+ @val = val
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,55 @@
1
+ module Runbook::Util
2
+ module StoredPose
3
+ FILE_ID = "current_position"
4
+ FILE_PERMISSIONS = 0600
5
+
6
+ def self.load(metadata)
7
+ title = metadata[:book_title]
8
+ file = _file(title)
9
+ if File.exist?(file)
10
+ ::YAML::load_file(file)
11
+ end
12
+ end
13
+
14
+ def self.save(repo, book_title:)
15
+ File.open(_file(book_title), 'w', FILE_PERMISSIONS) do |f|
16
+ f.write(repo.to_yaml)
17
+ end
18
+ end
19
+
20
+ def self.delete(title)
21
+ FileUtils.rm_f(_file(title))
22
+ end
23
+
24
+ def self._file(book_title)
25
+ "#{Dir.tmpdir}/runbook_#{FILE_ID}_#{ENV["USER"]}_#{_slug(book_title)}.yml"
26
+ end
27
+
28
+ def self._slug(title)
29
+ title.titleize.gsub(/[\/\s]+/, "").underscore.dasherize
30
+ end
31
+
32
+ def self.register_save_pose_hook(base)
33
+ base.register_hook(
34
+ :save_pose_hook,
35
+ :before,
36
+ Object,
37
+ ) do |object, metadata|
38
+ position = metadata[:position]
39
+ title = metadata[:book_title]
40
+ Runbook::Util::StoredPose.save(position, book_title: title)
41
+ end
42
+ end
43
+
44
+ def self.register_delete_stored_pose_hook(base)
45
+ base.register_hook(
46
+ :delete_stored_pose_hook,
47
+ :after,
48
+ Runbook::Entities::Book,
49
+ ) do |object, metadata|
50
+ title = metadata[:book_title]
51
+ Runbook::Util::StoredPose.delete(title)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ module Runbook
2
+ VERSION = "1.2.0"
3
+ end
@@ -0,0 +1,24 @@
1
+ module Runbook
2
+ module View
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ include Runbook::Hooks
9
+
10
+ def render(object, output, metadata)
11
+ method = _method_name(object)
12
+ if respond_to?(method)
13
+ send(method, object, output, metadata)
14
+ else
15
+ $stderr.puts("WARNING! No render rule for #{object.class} (#{_method_name(object)}) in #{self.to_s}")
16
+ end
17
+ end
18
+
19
+ def _method_name(object)
20
+ object.class.to_s.underscore.gsub("/", "__")
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ module Runbook
2
+ class Viewer
3
+ attr_reader :book
4
+
5
+ def initialize(book)
6
+ @book = book
7
+ end
8
+
9
+ def generate(view: :markdown)
10
+ view = "Runbook::Views::#{view.to_s.camelize}".constantize
11
+ metadata = Util::StickyHash.new.
12
+ merge(Runbook::Entities::Book.initial_render_metadata).
13
+ merge(additional_metadata)
14
+
15
+ StringIO.new.tap do |output|
16
+ book.render(view, output, metadata)
17
+ end.string
18
+ end
19
+
20
+ def additional_metadata
21
+ {}
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,117 @@
1
+ module Runbook::Views
2
+ module Markdown
3
+ include Runbook::View
4
+ extend Runbook::Helpers::FormatHelper
5
+ extend Runbook::Helpers::SSHKitHelper
6
+
7
+ def self.runbook__entities__book(object, output, metadata)
8
+ output << "# #{object.title}\n\n"
9
+ end
10
+
11
+ def self.runbook__entities__section(object, output, metadata)
12
+ heading = "#"*metadata[:depth]
13
+ output << "#{heading} #{metadata[:index]+1}. #{object.title}\n\n"
14
+ end
15
+
16
+ def self.runbook__entities__setup(object, output, metadata)
17
+ output << "[] #{object.title}\n\n"
18
+
19
+ ssh_config = find_ssh_config(object)
20
+ ssh_config_output = render_ssh_config_output(ssh_config)
21
+ output << "#{ssh_config_output}\n" unless ssh_config_output.empty?
22
+ end
23
+
24
+ def self.runbook__entities__step(object, output, metadata)
25
+ output << "#{metadata[:index]+1}. [] #{object.title}\n\n"
26
+
27
+ ssh_config = find_ssh_config(object)
28
+ ssh_config_output = render_ssh_config_output(ssh_config)
29
+ output << "#{ssh_config_output}\n" unless ssh_config_output.empty?
30
+ end
31
+
32
+ def self.runbook__statements__ask(object, output, metadata)
33
+ default_msg = object.default ? " (default: #{object.default})" : ""
34
+ output << " #{object.prompt} into `#{object.into}`#{default_msg}\n\n"
35
+ end
36
+
37
+ def self.runbook__statements__assert(object, output, metadata)
38
+ output << " run: `#{object.cmd}` every #{object.interval} seconds until it returns 0\n\n"
39
+ if object.timeout > 0 || object.attempts > 0
40
+ timeout_msg = object.timeout > 0 ? "#{object.timeout} second(s)" : nil
41
+ attempts_msg = object.attempts > 0 ? "#{object.attempts} attempts" : nil
42
+ abort_msg = "after #{[timeout_msg, attempts_msg].compact.join(" or ")}, abort..."
43
+ output << " #{abort_msg}\n\n"
44
+ if object.abort_statement
45
+ object.abort_statement.render(self, output, metadata.dup)
46
+ end
47
+ output << " and exit\n\n"
48
+ end
49
+ end
50
+
51
+ def self.runbook__statements__capture(object, output, metadata)
52
+ output << " capture: `#{object.cmd}` into `#{object.into}`\n\n"
53
+ end
54
+
55
+ def self.runbook__statements__capture_all(object, output, metadata)
56
+ output << " capture_all: `#{object.cmd}` into `#{object.into}`\n\n"
57
+ end
58
+
59
+ def self.runbook__statements__command(object, output, metadata)
60
+ output << " run: `#{object.cmd}`\n\n"
61
+ end
62
+
63
+ def self.runbook__statements__confirm(object, output, metadata)
64
+ output << " confirm: #{object.prompt}\n\n"
65
+ end
66
+
67
+ def self.runbook__statements__description(object, output, metadata)
68
+ output << "#{object.msg}\n"
69
+ end
70
+
71
+ def self.runbook__statements__download(object, output, metadata)
72
+ options = object.options
73
+ to = " to #{object.to}" if object.to
74
+ opts = " with options #{options}" unless options == {}
75
+ output << " download: #{object.from}#{to}#{opts}\n\n"
76
+ end
77
+
78
+ def self.runbook__statements__layout(object, output, metadata)
79
+ output << "layout:\n"
80
+ output << "#{object.structure.inspect}\n\n"
81
+ end
82
+
83
+ def self.runbook__statements__note(object, output, metadata)
84
+ output << " #{object.msg}\n\n"
85
+ end
86
+
87
+ def self.runbook__statements__notice(object, output, metadata)
88
+ output << " **#{object.msg}**\n\n"
89
+ end
90
+
91
+ def self.runbook__statements__ruby_command(object, output, metadata)
92
+ output << " run:\n"
93
+ output << " ```ruby\n"
94
+ begin
95
+ output << "#{deindent(object.block.source, padding: 3)}\n"
96
+ rescue ::MethodSource::SourceNotFoundError => e
97
+ output << " Unable to retrieve source code\n"
98
+ end
99
+ output << " ```\n\n"
100
+ end
101
+
102
+ def self.runbook__statements__tmux_command(object, output, metadata)
103
+ output << " run: `#{object.cmd}` in pane #{object.pane}\n\n"
104
+ end
105
+
106
+ def self.runbook__statements__upload(object, output, metadata)
107
+ options = object.options
108
+ to = " to #{object.to}" if object.to
109
+ opts = " with options #{options}" unless options == {}
110
+ output << " upload: #{object.from}#{to}#{opts}\n\n"
111
+ end
112
+
113
+ def self.runbook__statements__wait(object, output, metadata)
114
+ output << " wait: #{object.time} seconds\n\n"
115
+ end
116
+ end
117
+ end
data/lib/runbook.rb ADDED
@@ -0,0 +1,140 @@
1
+ require "tmpdir"
2
+ require "yaml"
3
+ require "thread"
4
+
5
+ require "active_support/deprecation"
6
+ require "active_support/inflector"
7
+ require "method_source"
8
+ require "ruby2_keywords"
9
+ require "pastel"
10
+ require "sshkit"
11
+ require "sshkit/sudo"
12
+ require "airbrussh"
13
+ require "tty-progressbar"
14
+ require "tty-prompt"
15
+ require "thor/group"
16
+
17
+ require "runbook/airbrussh_context"
18
+
19
+ require "runbook/configuration"
20
+
21
+ require "hacks/ssh_kit"
22
+
23
+ require "runbook/dsl"
24
+ require "runbook/errors"
25
+ require "runbook/hooks"
26
+
27
+ require "runbook/util/repo"
28
+ require "runbook/util/runbook"
29
+ require "runbook/util/sticky_hash"
30
+ require "runbook/util/stored_pose"
31
+
32
+ require "runbook/node"
33
+
34
+ require "runbook/entity"
35
+ require "runbook/entities/book"
36
+ require "runbook/entities/section"
37
+ require "runbook/entities/setup"
38
+ require "runbook/entities/step"
39
+
40
+ require "runbook/statement"
41
+ require "runbook/statements/ask"
42
+ require "runbook/statements/assert"
43
+ require "runbook/statements/capture"
44
+ require "runbook/statements/capture_all"
45
+ require "runbook/statements/command"
46
+ require "runbook/statements/confirm"
47
+ require "runbook/statements/description"
48
+ require "runbook/statements/download"
49
+ require "runbook/statements/layout"
50
+ require "runbook/statements/note"
51
+ require "runbook/statements/notice"
52
+ require "runbook/statements/ruby_command"
53
+ require "runbook/statements/tmux_command"
54
+ require "runbook/statements/upload"
55
+ require "runbook/statements/wait"
56
+
57
+ require "runbook/helpers/format_helper"
58
+ require "runbook/helpers/ssh_kit_helper"
59
+ require "runbook/helpers/tmux_helper"
60
+
61
+ require "runbook/runner"
62
+ require "runbook/run"
63
+ require "runbook/runs/ssh_kit"
64
+
65
+ require "runbook/toolbox"
66
+
67
+ require "runbook/viewer"
68
+ require "runbook/view"
69
+ require "runbook/views/markdown"
70
+
71
+ require "runbook/generators/base"
72
+ require "runbook/generators/dsl_extension/dsl_extension"
73
+ require "runbook/generators/generator/generator"
74
+ require "runbook/generators/project/project"
75
+ require "runbook/generators/runbook/runbook"
76
+ require "runbook/generators/statement/statement"
77
+
78
+ require "runbook/extensions/add"
79
+ require "runbook/extensions/description"
80
+ require "runbook/extensions/shared_variables"
81
+ require "runbook/extensions/sections"
82
+ require "runbook/extensions/setup"
83
+ require "runbook/extensions/ssh_config"
84
+ require "runbook/extensions/statements"
85
+ require "runbook/extensions/steps"
86
+ require "runbook/extensions/tmux"
87
+
88
+ require "runbook/version"
89
+
90
+ ActiveSupport::Inflector.inflections(:en) do |inflect|
91
+ inflect.acronym 'SSH'
92
+ end
93
+
94
+ module Runbook
95
+ def self.book(title, *tags, labels: {}, &block)
96
+ Configuration.load_config
97
+ Entities::Book.new(title, tags: tags, labels: labels).tap do |book|
98
+ book.dsl.instance_eval(&block)
99
+ register(book)
100
+ end
101
+ end
102
+
103
+ def self.section(title, *tags, labels: {}, &block)
104
+ Configuration.load_config
105
+ Entities::Section.new(title, tags: tags, labels: labels).tap do |section|
106
+ section.dsl.instance_eval(&block)
107
+ end
108
+ end
109
+
110
+ def self.setup(*tags, labels: {}, &block)
111
+ Configuration.load_config
112
+ Entities::Setup.new(tags: tags, labels: labels).tap do |setup|
113
+ setup.dsl.instance_eval(&block)
114
+ end
115
+ end
116
+
117
+ def self.step(title=nil, *tags, labels: {}, &block)
118
+ if title.is_a?(Symbol)
119
+ tags.unshift(title)
120
+ title = nil
121
+ end
122
+
123
+ Configuration.load_config
124
+ Entities::Step.new(title, tags: tags, labels: labels).tap do |step|
125
+ step.dsl.instance_eval(&block) if block
126
+ end
127
+ end
128
+
129
+ def self.register(book)
130
+ books << book
131
+ end
132
+
133
+ def self.books
134
+ @books ||= []
135
+ end
136
+
137
+ def self.runtime_methods
138
+ @runtime_methods ||= []
139
+ end
140
+ end
data/runbook.gemspec ADDED
@@ -0,0 +1,53 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "runbook/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "careacademy-runbook"
8
+ spec.version = Runbook::VERSION
9
+ spec.authors = ["pblesi"]
10
+ spec.email = ["code@getbraintree.com"]
11
+
12
+ spec.summary = %q{Write beautiful, executable runbooks for conducting system operations.}
13
+ spec.description = %q{Runbook provides a DSL for specifying system operations. This DSL is used to generate formatted runbooks as well as interactive runbooks to be executed on the command line.}
14
+ spec.homepage = "https://github.com/braintree/runbook/"
15
+ spec.license = "MIT"
16
+ spec.required_ruby_version = '>= 2.2.3'
17
+
18
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
19
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
20
+ if spec.respond_to?(:metadata)
21
+ spec.metadata["allowed_push_host"] = "https://rubygems.org/"
22
+ else
23
+ raise "RubyGems 2.0 or newer is required to protect against " \
24
+ "public gem pushes."
25
+ end
26
+
27
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
28
+ f.match(%r{^(test|spec|features)/})
29
+ end
30
+ spec.bindir = "exe"
31
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ["lib"]
33
+
34
+ spec.add_runtime_dependency "activesupport", ">= 5.0.1.x", "< 7.1"
35
+ spec.add_runtime_dependency "method_source", "~> 1.0"
36
+ spec.add_runtime_dependency "ruby2_keywords", "~> 0.0.4"
37
+ spec.add_runtime_dependency "sshkit", "1.21.0"
38
+ spec.add_runtime_dependency "sshkit-sudo", "~> 0.1"
39
+ spec.add_runtime_dependency "airbrussh", "~> 1.4"
40
+ spec.add_runtime_dependency "thor", "~> 1.0"
41
+ spec.add_runtime_dependency "tty-progressbar", "~> 0.14"
42
+ spec.add_runtime_dependency "tty-prompt", "~> 0.20"
43
+
44
+ spec.add_development_dependency "appraisal", "~> 2.2"
45
+ spec.add_development_dependency "aruba", "~> 0.14"
46
+ spec.add_development_dependency "bundler", "~> 2.2"
47
+ spec.add_development_dependency "bcrypt_pbkdf", ">= 1.0", "< 2.0"
48
+ spec.add_development_dependency "ed25519", ">= 1.2", "< 2.0"
49
+ spec.add_development_dependency "pry", "~> 0.13"
50
+ spec.add_development_dependency "pry-byebug", "~> 3.6"
51
+ spec.add_development_dependency "rake", "~> 12.3"
52
+ spec.add_development_dependency "rspec", "~> 3.0"
53
+ end