Lightweight and reproducible environments
with
Vagrant & Puppet
& Java
About me
•Hendrik Ebbers
•Lead of JUG Dortmund
•Senior Java Architect at
GmbH in Dortmund, Germany
•DataFX, ControlsFX,AquaFX,
MarvinFX,Vagrant-Binding @hendrikEbbers
www.guigarage.com
hendrik.ebbers@web.de
Let´s talk about this one...
Content
•Virtualization
•Vagrant
•Puppet
•Chef
•JavaVagrant-Binding API
Virtualization
Machines
Virtual Machines
VM templates automated VM
creation
Evolution of VMs
Antipattern by
example
By only using VMs we
can rebuild any customer
system
For each new customer the
best matching VM is copied.
So no initial setup is needed!
Why not deploy all
linux 64bit customer
installations on one
server VM?
Because we copy the VMs on
our Laptops when we travel
to the Customer. And we
only need the system for one
Customer then.
So you have a
virtualized Server for
every Customer where
all developers work on?
No! Only one developer works
on one VM. If a developer
starts working for a customer
he simply copies the VM of
another developer or customer.
D
evelopers
Customers
A
B
C
D
E
1 2 3 4 5 6
One month
later...
Someone updated our SVN.
Eclipse can't use it
anymore
Oh, it took me 15 minutesto update Eclipse and theSVN plugin
And this was only the
first of 50 VMs!!!
Automated VM creation
Vagrant
VirtualBox
Puppet
Chef
Java
•Don‘t repeat yourself
•„Infrastructure-As-Code“
Automated VM creation
Devs & Ops havetime for other
stuff
Vagrant
Vagrant
•configure virtual machines by script
•create new instances on the fly
•manage theVM lifecycle
Vagrant
VM
create
managelifecycle
http://www.vagrantup.com
$ vagrant box add lucid32 http://
files.vagrantup.com/lucid32.box
$ vagrant init lucid32
$ vagrant up
Vagrant
add template VM to
Vagrant
creates VM
configuration-script
start the virtual
machine
Vagrant
•build on top of VirtualBox
•written in Ruby
access by shell &
Ruby
Vagrant
•provides 2 template boxes by default
•simple config-files
•easy ssh connection, shared folder, etc.
Vagrant::Config.run do |config|
config.vm.box = "lucid32"
end
Ubuntu Lucid
32- & 64-bit
it´s just Ruby
see great Vagrant
documentation
Vagrant 1.1.x
•Released this spring
•PlugIn API
•New Providers
Vagrant::Config.run do |config|
config.vm.box = "lucid32"
end
Vagrant.configure("1")
„1“ for Vagrant 1.0.x
„2“ for Vagrant 1.1.x
Provider & Provisioner
•PlugIn API for Providers
•Virtual Box,AWS,VMWare Fusion
•PlugIn API for Provisioners
•Shell, Puppet, Chef,Ansible
Demo
Puppet
Puppet
•configure your machines (nodes) by script
•install and configure software & services
https://puppetlabs.com
Puppet
class apache {
exec { 'apt-get update':
command => '/usr/bin/apt-get update'
}
package { "apache2":
ensure => present,
}
service { "apache2":
ensure => running,
require => Package["apache2"],
}
}
include apache
Apache2 is
installed &
started on node
Puppet
•package individual components in modules
•many online documentations & books out
there
Vagrant
&
Puppet
Vagrant & Puppet
•define yourVM withVagrant & configure it
with Puppet
•Puppet is pre-installed onVagrant boxes
Vagrant defines
the box
Puppet defines
the content
Vagrant & Puppet
Vagrant::Config.run do |config|
config.vm.box = "lucid32"
config.vm.provision :puppet do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "my_manifest.pp"
end
end
path to Puppet
script
Vagrantfile
Chef
Chef
•Just another Provisioner
•Similar to Puppet (at the first look)
conventions
•Modules = recipes
•Module collection = cookbook
Chef
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "my_cookbooks"
chef.add_recipe "apache2"
chef.json = { :apache => { :site_enabled => true } } end
end
path to
cookbooks
use this recipe
configure
Vagrant
&
Chef
Vagrant & Chef
•define yourVM withVagrant & configure it
with Chef
•Chef is pre-installed onVagrant boxes
just like Puppet
Demo
Vagrant-
Binding
configure & manage
VMs in Java
Vagrant-Binding
•Java Wrapper aroundVagrant
•create & startVMs at runtime
•onlyVirtualBox is required
Let´s have a look
Vagrant-Binding
•Builder APIs
•JUnit support
•Puppet support
Builder API
VagrantVmConfig vmConfig = new VagrantVmConfigBuilder()
! ! ! ! .withLucid32Box()
! ! ! ! .withName("myLittleVm")
! ! ! ! .withHostOnlyIp("192.168.50.4")
! ! ! ! .build();
VagrantEnvironment environment = ...;
environment.up();
! ! !
environment.getVm(0).createConnection().execute("touch /tmp1");
environment.destroy();
also builder API
available
builder API for VM
manage VM lifecycle
ssh connection
Demo
JUnit support
@Test
public void testJdbc() {
MySql dbHandler = new MySql(ip, db, user, pwd);
dbHandler.createMyTable();
dbHandler.insertRow();
assertEquals(1, dbHandler.getRowCount());
dbHandler.clearAndClose();
}
what if table already
exists?
what if host not reachable?
parallel
processes?
JUnit support
@Rule
public VagrantTestRule testRule =
new VagrantTestRule(createConfig());
public static VagrantConfiguration createConfig() {
//Configure VM with MySQL-Server & static ip
}
@Test public void testJdbc() {...}
create VM start VM run UnitTest destroy VM
default JUnit annotation
manage VM lifecycle
use builder API for VM
specification use the VM
Demo
QA Portal
•Manage all test machines withVagrant &
Puppet
•Manage lifecycle with Java
Super App Nightly Build with MySQL
Default installation of the App with MySQL DB Server
Super App Nightly Build with Oracle DB
Default installation of the App with Oracle DB Server
Super App Nightly Build without Database
Use this to check the default Errors in UI at startup
state: down
state: running
started by: John
state: down
Mockup
Workflow example
Create VM-
Definition
Upload to
portal
Add Link to
Jenkins-Job
User starts
QA
Create &
configure VM
use
Trigger Jenkins
build
use
feedback
Test the
nightly build
let´s find
some bugs
deploy the
nightly
destroy VM
in portal
just a click
in the portal
Vagrant-Binding
https://github.com/guigarage/vagrant-binding
fork me on github
Roadmap
•RemoveVirtualBox as dependency (VMWare &
AWS support)
•Chef support
•Simpler management of Environments
•Better Builder APIs
•CreateVagrant boxes at runtime
Puppet Forge
Puppet Forge access
•Puppet provied a Repo for default modules
•REST API Let´s use this
Puppet Forge access
File moduleFolder = new File("...");
PuppetForgeClient client = new PuppetForgeClient();
! !
! !
List<PuppetForgeModuleDescription> allDescriptions =
! client.findModules("mongodb");
! !
for(PuppetForgeModuleDescription desc : allDescriptions) {
! System.out.println("Installing " + desc.getFullName());
! PuppetForgeModule module = client.findModule(desc);
! client.installToModulesDir(moduleFolder, module);
}
search
install as module
at runtime
Demo
Veewee
Veewee
•Build newVM definitions
•Provides > 100 OS templates
•Customize the definition
•Export toVM definition asVagrant Box
Veewee templates
Veewee
$ bundle exec veewee vbox templates | grep -i ubuntu
$ bundle exec veewee vbox define 'mybuntubox'
'ubuntu-12.10-server-amd64'
$ bundle exec veewee vbox build 'mybuntubox'
list all ubuntu
templates
define new VM
for Virtual Box
build VM for
Virtual Box
Veewee
$ bundle exec veewee vbox export 'myubuntubox'
$ vagrant box add 'myubuntubox' 'myubuntubox.box'
Vagrant.configure("2") do |config|
config.vm.box = "myubuntubox"
end
Export VM instance
as box
add box to
Vagrant
use VM template
in Vagrantfile
Vagrant-Binding
2.0
Vagrant-Binding 2.0
•Support of Vagrant 1.1.x
•Virtual Box and AWS Provider API
•Veewee wrapper
•Better Chef and Puppet API
•Basic Java / Groovy Provisioner API
Thanks
for
watching
@hendrikEbbers
www.guigarage.com
hendrik.ebbers@web.de

Vagrant Binding JayDay 2013