toque 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/.travis.yml +4 -0
- data/Capfile +3 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +109 -0
- data/Rakefile +6 -0
- data/Vagrantfile +99 -0
- data/lib/toque.rb +18 -0
- data/lib/toque/chef.rb +145 -0
- data/lib/toque/helpers.rb +69 -0
- data/lib/toque/tasks.rb +20 -0
- data/lib/toque/version.rb +12 -0
- data/spec/config/cookbooks/awesomeium/recipes/default.rb +8 -0
- data/spec/config/cookbooks/awesomeium/recipes/second.rb +7 -0
- data/spec/config/deploy.rb +35 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_toque.rb +54 -0
- data/spec/toque/chef_spec.rb +129 -0
- data/spec/toque/helpers_spec.rb +39 -0
- data/toque.gemspec +22 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 728adde958810a994d9d16b9d51d2f8cd31ef9dd
|
4
|
+
data.tar.gz: f56fb4afebd0bfc9defe5a9e995a4f26a4466f17
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2c689a0d5f297ed1cbd9c4fba502ecf4ab918770afe4eef89c936d1a207dc3593d85e476c5ce127a2e384d1d23d50cb036d4c46c905b0fc938c02cd16ada185f
|
7
|
+
data.tar.gz: d13815fc714a02a45cb16a4fb3a783e970b3761910b5387078a3aa8464cf0401104fcc7de1b1b21b5b39716174ad1ca826e4af7b6b9269b9e2a4561ee1c297cd
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Capfile
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in toque.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem 'rake'
|
8
|
+
gem 'rspec'
|
9
|
+
gem 'vagrant', '>= 1.0.7'
|
10
|
+
gem 'bundler', '~> 1.3'
|
11
|
+
gem 'capistrano-spec', github: 'jgraichen/capistrano-spec'
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Jan Graichen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Toque - The cap of a Chef
|
2
|
+
|
3
|
+
[](https://travis-ci.org/jgraichen/toque)
|
4
|
+
|
5
|
+
**Toque** combines the power of *chef-solo* and *capistrano*. It allows you to
|
6
|
+
run chef cookbooks with chef-solo as part of your capistrano deploy process.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'toque'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install toque
|
21
|
+
|
22
|
+
After capifying your project add to your `Capfile`:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'toque'
|
26
|
+
```
|
27
|
+
|
28
|
+
You can install chef by running `cap toque:chef:install` otherwise it will be
|
29
|
+
installed on first `run_list` call. **Toque** uses chef omnibus installer to
|
30
|
+
install a complete self-contained embedded chef environment.
|
31
|
+
|
32
|
+
You can specify a specific chef version by setting `:chef_version` to
|
33
|
+
something different to `:latest` or `nil`. An already installed version of
|
34
|
+
chef will not be upgraded.
|
35
|
+
|
36
|
+
See `cap toque:config` for more options.
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
**Toque** assumes your cookbooks to be in `config/cookbooks` or
|
41
|
+
`vendor/cookbooks`. One way is to use `config/cookbooks` for your own
|
42
|
+
application cookbook(s) and `vendor/cookbooks` for community cookbooks managed
|
43
|
+
by [librarian-chef](https://github.com/applicationsonline/librarian-chef).
|
44
|
+
|
45
|
+
You can configure *librarian-chef* to use `vendor/cookbooks` as cookbook path:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
$ librarian-chef config path ./vendor/cookbooks --local
|
49
|
+
```
|
50
|
+
|
51
|
+
In your deploy configuration you can now run `toque.run_list` with a list of
|
52
|
+
recipes you want to execute. You can run chef more then once with different
|
53
|
+
list.
|
54
|
+
|
55
|
+
For example if you want to setup the server before deploying your app run
|
56
|
+
your setup recipe right at the start:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
before "deploy:update_code" do
|
60
|
+
toque.run_list 'recipe[awesome::setup]'
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
After deploying your app you may need to create a config for your application
|
65
|
+
like `database.yml` or redis configuration:
|
66
|
+
|
67
|
+
after "deploy:create_symlink" do
|
68
|
+
toque.run_list 'recipe[awesome::configure]'
|
69
|
+
end
|
70
|
+
|
71
|
+
## Configuration
|
72
|
+
|
73
|
+
By default all capistrano options are available in your node configuration:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
# config/deploy.rb
|
77
|
+
|
78
|
+
set :application, 'awesomeium'
|
79
|
+
set :deploy_to, "/var/www/#{application}"
|
80
|
+
set :user, 'awesomeix'
|
81
|
+
|
82
|
+
# config/cookbooks/awesome/recipes/configure.rb
|
83
|
+
|
84
|
+
template File.join(node[:deploy_to], 'config', 'database.yml') do
|
85
|
+
source 'database.yml.erb'
|
86
|
+
owner node[:user]
|
87
|
+
recursive true
|
88
|
+
end
|
89
|
+
```
|
90
|
+
|
91
|
+
## Thanks
|
92
|
+
|
93
|
+
Thanks to [roundsman](https://github.com/iain/roundsman) doing even some more
|
94
|
+
tasks like installing ruby and chef via rubygems. I've decided to make up
|
95
|
+
something new to use omnibus installer right from the start.
|
96
|
+
|
97
|
+
Also take a look at
|
98
|
+
[capistrano-spec](https://github.com/technicalpickles/capistrano-spec) allowing
|
99
|
+
some really great capistrano testing.
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
1. Fork it
|
104
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
105
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
106
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
107
|
+
5. Create new Pull Request
|
108
|
+
|
109
|
+
You can run a simple vagrant based test by running `bundle exec rspec spec/spec_toque.rb`.
|
data/Rakefile
ADDED
data/Vagrantfile
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
Vagrant::Config.run do |config|
|
5
|
+
# All Vagrant configuration is done here. The most common configuration
|
6
|
+
# options are documented and commented below. For a complete reference,
|
7
|
+
# please see the online documentation at vagrantup.com.
|
8
|
+
|
9
|
+
# Every Vagrant virtual environment requires a box to build off of.
|
10
|
+
config.vm.box = 'precise32'
|
11
|
+
|
12
|
+
# The url from where the 'config.vm.box' box will be fetched if it
|
13
|
+
# doesn't already exist on the user's system.
|
14
|
+
config.vm.box_url = 'http://files.vagrantup.com/precise32.box'
|
15
|
+
|
16
|
+
# Boot with a GUI so you can see the screen. (Default is headless)
|
17
|
+
# config.vm.boot_mode = :gui
|
18
|
+
|
19
|
+
# Assign this VM to a host-only network IP, allowing you to access it
|
20
|
+
# via the IP. Host-only networks can talk to the host machine as well as
|
21
|
+
# any other machines on the same network, but cannot be accessed (through this
|
22
|
+
# network interface) by any external networks.
|
23
|
+
config.vm.network :hostonly, "192.168.33.10"
|
24
|
+
|
25
|
+
# Assign this VM to a bridged network, allowing you to connect directly to a
|
26
|
+
# network using the host's network device. This makes the VM appear as another
|
27
|
+
# physical device on your network.
|
28
|
+
# config.vm.network :bridged
|
29
|
+
|
30
|
+
# Forward a port from the guest to the host, which allows for outside
|
31
|
+
# computers to access the VM, whereas host only networking does not.
|
32
|
+
# config.vm.forward_port 80, 8080
|
33
|
+
|
34
|
+
# Share an additional folder to the guest VM. The first argument is
|
35
|
+
# an identifier, the second is the path on the guest to mount the
|
36
|
+
# folder, and the third is the path on the host to the actual folder.
|
37
|
+
# config.vm.share_folder "v-data", "/vagrant_data", "../data"
|
38
|
+
|
39
|
+
# Enable provisioning with Puppet stand alone. Puppet manifests
|
40
|
+
# are contained in a directory path relative to this Vagrantfile.
|
41
|
+
# You will need to create the manifests directory and a manifest in
|
42
|
+
# the file base.pp in the manifests_path directory.
|
43
|
+
#
|
44
|
+
# An example Puppet manifest to provision the message of the day:
|
45
|
+
#
|
46
|
+
# # group { "puppet":
|
47
|
+
# # ensure => "present",
|
48
|
+
# # }
|
49
|
+
# #
|
50
|
+
# # File { owner => 0, group => 0, mode => 0644 }
|
51
|
+
# #
|
52
|
+
# # file { '/etc/motd':
|
53
|
+
# # content => "Welcome to your Vagrant-built virtual machine!
|
54
|
+
# # Managed by Puppet.\n"
|
55
|
+
# # }
|
56
|
+
#
|
57
|
+
# config.vm.provision :puppet do |puppet|
|
58
|
+
# puppet.manifests_path = "manifests"
|
59
|
+
# puppet.manifest_file = "base.pp"
|
60
|
+
# end
|
61
|
+
|
62
|
+
# Enable provisioning with chef solo, specifying a cookbooks path, roles
|
63
|
+
# path, and data_bags path (all relative to this Vagrantfile), and adding
|
64
|
+
# some recipes and/or roles.
|
65
|
+
#
|
66
|
+
# config.vm.provision :chef_solo do |chef|
|
67
|
+
# chef.cookbooks_path = "../my-recipes/cookbooks"
|
68
|
+
# chef.roles_path = "../my-recipes/roles"
|
69
|
+
# chef.data_bags_path = "../my-recipes/data_bags"
|
70
|
+
# chef.add_recipe "mysql"
|
71
|
+
# chef.add_role "web"
|
72
|
+
#
|
73
|
+
# # You may also specify custom JSON attributes:
|
74
|
+
# chef.json = { :mysql_password => "foo" }
|
75
|
+
# end
|
76
|
+
|
77
|
+
# Enable provisioning with chef server, specifying the chef server URL,
|
78
|
+
# and the path to the validation key (relative to this Vagrantfile).
|
79
|
+
#
|
80
|
+
# The Opscode Platform uses HTTPS. Substitute your organization for
|
81
|
+
# ORGNAME in the URL and validation key.
|
82
|
+
#
|
83
|
+
# If you have your own Chef Server, use the appropriate URL, which may be
|
84
|
+
# HTTP instead of HTTPS depending on your configuration. Also change the
|
85
|
+
# validation key to validation.pem.
|
86
|
+
#
|
87
|
+
# config.vm.provision :chef_client do |chef|
|
88
|
+
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
|
89
|
+
# chef.validation_key_path = "ORGNAME-validator.pem"
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# If you're using the Opscode platform, your validator client is
|
93
|
+
# ORGNAME-validator, replacing ORGNAME with your organization name.
|
94
|
+
#
|
95
|
+
# IF you have your own Chef Server, the default validation client name is
|
96
|
+
# chef-validator, unless you changed the configuration.
|
97
|
+
#
|
98
|
+
# chef.validation_client_name = "ORGNAME-validator"
|
99
|
+
end
|
data/lib/toque.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
|
3
|
+
require 'toque/version'
|
4
|
+
require 'toque/helpers'
|
5
|
+
require 'toque/tasks'
|
6
|
+
require 'toque/chef'
|
7
|
+
|
8
|
+
module Toque
|
9
|
+
def self.load_into(configuration)
|
10
|
+
Toque::Helpers.load_into configuration
|
11
|
+
Toque::Tasks.load_into configuration
|
12
|
+
Toque::Chef.load_into configuration
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
if Capistrano::Configuration.instance
|
17
|
+
Toque.load_into Capistrano::Configuration.instance
|
18
|
+
end
|
data/lib/toque/chef.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Toque
|
4
|
+
|
5
|
+
# Tasks and method to interact with chef.
|
6
|
+
#
|
7
|
+
module Chef
|
8
|
+
def self.load_into(configuration)
|
9
|
+
configuration.load do
|
10
|
+
|
11
|
+
namespace :toque do
|
12
|
+
namespace :chef do
|
13
|
+
|
14
|
+
set_default :chef_omnibus_installer_url, 'http://www.opscode.com/chef/install.sh'
|
15
|
+
set_default :cookbooks_paths, %w(config/cookbooks vendor/cookbooks)
|
16
|
+
set_default :databags_path, 'config/databags'
|
17
|
+
set_default :chef_version, :latest
|
18
|
+
set_default :chef_debug, false
|
19
|
+
set_default :chef_solo, '/opt/chef/bin/chef-solo'
|
20
|
+
|
21
|
+
# Check if chef-solo installed on remote machine.
|
22
|
+
#
|
23
|
+
def installed?
|
24
|
+
!installed_version.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return installed chef-solo version.
|
28
|
+
#
|
29
|
+
def installed_version
|
30
|
+
capture("#{chef_solo} -v || true") =~ /Chef: (\d+\.\d+\.\d+)/ ? $1 : nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return path to chef solo executable.
|
34
|
+
#
|
35
|
+
def chef_solo
|
36
|
+
fetch(:chef_solo).to_s || 'chef-solo'
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return list of current recipes in run_list.
|
40
|
+
#
|
41
|
+
def recipes
|
42
|
+
Array fetch(:run_list)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return list of existing cookbook paths.
|
46
|
+
#
|
47
|
+
def cookbooks_paths
|
48
|
+
fetch(:cookbooks_paths).to_a.select { |path| File.exists? path }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Abort if no existing cookbook paths are setted.
|
52
|
+
#
|
53
|
+
def ensure_cookbooks!
|
54
|
+
raise 'No existing cookbook paths found.' if cookbooks_paths.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return existing databag path or nil if path does not exist.
|
58
|
+
#
|
59
|
+
def databags_path
|
60
|
+
File.exists?((path = fetch(:databags_path))) ? path : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Create and return omnibus installer command
|
64
|
+
#
|
65
|
+
def install_command
|
66
|
+
cmd = "#{top.sudo} bash"
|
67
|
+
cmd += " -s -- -v #{fetch :chef_version}" unless fetch(:chef_version) == :latest or fetch(:chef_version).nil?
|
68
|
+
cmd
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Tasks
|
73
|
+
#
|
74
|
+
|
75
|
+
desc 'Install chef via omnibus installed if not preset.'
|
76
|
+
task :check do
|
77
|
+
install unless installed?
|
78
|
+
end
|
79
|
+
|
80
|
+
desc 'Installs chef using omnibus installer.'
|
81
|
+
task :install do
|
82
|
+
require_curl
|
83
|
+
run "#{top.sudo} true && curl -L #{fetch :chef_omnibus_installer_url} | #{install_command}"
|
84
|
+
end
|
85
|
+
|
86
|
+
namespace :setup do
|
87
|
+
desc 'Upload local cookbook to remote server.'
|
88
|
+
task :cookbooks do
|
89
|
+
pwd!
|
90
|
+
|
91
|
+
tar = ::Tempfile.new("cookbooks.tar")
|
92
|
+
begin
|
93
|
+
tar.close
|
94
|
+
system "tar -cjf #{tar.path} #{cookbooks_paths.join(' ')} #{databags_path.to_s}"
|
95
|
+
upload tar.path, toque.pwd("cookbooks.tar"), :via => :scp
|
96
|
+
run "cd #{toque.pwd} && tar -xjf cookbooks.tar"
|
97
|
+
ensure
|
98
|
+
tar.unlink
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
desc 'Generate and upload chef solo script.'
|
103
|
+
task :script do
|
104
|
+
pwd!
|
105
|
+
|
106
|
+
cookbooks = cookbooks_paths.map { |p| %("#{pwd p}") }.join(', ')
|
107
|
+
solo = <<-HEREDOC
|
108
|
+
file_cache_path "#{pwd! 'cache'}"
|
109
|
+
cookbook_path [ #{cookbooks} ]
|
110
|
+
data_bag_path "#{pwd databags_path}"
|
111
|
+
HEREDOC
|
112
|
+
put solo, pwd("node.rb"), :via => :scp
|
113
|
+
end
|
114
|
+
|
115
|
+
desc 'Generate and upload node json configuration.'
|
116
|
+
task :configuration do
|
117
|
+
pwd!
|
118
|
+
|
119
|
+
attrs = variables.dup
|
120
|
+
attrs[:run_list] = recipes
|
121
|
+
put attrs.to_json, pwd("node.json"), :via => :scp
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
desc 'Run list of recipes from `:run_list` option.'
|
126
|
+
task :run_list do
|
127
|
+
ensure_cookbooks!
|
128
|
+
|
129
|
+
check
|
130
|
+
setup.cookbooks
|
131
|
+
setup.script
|
132
|
+
setup.configuration
|
133
|
+
|
134
|
+
logger.info "Now running #{recipes.join(', ')}"
|
135
|
+
|
136
|
+
sudo "#{chef_solo} -c #{pwd "node.rb"} -j #{pwd "node.json"}#{' -l debug' if fetch(:chef_debug)}"
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Toque
|
2
|
+
|
3
|
+
# Toque helpers
|
4
|
+
#
|
5
|
+
module Helpers
|
6
|
+
def self.load_into(configuration)
|
7
|
+
configuration.load do
|
8
|
+
|
9
|
+
namespace :toque do
|
10
|
+
|
11
|
+
# Set toque default variable.
|
12
|
+
#
|
13
|
+
def set_default(variable, *args, &block)
|
14
|
+
@_toque_variables ||= []
|
15
|
+
@_toque_overridden ||= []
|
16
|
+
@_toque_variables << variable
|
17
|
+
if exists? variable
|
18
|
+
@_toque_overridden << variable
|
19
|
+
else
|
20
|
+
set variable, *args, &block
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return toque remote working directory.
|
25
|
+
#
|
26
|
+
def pwd(*path)
|
27
|
+
File.join(fetch(:toque_pwd).to_s, *path.map(&:to_s))
|
28
|
+
end
|
29
|
+
set_default :toque_pwd, '/tmp/toque'
|
30
|
+
|
31
|
+
# Return toque remote working directory. Will be created remotely if not existing.
|
32
|
+
#
|
33
|
+
def pwd!(*path)
|
34
|
+
run "mkdir -p #{pwd = pwd(*path)}"
|
35
|
+
pwd
|
36
|
+
end
|
37
|
+
|
38
|
+
# Search if curl is present
|
39
|
+
#
|
40
|
+
def curl?
|
41
|
+
!(capture('curl || true') =~ /not found/)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Install curl if not present
|
45
|
+
#
|
46
|
+
def require_curl
|
47
|
+
sudo 'apt-get install --no-install-recommends -yq curl' unless curl?
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'List current toque configuration'
|
51
|
+
task :config do
|
52
|
+
@_toque_variables.sort_by(&:to_s).each do |name|
|
53
|
+
display_name = ":#{name},".ljust(30)
|
54
|
+
if variables[name].is_a?(Proc)
|
55
|
+
value = "<block>"
|
56
|
+
else
|
57
|
+
value = fetch(name).inspect
|
58
|
+
value = "#{value[0..40]}... (truncated)" if value.length > 40
|
59
|
+
end
|
60
|
+
overridden = @_toque_overridden.include?(name) ? " (overridden)" : ""
|
61
|
+
puts "set #{display_name} #{value}#{overridden}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/toque/tasks.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Toque
|
2
|
+
module Tasks
|
3
|
+
def self.load_into(configuration)
|
4
|
+
configuration.load do
|
5
|
+
|
6
|
+
namespace :toque do
|
7
|
+
|
8
|
+
# Run list of recipes. Install chef if not already preset.
|
9
|
+
#
|
10
|
+
def run_list(*recipes)
|
11
|
+
set :run_list, recipes
|
12
|
+
chef.run_list
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
set :application, 'awesomeium'
|
4
|
+
|
5
|
+
set :repository, '.'
|
6
|
+
set :scm, :none # not recommended in production
|
7
|
+
set :deploy_via, :copy
|
8
|
+
|
9
|
+
server '192.168.33.10', :web, :app, :db, :primary => true
|
10
|
+
|
11
|
+
set :user, 'vagrant'
|
12
|
+
set :password, 'vagrant' # not recommended in production
|
13
|
+
|
14
|
+
set :deploy_to, "/home/#{user}/#{application}"
|
15
|
+
|
16
|
+
set :use_sudo, false
|
17
|
+
default_run_options[:pty] = true
|
18
|
+
|
19
|
+
# Toque options
|
20
|
+
set :cookbooks_paths, %w(spec/config/cookbooks)
|
21
|
+
|
22
|
+
namespace :vagrant do
|
23
|
+
task :up do
|
24
|
+
Vagrant::Environment.new.cli 'up'
|
25
|
+
end
|
26
|
+
|
27
|
+
task :destroy do
|
28
|
+
Vagrant::Environment.new.cli 'destroy'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
task :spec do
|
33
|
+
toque.run_list "recipe[awesomeium]"
|
34
|
+
end
|
35
|
+
before 'spec', 'vagrant:up'
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'capistrano-spec'
|
2
|
+
require 'toque'
|
3
|
+
|
4
|
+
Dir[File.expand_path('spec/support/**/*.rb')].each {|f| require f}
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.include Capistrano::Spec::Matchers
|
8
|
+
config.include Capistrano::Spec::Helpers
|
9
|
+
|
10
|
+
config.order = "random"
|
11
|
+
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
# Only allow expect syntax
|
14
|
+
c.syntax = :expect
|
15
|
+
end
|
16
|
+
end
|
data/spec/spec_toque.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'vagrant'
|
3
|
+
|
4
|
+
describe Toque do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@vagrant = Vagrant::Environment.new
|
8
|
+
@vagrant.cli 'up'
|
9
|
+
|
10
|
+
@configuration = Capistrano::Configuration.new
|
11
|
+
Toque.load_into(@configuration)
|
12
|
+
|
13
|
+
@configuration.load do
|
14
|
+
|
15
|
+
server '192.168.33.10', :web, :app, :db, :primary => true
|
16
|
+
set :user, 'vagrant'
|
17
|
+
set :password, 'vagrant'
|
18
|
+
|
19
|
+
set :use_sudo, false
|
20
|
+
default_run_options[:pty] = true
|
21
|
+
|
22
|
+
# Toque options
|
23
|
+
set :cookbooks_paths, %w(spec/config/cookbooks)
|
24
|
+
set :chef_version, '10.24.0'
|
25
|
+
|
26
|
+
task :awesome! do
|
27
|
+
toque.run_list 'recipe[awesomeium]'
|
28
|
+
end
|
29
|
+
|
30
|
+
task :awesome_the_second! do
|
31
|
+
toque.run_list 'recipe[awesomeium::second]'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@configuration.sudo 'apt-get remove -yq curl'
|
36
|
+
@configuration.sudo 'apt-get autoremove -yq'
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should write an awesome file' do
|
40
|
+
@configuration.awesome!
|
41
|
+
|
42
|
+
# should have installed chef version
|
43
|
+
expect(@configuration.capture('/opt/chef/bin/chef-solo -v').strip).to be == 'Chef: 10.24.0'
|
44
|
+
|
45
|
+
# should have executed cookbook and created an awesome file
|
46
|
+
file_exists = @vagrant.primary_vm.channel.sudo 'ls /tmp/toque/awesome'
|
47
|
+
expect(file_exists).to be == 0
|
48
|
+
|
49
|
+
@configuration.awesome_the_second!
|
50
|
+
|
51
|
+
file_exists = @vagrant.primary_vm.channel.sudo 'ls /tmp/toque/awesome', :error_check => false
|
52
|
+
expect(file_exists).to_not be == 0
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Toque::Chef, 'loaded into capistrano' do
|
4
|
+
before do
|
5
|
+
@configuration = Capistrano::Configuration.new
|
6
|
+
@configuration.extend Capistrano::Spec::ConfigurationExtension
|
7
|
+
Toque.load_into(@configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should define default omnibus installer URL' do
|
11
|
+
expect(@configuration.fetch :chef_omnibus_installer_url).to be == 'http://www.opscode.com/chef/install.sh'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "defines toque:chef:install task" do
|
15
|
+
expect(@configuration.find_task 'toque:chef:install').to_not be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#installed?' do
|
19
|
+
it 'detect if chef-solo is not installed' do
|
20
|
+
expect(@configuration.toque.chef.installed?).to be_false
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'detect if chef-solo is installed' do
|
24
|
+
@configuration.stub_command '/opt/chef/bin/chef-solo -v || true', data: 'Chef: 11.4.0'
|
25
|
+
expect(@configuration.toque.chef.installed?).to be_true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#installed_version' do
|
30
|
+
it 'should fetch installed chef version' do
|
31
|
+
@configuration.stub_command '/opt/chef/bin/chef-solo -v || true', data: 'Chef: 11.4.0'
|
32
|
+
expect(@configuration.toque.chef.installed_version).to be == '11.4.0'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#cookbooks_paths' do
|
37
|
+
it 'should return existing cookbook paths' do
|
38
|
+
File.stub(:exists?).with('config/cookbooks').and_return true
|
39
|
+
File.stub(:exists?).with('vendor/cookbooks').and_return false
|
40
|
+
|
41
|
+
expect(@configuration.toque.chef.cookbooks_paths).to be == %w(config/cookbooks)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#ensure_cookbooks!' do
|
46
|
+
it 'should abort if no cookbook path exist' do
|
47
|
+
File.stub(:exists?).with('config/cookbooks').and_return false
|
48
|
+
File.stub(:exists?).with('vendor/cookbooks').and_return false
|
49
|
+
|
50
|
+
expect{ @configuration.toque.chef.ensure_cookbooks! }.to raise_error
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#databags_path' do
|
55
|
+
it 'should return path if exists' do
|
56
|
+
File.stub(:exists?).with('config/databags').and_return true
|
57
|
+
|
58
|
+
expect(@configuration.toque.chef.databags_path).to be == 'config/databags'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should return nit if path does not exists' do
|
62
|
+
File.stub(:exists?).with('config/databags').and_return false
|
63
|
+
|
64
|
+
expect(@configuration.toque.chef.databags_path).to be_nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#chef_solo' do
|
69
|
+
it 'should return path to chef solo executable' do
|
70
|
+
expect(@configuration.toque.chef.chef_solo).to be == '/opt/chef/bin/chef-solo'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should return path to custom chef solo executable' do
|
74
|
+
@configuration.set :chef_solo, 'chef-solo'
|
75
|
+
expect(@configuration.toque.chef.chef_solo).to be == 'chef-solo'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#upload_cookbooks' do
|
80
|
+
before do
|
81
|
+
File.stub(:exists?).and_return false
|
82
|
+
File.stub(:exists?).with('config/cookbooks').and_return true
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should create working dir' do
|
86
|
+
@configuration.toque.chef.setup.cookbooks
|
87
|
+
|
88
|
+
expect(@configuration).to have_run 'mkdir -p /tmp/toque'
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should upload cookbooks' do
|
92
|
+
@configuration.toque.chef.setup.cookbooks
|
93
|
+
|
94
|
+
expect(@configuration).to have_uploaded.to('/tmp/toque/cookbooks.tar')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should extract cookbooks on server' do
|
98
|
+
@configuration.toque.chef.setup.cookbooks
|
99
|
+
|
100
|
+
expect(@configuration).to have_run 'cd /tmp/toque && tar -xjf cookbooks.tar'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'toque:chef:install' do
|
105
|
+
|
106
|
+
it 'should install chef using omnibus installer' do
|
107
|
+
@configuration.toque.chef.install
|
108
|
+
expect(@configuration).to have_run("sudo -p 'sudo password: ' true && curl -L http://www.opscode.com/chef/install.sh | sudo -p 'sudo password: ' bash")
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with custom installer URL' do
|
112
|
+
before { @configuration.set :chef_omnibus_installer_url, 'http://mysrv.tld/inst.sh' }
|
113
|
+
|
114
|
+
it 'should install chef using custom omnibus installer' do
|
115
|
+
@configuration.toque.chef.install
|
116
|
+
expect(@configuration).to have_run("sudo -p 'sudo password: ' true && curl -L http://mysrv.tld/inst.sh | sudo -p 'sudo password: ' bash")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with specific chef version' do
|
121
|
+
before { @configuration.set :chef_version, '10.24.0' }
|
122
|
+
|
123
|
+
it 'should install chef using custom omnibus installer' do
|
124
|
+
@configuration.toque.chef.install
|
125
|
+
expect(@configuration).to have_run("sudo -p 'sudo password: ' true && curl -L http://www.opscode.com/chef/install.sh | sudo -p 'sudo password: ' bash -s -- -v 10.24.0")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Toque::Helpers, 'loaded into capistrano' do
|
4
|
+
before do
|
5
|
+
@configuration = Capistrano::Configuration.new
|
6
|
+
@configuration.extend Capistrano::Spec::ConfigurationExtension
|
7
|
+
Toque.load_into(@configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#pwd' do
|
11
|
+
it 'return toque working dir' do
|
12
|
+
expect(@configuration.toque.pwd).to be == '/tmp/toque'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'return custom path if set' do
|
16
|
+
@configuration.set :toque_pwd, '/tmp/custom_path'
|
17
|
+
expect(@configuration.toque.pwd).to be == '/tmp/custom_path'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#pwd!' do
|
22
|
+
it 'return create remote working dir' do
|
23
|
+
@configuration.toque.pwd!
|
24
|
+
expect(@configuration).to have_run 'mkdir -p /tmp/toque'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#curl?' do
|
29
|
+
it 'return true if curl exists' do
|
30
|
+
@configuration.stub_command 'curl || true', data: "curl: try 'curl --help' or 'curl --manual' for more information"
|
31
|
+
expect(@configuration.toque.curl?).to be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'return false if curl is missing' do
|
35
|
+
@configuration.stub_command 'curl || true', data: "sh: command not found"
|
36
|
+
expect(@configuration.toque.curl?).to be_false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/toque.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'toque/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'toque'
|
8
|
+
spec.version = Toque::VERSION
|
9
|
+
spec.authors = ['Jan Graichen']
|
10
|
+
spec.email = %w(jg@altimos.de)
|
11
|
+
spec.description = %q{Toque: Cap of a Chef. Integrate Chef into Capistrano.}
|
12
|
+
spec.summary = %q{Toque: Cap of a Chef. Integrate Chef into Capistrano.}
|
13
|
+
spec.homepage = 'https://github.com/jgraichen/toque'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = %w(lib)
|
20
|
+
|
21
|
+
spec.add_dependency 'capistrano'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: toque
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan Graichen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: capistrano
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: 'Toque: Cap of a Chef. Integrate Chef into Capistrano.'
|
28
|
+
email:
|
29
|
+
- jg@altimos.de
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- .travis.yml
|
36
|
+
- Capfile
|
37
|
+
- Gemfile
|
38
|
+
- LICENSE.txt
|
39
|
+
- README.md
|
40
|
+
- Rakefile
|
41
|
+
- Vagrantfile
|
42
|
+
- lib/toque.rb
|
43
|
+
- lib/toque/chef.rb
|
44
|
+
- lib/toque/helpers.rb
|
45
|
+
- lib/toque/tasks.rb
|
46
|
+
- lib/toque/version.rb
|
47
|
+
- spec/config/cookbooks/awesomeium/recipes/default.rb
|
48
|
+
- spec/config/cookbooks/awesomeium/recipes/second.rb
|
49
|
+
- spec/config/deploy.rb
|
50
|
+
- spec/spec_helper.rb
|
51
|
+
- spec/spec_toque.rb
|
52
|
+
- spec/toque/chef_spec.rb
|
53
|
+
- spec/toque/helpers_spec.rb
|
54
|
+
- toque.gemspec
|
55
|
+
homepage: https://github.com/jgraichen/toque
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.0.3
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: 'Toque: Cap of a Chef. Integrate Chef into Capistrano.'
|
79
|
+
test_files:
|
80
|
+
- spec/config/cookbooks/awesomeium/recipes/default.rb
|
81
|
+
- spec/config/cookbooks/awesomeium/recipes/second.rb
|
82
|
+
- spec/config/deploy.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
- spec/spec_toque.rb
|
85
|
+
- spec/toque/chef_spec.rb
|
86
|
+
- spec/toque/helpers_spec.rb
|