micro-hookit 0.12.11

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 (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +21 -0
  6. data/README.md +24 -0
  7. data/Rakefile +18 -0
  8. data/bin/hookit +51 -0
  9. data/boxfile.yml +2 -0
  10. data/hookit.gemspec +30 -0
  11. data/lib/hookit/converginator.rb +165 -0
  12. data/lib/hookit/db.rb +37 -0
  13. data/lib/hookit/error.rb +9 -0
  14. data/lib/hookit/exit.rb +23 -0
  15. data/lib/hookit/helper/cron.rb +42 -0
  16. data/lib/hookit/helper/nfs.rb +113 -0
  17. data/lib/hookit/helper/shell.rb +35 -0
  18. data/lib/hookit/helper/xml.rb +25 -0
  19. data/lib/hookit/helper.rb +9 -0
  20. data/lib/hookit/hook.rb +96 -0
  21. data/lib/hookit/logger.rb +60 -0
  22. data/lib/hookit/platform/base.rb +11 -0
  23. data/lib/hookit/platform/docker.rb +22 -0
  24. data/lib/hookit/platform/smartos.rb +19 -0
  25. data/lib/hookit/platform/ubuntu.rb +19 -0
  26. data/lib/hookit/platform.rb +10 -0
  27. data/lib/hookit/platforms.rb +3 -0
  28. data/lib/hookit/registry.rb +53 -0
  29. data/lib/hookit/resource/base.rb +138 -0
  30. data/lib/hookit/resource/cron.rb +29 -0
  31. data/lib/hookit/resource/directory.rb +69 -0
  32. data/lib/hookit/resource/execute.rb +205 -0
  33. data/lib/hookit/resource/file.rb +89 -0
  34. data/lib/hookit/resource/hook_file.rb +109 -0
  35. data/lib/hookit/resource/link.rb +50 -0
  36. data/lib/hookit/resource/logrotate.rb +36 -0
  37. data/lib/hookit/resource/mount.rb +85 -0
  38. data/lib/hookit/resource/package.rb +57 -0
  39. data/lib/hookit/resource/rsync.rb +58 -0
  40. data/lib/hookit/resource/scp.rb +78 -0
  41. data/lib/hookit/resource/service.rb +117 -0
  42. data/lib/hookit/resource/socket.rb +79 -0
  43. data/lib/hookit/resource/template.rb +114 -0
  44. data/lib/hookit/resource/warning.rb +87 -0
  45. data/lib/hookit/resource/zfs.rb +77 -0
  46. data/lib/hookit/resource.rb +21 -0
  47. data/lib/hookit/resources.rb +15 -0
  48. data/lib/hookit/setup.rb +59 -0
  49. data/lib/hookit/version.rb +3 -0
  50. data/lib/hookit.rb +26 -0
  51. metadata +208 -0
@@ -0,0 +1,78 @@
1
+ module Hookit
2
+ module Resource
3
+ class Scp < Base
4
+
5
+ field :source
6
+ field :destination
7
+ field :port
8
+ field :recursive
9
+ field :config
10
+ field :cipher
11
+ field :identity
12
+ field :ssh_options
13
+ field :compression
14
+ field :preserve
15
+
16
+ actions :copy
17
+ default_action :copy
18
+
19
+ def initialize(name)
20
+ source(name) unless source
21
+ preserve(true) unless preserve
22
+ recursive(true) unless recursive
23
+ super
24
+ end
25
+
26
+ def run(action)
27
+ case action
28
+ when :copy
29
+ copy!
30
+ end
31
+ end
32
+
33
+ def copy!
34
+ run_command! "scp -q#{preserve!}#{recursive!}B#{compression!} #{config!} #{port!} #{cipher!} #{identity!} #{ssh_options!} #{source} #{destination}"
35
+ end
36
+
37
+ def cipher!
38
+ (return "-c #{cipher}") if cipher
39
+ ""
40
+ end
41
+
42
+ def compression!
43
+ (return "C") if compression
44
+ ""
45
+ end
46
+
47
+ def config!
48
+ (return "-F #{config}") if config
49
+ ""
50
+ end
51
+
52
+ def identity!
53
+ (return "-i #{identity}") if identity
54
+ ""
55
+ end
56
+
57
+ def port!
58
+ (return "-P #{port}") if port
59
+ ""
60
+ end
61
+
62
+ def preserve!
63
+ (return "p") if preserve
64
+ ""
65
+ end
66
+
67
+ def recursive!
68
+ (return "r") if recursive
69
+ ""
70
+ end
71
+
72
+ def ssh_options!
73
+ (return "-o #{ssh_options}") if ssh_options
74
+ ""
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,117 @@
1
+ module Hookit
2
+ module Resource
3
+ class Service < Base
4
+
5
+ field :recursive
6
+ field :service_name
7
+ field :init
8
+ field :timeout
9
+
10
+ actions :enable, :disable, :start, :stop, :force_stop, :restart, :reload
11
+ default_action :enable
12
+
13
+ def initialize(name)
14
+ service_name(name) unless service_name
15
+ super
16
+
17
+ # if init scheme is not provided, try to set reasonable defaults
18
+ if not init
19
+ case platform.name
20
+ when 'smartos'
21
+ init(:smf)
22
+ when 'ubuntu'
23
+ init(:upstart)
24
+ when 'docker'
25
+ init(:runit)
26
+ end
27
+ end
28
+ end
29
+
30
+ def run(action)
31
+ case action
32
+ when :enable
33
+ enable!
34
+ when :disable
35
+ disable!
36
+ when :start
37
+ enable!
38
+ when :stop
39
+ disable!
40
+ when :force_stop
41
+ force_disable!
42
+ when :restart
43
+ restart!
44
+ when :reload
45
+ reload!
46
+ end
47
+ end
48
+
49
+ protected
50
+
51
+ def enable!
52
+ case init
53
+ when :smf
54
+ run_command! "svcadm enable -s #{"-r" if recursive} #{service_name}"
55
+ when :runit
56
+ # register and potentially start the service
57
+ run_command! "sv #{"-w #{timeout}" if timeout} start #{service_name}", false
58
+
59
+ # runit can take up to 5 seconds to register the service before the
60
+ # service starts to run. We'll keep checking the status for up to
61
+ # 6 seconds, after which time we'll raise an exception.
62
+ registered = false
63
+
64
+ 6.times do
65
+ # check the status
66
+ `sv status #{service_name}`
67
+ if $?.exitstatus == 0
68
+ registered = true
69
+ break
70
+ end
71
+
72
+ sleep 1
73
+ end
74
+
75
+ if registered
76
+ # just in case the service is registered but not started, try
77
+ # to start the service one more time
78
+ run_command! "sv #{"-w #{timeout}" if timeout} start #{service_name}"
79
+ end
80
+ end
81
+ end
82
+
83
+ def disable!
84
+ case init
85
+ when :smf
86
+ run_command! "svcadm disable -s #{service_name}"
87
+ when :runit
88
+ run_command! "sv #{"-w #{timeout}" if timeout} stop #{service_name}"
89
+ end
90
+ end
91
+
92
+ def force_disable!
93
+ case init
94
+ when :runit
95
+ run_command! "sv #{"-w #{timeout}" if timeout} force-stop #{service_name}"
96
+ end
97
+ end
98
+
99
+ def restart!
100
+ case init
101
+ when :smf
102
+ run_command! "svcadm restart #{service_name}"
103
+ when :runit
104
+ disable!; enable!
105
+ end
106
+ end
107
+
108
+ def reload!
109
+ case init
110
+ when :smf
111
+ run_command! "svcadm refresh #{service_name}"
112
+ end
113
+ end
114
+
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,79 @@
1
+ module Hookit
2
+ module Resource
3
+ class Socket < Base
4
+
5
+ field :port
6
+ field :interface
7
+ field :service
8
+ field :max_checks
9
+
10
+ actions :listening, :no_connections, :reset
11
+ default_action :listening
12
+
13
+ def initialize(name)
14
+ service name unless service
15
+ max_checks 3 unless max_checks
16
+ super
17
+
18
+ case platform.os
19
+ when 'sun'
20
+ @active_com = "netstat -an | egrep '\*\.#{port}' | grep LISTEN"
21
+ @inactive_com = "netstat -an | grep 'ESTABLISHED' | awk '{ print $1 }' | grep \"$(ifconfig #{interface} | grep inet | awk '{ print $2 }')\.#{port}\""
22
+ else
23
+ @active_com = "netstat -an | egrep ':#{port}' | grep LISTEN"
24
+ @inactive_com = "netstat -an | grep 'ESTABLISHED' | awk '{ print $4 }' | grep \"$(ifconfig #{interface} | awk '/inet addr/ { print $2}' | cut -f2 -d':' | tr -d '\n'):#{port}\""
25
+ end
26
+ end
27
+
28
+ def run(action)
29
+ case action
30
+ when :listening
31
+ check_listening!
32
+ when :no_connections
33
+ check_no_connections!
34
+ when :reset
35
+ reset!
36
+ end
37
+ end
38
+
39
+ protected
40
+
41
+ def check_listening!
42
+ # increment check
43
+ registry("#{service}.listening", registry("#{service}.listening").to_i + 1)
44
+
45
+ if `#{@active_com}`.empty?
46
+ count = registry("#{service}.listening").to_i
47
+ if count <= max_checks
48
+ sleep 1
49
+ exit(count + 10)
50
+ else
51
+ print_error(name, {
52
+ reason: "timed out waiting for #{service} to listen"
53
+ })
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ def check_no_connections!
60
+ # increment check
61
+ registry("#{service}.no_connections", registry("#{service}.no_connections").to_i + 1)
62
+
63
+ unless `#{@inactive_com}`.empty?
64
+ count = registry("#{service}.no_connections").to_i
65
+ sleep 1
66
+ if count <= max_checks
67
+ exit(count + 10)
68
+ end
69
+ end
70
+ end
71
+
72
+ def reset!
73
+ registry("#{service}.listening", 0)
74
+ registry("#{service}.no_connections", 0)
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,114 @@
1
+ require 'tilt'
2
+ require 'erubis'
3
+ require 'erb'
4
+ require 'oj'
5
+ require 'multi_json'
6
+
7
+ module Hookit
8
+ module Resource
9
+ class Template < Base
10
+
11
+ field :path
12
+ field :source
13
+ field :variables
14
+ field :mode
15
+ field :owner
16
+ field :group
17
+
18
+ actions :create, :create_if_missing, :delete, :touch
19
+ default_action :create
20
+
21
+ def initialize(name)
22
+ path name unless path
23
+ source "#{::File.basename(name)}.erb"
24
+ super
25
+ end
26
+
27
+ def run(action)
28
+ case action
29
+ when :create
30
+ create!
31
+ chown!
32
+ chmod!
33
+ when :create_if_missing
34
+ create_if_missing!
35
+ chown!
36
+ chmod!
37
+ when :delete
38
+ delete!
39
+ when :touch
40
+ touch!
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ def create!
47
+ begin
48
+ ::File.write path, render
49
+ rescue Exception => e
50
+ unexpected_failure("create file", e.message)
51
+ end
52
+ end
53
+
54
+ def create_if_missing!
55
+ if not ::File.exists? path
56
+ create!
57
+ end
58
+ end
59
+
60
+ def delete!
61
+ begin
62
+ ::File.delete path
63
+ rescue Exception => e
64
+ unexpected_failure("delete file", e.message)
65
+ end
66
+ end
67
+
68
+ def chown!
69
+ return unless owner or group
70
+ if ::File.exists? path
71
+ run_command! "chown #{(group.nil?) ? owner : "#{owner}:#{group}"} #{path}"
72
+ end
73
+ end
74
+
75
+ def chmod!
76
+ if ::File.exists? path and mode
77
+ begin
78
+ ::File.chmod(mode, path)
79
+ rescue Exception => e
80
+ unexpected_failure("chmod file", e.message)
81
+ end
82
+ end
83
+ end
84
+
85
+ def touch!
86
+ run_command! "touch -c #{path}"
87
+ end
88
+
89
+ def render
90
+ begin
91
+ Tilt.new("#{template_dir}/#{source}").render(self, variables)
92
+ rescue Exception => e
93
+ unexpected_failure("render template", e.message)
94
+ end
95
+ end
96
+
97
+ def template_dir
98
+ "#{module_root}/templates"
99
+ end
100
+
101
+ def module_root
102
+ dict[:module_root]
103
+ end
104
+
105
+ def unexpected_failure(message, reason)
106
+ print_error(message, {
107
+ path: path,
108
+ reason: reason
109
+ })
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,87 @@
1
+ module Hookit
2
+ module Resource
3
+ class Warning < Base
4
+
5
+ field :source
6
+ field :content
7
+ field :stream
8
+
9
+ actions :warn
10
+ default_action :warn
11
+
12
+ def initialize(name)
13
+ source(name) unless source or content
14
+ stream :stdout unless stream
15
+
16
+ @default_header = "\u25BC\u25BC\u25BC\u25BC :: WARNING :: \u25BC\u25BC\u25BC\u25BC"
17
+ @block_width = @default_header.length
18
+ end
19
+
20
+ def run(action)
21
+ case action
22
+ when :warn
23
+ warn!
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def gem
30
+ dict[:template_gem]
31
+ end
32
+
33
+ def gem_spec
34
+ Gem::Specification.find_by_name(gem)
35
+ end
36
+
37
+ def gem_root
38
+ gem_spec.gem_dir
39
+ end
40
+
41
+ def content!
42
+ output_string ||= content or ::File.open("#{gem_root}/messages/#{source}").read
43
+ return output_string
44
+ end
45
+
46
+ def header!
47
+
48
+ header = @default_header
49
+ padding = "\u25BC"
50
+
51
+ longest_line = content!.split.sort_by {|x| x.length}.last
52
+
53
+ if longest_line.length > header.length
54
+
55
+ difference = longest_line.length - header.length
56
+ padding *= (difference.to_f / 2).ceil
57
+
58
+ header = padding + header + padding
59
+ end
60
+
61
+ @block_width = header.length
62
+
63
+ puts header
64
+ end
65
+
66
+ def footer!
67
+ footer = "\u25B2" * @block_width
68
+ puts footer
69
+ end
70
+
71
+ def warn!
72
+
73
+ header!
74
+
75
+ case stream
76
+ when :stdout
77
+ puts content!
78
+ when :stderr
79
+ $stderr.puts content!
80
+ end
81
+
82
+ footer!
83
+ end
84
+
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,77 @@
1
+ module Hookit
2
+ module Resource
3
+ class Zfs < Base
4
+
5
+ field :snapshot
6
+ field :dataset
7
+ field :destination
8
+ field :source
9
+ field :ssh_host
10
+ field :options
11
+
12
+ actions :send, :receive, :transmit, :snapshot, :destroy, :rollback, :clone
13
+ default_action :send
14
+
15
+ def initialize(name)
16
+ snapshot(name) unless snapshot
17
+ super
18
+ end
19
+
20
+ def run(action)
21
+ case action
22
+ when :send
23
+ send!
24
+ when :receive
25
+ receive!
26
+ when :transmit
27
+ transmit!
28
+ when :snapshot
29
+ snapshot!
30
+ when :destroy
31
+ destroy!
32
+ when :rollback
33
+ rollback!
34
+ when :clone
35
+ clone!
36
+ end
37
+ end
38
+
39
+ def send!
40
+ run_command! "zfs send #{snapshot} | #{destination}"
41
+ end
42
+
43
+ def receive!
44
+ run_command! "#{source.to_s.strip} | zfs receive -F #{dataset}"
45
+ end
46
+
47
+ def transmit!
48
+ if ssh_host
49
+ run_command! "zfs send #{options} #{snapshot} | ssh -o stricthostkeychecking=no #{ssh_host} zfs receive -F #{dataset}"
50
+ else
51
+ run_command! "zfs send #{options} #{snapshot} | zfs receive -F #{dataset}"
52
+ end
53
+ end
54
+
55
+ def snapshot!
56
+ destroy!
57
+ run_command! "zfs snapshot #{snapshot}"
58
+ end
59
+
60
+ def destroy!
61
+ `zfs list -t snapshot | grep #{snapshot}`
62
+ if $?.exitstatus == 0
63
+ run_command! "zfs destroy #{snapshot}"
64
+ end
65
+ end
66
+
67
+ def rollback!
68
+ run_command! "zfs rollback -r #{snapshot}"
69
+ end
70
+
71
+ def clone!
72
+ run_command! "zfs clone #{snapshot} #{dataset}"
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,21 @@
1
+ require 'hookit/resource/base'
2
+ require 'hookit/resource/directory'
3
+ require 'hookit/resource/execute'
4
+ require 'hookit/resource/file'
5
+ require 'hookit/resource/hook_file'
6
+ require 'hookit/resource/link'
7
+ require 'hookit/resource/logrotate'
8
+ require 'hookit/resource/mount'
9
+ require 'hookit/resource/package'
10
+ require 'hookit/resource/rsync'
11
+ require 'hookit/resource/socket'
12
+ require 'hookit/resource/scp'
13
+ require 'hookit/resource/service'
14
+ require 'hookit/resource/template'
15
+ require 'hookit/resource/zfs'
16
+
17
+ module Hookit
18
+ module Resource
19
+
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ Hookit.resources.register(:directory) { Hookit::Resource::Directory }
2
+ Hookit.resources.register(:ensure_socket) { Hookit::Resource::Socket }
3
+ Hookit.resources.register(:execute) { Hookit::Resource::Execute }
4
+ Hookit.resources.register(:file) { Hookit::Resource::File }
5
+ Hookit.resources.register(:hook_file) { Hookit::Resource::HookFile }
6
+ Hookit.resources.register(:hookit_file) { Hookit::Resource::HookFile }
7
+ Hookit.resources.register(:link) { Hookit::Resource::Link }
8
+ Hookit.resources.register(:logrotate) { Hookit::Resource::Logrotate }
9
+ Hookit.resources.register(:mount) { Hookit::Resource::Mount }
10
+ Hookit.resources.register(:package) { Hookit::Resource::Package }
11
+ Hookit.resources.register(:rsync) { Hookit::Resource::Rsync }
12
+ Hookit.resources.register(:scp) { Hookit::Resource::Scp }
13
+ Hookit.resources.register(:service) { Hookit::Resource::Service }
14
+ Hookit.resources.register(:template) { Hookit::Resource::Template }
15
+ Hookit.resources.register(:zfs) { Hookit::Resource::Zfs }
@@ -0,0 +1,59 @@
1
+ # This file is meant ONLY as a way to make a hookit hook directly executable.
2
+ #
3
+ # Normally hookit is bootstrapped via `hookit hook-name "payload"`.
4
+ #
5
+ # This script allows a ruby executable script to bootstrap hookit and run as
6
+ # a hook directly.
7
+ #
8
+ # Usage:
9
+ #
10
+ # #!/usr/bin/env ruby
11
+ #
12
+ # # optionally, set some configuration
13
+ # # (if not set, MODULE_ROOT will default to the directory if this script)
14
+ #
15
+ # $LOG_LEVEL = :error
16
+ # $LOGFILE = '/var/log/hookit/hookit.log'
17
+ # $MODULE_DIR = "/opt/local/hookit/mod"
18
+ #
19
+ # # load hookit/setup to bootstrap hookit
20
+ # require 'hookit/setup'
21
+ #
22
+ # execute 'list all the files!' do
23
+ # command 'ls -lah /'
24
+ # end
25
+ #
26
+
27
+ # This won't handle every scenario, but essentially it tries to find the
28
+ # location of the script that was executed
29
+ hook = begin
30
+ if $0[0] == '/'
31
+ $0
32
+ else
33
+ "#{Dir.getwd}/#{$0}"
34
+ end
35
+ end
36
+
37
+ module_dir = File.dirname(hook)
38
+
39
+ MODULE_DIR = $MODULE_DIR || ENV['MODULE_DIR'] || module_dir
40
+ LOG_LEVEL = $LOG_LEVEL || ENV['LOG_LEVEL'] || :error
41
+ LOGFILE = $LOGFILE || ENV['LOGFILE'] || '/var/log/hookit/hookit.log'
42
+
43
+ require 'hookit'
44
+ require 'json'
45
+
46
+ include Hookit::Hook # payload helpers / resource dsl
47
+
48
+ set :log_level, LOG_LEVEL
49
+ set :logfile, LOGFILE
50
+ set :module_root, MODULE_DIR
51
+
52
+ # require hook libs
53
+ Dir.glob("#{MODULE_DIR}/lib/*.rb").each do |file|
54
+ require file
55
+ end
56
+
57
+ logger.info ""
58
+ logger.info "hook: #{hook}"
59
+ logger.info "payload: #{payload.to_json}"
@@ -0,0 +1,3 @@
1
+ module Hookit
2
+ VERSION = "0.12.11"
3
+ end
data/lib/hookit.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'hookit/converginator'
2
+ require 'hookit/db'
3
+ require 'hookit/error'
4
+ require 'hookit/exit'
5
+ require 'hookit/helper'
6
+ require 'hookit/hook'
7
+ require 'hookit/logger'
8
+ require 'hookit/platform'
9
+ require 'hookit/registry'
10
+ require 'hookit/resource'
11
+ require "hookit/version"
12
+
13
+ module Hookit
14
+ extend self
15
+
16
+ def resources
17
+ @resources ||= Hookit::Registry.new
18
+ end
19
+
20
+ def platforms
21
+ @platforms ||= Hookit::Registry.new
22
+ end
23
+ end
24
+
25
+ require 'hookit/resources'
26
+ require 'hookit/platforms'