├── .gitignore ├── README.md ├── Vagrantfile ├── chef └── cookbooks │ └── cocoon │ ├── .kitchen.yml │ ├── Gemfile │ ├── Gemfile.lock │ ├── metadata.rb │ ├── recipes │ ├── _git.rb │ ├── _node.rb │ ├── _postgres.rb │ ├── _ruby.rb │ └── default.rb │ └── test │ └── integration │ └── default │ └── serverspec │ ├── git_test.rb │ ├── node_spec.rb │ ├── postgres_spec.rb │ ├── ruby_spec.rb │ └── spec_helper.rb └── code └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | **/.vagrant/* 2 | **/.kitchen/* 3 | code/** 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cocoon 2 | 3 | Like a warm blanket cocoon is a Rails development Vagrant box to wrap your 4 | Rails application in a repeatable environment. No more, "It works on my 5 | machine." 6 | 7 | ## Getting Started 8 | 9 | 1. Install [Vagrant](https://www.vagrantup.com) and 10 | [VirtualBox](https://www.virtualbox.org/wiki/Downloads) 11 | 12 | 1. Install the Vagrant Omnibus plugin. 13 | 14 | ```bash 15 | $ vagrant plugin install vagrant-omnibus 16 | ``` 17 | 1. Clone this repo and cd into the directory 18 | 19 | ```bash 20 | $ git clone git@github.com:gofullstack/cocoon.git 21 | $ cd cocoon 22 | ``` 23 | 24 | 1. Startup and provision Vagrant, you'll be promped for your local password. 25 | The rest of this process may take a bit of time the first run, go grab a 26 | :cookie: and come back. 27 | 28 | ```bash 29 | $ vagrant up 30 | ``` 31 | 32 | If you get an error about DHCP server config 33 | 34 | ``` 35 | There was an error while executing `VBoxManage`, a CLI used by Vagrant 36 | for controlling VirtualBox. The command and stderr is shown below. 37 | 38 | Command: ["dhcpserver", "add", "--ifname", "vboxnet0", "--ip", "172.28.128.2", "--netmask", "255.255.255.0", "--lowerip", "172.28.128.3", "--upperip", "172.28.128.254", "--enable"] 39 | 40 | Stderr: VBoxManage: error: DHCP server already exists 41 | ``` 42 | 43 | Then run the following command and then vagrant up again (see https://github.com/mitchellh/vagrant/issues/3083 for details) 44 | 45 | ```bash 46 | $ VBoxManage dhcpserver remove --netname HostInterfaceNetworking-vboxnet0 47 | $ vagrant up 48 | ``` 49 | 50 | 1. SSH into Vagrant box. 51 | 52 | ```bash 53 | $ vagrant ssh 54 | ``` 55 | 56 | 1. cd into the code directory and start a new Rails project. 57 | 58 | ```bash 59 | $ cd code 60 | $ rails new awesomesauce 61 | ``` 62 | 63 | or to use this as a wrapper for an existing project checkout your existing project 64 | 65 | ```bash 66 | $ cd code 67 | $ git clone git@github.com:your/project.git 68 | ``` 69 | 70 | 1. Go about your regular Rails development business. Anything in the code 71 | directory will be synced locally to the code directory in cocoon. 72 | 73 | ## Testing 74 | 75 | Cocoon uses Test Kitchen and Rubocop to ensure the chef recipe is in tip 76 | top shape. To run Test Kitchen change into the cocoon cookbook directory 77 | located at `chef/cookbooks/cocoon` and run `kitchen test`. For Rubocop run 78 | `rubocop`. 79 | 80 | ## Contributing 81 | 82 | If you're interested in contributing to Cocoon, go for it! Just branch 83 | from master to a feature branch, make your change and open a pull request. 84 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure('2') do |config| 2 | config.vm.box = 'chef/ubuntu-14.04' 3 | config.omnibus.chef_version = :latest 4 | 5 | config.vm.network :private_network, type: 'dhcp' 6 | config.vm.network :forwarded_port, guest: 3000, host: 3000 7 | config.vm.synced_folder './code', '/home/vagrant/code', nfs: true 8 | 9 | config.vm.provision :chef_solo do |chef| 10 | chef.cookbooks_path = ['chef/cookbooks'] 11 | chef.add_recipe 'recipe[cocoon]' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | provisioner: 6 | name: chef_zero 7 | 8 | platforms: 9 | - name: ubuntu-14.04 10 | 11 | suites: 12 | - name: default 13 | run_list: 14 | - recipe[cocoon::default] 15 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'test-kitchen' 4 | gem 'kitchen-vagrant' 5 | gem 'serverspec' 6 | gem 'chef-zero' 7 | gem 'rubocop' 8 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | ast (2.0.0) 5 | astrolabe (1.3.0) 6 | parser (>= 2.2.0.pre.3, < 3.0) 7 | chef-zero (3.2) 8 | ffi-yajl (~> 1.1) 9 | hashie (~> 2.0) 10 | mixlib-log (~> 1.3) 11 | rack 12 | uuidtools (~> 2.1) 13 | diff-lcs (1.2.5) 14 | ffi (1.9.6) 15 | ffi-yajl (1.2.0) 16 | ffi (~> 1.5) 17 | libyajl2 (~> 1.0) 18 | hashie (2.1.2) 19 | kitchen-vagrant (0.15.0) 20 | test-kitchen (~> 1.0) 21 | libyajl2 (1.1.0) 22 | mixlib-log (1.6.0) 23 | mixlib-shellout (1.6.0) 24 | net-scp (1.2.1) 25 | net-ssh (>= 2.6.5) 26 | net-ssh (2.9.1) 27 | parser (2.2.0.pre.5) 28 | ast (>= 1.1, < 3.0) 29 | slop (~> 3.4, >= 3.4.5) 30 | powerpack (0.0.9) 31 | rack (1.5.2) 32 | rainbow (2.0.0) 33 | rspec (3.1.0) 34 | rspec-core (~> 3.1.0) 35 | rspec-expectations (~> 3.1.0) 36 | rspec-mocks (~> 3.1.0) 37 | rspec-core (3.1.7) 38 | rspec-support (~> 3.1.0) 39 | rspec-expectations (3.1.2) 40 | diff-lcs (>= 1.2.0, < 2.0) 41 | rspec-support (~> 3.1.0) 42 | rspec-its (1.0.1) 43 | rspec-core (>= 2.99.0.beta1) 44 | rspec-expectations (>= 2.99.0.beta1) 45 | rspec-mocks (3.1.3) 46 | rspec-support (~> 3.1.0) 47 | rspec-support (3.1.2) 48 | rubocop (0.26.1) 49 | astrolabe (~> 1.3) 50 | parser (>= 2.2.0.pre.4, < 3.0) 51 | powerpack (~> 0.0.6) 52 | rainbow (>= 1.99.1, < 3.0) 53 | ruby-progressbar (~> 1.4) 54 | ruby-progressbar (1.6.0) 55 | safe_yaml (1.0.4) 56 | serverspec (2.2.0) 57 | rspec (~> 3.0) 58 | rspec-its 59 | specinfra (~> 2.3) 60 | slop (3.6.0) 61 | specinfra (2.3.0) 62 | net-scp 63 | net-ssh 64 | test-kitchen (1.2.1) 65 | mixlib-shellout (~> 1.2) 66 | net-scp (~> 1.1) 67 | net-ssh (~> 2.7) 68 | safe_yaml (~> 1.0) 69 | thor (~> 0.18) 70 | thor (0.19.1) 71 | uuidtools (2.1.5) 72 | 73 | PLATFORMS 74 | ruby 75 | 76 | DEPENDENCIES 77 | chef-zero 78 | kitchen-vagrant 79 | rubocop 80 | serverspec 81 | test-kitchen 82 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'cocoon' 2 | maintainer 'FullStack' 3 | maintainer_email 'team@gofullstack.com' 4 | license 'MIT' 5 | description 'Installs/Configures a Rails development box.' 6 | long_description 'Installs/Configures a Rails development box.' 7 | version '0.1.1' 8 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/recipes/_git.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cocoon 3 | # Recipe:: _git 4 | # 5 | # Copyright (C) 2014 FullStack 6 | # 7 | 8 | # 9 | # Install Git. 10 | # 11 | package 'git' 12 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/recipes/_node.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cocoon 3 | # Recipe:: _node 4 | # 5 | # Copyright (C) 2014 FullStack 6 | # 7 | 8 | # 9 | # Install Node. 10 | # 11 | package 'nodejs' 12 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/recipes/_postgres.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cocoon 3 | # Recipe:: _postgres 4 | # 5 | # Copyright (C) 2014 FullStack 6 | # 7 | 8 | # 9 | # Install Postgres. 10 | # 11 | package 'postgresql' 12 | package 'postgresql-contrib' 13 | 14 | # 15 | # Create a Postgres user. 16 | # 17 | execute 'createuser' do 18 | guard = <<-EOH 19 | psql -U postgres -c "select * from pg_user where 20 | usename='vagrant'" | 21 | grep -c vagrant 22 | EOH 23 | 24 | user 'postgres' 25 | command 'createuser -s vagrant' 26 | not_if guard, user: 'postgres' 27 | end 28 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/recipes/_ruby.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: cocoon 3 | # Recipe:: _ruby 4 | # 5 | # Copyright (C) 2014 FullStack 6 | # 7 | 8 | # 9 | # Install Ruby Build Dependencies 10 | # 11 | package 'libxslt-dev' 12 | package 'libxml2-dev' 13 | package 'build-essential' 14 | package 'libpq-dev' 15 | package 'libsqlite3-dev' 16 | 17 | # 18 | # Add apt-add-repository. 19 | # 20 | package 'software-properties-common' 21 | 22 | # 23 | # Add brightbox ruby repo. 24 | # 25 | execute 'apt-add-repository ppa:brightbox/ruby-ng -y' do 26 | not_if 'which ruby | grep -c 2.1' 27 | end 28 | 29 | # 30 | # Update dependencies. 31 | # 32 | execute 'apt-get update' do 33 | ignore_failure true 34 | end 35 | 36 | # 37 | # Install Ruby 2.1 38 | # 39 | package 'ruby2.1' 40 | package 'ruby2.1-dev' 41 | 42 | # 43 | # Install Bundler, build it against the newly installed 2.1 gem binary 44 | # 45 | gem_package 'bundler' do 46 | gem_binary('/usr/bin/gem2.1') 47 | end 48 | 49 | # 50 | # Install yajl-ruby, required for re-provisioning Chef. 51 | # 52 | gem_package 'yajl-ruby' do 53 | gem_binary('/usr/bin/gem2.1') 54 | end 55 | 56 | # 57 | # Install Rails. 58 | # 59 | gem_package 'rails' do 60 | gem_binary('/usr/bin/gem2.1') 61 | end 62 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/recipes/default.rb: -------------------------------------------------------------------------------- 1 | 2 | # Cookbook Name:: cocoon 3 | # Recipe:: default 4 | # 5 | # Copyright (C) 2014 FullStack 6 | # 7 | 8 | include_recipe 'cocoon::_ruby' 9 | include_recipe 'cocoon::_postgres' 10 | include_recipe 'cocoon::_node' 11 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/test/integration/default/serverspec/git_test.rb: -------------------------------------------------------------------------------- 1 | require_relative 'spec_helper' 2 | 3 | describe 'git' do 4 | describe package('git') do 5 | it { should be_installed } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/test/integration/default/serverspec/node_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative 'spec_helper' 2 | 3 | describe 'node' do 4 | describe package('nodejs') do 5 | it { should be_installed } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/test/integration/default/serverspec/postgres_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative 'spec_helper' 2 | 3 | describe 'postgres' do 4 | it 'is running' do 5 | expect(process 'postgres').to be_running 6 | end 7 | 8 | it 'listens on a tcp socket' do 9 | expect(port 5432).to be_listening 10 | end 11 | 12 | it 'has a vagrant user' do 13 | cmd = command 'echo "\dg" | sudo -u postgres psql' 14 | expect(cmd.stdout).to match 'vagrant' 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/test/integration/default/serverspec/ruby_spec.rb: -------------------------------------------------------------------------------- 1 | require_relative 'spec_helper' 2 | 3 | describe 'ruby' do 4 | it 'has ruby 2.1.2 installed and set as the default version' do 5 | cmd = command 'ruby -v' 6 | expect(cmd.stdout).to match 'ruby 2.1.2' 7 | end 8 | 9 | describe package('bundler') do 10 | it { should be_installed.by('gem') } 11 | end 12 | 13 | describe package('rails') do 14 | it { should be_installed.by('gem') } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /chef/cookbooks/cocoon/test/integration/default/serverspec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'serverspec' 2 | 3 | set :backend, :exec 4 | -------------------------------------------------------------------------------- /code/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gofullstack/cocoon/ec23124a6bcd36f83fbada857267a56a5603fdf9/code/.gitkeep --------------------------------------------------------------------------------