knife-sce 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ class String
19
+ def is_number?
20
+ true if Float(self) rescue false
21
+ end
22
+ end
23
+
24
+ require 'chef/knife'
25
+
26
+ class Chef
27
+ class Knife
28
+ module SceBase
29
+
30
+ # :nodoc:
31
+ # Would prefer to do this in a rational way, but can't be done b/c of
32
+ # Mixlib::CLI's design :(
33
+ def self.included(includer)
34
+ includer.class_eval do
35
+
36
+ deps do
37
+ require 'fog'
38
+ require 'readline'
39
+ require 'chef/json_compat'
40
+ end
41
+
42
+ option :ibm_username,
43
+ :short => "-A USERNAME",
44
+ :long => "--ibm-username USERNAME",
45
+ :description => "Your IBM SCE username",
46
+ :proc => Proc.new { |key| Chef::Config[:knife][:ibm_username] = key }
47
+
48
+ option :ibm_password,
49
+ :short => "-K PASSWORD",
50
+ :long => "--ibm-password PASSWORD",
51
+ :description => "Your SCE password",
52
+ :proc => Proc.new { |key| Chef::Config[:knife][:ibm_password] = key }
53
+ end
54
+ end
55
+
56
+ def connection
57
+ @connection ||= begin
58
+ connection = Fog::Compute.new(
59
+ :provider => 'IBM',
60
+ :ibm_username => Chef::Config[:knife][:ibm_username],
61
+ :ibm_password => Chef::Config[:knife][:ibm_password]
62
+ )
63
+ end
64
+ end
65
+
66
+ def connection_storage
67
+ @connection_storage ||= begin
68
+ connection_storage = Fog::Storage.new(
69
+ :provider => 'IBM',
70
+ :ibm_username => Chef::Config[:knife][:ibm_username],
71
+ :ibm_password => Chef::Config[:knife][:ibm_password]
72
+ )
73
+ end
74
+ end
75
+
76
+ def locate_config_value(key)
77
+ key = key.to_sym
78
+ config[key] || Chef::Config[:knife][key]
79
+ end
80
+
81
+ def datacenter_id
82
+ id = nil
83
+ if locate_config_value(:datacenter).to_s.is_number?
84
+ location = connection.locations.get( locate_config_value(:datacenter) )
85
+ if !location.nil?
86
+ id = location.id.to_s
87
+ else
88
+ ui.error("Location ID #{locate_config_value(:datacenter)} is invalid. Use knife sce location list to learn what IDs or textual locations are available.")
89
+ exit 1
90
+ end
91
+ else
92
+ connection.locations.all.each do |location|
93
+ if location.name.to_s.split(",").first.downcase.eql?( locate_config_value(:datacenter).downcase )
94
+ id = location.id.to_s
95
+ end
96
+ end
97
+ end
98
+
99
+ if id.nil?
100
+ ui.error("Location #{locate_config_value(:datacenter)} is invalid. Use knife sce location list to learn what IDs or textual locations are available.")
101
+ exit 1
102
+ end
103
+
104
+ id
105
+ end
106
+
107
+ def msg_pair(label, value, color=:cyan)
108
+ if value && !value.to_s.empty?
109
+ puts "#{ui.color(label, color)}: #{value}"
110
+ end
111
+ end
112
+
113
+ def validate!(keys=[:ibm_username, :ibm_password])
114
+ errors = []
115
+ keys.each do |k|
116
+ pretty_key = k.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
117
+ if Chef::Config[:knife][k].nil?
118
+ errors << "You did not provide a valid '#{pretty_key}' value."
119
+ end
120
+ end
121
+ if errors.each{|e| ui.error(e)}.any?
122
+ exit 1
123
+ end
124
+ end
125
+
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,82 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceImageDescribe < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce image describe IMAGE_ID [IMAGE_ID]"
27
+
28
+ def run
29
+
30
+ validate!
31
+
32
+ @name_args.each do |image_id|
33
+
34
+ begin
35
+ @image = connection.images.get(image_id)
36
+ rescue Excon::Errors::InternalServerError => e
37
+ if image_id.is_number?
38
+ ui.error e.inspect
39
+ exit 1
40
+ end
41
+ # is not a number and we received an error, ignore, API likes numbers only, we try to fetch the image by the name
42
+ end
43
+
44
+ if @image.nil?
45
+ connection.images.all.each do |i|
46
+ if i.name.to_s == image_id
47
+ @image = i
48
+ end
49
+ end
50
+ end
51
+
52
+ msg_pair("Image ID", @image.id.to_s)
53
+ msg_pair("Name", @image.name.to_s)
54
+ msg_pair("Location", connection.locations.get(@image.location).name.to_s)
55
+ msg_pair("Description", @image.description.to_s)
56
+ msg_pair("Visbility", @image.visibility.to_s)
57
+ msg_pair("Platform", @image.platform.to_s)
58
+ msg_pair("Architecture", @image.architecture.to_s)
59
+ msg_pair("Owner", @image.owner.to_s)
60
+ msg_pair("State", @image.state.to_s)
61
+ msg_pair("Manifest", @image.manifest.to_s)
62
+ msg_pair("Product codes", ":")
63
+ @image.product_codes.each do |pc|
64
+ msg_pair(" -> ", pc)
65
+ end
66
+ msg_pair("Supported instance types", ":")
67
+ @image.supported_instance_types.each do |sit|
68
+ msg_pair(" -> ", sit.id.to_s)
69
+ msg_pair(" ", sit.label.to_s)
70
+ msg_pair(" ", sit.detail.to_s)
71
+ msg_pair(" ", "Price: #{sit.price['rate']}#{sit.price['currencyCode']}/#{sit.price['pricePerQuantity']}#{sit.price['unitOfMeasure']}")
72
+ end
73
+ msg_pair("Documentation", @image.documentation.to_s)
74
+
75
+ puts "\n"
76
+
77
+ end
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,55 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceInstanceData < Knife
23
+
24
+ deps do
25
+ require 'chef/json_compat'
26
+ end
27
+
28
+ banner "knife sce instance data (options)"
29
+
30
+ option :edit,
31
+ :short => "-e",
32
+ :long => "--edit",
33
+ :description => "Edit the instance data"
34
+
35
+ option :run_list,
36
+ :short => "-r RUN_LIST",
37
+ :long => "--run-list RUN_LIST",
38
+ :description => "Comma separated list of roles/recipes to apply",
39
+ :proc => lambda { |o| o.split(/[\s,]+/) },
40
+ :default => []
41
+
42
+ def run
43
+ data = {
44
+ "chef_server" => Chef::Config[:chef_server_url],
45
+ "validation_client_name" => Chef::Config[:validation_client_name],
46
+ "validation_key" => IO.read(Chef::Config[:validation_key]),
47
+ "attributes" => { "run_list" => config[:run_list] }
48
+ }
49
+ data = edit_data(data) if config[:edit]
50
+ ui.output(data)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,58 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceKeyCreate < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce key create KEYNAME"
27
+
28
+ def run!(key_name)
29
+ @key = connection.keys.create(:name => key_name)
30
+ @key
31
+ end
32
+
33
+ def run
34
+
35
+ $stdout.sync = true
36
+
37
+ validate!
38
+
39
+ @key = run!(config[:name])
40
+
41
+ msg_pair("Name", @key.name.to_s)
42
+ msg_pair("Default", (@key.default ? "Yes" : "No"))
43
+ msg_pair("Key", @key.public_key.to_s)
44
+
45
+ end
46
+
47
+ def validate!
48
+
49
+ super
50
+
51
+ raise "No key name specified." if @name_args.length == 0
52
+ config[:name] = @name_args[0]
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceKeyDelete < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce key delete KEYNAME"
27
+
28
+ def run!(key)
29
+ key.destroy
30
+ end
31
+
32
+ def run
33
+
34
+ $stdout.sync = true
35
+
36
+ validate!
37
+
38
+ @key = connection.keys.get(config[:name])
39
+
40
+ raise "Key #{config[:name]} does not exist." if @key.nil?
41
+
42
+ msg_pair("Name", @key.name.to_s)
43
+ msg_pair("Instances", @key.instance_ids.join(", ").to_s)
44
+ msg_pair("Default", (@key.default ? "Yes" : "No"))
45
+
46
+ puts "\n"
47
+ confirm("Do you really want to delete this key")
48
+
49
+ run!(@key)
50
+
51
+ ui.warn("Deleted key #{@key.name.to_s}")
52
+
53
+ end
54
+
55
+ def validate!
56
+
57
+ super
58
+
59
+ raise "No key name specified." if @name_args.length == 0
60
+ config[:name] = @name_args[0]
61
+
62
+ end
63
+
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceKeyGet < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce key get KEYNAME"
27
+
28
+ def run!(key_name)
29
+ @key = connection.keys.get(key_name)
30
+ @key
31
+ end
32
+
33
+ def run
34
+
35
+ $stdout.sync = true
36
+
37
+ validate!
38
+
39
+ @key = run!(config[:name])
40
+
41
+ raise "Key #{config[:name]} does not exist." if @key.nil?
42
+
43
+ msg_pair("Name", @key.name.to_s)
44
+ msg_pair("Instances", @key.instance_ids.join(", ").to_s)
45
+ msg_pair("Default", (@key.default ? "Yes" : "No"))
46
+ msg_pair("Key", @key.public_key.to_s)
47
+
48
+ end
49
+
50
+ def validate!
51
+
52
+ super
53
+
54
+ raise "No key name specified." if @name_args.length == 0
55
+ config[:name] = @name_args[0]
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceKeyList < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce key list"
27
+
28
+ def run!
29
+ connection.keys.all
30
+ end
31
+
32
+ def run
33
+
34
+ $stdout.sync = true
35
+
36
+ validate!
37
+
38
+ keys = run!
39
+
40
+ key_list = [
41
+ ui.color('Name', :bold),
42
+ ui.color('Default', :bold),
43
+ ui.color("Modified at", :bold),
44
+ ui.color('Instances', :bold)
45
+ ].flatten.compact
46
+
47
+ output_column_count = key_list.length
48
+
49
+ keys.each do |k|
50
+ key_list << k.name.to_s
51
+ key_list << (k.default ? "*" : " ")
52
+ key_list << Time.at(k.modified_at/1000).to_datetime.to_s
53
+ key_list << k.instance_ids.join(", ").to_s
54
+ end
55
+
56
+ puts ui.list(key_list, :uneven_columns_across, output_column_count)
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,105 @@
1
+ #
2
+ # Author:: Rad Gruchalski (<radek@gruchalski.com>)
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require 'chef/knife/sce_base'
19
+
20
+ class Chef
21
+ class Knife
22
+ class SceLocationList < Knife
23
+
24
+ include Knife::SceBase
25
+
26
+ banner "knife sce location list (options)"
27
+
28
+ option :description,
29
+ :short => "-L",
30
+ :long => "--with-description",
31
+ :boolean => true,
32
+ :default => false,
33
+ :description => "Display description of the location"
34
+
35
+ option :capabilities,
36
+ :short => "-C",
37
+ :long => "--with-capabilities",
38
+ :boolean => true,
39
+ :default => false,
40
+ :description => "Display capabilities"
41
+
42
+ def run!
43
+ connection.locations.all
44
+ end
45
+
46
+ def run
47
+ $stdout.sync = true
48
+
49
+ validate!
50
+
51
+ location_list = [
52
+ ui.color('Location ID', :bold),
53
+ ui.color("Name", :bold),
54
+ ui.color('Location', :bold),
55
+ if config[:description]
56
+ ui.color('Description', :bold)
57
+ end,
58
+ if config[:capabilities]
59
+ ui.color('Capabilities', :bold)
60
+ end
61
+ ].flatten.compact
62
+
63
+ output_column_count = location_list.length
64
+
65
+ locations = run!
66
+
67
+ locations.each do |location|
68
+ location_list << location.id.to_s
69
+ location_list << location.name.to_s
70
+ location_list << location.location.to_s
71
+ if config[:description]
72
+ location_list << location.description.to_s
73
+ end
74
+ if config[:capabilities]
75
+ if location.capabilities.length > 0
76
+ tabs = "\t"
77
+ tabs = "#{tabs}\t" if location.capabilities[0]["id"].to_s.length < 25
78
+ location_list << "#{location.capabilities[0]["id"].to_s}:#{tabs}#{location.capabilities[0]["entries"].to_s}"
79
+ else
80
+ location_list << " "
81
+ end
82
+ end
83
+
84
+ if config[:capabilities]
85
+ (1...location.capabilities.length).each do |index|
86
+ location_list << " "
87
+ location_list << " "
88
+ location_list << " "
89
+ if config[:description]
90
+ location_list << " "
91
+ end
92
+ tabs = "\t"
93
+ tabs = "#{tabs}\t" if location.capabilities[index]["id"].to_s.length < 25
94
+ location_list << "#{location.capabilities[index]["id"].to_s}:#{tabs}#{location.capabilities[index]["entries"].to_s}"
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ puts ui.list(location_list, :uneven_columns_across, output_column_count)
101
+
102
+ end
103
+ end
104
+ end
105
+ end