knife-rightscale 0.0.2
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.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +201 -0
- data/README.md +191 -0
- data/Rakefile +32 -0
- data/knife-rightscale.gemspec +37 -0
- data/lib/chef/knife/rightscale_base.rb +113 -0
- data/lib/chef/knife/rightscale_cloud_list.rb +72 -0
- data/lib/chef/knife/rightscale_deployment_list.rb +70 -0
- data/lib/chef/knife/rightscale_image_list.rb +116 -0
- data/lib/chef/knife/rightscale_securitygroup_list.rb +78 -0
- data/lib/chef/knife/rightscale_server_create.rb +181 -0
- data/lib/chef/knife/rightscale_server_delete.rb +52 -0
- data/lib/chef/knife/rightscale_server_list.rb +73 -0
- data/lib/chef/knife/rightscale_servertemplate_list.rb +73 -0
- data/lib/knife-rightscale.rb +30 -0
- data/lib/knife-rightscale/version.rb +22 -0
- data/lib/right_api_provision.rb +92 -0
- data/lib/right_api_provision/api15.rb +372 -0
- data/lib/right_api_provision/exception.rb +23 -0
- data/lib/right_api_provision/provisioner.rb +139 -0
- data/lib/right_api_provision/version.rb +21 -0
- data/spec/chef/knife/rightscale_server_create_spec.rb +32 -0
- data/spec/right_api_provision/api15_spec.rb +203 -0
- data/spec/spec_helper.rb +20 -0
- data/test/create_server_test.rb +58 -0
- data/test/list_actions_test.rb +51 -0
- metadata +78 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
# -*- encoding: utf-8 -*-
|
20
|
+
lib = File.expand_path('../lib', __FILE__)
|
21
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
22
|
+
require 'knife-rightscale/version'
|
23
|
+
|
24
|
+
Gem::Specification.new do |gem|
|
25
|
+
gem.name = "knife-rightscale"
|
26
|
+
gem.version = Knife::Rightscale::VERSION
|
27
|
+
gem.authors = ["Cary Penniman"]
|
28
|
+
gem.email = ["cary@rightscale.com"]
|
29
|
+
gem.description = %q{One plugin to provision them all! This plugin allows the Chef developer to provision Chef clients on all major clouds using the RightScale platform.}
|
30
|
+
gem.summary = %q{RightScale plugin for Knife}
|
31
|
+
gem.homepage = "http://github.com/caryp/knife-rightscale"
|
32
|
+
|
33
|
+
gem.files = `git ls-files`.split($/)
|
34
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
35
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
36
|
+
gem.require_paths = ["lib"]
|
37
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# This file is modified from the knife-ec2 plugin project code
|
7
|
+
# That project is located at https://github.com/opscode/knife-ec2
|
8
|
+
# Author:: Seth Chisamore <schisamo@opscode.com>
|
9
|
+
# Copyright:: Copyright (c) 2011 Opscode, Inc.
|
10
|
+
# License:: Apache License, Version 2.0
|
11
|
+
#
|
12
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
13
|
+
# you may not use this file except in compliance with the License.
|
14
|
+
# You may obtain a copy of the License at
|
15
|
+
#
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
#
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
19
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
20
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
21
|
+
# See the License for the specific language governing permissions and
|
22
|
+
# limitations under the License.
|
23
|
+
#
|
24
|
+
require 'chef/knife'
|
25
|
+
require 'right_api_provision/provisioner'
|
26
|
+
require 'right_api_provision/api15'
|
27
|
+
|
28
|
+
class Chef
|
29
|
+
class Knife
|
30
|
+
module RightscaleBase
|
31
|
+
|
32
|
+
# :nodoc:
|
33
|
+
# Would prefer to do this in a rational way, but can't be done b/c of
|
34
|
+
# Mixlib::CLI's design :(
|
35
|
+
def self.included(includer)
|
36
|
+
includer.class_eval do
|
37
|
+
|
38
|
+
deps do
|
39
|
+
require 'right_api_client'
|
40
|
+
end
|
41
|
+
|
42
|
+
option :rightscale_user,
|
43
|
+
:short => "-U USER",
|
44
|
+
:long => "--rightscale-user USER",
|
45
|
+
:description => "Your RightScale User Email",
|
46
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:rightscale_user] = key }
|
47
|
+
|
48
|
+
option :rightscale_password,
|
49
|
+
:short => "-P PASSWORD",
|
50
|
+
:long => "--rightscale-password PASSWORD",
|
51
|
+
:description => "Your RightScale password",
|
52
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:rightscale_password] = key }
|
53
|
+
|
54
|
+
option :rightscale_account_id,
|
55
|
+
:short => "-A ID",
|
56
|
+
:long => "--rightscale-account-id ID",
|
57
|
+
:description => "Your RightScale account ID",
|
58
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:rightscale_account_id] = key }
|
59
|
+
|
60
|
+
option :rightscale_api_url,
|
61
|
+
:short => "-L API_URL",
|
62
|
+
:long => "--rightscale-api-url API_URL",
|
63
|
+
:description => "The API URL (defaults to my.rightscale.com)",
|
64
|
+
:default => "https://my.rightscale.com",
|
65
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:rightscale_api_url] = key }
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def connection
|
71
|
+
@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
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def locate_config_value(key)
|
84
|
+
key = key.to_sym
|
85
|
+
config[key] || Chef::Config[:knife][key]
|
86
|
+
end
|
87
|
+
|
88
|
+
def msg_pair(label, value, color=:cyan)
|
89
|
+
if value && !value.to_s.empty?
|
90
|
+
puts "#{ui.color(label, color)}: #{value}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def validate!(keys=[:rightscale_user, :rightscale_password, :rightscale_account_id])
|
95
|
+
errors = []
|
96
|
+
|
97
|
+
keys.each do |k|
|
98
|
+
pretty_key = k.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
|
99
|
+
if Chef::Config[:knife][k].nil?
|
100
|
+
errors << "You did not provide a valid '#{pretty_key}' value."
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if errors.each{|e| ui.error(e)}.any?
|
105
|
+
exit 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/rightscale_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class RightscaleCloudList < Knife
|
24
|
+
|
25
|
+
include Knife::RightscaleBase
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'right_api_client'
|
29
|
+
require 'timeout'
|
30
|
+
end
|
31
|
+
|
32
|
+
banner "knife rightscale cloud list (options)"
|
33
|
+
|
34
|
+
option :cloud_name,
|
35
|
+
:short => "-n CLOUD_NAME",
|
36
|
+
:long => "--name CLOUD_NAME",
|
37
|
+
:description => "The name of the cloud to search for",
|
38
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:cloud_name] = i }
|
39
|
+
|
40
|
+
def run
|
41
|
+
$stdout.sync = true
|
42
|
+
|
43
|
+
validate!
|
44
|
+
|
45
|
+
# query clouds
|
46
|
+
@clouds = connection.list_clouds(:by_name, config[:cloud_name])
|
47
|
+
|
48
|
+
cloud_list = [
|
49
|
+
ui.color('Name', :bold),
|
50
|
+
ui.color('Description', :bold)
|
51
|
+
].flatten.compact
|
52
|
+
|
53
|
+
output_column_count = cloud_list.length
|
54
|
+
|
55
|
+
@clouds.each do |cloud|
|
56
|
+
cloud_list << cloud.name
|
57
|
+
cloud_list << cloud.description
|
58
|
+
end
|
59
|
+
|
60
|
+
puts ui.list(cloud_list, :uneven_columns_across, output_column_count)
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def validate!
|
67
|
+
super([:rightscale_user, :rightscale_password, :rightscale_account_id])
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/rightscale_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class RightscaleDeploymentList < Knife
|
24
|
+
|
25
|
+
include Knife::RightscaleBase
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'right_api_client'
|
29
|
+
end
|
30
|
+
|
31
|
+
option :deployment_name,
|
32
|
+
:short => "-n DEPLOYMENTNAME",
|
33
|
+
:long => "--name DEPLOYMENTNAME",
|
34
|
+
:description => "The name of the deployment to search for",
|
35
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:deployment_name] = i }
|
36
|
+
|
37
|
+
banner "knife rightscale deployment list (options)"
|
38
|
+
|
39
|
+
def run
|
40
|
+
$stdout.sync = true
|
41
|
+
|
42
|
+
validate!
|
43
|
+
|
44
|
+
@deployments = connection.list_deployments(:by_name, config[:deployment_name])
|
45
|
+
|
46
|
+
deployment_list = [
|
47
|
+
ui.color('Name', :bold),
|
48
|
+
ui.color('Description', :bold)
|
49
|
+
].flatten.compact
|
50
|
+
|
51
|
+
output_column_count = deployment_list.length
|
52
|
+
|
53
|
+
@deployments.each do |deployment|
|
54
|
+
deployment_list << deployment.name
|
55
|
+
deployment_list << deployment.description
|
56
|
+
end
|
57
|
+
|
58
|
+
puts ui.list(deployment_list, :uneven_columns_across, output_column_count)
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def validate!
|
65
|
+
super([:rightscale_user, :rightscale_password, :rightscale_account_id])
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/rightscale_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class RightscaleImageList < Knife
|
24
|
+
|
25
|
+
include Knife::RightscaleBase
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'right_api_client'
|
29
|
+
end
|
30
|
+
|
31
|
+
option :server_template,
|
32
|
+
:short => "-s SERVER_TEMPLATE",
|
33
|
+
:long => "--server-template SERVER_TEMPLATE",
|
34
|
+
:description => "The name of the ServerTemplate or ID to use for the server",
|
35
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:server_template] = i },
|
36
|
+
:required => true
|
37
|
+
|
38
|
+
option :cloud_name,
|
39
|
+
:short => "-c CLOUD",
|
40
|
+
:long => "--cloud CLOUD",
|
41
|
+
:description => "The cloud you plan to run on.",
|
42
|
+
:proc => Proc.new { |f| Chef::Config[:knife][:cloud_name] = f },
|
43
|
+
:required => true
|
44
|
+
|
45
|
+
option :image_name,
|
46
|
+
:short => "-n IMAGE_NAME",
|
47
|
+
:long => "--name IMAGE_NAME",
|
48
|
+
:description => "The partial name of the image to search for",
|
49
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:image_name] = i }
|
50
|
+
|
51
|
+
banner "knife rightscale image list (options)"
|
52
|
+
|
53
|
+
def run
|
54
|
+
$stdout.sync = true
|
55
|
+
|
56
|
+
validate!
|
57
|
+
|
58
|
+
# fail if the requested cloud is not registered with RightScale account
|
59
|
+
puts(ui.color('Looking up cloud...', :magenta))
|
60
|
+
@cloud = connection.find_cloud_by_name(config[:cloud_name])
|
61
|
+
raise "ERROR: cannot find a cloud named: '#{config[:cloud_name]}'. " +
|
62
|
+
"See 'knife rightscale cloud list' command for a list of clouds" +
|
63
|
+
" registered with your RightScale account" unless @cloud
|
64
|
+
|
65
|
+
puts(ui.color('Looking up ServerTemplate...', :magenta))
|
66
|
+
@st = connection.find_servertemplate(config[:server_template])
|
67
|
+
raise "ERROR: cannot find ServerTemplate '#{config[:server_template]}'. Did you import it?\n" +
|
68
|
+
"Visit http://bit.ly/VnOiA7 for more info.\n\n" unless @st
|
69
|
+
|
70
|
+
image_list = [
|
71
|
+
ui.color('Image', :bold),
|
72
|
+
ui.color('Instance Type (default)', :bold)
|
73
|
+
].flatten.compact
|
74
|
+
|
75
|
+
output_column_count = image_list.length
|
76
|
+
|
77
|
+
puts(ui.color('Looking up supported multi-cloud images...', :magenta))
|
78
|
+
@multi_cloud_images = connection.list_multi_cloud_images(@st, :by_name, config[:image_name])
|
79
|
+
|
80
|
+
print(ui.color('Inspecting ServerTemplate images...', :magenta))
|
81
|
+
@multi_cloud_images.each do |multi_cloud_image|
|
82
|
+
multi_cloud_image.settings.index.each do |cloud_setting|
|
83
|
+
print(ui.color(".", :magenta))
|
84
|
+
STDOUT.flush
|
85
|
+
next unless registered_cloud?(cloud_setting.cloud)
|
86
|
+
image_list << multi_cloud_image.name
|
87
|
+
image_list << instance_type(cloud_setting.show)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
puts
|
91
|
+
puts ui.list(image_list, :uneven_columns_across, output_column_count)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def instance_type(setting)
|
97
|
+
type = "n/a"
|
98
|
+
type = setting.instance_type.show.name if instance_type?(setting)
|
99
|
+
type
|
100
|
+
end
|
101
|
+
|
102
|
+
def instance_type?(setting)
|
103
|
+
setting.respond_to?(:instance_type)
|
104
|
+
end
|
105
|
+
|
106
|
+
def registered_cloud?(cloud)
|
107
|
+
cloud.href == @cloud.href
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate!
|
111
|
+
super([:rightscale_user, :rightscale_password, :rightscale_account_id])
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Cary Penniman (<cary@rightscale.com>)
|
3
|
+
# Copyright:: Copyright (c) 2013 RightScale, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require 'chef/knife/rightscale_base'
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class RightscaleSecuritygroupList < Knife
|
24
|
+
|
25
|
+
include Knife::RightscaleBase
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'right_api_client'
|
29
|
+
end
|
30
|
+
|
31
|
+
option :security_group_name,
|
32
|
+
:short => "-n SECURITYGROUP_NAME",
|
33
|
+
:long => "--name SECURITYGROUP_NAME",
|
34
|
+
:description => "The partial name of the security group to search for",
|
35
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:security_group_name] = i }
|
36
|
+
|
37
|
+
option :cloud_name,
|
38
|
+
:short => "-C CLOUD_NAME",
|
39
|
+
:long => "--cloud CLOUD_NAME",
|
40
|
+
:description => "The partial name of the cloud to search for",
|
41
|
+
:proc => Proc.new { |i| Chef::Config[:knife][:cloud_name] = i }
|
42
|
+
|
43
|
+
banner "knife rightscale securitygroup list (options)"
|
44
|
+
|
45
|
+
def run
|
46
|
+
$stdout.sync = true
|
47
|
+
|
48
|
+
validate!
|
49
|
+
@clouds = connection.list_clouds(:by_name, config[:cloud_name])
|
50
|
+
count = @clouds.size
|
51
|
+
puts ui.color("Querying #{count} clouds for security groups. Could take a minute...", :magenta) if count > 1
|
52
|
+
security_group_list = [
|
53
|
+
ui.color('Cloud', :bold),
|
54
|
+
ui.color('Name', :bold),
|
55
|
+
ui.color('Resource UID', :bold)
|
56
|
+
].flatten.compact
|
57
|
+
|
58
|
+
output_column_count = security_group_list.length
|
59
|
+
@clouds.each do |cloud|
|
60
|
+
@security_groups = connection.list_security_groups(cloud, :by_name, config[:security_group_name])
|
61
|
+
@security_groups.each do |security_group|
|
62
|
+
security_group_list << cloud.name
|
63
|
+
security_group_list << security_group.name
|
64
|
+
security_group_list << security_group.resource_uid
|
65
|
+
end
|
66
|
+
end
|
67
|
+
puts ui.list(security_group_list, :uneven_columns_across, output_column_count)
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def validate!
|
73
|
+
super([:rightscale_user, :rightscale_password, :rightscale_account_id])
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|