knife-rackspace-load-balancer 0.0.1
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.
- data/.gitignore +1 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +28 -0
- data/knife-rackspace-load-balancer.gemspec +18 -0
- data/lib/chef/knife/rackspace_load_balancer_add_node.rb +161 -0
- data/lib/chef/knife/rackspace_load_balancer_base.rb +26 -0
- data/lib/chef/knife/rackspace_load_balancer_create.rb +124 -0
- data/lib/chef/knife/rackspace_load_balancer_delete.rb +41 -0
- data/lib/chef/knife/rackspace_load_balancer_delete_node.rb +117 -0
- data/lib/chef/knife/rackspace_load_balancer_list.rb +39 -0
- data/lib/chef/knife/rackspace_load_balancer_nodes.rb +32 -0
- data/lib/chef/knife/rackspace_load_balancer_show.rb +75 -0
- data/lib/version.rb +8 -0
- metadata +100 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 HowAboutWe
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
==Setup
|
2
|
+
Add region to your knife configuration:
|
3
|
+
#knife.rb
|
4
|
+
knife[:rackspace_api_region] = "ord"
|
5
|
+
|
6
|
+
==Commands
|
7
|
+
List:
|
8
|
+
bundle exec knife rackspace load balancer list
|
9
|
+
|
10
|
+
Show:
|
11
|
+
bundle exec knife rackspace load balancer show <load_balancer_id>
|
12
|
+
bundle exec knife rackspace load balancer show <load_balancer_id> <load_balancer_id> --resolve-node-names
|
13
|
+
|
14
|
+
Create:
|
15
|
+
bundle exec knife rackspace load balancer create "some.site.com" --port 80 --node-port 80 --add-nodes-by-name "app1,app2" --algorithm RANDOM
|
16
|
+
|
17
|
+
Delete:
|
18
|
+
bundle exec knife rackspace load balancer delete <load_balancer_id>
|
19
|
+
|
20
|
+
Add Node:
|
21
|
+
bundle exec knife rackspace load balancer add node --by-name "app1" --port 80 --only "<load_balancer_id>,<load_balancer_id>"
|
22
|
+
bundle exec knife rackspace load balancer add node --by-name "app1,app2" --auto-resolve-port --except "<load_balancer_id>"
|
23
|
+
|
24
|
+
Delete Node:
|
25
|
+
bundle exec knife rackspace load balancer delete node --by-search "chef_environment:staging AND name:staging-app" --all
|
26
|
+
|
27
|
+
== Copyright
|
28
|
+
Copyright (c) 2012 HowAboutWe. See LICENSE.txt for further details.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "knife-rackspace-load-balancer"
|
6
|
+
s.version = Knife::Rackspace::LoadBalancer::VERSION
|
7
|
+
s.authors = ["Matthew Vermaak"]
|
8
|
+
s.email = "dev@howaboutwe.com"
|
9
|
+
s.summary = "Rackspace cloud load balancer support for knife"
|
10
|
+
s.description = "A gem to extend knife-rackspace allowing cloud load balancer management."
|
11
|
+
s.homepage = "http://github.com/howaboutwe/knife-rackspace-load-balancer"
|
12
|
+
s.licenses = ["MIT"]
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.add_dependency "chef", "~> 0.10.8"
|
15
|
+
s.add_dependency "knife-rackspace", "~> 0.5.12"
|
16
|
+
s.add_dependency "cloudlb", "~> 0.1.0"
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/rackspace_base'
|
3
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
4
|
+
require 'chef/knife/rackspace_load_balancer_nodes'
|
5
|
+
require 'cloudlb'
|
6
|
+
|
7
|
+
module KnifePlugins
|
8
|
+
class RackspaceLoadBalancerAddNode < Chef::Knife
|
9
|
+
include Chef::Knife::RackspaceBase
|
10
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
11
|
+
include Chef::Knife::RackspaceLoadBalancerNodes
|
12
|
+
|
13
|
+
banner "knife rackspace load balancer add node (options)"
|
14
|
+
|
15
|
+
option :force,
|
16
|
+
:long => "--force",
|
17
|
+
:description => "Skip user input"
|
18
|
+
|
19
|
+
option :all,
|
20
|
+
:long => "--all",
|
21
|
+
:description => "Add to all load balancers"
|
22
|
+
|
23
|
+
option :except,
|
24
|
+
:long => "--except \"ID[,ID]\"",
|
25
|
+
:description => "Comma deliminated list of load balancer ids to omit (Implies --all)"
|
26
|
+
|
27
|
+
option :only,
|
28
|
+
:long => "--only \"ID[,ID]\"",
|
29
|
+
:description => "Comma deliminated list of load balancer ids to add to"
|
30
|
+
|
31
|
+
option :port,
|
32
|
+
:long => "--port PORT",
|
33
|
+
:description => "Add node listening to this port [DEFAULT: 80]",
|
34
|
+
:default => "80"
|
35
|
+
|
36
|
+
option :condition,
|
37
|
+
:long => "--condition CONDITION",
|
38
|
+
:description => "Add node in this condition [DEFAULT: ENABLED]",
|
39
|
+
:default => "ENABLED"
|
40
|
+
|
41
|
+
option :weight,
|
42
|
+
:long => "--weight WEIGHT",
|
43
|
+
:description => "Add node with this weight [DEFAULT: 1]",
|
44
|
+
:default => "1"
|
45
|
+
|
46
|
+
option :by_name,
|
47
|
+
:long => "--by-name \"NAME[,NAME]\"",
|
48
|
+
:description => "Resolve names against chef server to produce list of nodes to add"
|
49
|
+
|
50
|
+
option :by_private_ip,
|
51
|
+
:long => "--by-private-ip \"IP[,IP]\"",
|
52
|
+
:description => "List of nodes given by private ips to add"
|
53
|
+
|
54
|
+
option :by_search,
|
55
|
+
:long => "--by-search SEARCH",
|
56
|
+
:description => "Resolve search against chef server to produce list of nodes to add"
|
57
|
+
|
58
|
+
option :auto_resolve_port,
|
59
|
+
:long => "--auto-resolve-port",
|
60
|
+
:description => "Auto resolve port of node addition"
|
61
|
+
|
62
|
+
def run
|
63
|
+
unless [:all, :except, :only].any? {|target| not config[target].nil?}
|
64
|
+
ui.fatal("Must provide a target set of load balancers with --all, --except, or --only")
|
65
|
+
show_usage
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
unless [:by_name, :by_private_ip, :by_search].any? {|addition| not config[addition].nil?}
|
70
|
+
ui.fatal("Must provide a set of additional nodes with --by-name, --by-private-ip, or --by-search")
|
71
|
+
show_usage
|
72
|
+
exit 2
|
73
|
+
end
|
74
|
+
|
75
|
+
node_ips = resolve_node_ips_from_config({
|
76
|
+
:by_search => config[:by_search],
|
77
|
+
:by_name => config[:by_name],
|
78
|
+
:by_private_ip => config[:by_private_ip]
|
79
|
+
})
|
80
|
+
|
81
|
+
nodes = node_ips.map do |ip|
|
82
|
+
{
|
83
|
+
:address => ip,
|
84
|
+
:port => config[:auto_resolve_port] ? "Auto resolve" : config[:port],
|
85
|
+
:condition => config[:condition],
|
86
|
+
:weight => config[:weight]
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
if nodes.empty?
|
91
|
+
ui.fatal("Node resolution did not provide a set of nodes for addition")
|
92
|
+
exit 3
|
93
|
+
end
|
94
|
+
|
95
|
+
target_load_balancers = lb_connection.list_load_balancers
|
96
|
+
|
97
|
+
if config[:only]
|
98
|
+
only = config[:only].split(",").map(&:to_s)
|
99
|
+
target_load_balancers = target_load_balancers.select {|lb| only.include? lb[:id].to_s}
|
100
|
+
end
|
101
|
+
|
102
|
+
if config[:except]
|
103
|
+
except = config[:except].split(",").map(&:to_s)
|
104
|
+
target_load_balancers = target_load_balancers.reject {|lb| except.include? lb[:id].to_s}
|
105
|
+
end
|
106
|
+
|
107
|
+
if target_load_balancers.empty?
|
108
|
+
ui.fatal("Load balancer resolution did not provide a set of target load balancers")
|
109
|
+
exit 4
|
110
|
+
end
|
111
|
+
|
112
|
+
ui.output(format_for_display({
|
113
|
+
:targets => target_load_balancers.map {|lb| lb[:name]},
|
114
|
+
:nodes => nodes
|
115
|
+
}))
|
116
|
+
|
117
|
+
unless config[:force]
|
118
|
+
ui.confirm("Do you really want to add these nodes")
|
119
|
+
end
|
120
|
+
|
121
|
+
target_load_balancers.each do |lb|
|
122
|
+
begin
|
123
|
+
ui.output("Opening #{lb[:name]}")
|
124
|
+
balancer = lb_connection.get_load_balancer(lb[:id])
|
125
|
+
lb_nodes = balancer.list_nodes
|
126
|
+
lb_node_ips = lb_nodes.map {|lbn| lbn[:address]}
|
127
|
+
|
128
|
+
if config[:auto_resolve_port]
|
129
|
+
nodes_for_balancer = nodes.dup
|
130
|
+
|
131
|
+
port = lb_nodes.first[:port]
|
132
|
+
ui.output(ui.color("Auto resolved port to: #{port}", :cyan))
|
133
|
+
|
134
|
+
nodes_for_balancer.each do |nfb|
|
135
|
+
nfb[:port] = port
|
136
|
+
end
|
137
|
+
else
|
138
|
+
nodes_for_balancer = nodes
|
139
|
+
end
|
140
|
+
|
141
|
+
nodes_for_balancer.each do |node|
|
142
|
+
if lb_node_ips.include?(node[:address])
|
143
|
+
ui.warn("Skipping node #{node[:address]}")
|
144
|
+
else
|
145
|
+
ui.output("Adding node #{node[:address]}")
|
146
|
+
if balancer.create_node(node)
|
147
|
+
ui.output(ui.color("Success", :green))
|
148
|
+
else
|
149
|
+
ui.output(ui.color("Failed", :red))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
rescue CloudLB::Exception::Other => e
|
154
|
+
ui.error("Failed on #{lb[:name]}: CloudLB::Exception [#{e.class.name}] - #{e.message}")
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
ui.output(ui.color("Complete", :green))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Chef
|
2
|
+
class Knife
|
3
|
+
module RackspaceLoadBalancerBase
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
option :rackspace_api_region,
|
7
|
+
:short => "-R REGION",
|
8
|
+
:long => "--rackspace-api-region REGION",
|
9
|
+
:description => "Your rackspace API region. IE: ord, dfw",
|
10
|
+
:proc => Proc.new {|region| Chef::Config[:knife][:rackspace_api_region] = region}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def rackspace_api_credentials
|
14
|
+
{
|
15
|
+
:username => Chef::Config[:knife][:rackspace_api_username],
|
16
|
+
:api_key => Chef::Config[:knife][:rackspace_api_key],
|
17
|
+
:region => Chef::Config[:knife][:rackspace_api_region]
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def lb_connection
|
22
|
+
@lb_connection ||= CloudLB::Connection.new(rackspace_api_credentials)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/rackspace_base'
|
3
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
4
|
+
require 'chef/knife/rackspace_load_balancer_nodes'
|
5
|
+
require 'cloudlb'
|
6
|
+
|
7
|
+
module KnifePlugins
|
8
|
+
class RackspaceLoadBalancerCreate < Chef::Knife
|
9
|
+
include Chef::Knife::RackspaceBase
|
10
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
11
|
+
include Chef::Knife::RackspaceLoadBalancerNodes
|
12
|
+
|
13
|
+
banner "knife rackspace load balancer create NAME (options)"
|
14
|
+
|
15
|
+
option :force,
|
16
|
+
:long => "--force",
|
17
|
+
:description => "Skip user input"
|
18
|
+
|
19
|
+
option :protocol,
|
20
|
+
:long => "--protocol PROTOCOL",
|
21
|
+
:description => "The protocol to balance [Default: HTTP]",
|
22
|
+
:default => "HTTP"
|
23
|
+
|
24
|
+
option :add_nodes_by_search,
|
25
|
+
:long => "--add-nodes-by-search SEARCH",
|
26
|
+
:description => "Node search query resolved by Chef Server to add"
|
27
|
+
|
28
|
+
option :add_nodes_by_private_ip,
|
29
|
+
:long => "--add-nodes-by-private-ip \"IP[,IP]\"",
|
30
|
+
:description => "Comma deliminated list of private ips to add"
|
31
|
+
|
32
|
+
option :add_nodes_by_name,
|
33
|
+
:long => "--add-nodes-by-name \"NAME[,NAME]\"",
|
34
|
+
:description => "Comma deliminated list of node names resolved by Chef Server to add"
|
35
|
+
|
36
|
+
option :node_port,
|
37
|
+
:long => "--node-port PORT",
|
38
|
+
:description => "Add nodes listening to this port DEFAULT: 80",
|
39
|
+
:default => "80"
|
40
|
+
|
41
|
+
option :node_weight,
|
42
|
+
:long => "--node-weight WEIGHT",
|
43
|
+
:description => "Add nodes with this weight",
|
44
|
+
:default => "1"
|
45
|
+
|
46
|
+
option :node_condition,
|
47
|
+
:long => "--node-condition CONDITION",
|
48
|
+
:description => "Add nodes with this condition",
|
49
|
+
:default => "ENABLED"
|
50
|
+
|
51
|
+
option :port,
|
52
|
+
:long => "--port PORT",
|
53
|
+
:description => "Configure the load balancer to listen to this port DEFAULT: 80",
|
54
|
+
:default => "80"
|
55
|
+
|
56
|
+
option :algorithm,
|
57
|
+
:long => "--algorithm ALGORITHM",
|
58
|
+
:description => "The algorithm to employ for load balancing [Defualt: RANDOM]",
|
59
|
+
:default => "RANDOM"
|
60
|
+
|
61
|
+
option :virtual_ip_ids,
|
62
|
+
:long => "--virtual-ip-id \"ID[,ID]\"",
|
63
|
+
:description => "Comma deliminated list of virtual ip ids"
|
64
|
+
|
65
|
+
option :virtual_ip_type,
|
66
|
+
:long => "--virtual-ip-type TYPE",
|
67
|
+
:description => "Type of virtual IP to obtain [DEFAULT: PUBLIC]",
|
68
|
+
:default => "PUBLIC"
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
def run
|
73
|
+
if @name_args.first.nil?
|
74
|
+
ui.fatal("Must provide name")
|
75
|
+
show_usage
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
unless [:add_nodes_by_search, :add_nodes_by_name, :add_nodes_by_private_ip].any? {|addition| not config[addition].nil?}
|
80
|
+
ui.fatal("Must provide nodes via --add-nodes-by-search, --add-nodes-by-node-name, or --add-nodes-by-private-ip")
|
81
|
+
show_usage
|
82
|
+
exit 2
|
83
|
+
end
|
84
|
+
|
85
|
+
node_ips = resolve_node_ips_from_config({
|
86
|
+
:by_search => config[:add_nodes_by_search],
|
87
|
+
:by_name => config[:add_nodes_by_name],
|
88
|
+
:by_private_ip => config[:add_nodes_by_private_ip]
|
89
|
+
})
|
90
|
+
|
91
|
+
nodes = node_ips.map do |ip|
|
92
|
+
{
|
93
|
+
:address => ip,
|
94
|
+
:port => config[:node_port],
|
95
|
+
:condition => config[:node_condition],
|
96
|
+
:weight => config[:node_weight]
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
load_balancer_configuration = {
|
101
|
+
:name => @name_args.first,
|
102
|
+
:protocol => config[:protocol],
|
103
|
+
:port => config[:port],
|
104
|
+
:algorithm => config[:algorithm],
|
105
|
+
:nodes => nodes,
|
106
|
+
:virtual_ip_type => config[:virtual_ip_type]
|
107
|
+
}
|
108
|
+
|
109
|
+
unless config[:virtual_ip_ids].nil?
|
110
|
+
load_balancer_configuration[:virtual_ip_ids] = config[:virtual_ip_ids].split(",")
|
111
|
+
end
|
112
|
+
|
113
|
+
ui.output format_for_display(load_balancer_configuration)
|
114
|
+
|
115
|
+
unless config[:force]
|
116
|
+
ui.confirm("Do you really want to create this load balancer")
|
117
|
+
end
|
118
|
+
|
119
|
+
load_balancer_id = lb_connection.create_load_balancer(load_balancer_configuration)
|
120
|
+
|
121
|
+
ui.output(ui.color("Created load balancer #{@name_args.first}", :green))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/rackspace_base'
|
3
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
4
|
+
require 'cloudlb'
|
5
|
+
|
6
|
+
require 'chef/knife/rackspace_load_balancer_show'
|
7
|
+
|
8
|
+
module KnifePlugins
|
9
|
+
class RackspaceLoadBalancerDelete < Chef::Knife
|
10
|
+
include Chef::Knife::RackspaceBase
|
11
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
12
|
+
|
13
|
+
banner "knife rackspace load balancer delete ID [ID] (options)"
|
14
|
+
|
15
|
+
option :force,
|
16
|
+
:long => "--force",
|
17
|
+
:description => "Skip user prompts"
|
18
|
+
|
19
|
+
option :resolve_node_names,
|
20
|
+
:long => "--resolve-node-names",
|
21
|
+
:description => "Resolve node names against Chef Server"
|
22
|
+
|
23
|
+
def run
|
24
|
+
@name_args.each do |load_balancer_id|
|
25
|
+
show_load_balancer = RackspaceLoadBalancerShow.new
|
26
|
+
show_load_balancer.config[:resolve_node_names] = true if config[:resolve_node_names]
|
27
|
+
show_load_balancer.name_args = [load_balancer_id]
|
28
|
+
show_load_balancer.run
|
29
|
+
|
30
|
+
unless config[:force]
|
31
|
+
ui.confirm("Do you really want to delete this load balancer")
|
32
|
+
end
|
33
|
+
|
34
|
+
load_balancer = lb_connection.get_load_balancer(load_balancer_id)
|
35
|
+
load_balancer.destroy!
|
36
|
+
|
37
|
+
ui.warn("Deleted load balancer #{load_balancer_id}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/rackspace_base'
|
3
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
4
|
+
require 'chef/knife/rackspace_load_balancer_nodes'
|
5
|
+
require 'cloudlb'
|
6
|
+
|
7
|
+
module KnifePlugins
|
8
|
+
class RackspaceLoadBalancerDeleteNode < Chef::Knife
|
9
|
+
include Chef::Knife::RackspaceBase
|
10
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
11
|
+
include Chef::Knife::RackspaceLoadBalancerNodes
|
12
|
+
|
13
|
+
banner "knife rackspace load balancer delete node (options)"
|
14
|
+
|
15
|
+
option :force,
|
16
|
+
:long => "--force",
|
17
|
+
:description => "Skip user input"
|
18
|
+
|
19
|
+
option :all,
|
20
|
+
:long => "--all",
|
21
|
+
:description => "Remove from all load balancers"
|
22
|
+
|
23
|
+
option :except,
|
24
|
+
:long => "--except \"ID[,ID]\"",
|
25
|
+
:description => "List of load balancer ids to omit (Implies --all)"
|
26
|
+
|
27
|
+
option :only,
|
28
|
+
:long => "--only \"ID[,ID]\"",
|
29
|
+
:description => "List of load balancer ids to remove from"
|
30
|
+
|
31
|
+
option :by_name,
|
32
|
+
:long => "--by-name \"NAME[,NAME]\"",
|
33
|
+
:description => "Resolve names against chef server to produce list of nodes to remove"
|
34
|
+
|
35
|
+
option :by_private_ip,
|
36
|
+
:long => "--by-private-ip \"IP[,IP]\"",
|
37
|
+
:description => "List of nodes given by private ips to remove"
|
38
|
+
|
39
|
+
option :by_search,
|
40
|
+
:long => "--by-search SEARCH",
|
41
|
+
:description => "Resolve search against chef server to produce list of nodes to remove"
|
42
|
+
|
43
|
+
def run
|
44
|
+
unless [:all, :except, :only].any? {|target| not config[target].nil?}
|
45
|
+
ui.fatal("Must provide a target set of load balancers with --all, --except, or --only")
|
46
|
+
show_usage
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
|
50
|
+
unless [:by_name, :by_private_ip, :by_search].any? {|addition| not config[addition].nil?}
|
51
|
+
ui.fatal("Must provide a set of nodes to remove with --by-name, --by-private-ip, or --by-search")
|
52
|
+
show_usage
|
53
|
+
exit 2
|
54
|
+
end
|
55
|
+
|
56
|
+
node_ips = resolve_node_ips_from_config({
|
57
|
+
:by_search => config[:by_search],
|
58
|
+
:by_name => config[:by_name],
|
59
|
+
:by_private_ip => config[:by_private_ip]
|
60
|
+
})
|
61
|
+
|
62
|
+
nodes = node_ips.map do |ip|
|
63
|
+
{ :address => ip }
|
64
|
+
end
|
65
|
+
|
66
|
+
if nodes.empty?
|
67
|
+
ui.fatal("Node resolution did not provide a set of nodes for removal")
|
68
|
+
exit 3
|
69
|
+
end
|
70
|
+
|
71
|
+
target_load_balancers = lb_connection.list_load_balancers
|
72
|
+
|
73
|
+
if config[:only]
|
74
|
+
only = config[:only].split(",").map(&:to_s)
|
75
|
+
target_load_balancers = target_load_balancers.select {|lb| only.include? lb[:id].to_s}
|
76
|
+
end
|
77
|
+
|
78
|
+
if config[:except]
|
79
|
+
except = config[:except].split(",").map(&:to_s)
|
80
|
+
target_load_balancers = target_load_balancers.reject {|lb| except.include? lb[:id].to_s}
|
81
|
+
end
|
82
|
+
|
83
|
+
if target_load_balancers.empty?
|
84
|
+
ui.fatal("Load balancer resolution did not provide a set of target load balancers")
|
85
|
+
exit 4
|
86
|
+
end
|
87
|
+
|
88
|
+
ui.output(format_for_display({
|
89
|
+
:targets => target_load_balancers.map {|lb| lb[:name]},
|
90
|
+
:nodes => nodes
|
91
|
+
}))
|
92
|
+
|
93
|
+
unless config[:force]
|
94
|
+
ui.confirm("Do you really want to remove these nodes")
|
95
|
+
end
|
96
|
+
|
97
|
+
target_load_balancers.each do |lb|
|
98
|
+
ui.output("Opening #{lb[:name]}")
|
99
|
+
balancer = lb_connection.get_load_balancer(lb[:id])
|
100
|
+
|
101
|
+
lb_nodes = balancer.list_nodes
|
102
|
+
lb_nodes.each do |lb_node_hash|
|
103
|
+
if node_ips.include? lb_node_hash[:address].to_s
|
104
|
+
lb_node = balancer.get_node(lb_node_hash[:id])
|
105
|
+
ui.output("Removing node #{lb_node.address}")
|
106
|
+
if lb_node.destroy!
|
107
|
+
ui.output(ui.color("Success", :green))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
ui.output(ui.color("Complete", :green))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/knife/rackspace_base'
|
3
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
4
|
+
require 'cloudlb'
|
5
|
+
|
6
|
+
module KnifePlugins
|
7
|
+
class RackspaceLoadBalancerList < Chef::Knife
|
8
|
+
|
9
|
+
include Chef::Knife::RackspaceBase
|
10
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
11
|
+
|
12
|
+
banner "knife rackspace load balancer list"
|
13
|
+
|
14
|
+
def run
|
15
|
+
load_balancer_list = [
|
16
|
+
ui.color("Id", :bold),
|
17
|
+
ui.color("Name", :bold),
|
18
|
+
ui.color("Nodes", :bold),
|
19
|
+
ui.color("Virtual Ip", :bold),
|
20
|
+
ui.color("Protocol / Port", :bold),
|
21
|
+
ui.color("Status", :bold),
|
22
|
+
]
|
23
|
+
|
24
|
+
lb_connection.list_load_balancers.each do |load_balancer|
|
25
|
+
vip = (load_balancer[:virtualIps].detect {|vip| vip[:ipVersion] == "IPV4"})
|
26
|
+
vip ||= load_balancer[:virtualIps].first
|
27
|
+
|
28
|
+
load_balancer_list << load_balancer[:id].to_s
|
29
|
+
load_balancer_list << load_balancer[:name].to_s
|
30
|
+
load_balancer_list << load_balancer[:nodeCount].to_s
|
31
|
+
load_balancer_list << (vip.nil? ? "None" : vip[:address].to_s)
|
32
|
+
load_balancer_list << "#{load_balancer[:protocol]} / #{load_balancer[:port].to_s}"
|
33
|
+
load_balancer_list << ui.color(load_balancer[:status].to_s, load_balancer[:status] == "ACTIVE" ? :green : :red)
|
34
|
+
end
|
35
|
+
|
36
|
+
puts ui.list(load_balancer_list, :columns_across, 6)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
class Chef
|
2
|
+
class Knife
|
3
|
+
module RackspaceLoadBalancerNodes
|
4
|
+
def nodes_by_search(query)
|
5
|
+
nodes = []
|
6
|
+
Chef::Search::Query.new.search(:node, query) do |n|
|
7
|
+
nodes << n
|
8
|
+
end
|
9
|
+
|
10
|
+
nodes
|
11
|
+
end
|
12
|
+
|
13
|
+
def resolve_node_ips_from_config(options)
|
14
|
+
node_ips = []
|
15
|
+
if options[:by_search]
|
16
|
+
nodes_from_chef = nodes_by_search(options[:by_search])
|
17
|
+
|
18
|
+
node_ips = nodes_from_chef.map {|n| n.rackspace.private_ip}
|
19
|
+
elsif options[:by_name]
|
20
|
+
node_names = options[:by_name].split(",")
|
21
|
+
nodes_from_chef = nodes_by_search(node_names.map {|n| "name:#{n}"}.join(" OR "))
|
22
|
+
|
23
|
+
node_ips = nodes_from_chef.map {|n| n.rackspace.private_ip}
|
24
|
+
elsif options[:by_private_ip]
|
25
|
+
node_ips = config[:by_private_ip].split(",")
|
26
|
+
end
|
27
|
+
|
28
|
+
node_ips
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'chef/knife'
|
2
|
+
require 'chef/search/query'
|
3
|
+
require 'chef/knife/rackspace_base'
|
4
|
+
require 'chef/knife/rackspace_load_balancer_base'
|
5
|
+
require 'chef/knife/rackspace_load_balancer_nodes'
|
6
|
+
require 'cloudlb'
|
7
|
+
|
8
|
+
module KnifePlugins
|
9
|
+
class RackspaceLoadBalancerShow < Chef::Knife
|
10
|
+
include Chef::Knife::RackspaceBase
|
11
|
+
include Chef::Knife::RackspaceLoadBalancerBase
|
12
|
+
include Chef::Knife::RackspaceLoadBalancerNodes
|
13
|
+
|
14
|
+
banner "knife rackspace load balancer show ID [ID] (options)"
|
15
|
+
|
16
|
+
option :resolve_node_names,
|
17
|
+
:long => "--resolve-node-names",
|
18
|
+
:description => "Resolve node names against chef server"
|
19
|
+
|
20
|
+
def run
|
21
|
+
@name_args.each do |load_balancer_id|
|
22
|
+
load_balancer = lb_connection.get_load_balancer(load_balancer_id)
|
23
|
+
nodes = load_balancer.list_nodes
|
24
|
+
|
25
|
+
load_balancer_info = {
|
26
|
+
:name => load_balancer.name,
|
27
|
+
:id => load_balancer.id,
|
28
|
+
:protocol => load_balancer.protocol,
|
29
|
+
:port => load_balancer.port,
|
30
|
+
:status => ui.color(load_balancer.status, load_balancer.status == "ACTIVE" ? :green : :red)
|
31
|
+
}
|
32
|
+
|
33
|
+
vip_list = [
|
34
|
+
ui.color("Virtual Ip(s)", :bold),
|
35
|
+
ui.color("Id", :bold),
|
36
|
+
ui.color("Version", :bold),
|
37
|
+
]
|
38
|
+
|
39
|
+
load_balancer.list_virtual_ips.each do |vip|
|
40
|
+
vip_list << vip[:address].to_s
|
41
|
+
vip_list << vip[:id].to_s
|
42
|
+
vip_list << vip[:ipVersion].to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
node_list = [
|
46
|
+
ui.color("Node(s)", :bold),
|
47
|
+
ui.color("Address", :bold),
|
48
|
+
ui.color("Port", :bold),
|
49
|
+
ui.color("Condition", :bold),
|
50
|
+
ui.color("Status", :bold)
|
51
|
+
]
|
52
|
+
|
53
|
+
nodes.each do |node|
|
54
|
+
node_name = node[:id]
|
55
|
+
|
56
|
+
if config[:resolve_node_names]
|
57
|
+
first_node = nodes_by_search("private_ip:#{node[:address]}").first
|
58
|
+
node_name = first_node.name unless first_node.nil? || first_node.name.nil?
|
59
|
+
end
|
60
|
+
|
61
|
+
node_list << node_name.to_s
|
62
|
+
node_list << node[:address].to_s
|
63
|
+
node_list << node[:port].to_s
|
64
|
+
node_list << ui.color(node[:condition].to_s, node[:condition] == "ENABLED" ? :green : :red)
|
65
|
+
node_list << ui.color(node[:status].to_s, node[:status] == "ONLINE" ? :green : :red)
|
66
|
+
end
|
67
|
+
|
68
|
+
ui.output(format_for_display(load_balancer_info))
|
69
|
+
ui.output("\n")
|
70
|
+
ui.output(ui.list(vip_list, :columns_across, 3))
|
71
|
+
ui.output(ui.list(node_list, :columns_across, 5))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: knife-rackspace-load-balancer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Matthew Vermaak
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-04-12 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: chef
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.10.8
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: knife-rackspace
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.5.12
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: cloudlb
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 0.1.0
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
description: A gem to extend knife-rackspace allowing cloud load balancer management.
|
50
|
+
email: dev@howaboutwe.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- .gitignore
|
59
|
+
- LICENSE.txt
|
60
|
+
- README.rdoc
|
61
|
+
- knife-rackspace-load-balancer.gemspec
|
62
|
+
- lib/chef/knife/rackspace_load_balancer_add_node.rb
|
63
|
+
- lib/chef/knife/rackspace_load_balancer_base.rb
|
64
|
+
- lib/chef/knife/rackspace_load_balancer_create.rb
|
65
|
+
- lib/chef/knife/rackspace_load_balancer_delete.rb
|
66
|
+
- lib/chef/knife/rackspace_load_balancer_delete_node.rb
|
67
|
+
- lib/chef/knife/rackspace_load_balancer_list.rb
|
68
|
+
- lib/chef/knife/rackspace_load_balancer_nodes.rb
|
69
|
+
- lib/chef/knife/rackspace_load_balancer_show.rb
|
70
|
+
- lib/version.rb
|
71
|
+
has_rdoc: true
|
72
|
+
homepage: http://github.com/howaboutwe/knife-rackspace-load-balancer
|
73
|
+
licenses:
|
74
|
+
- MIT
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.6.2
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: Rackspace cloud load balancer support for knife
|
99
|
+
test_files: []
|
100
|
+
|