fry-cook 0.2.0.beta1
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/LICENSE +26 -0
- data/README.md +135 -0
- data/bin/fry-cook +69 -0
- data/lib/fry-cook.rb +3 -0
- data/lib/fry_cook/.version.rb.swp +0 -0
- data/lib/fry_cook/server.rb +24 -0
- data/lib/fry_cook/vagrant_plugin.rb +32 -0
- data/lib/fry_cook/vagrant_plugin/config.rb +38 -0
- data/lib/fry_cook/vagrant_plugin/hooks.rb +99 -0
- data/lib/fry_cook/version.rb +3 -0
- data/lib/fry_cook/work_tree.rb +184 -0
- metadata +138 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6bb59c77a0a41152f10c174fafcd5af5b0e2ecc2
|
4
|
+
data.tar.gz: 999b3e34abaaa77b593da933634dae1b28ac6008
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63627e5591cda4bb4646b2267fa979378bd41600ac2d4bc90bb7123b12495dbdc1732fa2ee70b4605ddaa0e466c6f549f26265e89fa4b24aabf9dbb14c6c5aff
|
7
|
+
data.tar.gz: ef31001c347c70f867827d59b6b62e24d4d5cbcbecc82c30403a55acfa96968c8b6c0459ef65ddee302d7920be2e4025005059a3d1bb43cb94b3246af8a6262e
|
data/LICENSE
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Copyright (c) 2013, Graham Batty
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
10
|
+
this list of conditions and the following disclaimer in the documentation
|
11
|
+
and/or other materials provided with the distribution.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
15
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
16
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
17
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
18
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
19
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
20
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
21
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
22
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
23
|
+
|
24
|
+
The views and conclusions contained in the software and documentation are those
|
25
|
+
of the authors and should not be interpreted as representing official policies,
|
26
|
+
either expressed or implied, of the Project.
|
data/README.md
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# Fry Cook
|
2
|
+
|
3
|
+
*Not quite a chef yet, the fry cook knows only one menu.*
|
4
|
+
|
5
|
+
Fry Cook is a chef server that is designed to be used with a
|
6
|
+
git repository (or working directory) that is to be treated as
|
7
|
+
a definitive source of truth. It is based on chef zero with
|
8
|
+
the Chef local filesystem data source, but has some modifications
|
9
|
+
on top of that.
|
10
|
+
|
11
|
+
## Standalone Usage
|
12
|
+
|
13
|
+
Fry Cook can be used as a standalone server just like a normal
|
14
|
+
chef server. All the caveats of using this as a chef server apply
|
15
|
+
as using [https://github.com/opscode/chef-zero](Chef-Zero). It
|
16
|
+
doesn't authenticate anything. This is because it uses chef-zero
|
17
|
+
to do most of the work.
|
18
|
+
|
19
|
+
However, it can be useful in ways that chef-zero is not. Namely,
|
20
|
+
it can seed your cookbooks from a git repository and even build
|
21
|
+
those cookbooks from a Berksfile. It will also convert all .rb files
|
22
|
+
to .json files as expected by the chef server. This is all a much
|
23
|
+
faster option than setting up a chef server and uploading everything
|
24
|
+
to it.
|
25
|
+
|
26
|
+
If you run fry-cook --help you will see this:
|
27
|
+
|
28
|
+
```bash
|
29
|
+
Usage: fry-cook [ARGS]
|
30
|
+
-H, --host HOST Host to bind to (default: 127.0.0.1)
|
31
|
+
-p, --port PORT Port to listen on (default: 8889)
|
32
|
+
--socket PATH Unix socket path to listen on
|
33
|
+
-d, --daemon Run as a daemon process
|
34
|
+
--path PATH A working copy of the chef-repo to build from (default: .)
|
35
|
+
--remote GIT_REMOTE A git remote to build from
|
36
|
+
--track GIT_REF The branch (or other ref) to track in the git remote (default: master)
|
37
|
+
--storage-path PATH Where to store the files the server works from (default: {working_path}/.fry-cook
|
38
|
+
-l, --log-level LEVEL Set the output log level
|
39
|
+
-h, --help Show this message
|
40
|
+
--version Show version
|
41
|
+
```
|
42
|
+
|
43
|
+
The arguments that differ from chef-zero are the path, remote,
|
44
|
+
track, and storage-path options. Fry-cook effectively has two modes,
|
45
|
+
depending on where you want to build your working chef server from:
|
46
|
+
|
47
|
+
### From a Local Path
|
48
|
+
|
49
|
+
You can build from a local path, like a working copy of a git repository. This
|
50
|
+
is great for development or using as a vagrant plugin (below). To use this mode you
|
51
|
+
can simply pass nothing special and it will assume the current working directory
|
52
|
+
is the local path you want to work from. To explicitly specify a path, you can
|
53
|
+
pass the --path option.
|
54
|
+
|
55
|
+
You should not pass the remote or track arguments for this mode. They put it
|
56
|
+
into the git mode, described in the next section.
|
57
|
+
|
58
|
+
Examples:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
fry-cook -d # The current working directory should be a chef repo.
|
62
|
+
```
|
63
|
+
|
64
|
+
```bash
|
65
|
+
fry-cook -d --path /var/lib/chef # Build from /var/lib/chef.
|
66
|
+
```
|
67
|
+
|
68
|
+
### From a Git Repository or Remote
|
69
|
+
|
70
|
+
If you want to build your chef server configuration from a remote git repository,
|
71
|
+
say on github or some other central repository, you can use the remote and track
|
72
|
+
arguments. Remote is a git remote, such as ```git@github.com:stormbrew/fry-cook.git```.
|
73
|
+
Track is the reference within the repository, which could be a branch or tag. It
|
74
|
+
defaults to the master branch.
|
75
|
+
|
76
|
+
Examples:
|
77
|
+
|
78
|
+
```bash
|
79
|
+
fry-cook -d --remote git@github.com:stormbrew/mything.git # Master branch of mything on github.
|
80
|
+
```
|
81
|
+
|
82
|
+
```bash
|
83
|
+
fry-cook -d --remote git@github.com:stormbew/mything.git --track production # Production branch of mything on github.
|
84
|
+
```
|
85
|
+
|
86
|
+
### Storage Path
|
87
|
+
|
88
|
+
The storage path is where fry-cook builds into. Every time it builds from
|
89
|
+
the source it builds into a fresh directory. It also keeps the uploaded node
|
90
|
+
json files in here in a way that persists across rebuilds.
|
91
|
+
|
92
|
+
This setup is designed to allow rebuilding from the repository on a live
|
93
|
+
server without turning it off. This feature will be added later.
|
94
|
+
|
95
|
+
Most of the time you'll want to leave this as the default, which will
|
96
|
+
put it in a .fry-cook directory in the current working directory.
|
97
|
+
|
98
|
+
## Using With Vagrant
|
99
|
+
|
100
|
+
If you install Fry Cook as a vagrant plugin you can use it in much the same
|
101
|
+
way as the vagrant-chef-zero plugin. You don't need to install a separate
|
102
|
+
plugin to do this, just ```vagrant plugin install fry-cook```. From there
|
103
|
+
you can add it to your Vagrantfile as follows:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
Vagrant.configure("2") do |config|
|
107
|
+
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
|
108
|
+
config.omnibus.chef_version = "11.8.0"
|
109
|
+
|
110
|
+
## For a local repository
|
111
|
+
config.fry_cook.repo_path = "."
|
112
|
+
|
113
|
+
## For a remote repository
|
114
|
+
# config.fry_cook.repo_git_remote = "git@github.com:stormbrew/stuff.git"
|
115
|
+
# config.fry_cook.repo_git_ref = "master" # optional
|
116
|
+
|
117
|
+
## If you have multiple vms in your vagrantfile and you
|
118
|
+
## want them to use a different chef server, you can set
|
119
|
+
## them up to use different 'prefixes' and different server
|
120
|
+
## ports (default is 18999) to keep them separate:
|
121
|
+
# config.fry_cook.prefix = "config1"
|
122
|
+
# config.fry_cook.server_port = 9432
|
123
|
+
|
124
|
+
config.vm.provision :chef_client do |chef_client|
|
125
|
+
chef_client.add_recipe "apt"
|
126
|
+
chef_client.add_recipe "nginx"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
## Future Work
|
132
|
+
|
133
|
+
This really needs more testing infrastructure (or any at all). It also needs
|
134
|
+
a command to rebuild the repo without restarting the server, which is not
|
135
|
+
terribly difficult.
|
data/bin/fry-cook
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "fry_cook/version"
|
4
|
+
require "chef_zero/version"
|
5
|
+
require "fry_cook/server"
|
6
|
+
require "optparse"
|
7
|
+
|
8
|
+
options = {}
|
9
|
+
fry_options = {}
|
10
|
+
|
11
|
+
OptionParser.new do |opts|
|
12
|
+
opts.banner = "Usage: fry-cook [ARGS]"
|
13
|
+
|
14
|
+
opts.on("-H", "--host HOST", "Host to bind to (default: 127.0.0.1)") do |value|
|
15
|
+
options[:host] = value
|
16
|
+
end
|
17
|
+
opts.on("-p", "--port PORT", Integer, "Port to listen on (default: 8889)") do |value|
|
18
|
+
options[:port] = value
|
19
|
+
end
|
20
|
+
opts.on("--socket PATH", String, "Unix socket path to listen on") do |value|
|
21
|
+
options[:socket] = value
|
22
|
+
end
|
23
|
+
opts.on("-d", "--daemon", "Run as a daemon process") do |value|
|
24
|
+
options[:daemon] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on("--path PATH", String, "A working copy of the chef-repo to build from (default: .)") do |value|
|
28
|
+
fry_options[:working_path] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on("--remote GIT_REMOTE", String, "A git remote to build from") do |value|
|
32
|
+
fry_options[:git_repo_remote] = value
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("--track GIT_REF", String, "The branch (or other ref) to track in the git remote (default: master)") do |value|
|
36
|
+
fry_options[:git_ref] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
opts.on("--storage-path PATH", String, "Where to store the files the server works from (default: {working_path}/.fry-cook") do |value|
|
40
|
+
fry_options[:storage_path] = value
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-l", "--log-level LEVEL", "Set the output log level") do |value|
|
44
|
+
options[:log_level] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
48
|
+
puts opts
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
opts.on_tail("--version", "Show version") do
|
53
|
+
puts "fry-cook-#{FryCook::VERSION}, chef-zero-#{ChefZero::VERSION}"
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end.parse!
|
57
|
+
|
58
|
+
server = FryCook::Server.new(options, fry_options)
|
59
|
+
|
60
|
+
if options[:daemon]
|
61
|
+
unless Process.respond_to?('daemon')
|
62
|
+
abort 'Process.deamon requires Ruby >= 1.9'
|
63
|
+
else
|
64
|
+
Process.daemon(true)
|
65
|
+
server.start(:publish => true)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
server.start(:publish => true)
|
69
|
+
end
|
data/lib/fry-cook.rb
ADDED
Binary file
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'chef_zero/server'
|
2
|
+
require 'fry_cook/work_tree'
|
3
|
+
|
4
|
+
module FryCook
|
5
|
+
class Server < ChefZero::Server
|
6
|
+
def initialize(chef_options, fry_options)
|
7
|
+
@work_tree = WorkTree.new(fry_options)
|
8
|
+
@work_tree.build
|
9
|
+
|
10
|
+
Chef::Config.node_path = @work_tree.node_path
|
11
|
+
Chef::Config.cookbook_path = @work_tree.cookbook_path
|
12
|
+
Chef::Config.role_path = @work_tree.role_path
|
13
|
+
Chef::Config.data_bag_path = @work_tree.data_bag_path
|
14
|
+
Chef::Config.environment_path = @work_tree.environment_path
|
15
|
+
|
16
|
+
data_store = Chef::ChefFS::ChefFSDataStore.new(
|
17
|
+
Chef::ChefFS::Config.new(Chef::Config).local_fs
|
18
|
+
)
|
19
|
+
chef_options[:data_store] = data_store
|
20
|
+
|
21
|
+
super(chef_options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module FryCook
|
2
|
+
module VagrantPlugin
|
3
|
+
class Plugin < ::Vagrant.plugin("2")
|
4
|
+
name "fry-cook"
|
5
|
+
description <<-DESC
|
6
|
+
Auto-configurator for fry cook for the chef_client provisioner.
|
7
|
+
DESC
|
8
|
+
|
9
|
+
config(:fry_cook) do
|
10
|
+
require File.expand_path("../vagrant_plugin/config", __FILE__)
|
11
|
+
Config
|
12
|
+
end
|
13
|
+
|
14
|
+
action_hook(:fry_cook_reconfig) do |hook|
|
15
|
+
chain = Vagrant::Action::Builder.new.tap do |b|
|
16
|
+
require File.expand_path("../vagrant_plugin/hooks", __FILE__)
|
17
|
+
b.use Hooks::ConfigureServerUrl
|
18
|
+
end
|
19
|
+
hook.before(::Vagrant::Action::Builtin::ConfigValidate, chain)
|
20
|
+
end
|
21
|
+
%w{up reload provision}.each do |action|
|
22
|
+
action_hook(:"fry_cook_#{action}", :"machine_action_#{action}") do |hook|
|
23
|
+
chain = Vagrant::Action::Builder.new.tap do |b|
|
24
|
+
require File.expand_path("../vagrant_plugin/hooks", __FILE__)
|
25
|
+
b.use Hooks::StartServer
|
26
|
+
end
|
27
|
+
hook.before(::Vagrant::Action::Builtin::Provision, chain)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module FryCook
|
2
|
+
module VagrantPlugin
|
3
|
+
class Config < Vagrant.plugin("2", :config)
|
4
|
+
def self.config_attr(name, default = nil, &block)
|
5
|
+
@config_attrs ||= {}
|
6
|
+
@config_attrs[name] = block || default
|
7
|
+
attr_accessor name
|
8
|
+
end
|
9
|
+
def self.config_attrs
|
10
|
+
@config_attrs || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
config_attr :repo_path
|
14
|
+
config_attr :repo_git_remote
|
15
|
+
config_attr :repo_git_track, "master"
|
16
|
+
config_attr :prefix, "default"
|
17
|
+
config_attr :server_port, 18998
|
18
|
+
|
19
|
+
def initialize()
|
20
|
+
self.class.config_attrs.each do |config_attr, default|
|
21
|
+
instance_variable_set(:"@#{config_attr}", UNSET_VALUE)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def finalize!
|
26
|
+
self.class.config_attrs.each do |config_attr, default|
|
27
|
+
if instance_variable_get(:"@#{config_attr}") == UNSET_VALUE
|
28
|
+
if default.respond_to? :call
|
29
|
+
default = default.call
|
30
|
+
end
|
31
|
+
instance_variable_set(:"@#{config_attr}", default)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
{}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'openssl'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'fry_cook/server'
|
5
|
+
|
6
|
+
module FryCook::VagrantPlugin::Hooks
|
7
|
+
class Base
|
8
|
+
def initialize(app, env)
|
9
|
+
@app = app
|
10
|
+
@env = env
|
11
|
+
end
|
12
|
+
|
13
|
+
def config
|
14
|
+
@env[:machine].config.fry_cook
|
15
|
+
end
|
16
|
+
|
17
|
+
def client_config
|
18
|
+
@env[:machine].config.vm.provisioners.select {|prov| prov.name == :chef_client }
|
19
|
+
end
|
20
|
+
|
21
|
+
def active?
|
22
|
+
client_config.any? && config.repo_path || config.repo_git_remote
|
23
|
+
end
|
24
|
+
|
25
|
+
def host_ip_address
|
26
|
+
# This gets the first ip address in a private range. With virtualbox,
|
27
|
+
# at least, things seem to be routed so that the vm can connect to this
|
28
|
+
# IP even if it has nothing to do with vagrant or virtualbox. This may not
|
29
|
+
# be an entirely safe assumption, but vagrant doesn't provide any kind of
|
30
|
+
# better way to obtain a canonical reachable address as far as I can tell.
|
31
|
+
Socket.ip_address_list.detect{|intf| intf.ipv4_private?}.ip_address
|
32
|
+
end
|
33
|
+
|
34
|
+
def call(env)
|
35
|
+
@env = env
|
36
|
+
if active?
|
37
|
+
do_action(env)
|
38
|
+
end
|
39
|
+
@app.call(env)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class ConfigureServerUrl < Base
|
44
|
+
def get_fake_key_path
|
45
|
+
fake_directory = File.join(Dir.tmpdir, "fake_key")
|
46
|
+
fake_key_path = File.join(fake_directory, "fake.pem")
|
47
|
+
|
48
|
+
if !File.exists?(fake_key_path)
|
49
|
+
fake_key = OpenSSL::PKey::RSA.new(2048)
|
50
|
+
Dir.mkdir(fake_directory) unless File.exists?(fake_directory)
|
51
|
+
File.open(fake_key_path,"w") {|f| f.puts fake_key }
|
52
|
+
end
|
53
|
+
|
54
|
+
fake_key_path
|
55
|
+
end
|
56
|
+
|
57
|
+
def do_action(env)
|
58
|
+
client_config.each do |client|
|
59
|
+
fake_key = get_fake_key_path
|
60
|
+
|
61
|
+
if !client.config.instance_variable_get(:"@chef_server_url")
|
62
|
+
client.config.instance_variable_set(:"@chef_server_url", "http://#{host_ip_address}:#{config.server_port}/")
|
63
|
+
end
|
64
|
+
if !client.config.instance_variable_get(:@validation_key_path)
|
65
|
+
client.config.instance_variable_set(:@validation_key_path, fake_key)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class StartServer < Base
|
72
|
+
def do_action(env)
|
73
|
+
# Note: This is not thread safe, but it may not entirely
|
74
|
+
# be able to be. I don't think vagrant would run these in
|
75
|
+
# parallel at the moment at any rate.
|
76
|
+
if !defined? @@running
|
77
|
+
server_options = {
|
78
|
+
host: host_ip_address,
|
79
|
+
port: config.server_port,
|
80
|
+
daemon: false,
|
81
|
+
}
|
82
|
+
fry_options = {
|
83
|
+
storage_path: ".vagrant/fry-cook/#{config.prefix}",
|
84
|
+
}
|
85
|
+
case
|
86
|
+
when config.repo_path
|
87
|
+
fry_options[:working_path] = config.repo_path
|
88
|
+
when config.repo_git_remote
|
89
|
+
fry_options[:git_repo_remote] = config.repo_git_remote
|
90
|
+
fry_options[:git_ref] = config.repo_git_track
|
91
|
+
end
|
92
|
+
|
93
|
+
server = FryCook::Server.new(server_options, fry_options)
|
94
|
+
server.start_background
|
95
|
+
@@running = true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
require 'chef/chef_fs/chef_fs_data_store'
|
2
|
+
require 'chef/chef_fs/config'
|
3
|
+
require 'chef/role'
|
4
|
+
require 'chef/environment'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'json'
|
7
|
+
require 'berkshelf'
|
8
|
+
|
9
|
+
module FryCook
|
10
|
+
class WorkTree
|
11
|
+
attr_reader :storage_path
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
if options[:storage_path] && File.file?("#{options[:storage_path]}/config.json")
|
15
|
+
existing_config = JSON.load(File.read("#{options[:storage_path]}/config.json"), nil, symbolize_names: true)
|
16
|
+
options = existing_config.merge(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
if options[:git_repo_remote]
|
20
|
+
@mode = :git
|
21
|
+
@git_remote = options[:git_repo_remote]
|
22
|
+
@git_ref = options[:git_ref] || 'master'
|
23
|
+
@storage_path = options[:storage_path] || raise("Must specify storage path for git mode.")
|
24
|
+
@git_repo = "#{@storage_path}/git-repo"
|
25
|
+
else
|
26
|
+
@mode = :path
|
27
|
+
@working_path = options[:working_path] || '.'
|
28
|
+
@storage_path = options[:storage_path] || "#{@working_path}/.fry-cook"
|
29
|
+
end
|
30
|
+
|
31
|
+
FileUtils.mkdir_p(@storage_path)
|
32
|
+
FileUtils.mkdir_p("#{@storage_path}/nodes")
|
33
|
+
|
34
|
+
File.write("#{@storage_path}/config.json", JSON.dump(options))
|
35
|
+
end
|
36
|
+
|
37
|
+
def node_path
|
38
|
+
"#{storage_path}/nodes"
|
39
|
+
end
|
40
|
+
def cookbook_path
|
41
|
+
"#{storage_path}/current/cookbooks"
|
42
|
+
end
|
43
|
+
def role_path
|
44
|
+
"#{storage_path}/current/roles"
|
45
|
+
end
|
46
|
+
def data_bag_path
|
47
|
+
"#{storage_path}/current/data_bags"
|
48
|
+
end
|
49
|
+
def environment_path
|
50
|
+
"#{storage_path}/current/environments"
|
51
|
+
end
|
52
|
+
|
53
|
+
def cmd(cmd)
|
54
|
+
res = IO.popen(cmd, :err=>[:child, :out]) do |p|
|
55
|
+
p.readlines.collect {|line| line.chomp }
|
56
|
+
end
|
57
|
+
if !$?.success?
|
58
|
+
raise("Command #{cmd.join(' ')} failed:\n#{res.join("\n")}")
|
59
|
+
end
|
60
|
+
res
|
61
|
+
end
|
62
|
+
def git(*cmd)
|
63
|
+
cmd(["git", "--git-dir", @git_repo, *cmd])
|
64
|
+
end
|
65
|
+
def git_in(work_path, *cmd)
|
66
|
+
FileUtils.mkdir_p(work_path)
|
67
|
+
git("--work-tree", work_path, *cmd)
|
68
|
+
end
|
69
|
+
|
70
|
+
def git_refresh
|
71
|
+
if !File.directory? @git_repo
|
72
|
+
git("clone", "--bare", @git_remote, @git_repo)
|
73
|
+
end
|
74
|
+
git("fetch", '-f', @git_remote, 'refs/heads/*:refs/heads/*')
|
75
|
+
end
|
76
|
+
|
77
|
+
def pull_source
|
78
|
+
case @mode
|
79
|
+
when :git
|
80
|
+
git_refresh
|
81
|
+
new_ref = git("rev-parse", @git_ref)
|
82
|
+
if new_ref.length == 0
|
83
|
+
raise("Didn't get a valid ref for #{@git_ref}")
|
84
|
+
end
|
85
|
+
new_version = "build-" + new_ref[0]
|
86
|
+
source_path = "#{@storage_path}/#{new_version}/chef_repo"
|
87
|
+
if !File.directory? source_path
|
88
|
+
git_in(source_path, "checkout", "-f", @git_ref)
|
89
|
+
end
|
90
|
+
when :path
|
91
|
+
new_version = "build-#{Time.now.to_i}"
|
92
|
+
source_path = @working_path
|
93
|
+
end
|
94
|
+
return new_version, source_path
|
95
|
+
end
|
96
|
+
|
97
|
+
def install_cookbooks(new_version, source_path, install_path)
|
98
|
+
case
|
99
|
+
when File.file?("#{source_path}/Berksfile")
|
100
|
+
# Note: Doesn't work properly without being in the directory of the berksfile.
|
101
|
+
Dir.chdir(source_path) do
|
102
|
+
berksfile = Berkshelf::Berksfile.from_file("Berksfile")
|
103
|
+
berksfile.vendor("#{install_path}/cookbooks")
|
104
|
+
end
|
105
|
+
when File.directory?("#{source_path}/cookbooks")
|
106
|
+
FileUtils.cp_r("#{source_path}/cookbooks", "#{install_path}/cookbooks")
|
107
|
+
else
|
108
|
+
raise("No cookbooks found.")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def install_environments(new_version, source_path, install_path)
|
113
|
+
FileUtils.mkdir_p("#{install_path}/environments")
|
114
|
+
environments = Dir.glob("#{source_path}/environments/*.json")
|
115
|
+
if !environments.empty?
|
116
|
+
FileUtils.cp(environments, "#{install_path}/environments")
|
117
|
+
end
|
118
|
+
Dir.glob("#{source_path}/environments/*.rb").each do |environment|
|
119
|
+
environment_obj = Chef::Environment.new
|
120
|
+
environment_obj.name File.basename(environment, ".rb")
|
121
|
+
environment_obj.from_file(environment)
|
122
|
+
File.write("#{install_path}/environments/#{File.basename(environment, ".rb")}.json", environment_obj.to_json)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def install_roles(new_version, source_path, install_path)
|
127
|
+
FileUtils.mkdir_p("#{install_path}/roles")
|
128
|
+
roles = Dir.glob("#{source_path}/roles/*.json")
|
129
|
+
if !roles.empty?
|
130
|
+
FileUtils.cp(roles, "#{install_path}/roles")
|
131
|
+
end
|
132
|
+
Dir.glob("#{source_path}/roles/*.rb").each do |role|
|
133
|
+
role_obj = Chef::Role.new
|
134
|
+
role_obj.name File.basename(role, ".rb")
|
135
|
+
role_obj.from_file(role)
|
136
|
+
File.write("#{install_path}/roles/#{File.basename(role, ".rb")}.json", role_obj.to_json)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def install_data_bags(new_version, source_path, install_path)
|
141
|
+
FileUtils.mkdir_p("#{install_path}/data_bags")
|
142
|
+
Dir.glob("#{source_path}/data_bags/*").each do |data_bag|
|
143
|
+
next if !File.directory? data_bag
|
144
|
+
|
145
|
+
data_bag_name = File.basename(data_bag)
|
146
|
+
FileUtils.mkdir_p("#{install_path}/data_bags/#{data_bag_name}")
|
147
|
+
items = Dir.glob("#{data_bag}/*.json")
|
148
|
+
if !items.empty?
|
149
|
+
FileUtils.cp(items, "#{install_path}/data_bags/#{data_bag_name}")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def build(force = false)
|
155
|
+
current_link = "#{@storage_path}/current"
|
156
|
+
old_version = File.symlink?(current_link) && File.readlink(current_link)
|
157
|
+
|
158
|
+
new_version, source_path = pull_source()
|
159
|
+
install_path = File.expand_path("#{@storage_path}/#{new_version}")
|
160
|
+
|
161
|
+
if force || new_version != old_version
|
162
|
+
begin
|
163
|
+
install_cookbooks(new_version, source_path, install_path)
|
164
|
+
install_environments(new_version, source_path, install_path)
|
165
|
+
install_roles(new_version, source_path, install_path)
|
166
|
+
install_data_bags(new_version, source_path, install_path)
|
167
|
+
rescue
|
168
|
+
# Clean up the probably broken deploy install path if it got created.
|
169
|
+
# We don't care why it failed, so we pass the buck up.
|
170
|
+
FileUtils.rmdir(install_path) if File.directory?(install_path)
|
171
|
+
raise
|
172
|
+
end
|
173
|
+
|
174
|
+
tmplink = current_link + ".#{Process.pid}.lnk"
|
175
|
+
FileUtils.ln_s(new_version, tmplink)
|
176
|
+
File.rename(tmplink, current_link)
|
177
|
+
|
178
|
+
if old_version && File.directory?("#{@storage_path}/#{old_version}")
|
179
|
+
FileUtils.rm_rf("#{@storage_path}/#{old_version}")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
metadata
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fry-cook
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0.beta1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Graham Batty
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chef
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '11'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '11'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: chef-zero
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.7'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.7'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: berkshelf
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0.beta7
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0.beta7
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-core
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.13.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.13.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-expectations
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.13.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.13.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-mocks
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.13.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.13.0
|
97
|
+
description: Not quite a chef yet, the fry cook knows only one menu.
|
98
|
+
email: graham@stormbrew.ca
|
99
|
+
executables:
|
100
|
+
- fry-cook
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- bin/fry-cook
|
105
|
+
- lib/fry_cook/version.rb
|
106
|
+
- lib/fry_cook/vagrant_plugin/hooks.rb
|
107
|
+
- lib/fry_cook/vagrant_plugin/config.rb
|
108
|
+
- lib/fry_cook/work_tree.rb
|
109
|
+
- lib/fry_cook/server.rb
|
110
|
+
- lib/fry_cook/vagrant_plugin.rb
|
111
|
+
- lib/fry_cook/.version.rb.swp
|
112
|
+
- lib/fry-cook.rb
|
113
|
+
- LICENSE
|
114
|
+
- README.md
|
115
|
+
homepage: https://www.github.com/stormbrew/fry-cook
|
116
|
+
licenses: []
|
117
|
+
metadata: {}
|
118
|
+
post_install_message:
|
119
|
+
rdoc_options: []
|
120
|
+
require_paths:
|
121
|
+
- lib
|
122
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>'
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.3.1
|
132
|
+
requirements: []
|
133
|
+
rubyforge_project:
|
134
|
+
rubygems_version: 2.0.3
|
135
|
+
signing_key:
|
136
|
+
specification_version: 4
|
137
|
+
summary: Not quite a chef yet, the fry cook knows only one menu.
|
138
|
+
test_files: []
|