knife-ninefold 0.1.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.
@@ -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: []