prepper 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +4 -1
- data/lib/prepper/tools/apt.rb +16 -18
- data/lib/prepper/tools/file.rb +103 -49
- data/lib/prepper/tools/rbenv.rb +19 -18
- data/lib/prepper/tools/text.rb +13 -11
- data/lib/prepper/tools/users.rb +19 -14
- data/lib/prepper/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8eb4e48bf36f79d83d5da672215e3ad1f4994eaa5a652532be310d5600c2597a
|
4
|
+
data.tar.gz: 7bfa00815d7aded4c7933e84e36a87fdc9388fa9f9c5631bec0e2d57379a2245
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69f96c1720596ecb24bc4ce289b29a16821b6c9f0227f6b2cd34778b5db5122bd1772eff17c4aca39867d417381b2e931533441d3213bf9a4660816cf03c4930
|
7
|
+
data.tar.gz: 909b0621f3c16c31717b4a4e968f6b5e60a4fc9f3f54836cc65c5a33879042435a3bccad79e82351f3e9d466f5b3d7d7482f458280b1bf4fc83ee428f38d5c21
|
data/CHANGELOG.md
ADDED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -17,7 +17,8 @@ upload files to the server, etc.
|
|
17
17
|
|
18
18
|
A simple example:
|
19
19
|
|
20
|
-
```
|
20
|
+
```ruby
|
21
|
+
|
21
22
|
server_host "YOUR_SERVER_IP"
|
22
23
|
server_port 22
|
23
24
|
server_user "root"
|
@@ -47,6 +48,8 @@ end
|
|
47
48
|
|
48
49
|
You can see a full example in [examples/config.rb](examples/config.rb). You would run that file with `bundle exec prepper config.rb` to provision the server.
|
49
50
|
|
51
|
+
The API documentation can be found on rubydoc: [https://rubydoc.info/github/gregmolnar/prepper](https://rubydoc.info/github/gregmolnar/prepper).
|
52
|
+
|
50
53
|
## Development
|
51
54
|
|
52
55
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/prepper/tools/apt.rb
CHANGED
@@ -1,27 +1,25 @@
|
|
1
1
|
module Prepper
|
2
2
|
module Tools
|
3
|
+
# Helper methods to interact with Apt
|
3
4
|
module Apt
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def apt_update
|
9
|
-
@commands << Command.new("apt update", sudo: true)
|
10
|
-
end
|
11
|
-
|
12
|
-
# Installs packages
|
13
|
-
# @param packages [Array] array of package names
|
14
|
-
def apt_install(packages)
|
15
|
-
packages.each do |package|
|
16
|
-
@commands << Command.new("apt install --force-yes -qyu #{package}", sudo: true, verify: has_apt_package?(package))
|
17
|
-
end
|
18
|
-
end
|
5
|
+
# Updates apt repositories
|
6
|
+
def apt_update
|
7
|
+
@commands << Command.new("apt update", sudo: true)
|
8
|
+
end
|
19
9
|
|
20
|
-
|
21
|
-
|
22
|
-
|
10
|
+
# Installs packages
|
11
|
+
# @param packages [Array] array of package names
|
12
|
+
def apt_install(packages)
|
13
|
+
packages.each do |package|
|
14
|
+
@commands << Command.new("apt install --force-yes -qyu #{package}", sudo: true, verify: has_apt_package?(package))
|
23
15
|
end
|
24
16
|
end
|
17
|
+
|
18
|
+
# Verifier command to checks if an apt package is installed
|
19
|
+
# @param package [String] name of the package
|
20
|
+
def has_apt_package?(package)
|
21
|
+
Command.new("dpkg --status #{package} | grep 'ok installed'", sudo: true)
|
22
|
+
end
|
25
23
|
end
|
26
24
|
end
|
27
25
|
end
|
data/lib/prepper/tools/file.rb
CHANGED
@@ -2,67 +2,121 @@ require 'erb'
|
|
2
2
|
require 'digest/md5'
|
3
3
|
module Prepper
|
4
4
|
module Tools
|
5
|
+
# Helper methods for file and directory management
|
5
6
|
module File
|
6
|
-
def self.included(base)
|
7
|
-
base.class_eval do
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
# Changes ownership of a path
|
9
|
+
# @param path [String] the path which we want to change the ownership of
|
10
|
+
# @param owner [String] name of the owner, ie: 'root:root'
|
11
|
+
# @param flags [String] flags to pass to chown, ie: '-R' to do it recursively
|
12
|
+
def chown(path, owner, flags = "")
|
13
|
+
@commands << Command.new("chown #{flags} #{owner} #{path}", sudo: true)
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
# Create a directory unless it already exists
|
17
|
+
# @param path [String] path of the directory
|
18
|
+
# @param [Hash] opts options hash
|
19
|
+
# @option opts [String] :owner Owner of the directory, ie: 'root:root'
|
20
|
+
# @option opts [String] :mode mode bits, ie: '0777'
|
21
|
+
def directory(path, opts = {})
|
22
|
+
@commands << Command.new("mkdir -p #{path}", opts.merge(sudo: true, verifier: has_directory?(path)))
|
23
|
+
@commands << Command.new("chown #{opts[:owner]} #{path}", sudo: true) if opts[:owner]
|
24
|
+
@commands << Command.new("chmod #{opts[:mode]} #{path}", sudo: true) if opts[:mode]
|
25
|
+
end
|
18
26
|
|
19
|
-
|
20
|
-
|
21
|
-
|
27
|
+
# returns a verifier command to test if a directory exists
|
28
|
+
# @param path [String] path to test
|
29
|
+
def has_directory?(path)
|
30
|
+
Command.new("test -d #{path}", sudo: true)
|
31
|
+
end
|
22
32
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
# Create a file unless it already exists. The contents can be set to a
|
34
|
+
# string or a template can be rendered with the provided locals
|
35
|
+
# @param path [String] path of the file
|
36
|
+
# @param [Hash] opts options hash
|
37
|
+
# @option opts [String] :content string content of the file
|
38
|
+
# @option opts [String] :template name of the template for the file
|
39
|
+
# @option opts [String] :locals hash of variables to pass to the template
|
40
|
+
# @option opts [String] :verify_content set to true to verify the file
|
41
|
+
# content is the same in case the file already exists
|
42
|
+
# @option opts [String] :owner Owner of the directory, ie: 'root:root'
|
43
|
+
# @option opts [String] :mode mode bits, ie: '0777'
|
44
|
+
def file(path, opts = {})
|
45
|
+
opts[:locals] ||= {}
|
46
|
+
opts[:verify_content] ||= true
|
47
|
+
content = opts[:content] || render_template(opts[:template], opts[:locals])
|
48
|
+
verifier = if opts[:verify_content]
|
49
|
+
matches_content?(path, content)
|
50
|
+
else
|
51
|
+
has_file?(path)
|
52
|
+
end
|
53
|
+
io = StringIO.new(content)
|
54
|
+
@commands << Command.new("put!", {params: [io, path, {owner: opts[:owner], mode: opts[:mode]}], verifier: verifier})
|
55
|
+
end
|
35
56
|
|
36
|
-
|
37
|
-
|
38
|
-
|
57
|
+
# returns a verifier command to test if a file exists
|
58
|
+
# @param path [String] path to test
|
59
|
+
def has_file?(path)
|
60
|
+
Command.new("test -f #{path}", sudo: true)
|
61
|
+
end
|
39
62
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
63
|
+
# returns a verifier command to test if has a matching content
|
64
|
+
# @param path [String] path to test
|
65
|
+
# @param content [String] expected content
|
66
|
+
def matches_content?(path, content)
|
67
|
+
md5 = Digest::MD5.hexdigest(content)
|
68
|
+
Command.new("md5sum #{path} | cut -f1 -d' '`\" = \"#{md5}\"", sudo: true, verifier: has_file?(path))
|
69
|
+
end
|
44
70
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
71
|
+
# creates a symlink
|
72
|
+
# @param link [String] link
|
73
|
+
# @param target [String] target
|
74
|
+
# @param [Hash] opts options hash
|
75
|
+
def symlink(link, target, opts = {})
|
76
|
+
opts.merge!(
|
77
|
+
sudo: true,
|
78
|
+
verifier: has_symlink?(link)
|
79
|
+
)
|
80
|
+
@commands << Command.new("ln -s #{target} #{link}", opts)
|
81
|
+
end
|
82
|
+
|
83
|
+
# returns a verifier command to test if as a matching content
|
84
|
+
# @param path [String] path to test
|
85
|
+
# @param content [String] expected content
|
86
|
+
def matches_content?(path, content)
|
87
|
+
md5 = Digest::MD5.hexdigest(content)
|
88
|
+
Command.new("md5sum #{path} | cut -f1 -d' '`\" = \"#{md5}\"", sudo: true, verifier: has_file?(path))
|
89
|
+
end
|
52
90
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
91
|
+
# creates a symlink
|
92
|
+
# @param link [String] link
|
93
|
+
# @param target [String] target
|
94
|
+
# @param [Hash] opts options hash
|
95
|
+
def symlink(link, target, opts = {})
|
96
|
+
opts.merge!(
|
97
|
+
sudo: true,
|
98
|
+
verifier: has_symlink?(link)
|
99
|
+
)
|
100
|
+
@commands << Command.new("ln -s #{target} #{link}", opts)
|
101
|
+
end
|
60
102
|
|
61
|
-
|
62
|
-
|
63
|
-
|
103
|
+
# returns a verifier command to test if symlink exists
|
104
|
+
# @param path [String] path to test
|
105
|
+
# @param file [String] optionally check if it points to the correct file
|
106
|
+
def has_symlink?(link, file = nil)
|
107
|
+
if file
|
108
|
+
Command.new("'#{file}' = `readlink #{link}`")
|
109
|
+
else
|
110
|
+
Command.new("test -L #{link}", sudo: true)
|
64
111
|
end
|
65
112
|
end
|
113
|
+
|
114
|
+
# render an ERB template
|
115
|
+
# @param template [String] name of the template
|
116
|
+
# @param locals [Hash] hash of variables to pass to the template
|
117
|
+
def render_template(template, locals)
|
118
|
+
ERB.new(::File.read("./templates/#{template}")).result_with_hash(locals)
|
119
|
+
end
|
66
120
|
end
|
67
121
|
end
|
68
122
|
end
|
data/lib/prepper/tools/rbenv.rb
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
module Prepper
|
2
2
|
module Tools
|
3
|
+
# Helper methods for rbenv
|
3
4
|
module Rbenv
|
4
|
-
|
5
|
-
|
5
|
+
# install rbenv for a given user
|
6
|
+
# @param user [String] name of the user to install rbenv for
|
7
|
+
def install_rbenv(user)
|
8
|
+
apt_install %w{libssl-dev zlib1g zlib1g-dev libreadline-dev}
|
9
|
+
@commands << Command.new("sudo -u #{user} -i git clone https://github.com/sstephenson/rbenv.git /home/#{user}/.rbenv", verifier: has_directory?("/home/#{user}/.rbenv"))
|
10
|
+
@commands << Command.new("sudo -u #{user} -i git clone https://github.com/sstephenson/ruby-build.git /home/#{user}/.rbenv/plugins/ruby-build", verifier: has_directory?("/home/#{user}/.rbenv/plugins/ruby-build"))
|
6
11
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
append_text 'export PATH="$HOME/.rbenv/bin:$PATH"', "/home/#{user}/.profile"
|
13
|
-
append_text 'eval "$(rbenv init -)"', "/home/#{user}/.profile"
|
14
|
-
chown "/home/#{user}/.profile", 'deploy:deploy'
|
15
|
-
end
|
12
|
+
append_text 'export PATH="$HOME/.rbenv/bin:$PATH"', "/home/#{user}/.profile"
|
13
|
+
append_text 'eval "$(rbenv init -)"', "/home/#{user}/.profile"
|
14
|
+
chown "/home/#{user}/.profile", 'deploy:deploy'
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# install a given ruby version for a given user
|
18
|
+
# @param user [String] name of the user
|
19
|
+
# @param version [String] ruby version
|
20
|
+
def install_ruby(user, version)
|
21
|
+
@commands << Command.new("sudo -u #{user} -i RUBY_CONFIGURE_OPTS='#{opts}' rbenv install #{version}", verifier: has_directory?("/home/#{user}/.rbenv/versions/#{version}"))
|
19
22
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
end
|
23
|
+
@commands << Command.new("sudo -u #{user} -i rbenv rehash")
|
24
|
+
@commands << Command.new("sudo -u #{user} -i rbenv global #{version}")
|
25
|
+
@commands << Command.new("sudo -u #{user} -i rbenv rehash")
|
25
26
|
end
|
26
27
|
end
|
27
28
|
end
|
data/lib/prepper/tools/text.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
module Prepper
|
2
2
|
module Tools
|
3
|
+
# text related helpers
|
3
4
|
module Text
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# append text to a file
|
6
|
+
# @param text [String] text to append
|
7
|
+
# @param path [String]
|
8
|
+
def append_text(text, path)
|
9
|
+
@commands << Command.new("/bin/echo -e '#{text}' | sudo tee -a #{path}", verifier: has_text?(text, path))
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
# returns a verifier command to test the presence of a string in a file
|
13
|
+
# @param text [String] text
|
14
|
+
# @param path [String] path to file
|
15
|
+
def has_text?(text, path)
|
16
|
+
regex = Regexp.escape(text)
|
17
|
+
Command.new("grep -qPzo '^#{regex}$' #{path} ||", sudo: true)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/prepper/tools/users.rb
CHANGED
@@ -1,22 +1,27 @@
|
|
1
1
|
module Prepper
|
2
2
|
module Tools
|
3
|
+
# user management related helpers
|
3
4
|
module Users
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# add a user to the host
|
6
|
+
# @param username [String] name of the user
|
7
|
+
# @param [Hash] opts options has
|
8
|
+
# @option opts [String] :flags flags to pass to adduser
|
9
|
+
def add_user(username, opts = {})
|
10
|
+
opts[:flags] << ' --gecos ,,,'
|
11
|
+
@commands << Command.new("adduser #{username} #{opts[:flags]}", sudo: true, verifier: has_user?(username))
|
12
|
+
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
# returns a verifier command to check if a user exists
|
15
|
+
# @param username [String] name of the user
|
16
|
+
# @param [Hash] opts options hash
|
17
|
+
# @option opts [String] :in_group check if the user is in the given group
|
18
|
+
def has_user?(username, opts = {})
|
19
|
+
if opts[:in_group]
|
20
|
+
command = "id -nG #{username} | xargs -n1 echo | grep #{opts[:in_group]}"
|
21
|
+
else
|
22
|
+
command = "id #{username}"
|
19
23
|
end
|
24
|
+
Command.new(command, sudo: true)
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
data/lib/prepper/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prepper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Molnar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: zeitwerk
|
@@ -76,6 +76,7 @@ extra_rdoc_files: []
|
|
76
76
|
files:
|
77
77
|
- ".gitignore"
|
78
78
|
- ".travis.yml"
|
79
|
+
- CHANGELOG.md
|
79
80
|
- CODE_OF_CONDUCT.md
|
80
81
|
- Gemfile
|
81
82
|
- Gemfile.lock
|