diff --git a/Vagrantfile b/Vagrantfile index adee06e..fd4f7e4 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,7 +6,13 @@ Vagrant.configure('2') do |config| config.vm.network :forwarded_port, guest: 3000, host: 3000 config.vm.synced_folder './code', '/home/vagrant/code', nfs: true + config.ssh.forward_agent = true + config.vm.provision :chef_solo do |chef| + chef.json = { + repo: 'foo/bar' + } + chef.cookbooks_path = ['chef/cookbooks'] chef.add_recipe 'recipe[cocoon]' end diff --git a/chef/cookbooks/bash/.gitignore b/chef/cookbooks/bash/.gitignore new file mode 100644 index 0000000..cd3b225 --- /dev/null +++ b/chef/cookbooks/bash/.gitignore @@ -0,0 +1,18 @@ +.vagrant +Berksfile.lock +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ +/cookbooks + +# Bundler +Gemfile.lock +bin/* +.bundle/* + +# RVM +.rvmrc +.ruby-* diff --git a/chef/cookbooks/bash/.travis.yml b/chef/cookbooks/bash/.travis.yml new file mode 100644 index 0000000..03b52ae --- /dev/null +++ b/chef/cookbooks/bash/.travis.yml @@ -0,0 +1,6 @@ +rvm: + - 1.9.3 + - 2.0.0 +script: + - bundle exec foodcritic -f any . + - bundle exec rspec --color --format progress \ No newline at end of file diff --git a/chef/cookbooks/bash/Berksfile b/chef/cookbooks/bash/Berksfile new file mode 100644 index 0000000..4c630a3 --- /dev/null +++ b/chef/cookbooks/bash/Berksfile @@ -0,0 +1,11 @@ +site :opscode +group :integration do + cookbook 'minitest-handler' +end + +group :unit do + cookbook 'test', + path: 'spec/support/cookbooks/test' +end + +metadata diff --git a/chef/cookbooks/bash/Gemfile b/chef/cookbooks/bash/Gemfile new file mode 100644 index 0000000..b31c13d --- /dev/null +++ b/chef/cookbooks/bash/Gemfile @@ -0,0 +1,8 @@ +source 'https://rubygems.org' + +gem 'berkshelf' +gem 'thor-foodcritic' + +group :dev do + gem 'chefspec' +end diff --git a/chef/cookbooks/bash/LICENSE b/chef/cookbooks/bash/LICENSE new file mode 100644 index 0000000..2b73828 --- /dev/null +++ b/chef/cookbooks/bash/LICENSE @@ -0,0 +1,13 @@ +Copyright (C) 2013 Guilhem Lettron + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/chef/cookbooks/bash/README.md b/chef/cookbooks/bash/README.md new file mode 100644 index 0000000..a478143 --- /dev/null +++ b/chef/cookbooks/bash/README.md @@ -0,0 +1,50 @@ +# bash cookbook + +[](https://travis-ci.org/optiflows-cookbooks/bash) + +This cookbook provides a simple `bash_profile` LWRP. + +It create multiple files in bash\_profile.d folder and merge them into bash\_profile file without loosing any local existing version. + +Obviously, it works only on Linux platform. + +## Usage +Just add `bash` to your cookbook dependency list. + +## Requirement +N/C + +## Resource / Provider +* `bash_profile` : does the init/setup/parse/merge process. This LWRP will create bash\_profile.d folder if not present. + +If an existing bash_profile file exists in user home folder, it will be saved in a permanent init file at the very first run and then will be merged each time LWRP is called. + +### Action +* `add:` (default) - add a specified file to bash\_profile.d folder and merge all files from this folder to given user bash\_profile file. +* `remove:` - remove a specified file from bash\_profile.d folder. + +## Attributes + +* `filename` - name of the file + +* `user` - user to interact with. Group and home folder will be automaticly resolved from system informations. + +* `content` - String to be set on the new profile file. It easily works with simple string, multiline string, or strings loaded from a file. + +#### Syntax + + bash_profile 'profile.addin' do + user 'jdoe' + content "PATH=/home/jdoe/my_bin:$PATH" + end + +## Testing + +Includes basic [chefspec](sethvargo/chefspec) support and matchers. + +1. `bundle install` +2. `rspec` + +## Author + +Author:: Guilhem Lettron (<guilhem.lettron@optiflows.com>) diff --git a/chef/cookbooks/bash/Thorfile b/chef/cookbooks/bash/Thorfile new file mode 100644 index 0000000..a180240 --- /dev/null +++ b/chef/cookbooks/bash/Thorfile @@ -0,0 +1,6 @@ +# encoding: utf-8 + +require 'bundler' +require 'bundler/setup' +require 'thor/foodcritic' +require 'berkshelf/thor' diff --git a/chef/cookbooks/bash/Vagrantfile b/chef/cookbooks/bash/Vagrantfile new file mode 100644 index 0000000..f1339e7 --- /dev/null +++ b/chef/cookbooks/bash/Vagrantfile @@ -0,0 +1,87 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure("2") do |config| + # All Vagrant configuration is done here. The most common configuration + # options are documented and commented below. For a complete reference, + # please see the online documentation at vagrantup.com. + + config.vm.hostname = "bash-berkshelf" + + # Every Vagrant virtual environment requires a box to build off of. + config.vm.box = "Berkshelf-CentOS-6.3-x86_64-minimal" + + # The url from where the 'config.vm.box' box will be fetched if it + # doesn't already exist on the user's system. + config.vm.box_url = "https://dl.dropbox.com/u/31081437/Berkshelf-CentOS-6.3-x86_64-minimal.box" + + # Assign this VM to a host-only network IP, allowing you to access it + # via the IP. Host-only networks can talk to the host machine as well as + # any other machines on the same network, but cannot be accessed (through this + # network interface) by any external networks. + config.vm.network :private_network, ip: "33.33.33.10" + + # Create a public network, which generally matched to bridged network. + # Bridged networks make the machine appear as another physical device on + # your network. + + # config.vm.network :public_network + + # Create a forwarded port mapping which allows access to a specific port + # within the machine from a port on the host machine. In the example below, + # accessing "localhost:8080" will access port 80 on the guest machine. + + # Share an additional folder to the guest VM. The first argument is + # the path on the host to the actual folder. The second argument is + # the path on the guest to mount the folder. And the optional third + # argument is a set of non-required options. + # config.vm.synced_folder "../data", "/vagrant_data" + + # Provider-specific configuration so you can fine-tune various + # backing providers for Vagrant. These expose provider-specific options. + # Example for VirtualBox: + # + # config.vm.provider :virtualbox do |vb| + # # Don't boot with headless mode + # vb.gui = true + # + # # Use VBoxManage to customize the VM. For example to change memory: + # vb.customize ["modifyvm", :id, "--memory", "1024"] + # end + # + # View the documentation for the provider you're using for more + # information on available options. + + config.ssh.max_tries = 40 + config.ssh.timeout = 120 + + # The path to the Berksfile to use with Vagrant Berkshelf + # config.berkshelf.berksfile_path = "./Berksfile" + + # Enabling the Berkshelf plugin. To enable this globally, add this configuration + # option to your ~/.vagrant.d/Vagrantfile file + config.berkshelf.enabled = true + + # An array of symbols representing groups of cookbook described in the Vagrantfile + # to exclusively install and copy to Vagrant's shelf. + # config.berkshelf.only = [] + + # An array of symbols representing groups of cookbook described in the Vagrantfile + # to skip installing and copying to Vagrant's shelf. + # config.berkshelf.except = [] + + config.vm.provision :chef_solo do |chef| + chef.json = { + :mysql => { + :server_root_password => 'rootpass', + :server_debian_password => 'debpass', + :server_repl_password => 'replpass' + } + } + + chef.run_list = [ + "recipe[minitest-handler::default]", + "recipe[bash::default]" + ] + end +end diff --git a/chef/cookbooks/bash/chefignore b/chef/cookbooks/bash/chefignore new file mode 100644 index 0000000..a6de142 --- /dev/null +++ b/chef/cookbooks/bash/chefignore @@ -0,0 +1,96 @@ +# Put files/directories that should be ignored in this file when uploading +# or sharing to the community site. +# Lines that start with '# ' are comments. + +# OS generated files # +###################### +.DS_Store +Icon? +nohup.out +ehthumbs.db +Thumbs.db + +# SASS # +######## +.sass-cache + +# EDITORS # +########### +\#* +.#* +*~ +*.sw[a-z] +*.bak +REVISION +TAGS* +tmtags +*_flymake.* +*_flymake +*.tmproj +.project +.settings +mkmf.log + +## COMPILED ## +############## +a.out +*.o +*.pyc +*.so +*.com +*.class +*.dll +*.exe +*/rdoc/ + +# Testing # +########### +.watchr +.rspec +spec/* +spec/fixtures/* +test/* +features/* +Guardfile +Procfile + +# SCM # +####### +.git +*/.git +.gitignore +.gitmodules +.gitconfig +.gitattributes +.svn +*/.bzr/* +*/.hg/* +*/.svn/* + +# Berkshelf # +############# +Berksfile +Berksfile.lock +cookbooks/* +tmp + +# Cookbooks # +############# +CONTRIBUTING +CHANGELOG* + +# Strainer # +############ +Colanderfile +Strainerfile +.colander +.strainer + +# Vagrant # +########### +.vagrant +Vagrantfile + +# Travis # +########## +.travis.yml diff --git a/chef/cookbooks/bash/files/default/bash_profile b/chef/cookbooks/bash/files/default/bash_profile new file mode 100644 index 0000000..eb73aa6 --- /dev/null +++ b/chef/cookbooks/bash/files/default/bash_profile @@ -0,0 +1,6 @@ +# Managed by Chef. Local changes will be overwritten. +# To manually add resources to the bash_profile, create a file in the ~/.bash_profile.d folder and add your changes there. + +for file in ~/.bash_profile.d/* ; do + source ${file} +done diff --git a/chef/cookbooks/bash/files/default/tests/minitest/default_test.rb b/chef/cookbooks/bash/files/default/tests/minitest/default_test.rb new file mode 100644 index 0000000..624eb5a --- /dev/null +++ b/chef/cookbooks/bash/files/default/tests/minitest/default_test.rb @@ -0,0 +1,11 @@ +require File.expand_path('../support/helpers', __FILE__) + +describe 'bash::default' do + + include Helpers::Bash + + # Example spec tests can be found at http://git.io/Fahwsw + it 'runs no tests by default' do + end + +end diff --git a/chef/cookbooks/bash/files/default/tests/minitest/support/helpers.rb b/chef/cookbooks/bash/files/default/tests/minitest/support/helpers.rb new file mode 100644 index 0000000..ce4d1a8 --- /dev/null +++ b/chef/cookbooks/bash/files/default/tests/minitest/support/helpers.rb @@ -0,0 +1,7 @@ +module Helpers + module Bash + include MiniTest::Chef::Assertions + include MiniTest::Chef::Context + include MiniTest::Chef::Resources + end +end diff --git a/chef/cookbooks/bash/libraries/matchers.rb b/chef/cookbooks/bash/libraries/matchers.rb new file mode 100644 index 0000000..bd22f2f --- /dev/null +++ b/chef/cookbooks/bash/libraries/matchers.rb @@ -0,0 +1,9 @@ +if defined?(ChefSpec) + def add_bash_profile(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:bash_profile, :add, resource_name) + end + + def remove_bash_profile(resource_name) + ChefSpec::Matchers::ResourceMatcher.new(:bash_profile, :remove, resource_name) + end +end \ No newline at end of file diff --git a/chef/cookbooks/bash/metadata.rb b/chef/cookbooks/bash/metadata.rb new file mode 100644 index 0000000..7aacc83 --- /dev/null +++ b/chef/cookbooks/bash/metadata.rb @@ -0,0 +1,7 @@ +name 'bash' +maintainer 'Guilhem Lettron' +maintainer_email 'guilhem.lettron@optiflows.com' +license 'Apache 2.0' +description 'Installs/Configures bash' +long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) +version '0.1.3' diff --git a/chef/cookbooks/bash/providers/profile.rb b/chef/cookbooks/bash/providers/profile.rb new file mode 100644 index 0000000..26929f8 --- /dev/null +++ b/chef/cookbooks/bash/providers/profile.rb @@ -0,0 +1,61 @@ +require 'etc' + +use_inline_resources + +action :add do + init + + file ::File.join(profile_d, new_resource.filename) do + content <<-EOH +# Managed by Chef. Local changes will be overwritten. +#{new_resource.content} +EOH + owner new_resource.user + group Etc.getpwnam(new_resource.user).gid + mode 0644 + end +end + +action :remove do + file ::File.join(profile_d, new_resource.filename) do + action :delete + end +end + +def init + directory profile_d do + owner new_resource.user + group Etc.getpwnam(new_resource.user).gid + mode 0755 + end + + file ::File.join(profile_d, "init") do + if ::File.exists?(::File.join(bash_profile)) + content ::IO.read(::File.join(bash_profile)) + else + action :touch + end + mode 0444 + not_if { ::File.exists?(::File.join(profile_d, "init")) } + end + + cookbook_file bash_profile do + cookbook "bash" + source "bash_profile" + owner new_resource.user + group Etc.getpwnam(new_resource.user).gid + mode 0644 + end +end + +def initial_config? + ::File.directory?(profile_d) +end + +def profile_d + ::File.join(::Dir.home(new_resource.user), ".bash_profile.d") +end + +def bash_profile + ::File.join(::Dir.home(new_resource.user), ".bash_profile") +end diff --git a/chef/cookbooks/bash/recipes/default.rb b/chef/cookbooks/bash/recipes/default.rb new file mode 100644 index 0000000..3e0f79a --- /dev/null +++ b/chef/cookbooks/bash/recipes/default.rb @@ -0,0 +1,18 @@ +# +# Cookbook Name:: bash +# Recipe:: default +# +# Copyright (C) 2013 Guilhem Lettron +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# diff --git a/chef/cookbooks/bash/resources/profile.rb b/chef/cookbooks/bash/resources/profile.rb new file mode 100644 index 0000000..83cfc4b --- /dev/null +++ b/chef/cookbooks/bash/resources/profile.rb @@ -0,0 +1,7 @@ +actions :add, :remove + +default_action :add + +attribute :filename, :kind_of => String, :name_attribute => true +attribute :user, :kind_of => String, :required => true +attribute :content, :kind_of => String, :default => '' diff --git a/chef/cookbooks/bash/spec/profile_spec.rb b/chef/cookbooks/bash/spec/profile_spec.rb new file mode 100644 index 0000000..e637e9d --- /dev/null +++ b/chef/cookbooks/bash/spec/profile_spec.rb @@ -0,0 +1,93 @@ +require_relative 'spec_helper' + +EtcPwnam = Struct.new(:name, :gid) + +describe 'test::profile' do + let(:chef_run) do + pw_user = EtcPwnam.new + pw_user.name = 'test_user' + pw_user.gid = 'users' + Dir.stub(:home).and_return('/home/test_user') + Etc.stub(:getpwnam).and_return(pw_user) + ChefSpec::Runner.new(step_into: ['bash_profile']) + end + + context 'action create' do + context 'init' do + context 'default' do + before do + File.stub(:exists?).and_call_original + IO.stub(:read).and_call_original + File.should_receive(:exists?).with('/home/test_user/.bash_profile').and_return(true) + File.should_receive(:exists?).with('/home/test_user/.bash_profile.d/init').and_return(false) + IO.should_receive(:read).with('/home/test_user/.bash_profile').and_return('') + chef_run.converge described_recipe + end + + it 'to create .bash_profile.d directory' do + expect(chef_run).to create_directory('/home/test_user/.bash_profile.d') + end + + it 'to create .bash_profile.d/init file' do + expect(chef_run).to create_file('/home/test_user/.bash_profile.d/init') + end + + it 'to replace .bash_profile with cookbook file' do + expect(chef_run).to create_cookbook_file('/home/test_user/.bash_profile') + end + end + + context 'to touch' do + before do + chef_run.converge described_recipe + end + + it '.bash_profile.d/init file' do + expect(chef_run).to touch_file('/home/test_user/.bash_profile.d/init') + end + end + end + + context 'test1' do + before do + chef_run.converge described_recipe + end + + it 'create .bash_profile.d/test1 file' do + expect(chef_run).to create_file('/home/test_user/.bash_profile.d/test1') + end + + it 'append chef warning to .bash_profile.d/test1 file' do + expect(chef_run).to render_file('/home/test_user/.bash_profile.d/test1') + .with_content <<-EOH +# Managed by Chef. Local changes will be overwritten. +test1 +EOH + end + end + end + + context 'action remove' do + before do + chef_run.converge described_recipe + end + + it 'delete .bash_profile.d/test2 file' do + expect(chef_run).to delete_file('/home/test_user/.bash_profile.d/test2') + end + end + + context 'matcher' do + before do + chef_run.converge described_recipe + end + + it 'add_bash_profile' do + expect(chef_run).to add_bash_profile('test1') + end + + it 'remove_bash_profile' do + expect(chef_run).to remove_bash_profile('test2') + end + end +end \ No newline at end of file diff --git a/chef/cookbooks/bash/spec/spec_helper.rb b/chef/cookbooks/bash/spec/spec_helper.rb new file mode 100644 index 0000000..58b08dd --- /dev/null +++ b/chef/cookbooks/bash/spec/spec_helper.rb @@ -0,0 +1,2 @@ +require 'chefspec' +require 'chefspec/berkshelf' \ No newline at end of file diff --git a/chef/cookbooks/bash/spec/support/cookbooks/test/metadata.rb b/chef/cookbooks/bash/spec/support/cookbooks/test/metadata.rb new file mode 100644 index 0000000..370d451 --- /dev/null +++ b/chef/cookbooks/bash/spec/support/cookbooks/test/metadata.rb @@ -0,0 +1,9 @@ +name 'test' +maintainer 'test' +maintainer_email 'test@test.com' +license '' +description 'Test the bash cookbook' +long_description 'Test the bash cookbook' +version '1.0' + +depends 'bash' diff --git a/chef/cookbooks/bash/spec/support/cookbooks/test/recipes/default.rb b/chef/cookbooks/bash/spec/support/cookbooks/test/recipes/default.rb new file mode 100644 index 0000000..e69de29 diff --git a/chef/cookbooks/bash/spec/support/cookbooks/test/recipes/profile.rb b/chef/cookbooks/bash/spec/support/cookbooks/test/recipes/profile.rb new file mode 100644 index 0000000..8c88266 --- /dev/null +++ b/chef/cookbooks/bash/spec/support/cookbooks/test/recipes/profile.rb @@ -0,0 +1,9 @@ +bash_profile 'test1' do + user 'test_user' + content 'test1' +end + +bash_profile 'test2' do + action :remove + user 'test_user' +end \ No newline at end of file diff --git a/chef/cookbooks/cocoon/metadata.rb b/chef/cookbooks/cocoon/metadata.rb index ccbef61..8576f6c 100644 --- a/chef/cookbooks/cocoon/metadata.rb +++ b/chef/cookbooks/cocoon/metadata.rb @@ -5,3 +5,4 @@ description 'Installs/Configures a Rails development box.' long_description 'Installs/Configures a Rails development box.' version '0.1.1' +depends 'bash', '~> 0.1.2' diff --git a/chef/cookbooks/cocoon/recipes/_aliases.rb b/chef/cookbooks/cocoon/recipes/_aliases.rb new file mode 100644 index 0000000..1793d85 --- /dev/null +++ b/chef/cookbooks/cocoon/recipes/_aliases.rb @@ -0,0 +1,15 @@ +# +# Some useful bash aliases +# + +bash_profile 'rails.aliases' do + user 'vagrant' + content <<-EOH + alias be='bundle exec' + + alias rails='bundle exec rails' + alias rake='bundle exec rake' + + alias web='bundle exec rackup -p 3000 --host 0.0.0.0' + EOH +end \ No newline at end of file diff --git a/chef/cookbooks/cocoon/recipes/_git.rb b/chef/cookbooks/cocoon/recipes/_git.rb index c48d8ed..3d90dc2 100644 --- a/chef/cookbooks/cocoon/recipes/_git.rb +++ b/chef/cookbooks/cocoon/recipes/_git.rb @@ -9,3 +9,11 @@ # Install Git. # package 'git' + +repo = node[:repo] + +git '/home/vagrant/code' do + repository "git@github.com:#{repo}.git" + reference "master" + action :sync +end diff --git a/chef/cookbooks/cocoon/recipes/_postgres.rb b/chef/cookbooks/cocoon/recipes/_postgres.rb index e3e69f0..645ba60 100644 --- a/chef/cookbooks/cocoon/recipes/_postgres.rb +++ b/chef/cookbooks/cocoon/recipes/_postgres.rb @@ -25,3 +25,34 @@ command 'createuser -s vagrant' not_if guard, user: 'postgres' end + +# +# Create a Postgres database, and related role. +# +# Default to use the git repo name defined in chef.json (in Vagrantfile) as the +# database name, as well as the username / password. For example, the Github +# repo 'foo/bar' would map to 'bar'. +# +name = node['repo'].split('/').last + +execute 'createrole' do + guard = <<-EOH + psql -U postgres -c "select * from pg_user where + usename='#{name}'" | + grep -c #{name} + EOH + + user 'postgres' + command "psql -U postgres -c \"CREATE ROLE #{name} LOGIN PASSWORD '#{name}'\"" + not_if guard, user: 'postgres' +end + +execute 'createdb' do + guard = <<-EOH + psql -U postgres -l | grep -c #{name} + EOH + + user 'postgres' + command "psql -U postgres -c \"CREATE DATABASE #{name} OWNER #{name}\"" + not_if guard, user: 'postgres' +end \ No newline at end of file diff --git a/chef/cookbooks/cocoon/recipes/_ruby.rb b/chef/cookbooks/cocoon/recipes/_ruby.rb index c123f05..91fae08 100644 --- a/chef/cookbooks/cocoon/recipes/_ruby.rb +++ b/chef/cookbooks/cocoon/recipes/_ruby.rb @@ -8,7 +8,15 @@ # # Install Ruby Build Dependencies # -package 'libxslt-dev' + +# +# Update dependencies. +# +execute 'apt-get update' do + ignore_failure true +end + +package 'libxslt1-dev' package 'libxml2-dev' package 'build-essential' package 'libpq-dev' diff --git a/chef/cookbooks/cocoon/recipes/default.rb b/chef/cookbooks/cocoon/recipes/default.rb index 653a82e..99ff374 100644 --- a/chef/cookbooks/cocoon/recipes/default.rb +++ b/chef/cookbooks/cocoon/recipes/default.rb @@ -8,3 +8,5 @@ include_recipe 'cocoon::_ruby' include_recipe 'cocoon::_postgres' include_recipe 'cocoon::_node' +include_recipe 'cocoon::_git' +include_recipe 'cocoon::_aliases'