knife-azure 1.0.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/{readme.rdoc → README.rdoc} +68 -26
- data/lib/azure/connection.rb +3 -1
- data/lib/azure/deploy.rb +3 -0
- data/lib/azure/host.rb +2 -2
- data/lib/azure/image.rb +2 -2
- data/lib/azure/rest.rb +8 -3
- data/lib/azure/role.rb +1 -1
- data/lib/azure/storageaccount.rb +87 -0
- data/lib/chef/knife/azure_base.rb +19 -17
- data/lib/chef/knife/azure_image_list.rb +13 -10
- data/lib/chef/knife/azure_server_create.rb +45 -13
- data/lib/knife-azure/version.rb +1 -1
- metadata +208 -178
- data/Gemfile +0 -22
- data/Guardfile +0 -8
- data/Rakefile +0 -51
- data/knife-azure.gemspec +0 -106
- data/spec/functional/deploys_test.rb +0 -39
- data/spec/functional/host_test.rb +0 -22
- data/spec/functional/images_list_test.rb +0 -44
- data/spec/functional/role_test.rb +0 -16
- data/spec/integration/role_lifecycle_test.rb +0 -60
- data/spec/spec_helper.rb +0 -41
- data/spec/unit/assets/create_deployment.xml +0 -37
- data/spec/unit/assets/create_deployment_in_progress.xml +0 -1
- data/spec/unit/assets/create_host.xml +0 -7
- data/spec/unit/assets/create_role.xml +0 -54
- data/spec/unit/assets/list_deployments_for_service000.xml +0 -126
- data/spec/unit/assets/list_deployments_for_service001.xml +0 -166
- data/spec/unit/assets/list_deployments_for_service002.xml +0 -1
- data/spec/unit/assets/list_deployments_for_service003.xml +0 -1
- data/spec/unit/assets/list_disks.xml +0 -1
- data/spec/unit/assets/list_hosts.xml +0 -1
- data/spec/unit/assets/list_images.xml +0 -1
- data/spec/unit/assets/post_success.xml +0 -6
- data/spec/unit/deploys_list_spec.rb +0 -55
- data/spec/unit/disks_spec.rb +0 -44
- data/spec/unit/hosts_spec.rb +0 -55
- data/spec/unit/images_spec.rb +0 -35
- data/spec/unit/query_azure_mock.rb +0 -69
- data/spec/unit/roles_create_spec.rb +0 -82
- data/spec/unit/roles_list_spec.rb +0 -32
data/{readme.rdoc → README.rdoc}
RENAMED
@@ -2,18 +2,42 @@
|
|
2
2
|
|
3
3
|
Description: This plugin supports listing, creating, and deleting Azure instances bootstrapped with chef client.
|
4
4
|
|
5
|
+
==Generating the Management Certifcate (PEM)
|
6
|
+
The Management Certificate is required for secure communication with the Windows Azure Platform via the REST APIs.
|
7
|
+
Follow these steps to generate the certificate
|
8
|
+
|
9
|
+
1. Download the settings file from http://go.microsoft.com/fwlink/?LinkId=254432
|
10
|
+
2. Extract the data from the ManagementCertificate field into a separate file named - cert.pfx
|
11
|
+
3. Decode the certificate file :
|
12
|
+
|
13
|
+
base64 -d cert.pfx > cert_decoded.pfx
|
14
|
+
|
15
|
+
4. Convert the decoded PFX file to a PEM file
|
16
|
+
|
17
|
+
openssl pkcs12 -in cert_decoded.pfx -out managementCertificate.pem -nodes
|
18
|
+
|
19
|
+
It is possible to generate your own certificates and upload them. More Detailed Documentation about the Management Certificates is available : https://www.windowsazure.com/en-us/manage/linux/common-tasks/manage-certificates/
|
20
|
+
|
5
21
|
==Installation:
|
22
|
+
The plugin relies on SSL for communication and hence requires the SSL certifcate is setup. The Environment variable SSL_CERT_FILE should point to the full path of the SSL Certificate file.(optional)
|
23
|
+
|
6
24
|
Be sure you are running the latest version Chef. Versions earlier than 0.10.0 don’t support plugins:
|
7
25
|
|
8
26
|
gem install chef
|
9
|
-
This plugin is distributed as a Ruby Gem. To install it, run:
|
10
27
|
|
11
|
-
|
28
|
+
This plugin is distributed as a Ruby Gem. To install it, with missing dependencies run:
|
29
|
+
|
30
|
+
bundle install
|
31
|
+
|
32
|
+
If you make any changes to the knife plugin code and want to re-install the plugin:
|
33
|
+
|
34
|
+
rake install
|
35
|
+
|
12
36
|
Depending on your system’s configuration, you may need to run this command with root privileges.
|
13
37
|
|
14
38
|
==Requirements:
|
15
39
|
|
16
|
-
Due to a bug in mixlib-authentication, Chef node names must be 91 characters or shorter. Chef uses the host name by default, however the host names provided by Azure are very long.
|
40
|
+
Due to a bug in mixlib-authentication, Chef node names must be 91 characters or shorter. Chef uses the host name by default, however the host names provided by Azure are very long.
|
17
41
|
|
18
42
|
You must use the '-N NODE_NAME' flag with 'knife azure' to specify a node name to be used by Chef that is less than 91 characters.
|
19
43
|
|
@@ -28,15 +52,22 @@ option :azure_subscription_id,
|
|
28
52
|
:long => "--azure-subscription-id ID",
|
29
53
|
:description => "Your Azure subscription ID",
|
30
54
|
|
31
|
-
option :
|
55
|
+
option :azure_mgmt_cert,
|
32
56
|
:short => "-p FILENAME",
|
33
|
-
:long => "--azure-
|
34
|
-
:description => "Your Azure
|
57
|
+
:long => "--azure-mgmt-cert FILENAME",
|
58
|
+
:description => "Your Azure Management Certificate File",
|
35
59
|
|
36
60
|
option :azure_host_name,
|
37
61
|
:short => "-H HOSTNAME",
|
38
|
-
:long => "--
|
62
|
+
:long => "--azure-host-name HOSTNAME",
|
39
63
|
:description => "Your Azure host name",
|
64
|
+
:default => "management.core.windows.net"
|
65
|
+
|
66
|
+
option :verify_ssl_cert,
|
67
|
+
:long => "--verify-ssl-cert",
|
68
|
+
:description => "Verify SSL Certificates for communication over HTTPS",
|
69
|
+
:boolean => true,
|
70
|
+
:default => false
|
40
71
|
|
41
72
|
Options used with the Create subcommand:
|
42
73
|
option :chef_node_name,
|
@@ -72,7 +103,7 @@ option :distro,
|
|
72
103
|
:short => "-d DISTRO",
|
73
104
|
:long => "--distro DISTRO",
|
74
105
|
:description => "Bootstrap a distro using a template",
|
75
|
-
:default => "
|
106
|
+
:default => "ubuntu10.04-gems"
|
76
107
|
|
77
108
|
option :template_file,
|
78
109
|
:long => "--template-file TEMPLATE",
|
@@ -96,20 +127,29 @@ option :hosted_service_name,
|
|
96
127
|
:long => "--hosted-service-name NAME",
|
97
128
|
:description => "specifies the name for the hosted service"
|
98
129
|
|
130
|
+
option :hosted_service_description,
|
131
|
+
:short => "-D DESCRIPTION",
|
132
|
+
:long => "--hosted_service_description DESCRIPTION",
|
133
|
+
:description => "Description for the hosted service"
|
134
|
+
|
99
135
|
option :role_name,
|
100
136
|
:short => "-R name",
|
101
137
|
:long => "-- role-name NAME",
|
102
138
|
:description => "specifies the name for the virtual machine"
|
103
139
|
|
104
140
|
option :host_name,
|
105
|
-
:short => "-H NAME",
|
106
141
|
:long => "--host-name NAME",
|
107
142
|
:description => "specifies the host name for the virtual machine"
|
108
143
|
|
109
|
-
option :
|
110
|
-
:short => "-
|
111
|
-
:long => "--
|
112
|
-
:description => "
|
144
|
+
option :storage_account,
|
145
|
+
:short => "-a NAME",
|
146
|
+
:long => "--storage-account NAME",
|
147
|
+
:description => "specifies the name for the hosted service"
|
148
|
+
|
149
|
+
option :service_location,
|
150
|
+
:short => "-m LOCATION",
|
151
|
+
:long => "--service-location LOCATION",
|
152
|
+
:description => "specify the Geographic location for the virtual machine and services. eg. West US, East US, North Europe East Asia etc"
|
113
153
|
|
114
154
|
option :os_disk_name,
|
115
155
|
:short => "-o DISKNAME",
|
@@ -138,11 +178,13 @@ option :udp_endpoints,
|
|
138
178
|
|
139
179
|
|
140
180
|
====Here are some lines with example values in a knife.rb file:
|
141
|
-
knife[:azure_subscription_id] = "
|
181
|
+
knife[:azure_subscription_id] = "155a9851-88a8-49b4-98e4-58055f08f412"
|
142
182
|
|
143
|
-
knife[:
|
183
|
+
knife[:azure_mgmt_cert] = "ManagementCertificate.pem"
|
144
184
|
|
145
|
-
knife[:azure_host_name] = "
|
185
|
+
knife[:azure_host_name] = "management.core.windows.net"
|
186
|
+
|
187
|
+
knife[:service_location] = 'West US'
|
146
188
|
|
147
189
|
knife[:hosted_service_name]='service001'
|
148
190
|
|
@@ -150,11 +192,11 @@ knife[:role_name]='role105'
|
|
150
192
|
|
151
193
|
knife[:host_name]='host105'
|
152
194
|
|
153
|
-
knife[:ssh_user]='
|
195
|
+
knife[:ssh_user]='jetstream'
|
154
196
|
|
155
|
-
knife[:ssh_password]='
|
197
|
+
knife[:ssh_password]='jetstream1!'
|
156
198
|
|
157
|
-
knife[:
|
199
|
+
knife[:storage_account]='auxpreview104'
|
158
200
|
|
159
201
|
knife[:os_disk_name]='disk107'
|
160
202
|
|
@@ -184,13 +226,13 @@ knife[:role_size]='Small'
|
|
184
226
|
This plugin provides the following Knife subcommands. Specific command options can be found by invoking the subcommand with a --help flag
|
185
227
|
|
186
228
|
===knife azure server create
|
187
|
-
Provisions a new server in Azure and then perform a Chef bootstrap (using the SSH protocol). The goal of the bootstrap is to get Chef installed on the target system so it can run Chef Client with a Chef Server. The main assumption is a baseline OS installation exists (provided by the provisioning). It is primarily intended for Chef Client systems that talk to a Chef server. By default the server is bootstrapped using the ubuntu10.04-gems template. This can be overridden using the -d or --template-file command options.
|
229
|
+
Provisions a new server in Azure and then perform a Chef bootstrap (using the SSH protocol). The goal of the bootstrap is to get Chef installed on the target system so it can run Chef Client with a Chef Server. The main assumption is a baseline OS installation exists (provided by the provisioning). It is primarily intended for Chef Client systems that talk to a Chef server. By default the server is bootstrapped using the ubuntu10.04-gems template. This can be overridden using the -d or --template-file command options. (*** Note that at the current time only CentOS is supported for bootstrapping and required the :distro to be set to centos5-gems. There is a fix in the works from Christpher Brown in mixlib-authentication I believe that fixes an RSA encryption too long error that occurs for some hostnames during bootstrap. ***)
|
188
230
|
|
189
231
|
===knife azure server delete [role_name_to_delete]
|
190
|
-
Deletes an existing server(role) in the currently configured
|
232
|
+
Deletes an existing server(role) in the currently configured Azure account. PLEASE NOTE - By default, this does not delete the associated node and client objects from the Chef server. To do so, add the --purge flag.
|
191
233
|
|
192
234
|
===knife azure server list
|
193
|
-
Outputs a list of all servers in the currently configured
|
235
|
+
Outputs a list of all servers in the currently configured Azure account. PLEASE NOTE - this shows all instances associated with the account, some of which may not be currently managed by the Chef server.
|
194
236
|
|
195
237
|
===knife azure server describe [role_name_to_describe]
|
196
238
|
Outputs detail about a specific role, including all the ports that it has open
|
@@ -198,13 +240,13 @@ Outputs detail about a specific role, including all the ports that it has open
|
|
198
240
|
===knife azure image list
|
199
241
|
Outputs a list of all linux images that are available to use for provisioning. You should choose one of these to use for the :source_image parameter to the server create command.
|
200
242
|
|
243
|
+
|
244
|
+
===knife azure server describe
|
245
|
+
Output additional information about the provisioned Virtual Machine
|
246
|
+
|
201
247
|
== Understanding Azure
|
202
248
|
Azure implements the following hierarchy - subscription=>hosted service=>deployment=>role (and the guest operating system has a hostname as well, which uses the role as its container)
|
203
249
|
|
204
250
|
These are generally a one to many relationship from top to bottom, however there are two anamolies relating to the deployment
|
205
251
|
1) a hosted service can have more than one deployment, but that seems to be an artifact of the PAAS origins of Azure. PAAS allows there to be one staging and one production deployment per hosted service. It is my understanding (and how the code works) that there should be only one deployment per hosted service. Some initial internal code I examined used the technique of looking at the "production" deployment slot to iterate for existing roles. If a create request occurs and a deployment does not exist, it is created and given the same name as the hosted service and the deployment slot is marked as "production".
|
206
252
|
2) Azure enforces that a deployment must include the initial role when it is created. It also will not allow you to delete a role if it is the last remaining role in a deployment; in that case you are required to delete the deployment.
|
207
|
-
|
208
|
-
==Tests:
|
209
|
-
|
210
|
-
The tests require a subscription id to be places in spec/spec_helper.rb and the associated private key to be placed in 'AzureLinuxCert.pem' in the top level directory. Then run 'rake spec'
|
data/lib/azure/connection.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
require File.expand_path('../utility', __FILE__)
|
19
19
|
require File.expand_path('../rest', __FILE__)
|
20
20
|
require File.expand_path('../host', __FILE__)
|
21
|
+
require File.expand_path('../storageaccount', __FILE__)
|
21
22
|
require File.expand_path('../deploy', __FILE__)
|
22
23
|
require File.expand_path('../role', __FILE__)
|
23
24
|
require File.expand_path('../disk', __FILE__)
|
@@ -26,10 +27,11 @@ require File.expand_path('../image', __FILE__)
|
|
26
27
|
class Azure
|
27
28
|
class Connection
|
28
29
|
include AzureAPI
|
29
|
-
attr_accessor :hosts, :rest, :images, :deploys, :roles, :disks
|
30
|
+
attr_accessor :hosts, :rest, :images, :deploys, :roles, :disks, :storageaccounts
|
30
31
|
def initialize(params={})
|
31
32
|
@rest = Rest.new(params)
|
32
33
|
@hosts = Hosts.new(self)
|
34
|
+
@storageaccounts = StorageAccounts.new(self)
|
33
35
|
@images = Images.new(self)
|
34
36
|
@deploys = Deploys.new(self)
|
35
37
|
@roles = Roles.new(self)
|
data/lib/azure/deploy.rb
CHANGED
@@ -45,6 +45,9 @@ class Azure
|
|
45
45
|
unless @connection.hosts.exists(params[:hosted_service_name])
|
46
46
|
@connection.hosts.create(params)
|
47
47
|
end
|
48
|
+
unless @connection.storageaccounts.exists(params[:storage_account])
|
49
|
+
@connection.storageaccounts.create(params)
|
50
|
+
end
|
48
51
|
params['deploy_name'] = find(params[:hosted_service_name])
|
49
52
|
if params['deploy_name'] != nil
|
50
53
|
role = Role.new(@connection)
|
data/lib/azure/host.rb
CHANGED
@@ -77,8 +77,8 @@ class Azure
|
|
77
77
|
xml.CreateHostedService('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
78
78
|
xml.ServiceName params[:hosted_service_name]
|
79
79
|
xml.Label Base64.encode64(params[:hosted_service_name])
|
80
|
-
xml.Description params[
|
81
|
-
xml.Location params[
|
80
|
+
xml.Description params[:hosted_service_description] || 'Explicitly created hosted service'
|
81
|
+
xml.Location params[:service_location] || 'West US'
|
82
82
|
}
|
83
83
|
end
|
84
84
|
@connection.query_azure("hostedservices", "post", builder.to_xml)
|
data/lib/azure/image.rb
CHANGED
@@ -51,8 +51,8 @@ class Azure
|
|
51
51
|
@label = image.at_css('Label').content
|
52
52
|
@name = image.at_css('Name').content
|
53
53
|
@os = image.at_css('OS').content
|
54
|
-
@eula = image.at_css('Eula').content
|
55
|
-
@description = image.at_css('Description').content
|
54
|
+
@eula = image.at_css('Eula').content if image.at_css('Eula')
|
55
|
+
@description = image.at_css('Description').content if image.at_css('Description')
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
data/lib/azure/rest.rb
CHANGED
@@ -24,8 +24,9 @@ module AzureAPI
|
|
24
24
|
class Rest
|
25
25
|
def initialize(params)
|
26
26
|
@subscription_id = params[:azure_subscription_id]
|
27
|
-
@pem_file = File.read find_pem(params[:
|
27
|
+
@pem_file = File.read find_pem(params[:azure_mgmt_cert])
|
28
28
|
@host_name = params[:azure_host_name]
|
29
|
+
@verify_ssl = params[:verify_ssl_cert]
|
29
30
|
end
|
30
31
|
def find_pem(name)
|
31
32
|
config_dir = Chef::Knife.chef_config_dir
|
@@ -60,9 +61,13 @@ module AzureAPI
|
|
60
61
|
def http_setup(uri)
|
61
62
|
http = Net::HTTP.new(uri.host, uri.port)
|
62
63
|
store = OpenSSL::X509::Store.new
|
63
|
-
store.
|
64
|
+
store.set_default_paths
|
64
65
|
http.cert_store = store
|
65
|
-
|
66
|
+
if @verify_ssl
|
67
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
68
|
+
else
|
69
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
70
|
+
end
|
66
71
|
http.use_ssl = true
|
67
72
|
http.cert = OpenSSL::X509::Certificate.new(@pem_file)
|
68
73
|
http.key = OpenSSL::PKey::RSA.new(@pem_file)
|
data/lib/azure/role.rb
CHANGED
@@ -165,7 +165,7 @@ class Azure
|
|
165
165
|
}
|
166
166
|
xml.Label Base64.encode64(params[:role_name]).strip
|
167
167
|
xml.OSVirtualHardDisk {
|
168
|
-
xml.MediaLink 'http://' + params[:
|
168
|
+
xml.MediaLink 'http://' + params[:storage_account] + '.blob.core.windows.net/vhds/' + (params[:os_disk_name] || Time.now.strftime('disk_%Y_%m_%d_%H_%M')) + '.vhd'
|
169
169
|
xml.SourceImageName params[:source_image]
|
170
170
|
}
|
171
171
|
xml.RoleSize params[:role_size]
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Barry Davis (barryd@jetstreamsoftware.com)
|
3
|
+
# Copyright:: Copyright (c) 2010-2011 Opscode, 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
|
+
class Azure
|
20
|
+
class StorageAccounts
|
21
|
+
def initialize(connection)
|
22
|
+
@connection=connection
|
23
|
+
end
|
24
|
+
def all
|
25
|
+
storage_accounts = Array.new
|
26
|
+
responseXML = @connection.query_azure('storageservices')
|
27
|
+
servicesXML = responseXML.css('StorageServices StorageService')
|
28
|
+
servicesXML.each do |serviceXML|
|
29
|
+
storage_account = StorageAccount.new(@connection)
|
30
|
+
storage_accounts << storage_account.parse(serviceXML)
|
31
|
+
end
|
32
|
+
storage_accounts
|
33
|
+
end
|
34
|
+
def exists(name)
|
35
|
+
storageExists = false
|
36
|
+
self.all.each do |storage|
|
37
|
+
next unless storage.name == name
|
38
|
+
storageExists = true
|
39
|
+
end
|
40
|
+
storageExists
|
41
|
+
end
|
42
|
+
def create(params)
|
43
|
+
storage = StorageAccount.new(@connection)
|
44
|
+
storage.create(params)
|
45
|
+
end
|
46
|
+
def clear_unattached
|
47
|
+
self.all.each do |storage|
|
48
|
+
next unless storage.attached == false
|
49
|
+
@connection.query_azure('storageaccounts/' + storage.name, 'delete')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Azure
|
56
|
+
class StorageAccount
|
57
|
+
include AzureUtility
|
58
|
+
attr_accessor :name, :location
|
59
|
+
attr_accessor :affinityGroup, :location, :georeplicationenabled
|
60
|
+
def initialize(connection)
|
61
|
+
@connection = connection
|
62
|
+
end
|
63
|
+
def parse(serviceXML)
|
64
|
+
@name = xml_content(serviceXML, 'ServiceName')
|
65
|
+
@description = xml_content(serviceXML, 'Description')
|
66
|
+
@label = xml_content(serviceXML, 'Label')
|
67
|
+
@affinitygroup = xml_content(serviceXML, 'AffinityGroup')
|
68
|
+
@location = xml_content(serviceXML, 'Location')
|
69
|
+
@georeplicationenabled = xml_content(serviceXML, 'GeoReplicationEnabled')
|
70
|
+
@extendpropertyname = xml_content(serviceXML, 'ExtendedProperties ExtendedProperty Name')
|
71
|
+
@extendpropertyvalue = xml_content(serviceXML, 'ExtendedProperties ExtendedProperty Value')
|
72
|
+
self
|
73
|
+
end
|
74
|
+
def create(params)
|
75
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
76
|
+
xml.CreateStorageServiceInput('xmlns'=>'http://schemas.microsoft.com/windowsazure') {
|
77
|
+
xml.ServiceName params[:storage_account]
|
78
|
+
xml.Label Base64.encode64(params[:storage_account])
|
79
|
+
xml.Description params[:storage_account_description] || 'Explicitly created storage service'
|
80
|
+
# Location defaults to 'West US'
|
81
|
+
xml.Location params[:service_location] || 'West US'
|
82
|
+
}
|
83
|
+
end
|
84
|
+
@connection.query_azure("storageservices", "post", builder.to_xml)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -41,32 +41,36 @@ class Chef
|
|
41
41
|
:description => "Your Azure subscription ID",
|
42
42
|
:proc => Proc.new { |key| Chef::Config[:knife][:azure_subscription_id] = key }
|
43
43
|
|
44
|
-
option :
|
44
|
+
option :azure_mgmt_cert,
|
45
45
|
:short => "-p FILENAME",
|
46
|
-
:long => "--azure-
|
46
|
+
:long => "--azure-mgmt-cert FILENAME",
|
47
47
|
:description => "Your Azure PEM file name",
|
48
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:
|
48
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:azure_mgmt_cert] = key }
|
49
49
|
|
50
50
|
option :azure_host_name,
|
51
51
|
:short => "-H HOSTNAME",
|
52
|
-
:long => "--
|
52
|
+
:long => "--azure-host-name HOSTNAME",
|
53
53
|
:description => "Your Azure host name",
|
54
|
-
:proc => Proc.new { |key| Chef::Config[:knife][:azure_host_name] = key }
|
55
|
-
|
54
|
+
:proc => Proc.new { |key| Chef::Config[:knife][:azure_host_name] = key },
|
55
|
+
:default => "management.core.windows.net"
|
56
|
+
|
57
|
+
option :verify_ssl_cert,
|
58
|
+
:long => "--verify-ssl-cert",
|
59
|
+
:description => "Verify SSL Certificates for communication over HTTPS",
|
60
|
+
:boolean => true,
|
61
|
+
:default => false
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
59
65
|
def connection
|
60
66
|
@connection ||= begin
|
61
67
|
connection = Azure::Connection.new(
|
62
|
-
:azure_subscription_id =>
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
:azure_host_name =>
|
67
|
-
config[:azure_host_name] || Chef::Config[:knife][:azure_host_name]
|
68
|
+
:azure_subscription_id => locate_config_value(:azure_subscription_id),
|
69
|
+
:azure_mgmt_cert => locate_config_value(:azure_mgmt_cert),
|
70
|
+
:azure_host_name => locate_config_value(:azure_host_name),
|
71
|
+
:verify_ssl_cert => locate_config_value(:verify_ssl_cert)
|
68
72
|
)
|
69
|
-
end
|
73
|
+
end
|
70
74
|
end
|
71
75
|
|
72
76
|
def locate_config_value(key)
|
@@ -80,12 +84,12 @@ class Chef
|
|
80
84
|
end
|
81
85
|
end
|
82
86
|
|
83
|
-
def validate!(keys=[:azure_subscription_id, :
|
87
|
+
def validate!(keys=[:azure_subscription_id, :azure_mgmt_cert, :azure_host_name])
|
84
88
|
errors = []
|
85
89
|
|
86
90
|
keys.each do |k|
|
87
91
|
pretty_key = k.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
|
88
|
-
if
|
92
|
+
if locate_config_value(k).nil?
|
89
93
|
errors << "You did not provide a valid '#{pretty_key}' value."
|
90
94
|
end
|
91
95
|
end
|
@@ -98,5 +102,3 @@ class Chef
|
|
98
102
|
end
|
99
103
|
end
|
100
104
|
end
|
101
|
-
|
102
|
-
|
@@ -18,6 +18,7 @@
|
|
18
18
|
# limitations under the License.
|
19
19
|
#
|
20
20
|
|
21
|
+
require 'highline'
|
21
22
|
require File.expand_path('../azure_base', __FILE__)
|
22
23
|
|
23
24
|
class Chef
|
@@ -28,6 +29,10 @@ class Chef
|
|
28
29
|
|
29
30
|
banner "knife azure image list (options)"
|
30
31
|
|
32
|
+
def h
|
33
|
+
@highline ||= HighLine.new
|
34
|
+
end
|
35
|
+
|
31
36
|
def run
|
32
37
|
$stdout.sync = true
|
33
38
|
|
@@ -35,23 +40,21 @@ class Chef
|
|
35
40
|
|
36
41
|
image_list = [
|
37
42
|
ui.color('Name', :bold),
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
#ui.color('Eula', :bold),
|
43
|
+
ui.color('Category', :bold),
|
44
|
+
ui.color('Label', :bold),
|
45
|
+
ui.color('OS', :bold),
|
42
46
|
]
|
43
47
|
items = connection.images.all
|
44
48
|
items.each do |image|
|
45
49
|
if image.os == 'Linux'
|
46
50
|
image_list << image.name.to_s
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#image_list << image.eula.to_s
|
51
|
+
image_list << image.category.to_s
|
52
|
+
image_list << image.label.to_s
|
53
|
+
image_list << image.os.to_s
|
51
54
|
end
|
52
55
|
end
|
53
|
-
puts
|
54
|
-
puts
|
56
|
+
puts "\n"
|
57
|
+
puts h.list(image_list, :columns_across, 4)
|
55
58
|
end
|
56
59
|
end
|
57
60
|
end
|