knife-clc 0.0.1.pre

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.
@@ -0,0 +1,119 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcServerList < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc server list (options)'
9
+
10
+ option :clc_datacenter,
11
+ :long => '--datacenter ID',
12
+ :description => 'Short string representing the data center you are querying',
13
+ :on => :head
14
+
15
+ option :clc_all,
16
+ :long => '--all',
17
+ :boolean => true,
18
+ :default => false,
19
+ :description => 'The attribute to return a list of all servers from all datacenters',
20
+ :on => :head
21
+
22
+ option :clc_chef_nodes,
23
+ :long => '--chef-nodes',
24
+ :boolean => true,
25
+ :default => false,
26
+ :description => 'Wherever to include Chef node names in the listing or not',
27
+ :on => :head
28
+
29
+ def execute
30
+ servers = cloud_servers
31
+ merge_public_ips!(servers)
32
+ merge_chef_nodes!(servers) if config[:clc_chef_nodes]
33
+
34
+ context[:servers] = servers
35
+
36
+ render
37
+ end
38
+
39
+ def merge_public_ips!(servers)
40
+ servers.map! do |server|
41
+ ip_link = server['links'].find { |link| link['rel'] == 'publicIPAddress' }
42
+ server['publicIP'] = ip_link['id'] if ip_link
43
+ server
44
+ end
45
+ end
46
+
47
+ def merge_chef_nodes!(servers)
48
+ nodes = Chef::Node.list(true).values
49
+ servers.map! do |server|
50
+ existing_node = nodes.find { |node| node['machinename'] == server['name'] }
51
+ server['chefNode'] = existing_node.name if existing_node
52
+ server
53
+ end
54
+ end
55
+
56
+ def cloud_servers
57
+ if config[:clc_datacenter]
58
+ connection.list_servers(config[:clc_datacenter])
59
+ elsif config[:clc_all]
60
+ datacenters = connection.list_datacenters
61
+
62
+ datacenters.map do |dc|
63
+ connection.list_servers(dc['id'])
64
+ end.flatten
65
+ end
66
+ end
67
+
68
+ def headers
69
+ {
70
+ 'id' => 'ID',
71
+ 'name' => 'Name',
72
+ 'publicIP' => 'Public IP',
73
+ 'chefNode' => 'Chef Node',
74
+ 'groupId' => 'Group',
75
+ 'osType' => 'OS Type',
76
+ 'status' => 'Status',
77
+ 'locationId' => 'DC'
78
+ }
79
+ end
80
+
81
+ def fields
82
+ # TODO AS: Displaying shortened list of fields for now
83
+ # default_fields = %w(id name publicIP groupId locationId osType status)
84
+ default_fields = %w(name publicIP status)
85
+ config[:clc_chef_nodes] ? default_fields.insert(3, 'chefNode') : default_fields
86
+ end
87
+
88
+ def filters
89
+ {
90
+ 'publicIP' => ->(ip) { ip || '-' },
91
+ 'chefNode' => ->(name) { name || '-' }
92
+ }
93
+ end
94
+
95
+ def width_limits
96
+ {
97
+ 'chefNode' => 21,
98
+ 'status' => 15
99
+ }
100
+ end
101
+
102
+ def render
103
+ ui.info Hirb::Helpers::AutoTable.render(context[:servers],
104
+ :headers => headers,
105
+ :fields => fields,
106
+ :filters => filters,
107
+ :max_fields => width_limits,
108
+ :resize => false,
109
+ :description => false)
110
+ end
111
+
112
+ def parse_and_validate_parameters
113
+ if config[:clc_datacenter].nil? && !config[:clc_all]
114
+ errors << 'Datacenter ID is required'
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,38 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcServerPowerOff < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc server power_off ID (options)'
9
+
10
+ option :clc_wait,
11
+ :long => '--wait',
12
+ :description => 'Wait for operation completion',
13
+ :boolean => true,
14
+ :default => false,
15
+ :on => :head
16
+
17
+ def parse_and_validate_parameters
18
+ unless name_args[0]
19
+ errors << 'Server ID is required'
20
+ end
21
+ end
22
+
23
+ def execute
24
+ ui.info 'Requesting server power off...'
25
+ links = connection.power_off_server(name_args[0])
26
+
27
+ if config[:clc_wait]
28
+ connection.wait_for(links['operation']['id']) { putc '.' }
29
+ ui.info "\n"
30
+ ui.info 'Server has been powered off'
31
+ else
32
+ ui.info 'Power off request has been sent'
33
+ ui.info "You can check power off operation status with 'knife clc operation show #{links['operation']['id']}'"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcServerPowerOn < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc server power_on ID (options)'
9
+
10
+ option :clc_wait,
11
+ :long => '--wait',
12
+ :description => 'Wait for operation completion',
13
+ :boolean => true,
14
+ :default => false,
15
+ :on => :head
16
+
17
+ def parse_and_validate_parameters
18
+ unless name_args[0]
19
+ errors << 'Server ID is required'
20
+ end
21
+ end
22
+
23
+ def execute
24
+ ui.info 'Requesting server power on...'
25
+ links = connection.power_on_server(name_args[0])
26
+
27
+ if config[:clc_wait]
28
+ connection.wait_for(links['operation']['id']) { putc '.' }
29
+ ui.info "\n"
30
+ ui.info 'Server has been powered on'
31
+ else
32
+ ui.info 'Power on request has been sent'
33
+ ui.info "You can check power on operation status with 'knife clc operation show #{links['operation']['id']}'"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcServerReboot < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc server reboot ID (options)'
9
+
10
+ option :clc_wait,
11
+ :long => '--wait',
12
+ :description => 'Wait for operation completion',
13
+ :boolean => true,
14
+ :default => false,
15
+ :on => :head
16
+
17
+ def parse_and_validate_parameters
18
+ unless name_args[0]
19
+ errors << 'Server ID is required'
20
+ end
21
+ end
22
+
23
+ def execute
24
+ ui.info 'Requesting server reboot...'
25
+ links = connection.reboot_server(name_args[0])
26
+
27
+ if config[:clc_wait]
28
+ connection.wait_for(links['operation']['id']) { putc '.' }
29
+ ui.info "\n"
30
+ ui.info 'Server has been rebooted'
31
+ else
32
+ ui.info 'Reboot request has been sent'
33
+ ui.info "You can check reboot operation status with 'knife clc operation show #{links['operation']['id']}'"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,188 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcServerShow < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc server show ID (options)'
9
+
10
+ option :clc_uuid,
11
+ :long => '--uuid',
12
+ :description => 'Use primary argument as server UUID instead of just ID',
13
+ :boolean => true,
14
+ :default => false,
15
+ :on => :head
16
+
17
+ option :clc_creds,
18
+ :long => '--creds',
19
+ :description => 'Show server credentials',
20
+ :boolean => true,
21
+ :default => false,
22
+ :on => :head
23
+
24
+ option :clc_ports,
25
+ :long => '--ports',
26
+ :description => 'Show opened ports and restrictions',
27
+ :boolean => true,
28
+ :default => false,
29
+ :on => :head
30
+
31
+ def parse_and_validate_parameters
32
+ unless name_args[0]
33
+ errors << 'Server ID is required'
34
+ end
35
+ end
36
+
37
+ def execute
38
+ ui.info 'Requesting server info...'
39
+
40
+ context[:server] = get_server
41
+ context[:creds] = get_creds if config[:clc_creds]
42
+ context[:ip_addresses] = get_ip_addresses if config[:clc_ports]
43
+
44
+ render
45
+ end
46
+
47
+ def get_server
48
+ server = connection.show_server(name_args[0], config[:clc_uuid])
49
+
50
+ server['details'] ||= {}
51
+ server['details'].tap do |details|
52
+ details['ipAddresses'] ||= []
53
+ public_ips = server['details']['ipAddresses'].map { |addr| addr['public'] }.compact
54
+ private_ips = server['details']['ipAddresses'].map { |addr| addr['internal'] }.compact
55
+ details.merge!('publicIps' => public_ips, 'privateIps' => private_ips)
56
+ end
57
+
58
+ server
59
+ end
60
+
61
+ def get_creds
62
+ creds_link = context[:server]['links'].find { |link| link['rel'] == 'credentials' }
63
+ connection.follow(creds_link) if creds_link
64
+ end
65
+
66
+ def get_ip_addresses
67
+ context[:ip_addresses] = connection.list_ip_addresses(context[:server]['id'])
68
+ end
69
+
70
+ def render
71
+ render_properties
72
+ render_creds if config[:clc_creds]
73
+ render_addresses if config[:clc_ports]
74
+ end
75
+
76
+ def server_properties
77
+ %w(id name description groupId locationId osType status)
78
+ end
79
+
80
+ def server_detail_properties
81
+ %w(powerState cpu memoryMB storageGB publicIps privateIps)
82
+ end
83
+
84
+ def property_labels
85
+ {
86
+ 'id' => 'ID',
87
+ 'name' => 'Name',
88
+ 'description' => 'Description',
89
+ 'groupId' => 'Group',
90
+ 'locationId' => 'Location',
91
+ 'osType' => 'OS Type',
92
+ 'cpu' => 'CPUs',
93
+ 'memoryMB' => 'Memory',
94
+ 'storageGB' => 'Storage',
95
+ 'status' => 'Status',
96
+ 'powerState' => 'Power State',
97
+ 'publicIps' => 'Public IPs',
98
+ 'privateIps' => 'Private IPs',
99
+ 'userName' => 'Username',
100
+ 'password' => 'Password'
101
+ }
102
+ end
103
+
104
+ def property_filters
105
+ {
106
+ 'description' => ->(description) { description.empty? ? '-' : description },
107
+ 'memoryMB' => ->(memory) { "#{memory} MB" },
108
+ 'storageGB' => ->(storage) { "#{storage} GB" },
109
+ 'publicIps' => ->(ips) { ips.empty? ? '-' : ips.join(', ') },
110
+ 'privateIps' => ->(ips) { ips.empty? ? '-' : ips.join(', ') }
111
+ }
112
+ end
113
+
114
+ def render_properties
115
+ server = context[:server]
116
+
117
+ render_fields(:fields => server_properties, :container => server)
118
+ render_fields(:fields => server_detail_properties, :container => server['details'])
119
+ end
120
+
121
+ def render_addresses
122
+ if context[:ip_addresses].empty?
123
+ ui.info 'No additional networking info available'
124
+ else
125
+ ui.info Hirb::Helpers::AutoTable.render(context[:ip_addresses],
126
+ :headers => ip_headers,
127
+ :fields => ip_fields,
128
+ :filters => ip_filters,
129
+ :resize => false,
130
+ :description => false)
131
+ end
132
+ end
133
+
134
+ def ip_fields
135
+ %w(id internalIPAddress ports sourceRestrictions)
136
+ end
137
+
138
+ def ip_headers
139
+ {
140
+ 'id' => 'Public IP',
141
+ 'internalIPAddress' => 'Internal IP',
142
+ 'ports' => 'Ports',
143
+ 'sourceRestrictions' => 'Sources'
144
+ }
145
+ end
146
+
147
+ def ip_filters
148
+ {
149
+ 'sourceRestrictions' => ->(sources) { sources.empty? ? '-' : sources.map { |source| source['cidr'] }.join(', ') },
150
+ 'ports' => ->(ports) { ports.map { |permission| format_permission(permission) }.join(', ') }
151
+ }
152
+ end
153
+
154
+ def format_permission(permission)
155
+ protocol = permission['protocol']
156
+
157
+ if %w(tcp udp).include? protocol.downcase
158
+ ports = permission.values_at('port', 'portTo').compact
159
+ [protocol, ports.join('-')].join(':')
160
+ else
161
+ protocol
162
+ end
163
+ end
164
+
165
+ def render_creds
166
+ render_fields(fields: %w(userName password), container: context[:creds] || {})
167
+ end
168
+
169
+
170
+ def render_fields(fields: [], labels: property_labels, filters: property_filters, container: {})
171
+ fields.each do |field|
172
+ value = container[field]
173
+ filter = filters[field]
174
+
175
+ formatted_value = if value
176
+ filter ? filter.call(value) : value
177
+ else
178
+ '-'
179
+ end
180
+
181
+ label = labels[field] || field
182
+
183
+ ui.info "#{ui.color(label + ':', :bold)} #{formatted_value}"
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,91 @@
1
+ require 'chef/knife/clc_base'
2
+
3
+ class Chef
4
+ class Knife
5
+ class ClcTemplateList < Knife
6
+ include Knife::ClcBase
7
+
8
+ banner 'knife clc template list (options)'
9
+
10
+ option :clc_datacenter,
11
+ :long => '--datacenter ID',
12
+ :short => '-D ID',
13
+ :description => 'Datacenter ID to show templates from',
14
+ :on => :head
15
+
16
+ option :clc_all,
17
+ :long => '--all',
18
+ :boolean => true,
19
+ :default => false,
20
+ :description => 'The attribute to return a list of all templates from all datacenters',
21
+ :on => :head
22
+
23
+ def execute
24
+ context[:templates] = cloud_templates
25
+ render
26
+ end
27
+
28
+ def cloud_templates
29
+ if config[:clc_datacenter]
30
+ connection.list_templates(config[:clc_datacenter])
31
+ elsif config[:clc_all]
32
+ datacenters = connection.list_datacenters
33
+
34
+ datacenters.map do |dc|
35
+ connection.list_templates(dc['id'])
36
+ end.flatten
37
+ end
38
+ end
39
+
40
+ def parse_and_validate_parameters
41
+ if config[:clc_datacenter].nil? && !config[:clc_all]
42
+ errors << 'Datacenter ID is required'
43
+ end
44
+ end
45
+
46
+ def filters
47
+ {
48
+ 'storageSizeGB' => ->(size) { (size.zero? ? '-' : "#{size} GB").rjust(7) },
49
+ 'apiOnly' => ->(api_flag) { (api_flag ? '+' : '-').center(9) },
50
+ 'capabilities' => ->(capabilities) { capabilities.empty? ? '-' : capabilities.join(', ') }
51
+ }
52
+ end
53
+
54
+ def width_limits
55
+ {
56
+ 'description' => 0.2,
57
+ 'storageSizeGB' => 7,
58
+ 'capabilities' => 15,
59
+ 'apiOnly' => 9
60
+ }
61
+ end
62
+
63
+ def fields
64
+ # TODO AS: Displaying shortened list of fields for now
65
+ # %w(name osType description storageSizeGB capabilities apiOnly)
66
+ %w(name storageSizeGB capabilities)
67
+ end
68
+
69
+ def headers
70
+ {
71
+ 'name' => 'Name',
72
+ 'osType' => 'OS Type',
73
+ 'description' => 'Description',
74
+ 'storageSizeGB' => 'Storage',
75
+ 'capabilities' => 'Capabilities',
76
+ 'apiOnly' => 'API Only'
77
+ }
78
+ end
79
+
80
+ def render
81
+ ui.info Hirb::Helpers::AutoTable.render(context[:templates],
82
+ :headers => headers,
83
+ :fields => fields,
84
+ :filters => filters,
85
+ :max_fields => width_limits,
86
+ :resize => false,
87
+ :description => false)
88
+ end
89
+ end
90
+ end
91
+ end