knife-clodo 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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *~
@@ -0,0 +1,14 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'knife-clodo'
3
+ spec.version = '0.1.0'
4
+ spec.summary = 'Clodo.Ru knife plugin'
5
+ spec.add_dependency('fog', '>= 0.10.0')
6
+ spec.description = <<-EOF
7
+ Knife plugin for Clodo.Ru cloud provider.
8
+ EOF
9
+ spec.author = 'Stepan G. Fedorov'
10
+ spec.email = 'sf@clodo.ru'
11
+ spec.homepage = 'http://clodo.ru/'
12
+ spec.files = `git ls-files`.split "\n"
13
+ spec.require_paths = ["lib"]
14
+ end
@@ -0,0 +1,51 @@
1
+ bash -c '
2
+ <%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>
3
+
4
+ if [ ! -f /usr/bin/chef-client ]; then
5
+ echo "chef chef/chef_server_url string <%= @chef_config[:chef_server_url] %>" | debconf-set-selections
6
+ [ -f /etc/apt/sources.list.d/opscode.list ] || echo "deb http://apt.opscode.com <%= chef_version.to_f == 0.10 ? "squeeze-0.10" : "squeeze" %> main" > /etc/apt/sources.list.d/opscode.list
7
+ wget <%= "--proxy=on " if knife_config[:bootstrap_proxy] %>-O- http://apt.opscode.com/packages@opscode.com.gpg.key | apt-key add -
8
+ fi
9
+
10
+ export DEBIAN_FRONTEND=noninteractive
11
+
12
+ apt-get update
13
+ apt-get install -y ucf chef
14
+
15
+ (
16
+ cat <<'EOP'
17
+ log_level :info
18
+ log_location STDOUT
19
+ ssl_verufy_mode :verify_none
20
+ chef_server_url "<%= @chef_config[:chef_server_url] %>"
21
+ EOP
22
+ ) > /etc/chef/client.rb
23
+
24
+ (
25
+ cat <<'EOP'
26
+ <%= validation_key %>
27
+ EOP
28
+ ) > /tmp/validation.pem
29
+ awk NF /tmp/validation.pem > /etc/chef/validation.pem
30
+ rm /tmp/validation.pem
31
+
32
+ <% unless @chef_config[:validation_client_name] == "chef-validator" -%>
33
+ [ `grep -qx "validation_client_name \"<%= @chef_config[:validation_client_name] %>\"" /etc/chef/client.rb` ] || echo "validation_client_name \"<%= @chef_config[:validation_client_name] %>\"" >> /etc/chef/client.rb
34
+ <% end -%>
35
+
36
+ <% if @config[:chef_node_name] %>
37
+ [ `grep -qx "node_name \"<%= @config[:chef_node_name] %>\"" /etc/chef/client.rb` ] || echo "node_name \"<%= @config[:chef_node_name] %>\"" >> /etc/chef/client.rb
38
+ <% end -%>
39
+
40
+ <% if knife_config[:bootstrap_proxy] %>
41
+ echo 'http_proxy "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
42
+ echo 'https_proxy "knife_config[:bootstrap_proxy]"' >> /etc/chef/client.rb
43
+ <% end -%>
44
+
45
+ (
46
+ cat <<'EOP'
47
+ <%= { "run_list" => @run_list }.to_json %>
48
+ EOP
49
+ ) > /etc/chef/first-boot.json
50
+
51
+ <%= start_chef %>'
@@ -0,0 +1,61 @@
1
+ require 'chef/knife'
2
+
3
+ class Chef
4
+ class Knife
5
+ module ClodoBase
6
+
7
+ # I don't know what this means, so just copy it from Rackspace
8
+ def self.included(includer)
9
+ includer.class_eval do
10
+
11
+ deps do
12
+ require 'fog'
13
+ require 'net/ssh/multi'
14
+ require 'readline'
15
+ require 'chef/json_compat'
16
+ end
17
+
18
+ option :clodo_api_key,
19
+ :short => "-K KEY",
20
+ :long => "--clodo-api-key KEY",
21
+ :description => "Your clodo.ru API key",
22
+ :proc => Proc.new { |key| Chef::Config[:knife][:clodo_api_key] = key }
23
+
24
+ option :clodo_username,
25
+ :short => "-A USERNAME",
26
+ :long => "--clodo-username USERNAME",
27
+ :description => "Your clodo.ru API username",
28
+ :proc => Proc.new { |username| Chef::Config[:knife][:clodo_username] = username }
29
+
30
+ option :clodo_api_auth_url,
31
+ :long => "--clodo-api-auth-url URL",
32
+ :description => "Your clodo.ru API auth url",
33
+ :default => "api.clodo.ru",
34
+ :proc => Proc.new { |url| Chef::Config[:knife][:clodo_api_auth_url] = url }
35
+ end
36
+
37
+ def connection
38
+ @connection ||= Fog::Compute::Clodo.new({
39
+ :clodo_api_key => Chef::Config[:knife][:clodo_api_key],
40
+ :clodo_username => (Chef::Config[:knife][:clodo_username] || Chef::Config[:knife][:clodo_api_username]),
41
+ :clodo_auth_url => Chef::Config[:knife][:clodo_api_auth_url] || config[:clodo_api_auth_url]})
42
+ end
43
+
44
+ def locate_config_value(key)
45
+ key = key.to_sym
46
+ Chef::Config[:knife][key] || config[key]
47
+ end
48
+
49
+ def public_dns_name(server)
50
+ @public_dns_name ||= begin
51
+ Resolv.getname(server.public_ip_address)
52
+ rescue
53
+ "#{server.public_ip_address.gsub('.','-')}.clodo.ru"
54
+ end
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,216 @@
1
+ require 'chef/knife/clodo_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClodoServerCreate < Knife
6
+
7
+ include Knife::ClodoBase
8
+
9
+ deps do
10
+ require 'fog'
11
+ require 'readline'
12
+ require 'chef/json_compat'
13
+ require 'chef/knife/bootstrap'
14
+ Chef::Knife::Bootstrap.load_deps
15
+ end
16
+
17
+ banner "knife clodo.ru server create (options)"
18
+
19
+ option :image,
20
+ :short => "-I IMAGE",
21
+ :long => "--image IMAGE",
22
+ :description => "The image of server; default is 541 (Debian 6 amd64 Scale)",
23
+ :proc => Proc.new { |f| Chef::Config[:knife][:image] = f.to_i },
24
+ :default => 541
25
+
26
+ option :server_name,
27
+ :short => "-N NAME",
28
+ :long => "--server-name NAME",
29
+ :description => "The title for your server"
30
+
31
+ option :server_type,
32
+ :long => "--server-type TYPE",
33
+ :description => "Type of the server - static or scale (default scale)",
34
+ :proc => Proc.new {|f| Chef::Config[:knife][:server_type] = f=="static"?"VirtualServer":"ScaleServer"},
35
+ :default => "ScaleServer"
36
+
37
+ option :server_memory,
38
+ :long => "--server-memory MB",
39
+ :description => "For static server is an amount of memory in megabytes, for scale server is a low limit in megabytes. (default is 512MB)",
40
+ :proc => Proc.new {|m| Chef::Config[:knife][:server_memory] = m.to_i},
41
+ :default => 512
42
+
43
+ option :server_memory_max,
44
+ :long => "--server-memory-max MB",
45
+ :description => "For static server is ignored, for scale server is a high limit in megabytes. (default is 4096MB)",
46
+ :proc => Proc.new {|m| Chef::Config[:knife][:server_memory_max] = m.to_i},
47
+ :default => 4096
48
+
49
+ option :server_disk,
50
+ :long => "--server-disk GB",
51
+ :description => "Server's disk size in gigabytes. (default 10GB)",
52
+ :proc => Proc.new {|d| Chef::Config[:knife][:server_disk] = d.to_i},
53
+ :default => 10
54
+
55
+ option :server_support_level,
56
+ :long => "--server-support-level LEVEL",
57
+ :description => "Support level for this server. Default is always 1. You can also choose from 2 and 3",
58
+ :proc => Proc.new {|s| Chef::Config[:knife][:server_support_level] = s.to_i},
59
+ :default => 1
60
+
61
+ option :chef_node_name,
62
+ :long => "--node-name NAME",
63
+ :description => "The Chef node name for your new node"
64
+
65
+ option :ssh_user,
66
+ :short => "-x USERNAME",
67
+ :long => "--ssh-user USERNAME",
68
+ :description => "The ssh username; default is 'root'",
69
+ :default => "root"
70
+
71
+ option :ssh_password,
72
+ :short => "-P PASSWORD",
73
+ :long => "--ssh-password PASSWORD",
74
+ :description => "The ssh password"
75
+
76
+ option :identity_file,
77
+ :short => "-i IDENTITY_FILE",
78
+ :long => "--identity-file IDENTITY_FILE",
79
+ :description => "The SSH identity file used for authentication"
80
+
81
+ option :prerelease,
82
+ :long => "--prerelease",
83
+ :description => "Install the pre-release chef gems"
84
+
85
+ option :bootstrap_version,
86
+ :long => "--bootstrap-version VERSION",
87
+ :description => "The version of Chef to install",
88
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
89
+ option :prerelease,
90
+ :long => "--prerelease",
91
+ :description => "Install the pre-release chef gems"
92
+
93
+ option :bootstrap_version,
94
+ :long => "--bootstrap-version VERSION",
95
+ :description => "The version of Chef to install",
96
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
97
+
98
+ option :distro,
99
+ :short => "-d DISTRO",
100
+ :long => "--distro DISTRO",
101
+ :description => "Bootstrap a distro using a template; default is 'debian6apt'",
102
+ :proc => Proc.new { |d| Chef::Config[:knife][:distro] = d },
103
+ :default => "debian6apt"
104
+
105
+ option :template_file,
106
+ :long => "--template-file TEMPLATE",
107
+ :description => "Full path to location of template to use",
108
+ :proc => Proc.new { |t| Chef::Config[:knife][:template_file] = t },
109
+ :default => false
110
+
111
+ option :run_list,
112
+ :short => "-r RUN_LIST",
113
+ :long => "--run-list RUN_LIST",
114
+ :description => "Comma separated list of roles/recipes to apply",
115
+ :proc => lambda { |o| o.split(/[\s,]+/) },
116
+ :default => []
117
+
118
+ def tcp_test_ssh(hostname)
119
+ tcp_socket = TCPSocket.new(hostname, 22)
120
+ readable = IO.select([tcp_socket], nil, nil, 5)
121
+ if readable
122
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
123
+ yield
124
+ true
125
+ else
126
+ false
127
+ end
128
+ rescue Errno::ETIMEDOUT
129
+ false
130
+ rescue Errno::EPERM
131
+ false
132
+ rescue Errno::ECONNREFUSED
133
+ sleep 2
134
+ false
135
+ rescue Errno::EHOSTUNREACH
136
+ sleep 2
137
+ false
138
+ ensure
139
+ tcp_socket && tcp_socket.close
140
+ end
141
+
142
+
143
+ def run
144
+ $stdout.sync = true
145
+
146
+ unless Chef::Config[:knife][:image]
147
+ ui.error("You have not provided a valid image value. Please note the short option for this value recently changed from '-i' to '-I'.")
148
+ exit 1
149
+ end
150
+
151
+ options = {
152
+ :vps_type => Chef::Config[:knife][:server_type],
153
+ :vps_memory => Chef::Config[:knife][:server_memory],
154
+ :vps_memory_max => Chef::Config[:knife][:server_memory_max],
155
+ :vps_hdd => Chef::Config[:knife][:server_disk],
156
+ :vps_admin => Chef::Config[:knife][:server_support_level],
157
+ :vps_os => Chef::Config[:knife][:image]
158
+ }
159
+
160
+ options[:name] = config[:server_name] if config[:server_name]
161
+
162
+ server = connection.servers.create(options)
163
+
164
+ puts "#{ui.color("ID", :cyan)}: #{server.id}"
165
+ puts "#{ui.color("Name", :cyan)}: #{server.name}"
166
+ puts "#{ui.color("Image", :cyan)}: #{server.image}"
167
+ puts "#{ui.color("IP", :cyan)}: #{server.public_ip_address}"
168
+ puts "#{ui.color("root password", :red)}: #{server.password}"
169
+
170
+ print "\n#{ui.color("Waiting server", :magenta)}"
171
+
172
+ # wait for it to be ready to do stuff
173
+ server.wait_for { print "."; ready? }
174
+
175
+ puts("\n")
176
+
177
+ puts "#{ui.color("Public DNS Name", :cyan)}: #{public_dns_name(server)}"
178
+ puts "#{ui.color("Public IP Address", :cyan)}: #{server.public_ip_address}"
179
+ puts "#{ui.color("Password", :cyan)}: #{server.password}"
180
+
181
+ print "\n#{ui.color("Waiting for sshd", :magenta)}"
182
+
183
+ print(".") until tcp_test_ssh(server.public_ip_address) { sleep @initial_sleep_delay ||= 10; puts("done") }
184
+
185
+ bootstrap_for_node(server).run
186
+
187
+ puts "\n"
188
+ puts "#{ui.color("Instance ID", :cyan)}: #{server.id}"
189
+ puts "#{ui.color("Name", :cyan)}: #{server.name}"
190
+ puts "#{ui.color("Image", :cyan)}: #{server.image}"
191
+ puts "#{ui.color("Public DNS Name", :cyan)}: #{public_dns_name(server)}"
192
+ puts "#{ui.color("Public IP Address", :cyan)}: #{server.public_ip_address}"
193
+ puts "#{ui.color("Password", :cyan)}: #{server.password}"
194
+ puts "#{ui.color("Environment", :cyan)}: #{config[:environment] || '_default'}"
195
+ puts "#{ui.color("Run List", :cyan)}: #{config[:run_list].join(', ')}"
196
+ end
197
+
198
+ def bootstrap_for_node(server)
199
+ bootstrap = Chef::Knife::Bootstrap.new
200
+ bootstrap.name_args = [public_dns_name(server)]
201
+ bootstrap.config[:run_list] = config[:run_list]
202
+ bootstrap.config[:ssh_user] = config[:ssh_user] || "root"
203
+ bootstrap.config[:ssh_password] = server.password
204
+ bootstrap.config[:identity_file] = config[:identity_file]
205
+ bootstrap.config[:chef_node_name] = config[:chef_node_name] || server.id
206
+ bootstrap.config[:prerelease] = config[:prerelease]
207
+ bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
208
+ # bootstrap will run as root...sudo (by default) also messes up Ohai on CentOS boxes
209
+ bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
210
+ bootstrap.config[:environment] = config[:environment]
211
+ bootstrap
212
+ end
213
+
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,48 @@
1
+ require 'chef/knife/clodo_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClodoServerList < Knife
6
+
7
+ include Knife::ClodoBase
8
+
9
+ banner "knife clodo server list (options)"
10
+
11
+ def run
12
+ $stdout.sync = true
13
+
14
+ server_list = [
15
+ ui.color('ID', :bold),
16
+ ui.color('Name', :bold),
17
+ ui.color('Public IP', :bold),
18
+ ui.color('Root pass', :bold),
19
+ ui.color('VNC', :bold),
20
+ ui.color('VNC pass', :bold),
21
+ ui.color('State', :bold)
22
+ ]
23
+
24
+ connection.servers.each do |server|
25
+ server_list << server.id.to_s
26
+ server_list << server.name
27
+ server_list << (server.public_ip_address ? server.public_ip_address : "")
28
+ server_list << server.password
29
+ server_list << server.vps_vnc
30
+ server_list << server.vps_vnc_pass
31
+ server_list << case server.state.downcase
32
+ when 'is_suspended'
33
+ ui.color(server.state.downcase, :red)
34
+ when 'is_disabled', 'is_request'
35
+ ui.color(server.state.downcase, :cyan)
36
+ when 'is_install'
37
+ ui.color(server.state.downcase, :yellow)
38
+ when 'is_running'
39
+ ui.color(server.state.downcase, :green)
40
+ else
41
+ ui.color(server.state.upcase, :red)
42
+ end
43
+ end
44
+ puts ui.list(server_list, :columns_across, 7)
45
+ end
46
+ end
47
+ end
48
+ end
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-clodo
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Stepan G. Fedorov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-24 00:00:00 +04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: fog
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 55
30
+ segments:
31
+ - 0
32
+ - 10
33
+ - 0
34
+ version: 0.10.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: "\tKnife plugin for Clodo.Ru cloud provider.\n"
38
+ email: sf@clodo.ru
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - knife-clodo.gemspec
48
+ - lib/chef/knife/bootstrap/debian6apt.erb
49
+ - lib/chef/knife/clodo_base.rb
50
+ - lib/chef/knife/clodo_server_create.rb
51
+ - lib/chef/knife/clodo_server_list.rb
52
+ has_rdoc: true
53
+ homepage: http://clodo.ru/
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.7
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Clodo.Ru knife plugin
86
+ test_files: []
87
+