knife-ninefold 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ # Knife Ninefold
2
+
3
+ ## Description
4
+
5
+ Knife plugin for ninefold
6
+
7
+ ## Installation
8
+
9
+ This plugin is distributed as a Ruby Gem. To install:
10
+
11
+ gem install knife-ninefold
12
+
13
+ ## Configuration
14
+
15
+ The following parameters need to be set in your knife.rb:
16
+
17
+ knife[:ninefold_compute_key] = "Your Ninefold compute API key"
18
+ knife[:ninefold_compute_secret] = "Your Ninefold compute API secret"
19
+
20
+ or added to the command line in the -K and -S parameters
21
+
22
+ ## Subcommands
23
+
24
+ ### knife ninefold flavor list
25
+
26
+ ### knife ninefold image list
27
+
28
+ ### knife ninefold server create
29
+
30
+ Creates a server. By default, a 1.7gb running Ubuntu
31
+
32
+ ### knife ninefold server list
33
+
34
+ ### knife ninefold server delete
35
+
36
+ ## Development
37
+
38
+ Run knife through bundler - this will load the in development gem
@@ -0,0 +1,59 @@
1
+ require 'chef/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ module NinefoldBase
6
+
7
+ # :nodoc:
8
+ # Would prefer to do this in a rational way, but can't be done b/c of
9
+ # Mixlib::CLI's design :(
10
+ def self.included(includer)
11
+ includer.class_eval do
12
+
13
+ deps do
14
+ require 'fog'
15
+ require 'net/ssh/multi'
16
+ require 'readline'
17
+ require 'chef/json_compat'
18
+
19
+ Chef::Knife::Bootstrap.load_deps
20
+ end
21
+
22
+ option(:ninefold_compute_key,
23
+ :short => "-K KEY",
24
+ :long => "--ninefold_compute_key KEY",
25
+ :description => "Your Ninefold API Key",
26
+ :proc => Proc.new { |key| Chef::Config[:knife][:ninefold_compute_key] = key })
27
+
28
+ option(:ninefold_compute_secret,
29
+ :short => "-S SECRET",
30
+ :long => "--ninefold_compute_secret SECRET",
31
+ :description => "Your Ninefold API Secret Secret",
32
+ :proc => Proc.new { |key| Chef::Config[:knife][:ninefold_compute_secret] = key })
33
+
34
+ end
35
+ end
36
+
37
+ def connection
38
+ unless Chef::Config[:knife][:ninefold_compute_key] && Chef::Config[:knife][:ninefold_compute_secret]
39
+ ui.error "Ninefold compute key and/or secret not specified with -K and -S parameters,"
40
+ ui.error "or set in knife.rb with:"
41
+ ui.error 'knife[:ninefold_compute_key] = "API key"'
42
+ ui.error 'knife[:ninefold_compute_secret] = "Secret key"'
43
+ exit 1
44
+ end
45
+ @connection ||= Fog::Compute.new(
46
+ :provider => 'Ninefold',
47
+ :ninefold_compute_key => Chef::Config[:knife][:ninefold_compute_key],
48
+ :ninefold_compute_secret => Chef::Config[:knife][:ninefold_compute_secret]
49
+ )
50
+ end
51
+
52
+ def locate_config_value(key)
53
+ key = key.to_sym
54
+ Chef::Config[:knife][key] || config[key]
55
+ end
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,29 @@
1
+ require 'chef/knife/ninefold_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class NinefoldFlavorList < Knife
6
+
7
+ include Knife::NinefoldBase
8
+
9
+ banner "knife ninefold flavor list"
10
+
11
+ def run
12
+ $stdout.sync = true
13
+
14
+ flavor_list = [
15
+ ui.color('ID', :bold),
16
+ ui.color('Name', :bold),
17
+ ui.color('Description', :bold)
18
+ ]
19
+ connection.flavors.all.each do |flavor|
20
+ flavor_list << flavor.identity.to_s
21
+ flavor_list << flavor.name
22
+ flavor_list << flavor.displaytext
23
+ end
24
+ puts ui.list(flavor_list, :columns_across, 3)
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ require 'chef/knife/ninefold_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class NinefoldImageList < Knife
6
+
7
+ include Knife::NinefoldBase
8
+
9
+ banner "knife ninefold image list"
10
+
11
+ def run
12
+ $stdout.sync = true
13
+
14
+ image_list = [
15
+ ui.color('ID', :bold),
16
+ ui.color('Name', :bold),
17
+ ui.color('Hypervisor', :bold),
18
+ ui.color('Zone', :bold)
19
+ ]
20
+ connection.images.all.each do |image|
21
+ image_list << image.identity.to_s
22
+ image_list << image.name
23
+ image_list << image.hypervisor
24
+ image_list << image.zonename
25
+ end
26
+ puts ui.list(image_list, :columns_across, 4)
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,153 @@
1
+ require 'chef/knife/ninefold_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class NinefoldServerCreate < Knife
6
+
7
+ include Knife::NinefoldBase
8
+
9
+ banner "knife ninefold server create (options)"
10
+
11
+ option :flavor,
12
+ :short => "-f FLAVOR",
13
+ :long => "--flavor FLAVOR",
14
+ :description => "The flavor of server; default is 67 - Compute Small PRD (1.7 GB)",
15
+ :proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f.to_i },
16
+ :default => 67
17
+
18
+ option :image,
19
+ :short => "-I IMAGE",
20
+ :long => "--image IMAGE",
21
+ :description => "The image of the server; Default is 421 - XEN Ubuntu 10.04 LTS 64bit",
22
+ :proc => Proc.new { |i| Chef::Config[:knife][:image] = i.to_i },
23
+ :default => 421
24
+
25
+ option :server_name,
26
+ :short => "-S NAME",
27
+ :long => "--server-name NAME",
28
+ :description => "The server name"
29
+
30
+ option :bootstrap,
31
+ :short => "-b",
32
+ :long => "--bootstrap",
33
+ :description => "If we should chef bootstrap this node; default is to not bootstrap",
34
+ :boolean => true,
35
+ :default => false
36
+
37
+ option :chef_node_name,
38
+ :short => "-N NAME",
39
+ :long => "--node-name NAME",
40
+ :description => "The Chef node name for your new node"
41
+
42
+ option :ssh_user,
43
+ :short => "-x USERNAME",
44
+ :long => "--ssh-user USERNAME",
45
+ :description => "The ssh username; default is 'ubuntu'",
46
+ :default => "ubuntu"
47
+
48
+ option :ssh_password,
49
+ :short => "-P PASSWORD",
50
+ :long => "--ssh-password PASSWORD",
51
+ :description => "The ssh password; default is 'Password01'",
52
+ :default => "Password01"
53
+
54
+ option :identity_file,
55
+ :short => "-i IDENTITY_FILE",
56
+ :long => "--identity-file IDENTITY_FILE",
57
+ :description => "The SSH identity file used for authentication"
58
+
59
+ option :prerelease,
60
+ :long => "--prerelease",
61
+ :description => "Install the pre-release chef gems"
62
+
63
+ option :bootstrap_version,
64
+ :long => "--bootstrap-version VERSION",
65
+ :description => "The version of Chef to install",
66
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
67
+
68
+ option :distro,
69
+ :short => "-d DISTRO",
70
+ :long => "--distro DISTRO",
71
+ :description => "Bootstrap a distro using a template; default is 'ubuntu10.04-gems'",
72
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
73
+ :default => "ubuntu10.04-gems"
74
+
75
+ option :template_file,
76
+ :long => "--template-file TEMPLATE",
77
+ :description => "Full path to location of template to use",
78
+ :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
79
+ :default => false
80
+
81
+ option :run_list,
82
+ :short => "-r RUN_LIST",
83
+ :long => "--run-list RUN_LIST",
84
+ :description => "Comma separated list of roles/recipes to apply",
85
+ :proc => lambda { |o| o.split(/[\s,]+/) },
86
+ :default => []
87
+
88
+ def run
89
+ $stdout.sync = true
90
+
91
+ server = connection.servers.create(:templateid => locate_config_value(:image),
92
+ :serviceofferingid => locate_config_value(:flavor),
93
+ :zoneid => 1,
94
+ :name => config[:server_name])
95
+
96
+ server.reload # fetch generated name etc.
97
+
98
+ puts "#{ui.color("Instance ID", :cyan)}: #{server.id}"
99
+ puts "#{ui.color("Name", :cyan)}: #{server.name}"
100
+ puts "#{ui.color("Flavor", :cyan)}: #{server.serviceofferingname}"
101
+ puts "#{ui.color("Image", :cyan)}: #{server.templatename}"
102
+
103
+ print "\n#{ui.color("Waiting on server", :magenta)}"
104
+ # wait for it to be ready to do stuff
105
+ server.wait_for { print "."; ready? }
106
+ puts
107
+
108
+ @ip = connection.addresses.new(:zoneid => 1)
109
+ @ip.save
110
+ @ip.reload
111
+ print "\n#{ui.color("Waiting on IP address allocation", :magenta)}"
112
+ @ip.wait_for { print '.' ; ready? }
113
+ puts "\n"
114
+ # Enable static NAT to this server
115
+ @ip.enable_static_nat(server)
116
+ # Map inbound connections
117
+ ipfw_tcp = connection.ip_forwarding_rules.new(:address => @ip, :protocol => 'TCP', :startport => 1, :endport => 65535)
118
+ ipfw_tcp.save
119
+ ipfw_udp = connection.ip_forwarding_rules.new(:address => @ip, :protocol => 'UDP', :startport => 1, :endport => 65535)
120
+ ipfw_udp.save
121
+ print "\n#{ui.color("Waiting on Inbound TCP&UDP connection mapping", :magenta)}"
122
+ ipfw_tcp.wait_for {print '.' ; ready?}
123
+ ipfw_udp.wait_for {print '.' ; ready?}
124
+ puts
125
+ puts "#{ui.color("Public IP Address", :cyan)}: #{@ip.ipaddress}"
126
+
127
+
128
+ if config[:bootstrap]
129
+ bootstrap_for_node(server).run
130
+ end
131
+ end
132
+
133
+ def bootstrap_for_node(server)
134
+ bootstrap = Chef::Knife::Bootstrap.new
135
+ bootstrap.name_args = [@ip.ipaddress]
136
+ bootstrap.config[:run_list] = config[:run_list]
137
+ bootstrap.config[:ssh_user] = config[:ssh_user] || "root"
138
+ bootstrap.config[:ssh_password] = config[:ssh_password]
139
+ bootstrap.config[:identity_file] = config[:identity_file]
140
+ bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.name
141
+ bootstrap.config[:prerelease] = config[:prerelease]
142
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
143
+ bootstrap.config[:distro] = locate_config_value(:distro)
144
+ # bootstrap will run as root...sudo (by default) also messes up Ohai on CentOS boxes
145
+ bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
146
+ bootstrap.config[:template_file] = locate_config_value(:template_file)
147
+ bootstrap.config[:environment] = config[:environment]
148
+ bootstrap
149
+ end
150
+ end
151
+ end
152
+ end
153
+
@@ -0,0 +1,55 @@
1
+ require 'chef/knife/ninefold_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class NinefoldServerDelete < Knife
6
+
7
+ include Knife::NinefoldBase
8
+
9
+ banner "knife ninefold server delete SERVER_ID [SERVER_ID..]"
10
+
11
+ def run
12
+ $stdout.sync = true
13
+
14
+ @name_args.each do |instance_id|
15
+
16
+ server = connection.servers.get(instance_id)
17
+
18
+ addrs = connection.addresses.all.select {|a| a.isstaticnat.to_s == "true" && a.virtualmachineid == server.id}
19
+
20
+ msg("Instance ID", server.id.to_s)
21
+ msg("Name", server.name)
22
+ msg("Flavor", server.serviceofferingname)
23
+ msg("Image", server.templatename)
24
+ msg("Public IP", addrs[0].ipaddress) if addrs[0]
25
+
26
+ puts "\n"
27
+ confirm("Do you really want to delete this server")
28
+
29
+ server.destroy
30
+ ui.warn("Deleted server #{server.id} named #{server.name}")
31
+ if addrs[0]
32
+ # addrs[0].disable_static_nat
33
+ # print "\n#{ui.color("Waiting on static nat disabling", :magenta)}"
34
+ # addrs[0].wait_for { print '.' ; ready? }
35
+ # puts
36
+ addrs[0].destroy
37
+ # print "\n#{ui.color("Waiting on ip address release", :magenta)}"
38
+ # addrs[0].wait_for { print '.' ; ready? }
39
+ # puts
40
+ ui.warn("Removed public IP allocation: #{addrs[0].ipaddress}")
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ def msg(label, value)
47
+ if value && !value.empty?
48
+ puts "#{ui.color(label, :cyan)}: #{value}"
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,42 @@
1
+ require 'chef/knife/ninefold_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class NinefoldServerList < Knife
6
+
7
+ include Knife::NinefoldBase
8
+
9
+ banner "knife ninefold server list"
10
+
11
+ def run
12
+ $stdout.sync = true
13
+
14
+ server_list = [
15
+ ui.color('Instance ID', :bold),
16
+ ui.color('Name', :bold),
17
+ ui.color('Public IP', :bold),
18
+ ui.color('Private IP', :bold),
19
+ ui.color('Flavor', :bold),
20
+ ui.color('Image', :bold),
21
+ ui.color('Zone', :bold)
22
+ ]
23
+ connection.servers.all.each do |server|
24
+ # Get public IP:
25
+ addrs = connection.addresses.all.select {|a| a.isstaticnat.to_s == "true" && a.virtualmachineid == server.id}
26
+ public_ip = addrs[0] ? addrs[0].ipaddress : 'No public IP'
27
+
28
+ server_list << server.identity.to_s
29
+ server_list << server.name
30
+ server_list << public_ip
31
+ server_list << server.ipaddress
32
+ server_list << server.serviceofferingname
33
+ server_list << server.templatename
34
+ server_list << server.zonename
35
+ end
36
+ puts ui.list(server_list, :columns_across, 7)
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+
@@ -0,0 +1,3 @@
1
+ module KnifeNinefold
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-ninefold
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Lincoln Stoll
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: chef
16
+ requirement: &70296831106840 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70296831106840
25
+ - !ruby/object:Gem::Dependency
26
+ name: fog
27
+ requirement: &70296831106420 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70296831106420
36
+ description: Ninefold Support for Chef's Knife Command
37
+ email: lstoll@lstoll.net
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files:
41
+ - README.md
42
+ files:
43
+ - README.md
44
+ - lib/chef/knife/ninefold_base.rb
45
+ - lib/chef/knife/ninefold_flavor_list.rb
46
+ - lib/chef/knife/ninefold_image_list.rb
47
+ - lib/chef/knife/ninefold_server_create.rb
48
+ - lib/chef/knife/ninefold_server_delete.rb
49
+ - lib/chef/knife/ninefold_server_list.rb
50
+ - lib/knife-ninefold/version.rb
51
+ homepage:
52
+ licenses: []
53
+ post_install_message:
54
+ rdoc_options: []
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 1.8.11
72
+ signing_key:
73
+ specification_version: 3
74
+ summary: Ninefold Support for Chef's Knife Command
75
+ test_files: []