buckknife 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/HISTORY.md +8 -0
- data/README.md +65 -0
- data/Rakefile +27 -0
- data/buckknife.gemspec +31 -0
- data/lib/buckknife.rb +44 -0
- data/lib/buckknife/command.rb +33 -0
- data/lib/buckknife/commands/add_role.rb +13 -0
- data/lib/buckknife/commands/base.rb +24 -0
- data/lib/buckknife/commands/bootstrap.rb +28 -0
- data/lib/buckknife/commands/capistrano.rb +46 -0
- data/lib/buckknife/commands/create.rb +42 -0
- data/lib/buckknife/commands/euca_create.rb +60 -0
- data/lib/buckknife/commands/rackspace_create.rb +58 -0
- data/lib/buckknife/commands/run_client.rb +49 -0
- data/lib/buckknife/data_accessor.rb +29 -0
- data/lib/buckknife/environment.rb +16 -0
- data/lib/buckknife/helper.rb +39 -0
- data/lib/buckknife/knife_helper.rb +22 -0
- data/lib/buckknife/node.rb +30 -0
- data/lib/buckknife/project.rb +80 -0
- data/lib/buckknife/templates/deploy_environments.rb.erb +85 -0
- data/lib/buckknife/templates/project.json.erb +75 -0
- data/lib/buckknife/version.rb +3 -0
- data/lib/chef/knife/project_add_role.rb +24 -0
- data/lib/chef/knife/project_bootstrap.rb +24 -0
- data/lib/chef/knife/project_capistrano.rb +19 -0
- data/lib/chef/knife/project_create.rb +53 -0
- data/lib/chef/knife/project_info.rb +13 -0
- data/lib/chef/knife/project_list.rb +17 -0
- data/lib/chef/knife/project_new.rb +28 -0
- data/lib/chef/knife/project_run_client.rb +30 -0
- data/lib/chef/knife/project_show.rb +34 -0
- data/spec/buckknife/commands/add_role_spec.rb +14 -0
- data/spec/buckknife/commands/bootstrap_spec.rb +22 -0
- data/spec/buckknife/commands/capistrano_spec.rb +13 -0
- data/spec/buckknife/commands/create_spec.rb +48 -0
- data/spec/buckknife/commands/run_client_spec.rb +15 -0
- data/spec/buckknife/environment_spec.rb +14 -0
- data/spec/buckknife/helper_spec.rb +11 -0
- data/spec/buckknife/node_spec.rb +18 -0
- data/spec/buckknife/project_spec.rb +49 -0
- data/spec/data_bags/projects/myapp.json +139 -0
- data/spec/knife.rb +4 -0
- data/spec/knife/project_bootstrap_spec.rb +0 -0
- data/spec/knife/project_info_spec.rb +17 -0
- data/spec/knife/project_list_spec.rb +18 -0
- data/spec/spec_helper.rb +27 -0
- metadata +251 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectAddRole < Chef::Knife
|
5
|
+
banner "knife project add role PROJECT [NODE]"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
project = project_from_arg_or_ask
|
14
|
+
node_name = @name_args[1]
|
15
|
+
nodes = Array(project.node(node_name) || project.nodes)
|
16
|
+
|
17
|
+
nodes.each do |node|
|
18
|
+
ui.output "# Run these command to add roles one at a time to #{node.name}:"
|
19
|
+
ui.output BuckKnife::Commands::AddRole.new( node )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectBootstrap < Chef::Knife
|
5
|
+
banner "knife project bootstrap PROJECT [NODE]"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
project = project_from_arg_or_ask
|
14
|
+
node_name = @name_args[1]
|
15
|
+
nodes = Array(project.node(node_name) || project.nodes)
|
16
|
+
|
17
|
+
nodes.each do |node|
|
18
|
+
ui.output "# Run this command to bootstrap #{node.name}:"
|
19
|
+
ui.output BuckKnife::Commands::Bootstrap.new( project, node )
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectCapistrano < Chef::Knife
|
5
|
+
banner "knife project capistrano PROJECT"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
project = project_from_arg_or_ask
|
14
|
+
ui.output "# Copy and commit this file to the project's repository:"
|
15
|
+
ui.output BuckKnife::Commands::Capistrano.new(project).call
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectCreate < Chef::Knife
|
5
|
+
banner "knife project create PROJECT [NODE]"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
option :identity_file,
|
13
|
+
:short => "-i IDENTITY_FILE",
|
14
|
+
:long => "--identity-file",
|
15
|
+
:description => "The SSH identity file used for authentication"
|
16
|
+
|
17
|
+
option :provider,
|
18
|
+
:short => "-p PROVIDER",
|
19
|
+
:long => "--provider",
|
20
|
+
:description => "The cloud provider to use (euca, rackspace, ...)"
|
21
|
+
|
22
|
+
option :ssh_username,
|
23
|
+
:short => "-x USERNAME",
|
24
|
+
:long => "--ssh-user",
|
25
|
+
:description => "The ssh username"
|
26
|
+
|
27
|
+
def run
|
28
|
+
project = project_from_arg_or_ask
|
29
|
+
node_name = @name_args[1]
|
30
|
+
nodes = Array(project.node(node_name) || project.nodes)
|
31
|
+
|
32
|
+
project.identity_file = Chef::Config[:knife][:euca_identity_file] if Chef::Config[:knife][:euca_identity_file]
|
33
|
+
project.provider = config[:provider] if config[:provider]
|
34
|
+
project.ssh_username = config[:ssh_username] if config[:ssh_username]
|
35
|
+
|
36
|
+
# TODO: Move this into project, ActiveModel validation?
|
37
|
+
unless project.valid?
|
38
|
+
ui.fatal("The #{project.name}.json file has some errors that need to be fixed:")
|
39
|
+
project.errors.each do |att, err|
|
40
|
+
ui.fatal("'#{att}' #{err}")
|
41
|
+
end
|
42
|
+
|
43
|
+
exit 1
|
44
|
+
end
|
45
|
+
|
46
|
+
nodes.each do |node|
|
47
|
+
ui.output "# Run this command to create #{node.name}:"
|
48
|
+
ui.output BuckKnife::Commands::Create[project.provider].new(project, node)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectInfo < Chef::Knife
|
5
|
+
banner "knife project info"
|
6
|
+
|
7
|
+
def run
|
8
|
+
ui.output "Config file: %s" % Chef::Config[:config_file] || config[:config_file]
|
9
|
+
ui.output "Chef Server: %s" % Chef::Config[:chef_server_url]
|
10
|
+
ui.output "Project Dir: %s" % Chef::Config[:knife][:project_dir]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectList < Chef::Knife
|
5
|
+
banner "knife project list"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
BuckKnife::Project.all.each do |project|
|
13
|
+
ui.output " #{project.name}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectNew < Chef::Knife
|
5
|
+
banner "knife project new PROJECT"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
project_name = @name_args[0]
|
13
|
+
|
14
|
+
if project_name.nil?
|
15
|
+
show_usage
|
16
|
+
ui.fatal("You must specify a project name")
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
template = BuckKnife.template_root.join("project.json.erb").read
|
21
|
+
compiled = ERB.new(template, nil, '%>').result(binding)
|
22
|
+
project_path = Project.root.join("#{project_name}.json")
|
23
|
+
project_path.open("w") { |f| f.write compiled }
|
24
|
+
|
25
|
+
ui.output ui.color("#{project_name}.json written to #{project_path}", :green)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectRunClient < Chef::Knife
|
5
|
+
banner "knife project run client PROJECT [NODE] [options]"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
option :env,
|
13
|
+
:short => "-e ENVIRONMENT",
|
14
|
+
:long => "--env ENVIRONMENT",
|
15
|
+
:description => "Project environment to scope to (dev,staging,production)"
|
16
|
+
|
17
|
+
def run
|
18
|
+
project = project_from_arg_or_ask
|
19
|
+
node_name = @name_args[1]
|
20
|
+
|
21
|
+
ui.output "# Run this command to run client:"
|
22
|
+
ui.output BuckKnife::Commands::RunClient.new(
|
23
|
+
:project => project.name,
|
24
|
+
:node => node_name,
|
25
|
+
:environment => config[:env]
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
|
3
|
+
module BuckKnife
|
4
|
+
class ProjectShow < Chef::Knife
|
5
|
+
banner "knife project show PROJECT"
|
6
|
+
|
7
|
+
deps do
|
8
|
+
require 'buckknife'
|
9
|
+
include BuckKnife::KnifeHelper
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
ui.use_presenter BuckKnife::ProjectPresenter
|
14
|
+
project = project_from_arg_or_ask
|
15
|
+
output(project)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ProjectPresenter < Chef::Knife::Core::GenericPresenter
|
20
|
+
|
21
|
+
def summarize(project)
|
22
|
+
summarized = <<-SUMMARY
|
23
|
+
#{ui.color('Project Name:', :bold)} #{ui.color(project.name, :bold)}
|
24
|
+
#{key('Environments:')} #{project.environment_names.join(', ')}
|
25
|
+
#{key('Nodes:')} #{project.node_names.join("\n" + ' ' * 14)}
|
26
|
+
SUMMARY
|
27
|
+
end
|
28
|
+
|
29
|
+
def key(key_text)
|
30
|
+
ui.color(key_text, :cyan)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Commands::AddRole do
|
4
|
+
it "should output a knife command to add roles" do
|
5
|
+
project = BuckKnife::Project.find('myapp')
|
6
|
+
node = project.node('myapp-monitor1')
|
7
|
+
cmd = BuckKnife::Commands::AddRole.new(node)
|
8
|
+
|
9
|
+
cmd.to_s.should == [
|
10
|
+
"knife node run_list add myapp-monitor1 'role[monitor_client]'",
|
11
|
+
"knife node run_list add myapp-monitor1 'role[rails_app]'"
|
12
|
+
].join("\n")
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# cli = BuckKnife::CLI.new(args, options, config)
|
2
|
+
# cli.invoke(:task, [first_arg, second_arg, third_arg], {options hash})
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe BuckKnife::Commands::Bootstrap do
|
6
|
+
it "should output a knife command to bootstrap the server on rackspace" do
|
7
|
+
project = BuckKnife::Project.find('myapp')
|
8
|
+
node = project.node('myapp-monitor1')
|
9
|
+
cmd = BuckKnife::Commands::Bootstrap.new(project, node)
|
10
|
+
|
11
|
+
cmd.to_s.should == [
|
12
|
+
"knife bootstrap 127.0.0.1",
|
13
|
+
"-N myapp-monitor1",
|
14
|
+
"-x username",
|
15
|
+
"-P password",
|
16
|
+
"-r 'role[base],recipe[base_projects::myapp],role[base_server]'",
|
17
|
+
"-d ubuntu10.04.deb",
|
18
|
+
"--sudo"
|
19
|
+
].join(' ')
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# cli = BuckKnife::CLI.new(args, options, config)
|
2
|
+
# cli.invoke(:task, [first_arg, second_arg, third_arg], {options hash})
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe BuckKnife::Commands::Capistrano do
|
6
|
+
it "should output a capistrano deploy script for a project" do
|
7
|
+
BuckKnife::Commands::Capistrano.any_instance.stub(:fetch_ip) { "127.0.0.1" }
|
8
|
+
project = BuckKnife::Project.find('myapp')
|
9
|
+
cmd = BuckKnife::Commands::Capistrano.new(project)
|
10
|
+
|
11
|
+
cmd.call.should =~ /DO NOT MODIFY THIS FILE/
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# cli = BuckKnife::CLI.new(args, options, config)
|
2
|
+
# cli.invoke(:task, [first_arg, second_arg, third_arg], {options hash})
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe BuckKnife::Commands::Create do
|
6
|
+
it "should output a knife command to create the server on rackspace" do
|
7
|
+
project = BuckKnife::Project.find('myapp')
|
8
|
+
node = project.node('myapp-monitor1')
|
9
|
+
cmd = BuckKnife::Commands::Create[project.provider].new(project, node)
|
10
|
+
|
11
|
+
cmd.to_s.should == [
|
12
|
+
"knife rackspace server create",
|
13
|
+
"-r 'role[base],recipe[base_projects::myapp],role[base_server]'",
|
14
|
+
"-f 4",
|
15
|
+
"-I 49",
|
16
|
+
"-d ubuntu10.04.deb",
|
17
|
+
"-s http://localhost:4000",
|
18
|
+
"-N myapp-monitor1",
|
19
|
+
"-S myapp-monitor1",
|
20
|
+
"-K ''",
|
21
|
+
"-A ''"
|
22
|
+
].join(' ')
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should output a knife command to create the server on eucalyptus" do
|
27
|
+
project = BuckKnife::Project.find('myapp')
|
28
|
+
project.should_receive(:provider) { "euca" }.twice
|
29
|
+
node = project.node('myapp-monitor1')
|
30
|
+
|
31
|
+
node.flavor.should be_nil
|
32
|
+
|
33
|
+
cmd = BuckKnife::Commands::Create[project.provider].new(project, node)
|
34
|
+
cmd.should_receive(:availability_zone) { "us-west-1" }.twice
|
35
|
+
|
36
|
+
cmd.to_s.should == [
|
37
|
+
"knife euca server create",
|
38
|
+
"-r 'role[base],recipe[base_projects::myapp],role[base_server]'",
|
39
|
+
"-f m1.large",
|
40
|
+
"-I emi-DFB9107F",
|
41
|
+
"-d ubuntu10.04.deb",
|
42
|
+
"-s http://localhost:4000",
|
43
|
+
"-N myapp-monitor1",
|
44
|
+
"-Z us-west-1"
|
45
|
+
].join(' ')
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Commands::RunClient do
|
4
|
+
it "should output a knife command to add roles" do
|
5
|
+
cmd = BuckKnife::Commands::RunClient.new(:project => 'myapp', :node => 'myapp-monitor1')
|
6
|
+
|
7
|
+
cmd.to_s.should == [
|
8
|
+
"knife ssh 'project:myapp AND name:myapp-monitor1'",
|
9
|
+
"'sudo chef-client'",
|
10
|
+
"--attribute ipaddress",
|
11
|
+
"-x username",
|
12
|
+
"-P password"
|
13
|
+
].join(' ')
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Environment do
|
4
|
+
context "initialized with a name and hash of data" do
|
5
|
+
subject { BuckKnife::Environment.new("dev", {"domain_name" => "dev.myapp.com"}, []) }
|
6
|
+
it "should have a name" do
|
7
|
+
subject.name.should == "dev"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have a domain name" do
|
11
|
+
subject.domain_name.should == "dev.myapp.com"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Helper do
|
4
|
+
it "should create a run list from roles and recipes" do
|
5
|
+
roles = ['base', 'base_server']
|
6
|
+
recipes = ["base_projects::projectname"]
|
7
|
+
sep = ','
|
8
|
+
result = BuckKnife::Helper.combine_roles_and_recipes(roles, recipes, sep)
|
9
|
+
result.should == "role[base],role[base_server],recipe[base_projects::projectname]"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Node do
|
4
|
+
context "initialized with a hash of data" do
|
5
|
+
subject { BuckKnife::Project.find("myapp").node("myapp-monitor1") }
|
6
|
+
it "should have a name" do
|
7
|
+
subject.name.should == "myapp-monitor1"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have a size" do
|
11
|
+
subject.size.should == "2G"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a run list" do
|
15
|
+
subject.run_list.should == "role[monitor_client] role[rails_app]"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BuckKnife::Project do
|
4
|
+
context "initialized with a hash of data" do
|
5
|
+
subject { BuckKnife::Project.find("myapp") }
|
6
|
+
it "should have a name" do
|
7
|
+
subject.name.should == "myapp"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should have node names" do
|
11
|
+
subject.node_names.should == %w[
|
12
|
+
myapp-dev-app1
|
13
|
+
myapp-dev-app2
|
14
|
+
myapp-dev-job1
|
15
|
+
myapp-monitor1
|
16
|
+
myapp-prod-app1
|
17
|
+
myapp-prod-app2
|
18
|
+
myapp-prod-job1
|
19
|
+
myapp-staging-app1
|
20
|
+
myapp-staging-app2
|
21
|
+
myapp-staging-job1
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have nodes" do
|
26
|
+
subject.nodes.first.should be_instance_of BuckKnife::Node
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can look up a node based on name" do
|
30
|
+
subject.node("myapp-monitor1").should be_instance_of BuckKnife::Node
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have a repository" do
|
34
|
+
subject.repository.should == "http://svn.domain.com/myapp/trunk"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have environment names" do
|
38
|
+
subject.environment_names.should == ["dev", "production", "staging"]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have environments" do
|
42
|
+
subject.environments.first.should be_instance_of BuckKnife::Environment
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have a provider" do
|
46
|
+
subject.provider.should == "rackspace"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|