knife-rightscale 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,6 @@
1
1
  v0.0.2
2
2
  * initial release
3
3
  v0.0.3
4
- * Updated Gemspec with right_api_client dependency. by kevinkarwaski
4
+ * Updated Gemspec with right_api_client dependency. by kevinkarwaski
5
+ v0.0.4
6
+ * retrofit to use right_api_provision client gem
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem "right_api_provision"
4
+
3
5
  # Specify your gem's dependencies in knife-rightscale.gemspec
4
6
  gemspec
data/README.md CHANGED
@@ -1,60 +1,54 @@
1
1
  # Knife RightScale
2
2
 
3
- This is a Knife plugin for RightScale. This plugin gives knife the ability to
4
- provision servers on clouds managed by the RightScale platform. It is expected
5
- that you already have a Chef Server running or are using a hosted Chef solution
3
+ This is a Knife plugin for RightScale. This plugin gives knife the ability to
4
+ provision servers on clouds managed by the RightScale platform. It is expected
5
+ that you already have a Chef Server running or are using a hosted Chef solution
6
6
  from OpsCode.
7
7
 
8
8
  NOTE: this plugin is currently under development and subject to change
9
9
 
10
10
  ## REQUIREMENTS:
11
11
 
12
- You will need a RightScale account with at least one cloud registered. You can
13
- sign up for a free trial account [here](https://www.rightscale.com).
14
-
15
- I was lazy and only added support for the RightScale API 1.5 (since API 1.0 is
16
- EC2 only and deprecated). As such, this plugin cannot currently provision
17
- servers on EC2. If you need this capability and would like to part in a private
18
- beta to enable that functionality, please contact support@rightscale.com and
19
- they will hook you up. If you have any problems, please send me an email
20
- directly.
12
+ You will need a RightScale account with at least one cloud registered. You can
13
+ sign up for a free trial account [here](https://www.rightscale.com).
21
14
 
22
15
  You will also need a running Chef Server. If you don't already have one you can
23
16
  sign up for a free trial of Hosted Chef from Opscode [here](http://www.opscode.com/hosted-chef/).
24
17
 
18
+ If you have an existing account and want to provision on EC2 clouds, you may need to migrate your account to the Unified Cloud Platform. Please see [here](http://support.rightscale.com/Announcements/2013-09-20_Unified_Cloud_Platform_Migration_Details) for more info on UCP.
25
19
 
26
20
  ## INSTALLATION:
27
21
 
28
22
  Be sure you are running the latest version Chef 10. Versions earlier than 0.10.0
29
23
  don't support plugins. This has not yet been tested with Chef 11.
30
24
 
31
- gem install chef -v 10.24.0
25
+ gem install chef -v 10.26.0
32
26
 
33
27
  This plugin is distributed as a Ruby Gem. To install it, run:
34
28
 
35
29
  gem install knife-rightscale
36
30
 
37
- Depending on your system's configuration, you may need to run this command with
31
+ Depending on your system's configuration, you may need to run this command with
38
32
  root privileges.
39
33
 
40
34
  ## CONFIGURATION:
41
35
 
42
- In order to communicate with the RightScale API you will have to tell Knife
43
- about your RightScale account information. The easiest way to accomplish this
36
+ In order to communicate with the RightScale API you will have to tell Knife
37
+ about your RightScale account information. The easiest way to accomplish this
44
38
  is to create some entries in your <tt>knife.rb</tt> file:
45
39
 
46
40
  knife[:rightscale_user] = "you@yourdomain.com"
47
41
  knife[:rightscale_password] = "supersecretpassword"
48
42
  knife[:rightscale_account_id] = "1234"
49
43
 
50
- If your knife.rb file will be checked into a SCM system (ie readable by others)
44
+ If your knife.rb file will be checked into a SCM system (i.e. readable by others)
51
45
  you may want to read the values from environment variables:
52
46
 
53
47
  knife[:rightscale_user] = "#{ENV['RIGHTSCALE_EMAIL']}"
54
48
  knife[:rightscale_password] = "#{ENV['RIGHTSCALE_PASSWORD']}"
55
49
 
56
- You also have the option of passing your RightScale credentials into the
57
- individual knife subcommands using the <tt>-A</tt> (or <tt>--rightscale-account-id</tt>),
50
+ You also have the option of passing your RightScale credentials into the
51
+ individual knife subcommands using the <tt>-A</tt> (or <tt>--rightscale-account-id</tt>),
58
52
  <tt>-U</tt> (or <tt>--rightscale-user</tt>), <tt>-P</tt> (or <tt>--rightscale-password</tt>) command options
59
53
 
60
54
  ## Provision a Server
@@ -72,18 +66,18 @@ to filter by partial name match use ```-n``` or ```--name``` option
72
66
  List the ServerTemplates available in your account. Typically you will just want to find a Chef Client template. For example:
73
67
 
74
68
  knife rightscale servertemplate list --name "Chef Client"
75
-
69
+
76
70
  ### Launch a server
77
71
  To provision a new server, supply ServerTemplate choice and target cloud as options:
78
72
 
79
73
  knife rightscale server create \
80
74
  --cloud "Rackspace Open Cloud - Chicago" \
81
75
  --server-template "Chef Client (v13.4)" \
82
- --deployment "CKP: My Sandbox" \
83
- --name "CKP:ChefClient" \
76
+ --deployment "CP: My Sandbox" \
77
+ --name "CP:ChefClient" \
84
78
  --input "chef/client/server_url":"text:https://api.opscode.com/organizations/kindsol" \
85
- --input "chef/client/validation_name":"cred:CKP: validation_client_name" \
86
- --input "chef/client/validator_pem":"cred:CKP:validator.pem" \
79
+ --input "chef/client/validation_name":"cred:CP: validation_client_name" \
80
+ --input "chef/client/validator_pem":"cred:CP:validator.pem" \
87
81
  --input "chef/client/node_name":"text:MyChefClient" \
88
82
  --input "chef/client/roles":"text:hello_world"
89
83
 
@@ -105,15 +99,15 @@ use the ```--yes``` option to bypass confirmation.
105
99
 
106
100
  ## OTHER SUBCOMMANDS:
107
101
 
108
- Some other subcommands that can be useful for provisioning servers are listed
109
- below. These are intended to query possible options that you can pass to the
110
- server create command.
102
+ Some other subcommands that can be useful for provisioning servers are listed
103
+ below. These are intended to query possible options that you can pass to the
104
+ server create command.
111
105
 
112
106
  All supported command options can be found by invoking:
113
107
 
114
- knife rightscale --help
108
+ knife rightscale --help
115
109
 
116
- Specific details for each command can be found by passing the ```--help```
110
+ Specific details for each command can be found by passing the ```--help```
117
111
  option the the subcommand. For example:
118
112
 
119
113
  knife rightscale <subcommand> --help
@@ -127,7 +121,7 @@ List the supported images for a given ServerTemplate and target cloud
127
121
  --cloud "Rackspace Open Cloud - Chicago"
128
122
 
129
123
  This will also indicate the default Instance Type or flavor for each image.
130
-
124
+ 
131
125
 
132
126
  ### List Deployments
133
127
  To list all the deployments available in your RightScale account:
@@ -142,7 +136,7 @@ To list all the Security Groups available per cloud:
142
136
 
143
137
  knife rightscale securitygroup list
144
138
 
145
- to filter by partial name match use the ```--name``` option or narrow the
139
+ to filter by partial name match use the ```--name``` option or narrow the
146
140
  results using the ```--cloud``` option
147
141
 
148
142
 
@@ -153,6 +147,22 @@ To list all the servers in your RightScale account:
153
147
 
154
148
  to filter by partial name match use the ```--name``` option
155
149
 
150
+ ## DEVELOPMENT
151
+
152
+ You can develop this plugin with out installing it using the bundler gem. First clone this repository, change to the working directory and run:
153
+
154
+ bundle
155
+
156
+ Verify the unit test pass:
157
+
158
+ bundle exec rake spec
159
+
160
+ Once those are passing you can run the plugin using `bundle exec`. For example, to view the help message run:
161
+
162
+ bundle exec knife rightscale --help
163
+
164
+ Happy hacking!
165
+
156
166
 
157
167
  ## FUTURE FEATURES
158
168
  * create action
@@ -163,11 +173,11 @@ to filter by partial name match use the ```--name``` option
163
173
  ** Private beta
164
174
  * display audit entry when server strands
165
175
  * ability to add server tags on create
166
- * server array create action
167
- * add timeout for operational
176
+ * server array create action
177
+ * add timeout for operational
168
178
  * credentials list action (waiting for new API release)
169
179
  * add VPC support to create action
170
-
180
+
171
181
 
172
182
  ## LICENSE:
173
183
 
@@ -176,7 +186,7 @@ Copyright:: Copyright (c) 2013 RightScale, Inc.
176
186
  License:: Apache License, Version 2.0
177
187
  See attribution notice in README.md
178
188
 
179
- This readme is modified from the knife-ec2 plugin project code
189
+ This readme is modified from the knife-ec2 plugin project code
180
190
  That project is located at https://github.com/opscode/knife-ec2
181
191
  Author:: Adam Jacob (<adam@opscode.com>)
182
192
  Copyright:: Copyright (c) 2009-2011 Opscode, Inc.
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- require "bundler/gem_tasks"
2
-
3
1
  #
4
2
  # Author:: Cary Penniman (<cary@rightscale.com>)
5
3
  # Copyright:: Copyright (c) 2013 RightScale, Inc.
@@ -17,6 +15,20 @@ require "bundler/gem_tasks"
17
15
  # See the License for the specific language governing permissions and
18
16
  # limitations under the License.
19
17
  #
18
+ require "bundler/gem_tasks"
19
+ require "rdoc/task"
20
+ require "yard"
21
+
22
+ YARD::Rake::YardocTask.new do |t|
23
+ t.files = ['lib/**/*.rb']
24
+ end
25
+
26
+ Rake::RDocTask.new(:rdoc) do |rd|
27
+ rd.main = "README.doc"
28
+ rd.rdoc_files.include("README.md", "lib/**/*.rb")
29
+ rd.options << "--all"
30
+ end
31
+
20
32
  require 'rspec/core/rake_task'
21
33
 
22
34
  desc "Run all specs in spec directory"
@@ -33,7 +33,11 @@ Gem::Specification.new do |gem|
33
33
  gem.files = `git ls-files`.split($/)
34
34
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
35
35
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
36
- gem.add_dependency "right_api_client", "~> 1.5"
36
+ gem.add_dependency "right_api_helper", ">= 1.1.2"
37
+ gem.add_dependency "rake"
38
+ gem.add_dependency "yard"
39
+ gem.add_dependency "rspec"
40
+ gem.add_dependency "chef"
37
41
 
38
42
  gem.require_paths = ["lib"]
39
43
  end
@@ -3,7 +3,7 @@
3
3
  # Copyright:: Copyright (c) 2013 RightScale, Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
- # This file is modified from the knife-ec2 plugin project code
6
+ # This file is modified from the knife-ec2 plugin project code
7
7
  # That project is located at https://github.com/opscode/knife-ec2
8
8
  # Author:: Seth Chisamore <schisamo@opscode.com>
9
9
  # Copyright:: Copyright (c) 2011 Opscode, Inc.
@@ -22,8 +22,7 @@
22
22
  # limitations under the License.
23
23
  #
24
24
  require 'chef/knife'
25
- require 'right_api_provision/provisioner'
26
- require 'right_api_provision/api15'
25
+ require 'right_api_helper'
27
26
 
28
27
  class Chef
29
28
  class Knife
@@ -36,7 +35,7 @@ class Chef
36
35
  includer.class_eval do
37
36
 
38
37
  deps do
39
- require 'right_api_client'
38
+ require 'right_api_helper'
40
39
  end
41
40
 
42
41
  option :rightscale_user,
@@ -69,17 +68,31 @@ class Chef
69
68
 
70
69
  def connection
71
70
  @connection ||= begin
72
- client = ::RightApiProvision::API15.new
73
- client.connection(
74
- Chef::Config[:knife][:rightscale_user],
75
- Chef::Config[:knife][:rightscale_password],
76
- Chef::Config[:knife][:rightscale_account_id],
77
- Chef::Config[:knife][:rightscale_api_url]
78
- )
79
- client
71
+ api_shim = RightApiHelper::API15.new(right_api_client)
72
+ set_log_level(api_shim)
73
+ api_shim
80
74
  end
81
75
  end
82
76
 
77
+ def right_api_client
78
+ @right_api_client ||= begin
79
+ session = RightApiHelper::Session.new
80
+ set_log_level(session)
81
+ right_api_client = session.create_client(
82
+ Chef::Config[:knife][:rightscale_user],
83
+ Chef::Config[:knife][:rightscale_password],
84
+ Chef::Config[:knife][:rightscale_account_id],
85
+ Chef::Config[:knife][:rightscale_api_url]
86
+ )
87
+ right_api_client
88
+ end
89
+ end
90
+
91
+ def set_log_level(obj)
92
+ log_level = (config[:verbosity] >= 1) ? Logger::DEBUG : Logger::INFO
93
+ obj.log_level(log_level)
94
+ end
95
+
83
96
  def locate_config_value(key)
84
97
  key = key.to_sym
85
98
  config[key] || Chef::Config[:knife][key]
@@ -96,7 +109,7 @@ class Chef
96
109
 
97
110
  keys.each do |k|
98
111
  pretty_key = k.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
99
- if Chef::Config[:knife][k].nil?
112
+ if Chef::Config[:knife][k].nil? && config[k].nil?
100
113
  errors << "You did not provide a valid '#{pretty_key}' value."
101
114
  end
102
115
  end
@@ -25,7 +25,7 @@ class Chef
25
25
  include Knife::RightscaleBase
26
26
 
27
27
  deps do
28
- require 'right_api_client'
28
+ require 'right_api_helper'
29
29
  require 'timeout'
30
30
  end
31
31
 
@@ -25,7 +25,7 @@ class Chef
25
25
  include Knife::RightscaleBase
26
26
 
27
27
  deps do
28
- require 'right_api_client'
28
+ require 'right_api_helper'
29
29
  end
30
30
 
31
31
  option :deployment_name,
@@ -25,7 +25,7 @@ class Chef
25
25
  include Knife::RightscaleBase
26
26
 
27
27
  deps do
28
- require 'right_api_client'
28
+ require 'right_api_helper'
29
29
  end
30
30
 
31
31
  option :server_template,
@@ -25,15 +25,15 @@ class Chef
25
25
  include Knife::RightscaleBase
26
26
 
27
27
  deps do
28
- require 'right_api_client'
28
+ require 'right_api_helper'
29
29
  end
30
-
30
+
31
31
  option :security_group_name,
32
32
  :short => "-n SECURITYGROUP_NAME",
33
33
  :long => "--name SECURITYGROUP_NAME",
34
34
  :description => "The partial name of the security group to search for",
35
35
  :proc => Proc.new { |i| Chef::Config[:knife][:security_group_name] = i }
36
-
36
+
37
37
  option :cloud_name,
38
38
  :short => "-C CLOUD_NAME",
39
39
  :long => "--cloud CLOUD_NAME",
@@ -54,9 +54,10 @@ class Chef
54
54
  ui.color('Name', :bold),
55
55
  ui.color('Resource UID', :bold)
56
56
  ].flatten.compact
57
-
57
+
58
58
  output_column_count = security_group_list.length
59
59
  @clouds.each do |cloud|
60
+ next unless connection.requires_security_groups?(cloud)
60
61
  @security_groups = connection.list_security_groups(cloud, :by_name, config[:security_group_name])
61
62
  @security_groups.each do |security_group|
62
63
  security_group_list << cloud.name
@@ -66,13 +67,13 @@ class Chef
66
67
  end
67
68
  puts ui.list(security_group_list, :uneven_columns_across, output_column_count)
68
69
  end
69
-
70
+
70
71
  private
71
72
 
72
73
  def validate!
73
74
  super([:rightscale_user, :rightscale_password, :rightscale_account_id])
74
75
  end
75
-
76
+
76
77
  end
77
78
  end
78
79
  end
@@ -3,7 +3,7 @@
3
3
  # Copyright:: Copyright (c) 2013 RightScale, Inc.
4
4
  # License:: Apache License, Version 2.0
5
5
  #
6
- # This file is modified from the knife-ec2 plugin project code
6
+ # This file is modified from the knife-ec2 plugin project code
7
7
  # That project is located at https://github.com/opscode/knife-ec2
8
8
  # Author:: Adam Jacob (<adam@opscode.com>)
9
9
  # Author:: Seth Chisamore (<schisamo@opscode.com>)
@@ -32,7 +32,7 @@ class Chef
32
32
  include Knife::RightscaleBase
33
33
 
34
34
  deps do
35
- require 'right_api_client'
35
+ require 'right_api_helper'
36
36
  end
37
37
 
38
38
  banner "knife rightscale server create (options)"
@@ -50,8 +50,7 @@ class Chef
50
50
  :short => "-s NAME",
51
51
  :long => "--server-template NAME",
52
52
  :description => "The name of the ServerTemplate or ID to use for the server",
53
- :proc => Proc.new { |i| Chef::Config[:knife][:server_template] = i },
54
- :required => true
53
+ :proc => Proc.new { |i| Chef::Config[:knife][:server_template] = i }
55
54
 
56
55
  option :server_name,
57
56
  :short => "-n SERVERNAME",
@@ -78,20 +77,20 @@ class Chef
78
77
  :long => "--input NAME:VALUE",
79
78
  :description => "An input name and value",
80
79
  :proc => lambda { |o| k,v=o.split(":",2); @@inputs[k]=v }
81
-
80
+
82
81
  option :ssh_key_name,
83
82
  :short => "-S KEY_UUID",
84
83
  :long => "--ssh-key KEY_UUID",
85
84
  :description => "The AWS SSH key resource UUIS",
86
85
  :proc => Proc.new { |key| Chef::Config[:knife][:ssh_key_uuid] = key }
87
-
86
+
88
87
  # Gets applied to chef/client/roles input of ServerTemplate, if it exists
89
88
  # option :run_list,
90
89
  # :short => "-r RUN_LIST",
91
90
  # :long => "--run-list RUN_LIST",
92
91
  # :description => "Comma separated list of roles/recipes to apply.",
93
92
  # :proc => lambda { |o| o.split(/[\s,]+/) }
94
- #
93
+ #
95
94
  # option :json_attributes,
96
95
  # :short => "-j JSON",
97
96
  # :long => "--json-attributes JSON",
@@ -102,7 +101,7 @@ class Chef
102
101
  # :long => "--bootstrap-version VERSION",
103
102
  # :description => "The version of Chef to install",
104
103
  # :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
105
- #
104
+ #
106
105
  # option :chef_node_name,
107
106
  # :short => "-N NAME",
108
107
  # :long => "--node-name NAME",
@@ -114,19 +113,25 @@ class Chef
114
113
  # :long => "--flavor FLAVOR",
115
114
  # :description => "The flavor of server (m1.small, m1.medium, etc)",
116
115
  # :proc => Proc.new { |f| Chef::Config[:knife][:flavor] = f }
117
- #
116
+ #
118
117
  # option :image,
119
118
  # :short => "-I IMAGE",
120
119
  # :long => "--image IMAGE",
121
120
  # :description => "The AMI for the server",
122
121
  # :proc => Proc.new { |i| Chef::Config[:knife][:image] = i }
123
- #
122
+ #
124
123
  option :security_groups,
125
124
  :short => "-G X,Y,Z",
126
125
  :long => "--groups X,Y,Z",
127
126
  :description => "The security groups for this server; not allowed when using VPC",
128
127
  :proc => Proc.new { |groups| groups.split(',') }
129
128
 
129
+ option :wait_for_operational,
130
+ :long => "--[no-]block",
131
+ :description => "Exit after server launch -- don't wait for operational. (non-blocking)",
132
+ :boolean => true,
133
+ :default => true
134
+
130
135
  def run
131
136
  $stdout.sync = true
132
137
 
@@ -139,27 +144,34 @@ class Chef
139
144
  print "\n#{ui.color("Cloud:", :magenta)} #{config[:cloud_name]}"
140
145
  print "\n#{ui.color("Deployment name:", :magenta)} #{config[:deployment_name]}"
141
146
  print "\n#{ui.color("Inputs:", :magenta)} #{@@inputs}"
147
+ print "\n#{ui.color("Wait for Operational:", :magenta)} FALSE" if config[:no_wait]
142
148
  print "\n"
143
-
144
- rightscale = ::RightApiProvision::Provisioner.new(connection)
149
+
150
+ rightscale = get_rightscale_provisioner
145
151
  rightscale.provision(
146
- config[:server_template],
147
- config[:server_name],
148
- config[:cloud_name],
149
- config[:deployment_name],
150
- @@inputs,
151
- config[:ssh_key_name],
152
- config[:security_groups]
153
- )
154
-
152
+ config[:server_name],
153
+ config[:server_template],
154
+ config[:cloud_name],
155
+ config[:deployment_name],
156
+ @@inputs,
157
+ nil, # MCI not yet supported
158
+ config[:ssh_key_name],
159
+ config[:security_groups]
160
+ )
161
+
162
+ unless config[:wait_for_operational]
163
+ print "#{ui.color("Server launched -- exiting.", :green)}"
164
+ return
165
+ end
166
+
155
167
  if rightscale.server_ready?
156
168
  print "#{ui.color("Server already running", :green)}"
157
- else
169
+ elsif
158
170
  print "\n#{ui.color("Waiting for RightScale to configure server\n", :yellow)}"
159
171
  rightscale.wait_for_operational
160
172
  print "\n"
161
173
  end
162
-
174
+
163
175
  # output connection information
164
176
  print "#{ui.color("Querying server info...\n", :magenta)}"
165
177
  info = rightscale.server_info
@@ -172,6 +184,10 @@ class Chef
172
184
 
173
185
  private
174
186
 
187
+ def get_rightscale_provisioner
188
+ RightApiHelper::Provisioner.new(right_api_client)
189
+ end
190
+
175
191
  def validate!
176
192
  super([:cloud_name, :deployment_name, :server_template, :rightscale_user, :rightscale_password, :rightscale_account_id])
177
193
  end