CabezaDeTermo::Cachivache
Installation
gem install cachivache
Description
Cachivache is a provisioner for Vagrant machines with Ubuntu images.
You can provision a Vagrant VM using shell scripts, or more sophisticated tools like Puppet, Chef, salt, Ansible and by the time you are reading this probably a few more.
If you are a developer, most of the time you just want to quickly provision you Vagrant with some bash script that installs some services and libraries, replace some parameter files in your application and probably run a few custom bash commands and that's pretty much it. The good thing about provisioning with bash scripts is that it is fast and very easy to implement (just google how to install something and toss the bash script into the provision script and that's it). On the other hand, the problems with shell provisions are that
bash is unreadable. That's not a problem most of the times, but when the a task becomes a little more complex than c&p the apt-get instructions to install something, it becomes one (even some super simple tasks like replacing parameters in a file)
it's very difficult to factorize and reuse
even if you factorize it into little bash scripts, you can't easyly declare dependencies between these scripts
The provisioning tools like Puppet and Chef resolve these problems, and a lot more. Actually, they resolve so much more problems that is overkill to only use them to provision a Vagrant machine for developing. All of these tools define their own DSL and high level concepts and metaphors, they require you configure them, you must search for the correct recipes to install what you want, etc. These tools are a must to manage the provisioning of different environments, but for a single developer machine they are way too much.
Cachivache is a middle ground between bash scripts and these tools. Instead of reinventing the wheel with a brand new DSL and new metaphors, Cachivache uses a wheel that we have had for ages: Rake.
Usage
Once you installed the cachivache
gem, setup cachivache for your project:
- Go to the root of your project
cachivache init
cd cachivache
write some stuffs in your stuff
folder and set what stuff to install and your git email and user:
cachivache configure
and that's it, you can now start Vagrant with:
vagrant up
vagrant ssh
cd src
and you have your project running in a Vagrant machine.
If you want to commit from Vagrant, add the :'projects-setup'
as a dependency of your project in the stuff you created, it will set your git credentials.
The idea behind Cachivache is to put little bash scripts in Rake tasks, and then run those tasks from within the Vagrant VM. As the Ubuntu images already come with a Ruby installation, there's not much to do at all.
So, Cachivache has very few concepts:
Bash scripts, which you put in Rake tasks
Rake tasks (also called stuffs in this framework), that can depend on other Rake tasks
Ruby string interpolation, which allows you to easily parametrize stuff in the bash scripts
And the secret ingredient: stuff
What is stuff? Stuff is a folder with .rb files. That's it. Cachivache believes in giving power to the people, so instead of defining how, where and when you must organize your scripts, it will let you organize things in any way you want in a couple of folders: stuff-library
and stuff
. No recipes, playbooks, roles, bags, configurations, minions, masters, slaves, facts, etc. Just put stuff in a folder.
stuff-library
folder holds some existing stuff you can use to install things, and in stuff
you can toss your own stuff for your project.
So, what does a stuff look like?
Well, here's an example stuff that setups all the necessary things to work on a php library:
dependencies = [
:'projects-setup',
:graphviz,
:xdebug,
:'php-cli',
:composer,
]
stuff :'php-json-spec' => dependencies do
shell %Q{
cd #{PhpJsonSpec.project_folder}
composer install
# Run the test coverage report
php vendor/bin/phpunit -c phpunit-with-coverage.xml
# Generate the documentation
php vendor/bin/phpdoc
}
end
configure :PhpJsonSpec do
let(:project_folder) { Cachivache.src_folder }
end
How about a more complex stuff, like setting up an app for apache?
Here is an example of that: php-site-sample
How do I tell Cachivache what to install?
Edit the file cachivache.rb
and define the stuffs to install in the section
####################################
# Define what stuff to install
####################################
let(:stuff_to_install) {
[
'ruby-json-spec',
'some-other-stuff',
'a-namespace:and-another-one:more-stuff',
'mysql-server', # You can install any stuff as long as it is defined
]
}
Note that if you set the dependencies of each stuff correctly, you will only have to tell Cachivache to install the top most stuff, and Rake will do the rest for you. Thanks Rake!
What other awesome features has Cachivache?
As I said before, all the work is done by Rake, so pretty much none.
There is some sintactic sugar you can use to perform some common task though. But please note that using any of these shorcuts is not mandatory at all, you can just stick to plain old shell scripts.
If you haven't see any ruby code before, here are some tips to use in Cachivache stuffs:
You can define strings in several ways:
stuff :'do-stuff' do
shell %Q{
echo "stuff"
}
end
# or
stuff :'do-stuff' do
shell %Q[
echo "stuff"
]
end
# or
stuff :'do-stuff' do
shell %Q(
echo "stuff"
)
end
# or in a single line
stuff :'do-stuff' do
shell %Q{echo "stuff"}
end
# or with ""
stuff :'do-stuff' do
shell "echo \"stuff\""
end
You see in the last example that if we define strings using "" we need to scape internals \", so the simpliest is to use %Q{}
.
You can call as many shell
blocks within a task as you like. You can also :invoke and :execute other tasks:
stuff :'do-stuff' do
shell %Q{
echo "stuff"
}
invoke 'install-apache'
shell %Q{
echo "even more stuff"
}
execute 'restart-apache'
shell! %Q{
echo "You would normally not need to use :shell! (note the exclamation mark) but you can"
}
end
The difference between :invoke and :execute is that :execute will perform the task every time it's called, whilst :invoke will only run the task once during the provision. So, to install and configure stuff use :invoke, but to turn things on and off use :execute. Or if your tasks are idempotent, always use :execute to make things simplier. It's up to you.
Instead of using bash if ! ...; then; .... fi
, you can use these Cachivache helpers:
stuff :'do-stuff' do
shell_unless file_exists: '/bla.conf' do
shell %Q{
ls -la
rm -rf bla
}
end
end
stuff :'do-stuff' do
shell_unless folder_exists: '/bla' do
shell %Q{
ls -la
rm -rf bla
}
end
end
stuff :'do-stuff' do
shell_unless file: '/bla', contains: 'some regex' do
shell %Q{
ls -la
rm -rf bla
}
end
end
stuff :'do-stuff' do
shell_unless command: 'java -version', contains: 'java 1.8' do
shell %Q{
ls -la
rm -rf bla
}
end
end
- To append and replace text in a file, you can use this Cachivache helper:
stuff :'do-stuff' do
in_file "/etc/bla.conf" do
shell replace pattern: "%user%", with: "admin"
shell append "[cachivache]"
shell append "path='/bla'"
shell append :new_line
end
end
You can use variables instead of hardcoding values in the scripts:
stuff :'do-stuff' do
shell %Q{
mkdir #{DoStuff.some_folder}
mkdir #{SomethingDefinedElsewhereWorksToo.some_folder}
}
end
configure :DoStuff do
let(:some_folder) { '/home/vagrant/some-folder' }
end
If you want to remind the user of something after the provision is done, in any task use :remind_to
stuff :'do-stuff' do
shell %Q{
ls -la
}
remind_to "Please don't forget to add '#{Cachivache.vagrant_ip_address} cachivache.com' to your /etc/hosts file"
end
What if I want to use my own stuff-library
?
No prob! Go to your cachivache
folder and:
cachivache add-stuff-library git@github.com:someuser/my-very-own-stuff-library.git
Cachivache will load any .rb file in the cachivache folder, so your library stuff will be loaded too.
To update some stuff library from git do:
cachivache update-stuff-libraries my-very-own-stuff-library
To update all the stuff libraries do:
cachivache update-stuff-libraries
To remove a stuff library do:
cachivache remove-stuff-libraries stuff-library
Debugging
During the building of the stuff, it's useful to be able to see what the provision would do instead of running it.
To debug the provision do
- Go to the root of your project
cd cachivache
vagrant ssh
cd src/cachivache
(now you are in Vagrant)bundle install
rake explain
will output the complete shell script without running itrake some-stuff
will execute only some-stuff and its dependencies
Running the tests
Not a single test was written this day :(
Roadmap
- v1.0.0: Make a custom Vagrant provisioner plugin
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/cabeza-de-termo/cachivache.
License
The gem is available as open source under the terms of the MIT License.