caco 0.1.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 (118) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.travis.yml +10 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +12 -0
  6. data/Gemfile.lock +227 -0
  7. data/Guardfile +42 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +97 -0
  10. data/Rakefile +10 -0
  11. data/bin/_guard-core +29 -0
  12. data/bin/bundle +114 -0
  13. data/bin/byebug +29 -0
  14. data/bin/caco +29 -0
  15. data/bin/coderay +29 -0
  16. data/bin/console +20 -0
  17. data/bin/eyaml +29 -0
  18. data/bin/guard +29 -0
  19. data/bin/listen +29 -0
  20. data/bin/pry +29 -0
  21. data/bin/rake +29 -0
  22. data/bin/safe_yaml +29 -0
  23. data/bin/setup +8 -0
  24. data/bin/thor +29 -0
  25. data/bin/tilt +29 -0
  26. data/caco.gemspec +43 -0
  27. data/exe/caco +27 -0
  28. data/lib/caco.rb +115 -0
  29. data/lib/caco/barman.rb +10 -0
  30. data/lib/caco/barman/cell/global.rb +4 -0
  31. data/lib/caco/barman/cell/node.rb +15 -0
  32. data/lib/caco/barman/install.rb +25 -0
  33. data/lib/caco/barman/view/global.erb +7 -0
  34. data/lib/caco/barman/view/node.erb +8 -0
  35. data/lib/caco/cell.rb +8 -0
  36. data/lib/caco/config.rb +23 -0
  37. data/lib/caco/debian.rb +28 -0
  38. data/lib/caco/debian/add_user.rb +18 -0
  39. data/lib/caco/debian/apt_key_install.rb +19 -0
  40. data/lib/caco/debian/apt_repo_add.rb +17 -0
  41. data/lib/caco/debian/apt_sources_list.rb +15 -0
  42. data/lib/caco/debian/apt_update.rb +33 -0
  43. data/lib/caco/debian/cell/service.rb +19 -0
  44. data/lib/caco/debian/cell/sources_list.rb +7 -0
  45. data/lib/caco/debian/package_install.rb +21 -0
  46. data/lib/caco/debian/package_installed.rb +17 -0
  47. data/lib/caco/debian/service_enable.rb +26 -0
  48. data/lib/caco/debian/service_install.rb +31 -0
  49. data/lib/caco/debian/user_home.rb +17 -0
  50. data/lib/caco/debian/view/service.erb +18 -0
  51. data/lib/caco/debian/view/sources_list.erb +10 -0
  52. data/lib/caco/downloader.rb +41 -0
  53. data/lib/caco/executer.rb +33 -0
  54. data/lib/caco/facter.rb +41 -0
  55. data/lib/caco/file_link.rb +36 -0
  56. data/lib/caco/file_reader.rb +24 -0
  57. data/lib/caco/file_writer.rb +57 -0
  58. data/lib/caco/finder.rb +13 -0
  59. data/lib/caco/grafana.rb +6 -0
  60. data/lib/caco/grafana/install.rb +26 -0
  61. data/lib/caco/haproxy.rb +12 -0
  62. data/lib/caco/haproxy/cell/conf_postgres.rb +4 -0
  63. data/lib/caco/haproxy/cell/conf_stats.rb +4 -0
  64. data/lib/caco/haproxy/conf_get.rb +15 -0
  65. data/lib/caco/haproxy/conf_set.rb +52 -0
  66. data/lib/caco/haproxy/install.rb +9 -0
  67. data/lib/caco/haproxy/view/conf_postgres.erb +25 -0
  68. data/lib/caco/haproxy/view/conf_stats.erb +6 -0
  69. data/lib/caco/macro.rb +2 -0
  70. data/lib/caco/postgres.rb +44 -0
  71. data/lib/caco/postgres/build_augeas.rb +20 -0
  72. data/lib/caco/postgres/conf_get.rb +37 -0
  73. data/lib/caco/postgres/conf_set.rb +54 -0
  74. data/lib/caco/postgres/database_create.rb +28 -0
  75. data/lib/caco/postgres/extension_create.rb +28 -0
  76. data/lib/caco/postgres/hba_set.rb +65 -0
  77. data/lib/caco/postgres/install.rb +34 -0
  78. data/lib/caco/postgres/shell.rb +13 -0
  79. data/lib/caco/postgres/sql.rb +17 -0
  80. data/lib/caco/postgres/user_change_password.rb +13 -0
  81. data/lib/caco/postgres/user_create.rb +33 -0
  82. data/lib/caco/prometheus.rb +15 -0
  83. data/lib/caco/prometheus/adapter_install_pg.rb +107 -0
  84. data/lib/caco/prometheus/adapter_install_postgresql.rb +47 -0
  85. data/lib/caco/prometheus/cell/alertmanager_conf.rb +4 -0
  86. data/lib/caco/prometheus/cell/alerts.rb +4 -0
  87. data/lib/caco/prometheus/cell/conf.rb +7 -0
  88. data/lib/caco/prometheus/exporter_install.rb +35 -0
  89. data/lib/caco/prometheus/install.rb +50 -0
  90. data/lib/caco/prometheus/install_alert_manager.rb +62 -0
  91. data/lib/caco/prometheus/view/alertmanager_conf.erb +13 -0
  92. data/lib/caco/prometheus/view/alerts.erb +18 -0
  93. data/lib/caco/prometheus/view/conf.erb +34 -0
  94. data/lib/caco/rbenv.rb +8 -0
  95. data/lib/caco/rbenv/cell/profile.rb +4 -0
  96. data/lib/caco/rbenv/install.rb +56 -0
  97. data/lib/caco/rbenv/install_version.rb +17 -0
  98. data/lib/caco/rbenv/view/profile.erb +3 -0
  99. data/lib/caco/repmgr.rb +15 -0
  100. data/lib/caco/repmgr/cell/conf.rb +43 -0
  101. data/lib/caco/repmgr/conf.rb +25 -0
  102. data/lib/caco/repmgr/install.rb +25 -0
  103. data/lib/caco/repmgr/node_register_primary.rb +34 -0
  104. data/lib/caco/repmgr/node_register_standby.rb +25 -0
  105. data/lib/caco/repmgr/node_registered.rb +15 -0
  106. data/lib/caco/repmgr/node_role.rb +18 -0
  107. data/lib/caco/repmgr/view/conf.erb +27 -0
  108. data/lib/caco/settings_loader.rb +67 -0
  109. data/lib/caco/settings_loader_monkeypatch.rb +28 -0
  110. data/lib/caco/ssh.rb +6 -0
  111. data/lib/caco/ssh/authorized_keys_add.rb +82 -0
  112. data/lib/caco/sudo.rb +6 -0
  113. data/lib/caco/sudo/sudoers_add.rb +15 -0
  114. data/lib/caco/timescale.rb +6 -0
  115. data/lib/caco/timescale/install.rb +25 -0
  116. data/lib/caco/unpacker.rb +76 -0
  117. data/lib/caco/version.rb +3 -0
  118. metadata +398 -0
@@ -0,0 +1,15 @@
1
+ module Caco::Debian
2
+ class AptSourcesList < Trailblazer::Operation
3
+ step ->(ctx, mirror_url: nil, **) {
4
+ ctx[:content] = Caco::Debian::Cell::SourcesList.(mirror_url: mirror_url).to_s
5
+ },
6
+ id: :generate_content
7
+
8
+ step ->(ctx, **) { ctx[:path] = '/etc/apt/sources.list' },
9
+ id: :build_path
10
+
11
+ step Subprocess(Caco::FileWriter),
12
+ input: [:path, :content],
13
+ output: { file_changed: :sources_updated }
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ module Caco::Debian
2
+ class AptUpdate < Trailblazer::Operation
3
+ step :apt_needs_update,
4
+ Output(Trailblazer::Activity::Left, :failure) => End(:success)
5
+
6
+ step Subprocess(Caco::Executer),
7
+ input: ->(_ctx, **) {{
8
+ command: 'apt-get update'
9
+ }},
10
+ output: { exit_code: :command_exit_code, output: :command_output }
11
+
12
+ step :apt_updated
13
+
14
+ fail :command_failed
15
+
16
+ def apt_needs_update(ctx, force: false, **)
17
+ ctx[:apt_needs_update] = !Caco::Debian.apt_updated
18
+ ctx[:apt_needs_update] = true if force
19
+ ctx[:apt_needs_update]
20
+ end
21
+
22
+ def apt_updated(ctx, **)
23
+ ctx[:apt_updated] = true
24
+ Caco::Debian.apt_updated = true
25
+ end
26
+
27
+ def command_failed(ctx, command_exit_code:, command_output:, **)
28
+ ctx[:apt_updated] = false
29
+ Caco::Debian.apt_updated = false
30
+ true
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module Caco::Debian::Cell
2
+ class Service < Trailblazer::Cell
3
+ def description
4
+ property(:description) || "No Description Provided"
5
+ end
6
+
7
+ def environment_file
8
+ property(:environment_file)
9
+ end
10
+
11
+ def environment_vars
12
+ property(:environment_vars) || []
13
+ end
14
+
15
+ def command
16
+ property(:command)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Caco::Debian::Cell
2
+ class SourcesList < Trailblazer::Cell
3
+ def mirror_url
4
+ property(:mirror_url) || Settings.debian.apt_default_repo.mirror_url
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ module Caco::Debian
2
+ class PackageInstall < Trailblazer::Operation
3
+ class PackageNameError < StandardError; end
4
+
5
+ step Subprocess(Caco::Debian::PackageInstalled),
6
+ id: "package_installed?",
7
+ input: [:package],
8
+ output: []
9
+
10
+ fail Subprocess(Caco::Executer),
11
+ Output(:success) => End(:success),
12
+ input: ->(_ctx, package:, **) {{
13
+ command: "apt-get install -y #{package}"
14
+ }},
15
+ output: { exit_code: :package_install_exit_code, output: :package_install_output },
16
+ id: "package_install"
17
+
18
+ step ->(ctx, **) { ctx[:already_installed] = true },
19
+ id: :package_already_installed!
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Caco::Debian
2
+ class PackageInstalled < Trailblazer::Operation
3
+ step Subprocess(Caco::Executer),
4
+ input: ->(_ctx, package:, **) {{
5
+ command: "dpkg -s #{package}"
6
+ }},
7
+ output: { exit_code: :command_exit_code, output: :command_output },
8
+ id: "dpkg"
9
+
10
+ step Subprocess(Caco::Finder),
11
+ input: ->(_ctx, package:, **) {{
12
+ command: "dpkg-query -W -f='${Status} ${Version}\n' #{package}",
13
+ regexp: /^install/
14
+ }},
15
+ id: "dpkg_query"
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Caco::Debian
2
+ class ServiceEnable < Trailblazer::Operation
3
+ step Subprocess(Caco::Executer),
4
+ input: ->(_ctx, service:, **) {{
5
+ command: "systemctl list-units --full -all | grep -Fq \"#{service}.service\""
6
+ }},
7
+ id: :check_service_exist
8
+
9
+ step Subprocess(Class.new(Caco::Executer)),
10
+ Output(:success) => End(:success),
11
+ Output(:failure) => Track(:success),
12
+ input: ->(_ctx, service:, **) {{
13
+ command: "systemctl is-enabled #{service}.service"
14
+ }},
15
+ id: :check_service_enabled
16
+
17
+ step Subprocess(Class.new(Caco::Executer)),
18
+ input: ->(_ctx, service:, **) {{
19
+ command: "systemctl enable #{service}.service"
20
+ }},
21
+ id: :enable_service
22
+
23
+ step ->(ctx, **) { ctx[:enabled] = true },
24
+ id: :mark_enabled
25
+ end
26
+ end
@@ -0,0 +1,31 @@
1
+ module Caco::Debian
2
+ class ServiceInstall < Trailblazer::Operation
3
+ step ->(ctx, name:, **) {
4
+ ctx[:service_path] = "/etc/systemd/system/#{name}.service"
5
+ },
6
+ id: :generate_service_path
7
+
8
+ step :generate_template_content
9
+
10
+ step Subprocess(Caco::FileWriter),
11
+ input: ->(_ctx, service_path:, template_content:, **) {{
12
+ path: service_path,
13
+ content: template_content
14
+ }}
15
+
16
+ step Subprocess(Caco::Executer),
17
+ input: ->(_ctx, **) {{
18
+ command: "systemctl daemon-reload",
19
+ }},
20
+ id: "systemctl_reload"
21
+
22
+ def generate_template_content(ctx, description: nil, environment_file: nil, environment_vars: nil, command:, **)
23
+ ctx[:template_content] = Caco::Debian::Cell::Service.(
24
+ command: command,
25
+ description: description,
26
+ environment_file: environment_file,
27
+ environment_vars: environment_vars,
28
+ ).to_s
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ module Caco::Debian
2
+ class UserHome < Trailblazer::Operation
3
+ step Subprocess(Caco::FileReader),
4
+ input: ->(_ctx, **) {{
5
+ path: "/etc/passwd",
6
+ }},
7
+ output: { output: :passwd_output }
8
+ step :find_user_home
9
+
10
+ def find_user_home(ctx, user:, passwd_output:, **)
11
+ match = passwd_output.match(/^#{user}:[^:]*:[^:]*:[^:]*:[^:]*:([^:]*):.*$/)
12
+ return false unless match
13
+
14
+ ctx[:user_home] = match[1]
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ # File Managed, Dot Not Edit
2
+ [Unit]
3
+ Description=<%= description %>
4
+ After=syslog.target network.target network-online.target
5
+
6
+ [Service]
7
+ <% if environment_file %>
8
+ EnvironmentFile=<%= environment_file %>
9
+ <% end %>
10
+ <% environment_vars.each do |env| %>
11
+ Environment=<%= env %>
12
+ <% end %>
13
+ User=root
14
+ Restart=on-failure
15
+ ExecStart=<%= command %>
16
+
17
+ [Install]
18
+ WantedBy=multi-user.target
@@ -0,0 +1,10 @@
1
+ # File Managed, Dot Not Edit
2
+ deb <%= mirror_url %> stretch main
3
+ deb-src <%= mirror_url %> stretch main
4
+
5
+ deb http://security.debian.org/debian-security stretch/updates main
6
+ deb-src http://security.debian.org/debian-security stretch/updates main
7
+
8
+ # stretch-updates, previously known as 'volatile'
9
+ deb <%= mirror_url %> stretch-updates main
10
+ deb-src <%= mirror_url %> stretch-updates main
@@ -0,0 +1,41 @@
1
+ require 'net/http'
2
+ require "open-uri"
3
+
4
+ module Caco
5
+ class Downloader < Trailblazer::Operation
6
+ Stubbed = Class.new(Trailblazer::Activity::Signal)
7
+
8
+ step ->(_ctx, stubbed_file: nil, **) {
9
+ stubbed_file ? Stubbed : true
10
+ },
11
+ Output(Stubbed, :stubbed) => Track(:stubbed),
12
+ id: :check_stubbed
13
+
14
+ step ->(ctx, url:, **) {
15
+ ctx[:tempfile] = Down.download(url)
16
+ },
17
+ id: :download_file
18
+
19
+ step ->(ctx, stubbed_file:, **) {
20
+ ctx[:tempfile] = File.new(ctx[:stubbed_file])
21
+ },
22
+ magnetic_to: :stubbed,
23
+ id: :stubbed_download_file
24
+
25
+ step ->(_ctx, **) {
26
+ true
27
+ },
28
+ id: :check_md5
29
+
30
+ step :write_file
31
+
32
+ def write_file(ctx, tempfile:, dest:, **)
33
+ if Caco.config.write_files
34
+ FileUtils.mkdir_p(File.dirname(dest))
35
+ File.rename tempfile.path, dest
36
+ else
37
+ tempfile.unlink
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module Caco
2
+ class Executer < Trailblazer::Operation
3
+ step :execute!
4
+
5
+ def execute!(ctx, command:, **)
6
+ s, e, o, error = self.class.send(:execute, command)
7
+ ctx[:signal] = [s, e, o, error]
8
+ ctx[:exit_code] = e
9
+ ctx[:output] = o
10
+ ctx[:stderr] = error
11
+
12
+ return s
13
+ end
14
+
15
+ module ClassMethods
16
+ private
17
+ def execute(command)
18
+ stdout = nil
19
+ stderr = nil
20
+ pid = nil
21
+ exit_status = nil
22
+ Open3.popen3(*command) do |i, o, e, t|
23
+ pid = t.pid
24
+ stdout = o.read
25
+ stderr = e.read
26
+ exit_status = t.value
27
+ end
28
+ return exit_status.success?, exit_status.exitstatus, stdout, stderr
29
+ end
30
+ end
31
+ extend ClassMethods
32
+ end
33
+ end
@@ -0,0 +1,41 @@
1
+ module Caco::Facter
2
+ class KeyNotFoundError < StandardError; end
3
+
4
+ module ClassMethods
5
+ @@fake_data = nil
6
+
7
+ def set_fake_data=(data)
8
+ @@fake_data = data
9
+ end
10
+
11
+ def use_fake(data, &block)
12
+ old_fake_data = @@fake_data
13
+ @@fake_data = data
14
+
15
+ yield
16
+
17
+ @@fake_data = old_fake_data
18
+ end
19
+
20
+ def call(*items)
21
+ value = json_data(*items).dig(*items)
22
+ raise KeyNotFoundError.new("#{items.join(":")} not found") unless value
23
+ value
24
+ end
25
+
26
+ private
27
+ def json_data(*items)
28
+ return @@fake_data unless @@fake_data.nil?
29
+
30
+ @@parsed_data ||= JSON.parse(external_facter_data)
31
+ end
32
+
33
+ def external_facter_data
34
+ facter_path = Caco::Executer.(command: "which facter")[:output].chomp!
35
+ result = Caco::Executer.(command: "#{facter_path} -j")
36
+ result[:output]
37
+ end
38
+ end
39
+
40
+ extend ClassMethods
41
+ end
@@ -0,0 +1,36 @@
1
+ class Caco::FileLink < Trailblazer::Operation
2
+ pass :link_exist?
3
+ pass :target_exist?
4
+ step :link_same_target?,
5
+ Output(:success) => End(:success),
6
+ Output(:failure) => Track(:success)
7
+ step :ensure_target!
8
+ step :create_link!
9
+
10
+ def link_exist?(ctx, link:, **)
11
+ ctx[:link_exist] = !!File.lstat(link) rescue false
12
+ ctx[:link_realpath] = File.realdirpath(link) rescue false
13
+ ctx[:link_exist]
14
+ end
15
+
16
+ def target_exist?(ctx, target:, **)
17
+ ctx[:target_exist] = File.exist?(target)
18
+ ctx[:target_realpath] = File.realdirpath(target) rescue nil
19
+ ctx[:target_exist]
20
+ end
21
+
22
+ def link_same_target?(ctx, target_realpath:, link_realpath:, **)
23
+ ctx[:link_same_target] = (target_realpath == link_realpath)
24
+ end
25
+
26
+ def ensure_target!(ctx, target_exist:, ensure_target: false, **)
27
+ return false if !target_exist && ensure_target
28
+ true
29
+ end
30
+
31
+ def create_link!(ctx, target:, link:, link_exist:, link_same_target:, **)
32
+ ctx[:force] = (link_exist && !link_same_target)
33
+ FileUtils.ln_s target, link, force: ctx[:force]
34
+ ctx[:link_created] = true
35
+ end
36
+ end
@@ -0,0 +1,24 @@
1
+ class Caco::FileReader < Trailblazer::Operation
2
+ UseCustomRoot = Class.new(Trailblazer::Activity::Signal)
3
+
4
+ step :use_custom_root,
5
+ Output(UseCustomRoot, :use_custom_root) => Track(:success)
6
+
7
+ step :file_exist
8
+ step :read_file, Output(Trailblazer::Activity::Left, :failure) => End(:success)
9
+
10
+ def use_custom_root(ctx, path:, **)
11
+ return true unless Caco.config.write_files_root
12
+ ctx[:path] = "#{Caco.config.write_files_root}#{ctx[:path]}"
13
+
14
+ UseCustomRoot
15
+ end
16
+
17
+ def file_exist(ctx, path:, **)
18
+ ctx[:file_exist] = File.exist?(path)
19
+ end
20
+
21
+ def read_file(ctx, path:, **)
22
+ ctx[:output] = File.read(path)
23
+ end
24
+ end
@@ -0,0 +1,57 @@
1
+ class Caco::FileWriter < Trailblazer::Operation
2
+ SameMD5 = Class.new(Trailblazer::Activity::Signal)
3
+ DifferentMD5 = Class.new(Trailblazer::Activity::Signal)
4
+ UseCustomRoot = Class.new(Trailblazer::Activity::Signal)
5
+
6
+ step :use_custom_root,
7
+ Output(UseCustomRoot, :use_custom_root) => Track(:success)
8
+
9
+ pass :file_exist
10
+ step :calculate_md5
11
+ step :compare_md5,
12
+ Output(SameMD5, :same_md5) => End(:success),
13
+ Output(DifferentMD5, :success) => Track(:success)
14
+ step :mkdir_p
15
+ step :write_file
16
+
17
+ def use_custom_root(ctx, path:, **)
18
+ return true unless Caco.config.write_files_root
19
+ unless ctx[:path].start_with?(Caco.config.write_files_root.to_s)
20
+ ctx[:path] = "#{Caco.config.write_files_root}#{ctx[:path]}"
21
+ end
22
+ UseCustomRoot
23
+ end
24
+
25
+ def file_exist(ctx, path:, **)
26
+ ctx[:file_exist] = File.exist?(path)
27
+ ctx[:file_created] = !ctx[:file_exist]
28
+ ctx[:file_exist]
29
+ end
30
+
31
+ def calculate_md5(ctx, path:, file_exist:, content:, **)
32
+ ctx[:current_md5] = (file_exist ? Digest::MD5.hexdigest(File.read(path)) : "")
33
+ ctx[:content_md5] = Digest::MD5.hexdigest(content)
34
+ end
35
+
36
+ def compare_md5(ctx, content_md5:, current_md5:, **)
37
+ different_md5 = (content_md5 != current_md5)
38
+ ctx[:file_changed] = different_md5 ? true : false
39
+ different_md5 ? DifferentMD5 : SameMD5
40
+ end
41
+
42
+ def mkdir_p(ctx, path:, **)
43
+ dirname = File.dirname(path)
44
+ if Caco.config.write_files
45
+ FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
46
+ end
47
+ true
48
+ end
49
+
50
+ def write_file(ctx, path:, content:, file_exist:, **)
51
+ if Caco.config.write_files
52
+ File.write(path, content)
53
+ end
54
+ ctx[:file_created] = !file_exist
55
+ ctx[:file_changed] = true
56
+ end
57
+ end