buckknife 0.0.4

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.
Files changed (50) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/HISTORY.md +8 -0
  4. data/README.md +65 -0
  5. data/Rakefile +27 -0
  6. data/buckknife.gemspec +31 -0
  7. data/lib/buckknife.rb +44 -0
  8. data/lib/buckknife/command.rb +33 -0
  9. data/lib/buckknife/commands/add_role.rb +13 -0
  10. data/lib/buckknife/commands/base.rb +24 -0
  11. data/lib/buckknife/commands/bootstrap.rb +28 -0
  12. data/lib/buckknife/commands/capistrano.rb +46 -0
  13. data/lib/buckknife/commands/create.rb +42 -0
  14. data/lib/buckknife/commands/euca_create.rb +60 -0
  15. data/lib/buckknife/commands/rackspace_create.rb +58 -0
  16. data/lib/buckknife/commands/run_client.rb +49 -0
  17. data/lib/buckknife/data_accessor.rb +29 -0
  18. data/lib/buckknife/environment.rb +16 -0
  19. data/lib/buckknife/helper.rb +39 -0
  20. data/lib/buckknife/knife_helper.rb +22 -0
  21. data/lib/buckknife/node.rb +30 -0
  22. data/lib/buckknife/project.rb +80 -0
  23. data/lib/buckknife/templates/deploy_environments.rb.erb +85 -0
  24. data/lib/buckknife/templates/project.json.erb +75 -0
  25. data/lib/buckknife/version.rb +3 -0
  26. data/lib/chef/knife/project_add_role.rb +24 -0
  27. data/lib/chef/knife/project_bootstrap.rb +24 -0
  28. data/lib/chef/knife/project_capistrano.rb +19 -0
  29. data/lib/chef/knife/project_create.rb +53 -0
  30. data/lib/chef/knife/project_info.rb +13 -0
  31. data/lib/chef/knife/project_list.rb +17 -0
  32. data/lib/chef/knife/project_new.rb +28 -0
  33. data/lib/chef/knife/project_run_client.rb +30 -0
  34. data/lib/chef/knife/project_show.rb +34 -0
  35. data/spec/buckknife/commands/add_role_spec.rb +14 -0
  36. data/spec/buckknife/commands/bootstrap_spec.rb +22 -0
  37. data/spec/buckknife/commands/capistrano_spec.rb +13 -0
  38. data/spec/buckknife/commands/create_spec.rb +48 -0
  39. data/spec/buckknife/commands/run_client_spec.rb +15 -0
  40. data/spec/buckknife/environment_spec.rb +14 -0
  41. data/spec/buckknife/helper_spec.rb +11 -0
  42. data/spec/buckknife/node_spec.rb +18 -0
  43. data/spec/buckknife/project_spec.rb +49 -0
  44. data/spec/data_bags/projects/myapp.json +139 -0
  45. data/spec/knife.rb +4 -0
  46. data/spec/knife/project_bootstrap_spec.rb +0 -0
  47. data/spec/knife/project_info_spec.rb +17 -0
  48. data/spec/knife/project_list_spec.rb +18 -0
  49. data/spec/spec_helper.rb +27 -0
  50. metadata +251 -0
@@ -0,0 +1,3 @@
1
+ module BuckKnife
2
+ VERSION = "0.0.4"
3
+ end
@@ -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