knife-glesys 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in knife-glesys.gemspec
4
+ gem "fog", :github => "fog/fog"
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Simon Gate
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # Knife Glesys
2
+
3
+ knife-glesys is a Knife addon that will make it easier manage your VPS at [Glesys](http://www.glesys.se). You can create,
4
+ delete, list and show info about your servers.
5
+ To be able to use this addon you need to create a Glesys API key with permission to `IP` and `SERVER`. You do this in their control panel.
6
+
7
+ ## Installation
8
+
9
+ To use the addon install it as a normal gem, from your command line run:
10
+
11
+ ```bash
12
+ $ gem install knife-glesys
13
+ ```
14
+
15
+ ## Configuration
16
+
17
+ To configure the addon you can either add your Glesys username and your API key to knife.rb in your chef directory.
18
+
19
+ ```ruby
20
+ knife[:glesys_username] = "YOUR USERNAME"
21
+ knife[:glesys_api_key] = "YOUR API KEY"
22
+ ```
23
+
24
+ Or you can pass your username and your API key to the knife glesys command.
25
+
26
+ ```bash
27
+ $ knife glesys server list --glesys-api-key "YOUR API KEY" --glesys-username "YOUR USERNAME"
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ### Create a new server
33
+
34
+ When creating a new instance you there are some options you need to supply for it to work, `template` (server image),
35
+ `platform`, `data-center`, `root-password` and a `hostname`. It is recommended that you also specify the number of
36
+ cpu cores, the amount of memory and disksize. Or else these will default to 1 cpu core, 512 mb memory and 10 gb disk.
37
+ If you want to view the options you can just run the command without any options.
38
+
39
+ ```bash
40
+ $ knife glesys server create (options)
41
+ ```
42
+
43
+ To create a OpenVZ Debian server in Stockholm you run this command (This will also provision the host with the `db` role):
44
+
45
+ ```bash
46
+ $ knife glesys server create --template "Debian 6.0 64-bit" --platform "OpenVZ" --data-center "Stockholm" \
47
+ --cpu-cores 1 --memory-size 128 --transfer 50 -N database --run-list 'role[:db]' \
48
+ --hostname "data.example.com" --root-password 'passw0rd' --description "Redis database server"
49
+ ```
50
+
51
+ ### List available templates
52
+
53
+ Glesys offers many different templates (or images) to use when you spin up a new VPS. To get a list of all available and on which platform you run:
54
+
55
+ ```bash
56
+ $ knife glesys templates list
57
+ ```
58
+
59
+ ### List your servers
60
+
61
+ To list your servers that you have connected to your account. This will give you a list with
62
+
63
+ ```bash
64
+ $ knife glesys server list
65
+ ```
66
+
67
+ ### More information about a server
68
+
69
+ To get detailed information about a server like how much memory that is used and how much the server costs you can issue the info command.
70
+
71
+ ```bash
72
+ $ knife glesys server info vz31337
73
+ ```
74
+
75
+ ### Delete a server
76
+
77
+ Every server has a uniqe id at Glesys. Just pass this id to the delete command to erase the server.
78
+
79
+ ```bash
80
+ $ knife glesys server delete vz31337
81
+ ```
82
+
83
+ And to at the same time delete the Chef node pass the `--purge` option to the delete command.
84
+
85
+ ## TODO
86
+
87
+ There are a few things that still needs to be fixed (in no special order).
88
+
89
+ * Manage Glesys IPs
90
+ * Graph server stats in console
91
+
92
+ ## Known issues
93
+
94
+ * Needs HEAD version of [fog](https://github.com/fog/fog) to work
95
+
96
+ ## Contributing
97
+
98
+ I like contributions, so if you find any errors please add a issue or even better, send a pull request.
99
+
100
+ 1. Fork it
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
103
+ 4. Push to the branch (`git push origin my-new-feature`)
104
+ 5. Create new Pull Request
105
+
106
+ ## Copyright
107
+
108
+ (The MIT License)
109
+
110
+ Copyright (c) 2013 smgt (Simon Gate)
111
+
112
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
113
+
114
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
115
+
116
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'knife-glesys/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "knife-glesys"
8
+ gem.version = Knife::Glesys::VERSION
9
+ gem.authors = ["Simon Gate"]
10
+ gem.email = ["simon@smgt.me"]
11
+ gem.description = %q{Glesys support for Chef's Knife Command}
12
+ gem.summary = gem.description
13
+ gem.homepage = "https://github.com/smgt/knife-glesys"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.add_dependency "fog", "~> 1.9"
20
+ gem.add_dependency "chef", ">= 0.10.10"
21
+ end
@@ -0,0 +1,68 @@
1
+ require "chef/knife"
2
+
3
+ class Chef
4
+ class Knife
5
+ module GlesysBase
6
+
7
+ def self.included(includer)
8
+ includer.class_eval do
9
+
10
+ deps do
11
+ require 'fog'
12
+ require 'readline'
13
+ require 'chef/json_compat'
14
+ end
15
+
16
+ option :glesys_api_key,
17
+ :short => "-A KEY",
18
+ :long => "--glesys-api-key KEY",
19
+ :description => "Your Glesys API key",
20
+ :proc => Proc.new { |key| Chef::Config[:knife][:glesys_api_key] = key }
21
+
22
+ option :glesys_username,
23
+ :short => "-U USERNAME",
24
+ :long => "--glesys-username USERNAME",
25
+ :description => "Your Glesysusername",
26
+ :proc => Proc.new { |key| Chef::Config[:knife][:glesys_username] = key }
27
+ end
28
+ end
29
+
30
+ def connection
31
+ @connection ||= begin
32
+ connection = Fog::Compute.new(
33
+ :provider => 'Glesys',
34
+ :glesys_api_key => Chef::Config[:knife][:glesys_api_key],
35
+ :glesys_username => Chef::Config[:knife][:glesys_username],
36
+ )
37
+ end
38
+ end
39
+
40
+ def msg_pair(label, value, color=:cyan)
41
+ if value && !value.to_s.empty?
42
+ puts "#{ui.color(label, color)}: #{value}"
43
+ end
44
+ end
45
+
46
+ def locate_config_value(key)
47
+ key = key.to_sym
48
+ config[key] || Chef::Config[:knife][key]
49
+ end
50
+
51
+ def color_state(state)
52
+
53
+ return ui.color("unknown", :cyan) if state.nil?
54
+
55
+ case state.to_s.downcase
56
+ when 'shutting-down','terminated','stopping','stopped' then ui.color(state, :red)
57
+ when 'pending', 'locked' then ui.color(state, :yellow)
58
+ else ui.color(state, :green)
59
+ end
60
+
61
+ end
62
+
63
+ def validate!
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,271 @@
1
+ require "chef/knife/glesys_base"
2
+
3
+ class Chef
4
+ class Knife
5
+ class GlesysServerCreate < Knife
6
+
7
+ include Knife::GlesysBase
8
+
9
+ banner "knife glesys server create (options)"
10
+
11
+ attr_reader :server
12
+
13
+ deps do
14
+ require 'fog'
15
+ require 'readline'
16
+ require 'chef/json_compat'
17
+ require 'chef/knife/bootstrap'
18
+ Chef::Knife::Bootstrap.load_deps
19
+ end
20
+
21
+ option :image,
22
+ :short => "-i IMAGE",
23
+ :long => "--image IMAGE",
24
+ :description => "The image to use on the server (Debian 6.0 64-bit, Ubuntu, etc)",
25
+ :proc => Proc.new { |f| Chef::Config[:knife][:image] = f },
26
+ :required => true
27
+
28
+ option :platform,
29
+ :short => "-p PLATFORM",
30
+ :long => "--platform PLATFORM",
31
+ :description => "The platform to launch the server on (Xen or OpenVZ)",
32
+ :proc => Proc.new { |f| Chef::Config[:knife][:platform] = f },
33
+ :required => true
34
+
35
+ option :datacenter,
36
+ :long => "--data-center DATACENTER",
37
+ :description => "The data center to launch the server in (Falkenberg, New York, Amsterdam or Stockholm)",
38
+ :proc => Proc.new { |f| Chef::Config[:knife][:datacenter] = f },
39
+ :required => true
40
+
41
+ option :rootpassword,
42
+ :short => "-P PASSWORD",
43
+ :long => "--root-password PASSWORD",
44
+ :description => "Root password to set on the new server",
45
+ :required => true
46
+
47
+ option :hostname,
48
+ :short => "-h HOSTNAME",
49
+ :long => "--hostname HOSTNAME",
50
+ :hostname => "Server hostname",
51
+ :required => true
52
+
53
+ option :cpucores,
54
+ :long => "--cpu-cores CPUCORES",
55
+ :description => "The number cpu cores (1-8)",
56
+ :proc => Proc.new { |f| Chef::Config[:knife][:cpucores] = f }
57
+
58
+ option :memorysize,
59
+ :long => "--memory-size MEMORY",
60
+ :description => "The amount of memory (128mb - 16384mb)",
61
+ :proc => Proc.new { |f| Chef::Config[:knife][:memorysize] = f }
62
+
63
+ option :disksize,
64
+ :long => "--disk-size DISK",
65
+ :description => "The amount of disk (5gb-100gb)",
66
+ :proc => Proc.new { |f| Chef::Config[:knife][:disksize] = f }
67
+
68
+ option :transfer,
69
+ :long => "--transfer TRANSFER",
70
+ :description => "Transfer (50gb - 10000gb)",
71
+ :proc => Proc.new { |f| Chef::Config[:knife][:transfer] = f }
72
+
73
+ option :chef_node_name,
74
+ :short => "-N NAME",
75
+ :long => "--node-name NAME",
76
+ :description => "Chef node name",
77
+ :proc => Proc.new { |f| Chef::Config[:knife][:chef_node_name] = f }
78
+
79
+ option :description,
80
+ :short => "-D DESCRIPTION",
81
+ :long => "--description DESCRIPTION",
82
+ :description => "Server description"
83
+
84
+ option :ipv4,
85
+ :long => "--ipv4 IP",
86
+ :hostname => "IPV4 to assign the server"
87
+
88
+ option :ipv6,
89
+ :long => "--ipv6 IP",
90
+ :hostname => "IPV6 to assign the server"
91
+
92
+ option :run_list,
93
+ :short => "-r RUN_LIST",
94
+ :long => "--run-list RUN_LIST",
95
+ :description => "Comma separated list of roles/recipes to apply",
96
+ :proc => lambda { |o| o.split(/[\s,]+/) }
97
+
98
+ option :ssh_gateway,
99
+ :short => "-w GATEWAY",
100
+ :long => "--ssh-gateway GATEWAY",
101
+ :description => "The SSH gateway server",
102
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_gateway] = key }
103
+
104
+ option :ssh_port,
105
+ :short => "-o PORT",
106
+ :long => "--ssh-port PORT",
107
+ :default => "22",
108
+ :description => "SSH Port",
109
+ :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
110
+
111
+ option :json_attributes,
112
+ :short => "-j JSON",
113
+ :long => "--json-attributes JSON",
114
+ :description => "A JSON string to be added to the first run of chef-client",
115
+ :proc => lambda { |o| JSON.parse(o) }
116
+
117
+ def tcp_test_ssh(hostname, ssh_port)
118
+ tcp_socket = TCPSocket.new(hostname, ssh_port)
119
+ readable = IO.select([tcp_socket], nil, nil, 5)
120
+ if readable
121
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
122
+ yield
123
+ true
124
+ else
125
+ false
126
+ end
127
+ rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
128
+ sleep 2
129
+ false
130
+ rescue Errno::EPERM, Errno::ETIMEDOUT
131
+ false
132
+ ensure
133
+ tcp_socket && tcp_socket.close
134
+ end
135
+
136
+ def run
137
+ validate!
138
+
139
+ default_server = create_server_def
140
+ @server = connection.servers.create default_server
141
+
142
+ # Show information about the new server
143
+ msg_pair("Server ID", @server.serverid)
144
+ msg_pair("State", ui.color(color_state(@server.state),:bold))
145
+ msg_pair("Hostname", @server.hostname)
146
+ msg_pair("Description", @server.description)
147
+ puts "\n"
148
+ msg_pair("IPv4", @server.iplist.select{|i| i["version"] == 4}.collect{|i| i["ipaddress"]}.join(", "))
149
+ msg_pair("IPv6", @server.iplist.select{|i| i["version"] == 6}.collect{|i| i["ipaddress"]}.join(", "))
150
+ puts "\n"
151
+ msg_pair("CPU Cores", @server.cpucores)
152
+ msg_pair("Memory", "#{@server.memorysize} MB")
153
+ msg_pair("Disk", "#{@server.disksize} GB")
154
+ puts "\n"
155
+ msg_pair("Image", @server.templatename)
156
+ msg_pair("Platform", @server.platform)
157
+ msg_pair("Datacenter", @server.datacenter)
158
+
159
+ # Waiting for server to boot
160
+ print "\nBooting"
161
+ @server.wait_for{ print "."; ready? }
162
+
163
+ # Waiting for sshd to start
164
+ wait_for_sshd(@server.public_ip_address)
165
+
166
+ # Bootstrap the node
167
+ bootstrap_for_node(@server,@server.public_ip_address).run
168
+
169
+ msg_pair("Server ID", @server.serverid)
170
+ msg_pair("State", ui.color(color_state(@server.state),:bold))
171
+ msg_pair("Hostname", @server.hostname)
172
+ msg_pair("Description", @server.description)
173
+ puts "\n"
174
+ msg_pair("IPv4", @server.iplist.select{|i| i["version"] == 4}.collect{|i| i["ipaddress"]}.join(", "))
175
+ msg_pair("IPv6", @server.iplist.select{|i| i["version"] == 6}.collect{|i| i["ipaddress"]}.join(", "))
176
+ puts "\n"
177
+ msg_pair("CPU Cores", @server.cpucores)
178
+ msg_pair("Memory", "#{@server.memorysize} MB")
179
+ msg_pair("Disk", "#{@server.disksize} GB")
180
+ puts "\n"
181
+ msg_pair("Image", @server.templatename)
182
+ msg_pair("Platform", @server.platform)
183
+ msg_pair("Datacenter", @server.datacenter)
184
+ puts "\n"
185
+ msg_pair("Environment", config[:environment] || '_default')
186
+ msg_pair("Run List", (config[:run_list] || []).join(', '))
187
+ msg_pair("JSON Attributes", config[:json_attributes]) unless !config[:json_attributes] || config[:json_attributes].empty?
188
+ end
189
+
190
+ def create_server_def
191
+ default_server = {
192
+ templatename: locate_config_value(:image),
193
+ datacenter: locate_config_value(:datacenter),
194
+ platform: locate_config_value(:platform),
195
+ memorysize: locate_config_value(:memorysize),
196
+ disksize: locate_config_value(:disksize),
197
+ cpucores: locate_config_value(:cpucores),
198
+ transfer: locate_config_value(:transfer),
199
+ description: config[:description],
200
+ hostname: config[:hostname],
201
+ rootpassword: config[ :rootpassword ]
202
+ }
203
+
204
+ default_server
205
+ end
206
+
207
+ def bootstrap_for_node(server,ssh_host)
208
+ bootstrap = Chef::Knife::Bootstrap.new
209
+ bootstrap.name_args = [ssh_host]
210
+ bootstrap.config[:run_list] = locate_config_value(:run_list) || []
211
+ bootstrap.config[:ssh_user] = "root"
212
+ bootstrap.config[:ssh_port] = config[:ssh_port]
213
+ bootstrap.config[:ssh_password] = server.rootpassword
214
+ bootstrap.config[:ssh_gateway] = config[:ssh_gateway]
215
+ bootstrap.config[:use_sudo] = false
216
+ # bootstrap.config[:identity_file] = config[:identity_file]
217
+ bootstrap.config[:chef_node_name] = locate_config_value(:chef_node_name) || server.serverid
218
+ bootstrap.config[:prerelease] = config[:prerelease]
219
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
220
+ bootstrap.config[:first_boot_attributes] = locate_config_value(:json_attributes) || {}
221
+ bootstrap.config[:distro] = locate_config_value(:distro) || "chef-full"
222
+ bootstrap.config[:template_file] = locate_config_value(:template_file)
223
+ bootstrap.config[:environment] = config[:environment]
224
+
225
+ # knife-bootstrap
226
+ Chef::Config[:knife][:hints] ||= {}
227
+ Chef::Config[:knife][:hints]["glesys"] ||= {}
228
+ bootstrap
229
+ end
230
+
231
+ def wait_for_sshd(hostname)
232
+ config[:ssh_gateway] ? wait_for_tunnelled_sshd(hostname) : wait_for_direct_sshd(hostname, config[:ssh_port])
233
+ end
234
+
235
+ def wait_for_tunnelled_sshd(hostname)
236
+ print("\nWaiting for sshd tunnel.")
237
+ print(".") until tunnel_test_ssh(ssh_connect_host) {
238
+ sleep @initial_sleep_delay ||= (vpc_mode? ? 40 : 10)
239
+ puts("done")
240
+ }
241
+ end
242
+
243
+ def tunnel_test_ssh(hostname, &block)
244
+ gw_host, gw_user = config[:ssh_gateway].split('@').reverse
245
+ gw_host, gw_port = gw_host.split(':')
246
+ gateway = Net::SSH::Gateway.new(gw_host, gw_user, :port => gw_port || 22)
247
+ status = false
248
+ gateway.open(hostname, config[:ssh_port]) do |local_tunnel_port|
249
+ status = tcp_test_ssh('localhost', local_tunnel_port, &block)
250
+ end
251
+ status
252
+ rescue SocketError, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH, IOError
253
+ sleep 2
254
+ false
255
+ rescue Errno::EPERM, Errno::ETIMEDOUT
256
+ false
257
+ end
258
+
259
+ def wait_for_direct_sshd(hostname, ssh_port)
260
+ print "\nWaiting for ssh."
261
+ print(".") until tcp_test_ssh(ssh_connect_host, ssh_port) {
262
+ puts "done"
263
+ }
264
+ end
265
+
266
+ def ssh_connect_host
267
+ @server.public_ip_address
268
+ end
269
+ end
270
+ end
271
+ end
@@ -0,0 +1,110 @@
1
+ require "chef/knife/glesys_base"
2
+
3
+ # These two are needed for the '--purge' deletion case
4
+ require 'chef/node'
5
+ require 'chef/api_client'
6
+
7
+ class Chef
8
+ class Knife
9
+ class GlesysServerDelete < Knife
10
+
11
+ include Knife::GlesysBase
12
+
13
+ banner "knife glesys server delete SERVER [SERVER] (options)"
14
+
15
+ deps do
16
+ require 'fog'
17
+ require 'readline'
18
+ Chef::Knife::Bootstrap.load_deps
19
+ end
20
+
21
+ option :purge,
22
+ :short => "-P",
23
+ :long => "--purge",
24
+ :boolean => true,
25
+ :default => false,
26
+ :description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the Glesys server itself. Assumes node and client have the same name as the server (if not, add the '--node-name' option)."
27
+
28
+ option :keepip,
29
+ :short => "-i",
30
+ :long => "--keep-ip",
31
+ :boolean => true,
32
+ :default => false,
33
+ :description => "Don't release the IP"
34
+
35
+ option :chef_node_name,
36
+ :short => "-N NAME",
37
+ :long => "--node-name NAME",
38
+ :description => "The name of the node and client to delete, if it differs from the server name. Only has meaning when used with the '--purge' option."
39
+
40
+ # Extracted from Chef::Knife.delete_object, because it has a
41
+ # confirmation step built in... By specifying the '--purge'
42
+ # flag (and also explicitly confirming the server destruction!)
43
+ # the user is already making their intent known. It is not
44
+ # necessary to make them confirm two more times.
45
+ def destroy_item(klass, name, type_name)
46
+ begin
47
+ object = klass.load(name)
48
+ object.destroy
49
+ ui.warn("Deleted #{type_name} #{name}")
50
+ rescue Net::HTTPServerException
51
+ ui.warn("Could not find a #{type_name} named #{name} to delete!")
52
+ end
53
+ end
54
+
55
+ def run
56
+ @name_args.each do |server_id|
57
+ server = connection.servers.get(server_id)
58
+ puts "\n"
59
+ msg_pair("Server ID", server.serverid)
60
+ state = case server.state.to_s.downcase
61
+ when 'shutting-down','terminated','stopping','stopped' then ui.color(server.state, :red)
62
+ when 'pending' then ui.color(server.state, :yellow)
63
+ else ui.color(server.state, :green)
64
+ end
65
+ msg_pair("State", ui.color(state,:bold))
66
+ msg_pair("Hostname", server.hostname)
67
+ msg_pair("Description", server.description) if server.respond_to? :description # When fog supports description
68
+ puts "\n"
69
+ msg_pair("IPv4", server.iplist.select{|i| i["version"] == 4}.collect{|i| i["ipaddress"]}.join(", "))
70
+ msg_pair("IPv6", server.iplist.select{|i| i["version"] == 6}.collect{|i| i["ipaddress"]}.join(", "))
71
+ puts "\n"
72
+ msg_pair("CPU Cores", server.cpucores)
73
+ msg_pair("Memory", "#{server.memorysize} MB")
74
+ msg_pair("Disk", "#{server.disksize} GB")
75
+ puts "\n"
76
+ msg_pair("Template", server.templatename)
77
+ msg_pair("Platform", server.platform)
78
+ msg_pair("Datacenter", server.datacenter)
79
+ puts "\n"
80
+ msg_pair("Transfer", "#{server.transfer['usage']} of #{server.transfer['max']} #{server.transfer['unit']}")
81
+ msg_pair("Cost", "#{server.cost['amount']} #{server.cost['currency']} per #{server.cost['timeperiod']}")
82
+
83
+ puts "\n"
84
+
85
+ ui.confirm("Do you wan't to delete this server?")
86
+
87
+ if config[:keepip]
88
+ server.keepip = config[:keepip]
89
+ end
90
+
91
+ server.destroy
92
+
93
+ ui.warn("Deleted server #{server_id}")
94
+
95
+ if config[:purge]
96
+ thing_to_delete = config[:chef_node_name] || server_id
97
+ destroy_item(Chef::Node, thing_to_delete, "node")
98
+ destroy_item(Chef::ApiClient, thing_to_delete, "client")
99
+ else
100
+ ui.warn("Corresponding node and client for the #{server_id} server were not deleted and remain registered with the Chef Server")
101
+ end
102
+ end
103
+
104
+ rescue NoMethodError
105
+ ui.error("Could not locate server '#{server_id}'.")
106
+ end
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,45 @@
1
+ require "chef/knife/glesys_base"
2
+
3
+ class Chef
4
+ class Knife
5
+ class GlesysServerInfo < Knife
6
+
7
+ include Knife::GlesysBase
8
+
9
+ banner "knife glesys server info SERVER"
10
+
11
+ deps do
12
+ require 'fog'
13
+ require 'readline'
14
+ Chef::Knife::Bootstrap.load_deps
15
+ end
16
+
17
+ def run
18
+ server = connection.servers.get(@name_args.first)
19
+ msg_pair("Server ID", server.serverid)
20
+ msg_pair("State", ui.color(color_state(server.state),:bold))
21
+ msg_pair("Hostname", server.hostname)
22
+ msg_pair("Description", server.description) if server.respond_to? :description # When fog supports description
23
+ puts "\n"
24
+ msg_pair("IPv4", server.iplist.select{|i| i["version"] == 4}.collect{|i| i["ipaddress"]}.join(", "))
25
+ msg_pair("IPv6", server.iplist.select{|i| i["version"] == 6}.collect{|i| i["ipaddress"]}.join(", "))
26
+ puts "\n"
27
+ msg_pair("CPU Cores", server.cpucores)
28
+ msg_pair("Memory", "#{server.memorysize} MB")
29
+ msg_pair("Disk", "#{server.disksize} GB")
30
+ puts "\n"
31
+ msg_pair("Image", server.templatename)
32
+ msg_pair("Platform", server.platform)
33
+ msg_pair("Datacenter", server.datacenter)
34
+ puts "\n"
35
+ msg(ui.color("Current Usage:",:bold))
36
+ msg_pair("Transfer", "#{ui.color(server.usage['transfer']['usage'].to_s, :yellow)} of #{server.usage['transfer']['max']} #{server.usage['transfer']['unit']}")
37
+ msg_pair("Memory", "#{ui.color(server.usage['memory']['usage'].to_s, :yellow)} of #{server.usage['memory']['max']} #{server.usage['memory']['unit']}")
38
+ msg_pair("CPU", "#{ui.color(server.usage['cpu']['usage'].to_s, :yellow)} of #{server.usage['cpu']['max']} #{server.usage['cpu']['unit']}")
39
+ msg_pair("Disk", "#{ui.color(server.usage['disk']['usage'].to_s, :yellow)} of #{server.usage['disk']['max']} #{server.usage['disk']['unit']}")
40
+ msg_pair("Cost", "#{ui.color(server.cost['amount'].to_s, :yellow)} #{server.cost['currency']} per #{server.cost['timeperiod']}")
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ require "chef/knife/glesys_base"
2
+
3
+ class Chef
4
+ class Knife
5
+ class GlesysServerList < Knife
6
+
7
+ include Knife::GlesysBase
8
+
9
+ banner "knife glesys server list"
10
+
11
+ deps do
12
+ require 'fog'
13
+ require 'readline'
14
+ Chef::Knife::Bootstrap.load_deps
15
+ end
16
+
17
+ def run
18
+
19
+ server_list = [
20
+ ui.color('ID', :bold),
21
+ ui.color("Hostname", :bold),
22
+ ui.color("Platform", :bold),
23
+ ui.color("Datacenter", :bold),
24
+ ].flatten.compact
25
+
26
+ connection.servers.all.each do |server|
27
+ server_list << server.serverid.to_s
28
+ server_list << server.hostname
29
+ server_list << server.platform
30
+ server_list << server.datacenter
31
+ end
32
+
33
+ puts ui.list(server_list, :columns_across, 4)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ require "chef/knife/glesys_base"
2
+
3
+ class Chef
4
+ class Knife
5
+ class GlesysTemplateList < Knife
6
+ include Knife::GlesysBase
7
+
8
+ banner "knife glesys template list (options)"
9
+
10
+ deps do
11
+ require 'fog'
12
+ require 'readline'
13
+ Chef::Knife::Bootstrap.load_deps
14
+ end
15
+
16
+ def run
17
+
18
+ template_list = [
19
+ ui.color('Platform', :bold),
20
+ ui.color('Name', :bold),
21
+ ui.color('Operating System', :bold),
22
+ ui.color('Min Memory Size', :bold),
23
+ ui.color('Min Disk Size', :bold),
24
+
25
+ ]
26
+
27
+ connection.templates.sort_by(&:platform).each do |template|
28
+ template_list << template.platform
29
+ template_list << template.name
30
+ template_list << template.operating_system
31
+ template_list << "#{template.minimum_memory_size} mb"
32
+ template_list << "#{template.minimum_disk_size} gb"
33
+ end
34
+
35
+ puts ui.list(template_list, :columns_across, 5)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ module Knife
2
+ module Glesys
3
+ VERSION = "0.1.0"
4
+ MAJOR, MINOR, TINY = VERSION.split "."
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-glesys
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Simon Gate
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fog
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.9'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '1.9'
30
+ - !ruby/object:Gem::Dependency
31
+ name: chef
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.10.10
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.10.10
46
+ description: Glesys support for Chef's Knife Command
47
+ email:
48
+ - simon@smgt.me
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - knife-glesys.gemspec
59
+ - lib/chef/knife/glesys_base.rb
60
+ - lib/chef/knife/glesys_server_create.rb
61
+ - lib/chef/knife/glesys_server_delete.rb
62
+ - lib/chef/knife/glesys_server_info.rb
63
+ - lib/chef/knife/glesys_server_list.rb
64
+ - lib/chef/knife/glesys_template_list.rb
65
+ - lib/knife-glesys/version.rb
66
+ homepage: https://github.com/smgt/knife-glesys
67
+ licenses: []
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 1.8.23
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Glesys support for Chef's Knife Command
90
+ test_files: []
91
+ has_rdoc: