caco 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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