vagabond 0.1.0 → 0.1.2

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.
data/CHANGELOG.md CHANGED
@@ -1,2 +1,13 @@
1
+ ## v0.1.2
2
+ * Added support for centos guests
3
+ * Added new base templates for centos and debian
4
+ * Debugging output support
5
+ * Pretty CLI output
6
+ * Actual help output
7
+ * Improved status output
8
+ * SSH functionality to nodes
9
+ * Improved server functionality
10
+ * Other stuff I probably forgot
11
+
1
12
  ## v0.1.0
2
13
  * Initial release!
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Vagabond
2
2
 
3
- * Issue: VMs are slow. Especially when creating over and over.
4
- * Discovery: Linux provides LXC tools similar to BSD jails
5
- * Helpful: LXCs can provide different distributions
3
+ * Issue: VMs are slow.
4
+ * Discovery: Linux has LXC, which is pretty cool.
5
+ * Helpful: LXCs can run different distributions.
6
6
  * Implementation: Vagabond
7
7
 
8
8
  Awesome
@@ -42,53 +42,116 @@ Hash you return. Heres a simple example:
42
42
 
43
43
  Pretty simple, right?
44
44
 
45
- ## Commands
46
-
47
- ```
48
- # create and provision
49
- $ vagabond up precise
45
+ ### Templates available
50
46
 
51
- # provision existing
52
- $ vagabond provision precise
47
+ Currently builtin templates:
53
48
 
54
- # freeze (pause) node
55
- $ vagabond freeze precise
49
+ * ubuntu_1204
50
+ * ubuntu_1210
51
+ * debian_6
52
+ * debian_7
53
+ * centos_58
54
+ * centos_63
55
+ * centos_64
56
56
 
57
- # thaw (unpause) node
58
- $ vagabond thaw node
59
-
60
- # destroy node
61
- $ vagabond destroy precise
57
+ ## Commands
62
58
 
63
- # status of defined nodes
64
- $ vagabond status [node]
59
+ Lots of commands. What to see them all? Just ask:
65
60
 
66
- # ssh to node
67
- $ vagabond ssh precise
61
+ ```
62
+ $ vagabond --help
63
+ Nodes:
64
+ vagabond create NODE [options]
65
+ vagabond destroy NODE [options]
66
+ vagabond freeze NODE [options]
67
+ vagabond provision NODE [options]
68
+ vagabond rebuild NODE [options]
69
+ vagabond ssh NODE [options]
70
+ vagabond start NODE [options]
71
+ vagabond status NODE [options]
72
+ vagabond thaw NODE [options]
73
+ vagabond up NODE [options]
74
+ Server:
75
+ vagabond server auto_upload [options]
76
+ vagabond server create [options]
77
+ vagabond server destroy [options]
78
+ vagabond server freeze [options]
79
+ vagabond server provision [options]
80
+ vagabond server rebuild [options]
81
+ vagabond server ssh [options]
82
+ vagabond server start [options]
83
+ vagabond server status [options]
84
+ vagabond server stop [options]
85
+ vagabond server thaw [options]
86
+ vagabond server up [options]
87
+ vagabond server upload_cookbooks [options]
88
+ vagabond server upload_databags [options]
89
+ vagabond server upload_environments [options]
90
+ vagabond server upload_roles [options]
91
+ Options:
92
+ --debug
93
+ --disable-auto-provision
94
+ --disable-local-server
95
+ --disable-configure
96
+ --force-configure
97
+ -f, --vagabond-file FILE
98
+ ```
68
99
 
69
100
  ## Local chef server?
70
101
 
71
102
  Yep, that's right. You can let vagabond set you up with a local chef
72
103
  server hanging out in a container, which all your vagabond nodes can
73
- then run against. Isolated building and test? You betcha!
104
+ then run against. Isolated building and testing? You betcha!
105
+
106
+ Server containers are isolated by project. This means you will have an
107
+ erchef instance running in an isolated container for every project the
108
+ local server option is enabled. It's just an important bit of information
109
+ to remember so you can make a mental note to stop or freeze it when not
110
+ in use. Or just let them run. What ever floats your boat.
111
+
112
+ ### Vagabond knife
74
113
 
75
- Server provides a superset of the commands available for regular
76
- vagabond nodes. They are accessed using:
114
+ Since you can have a local chef server running, it can also be helpful
115
+ to be able to actually interact with that server. Vagabond has commands
116
+ for doing bulk uploads of assets, but you can access it too with knife
117
+ to do isolated uploads, or to just do knifey things:
118
+
119
+ ```
120
+ vagabond knife SOME COOL KNIFE COMMAND
121
+ ```
77
122
 
78
- `$ vagabond server COMMAND`
123
+ This will just push the command into the local chef server.
79
124
 
80
125
  ## Important note
81
126
 
82
127
  Until namespaces hit Linux proper, vagabond `sudo`s its way around. You
83
128
  _can_ get around this using the setcap stuff, but it's pretty meh. If you
84
- do go that road, just turn off `sudo` in your Vagabond file by setting
85
- `:sudo => false`.
129
+ do go that road, just turn off `sudo` in your Vagabond file by setting:
130
+
131
+ ```
132
+ :sudo => false
133
+ ```
134
+
135
+ Oh, and if you use `rvm` and would rather be using `rvmsudo` instead of
136
+ boring old `sudo`, you can do that to:
137
+
138
+ ```
139
+ :sudo => 'rvmsudo'
140
+ ```
86
141
 
87
142
  ## Extra note
88
143
 
89
144
  This is still very much in alpha testing phase. So if you find bugs, please
90
145
  report them!
91
146
 
147
+ ## Contributing
148
+
149
+ No hard and fast rules for contributing just preferences. I'm always happy to
150
+ get help making things better!
151
+
152
+ * Base updates and pull requests on the `develop` branch
153
+ * Please don't update core files like `version.rb` or `vagabond.gemspec`
154
+
92
155
  ## Infos
93
156
 
94
157
  * Repository: https://github.com/chrisroberts/vagabond
@@ -2,26 +2,27 @@ module Vagabond
2
2
  module Actions
3
3
  module Create
4
4
  def create
5
- create
5
+ if(lxc.exists?)
6
+ ui.warn "Node already exists: #{name}" unless name == 'server'
7
+ start
8
+ else
9
+ ui.info "#{ui.color('Vagabond:', :bold)} Creating #{ui.color(name, :green)}"
10
+ do_create
11
+ ui.info ui.color(' -> CREATED!', :green)
12
+ end
6
13
  end
7
14
 
8
15
  private
9
16
 
10
- # Lets get this out proper!
11
17
  def do_create
12
- unless(check_existing!)
13
- @ui.info "LXC: Creating #{name}..."
14
- com = "#{sudo}lxc-start-ephemeral -d -o #{config[:template]}"
15
- c = Mixlib::ShellOut.new("#{com} && sleep 3")
16
- c.run_command
17
- e_name = c.stdout.split("\n").last.split(' ').last.strip
18
- @internal_config[:mappings][name] = e_name
19
- @internal_config.save
20
- @lxc = Lxc.new(e_name)
21
- @ui.info "LXC: #{name} has been created!"
22
- else
23
- lxc.start unless lxc.running?
24
- end
18
+ com = "#{sudo}lxc-start-ephemeral -d -o #{config[:template]}"
19
+ debug(com)
20
+ c = Mixlib::ShellOut.new("#{com} && sleep 3", :live_stream => Config[:debug])
21
+ c.run_command
22
+ e_name = c.stdout.split("\n").last.split(' ').last.strip
23
+ @internal_config[:mappings][name] = e_name
24
+ @internal_config.save
25
+ @lxc = Lxc.new(e_name)
25
26
  end
26
27
 
27
28
  end
@@ -2,9 +2,13 @@ module Vagabond
2
2
  module Actions
3
3
  module Destroy
4
4
  def destroy
5
- ui.info "Destroying instance: #{name}..."
6
- do_destroy
7
- ui.info 'Complete!'
5
+ if(lxc.exists?)
6
+ ui.info "#{ui.color('Vagabond:', :bold)} Destroying node: #{ui.color(name, :red)}"
7
+ do_destroy
8
+ ui.info ui.color(' -> DESTROYED', :red)
9
+ else
10
+ ui.error "Node not created: #{name}"
11
+ end
8
12
  end
9
13
 
10
14
  private
@@ -12,18 +16,25 @@ module Vagabond
12
16
  def do_destroy
13
17
  lxc.stop if lxc.running?
14
18
  com = "#{Config[:sudo]}lxc-destroy -n #{lxc.name}"
15
- cmd = Mixlib::ShellOut.new(com)
19
+ debug(com)
20
+ cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
16
21
  cmd.run_command
17
22
  cmd.error!
18
23
  if(cmd.stderr.include?('skipping'))
19
- ui.warn 'Failed to unmount some resource. Doing so manually'
24
+ ui.info ui.color(' -> Failed to unmount some resources. Forcing manually.', :yellow)
20
25
  %w(rootfs ephemeralbind).each do |mnt|
21
- cmd = Mixlib::ShellOut.new("#{Config[:sudo]}umount /var/lib/lxc/#{lxc.name}/#{mnt}")
26
+ com = "#{Config[:sudo]}umount /var/lib/lxc/#{lxc.name}/#{mnt}"
27
+ debug(com)
28
+ cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
22
29
  cmd.run_command
23
- cmd = Mixlib::ShellOut.new("#{Config[:sudo]}lxc-destroy -n #{lxc.name}")
30
+ com = "#{Config[:sudo]}lxc-destroy -n #{lxc.name}"
31
+ debug(com)
32
+ cmd = Mixlib::ShellOut.new(com, :live_stream => Config[:debug])
24
33
  cmd.run_command
25
34
  cmd.error!
35
+ internal_config[:mappings].delete(name)
26
36
  end
37
+ internal_config.save
27
38
  end
28
39
  end
29
40
  end
@@ -2,11 +2,16 @@ module Vagabond
2
2
  module Actions
3
3
  module Freeze
4
4
  def freeze
5
- if(lxc.running?)
6
- lxc.freeze
7
- ui.info "Container has been frozen: #{name}"
5
+ if(lxc.exists?)
6
+ ui.info "#{ui.color('Vagabond:', :bold)} Freezing node: #{ui.color(name, :blue)}"
7
+ if(lxc.running?)
8
+ lxc.freeze
9
+ ui.info ui.color(' -> FROZEN', :blue)
10
+ else
11
+ ui.error "Node is not currently running: #{name}"
12
+ end
8
13
  else
9
- ui.error "Container #{name} is not currently running"
14
+ ui.error "Node not created: #{name}"
10
15
  end
11
16
  end
12
17
  end
@@ -2,28 +2,40 @@ module Vagabond
2
2
  module Actions
3
3
  module Provision
4
4
  def provision
5
- if(lxc.exists? && lxc.running?)
6
- do_provision
5
+ if(lxc.exists?)
6
+ if(lxc.running?)
7
+ do_provision
8
+ else
9
+ ui.error "Node is not currently running: #{name}"
10
+ end
7
11
  else
8
- ui.fatal "LXC: Requested container: #{name} has not been created!"
12
+ ui.error "Node not created: #{name}"
9
13
  end
10
14
  end
11
-
15
+
12
16
  private
13
17
 
14
18
  def do_provision
15
- @ui.info "LXC: Provisioning #{name}..."
16
- com = "#{sudo}knife bootstrap #{lxc.container_ip(10, true)} -d chef-full -N #{name} -i /opt/hw-lxc-config/id_rsa "
19
+ ui.info "#{ui.color('Vagabond:', :bold)} Provisioning node: #{ui.color(name, :magenta)}"
20
+ com = "sudo knife bootstrap #{lxc.container_ip(10, true)} -d chef-full -N #{name} -i /opt/hw-lxc-config/id_rsa "
17
21
  com << "--no-host-key-verify --run-list \"#{config[:run_list].join(',')}\" "
18
22
  if(config[:environment])
19
23
  com << "-E #{config[:environment]}"
20
24
  end
21
25
  if(Config[:knife_opts])
22
- com << Conifg[:knife_opts]
26
+ com << Config[:knife_opts]
23
27
  end
28
+ debug(com)
29
+ # Send the live stream out since people will generally want to
30
+ # know what's happening
24
31
  cmd = Mixlib::ShellOut.new(com, :live_stream => STDOUT)
25
32
  cmd.run_command
26
- @ui.info "LXC: Provisioning of #{name} complete!"
33
+ # NOTE: cmd.status.success? won't be valid, so check for FATAL
34
+ unless(cmd.stdout.split("\n").last.to_s.include?('FATAL'))
35
+ ui.info ui.color(' -> PROVISIONED', :magenta)
36
+ else
37
+ ui.info ui.color(' -> PROVISION FAILED', :red)
38
+ end
27
39
  end
28
40
 
29
41
  end
@@ -0,0 +1,18 @@
1
+ module Vagabond
2
+ module Actions
3
+ module Rebuild
4
+ def rebuild
5
+ ui.info "#{ui.color('Vagabond:', :bold)} Rebuilding #{ui.color(name, :blue)}"
6
+ destroy
7
+ @lxc = Lxc.new(name)
8
+ destroy
9
+ Config[:force_solo] = true
10
+ ui.info ui.color(' -> DESTROYED!', :red)
11
+ internal_config.run_solo
12
+ internal_config[:mappings].delete(name)
13
+ internal_config.save
14
+ ui.info ui.color(' -> REBUILT!', :green)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,10 +2,15 @@ module Vagabond
2
2
  module Actions
3
3
  module SSH
4
4
  def ssh
5
- if(lxc.running?)
6
- exec("#{Config[:sudo]}ssh root@#{lxc.container_ip(10, true)} -i /opt/hw-lxc-config/id_rsa -oStrictHostKeyChecking=no")
5
+ if(lxc.exists?)
6
+ if(lxc.running?)
7
+ ui.info "#{ui.color('Vagabond:', :bold)} SSH connect to: #{ui.color(name, :cyan)}"
8
+ exec("#{Config[:sudo]}ssh root@#{lxc.container_ip(10, true)} -i /opt/hw-lxc-config/id_rsa -oStrictHostKeyChecking=no")
9
+ else
10
+ ui.error "Node not running: #{name}"
11
+ end
7
12
  else
8
- ui.error "Container #{name} is not currently running"
13
+ ui.error "Node not created: #{name}"
9
14
  end
10
15
  end
11
16
  end
@@ -0,0 +1,18 @@
1
+ module Vagabond
2
+ module Actions
3
+ module Start
4
+
5
+ def start
6
+ ui.info "#{ui.color('Vagabond:', :bold)} Starting node: #{ui.color(name, :green)}"
7
+ do_start
8
+ ui.info ui.color(' -> STARTED', :green)
9
+ end
10
+
11
+ protected
12
+
13
+ def do_start
14
+ lxc.start
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,6 +2,7 @@ module Vagabond
2
2
  module Actions
3
3
  module Status
4
4
  def status
5
+ ui.info ui.color("Vagabond node status:\n", :bold)
5
6
  if(name)
6
7
  status_for(name)
7
8
  else
@@ -11,18 +12,34 @@ module Vagabond
11
12
  end
12
13
  end
13
14
 
15
+ private
16
+
14
17
  def status_for(c_name)
15
18
  m_name = internal_config[:mappings][c_name]
19
+ state = nil
20
+ status = []
16
21
  if(Lxc.exists?(m_name))
22
+ @lxc = Lxc.new(m_name) unless lxc.name == m_name
17
23
  info = Lxc.info(m_name)
18
- status = info[:state].to_s
19
- if(info[:pid])
20
- status << " - PID: #{info[:pid]}"
21
- end
24
+ state = info[:state]
25
+ status << "PID: #{info[:pid] == -1 ? 'N/A' : info[:pid]}"
26
+ status << "Address: #{lxc.container_ip || 'unknown'}"
27
+ status << "\n"
28
+ end
29
+ case state
30
+ when :running
31
+ color = :green
32
+ when :frozen
33
+ color = :blue
34
+ when :stopped
35
+ color = :yellow
22
36
  else
23
- status = 'does not exist'
37
+ color = :red
38
+ end
39
+ ui.info ui.color(" #{c_name}: #{state || "Not currently created\n"}", color)
40
+ unless(status.empty?)
41
+ ui.info(status.map{|s| " #{s}"}.join("\n").chomp)
24
42
  end
25
- ui.info "Status of #{c_name}: #{status}"
26
43
  end
27
44
  end
28
45
  end
@@ -2,11 +2,16 @@ module Vagabond
2
2
  module Actions
3
3
  module Thaw
4
4
  def thaw
5
- if(lxc.frozen?)
6
- lxc.unfreeze
7
- ui.info "Container has been thawed: #{name}"
5
+ if(lxc.exists?)
6
+ if(lxc.frozen?)
7
+ ui.info "#{ui.color('Vagabond:', :bold)} Thawing node: #{ui.color(name, :yellow)}"
8
+ lxc.unfreeze
9
+ ui.info ui.color(' -> THAWED!', :yellow)
10
+ else
11
+ ui.error "Node is not currently frozen: #{name}"
12
+ end
8
13
  else
9
- ui.error "Container #{name} is not currently frozen"
14
+ ui.error "Node does not exist: #{name}"
10
15
  end
11
16
  end
12
17
  end