vagabund 0.0.20
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 +32 -0
- data/Gemfile +13 -0
- data/README.md +301 -0
- data/Rakefile +1 -0
- data/Vagrantfile +50 -0
- data/lib/monkey_patches.rb +16 -0
- data/lib/vagabund/boxer/command.rb +202 -0
- data/lib/vagabund/boxer.rb +4 -0
- data/lib/vagabund/settler/config.rb +49 -0
- data/lib/vagabund/settler/errors.rb +48 -0
- data/lib/vagabund/settler/packages/base.rb +215 -0
- data/lib/vagabund/settler/packages/config.rb +39 -0
- data/lib/vagabund/settler/packages/package_config.rb +118 -0
- data/lib/vagabund/settler/packages.rb +101 -0
- data/lib/vagabund/settler/projects/base.rb +120 -0
- data/lib/vagabund/settler/projects/config.rb +51 -0
- data/lib/vagabund/settler/projects/project_config.rb +123 -0
- data/lib/vagabund/settler/projects/rails.rb +8 -0
- data/lib/vagabund/settler/projects/ruby.rb +38 -0
- data/lib/vagabund/settler/projects.rb +19 -0
- data/lib/vagabund/settler/provisioner.rb +34 -0
- data/lib/vagabund/settler/sources/git.rb +59 -0
- data/lib/vagabund/settler/sources/local.rb +28 -0
- data/lib/vagabund/settler/sources/url.rb +37 -0
- data/lib/vagabund/settler/sources.rb +10 -0
- data/lib/vagabund/settler.rb +4 -0
- data/lib/vagabund/squatter/config.rb +36 -0
- data/lib/vagabund/squatter/provisioner.rb +199 -0
- data/lib/vagabund/squatter/user.rb +56 -0
- data/lib/vagabund/squatter.rb +4 -0
- data/lib/vagabund/version.rb +3 -0
- data/lib/vagabund.rb +45 -0
- data/templates/locales/en.yml +15 -0
- data/vagabund.gemspec +24 -0
- metadata +121 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Settler
|
3
|
+
module Projects
|
4
|
+
class ProjectConfig
|
5
|
+
attr_reader :config, :source
|
6
|
+
|
7
|
+
# Bit of metaprogramming to define methods like builder, installer,
|
8
|
+
# before_build, after_install, etc.
|
9
|
+
%w(project bundler puller).each do |action|
|
10
|
+
%w(before after).each do |hook|
|
11
|
+
hook_action = (action == 'bundler') ? "#{hook}_bundle" : "#{hook}_#{action.gsub(/[eo]r$/, '')}"
|
12
|
+
|
13
|
+
# Defines before/after 'hook' methods for each action: before_build,
|
14
|
+
# before_pull, after_install, etc.
|
15
|
+
define_method hook_action.to_sym do |*args, &block|
|
16
|
+
if args.first.is_a?(String)
|
17
|
+
command = args.shift
|
18
|
+
opts = args.extract_options!
|
19
|
+
|
20
|
+
cmd_proc = Proc.new do |project, machine, channel|
|
21
|
+
cmd = "cd #{project.project_path}; #{command}"
|
22
|
+
execute cmd, {verbose: true}.merge(opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
|
26
|
+
config.send(hook_action.to_sym) << cmd_proc
|
27
|
+
end
|
28
|
+
|
29
|
+
if !args.empty? && (args.first.nil? || args.first.is_a?(Proc))
|
30
|
+
config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
|
31
|
+
config.send(hook_action.to_sym) << args.shift
|
32
|
+
end
|
33
|
+
|
34
|
+
if !block.nil? # block_given? doesn't work here
|
35
|
+
config.send "#{hook_action}=".to_sym, [] if config.send(hook_action.to_sym).nil?
|
36
|
+
config.send(hook_action.to_sym) << block
|
37
|
+
end
|
38
|
+
|
39
|
+
config.send "#{hook_action}".to_sym
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if action == 'project'
|
44
|
+
alias_method :before, :before_project
|
45
|
+
alias_method :after, :after_project
|
46
|
+
next
|
47
|
+
end
|
48
|
+
|
49
|
+
# Defines custom action methods to override the built-in puller,
|
50
|
+
# extractor, builder, installer and cleaner.
|
51
|
+
define_method action.to_sym do |*args, &block|
|
52
|
+
if args.first.is_a?(String)
|
53
|
+
command = args.shift
|
54
|
+
opts = args.extract_options!
|
55
|
+
|
56
|
+
cmd_proc = Proc.new do |project, machine, channel|
|
57
|
+
cmd = "cd #{project.project_path}; #{command}"
|
58
|
+
execute cmd, {verbose: true}.merge(opts)
|
59
|
+
end
|
60
|
+
|
61
|
+
config.send "#{action}=".to_sym, cmd_proc
|
62
|
+
end
|
63
|
+
|
64
|
+
config.send "#{action}=".to_sym, args.shift if !args.empty? && (args.first.nil? || args.first.is_a?(Proc))
|
65
|
+
config.send "#{action}=".to_sym, block if !block.nil? # block_given? doesn't work here
|
66
|
+
|
67
|
+
config.send action.to_sym
|
68
|
+
end
|
69
|
+
alias_method "#{action}=".to_sym, action.to_sym
|
70
|
+
alias_method "#{(action == 'bundle') ? 'bundle' : action.gsub(/[eo]r$/, '')}_with".to_sym, action.to_sym
|
71
|
+
end
|
72
|
+
|
73
|
+
def projects_path
|
74
|
+
config.projects_path ||= '/vagrant'
|
75
|
+
end
|
76
|
+
|
77
|
+
def projects_path=(path)
|
78
|
+
config.projects_path = path
|
79
|
+
end
|
80
|
+
|
81
|
+
def project_path
|
82
|
+
config.project_path ||= File.join(config.projects_path, name)
|
83
|
+
end
|
84
|
+
alias_method :path, :project_path
|
85
|
+
|
86
|
+
def project_path=(path)
|
87
|
+
config.project_path = path
|
88
|
+
end
|
89
|
+
alias_method :path=, :project_path=
|
90
|
+
|
91
|
+
def configure(&block)
|
92
|
+
instance_eval &block if block_given?
|
93
|
+
end
|
94
|
+
|
95
|
+
def method_missing(meth, *args, &block)
|
96
|
+
config.send meth, *args, &block
|
97
|
+
end
|
98
|
+
|
99
|
+
def respond_to_missing?(meth, include_private=false)
|
100
|
+
config.respond_to? meth, include_private
|
101
|
+
end
|
102
|
+
|
103
|
+
protected
|
104
|
+
|
105
|
+
def initialize(*args, &block)
|
106
|
+
@config = OpenStruct.new(args.extract_options!)
|
107
|
+
|
108
|
+
configure &block if block_given?
|
109
|
+
|
110
|
+
if config.respond_to?(:git)
|
111
|
+
@source = Sources::Git.new(config.git)
|
112
|
+
elsif config.respond_to?(:url)
|
113
|
+
@source = Sources::Url.new(config.url)
|
114
|
+
elsif config.respond_to?(:local)
|
115
|
+
@source = Sources::Local.new(config.local)
|
116
|
+
#elsif config.respond_to?(:scp)
|
117
|
+
# remote scp
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Settler
|
3
|
+
module Projects
|
4
|
+
class Ruby < Base
|
5
|
+
|
6
|
+
def provision(machine)
|
7
|
+
exec_before :project, machine
|
8
|
+
pull machine
|
9
|
+
bundle machine
|
10
|
+
exec_after :project, machine
|
11
|
+
end
|
12
|
+
|
13
|
+
def bundle(machine)
|
14
|
+
exec_before :bundle, machine
|
15
|
+
machine.ui.detail "Bundling #{self.class.name.split('::').last.downcase} project #{name}..."
|
16
|
+
if config.bundler.nil?
|
17
|
+
machine.communicate.execute "cd #{config.project_path}; bundle install" do |type,data|
|
18
|
+
color = type == :stderr ? :red : :green
|
19
|
+
options = {
|
20
|
+
color: color,
|
21
|
+
new_line: false,
|
22
|
+
prefix: false
|
23
|
+
}
|
24
|
+
|
25
|
+
machine.ui.detail(data, options)
|
26
|
+
end
|
27
|
+
else
|
28
|
+
action_exec config.bundler, machine
|
29
|
+
end
|
30
|
+
exec_after :bundle, machine
|
31
|
+
rescue StandardError => e
|
32
|
+
raise Settler::Errors::ProjectError, e
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
require_relative 'projects/base'
|
3
|
+
require_relative 'projects/ruby'
|
4
|
+
require_relative 'projects/rails'
|
5
|
+
|
6
|
+
module Vagabund
|
7
|
+
module Settler
|
8
|
+
module Projects
|
9
|
+
end
|
10
|
+
|
11
|
+
class Project < Projects::Base
|
12
|
+
def self.new(*args, &block)
|
13
|
+
klass = (args.first.is_a?(Symbol) ? args.shift : :base).to_s.capitalize
|
14
|
+
eval("Projects::#{klass}.new *args, &block")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative 'packages'
|
2
|
+
require_relative 'projects'
|
3
|
+
require_relative 'sources'
|
4
|
+
|
5
|
+
module Vagabund
|
6
|
+
module Settler
|
7
|
+
class Provisioner < Vagrant.plugin(2, :provisioner)
|
8
|
+
|
9
|
+
def provision
|
10
|
+
config.packages.each do |package|
|
11
|
+
begin
|
12
|
+
machine.ui.info "Provisioning package #{package.name}-#{package.version}..."
|
13
|
+
package.provision @machine
|
14
|
+
rescue Vagrant::Errors::VagrantError => e
|
15
|
+
machine.ui.error "Failed to provision package #{package.name}-#{package.version}!"
|
16
|
+
machine.ui.error e.message(false), prefix: false
|
17
|
+
machine.ui.detail "#{e.message} in #{[e.backtrace[0..5], '...'].join($/)}", prefix: false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
config.projects.each do |project|
|
22
|
+
begin
|
23
|
+
machine.ui.info "Provisioning project #{project.name}"
|
24
|
+
project.provision @machine
|
25
|
+
rescue Vagrant::Errors::VagrantError => e
|
26
|
+
machine.ui.error "Failed to provision project #{project.name}!"
|
27
|
+
machine.ui.detail "#{e.message} in #{[e.backtrace[0..5], '...'].join($/)}", prefix: false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Settler
|
3
|
+
module Sources
|
4
|
+
class Git
|
5
|
+
attr_reader :origin
|
6
|
+
|
7
|
+
def clone(machine, target_path)
|
8
|
+
machine.ui.detail "Cloning #{origin} into #{target_path}..."
|
9
|
+
unless machine.communicate.test "[ -d #{File.dirname(target_path)} ]"
|
10
|
+
machine.communicate.sudo "mkdir -p #{File.dirname(target_path)}"
|
11
|
+
machine.communicate.sudo "chown -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
12
|
+
machine.communicate.sudo "chgrp -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
13
|
+
end
|
14
|
+
machine.communicate.execute "git clone #{origin} #{target_path}" do |type,data|
|
15
|
+
color = type == :stderr ? :red : :green
|
16
|
+
options = {
|
17
|
+
color: color,
|
18
|
+
new_line: false,
|
19
|
+
prefix: false
|
20
|
+
}
|
21
|
+
|
22
|
+
machine.ui.detail(data, options)
|
23
|
+
end
|
24
|
+
target_path
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(machine, target_path)
|
28
|
+
machine.ui.detail "Updating #{target_path} from #{origin}..."
|
29
|
+
machine.communicate.execute "cd #{target_path}; git pull" do |type,data|
|
30
|
+
color = type == :stderr ? :red : :green
|
31
|
+
options = {
|
32
|
+
color: color,
|
33
|
+
new_line: false,
|
34
|
+
prefix: false
|
35
|
+
}
|
36
|
+
|
37
|
+
machine.ui.detail(data, options)
|
38
|
+
end
|
39
|
+
target_path
|
40
|
+
end
|
41
|
+
|
42
|
+
def pull(machine, target_path)
|
43
|
+
if machine.communicate.test "[ -d #{target_path} ]"
|
44
|
+
update machine, target_path
|
45
|
+
else
|
46
|
+
clone machine, target_path
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def initialize(origin)
|
53
|
+
@origin = origin
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Settler
|
3
|
+
module Sources
|
4
|
+
class Local
|
5
|
+
attr_reader :origin
|
6
|
+
|
7
|
+
def upload(machine, target_path)
|
8
|
+
machine.ui.detail "Uploading #{origin} to #{target_path}..."
|
9
|
+
unless machine.communicate.test "[ -d #{File.dirname(target_path)} ]"
|
10
|
+
machine.communicate.sudo "mkdir -p #{File.dirname(target_path)}"
|
11
|
+
machine.communicate.sudo "chown -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
12
|
+
machine.communicate.sudo "chgrp -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
13
|
+
end
|
14
|
+
machine.communicate.upload origin, target_path
|
15
|
+
target_path
|
16
|
+
end
|
17
|
+
alias_method :pull, :upload
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def initialize(origin)
|
22
|
+
@origin = File.expand_path(origin)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Settler
|
3
|
+
module Sources
|
4
|
+
class Url
|
5
|
+
attr_reader :origin
|
6
|
+
|
7
|
+
def download(machine, target_path)
|
8
|
+
machine.ui.detail "Downloading #{origin} to #{target_path}..."
|
9
|
+
unless machine.communicate.test "[ -d #{File.dirname(target_path)} ]"
|
10
|
+
machine.communicate.sudo "mkdir -p #{File.dirname(target_path)}"
|
11
|
+
machine.communicate.sudo "chown -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
12
|
+
machine.communicate.sudo "chgrp -R #{machine.ssh_info[:username]} #{File.dirname(target_path)}"
|
13
|
+
end
|
14
|
+
machine.communicate.execute "curl -L -o #{target_path} #{origin}" do |type,data|
|
15
|
+
color = type == :stderr ? :red : :green
|
16
|
+
options = {
|
17
|
+
color: color,
|
18
|
+
new_line: false,
|
19
|
+
prefix: false
|
20
|
+
}
|
21
|
+
|
22
|
+
machine.ui.detail(data, options)
|
23
|
+
end
|
24
|
+
target_path
|
25
|
+
end
|
26
|
+
alias_method :pull, :download
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def initialize(origin)
|
31
|
+
@origin = origin
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require_relative 'user'
|
2
|
+
|
3
|
+
module Vagabund
|
4
|
+
module Squatter
|
5
|
+
class Config < Vagrant.plugin(2, :config)
|
6
|
+
attr_accessor :guest_home, :host_home
|
7
|
+
|
8
|
+
DEFAULT_FILES = ['.vimrc', '.viminfo', '.gitconfig', '.ssh/known_hosts']
|
9
|
+
|
10
|
+
def files
|
11
|
+
@files ||= DEFAULT_FILES
|
12
|
+
end
|
13
|
+
|
14
|
+
def files=(file_arr)
|
15
|
+
@files = file_arr
|
16
|
+
end
|
17
|
+
|
18
|
+
def file=(filename)
|
19
|
+
files << filename
|
20
|
+
end
|
21
|
+
|
22
|
+
def host_home
|
23
|
+
@host_home ||= File.expand_path('~')
|
24
|
+
end
|
25
|
+
|
26
|
+
def guest_home
|
27
|
+
@guest_home ||= '~'
|
28
|
+
end
|
29
|
+
|
30
|
+
def user
|
31
|
+
@user ||= User.new
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Squatter
|
3
|
+
class Provisioner < Vagrant.plugin(2, :provisioner)
|
4
|
+
|
5
|
+
def configure(root_config)
|
6
|
+
@root_config = root_config
|
7
|
+
end
|
8
|
+
|
9
|
+
def provision
|
10
|
+
create_user
|
11
|
+
upload_files
|
12
|
+
end
|
13
|
+
|
14
|
+
def cleanup
|
15
|
+
# remove the user?
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_user
|
20
|
+
if config.user.create?
|
21
|
+
if @machine.communicate.test "[ `getent passwd | grep -c '^#{config.user.username}:'` == 0 ]"
|
22
|
+
@machine.ui.info "Creating user #{config.user.username}..."
|
23
|
+
@machine.communicate.sudo config.user.to_s
|
24
|
+
|
25
|
+
# Copy over the authorized_keys and known_hosts files being used currently for compatibility
|
26
|
+
if !@machine.communicate.test "[ -d #{config.user.home}/.ssh ]"
|
27
|
+
ssh_user_home = ''
|
28
|
+
@machine.communicate.execute "echo $HOME" do |type,data|
|
29
|
+
ssh_user_home = data.chomp if type == :stdout
|
30
|
+
end
|
31
|
+
|
32
|
+
@machine.communicate.sudo "mkdir -p #{config.user.home}/.ssh"
|
33
|
+
|
34
|
+
if config.user.pubkeys.nil?
|
35
|
+
# Copy the authorized_keys file if it doesn't exist and no public keys were provided
|
36
|
+
if !@machine.communicate.test("[ -f #{config.user.home}/.ssh/authorized_keys ]") && @machine.communicate.test("[ -f #{ssh_user_home}/.ssh/authorized_keys ]")
|
37
|
+
@machine.communicate.sudo "cp #{ssh_user_home}/.ssh/authorized_keys #{config.user.home}/.ssh/authorized_keys"
|
38
|
+
end
|
39
|
+
else
|
40
|
+
# Add the public key(s) provided
|
41
|
+
@machine.communicate.sudo "echo \"#{config.user.pubkeys}\" > #{config.user.home}/.ssh/authorized_keys"
|
42
|
+
end
|
43
|
+
|
44
|
+
unless config.user.ssh_conf_str.nil?
|
45
|
+
@machine.communicate.sudo "echo \"#{config.user.ssh_conf_str}\" > #{config.user.home}/.ssh/config", verbose: true
|
46
|
+
end
|
47
|
+
|
48
|
+
if !@machine.communicate.test("[ -f #{config.user.home}/.ssh/known_hosts ]") && @machine.communicate.test("[ -f #{ssh_user_home}/.ssh/known_hosts ]")
|
49
|
+
@machine.communicate.sudo "cp #{ssh_user_home}/.ssh/known_hosts #{config.user.home}/.ssh/known_hosts"
|
50
|
+
end
|
51
|
+
|
52
|
+
@machine.communicate.sudo "chown -R #{config.user.username} #{config.user.home}/.ssh"
|
53
|
+
@machine.communicate.sudo "chgrp -R #{config.user.username} #{config.user.home}/.ssh"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Add to sudoers
|
57
|
+
if config.user.sudo
|
58
|
+
@machine.communicate.sudo "echo \"#{config.user.username} ALL=(ALL) NOPASSWD:ALL\" > /etc/sudoers.d/#{config.user.username}"
|
59
|
+
@machine.communicate.sudo "chmod 0440 /etc/sudoers.d/#{config.user.username}"
|
60
|
+
end
|
61
|
+
else
|
62
|
+
@machine.ui.warn "User #{config.user.username} already exists"
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
rescue
|
67
|
+
@machine.ui.error "Failed to create user #{config.user.username}"
|
68
|
+
@machine.communicate.sudo "userdel -r #{config.user.username}" rescue nil
|
69
|
+
@machine.communicate.sudo "rm -rf /etc/sudoers.d/#{config.user.username}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def upload_files
|
73
|
+
config.files.each do |file|
|
74
|
+
sync *expanded_paths(file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def guest_home
|
81
|
+
gh_path = config.guest_home
|
82
|
+
@machine.communicate.execute "cd #{gh_path}; pwd" do |type, data|
|
83
|
+
gh_path = data.chomp if type == :stdout
|
84
|
+
end
|
85
|
+
gh_path
|
86
|
+
end
|
87
|
+
|
88
|
+
def host_home
|
89
|
+
File.expand_path(config.host_home)
|
90
|
+
end
|
91
|
+
|
92
|
+
def expanded_paths(file)
|
93
|
+
# separate source and destination, both expanded relative to home if not absolute
|
94
|
+
if file.is_a?(Array)
|
95
|
+
from = expanded_paths(file[0])[0]
|
96
|
+
to = expanded_paths(file[1])[1]
|
97
|
+
|
98
|
+
# proc should return [from, to]
|
99
|
+
elsif file.is_a?(Proc)
|
100
|
+
from, to = expanded_paths(clean_room.instance_exec(@machine, @machine.communicate, &file))
|
101
|
+
|
102
|
+
# remote source file
|
103
|
+
elsif file.match(/^(http[s]?|s3):\/\//i)
|
104
|
+
from = file
|
105
|
+
to = File.join(guest_home, File.basename(file))
|
106
|
+
|
107
|
+
# already absolute
|
108
|
+
elsif Pathname.new(file).absolute?
|
109
|
+
from = to = file
|
110
|
+
|
111
|
+
# expand path relative to home
|
112
|
+
else
|
113
|
+
from = File.join(host_home, file)
|
114
|
+
to = File.join(guest_home, file)
|
115
|
+
end
|
116
|
+
|
117
|
+
[from, to]
|
118
|
+
end
|
119
|
+
|
120
|
+
def sync(from, to)
|
121
|
+
if from.match(/^(http[s]?|s3):\/\//i)
|
122
|
+
@machine.ui.detail "Downloading #{from}..."
|
123
|
+
Dir.mktmpdir do |dir|
|
124
|
+
from_file = File.join(dir, File.basename(from))
|
125
|
+
|
126
|
+
if from.match(/^http[s]?:\/\//i)
|
127
|
+
`curl -L -o #{from_file} #{from} 2>&1`
|
128
|
+
elsif from.match(/^s3:\/\//i)
|
129
|
+
`aws s3 cp #{from} #{from_file}`
|
130
|
+
end
|
131
|
+
|
132
|
+
upload from_file, to
|
133
|
+
end
|
134
|
+
else
|
135
|
+
unless File.exists?(from)
|
136
|
+
@machine.ui.warn "Local file #{from} does not exist. Skipping."
|
137
|
+
return
|
138
|
+
end
|
139
|
+
upload from, to
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def upload(from, to)
|
144
|
+
begin
|
145
|
+
@machine.ui.detail "Uploading #{from} to #{to}..."
|
146
|
+
@machine.communicate.execute "mkdir -p #{File.dirname(to)}" # TODO this should be guest OS agnostic
|
147
|
+
@machine.communicate.upload from, to
|
148
|
+
rescue Vagrant::Errors::VagrantError => e
|
149
|
+
@machine.ui.error "Failed to upload config file #{from} to #{to}"
|
150
|
+
raise e
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def clean_room
|
155
|
+
dsl = Struct.new(:machine).new(@machine)
|
156
|
+
dsl.class.instance_eval do
|
157
|
+
[:ask, :detail, :error, :info, :output, :warn].each do |cmd|
|
158
|
+
define_method cmd do |*args, &block|
|
159
|
+
machine.ui.send cmd, *args, &block
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
[:execute, :sudo, :test].each do |cmd|
|
164
|
+
define_method cmd do |*args, &block|
|
165
|
+
opts = {verbose: false}.merge(args.extract_options!)
|
166
|
+
if opts[:verbose] == true
|
167
|
+
machine.communicate.send cmd, *args, opts do |type,data|
|
168
|
+
color = type == :stderr ? :red : :green
|
169
|
+
options = {
|
170
|
+
color: color,
|
171
|
+
new_line: false,
|
172
|
+
prefix: false
|
173
|
+
}
|
174
|
+
|
175
|
+
detail(data, options)
|
176
|
+
block.call(type, data) unless block.nil?
|
177
|
+
end
|
178
|
+
else
|
179
|
+
machine.communicate.send cmd, *args, opts, &block
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
define_method :capture do |*args, &block|
|
185
|
+
output = ''
|
186
|
+
machine.communicate.execute *args do |type,data|
|
187
|
+
output += data if type == :stdout
|
188
|
+
block.call(type, data) unless block.nil?
|
189
|
+
end
|
190
|
+
output
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
dsl
|
195
|
+
end
|
196
|
+
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Vagabund
|
2
|
+
module Squatter
|
3
|
+
class User
|
4
|
+
attr_accessor :username, :password, :home, :shell, :group, :groups, :sudo, :public_key, :ssh_config
|
5
|
+
|
6
|
+
def home
|
7
|
+
@home || "/home/#{username}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def shell
|
11
|
+
@shell ||= "/bin/bash"
|
12
|
+
end
|
13
|
+
|
14
|
+
def pubkeys
|
15
|
+
unless @public_key.nil?
|
16
|
+
[@public_key].flatten.map do |pubkey|
|
17
|
+
begin
|
18
|
+
File.read(File.expand_path(pubkey)).chomp
|
19
|
+
rescue Exception => e
|
20
|
+
pubkey
|
21
|
+
end
|
22
|
+
end.join($/)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def ssh_conf_str
|
27
|
+
unless @ssh_config.nil?
|
28
|
+
begin
|
29
|
+
File.read(File.expand_path(@ssh_config)).chomp
|
30
|
+
rescue Exception => e
|
31
|
+
@ssh_config
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
cmd_str = "useradd -m -s #{shell}"
|
38
|
+
cmd_str += " -d #{home}"
|
39
|
+
cmd_str += " -g #{group}" unless group.nil?
|
40
|
+
cmd_str += " -G #{[groups].flatten.join(',')}" unless groups.nil?
|
41
|
+
cmd_str += " #{username}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def create?
|
45
|
+
!username.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@sudo = true
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|