dust-deploy 0.16.4 → 0.16.5
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/LICENSE +3 -3
- data/README.md +1 -1
- data/changelog.md +14 -0
- data/dust.gemspec +8 -7
- data/lib/dust/examples/nodes/postgresql.yaml +4 -3
- data/lib/dust/examples/templates/duplicity/cronjob.erb +2 -2
- data/lib/dust/helper.rb +0 -7
- data/lib/dust/recipes/apt.rb +4 -4
- data/lib/dust/recipes/debsecan.rb +26 -30
- data/lib/dust/recipes/dnsmasq.rb +1 -1
- data/lib/dust/recipes/dovecot.rb +1 -1
- data/lib/dust/recipes/duplicity.rb +1 -1
- data/lib/dust/recipes/iptables.rb +1 -1
- data/lib/dust/recipes/limits.rb +1 -1
- data/lib/dust/recipes/nginx.rb +2 -2
- data/lib/dust/recipes/packages.rb +1 -1
- data/lib/dust/recipes/postfix.rb +2 -2
- data/lib/dust/recipes/postgres.rb +6 -3
- data/lib/dust/recipes/rc_local.rb +1 -1
- data/lib/dust/recipes/repositories.rb +9 -4
- data/lib/dust/recipes/resolv_conf.rb +1 -1
- data/lib/dust/recipes/skel.rb +2 -2
- data/lib/dust/recipes/ssh_config.rb +2 -2
- data/lib/dust/recipes/sshd.rb +3 -4
- data/lib/dust/recipes/sysctl.rb +1 -1
- data/lib/dust/recipes/users.rb +1 -1
- data/lib/dust/recipes/zabbix_agent.rb +1 -1
- data/lib/dust/runner.rb +3 -3
- data/lib/dust/server.rb +3 -873
- data/lib/dust/server/facter.rb +33 -0
- data/lib/dust/server/file.rb +152 -0
- data/lib/dust/server/osdetect.rb +112 -0
- data/lib/dust/server/package.rb +215 -0
- data/lib/dust/server/selinux.rb +40 -0
- data/lib/dust/server/service.rb +82 -0
- data/lib/dust/server/ssh.rb +182 -0
- data/lib/dust/server/user.rb +117 -0
- data/lib/dust/version.rb +1 -1
- metadata +32 -39
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'dust/server/ssh'
|
2
|
+
|
3
|
+
module Dust
|
4
|
+
class Server
|
5
|
+
def selinuxenabled?
|
6
|
+
return true if exec('selinuxenabled')[:exit_code] == 0
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
# check if restorecon (selinux) is available
|
11
|
+
# if so, run it on "path" recursively
|
12
|
+
def restorecon(path, options={})
|
13
|
+
options = default_options.merge(options)
|
14
|
+
|
15
|
+
# if selinux is not enabled, just return
|
16
|
+
return true unless selinuxenabled?
|
17
|
+
|
18
|
+
msg = messages.add("restoring selinux labels for #{path}", options)
|
19
|
+
msg.parse_result(exec("restorecon -R #{path}")[:exit_code])
|
20
|
+
end
|
21
|
+
|
22
|
+
def chcon(permissions, file, options={})
|
23
|
+
options = default_options.merge(options)
|
24
|
+
|
25
|
+
# just return if selinux is not enabled
|
26
|
+
return true unless selinuxenabled?
|
27
|
+
|
28
|
+
args = ""
|
29
|
+
args << " --type #{permissions['type']}" if permissions['type']
|
30
|
+
args << " --recursive #{permissions['recursive']}" if permissions['recursive']
|
31
|
+
args << " --user #{permissions['user']}" if permissions['user']
|
32
|
+
args << " --range #{permissions['range']}" if permissions['range']
|
33
|
+
args << " --role #{permissions['role']}" if permissions['role']
|
34
|
+
|
35
|
+
msg = messages.add("setting selinux permissions of #{File.basename(file)}", options)
|
36
|
+
msg.parse_result(exec("chcon #{args} #{file}")[:exit_code])
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'dust/server/ssh'
|
2
|
+
|
3
|
+
module Dust
|
4
|
+
class Server
|
5
|
+
def autostart_service(service, options={})
|
6
|
+
options = default_options.merge(options)
|
7
|
+
|
8
|
+
msg = messages.add("autostart #{service} on boot", options)
|
9
|
+
|
10
|
+
if uses_rpm?
|
11
|
+
if file_exists? '/bin/systemctl', :quiet => true
|
12
|
+
msg.parse_result(exec("systemctl enable #{service}.service")[:exit_code])
|
13
|
+
else
|
14
|
+
msg.parse_result(exec("chkconfig #{service} on")[:exit_code])
|
15
|
+
end
|
16
|
+
|
17
|
+
elsif uses_apt?
|
18
|
+
msg.parse_result(exec("update-rc.d #{service} defaults")[:exit_code])
|
19
|
+
|
20
|
+
elsif uses_emerge?
|
21
|
+
msg.parse_result(exec("rc-update add #{service} default")[:exit_code])
|
22
|
+
|
23
|
+
# archlinux needs his autostart daemons in /etc/rc.conf, in the DAEMONS line
|
24
|
+
#elsif uses_pacman?
|
25
|
+
|
26
|
+
else
|
27
|
+
msg.failed
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# invoke 'command' on the service (e.g. @node.service 'postgresql', 'restart')
|
32
|
+
def service(service, command, options={})
|
33
|
+
options = default_options.merge(options)
|
34
|
+
|
35
|
+
return messages.add("service: '#{service}' unknown", options).failed unless service.is_a? String
|
36
|
+
|
37
|
+
# try systemd, then upstart, then sysvconfig, then rc.d, then initscript
|
38
|
+
if file_exists? '/bin/systemctl', :quiet => true
|
39
|
+
msg = messages.add("#{command}ing #{service} (via systemd)", options)
|
40
|
+
ret = exec("systemctl #{command} #{service}.service")
|
41
|
+
|
42
|
+
elsif file_exists? "/etc/init/#{service}", :quiet => true
|
43
|
+
msg = messages.add("#{command}ing #{service} (via upstart)", options)
|
44
|
+
ret = exec("#{command} #{service}")
|
45
|
+
|
46
|
+
elsif file_exists? '/sbin/service', :quiet => true or file_exists? '/usr/sbin/service', :quiet => true
|
47
|
+
msg = messages.add("#{command}ing #{service} (via sysvconfig)", options)
|
48
|
+
ret = exec("service #{service} #{command}")
|
49
|
+
|
50
|
+
elsif file_exists? '/usr/sbin/rc.d', :quiet => true
|
51
|
+
msg = messages.add("#{command}ing #{service} (via rc.d)", options)
|
52
|
+
ret = exec("rc.d #{command} #{service}")
|
53
|
+
|
54
|
+
else
|
55
|
+
msg = messages.add("#{command}ing #{service} (via initscript)", options)
|
56
|
+
ret = exec("/etc/init.d/#{service} #{command}")
|
57
|
+
end
|
58
|
+
|
59
|
+
msg.parse_result(ret[:exit_code])
|
60
|
+
ret
|
61
|
+
end
|
62
|
+
|
63
|
+
def restart_service(service, options={})
|
64
|
+
options = default_options.merge(options)
|
65
|
+
|
66
|
+
service(service, 'restart', options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def reload_service(service, options={})
|
70
|
+
options = default_options.merge(options)
|
71
|
+
|
72
|
+
service(service, 'reload', options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_service_status(service, options={})
|
76
|
+
options = default_options.merge(:indent => 0).merge(options)
|
77
|
+
ret = service(service, 'status', options)
|
78
|
+
messages.add('', options).print_output(ret)
|
79
|
+
ret
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'net/ssh'
|
2
|
+
require 'net/scp'
|
3
|
+
require 'net/ssh/proxy/socks5'
|
4
|
+
|
5
|
+
require 'dust/server/file'
|
6
|
+
require 'dust/server/osdetect'
|
7
|
+
require 'dust/server/package'
|
8
|
+
require 'dust/server/selinux'
|
9
|
+
|
10
|
+
module Dust
|
11
|
+
class Server
|
12
|
+
attr_reader :ssh
|
13
|
+
|
14
|
+
def connect
|
15
|
+
messages.print_hostname_header(@node['hostname']) unless $parallel
|
16
|
+
|
17
|
+
begin
|
18
|
+
# connect to proxy if given
|
19
|
+
if @node['proxy']
|
20
|
+
host, port = @node['proxy'].split ':'
|
21
|
+
proxy = Net::SSH::Proxy::SOCKS5.new(host, port)
|
22
|
+
else
|
23
|
+
proxy = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
@ssh = Net::SSH.start @node['fqdn'], @node['user'],
|
27
|
+
{ :password => @node['password'],
|
28
|
+
:port => @node['port'],
|
29
|
+
:proxy => proxy }
|
30
|
+
rescue Exception
|
31
|
+
error_message = "coudln't connect to #{@node['fqdn']}"
|
32
|
+
error_message << " (via socks5 proxy #{@node['proxy']})" if proxy
|
33
|
+
messages.add(error_message, :indent => 0).failed
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def disconnect
|
41
|
+
@ssh.close
|
42
|
+
end
|
43
|
+
|
44
|
+
def exec(command, options={:live => false, :as_user => false})
|
45
|
+
sudo_authenticated = false
|
46
|
+
stdout = ''
|
47
|
+
stderr = ''
|
48
|
+
exit_code = nil
|
49
|
+
exit_signal = nil
|
50
|
+
|
51
|
+
# prepend a newline, if output is live
|
52
|
+
messages.add("\n", :indent => 0) if options[:live]
|
53
|
+
|
54
|
+
@ssh.open_channel do |channel|
|
55
|
+
|
56
|
+
# if :as_user => user is given, execute as user (be aware of ' usage)
|
57
|
+
command = "su #{options[:as_user]} -l -c '#{command}'" if options[:as_user]
|
58
|
+
|
59
|
+
# request a terminal (sudo needs it)
|
60
|
+
# and prepend "sudo"
|
61
|
+
# command is wrapped in ", escapes " in the command string
|
62
|
+
# and then executed using "sh -c", so that
|
63
|
+
# the use of > < && || | and ; doesn't screw things up
|
64
|
+
if @node['sudo']
|
65
|
+
channel.request_pty
|
66
|
+
command = "sudo -k -- sh -c \"#{command.gsub('"','\\"')}\""
|
67
|
+
end
|
68
|
+
|
69
|
+
channel.exec command do |ch, success|
|
70
|
+
abort "FAILED: couldn't execute command (ssh.channel.exec)" unless success
|
71
|
+
|
72
|
+
channel.on_data do |ch, data|
|
73
|
+
# only send password if sudo mode is enabled,
|
74
|
+
# and only send password once in a session (trying to prevent attacks reading out the password)
|
75
|
+
if data =~ /\[sudo\] password for #{@node['user']}/
|
76
|
+
|
77
|
+
raise 'password requested, but none given in config!' if @node['password'].empty?
|
78
|
+
raise 'already sent password, but sudo requested the password again. (wrong password?)' if sudo_authenticated
|
79
|
+
|
80
|
+
# we're not authenticated yet, send password
|
81
|
+
channel.send_data "#{@node['password']}\n"
|
82
|
+
sudo_authenticated = true
|
83
|
+
|
84
|
+
else
|
85
|
+
# skip everything util authenticated (if sudo is used and password given in config)
|
86
|
+
next if @node['sudo'] and not @node['password'].empty? and not sudo_authenticated
|
87
|
+
|
88
|
+
stdout += data
|
89
|
+
messages.add(data.green, :indent => 0) if options[:live] and not data.empty?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
channel.on_extended_data do |ch, type, data|
|
94
|
+
stderr += data
|
95
|
+
messages.add(data.red, :indent => 0) if options[:live] and not data.empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
channel.on_request('exit-status') { |ch, data| exit_code = data.read_long }
|
99
|
+
channel.on_request('exit-signal') { |ch, data| exit_signal = data.read_long }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
@ssh.loop
|
104
|
+
|
105
|
+
# sudo usage provokes a heading newline that's unwanted.
|
106
|
+
stdout.sub! /^(\r\n|\n|\r)/, '' if @node['sudo']
|
107
|
+
|
108
|
+
{ :stdout => stdout, :stderr => stderr, :exit_code => exit_code, :exit_signal => exit_signal }
|
109
|
+
end
|
110
|
+
|
111
|
+
def scp(source, destination, options={})
|
112
|
+
options = default_options.merge(options)
|
113
|
+
|
114
|
+
# make sure scp is installed on client
|
115
|
+
install_package('openssh-clients', :quiet => true) if uses_rpm?
|
116
|
+
|
117
|
+
msg = messages.add("deploying #{File.basename source}", options)
|
118
|
+
|
119
|
+
# check if destination is a directory
|
120
|
+
is_dir = dir_exists?(destination, :quiet => true)
|
121
|
+
|
122
|
+
# save permissions if the file already exists
|
123
|
+
ret = exec("stat -c %a:%u:%g #{destination}")
|
124
|
+
if ret[:exit_code] == 0 and not is_dir
|
125
|
+
permissions, user, group = ret[:stdout].chomp.split(':')
|
126
|
+
else
|
127
|
+
# files = 644, dirs = 755
|
128
|
+
permissions = 'ug-x,o-wx,u=rwX,g=rX,o=rX'
|
129
|
+
user = 'root'
|
130
|
+
group = 'root'
|
131
|
+
end
|
132
|
+
|
133
|
+
# if in sudo mode, copy file to temporary place, then move using sudo
|
134
|
+
if @node['sudo']
|
135
|
+
tmpdir = mktemp(:type => 'directory')
|
136
|
+
return msg.failed('could not create temporary directory (needed for sudo)') unless tmpdir
|
137
|
+
|
138
|
+
# temporary destination in tmpdir
|
139
|
+
tmpdest = "#{tmpdir}/#{File.basename(destination)}"
|
140
|
+
|
141
|
+
# allow user to write file without sudo (for scp)
|
142
|
+
# then change file back to root, and copy to the destination
|
143
|
+
chown(@node['user'], tmpdir, :quiet => true)
|
144
|
+
@ssh.scp.upload!(source, tmpdest, :recursive => true)
|
145
|
+
|
146
|
+
# set file permissions
|
147
|
+
chown("#{user}:#{group}", tmpdest, :quiet => true) if user and group
|
148
|
+
chmod(permissions, tmpdest, :quiet => true)
|
149
|
+
|
150
|
+
# if destination is a directory, append real filename
|
151
|
+
destination = "#{destination}/#{File.basename(source)}" if is_dir
|
152
|
+
|
153
|
+
# move the file from the temporary location to where it actually belongs
|
154
|
+
msg.parse_result(exec("mv -f #{tmpdest} #{destination}")[:exit_code])
|
155
|
+
|
156
|
+
# remove temporary directory
|
157
|
+
rm(tmpdir, :quiet => true)
|
158
|
+
|
159
|
+
else
|
160
|
+
@ssh.scp.upload!(source, destination, :recursive => true)
|
161
|
+
msg.ok
|
162
|
+
|
163
|
+
# set file permissions
|
164
|
+
chown("#{user}:#{group}", destination, :quiet => true) if user and group
|
165
|
+
chmod(permissions, destination, :quiet => true)
|
166
|
+
end
|
167
|
+
|
168
|
+
restorecon(destination, options) # restore SELinux labels
|
169
|
+
end
|
170
|
+
|
171
|
+
# download a file (sudo not yet supported)
|
172
|
+
def download(source, destination, options={})
|
173
|
+
options = default_options.merge(options)
|
174
|
+
|
175
|
+
# make sure scp is installed on client
|
176
|
+
install_package('openssh-clients', :quiet => true) if uses_rpm?
|
177
|
+
|
178
|
+
msg = messages.add("downloading #{File.basename source}", options)
|
179
|
+
msg.parse_result(@ssh.scp.download!(source, destination))
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'dust/server/ssh'
|
2
|
+
require 'dust/server/selinux'
|
3
|
+
|
4
|
+
module Dust
|
5
|
+
class Server
|
6
|
+
def get_system_users(options={})
|
7
|
+
options = default_options.merge(options)
|
8
|
+
|
9
|
+
msg = messages.add("getting all system users", options)
|
10
|
+
ret = exec 'getent passwd |cut -d: -f1'
|
11
|
+
msg.parse_result(ret[:exit_code])
|
12
|
+
|
13
|
+
users = []
|
14
|
+
ret[:stdout].each do |user|
|
15
|
+
users.push(user.chomp)
|
16
|
+
end
|
17
|
+
users
|
18
|
+
end
|
19
|
+
|
20
|
+
# check whether a user exists on this node
|
21
|
+
def user_exists? user, options={}
|
22
|
+
options = default_options.merge(options)
|
23
|
+
|
24
|
+
msg = messages.add("checking if user #{user} exists", options)
|
25
|
+
msg.parse_result(exec("id #{user}")[:exit_code])
|
26
|
+
end
|
27
|
+
|
28
|
+
# manages users (create, modify)
|
29
|
+
def manage_user(user, options={})
|
30
|
+
options = default_options.merge(options)
|
31
|
+
options = { 'home' => nil, 'shell' => nil, 'uid' => nil, 'remove' => false,
|
32
|
+
'gid' => nil, 'groups' => nil, 'system' => false }.merge(options)
|
33
|
+
|
34
|
+
# delete user from system
|
35
|
+
if options['remove']
|
36
|
+
if user_exists?(user, :quiet => true)
|
37
|
+
msg = messages.add("deleting user #{user} from system", { :indent => options[:indent] }.merge(options))
|
38
|
+
return msg.parse_result(exec("userdel --remove #{user}")[:exit_code])
|
39
|
+
end
|
40
|
+
|
41
|
+
return messages.add("user #{user} not present in system", options).ok
|
42
|
+
end
|
43
|
+
|
44
|
+
if user_exists?(user, :quiet => true)
|
45
|
+
args = ""
|
46
|
+
args << " --move-home --home #{options['home']}" if options['home']
|
47
|
+
args << " --shell #{options['shell']}" if options['shell']
|
48
|
+
args << " --uid #{options['uid']}" if options['uid']
|
49
|
+
args << " --gid #{options['gid']}" if options['gid']
|
50
|
+
args << " --append --groups #{Array(options['groups']).join(',')}" if options['groups']
|
51
|
+
|
52
|
+
if args.empty?
|
53
|
+
ret = messages.add("user #{user} already set up correctly", options).ok
|
54
|
+
else
|
55
|
+
msg = messages.add("modifying user #{user}", { :indent => options[:indent] }.merge(options))
|
56
|
+
ret = msg.parse_result(exec("usermod #{args} #{user}")[:exit_code])
|
57
|
+
end
|
58
|
+
|
59
|
+
else
|
60
|
+
args = ""
|
61
|
+
args = "--create-home" unless options['system']
|
62
|
+
args << " --system" if options['system']
|
63
|
+
args << " --home #{options['home']}" if options['home'] and not options['system']
|
64
|
+
args << " --shell #{options['shell']}" if options['shell']
|
65
|
+
args << " --uid #{options['uid']}" if options['uid']
|
66
|
+
args << " --gid #{options['gid']}" if options['gid']
|
67
|
+
args << " --groups #{Array(options['groups']).join(',')}" if options['groups']
|
68
|
+
|
69
|
+
msg = messages.add("creating user #{user}", { :indent => options[:indent] }.merge(options))
|
70
|
+
ret = msg.parse_result(exec("useradd #{user} #{args}")[:exit_code])
|
71
|
+
end
|
72
|
+
|
73
|
+
# set selinux permissions
|
74
|
+
chcon({ 'type' => 'user_home_dir_t' }, get_home(user), options)
|
75
|
+
return ret
|
76
|
+
end
|
77
|
+
|
78
|
+
# returns the home directory of this user
|
79
|
+
def get_home(user, options={})
|
80
|
+
options = default_options(:quiet => true).merge(options)
|
81
|
+
|
82
|
+
msg = messages.add("getting home directory of #{user}", options)
|
83
|
+
ret = exec("getent passwd |cut -d':' -f1,6 |grep '^#{user}' |head -n1 |cut -d: -f2")
|
84
|
+
if msg.parse_result(ret[:exit_code]) and not ret[:stdout].chomp.empty?
|
85
|
+
return ret[:stdout].chomp
|
86
|
+
else
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# returns shell of this user
|
92
|
+
def get_shell(user, options={})
|
93
|
+
options = default_options(:quiet => true).merge(options)
|
94
|
+
|
95
|
+
msg = messages.add("getting shell of #{user}", options)
|
96
|
+
ret = exec("getent passwd |cut -d':' -f1,7 |grep '^#{user}' |head -n1 |cut -d: -f2")
|
97
|
+
if msg.parse_result(ret[:exit_code])
|
98
|
+
return ret[:stdout].chomp
|
99
|
+
else
|
100
|
+
return false
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# returns primary group id of this user
|
105
|
+
def get_gid(user, options={})
|
106
|
+
options = default_options(:quiet => true).merge(options)
|
107
|
+
|
108
|
+
msg = messages.add("getting primary gid of #{user}", options)
|
109
|
+
ret = exec("id -g #{user}")
|
110
|
+
if msg.parse_result(ret[:exit_code])
|
111
|
+
return ret[:stdout].chomp
|
112
|
+
else
|
113
|
+
return false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/dust/version.rb
CHANGED
metadata
CHANGED
@@ -1,126 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dust-deploy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.
|
5
|
-
prerelease:
|
4
|
+
version: 0.16.5
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- kris kechagia
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-05-31 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: json
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: net-ssh
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :runtime
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: net-scp
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: net-sftp
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: thor
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: ipaddress
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :runtime
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
108
95
|
- !ruby/object:Gem::Version
|
109
96
|
version: '0'
|
110
97
|
- !ruby/object:Gem::Dependency
|
111
98
|
name: colorize
|
112
99
|
requirement: !ruby/object:Gem::Requirement
|
113
|
-
none: false
|
114
100
|
requirements:
|
115
|
-
- -
|
101
|
+
- - '>='
|
116
102
|
- !ruby/object:Gem::Version
|
117
103
|
version: '0'
|
118
104
|
type: :runtime
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
107
|
requirements:
|
123
|
-
- -
|
108
|
+
- - '>='
|
124
109
|
- !ruby/object:Gem::Version
|
125
110
|
version: '0'
|
126
111
|
description: when puppet and chef suck because you want to be in control and sprinkle
|
@@ -205,29 +190,37 @@ files:
|
|
205
190
|
- lib/dust/recipes/zabbix_agent.rb
|
206
191
|
- lib/dust/runner.rb
|
207
192
|
- lib/dust/server.rb
|
193
|
+
- lib/dust/server/facter.rb
|
194
|
+
- lib/dust/server/file.rb
|
195
|
+
- lib/dust/server/osdetect.rb
|
196
|
+
- lib/dust/server/package.rb
|
197
|
+
- lib/dust/server/selinux.rb
|
198
|
+
- lib/dust/server/service.rb
|
199
|
+
- lib/dust/server/ssh.rb
|
200
|
+
- lib/dust/server/user.rb
|
208
201
|
- lib/dust/version.rb
|
209
|
-
homepage:
|
210
|
-
licenses:
|
202
|
+
homepage: https://github.com/kechagia/dust-deploy
|
203
|
+
licenses:
|
204
|
+
- GPLv3
|
205
|
+
metadata: {}
|
211
206
|
post_install_message:
|
212
207
|
rdoc_options: []
|
213
208
|
require_paths:
|
214
209
|
- lib
|
215
210
|
required_ruby_version: !ruby/object:Gem::Requirement
|
216
|
-
none: false
|
217
211
|
requirements:
|
218
|
-
- -
|
212
|
+
- - '>='
|
219
213
|
- !ruby/object:Gem::Version
|
220
214
|
version: '0'
|
221
215
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
|
-
none: false
|
223
216
|
requirements:
|
224
|
-
- -
|
217
|
+
- - '>='
|
225
218
|
- !ruby/object:Gem::Version
|
226
219
|
version: '0'
|
227
220
|
requirements: []
|
228
221
|
rubyforge_project: dust-deploy
|
229
|
-
rubygems_version:
|
222
|
+
rubygems_version: 2.0.0
|
230
223
|
signing_key:
|
231
|
-
specification_version:
|
224
|
+
specification_version: 4
|
232
225
|
summary: small server deployment tool for complex environments
|
233
226
|
test_files: []
|