Create a virtual machine for development with Vagrant - bash

I am using nodejs with ansible and vagrant
I need to create a new machine for development with such things:
on every vagrant up I need to do:
run this script (to install all needed soft for development):
bash <(wget -qO- https://raw.githubusercontent.com/thoughtbot/laptop/master/linux)
NPM install on every submodule in my project
install and run mongodb service
How I can set these stuff to do automatically in vagrant or ansible?

You have a few options:
vagrant up, install your dependencies and repackage it as a box with: vagrant package or vagrant box repackage
Use chef/puppet/ansible provisioners, or even the shell provisioner. This will allow it to happen on vagrant up or vagrant provision
Roll your own in ruby and have vagrant run it (a vagrantfile is basically just ruby). I don't recommend this way.
I personally recommend 2 even though its the slowest (requires you to do all the owrk every time you destroy and up). 1 is a really good choice but I tend to keep vagrant as close to base state as possible so that no surprises pop up during deployment. And it makes it easier to share across people if you don't have to constantly re-package it and maintain that .box

Related

Can you perform a vagrant provision from inside the VM?

Usually you have to run vagrant provision from outside your VM to create the VM to begin with. I then do a vagrant ssh to inspect the resultant VM.
If I wish to make small tweaks to the VM (using chef zero recipes in my case), I have to either switch to an other tab that is on my physical host, or exit the SSH session. it would be nice if you could do this run-and-inspect inside the previously created VM.
Why I'm asking: I have too many terminal tabs open for development and am looking for ways to prune, and avoid mental context switching (not to mention trying to figure out which tab is which).
No, you can not run a vagrant provision from inside the same vagrant machine.
Vagrant is running on your host and provisioning the VM according to the specified vagrantfile. Any changes that you want to have applied during the provisioning must somehow come from the vagrantfile.
What you can do is modify a running vagrant machine in any way you want from inside the vagrant machine, and then export the VM using vagrant package to a new vagrant box which then can be used as base for new vagrant VMs.
PS: Not sure how you're dev environment looks like, but I suggest you look into terminal multiplexers like GNU screen or tmux, that might be able to help you with your "tab issues".

Upgrade php to 5.6 in Vagrant provisioning

I upgraded php to 5.6 within the Vagrant box 'trusty64', and also installed SOAP client. When I next update Vagrant I'm thinking it might overwrite these changes. Would I also need to change the provisioning in the vagrantfile, and if so what should I add?
When I next update Vagrant I'm thinking it might overwrite these
changes.
No, You would not loose anything if you upgrade vagrant. Once the VMs are created, vagrant will operate those VMs and upgrading vagrant will not impact the existing VM.
Basically, it works like this:
- when you run vagrant up, vagrant clone the box (which is VM files) and add the VM to VirtualBox
- after the VM have been created, vagrant "operates" (i.e. start, stop ...) the VirtualBox VM for you
Would I also need to change the provisioning in the vagrantfile
Thats necessary to change the provisioning if you plan to create more VM of this kind, or if you will destroy and recreate this VM; in this case the provisioning will run and you would need to have it updated.
and if so what should I add?
save all the commands you have run to run the upgrade and create a shell script out of it, might be the most simple option. You can also look at more advanced tool (puppet, ansible, chef .... that would do this job)

Hot deploying app builds to Vagrant

Please note: although I mention Gradle/Groovy in this question, this is strictly about Vagrant usage, and could just as easily apply to any other language/build system.
I am new to Vagrant and am trying to figure out how Vagrantfiles, when pushed to source control, interact with that repo's build.
Say I have the following repo, built by Gradle:
src/
main/
groovy/
<lots of groovy source>
test/
groovy/
<lots of groovy test source>
build.gradle
settings.gradle
Now let's say that, without Vagrant, I would normally clone this repo and run gradle clean build to run unit tests on the code, and ultimately, package it into a running program (executable JAR). Then a gradle run starts the app.
Well, in a lot of GitHub repos I see Vagrantfiles committed. So obviously this is to make it easy to spin up a VM and run the respective app inside of. I'm trying to figure out the typical "flow" of incorporating a Vagrantfile into my repo above such that developers can:
Clone the repo
Build with Gradle
Somehow, deploy to the Vagrant box
Test the running app instance (running inside the box)
Tweak the code } #4, #5 and #6 quick/rapid dev-test-tweak cycles utilizing hot re-deploys
Re-test
Take a look at this Vagrantfile for a CAS server (chosen at random). I think this is where the magic happens, in terms of deploying and restarting the server on the box, but I checked the Vagrant docs for shell.inline and nothing concrete came up.
So I ask: How do I "integrate" my Vagrantfile with my build, such that the build produces a deployed, running app? Further, what do my run/deploy-test-code-redeploy cycles look like with Vagrant boxes (what I call "hot deploying")?
I'm going to explain how I would achieve what you are looking to do, this might not be the official way to do it, so anyone with more Vagrant experience should please provide pointers on where it can be improved. I've been working with Vagrant for about 6 months now. You say you are new to Vagrant, so I'll be as complete as I can, even though some parts you have probably already mastered, but might be useful to other users.
tl;dr; Skip to Creating the Vagrantfile section if you are already familiar with how the Vagrantfile works
Let's start with what the example Vagrantfile is doing.
config.vm.box = "puppetlabs/centos-6.5-64-puppet"
This is telling Vagrant to pull the box on which everything else is built. You can find a lot of official and community contributed boxes on the Vagrant Cloud. This one being from puppetlabs, based on CentOS 6.5 64-bit with Puppet already installed.
config.vm.network "forwarded_port", guest: 8080, host: 8088
This is telling Vagrant to forward port 8088 on your host to 8080 on the Vagrant box. So accessing http://127.0.0.1:8088 on your host will access port 8080 on the guest.
config.vm.provision :shell do |shell|
Provisioning is the process of setting up the Vagrant box when it is ran for the first time. Provisioning will only run once for a new VM, unless forced. See the provisioning section of the Basic Usage Vagrant Docs. This one specifically is executing a bunch of shell commands when it is being provisioned.
shell.inline = "command;
command;"
Shell inline is sending these commands, seperated by the semicolon, to the box. This is to automate the commands as if you were typing them in an SSH session yourself. The Vagrant Docs on Shell Provisioning has some more advanced uses where you can define an actual file to be executed.
Note: Your shell script should not try to execute tools that have not yet been installed. (ex. Running a Python script where Python is not available yet).
config.vm.provision "puppet" do |puppet|
I can't comment much on the Puppet section since I'm not a Puppet user (yet, probably). This is setting some Puppet values.
shell.inline = "cd /vagrant && mvn clean package;
sudo cp target/cas.war /srv/tomcat/cas/webapps/;
sudo /sbin/service tomcat-cas restart"
This is also executing shell commands. Basically changing directory, cleaning, copying cas.war to the webapps directory and then restarting the service. More on the /vagrant shared folder later. Now we have enough to start building our own Vagrant file on. I'm going to keep the sample simple to make it generic.
Creating the Vagrantfile
You will most likely want to build on a Vagrant box that already matches your requirements, but for now, let's not do that. You can however find a lot of already created boxes on the Vagrant Cloud. I'm going to show you how to get a (very) simple Python app running using Flask.
Pick your favourite distribution from the available Vagrant boxes. I'm going to use ubuntu/trusty64 since I use it on a daily basis. All command should be easily translated to other distributions.
Create a new directory for your project and open a shell / console window in it.
Using the console, initialize your Vagrant box vagrant init ubuntu/trusty64. This will create a base Vagrantfile for you to work from.
Open your Vagrantfile and uncomment config.vm.network "forwarded_port", guest: 5000, host: 8080. We want port 8080 to take us to port 5000 on the guest machine. Tip: For your project, it will be wise to choose a port that is most likely not already in use to avoid clashing with other apps. 8080 might be bad choice, 8089 will be better.
Let's add some scripts to execute on provisioning. Since Python is shipped with Ubuntu (and most other I know) we don't need to install Python, but we do need pip (a Python Package manager) and Flask.
config.vm.provision :shell do |shell|
shell.inline = "cd /vagrant;
sudo apt-get -y install python-pip;
sudo pip install Flask;"
end
This will change the directory to the Vagrant share. Install pip using Ubuntu's package manager, then install Flask using pip. The -y flag is to automatically have apt-get install without prompting for a yes/no question. You might need to run Vagrant up --provision a couple of times to get all your commands 100% correct.
Note on the Vagrant share: The Vagrant share is a directory that is synced between the host and guest machine and will be available under /vagrant. It includes all the files and directories in your project directory (where your Vagrantfile resides).
We now have all the tools we need to run our app. I've created an incredibly simple Flask app as a sample. Download it to your project directory from this Gist and name it app.py
Now we'll be able to run the Python app located in your project directory. I like to keep the install sections and running sections seperate. So add another section that starts the app.
Note: The & makes the app fork to the background so the vagrant up can complete. You'll probably want to do something more fancy than this with your app.
config.vm.provision :shell do |shell|
shell.inline = "/vagrant/app.py &"
end
Finally we can start everything and have Vagrant do its magic. In your console, in your project directory (where your Vagrant file is located). Run vagrant up.
Moment of truth. Open your browser (on the host) and browse to http://127.0.0.1:8080/. You should see Hello Vagrant Provisioned World!.
That takes care of the provisioning of your app. Automatically, from a Vagrantfile, that you can commit with your project code.
Now to get to your initial steps, and how this fits in.
Integrating into your development workflow
I'm listing your steps, integrated with Vagrant.
Clone the repo
This step stays the same, with the exception of a Vagrantfile included in your repo with provisioning for any required libraries and tools required for your project.
Run vagrant up in the project directory. This will automatically create and provision the box and share your project with the box.
You can build the project in the Vagrant provisioning steps, but if you are actively developing the application, you might not want to do that.
Test the running app instance (running inside the box) - Simply SSH into the box, enter the `/vagrant' directory and run your app.
Tweak the code } #4, #5 and #6 quick/rapid dev-test-tweak cycles utilizing hot re-deploys
Since your project is shared live between the host and the guest. you can simply stop the app (if running) and run the app again on the guest. No copying needed.
Re-test
This will give you quick developent cycles while keeping the environment the same. A new developer can simply clone and vagrant up to get going on the project without worrying about the environment and whatnot.
Continuous Integration is a vast topic. You can still apply the practises to your repo, etc. But I'd skip the CI deployment process while developing. I make use of Jenkins and Capistrano for my CI deployments, but it is too heavy weight for development. In production I won't use Vagrant since it will double-virtualize your VM already (unless you run bare metal). For production I'll make use of Docker and Fig.
I hope this explains how to integrate Vagrant into your flow for your project, please do comment if anything needs clarification. I believe the sample should word perfectly, since that is the goal of using Vagrant.

Vagrant: running ansible provisioning just while creating virtual machine?

Using Vagrant, is it possible to run my provisioning Ansible script just when vagrant up creates the virtual machine? I wan to provision just when the import sequence is run. I have a very slow step that imports the database. It isn't idempotent and I'd like it to run just the first time.
I can make a script using vagrant status and vagrant up --no-provision, but I believe there should be a more straightforward way.
I also can just run Ansible after the first vagrant up, but then I won't be able to brag to my friends that I create my server from scratch running just one command :-)
I think you are using a version older than 1.3.0;-)
Since Vagrant 1.3.0, vagrant up only run provisioning by default the first time it runs (after the import). Subsequent reload or up will need to explicitly specify the --provision flag, for example vagrant up --provision or just vagrant provision.
See the full changelog
The change => vagrant up will now only run provisioning by default the first time it is run. Subsequent reload or up will need to explicitly specify the --provision flag to provision. [GH-1776]

Does Puppet continue to run after startup when used as a provisioner in Vagrant?

The question is basically in the title, but to expound a little: I've got a puppet manifest that runs on startup in our development Vagrant VMs. I'd like to add a couple things that make life easier for our developers -- things like bouncing Apache when our source files change or rebuilding our translation files when the master file is changed.
All of that seems simple enough to do, but I'm not sure whether it's possible to make the puppet service continue to monitor the machine after the VM is provisioned, and the Vagrant documentation doesn't seem to mention it.
Provisioning is a part of the vagrant up process, once the VM is up and running, it's finished.
NOTE: Provisioners in Vagrant allow you to automatically install software, alter configurations, and more on the machine as part of the vagrant up process.
I am NOT an expert on Puppet (Chef user), I think to bounce Apache if config files are changed, you may need an agent running on the VM.
BTW: vagrant provision can be used to run updated Chef cookbooks or Puppet modules after the VM is up.
Update
Since Vagrant 1.3.0 (released Sep 5, 2013)
vagrant up will now only run provisioning by default the first time it is run. Subsequent reload or up will need to explicitly specify the --provision flag to provision. [GH-1776]
See change log => https://github.com/mitchellh/vagrant/blob/master/CHANGELOG.md

Resources