hookit 0.7.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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +3 -0
- data/Rakefile +10 -0
- data/bin/hookit +41 -0
- data/hookit.gemspec +30 -0
- data/lib/hookit/converginator.rb +141 -0
- data/lib/hookit/db.rb +37 -0
- data/lib/hookit/error.rb +8 -0
- data/lib/hookit/exit.rb +23 -0
- data/lib/hookit/helper/cron.rb +42 -0
- data/lib/hookit/helper/nfs.rb +113 -0
- data/lib/hookit/helper/shell.rb +35 -0
- data/lib/hookit/helper/xml.rb +25 -0
- data/lib/hookit/helper.rb +9 -0
- data/lib/hookit/hook.rb +102 -0
- data/lib/hookit/logger.rb +58 -0
- data/lib/hookit/logvac.rb +34 -0
- data/lib/hookit/platform/base.rb +11 -0
- data/lib/hookit/platform/smartos.rb +19 -0
- data/lib/hookit/platform/ubuntu.rb +19 -0
- data/lib/hookit/platform.rb +9 -0
- data/lib/hookit/platforms.rb +2 -0
- data/lib/hookit/registry.rb +53 -0
- data/lib/hookit/resource/base.rb +105 -0
- data/lib/hookit/resource/cron.rb +26 -0
- data/lib/hookit/resource/directory.rb +67 -0
- data/lib/hookit/resource/execute.rb +148 -0
- data/lib/hookit/resource/file.rb +71 -0
- data/lib/hookit/resource/hook_file.rb +80 -0
- data/lib/hookit/resource/link.rb +61 -0
- data/lib/hookit/resource/logrotate.rb +38 -0
- data/lib/hookit/resource/mount.rb +77 -0
- data/lib/hookit/resource/package.rb +74 -0
- data/lib/hookit/resource/rsync.rb +67 -0
- data/lib/hookit/resource/scp.rb +87 -0
- data/lib/hookit/resource/service.rb +89 -0
- data/lib/hookit/resource/socket.rb +67 -0
- data/lib/hookit/resource/template.rb +87 -0
- data/lib/hookit/resource/warning.rb +87 -0
- data/lib/hookit/resource/zfs.rb +99 -0
- data/lib/hookit/resource.rb +21 -0
- data/lib/hookit/resources.rb +15 -0
- data/lib/hookit/version.rb +3 -0
- data/lib/hookit.rb +27 -0
- metadata +205 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
module Hookit
|
2
|
+
class Logger
|
3
|
+
|
4
|
+
attr_reader :log_file, :log_level
|
5
|
+
|
6
|
+
def initialize(file, level)
|
7
|
+
@log_file = file || '/var/log/hookit/hookit.log'
|
8
|
+
@log_level = level || :error
|
9
|
+
end
|
10
|
+
|
11
|
+
def log(level, message)
|
12
|
+
|
13
|
+
if not message
|
14
|
+
message = level
|
15
|
+
level = :error
|
16
|
+
end
|
17
|
+
|
18
|
+
if level_to_int(level) <= level_to_int(log_level)
|
19
|
+
send(level, message)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def error(message)
|
25
|
+
log! "[error]: #{message}\n"
|
26
|
+
end
|
27
|
+
|
28
|
+
def warn(message)
|
29
|
+
log! "[warn]: #{message}\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def info(message)
|
33
|
+
log! "[info]: #{message}\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def debug(message)
|
37
|
+
log! "[debug]: #{message}\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def log!(message)
|
43
|
+
File.open log_file, 'a' do |f|
|
44
|
+
f.write message
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def level_to_int(level)
|
49
|
+
case level
|
50
|
+
when :error then 1
|
51
|
+
when :warn then 2
|
52
|
+
when :info then 3
|
53
|
+
when :debug then 4
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
|
3
|
+
module Hookit
|
4
|
+
class Logvac
|
5
|
+
|
6
|
+
def initialize(opts)
|
7
|
+
@app = opts[:app]
|
8
|
+
@deploy = opts[:deploy]
|
9
|
+
@token = opts[:token]
|
10
|
+
end
|
11
|
+
|
12
|
+
def post(message)
|
13
|
+
connection.post("/deploy/#{@app}") do |req|
|
14
|
+
req.headers[:x_auth_token] = @token
|
15
|
+
req.headers[:x_deploy_id] = @deploy
|
16
|
+
req.body = message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
alias :print :post
|
20
|
+
|
21
|
+
def puts(message='')
|
22
|
+
post("#{message}\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def connection
|
28
|
+
@connection ||= Faraday.new(url: 'http://logvac.admin.pagodabox.io:6361') do |faraday|
|
29
|
+
faraday.adapter :excon
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Platform
|
3
|
+
class Ubuntu < Base
|
4
|
+
|
5
|
+
def detect?
|
6
|
+
! `[ -x /usr/bin/lsb_release ] && /usr/bin/lsb_release -i 2>/dev/null | grep Ubuntu`.empty?
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
'ubuntu'
|
11
|
+
end
|
12
|
+
|
13
|
+
def os
|
14
|
+
'linux'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Hookit
|
2
|
+
# Register components in a single location that can be queried.
|
3
|
+
#
|
4
|
+
# This allows certain components (such as guest systems, configuration
|
5
|
+
# pieces, etc.) to be registered and queried.
|
6
|
+
class Registry
|
7
|
+
def initialize
|
8
|
+
@actions = {}
|
9
|
+
@results_cache = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Register a callable by key.
|
13
|
+
#
|
14
|
+
# The callable should be given in a block which will be lazily evaluated
|
15
|
+
# when the action is needed.
|
16
|
+
#
|
17
|
+
# If an action by the given name already exists then it will be
|
18
|
+
# overwritten.
|
19
|
+
def register(key, value=nil, &block)
|
20
|
+
@results_cache.delete key
|
21
|
+
block = lambda { value } unless value.nil?
|
22
|
+
@actions[key] = block
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get an action by the given key.
|
26
|
+
#
|
27
|
+
# This will evaluate the block given to `register` and return the resulting
|
28
|
+
# action stack.
|
29
|
+
def get(key)
|
30
|
+
return nil unless @actions.has_key?(key)
|
31
|
+
return @results_cache[key] if @results_cache.has_key?(key)
|
32
|
+
@results_cache[key] = @actions[key].call
|
33
|
+
end
|
34
|
+
alias :[] :get
|
35
|
+
|
36
|
+
# Iterate over the keyspace.
|
37
|
+
def each(&block)
|
38
|
+
@actions.each do |key, _|
|
39
|
+
yield key, get(key)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts this registry to a hash
|
44
|
+
def to_hash
|
45
|
+
result = {}
|
46
|
+
self.each do |key, value|
|
47
|
+
result[key] = value
|
48
|
+
end
|
49
|
+
|
50
|
+
result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Resource
|
3
|
+
class Base
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def field(key)
|
8
|
+
define_method key do |*args, &block|
|
9
|
+
if data = block || args[0]
|
10
|
+
instance_variable_set("@#{key}", data)
|
11
|
+
else
|
12
|
+
instance_variable_get("@#{key}")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def actions(*actions)
|
18
|
+
if actions.any?
|
19
|
+
@actions = *actions
|
20
|
+
else
|
21
|
+
@actions
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_action(action=nil)
|
26
|
+
if action
|
27
|
+
@default_action = action
|
28
|
+
else
|
29
|
+
@default_action || :run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_accessor :dict
|
36
|
+
|
37
|
+
field :name
|
38
|
+
|
39
|
+
def initialize(name)
|
40
|
+
name(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def run(action); end
|
44
|
+
|
45
|
+
def can_run?
|
46
|
+
only_if_res = true
|
47
|
+
not_if_res = false
|
48
|
+
|
49
|
+
if only_if and only_if.respond_to? :call
|
50
|
+
only_if_res = only_if.call
|
51
|
+
end
|
52
|
+
|
53
|
+
if not_if and not_if.respond_to? :call
|
54
|
+
not_if_res = not_if.call
|
55
|
+
end
|
56
|
+
|
57
|
+
only_if_res and not not_if_res
|
58
|
+
end
|
59
|
+
|
60
|
+
def action(*actions)
|
61
|
+
if actions.any?
|
62
|
+
actions.each do |action|
|
63
|
+
if not self.class.actions.include? action
|
64
|
+
raise Hookit::Error::UnknownAction, "unknown action '#{action}'"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
@actions = *actions
|
68
|
+
else
|
69
|
+
@actions || [default_action]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def default_action
|
74
|
+
self.class.default_action
|
75
|
+
end
|
76
|
+
|
77
|
+
def not_if(&block)
|
78
|
+
if block_given?
|
79
|
+
@not_if = block
|
80
|
+
else
|
81
|
+
@not_if
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def only_if(&block)
|
86
|
+
if block_given?
|
87
|
+
@only_if = block
|
88
|
+
else
|
89
|
+
@only_if
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
def run_command!(cmd, expect_code=0)
|
96
|
+
`#{cmd}`
|
97
|
+
code = $?.exitstatus
|
98
|
+
if code != expect_code
|
99
|
+
raise Hookit::Error::UnexpectedExit, "#{cmd} failed with exit code '#{code}'"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Resource
|
3
|
+
class Cron < Execute
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
super
|
7
|
+
timeout 60
|
8
|
+
cwd '/data'
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def run!
|
14
|
+
begin
|
15
|
+
Timeout::timeout(timeout) do
|
16
|
+
f = IO.popen("#{cmd} || exit 0", :err=>[:child, :out])
|
17
|
+
puts f.readline while true
|
18
|
+
end
|
19
|
+
rescue Timeout::Error
|
20
|
+
$stderr.puts 'Timed out running cron! Consider using a worker.'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Resource
|
3
|
+
class Directory < Base
|
4
|
+
|
5
|
+
field :path
|
6
|
+
field :recursive
|
7
|
+
field :mode
|
8
|
+
field :owner
|
9
|
+
field :group
|
10
|
+
|
11
|
+
actions :create, :delete
|
12
|
+
default_action :create
|
13
|
+
|
14
|
+
def initialize(name)
|
15
|
+
path name unless path
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(action)
|
20
|
+
case action
|
21
|
+
when :create
|
22
|
+
create!
|
23
|
+
chown!
|
24
|
+
chmod!
|
25
|
+
when :delete
|
26
|
+
delete!
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def create!
|
33
|
+
return if ::File.exists? path
|
34
|
+
cmd = "mkdir #{"-p " if recursive}#{path}"
|
35
|
+
`#{cmd}`
|
36
|
+
code = $?.exitstatus
|
37
|
+
if code != 0
|
38
|
+
raise Hookit::Error::UnexpectedExit, "#{cmd} failed with exit code '#{code}'"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete!
|
43
|
+
return if not ::File.exists? path
|
44
|
+
cmd = "rm -rf #{path}"
|
45
|
+
`#{cmd}`
|
46
|
+
code = $?.exitstatus
|
47
|
+
if code != 0
|
48
|
+
raise Hookit::Error::UnexpectedExit, "#{cmd} failed with exit code '#{code}'"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def chown!
|
53
|
+
return unless owner or group
|
54
|
+
if ::File.exists? path
|
55
|
+
`chown #{(group.nil?) ? owner : "#{owner}:#{group}"} #{path}`
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def chmod!
|
60
|
+
if ::File.exists? path and mode
|
61
|
+
::File.chmod(mode, path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
|
3
|
+
module Hookit
|
4
|
+
module Resource
|
5
|
+
class Execute < Base
|
6
|
+
|
7
|
+
field :command
|
8
|
+
field :cwd
|
9
|
+
field :environment
|
10
|
+
field :user
|
11
|
+
field :path
|
12
|
+
field :returns
|
13
|
+
field :timeout
|
14
|
+
field :stream
|
15
|
+
field :on_data
|
16
|
+
field :validator
|
17
|
+
field :ignore_exit
|
18
|
+
|
19
|
+
actions :run
|
20
|
+
default_action :run
|
21
|
+
|
22
|
+
def initialize(name)
|
23
|
+
command name unless command
|
24
|
+
timeout 3600
|
25
|
+
returns 0
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def run(action)
|
30
|
+
case action
|
31
|
+
when :run
|
32
|
+
if stream
|
33
|
+
stream!
|
34
|
+
else
|
35
|
+
run!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def validate!(res)
|
43
|
+
if validator.is_a? Proc
|
44
|
+
if validator.call(res)
|
45
|
+
res
|
46
|
+
else
|
47
|
+
raise "ERROR: execute resource \"#{name}\" failed validation!"
|
48
|
+
end
|
49
|
+
else
|
50
|
+
res
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def run!
|
55
|
+
Timeout::timeout(timeout) do
|
56
|
+
res = `#{cmd}`
|
57
|
+
code = $?.exitstatus
|
58
|
+
unexpected_exit(code) unless code == returns
|
59
|
+
validate! res
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def stream!
|
64
|
+
result = ""
|
65
|
+
|
66
|
+
STDOUT.sync = STDERR.sync = true # don't buffer stdout/stderr
|
67
|
+
|
68
|
+
::IO.popen(cmd, :err=>[:child, :out]) do |out|
|
69
|
+
eof = false
|
70
|
+
until eof do
|
71
|
+
begin
|
72
|
+
chunk = out.readpartial(4096)
|
73
|
+
if on_data and on_data.respond_to? :call
|
74
|
+
on_data.call(chunk)
|
75
|
+
end
|
76
|
+
rescue EOFError
|
77
|
+
eof = true
|
78
|
+
end
|
79
|
+
result << chunk.to_s
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
code = $?.exitstatus
|
84
|
+
unexpected_exit(code) unless code == returns
|
85
|
+
|
86
|
+
validate! result
|
87
|
+
end
|
88
|
+
|
89
|
+
def cmd
|
90
|
+
com = command
|
91
|
+
|
92
|
+
if environment
|
93
|
+
com = "#{env}#{com}"
|
94
|
+
end
|
95
|
+
|
96
|
+
if path
|
97
|
+
com = "export PATH=\"#{path}\"; #{com}"
|
98
|
+
end
|
99
|
+
|
100
|
+
if cwd
|
101
|
+
com = "cd #{cwd}; #{com}"
|
102
|
+
end
|
103
|
+
|
104
|
+
if user
|
105
|
+
com = su(user, com)
|
106
|
+
end
|
107
|
+
|
108
|
+
com
|
109
|
+
end
|
110
|
+
|
111
|
+
# strategy:
|
112
|
+
# 1- escape the escapes
|
113
|
+
# 2- escape quotes
|
114
|
+
# 3- escape dollar signs
|
115
|
+
def escape(cmd)
|
116
|
+
cmd.gsub!(/\\/, "\\\\\\")
|
117
|
+
cmd.gsub!(/"/, "\\\"")
|
118
|
+
cmd.gsub!(/\$/, "\\$")
|
119
|
+
cmd
|
120
|
+
end
|
121
|
+
|
122
|
+
def su(user, cmd)
|
123
|
+
"su - #{user} -c \"#{escape(cmd)}\""
|
124
|
+
end
|
125
|
+
|
126
|
+
def env
|
127
|
+
vars = environment || {}
|
128
|
+
env = ''
|
129
|
+
vars.each do |key, val|
|
130
|
+
env += " " if not env == ''
|
131
|
+
env += env_string(key, val)
|
132
|
+
end
|
133
|
+
(env == '')? env : "#{env}"
|
134
|
+
end
|
135
|
+
|
136
|
+
def env_string(key, val)
|
137
|
+
key = key.to_s if not key.is_a? String
|
138
|
+
val = val.to_s if not val.is_a? String
|
139
|
+
%Q{export #{key.upcase}="#{escape(val)}";}
|
140
|
+
end
|
141
|
+
|
142
|
+
def unexpected_exit(res)
|
143
|
+
raise Hookit::Error::UnexpectedExit, "'#{name}' exited with #{res}, expected #{returns}" unless ignore_exit
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Resource
|
3
|
+
class File < Base
|
4
|
+
|
5
|
+
field :path
|
6
|
+
field :content
|
7
|
+
field :mode
|
8
|
+
field :owner
|
9
|
+
field :group
|
10
|
+
|
11
|
+
actions :create, :create_if_missing, :delete, :touch
|
12
|
+
default_action :create
|
13
|
+
|
14
|
+
def initialize(name)
|
15
|
+
path name unless path
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(action)
|
20
|
+
case action
|
21
|
+
when :create
|
22
|
+
create!
|
23
|
+
chown!
|
24
|
+
chmod!
|
25
|
+
when :create_if_missing
|
26
|
+
create_if_missing!
|
27
|
+
chown!
|
28
|
+
chmod!
|
29
|
+
when :delete
|
30
|
+
delete!
|
31
|
+
when :touch
|
32
|
+
touch!
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def create!
|
39
|
+
::File.write path, (content || "")
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_if_missing!
|
43
|
+
if not ::File.exists? path
|
44
|
+
create!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete!
|
49
|
+
::File.delete path
|
50
|
+
end
|
51
|
+
|
52
|
+
def chown!
|
53
|
+
return unless owner or group
|
54
|
+
if ::File.exists? path
|
55
|
+
`chown #{(group.nil?) ? owner : "#{owner}:#{group}"} #{path}`
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def chmod!
|
60
|
+
if ::File.exists? path and mode
|
61
|
+
::File.chmod(mode, path)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def touch!
|
66
|
+
`touch -c #{path}`
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Hookit
|
2
|
+
module Resource
|
3
|
+
class HookFile < Base
|
4
|
+
|
5
|
+
field :path
|
6
|
+
field :source
|
7
|
+
field :mode
|
8
|
+
field :owner
|
9
|
+
field :group
|
10
|
+
|
11
|
+
actions :create, :create_if_missing, :delete, :touch
|
12
|
+
default_action :create
|
13
|
+
|
14
|
+
def initialize(name)
|
15
|
+
path name unless path
|
16
|
+
source ::File.basename(name)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(action)
|
21
|
+
case action
|
22
|
+
when :create
|
23
|
+
create!
|
24
|
+
chown!
|
25
|
+
chmod!
|
26
|
+
when :create_if_missing
|
27
|
+
create_if_missing!
|
28
|
+
chown!
|
29
|
+
chmod!
|
30
|
+
when :delete
|
31
|
+
delete!
|
32
|
+
when :touch
|
33
|
+
touch!
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def create!
|
40
|
+
::File.write path, render
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_if_missing!
|
44
|
+
if not ::File.exists? path
|
45
|
+
create!
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete!
|
50
|
+
::File.delete path
|
51
|
+
end
|
52
|
+
|
53
|
+
def chown!
|
54
|
+
return unless owner or group
|
55
|
+
`chown #{(group.nil?) ? owner : "#{owner}:#{group}"} #{path}`
|
56
|
+
end
|
57
|
+
|
58
|
+
def chmod!
|
59
|
+
::File.chmod(mode, path) if mode
|
60
|
+
end
|
61
|
+
|
62
|
+
def touch!
|
63
|
+
`touch -c #{path}`
|
64
|
+
end
|
65
|
+
|
66
|
+
def render
|
67
|
+
::File.read("#{file_dir}/#{source}")
|
68
|
+
end
|
69
|
+
|
70
|
+
def file_dir
|
71
|
+
"#{module_root}/files"
|
72
|
+
end
|
73
|
+
|
74
|
+
def module_root
|
75
|
+
dict[:module_root]
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|