vagrant binding jayday 2013
TRANSCRIPT
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
Let´s talk about this one...
Content
•Virtualization
•Vagrant
•Puppet
•Chef
•Java Vagrant-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.
Devel
opers
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 minutes to update Eclipse and the SVN plugin
And this was only the first of 50 VMs!!!
Automated VM creationVagrant
VirtualBox
Puppet
Chef
Java
•Don‘t repeat yourself
•„Infrastructure-As-Code“
Automated VM creation
Devs & Ops have time for other stuff
Vagrant
Vagrant
•configure virtual machines by script
•create new instances on the fly
•manage the VM lifecycle
Vagrant
VM
crea
te
man
age
lifec
ycle
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 your VM with Vagrant & configure it with Puppet
•Puppet is pre-installed on Vagrant 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" endend
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 your VM with Vagrant & configure it with Chef
•Chef is pre-installed on Vagrant boxes
just like Puppet
Demo
Vagrant-Binding
configure & manage
VMs in Java
Vagrant-Binding
•Java Wrapper around Vagrant
•create & start VMs at runtime
•only VirtualBox 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
@Testpublic 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
@Rulepublic 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 with Vagrant & Puppet
•Manage lifecycle with Java
Super App Nightly Build with MySQLDefault installation of the App with MySQL DB Server
Super App Nightly Build with Oracle DBDefault installation of the App with Oracle DB Server
Super App Nightly Build without DatabaseUse this to check the default Errors in UI at startup
state: down
state: runningstarted 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
•Remove VirtualBox as dependency (VMWare & AWS support)
•Chef support
•Simpler management of Environments
•Better Builder APIs
•Create Vagrant boxes at runtime
Puppet Forge
Puppet Forge access
•Puppet provied a Repo for default modules
•REST APILet´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 new VM definitions
•Provides > 100 OS templates
•Customize the definition
•Export to VM definition as Vagrant 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