vagabund 0.0.20
Sign up to get free protection for your applications and to get access to all the features.
- 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
|