knife-azure 1.6.0 → 1.7.0
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 +4 -4
- data/LICENSE +201 -201
- data/README.md +37 -654
- data/lib/azure/resource_management/ARM_deployment_template.rb +87 -50
- data/lib/azure/resource_management/ARM_interface.rb +236 -516
- data/lib/azure/resource_management/vnet_config.rb +254 -0
- data/lib/azure/resource_management/windows_credentials.rb +109 -61
- data/lib/azure/service_management/ASM_interface.rb +17 -1
- data/lib/azure/service_management/certificate.rb +37 -13
- data/lib/azure/service_management/connection.rb +0 -0
- data/lib/azure/service_management/deploy.rb +0 -0
- data/lib/azure/service_management/disk.rb +0 -0
- data/lib/azure/service_management/host.rb +0 -0
- data/lib/azure/service_management/image.rb +0 -0
- data/lib/azure/service_management/rest.rb +0 -0
- data/lib/azure/service_management/role.rb +0 -0
- data/lib/azure/service_management/utility.rb +0 -0
- data/lib/chef/knife/azure_base.rb +100 -0
- data/lib/chef/knife/azure_image_list.rb +0 -0
- data/lib/chef/knife/azure_server_create.rb +0 -98
- data/lib/chef/knife/azure_server_delete.rb +0 -0
- data/lib/chef/knife/azure_server_list.rb +0 -0
- data/lib/chef/knife/azure_server_show.rb +0 -0
- data/lib/chef/knife/azurerm_base.rb +42 -9
- data/lib/chef/knife/azurerm_server_create.rb +31 -24
- data/lib/chef/knife/azurerm_server_delete.rb +1 -10
- data/lib/chef/knife/azurerm_server_list.rb +5 -1
- data/lib/chef/knife/azurerm_server_show.rb +5 -1
- data/lib/chef/knife/bootstrap/bootstrap_options.rb +12 -18
- data/lib/chef/knife/bootstrap/bootstrapper.rb +34 -15
- data/lib/chef/knife/bootstrap/common_bootstrap_options.rb +21 -24
- data/lib/chef/knife/bootstrap_azure.rb +58 -0
- data/lib/chef/knife/bootstrap_azurerm.rb +40 -50
- data/lib/knife-azure/version.rb +1 -1
- metadata +27 -12
@@ -132,17 +132,24 @@ class Chef
|
|
132
132
|
|
133
133
|
option :azure_vnet_name,
|
134
134
|
:long => "--azure-vnet-name VNET_NAME",
|
135
|
-
:description => "Optional. Specifies the virtual network name
|
136
|
-
|
137
|
-
|
135
|
+
:description => "Optional. Specifies the virtual network name.
|
136
|
+
This may be the name of an existing vnet present under the given resource group
|
137
|
+
or this may be the name of a new vnet to be added in the given resource group.
|
138
|
+
If not specified then azure-vm-name will be taken as the default name for vnet name as well.
|
139
|
+
Along with this option azure-vnet-subnet-name option can also be specified or it can also be skipped."
|
138
140
|
|
139
141
|
option :azure_vnet_subnet_name,
|
140
142
|
:long => "--azure-vnet-subnet-name VNET_SUBNET_NAME",
|
141
|
-
:description => "Optional. Specifies the virtual network subnet name.
|
143
|
+
:description => "Optional. Specifies the virtual network subnet name.
|
144
|
+
Must be specified only with azure-vnet-name option.
|
145
|
+
This may be the name of an existing subnet present under the given virtual network
|
146
|
+
or this may be the name of a new subnet to be added in the given virtual network.
|
147
|
+
If not specified then azure-vm-name will be taken as the default name for subnet name as well.
|
148
|
+
Value as 'GatewaySubnet' cannot be used as the name for the --azure-vnet-subnet-name option."
|
142
149
|
|
143
|
-
option :
|
144
|
-
:long => "--
|
145
|
-
:description => "
|
150
|
+
option :ssh_public_key,
|
151
|
+
:long => "--ssh-public-key FILENAME",
|
152
|
+
:description => "It is the ssh-rsa public key path. Specify either ssh-password or ssh-public-key"
|
146
153
|
|
147
154
|
option :thumbprint,
|
148
155
|
:long => "--thumbprint THUMBPRINT",
|
@@ -156,6 +163,11 @@ class Chef
|
|
156
163
|
:long => "--cert-path PATH",
|
157
164
|
:description => "SSL Certificate Path"
|
158
165
|
|
166
|
+
option :tcp_endpoints,
|
167
|
+
:short => "-t PORT_LIST",
|
168
|
+
:long => "--tcp-endpoints PORT_LIST",
|
169
|
+
:description => "Comma-separated list of TCP ports to open e.g. '80,433'"
|
170
|
+
|
159
171
|
option :server_count,
|
160
172
|
:long => "--server-count COUNT",
|
161
173
|
:description => "Number of servers to create with same configuration.
|
@@ -188,16 +200,7 @@ class Chef
|
|
188
200
|
|
189
201
|
vm_details = service.create_server(create_server_def)
|
190
202
|
rescue => error
|
191
|
-
|
192
|
-
if error.response.body['error']['code'] == 'DeploymentFailed'
|
193
|
-
ui.error("#{error.body['error']['message']}")
|
194
|
-
else
|
195
|
-
ui.error(error.response.body)
|
196
|
-
end
|
197
|
-
else
|
198
|
-
ui.error("#{error.message}")
|
199
|
-
end
|
200
|
-
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
203
|
+
service.common_arm_rescue_block(error)
|
201
204
|
exit
|
202
205
|
end
|
203
206
|
end
|
@@ -227,6 +230,10 @@ class Chef
|
|
227
230
|
:server_count => locate_config_value(:server_count)
|
228
231
|
}
|
229
232
|
|
233
|
+
if locate_config_value(:tcp_endpoints)
|
234
|
+
server_def[:tcp_endpoints] = locate_config_value(:tcp_endpoints)
|
235
|
+
end
|
236
|
+
|
230
237
|
server_def[:azure_storage_account] = locate_config_value(:azure_vm_name) if server_def[:azure_storage_account].nil?
|
231
238
|
server_def[:azure_storage_account] = server_def[:azure_storage_account].gsub(/[!@#$%^&*()_-]/,'')
|
232
239
|
|
@@ -234,7 +241,7 @@ class Chef
|
|
234
241
|
server_def[:azure_os_disk_name] = server_def[:azure_os_disk_name].gsub(/[!@#$%^&*()_-]/,'')
|
235
242
|
|
236
243
|
server_def[:azure_vnet_name] = locate_config_value(:azure_vm_name) if server_def[:azure_vnet_name].nil?
|
237
|
-
server_def[:azure_vnet_subnet_name] = locate_config_value(:azure_vm_name) if locate_config_value(:azure_vnet_subnet_name).nil?
|
244
|
+
server_def[:azure_vnet_subnet_name] = locate_config_value(:azure_vm_name) if locate_config_value(:azure_vnet_subnet_name).nil?
|
238
245
|
|
239
246
|
server_def[:chef_extension] = get_chef_extension_name
|
240
247
|
server_def[:chef_extension_publisher] = get_chef_extension_publisher
|
@@ -249,9 +256,9 @@ class Chef
|
|
249
256
|
server_def[:ssh_user] = locate_config_value(:ssh_user)
|
250
257
|
server_def[:ssh_password] = locate_config_value(:ssh_password)
|
251
258
|
server_def[:disablePasswordAuthentication] = "false"
|
252
|
-
if locate_config_value(:
|
259
|
+
if locate_config_value(:ssh_public_key)
|
253
260
|
server_def[:disablePasswordAuthentication] = "true"
|
254
|
-
server_def[:ssh_key] = File.read(locate_config_value(:
|
261
|
+
server_def[:ssh_key] = File.read(locate_config_value(:ssh_public_key))
|
255
262
|
end
|
256
263
|
end
|
257
264
|
|
@@ -285,14 +292,14 @@ class Chef
|
|
285
292
|
end
|
286
293
|
|
287
294
|
def validate_params!
|
288
|
-
if locate_config_value(:azure_vnet_name) && !locate_config_value(:azure_vnet_subnet_name)
|
289
|
-
raise ArgumentError, "When a --azure-vnet-name is specified, the --azure-vnet-subnet-name must also be specified."
|
290
|
-
end
|
291
|
-
|
292
295
|
if locate_config_value(:azure_vnet_subnet_name) && !locate_config_value(:azure_vnet_name)
|
293
296
|
raise ArgumentError, "When --azure-vnet-subnet-name is specified, the --azure-vnet-name must also be specified."
|
294
297
|
end
|
295
298
|
|
299
|
+
if locate_config_value(:azure_vnet_subnet_name) == 'GatewaySubnet'
|
300
|
+
raise ArgumentError, 'GatewaySubnet cannot be used as the name for --azure-vnet-subnet-name option. GatewaySubnet can only be used for virtual network gateways.'
|
301
|
+
end
|
302
|
+
|
296
303
|
if is_image_windows?
|
297
304
|
if locate_config_value(:winrm_user).nil? || locate_config_value(:winrm_password).nil?
|
298
305
|
raise ArgumentError, "Please provide --winrm-user and --winrm-password options for Windows option."
|
@@ -104,16 +104,7 @@ class Chef
|
|
104
104
|
ui.warn("Corresponding node and client for the #{vm_name} server were not deleted and remain registered with the Chef Server")
|
105
105
|
end
|
106
106
|
rescue => error
|
107
|
-
|
108
|
-
if error.body['error']['code'] == 'ResourceNotFound'
|
109
|
-
ui.error("#{error.body['error']['message']}")
|
110
|
-
else
|
111
|
-
ui.error(error.body)
|
112
|
-
end
|
113
|
-
else
|
114
|
-
ui.error("#{error.message}")
|
115
|
-
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
116
|
-
end
|
107
|
+
service.common_arm_rescue_block(error)
|
117
108
|
end
|
118
109
|
end
|
119
110
|
end
|
@@ -11,7 +11,11 @@ class Chef
|
|
11
11
|
def run
|
12
12
|
$stdout.sync = true
|
13
13
|
validate_arm_keys!
|
14
|
-
|
14
|
+
begin
|
15
|
+
service.list_servers(locate_config_value(:azure_resource_group_name))
|
16
|
+
rescue => error
|
17
|
+
service.common_arm_rescue_block(error)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
@@ -29,7 +29,11 @@ class Chef
|
|
29
29
|
def run
|
30
30
|
$stdout.sync = true
|
31
31
|
validate_arm_keys!(:azure_resource_group_name)
|
32
|
-
|
32
|
+
begin
|
33
|
+
service.show_server(@name_args[0], locate_config_value(:azure_resource_group_name))
|
34
|
+
rescue => error
|
35
|
+
service.common_arm_rescue_block(error)
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
end
|
@@ -16,6 +16,12 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
|
+
#
|
20
|
+
# Bootstrap options listed here are in accordance with the options supported by
|
21
|
+
# Chef's bootstrap which bootstraps the target system through protocols like ssh
|
22
|
+
# or winrm. In addition it contains additional options which gives the users a
|
23
|
+
# choice to bootstrap the target system through cloud-api protocol.
|
24
|
+
#
|
19
25
|
|
20
26
|
require 'chef/knife/winrm_base'
|
21
27
|
require 'chef/knife/bootstrap_windows_base'
|
@@ -72,30 +78,18 @@ class Chef
|
|
72
78
|
:description => "Execute the bootstrap via sudo with password",
|
73
79
|
:boolean => false
|
74
80
|
|
75
|
-
option :auto_update_client,
|
76
|
-
:long => "--auto-update-client",
|
77
|
-
:boolean => true,
|
78
|
-
:default => false,
|
79
|
-
:description => "Set this flag to enable auto chef client update in azure chef extension. This flag should be used with cloud-api bootstrap protocol only"
|
80
|
-
|
81
|
-
option :delete_chef_extension_config,
|
82
|
-
:long => "--delete-chef-extension-config",
|
83
|
-
:boolean => true,
|
84
|
-
:default => false,
|
85
|
-
:description => "Determines whether Chef configuration files removed when Azure removes the Chef resource extension from the VM. This option is only valid for the 'cloud-api' bootstrap protocol. The default is false."
|
86
|
-
|
87
|
-
option :uninstall_chef_client,
|
88
|
-
:long => "--uninstall-chef-client",
|
89
|
-
:boolean => true,
|
90
|
-
:default => false,
|
91
|
-
:description => "Determines whether Chef Client will be un-installed from the VM or not. This option is only valid for the 'cloud-api' bootstrap protocol. The default value is false."
|
92
|
-
|
93
81
|
option :extended_logs,
|
94
82
|
:long => "--extended-logs",
|
95
83
|
:boolean => true,
|
96
84
|
:default => false,
|
97
85
|
:description => "Optional. Provide this option when --bootstrap-protocol is set to 'cloud-api'. It shows chef converge logs in detail."
|
98
86
|
|
87
|
+
option :chef_service_interval,
|
88
|
+
:long => "--chef-service-interval INTERVAL",
|
89
|
+
:description => "Optional. Provide this option when --bootstrap-protocol is set to 'cloud-api'.
|
90
|
+
It specifies the frequency (in minutes) at which the chef-service runs.
|
91
|
+
Pass 0 if you don't want the chef-service to be installed on the target machine."
|
92
|
+
|
99
93
|
end
|
100
94
|
end
|
101
95
|
end
|
@@ -217,8 +217,8 @@ class Chef
|
|
217
217
|
bootstrap.config[:host_key_verify] = config[:host_key_verify]
|
218
218
|
Chef::Config[:knife][:secret] = config[:encrypted_data_bag_secret] if config[:encrypted_data_bag_secret]
|
219
219
|
Chef::Config[:knife][:secret_file] = config[:encrypted_data_bag_secret_file] if config[:encrypted_data_bag_secret_file]
|
220
|
-
bootstrap.config[:secret] = locate_config_value(:
|
221
|
-
bootstrap.config[:secret_file] = locate_config_value(:
|
220
|
+
bootstrap.config[:secret] = locate_config_value(:encrypted_data_bag_secret)
|
221
|
+
bootstrap.config[:secret_file] = locate_config_value(:encrypted_data_bag_secret_file)
|
222
222
|
bootstrap.config[:bootstrap_install_command] = locate_config_value(:bootstrap_install_command)
|
223
223
|
bootstrap.config[:bootstrap_wget_options] = locate_config_value(:bootstrap_wget_options)
|
224
224
|
bootstrap.config[:bootstrap_curl_options] = locate_config_value(:bootstrap_curl_options)
|
@@ -239,8 +239,16 @@ class Chef
|
|
239
239
|
Chef::Config[:knife][:azure_chef_extension_version]
|
240
240
|
else
|
241
241
|
chef_extension_name = chef_extension_name.nil? ? get_chef_extension_name : chef_extension_name
|
242
|
-
|
243
|
-
|
242
|
+
if @service.instance_of? Azure::ResourceManagement::ARMInterface
|
243
|
+
service.get_latest_chef_extension_version({
|
244
|
+
:azure_service_location => locate_config_value(:azure_service_location),
|
245
|
+
:chef_extension_publisher => get_chef_extension_publisher,
|
246
|
+
:chef_extension => chef_extension_name
|
247
|
+
})
|
248
|
+
elsif @service.instance_of? Azure::ServiceManagement::ASMInterface
|
249
|
+
extensions = service.get_extension(chef_extension_name, get_chef_extension_publisher)
|
250
|
+
extensions.css("Version").max.text.split(".").first + ".*"
|
251
|
+
end
|
244
252
|
end
|
245
253
|
end
|
246
254
|
|
@@ -273,24 +281,15 @@ class Chef
|
|
273
281
|
end
|
274
282
|
|
275
283
|
pub_config[:runlist] = locate_config_value(:run_list).empty? ? "" : locate_config_value(:run_list).join(",").to_json
|
276
|
-
pub_config[:autoUpdateClient] = locate_config_value(:auto_update_client) ? "true" : "false"
|
277
|
-
pub_config[:deleteChefConfig] = locate_config_value(:delete_chef_extension_config) ? "true" : "false"
|
278
|
-
pub_config[:uninstallChefClient] = locate_config_value(:uninstall_chef_client) ? "true" : "false"
|
279
284
|
pub_config[:custom_json_attr] = locate_config_value(:json_attributes) || {}
|
280
285
|
pub_config[:extendedLogs] = locate_config_value(:extended_logs) ? "true" : "false"
|
281
|
-
pub_config[:hints] = ohai_hints if @service.instance_of?
|
286
|
+
pub_config[:hints] = ohai_hints if @service.instance_of?(Azure::ResourceManagement::ARMInterface) && !locate_config_value(:ohai_hints).nil?
|
287
|
+
pub_config[:chef_service_interval] = locate_config_value(:chef_service_interval) if locate_config_value(:chef_service_interval)
|
282
288
|
|
283
289
|
# bootstrap attributes
|
284
290
|
pub_config[:bootstrap_options] = {}
|
285
291
|
pub_config[:bootstrap_options][:environment] = locate_config_value(:environment) if locate_config_value(:environment)
|
286
292
|
pub_config[:bootstrap_options][:chef_node_name] = locate_config_value(:chef_node_name) if locate_config_value(:chef_node_name)
|
287
|
-
|
288
|
-
if ( locate_config_value(:secret_file) || locate_config_value(:encrypted_data_bag_secret_file) ) && ( !locate_config_value(:secret) || !locate_config_value(:encrypted_data_bag_secret) )
|
289
|
-
pub_config[:bootstrap_options][:encrypted_data_bag_secret] = Chef::EncryptedDataBagItem.load_secret(config[:secret_file])
|
290
|
-
elsif locate_config_value(:encrypted_data_bag_secret) || locate_config_value(:secret)
|
291
|
-
pub_config[:bootstrap_options][:encrypted_data_bag_secret] = locate_config_value(:encrypted_data_bag_secret) || locate_config_value(:secret)
|
292
|
-
end
|
293
|
-
|
294
293
|
pub_config[:bootstrap_options][:chef_server_url] = Chef::Config[:chef_server_url] if Chef::Config[:chef_server_url]
|
295
294
|
pub_config[:bootstrap_options][:validation_client_name] = Chef::Config[:validation_client_name] if Chef::Config[:validation_client_name]
|
296
295
|
pub_config[:bootstrap_options][:node_verify_api_cert] = locate_config_value(:node_verify_api_cert) ? "true" : "false" if config.key?(:node_verify_api_cert)
|
@@ -301,6 +300,23 @@ class Chef
|
|
301
300
|
pub_config
|
302
301
|
end
|
303
302
|
|
303
|
+
def load_correct_secret
|
304
|
+
knife_secret_file = Chef::Config[:knife][:encrypted_data_bag_secret_file]
|
305
|
+
knife_secret = Chef::Config[:knife][:encrypted_data_bag_secret]
|
306
|
+
cli_secret_file = config[:encrypted_data_bag_secret_file]
|
307
|
+
cli_secret = config[:encrypted_data_bag_secret]
|
308
|
+
|
309
|
+
#The value set in knife.rb gets set in config object too
|
310
|
+
#That's why setting cli objects to nil if the values are specified in knife.rb
|
311
|
+
cli_secret_file = nil if cli_secret_file == knife_secret_file
|
312
|
+
cli_secret = nil if cli_secret == knife_secret
|
313
|
+
|
314
|
+
cli_secret_file = Chef::EncryptedDataBagItem.load_secret(cli_secret_file) if cli_secret_file != nil
|
315
|
+
knife_secret_file = Chef::EncryptedDataBagItem.load_secret(knife_secret_file) if knife_secret_file != nil
|
316
|
+
|
317
|
+
cli_secret_file || cli_secret || knife_secret_file || knife_secret
|
318
|
+
end
|
319
|
+
|
304
320
|
def get_chef_extension_private_params
|
305
321
|
pri_config = Hash.new
|
306
322
|
|
@@ -335,6 +351,9 @@ class Chef
|
|
335
351
|
end
|
336
352
|
end
|
337
353
|
|
354
|
+
# encrypted_data_bag_secret key for encrypting/decrypting the data bags
|
355
|
+
pri_config[:encrypted_data_bag_secret] = load_correct_secret
|
356
|
+
|
338
357
|
pri_config
|
339
358
|
end
|
340
359
|
end
|
@@ -16,6 +16,9 @@
|
|
16
16
|
# See the License for the specific language governing permissions and
|
17
17
|
# limitations under the License.
|
18
18
|
#
|
19
|
+
#
|
20
|
+
# Bootstrap options listed here are supported only for cloud-api protocol.
|
21
|
+
#
|
19
22
|
|
20
23
|
class Chef
|
21
24
|
class Knife
|
@@ -81,36 +84,30 @@ class Chef
|
|
81
84
|
:long => "--azure-extension-client-config CLIENT_PATH",
|
82
85
|
:description => "Optional. Path to a client.rb file for use by the bootstrapped node."
|
83
86
|
|
84
|
-
option :
|
85
|
-
:long => "--auto-update-client",
|
86
|
-
:boolean => true,
|
87
|
-
:default => false,
|
88
|
-
:description => "Set this flag to enable auto chef client update in azure chef extension."
|
89
|
-
|
90
|
-
option :delete_chef_extension_config,
|
91
|
-
:long => "--delete-chef-extension-config",
|
92
|
-
:boolean => true,
|
93
|
-
:default => false,
|
94
|
-
:description => "Determines whether Chef configuration files removed when Azure removes the Chef resource extension from the VM. The default is false."
|
95
|
-
|
96
|
-
option :uninstall_chef_client,
|
97
|
-
:long => "--uninstall-chef-client",
|
98
|
-
:boolean => true,
|
99
|
-
:default => false,
|
100
|
-
:description => "Determines whether Chef Client will be un-installed from the VM or not. The default value is false."
|
101
|
-
|
102
|
-
option :secret,
|
87
|
+
option :encrypted_data_bag_secret,
|
103
88
|
:short => "-s SECRET",
|
104
89
|
:long => "--secret ",
|
105
90
|
:description => "The secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret'"
|
106
91
|
|
107
|
-
option :
|
92
|
+
option :encrypted_data_bag_secret_file,
|
108
93
|
:long => "--secret-file SECRET_FILE",
|
109
94
|
:description => "A file containing the secret key to use to encrypt data bag item values. Can also be defaulted in your config with the key 'secret_file'"
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
95
|
+
|
96
|
+
option :extended_logs,
|
97
|
+
:long => "--extended-logs",
|
98
|
+
:boolean => true,
|
99
|
+
:default => false,
|
100
|
+
:description => "Optional. It shows chef convergence logs in detail."
|
101
|
+
|
102
|
+
option :chef_service_interval,
|
103
|
+
:long => "--chef-service-interval INTERVAL",
|
104
|
+
:description => "Optional. It specifies the frequency (in minutes) at which the chef-service runs.
|
105
|
+
Pass 0 if you don't want the chef-service to be installed on the target machine."
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
@@ -42,6 +42,12 @@ class Chef
|
|
42
42
|
begin
|
43
43
|
if @name_args.length == 1
|
44
44
|
service.add_extension(@name_args[0], set_ext_params)
|
45
|
+
if locate_config_value(:extended_logs)
|
46
|
+
print "\n\nWaiting for the Chef Extension to become available/ready"
|
47
|
+
wait_until_extension_available(Time.now, 10)
|
48
|
+
print "\n\nWaiting for the first chef-client run"
|
49
|
+
fetch_chef_client_logs(Time.now, 35)
|
50
|
+
end
|
45
51
|
else
|
46
52
|
raise ArgumentError, 'Please specify the SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length == 0
|
47
53
|
raise ArgumentError, 'Please specify only one SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length > 1
|
@@ -61,6 +67,8 @@ class Chef
|
|
61
67
|
azure_dns_name: locate_config_value(:azure_dns_name)
|
62
68
|
})
|
63
69
|
|
70
|
+
## if azure_dns_name value not passed by user then set it using the hostedservicename attribute from the retrieved server's object ##
|
71
|
+
config[:azure_dns_name] = server.hostedservicename if locate_config_value(:azure_dns_name).nil? && (server.instance_of? Azure::Role)
|
64
72
|
if !server.instance_of? Azure::Role
|
65
73
|
if server.nil?
|
66
74
|
if !locate_config_value(:azure_dns_name).nil?
|
@@ -105,6 +113,56 @@ class Chef
|
|
105
113
|
|
106
114
|
ext_params
|
107
115
|
end
|
116
|
+
|
117
|
+
def wait_until_extension_available(extension_deploy_start_time, extension_availaibility_wait_timeout)
|
118
|
+
extension_availaibility_wait_time = ((Time.now - extension_deploy_start_time) / 60).round
|
119
|
+
if extension_availaibility_wait_time <= extension_availaibility_wait_timeout
|
120
|
+
## extension availaibility wait time has not exceeded the maximum threshold set for the wait timeout ##
|
121
|
+
my_role = nil
|
122
|
+
sleep_and_wait = false
|
123
|
+
deployment = fetch_deployment
|
124
|
+
if deployment.at_css('Deployment Name') != nil
|
125
|
+
role_list_xml = deployment.css('RoleInstanceList RoleInstance')
|
126
|
+
## list of roles found under the deployment ##
|
127
|
+
role_list_xml.each do |role|
|
128
|
+
## search in the roles list for the given role ##
|
129
|
+
if role.at_css("RoleName").text == @name_args[0]
|
130
|
+
my_role = role
|
131
|
+
break
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
if my_role && my_role.at_css("GuestAgentStatus Status").text == "Ready"
|
136
|
+
## given role found and also GuestAgent is ready ##
|
137
|
+
extension = fetch_extension(my_role)
|
138
|
+
## check if Chef Extension not found (which means it is not available/ready yet) then sleep_and_wait OR
|
139
|
+
## if found (which means it is available/ready now) then proceed further with chef-client run logs fetch process ##
|
140
|
+
if extension.nil?
|
141
|
+
sleep_and_wait = true
|
142
|
+
end
|
143
|
+
else
|
144
|
+
## given role not found or GuestAgent not ready yet ##
|
145
|
+
sleep_and_wait = true
|
146
|
+
end
|
147
|
+
else
|
148
|
+
## deployment could not be found ##
|
149
|
+
sleep_and_wait = true
|
150
|
+
end
|
151
|
+
|
152
|
+
## wait for some time and then re-fetch the status ##
|
153
|
+
if sleep_and_wait == true
|
154
|
+
print "#{ui.color('.', :bold)}"
|
155
|
+
sleep 30
|
156
|
+
wait_until_extension_available(
|
157
|
+
extension_deploy_start_time,
|
158
|
+
extension_availaibility_wait_timeout
|
159
|
+
)
|
160
|
+
end
|
161
|
+
else
|
162
|
+
## extension availaibility wait time exceeded maximum threshold set for the wait timeout ##
|
163
|
+
raise "\nUnable to fetch chef-client run logs as Chef Extension seems to be unavailable even after #{extension_availaibility_wait_timeout} minutes of its deployment.\n"
|
164
|
+
end
|
165
|
+
end
|
108
166
|
end
|
109
167
|
end
|
110
168
|
end
|
@@ -20,6 +20,8 @@
|
|
20
20
|
require 'chef/knife/azurerm_base'
|
21
21
|
require 'chef/knife/bootstrap/common_bootstrap_options'
|
22
22
|
require 'chef/knife/bootstrap/bootstrapper'
|
23
|
+
require 'azure/resource_management/ARM_interface'
|
24
|
+
require 'time'
|
23
25
|
|
24
26
|
class Chef
|
25
27
|
class Knife
|
@@ -34,7 +36,7 @@ class Chef
|
|
34
36
|
:short => "-m LOCATION",
|
35
37
|
:long => "--azure-service-location LOCATION",
|
36
38
|
:description => "Required if not using an Affinity Group. Specifies the geographic location - the name of the data center location that is valid for your subscription.
|
37
|
-
Eg:
|
39
|
+
Eg: westus, eastus, eastasia, southeastasia, northeurope, westeurope",
|
38
40
|
:proc => Proc.new { |lo| Chef::Config[:knife][:azure_service_location] = lo }
|
39
41
|
|
40
42
|
def run
|
@@ -42,70 +44,58 @@ class Chef
|
|
42
44
|
validate_arm_keys!(:azure_resource_group_name, :azure_service_location)
|
43
45
|
|
44
46
|
begin
|
45
|
-
|
47
|
+
if @name_args.length == 1
|
46
48
|
ui.log("Creating VirtualMachineExtension....")
|
47
|
-
|
49
|
+
ext_params = set_ext_params
|
50
|
+
vm_extension = service.create_vm_extension(ext_params)
|
48
51
|
if vm_extension
|
52
|
+
if ext_params[:chef_extension_public_param][:extendedLogs] == 'true'
|
53
|
+
service.fetch_chef_client_logs(ext_params[:azure_resource_group_name], ext_params[:azure_vm_name], ext_params[:chef_extension], Time.now)
|
54
|
+
end
|
49
55
|
ui.log("VirtualMachineExtension creation successfull.")
|
50
56
|
ui.log("Virtual Machine Extension name is: #{vm_extension.name}")
|
51
57
|
ui.log("Virtual Machine Extension ID is: #{vm_extension.id}")
|
52
58
|
end
|
53
|
-
else
|
54
|
-
raise ArgumentError, 'Please specify the SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length == 0
|
55
|
-
raise ArgumentError, 'Please specify only one SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length > 1
|
56
|
-
end
|
57
|
-
rescue => error
|
58
|
-
if error.class == MsRestAzure::AzureOperationError && error.body
|
59
|
-
if error.body['error']['code'] == 'DeploymentFailed'
|
60
|
-
ui.error("#{error.body['error']['message']}")
|
61
|
-
else
|
62
|
-
ui.error(error.body)
|
63
|
-
end
|
64
59
|
else
|
65
|
-
|
66
|
-
Chef
|
60
|
+
raise ArgumentError, 'Please specify the SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length == 0
|
61
|
+
raise ArgumentError, 'Please specify only one SERVER name which needs to be bootstrapped via the Chef Extension.' if @name_args.length > 1
|
67
62
|
end
|
68
|
-
|
69
|
-
|
63
|
+
rescue => error
|
64
|
+
service.common_arm_rescue_block(error)
|
65
|
+
end
|
70
66
|
end
|
71
67
|
|
72
68
|
def set_ext_params
|
73
|
-
|
74
|
-
server = service.find_server(locate_config_value(:azure_resource_group_name), name_args[0])
|
69
|
+
server = service.find_server(locate_config_value(:azure_resource_group_name), name_args[0])
|
75
70
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
else
|
88
|
-
raise "Offer #{server.properties.storage_profile.image_reference.offer} is not supported in the extension."
|
89
|
-
end
|
71
|
+
if server
|
72
|
+
if service.extension_already_installed?(server)
|
73
|
+
raise "Virtual machine #{server.name} already has Chef extension installed on it."
|
74
|
+
else
|
75
|
+
ext_params = Hash.new
|
76
|
+
case server.properties.storage_profile.os_disk.os_type.downcase
|
77
|
+
when 'windows'
|
78
|
+
ext_params[:chef_extension] = 'ChefClient'
|
79
|
+
when 'linux'
|
80
|
+
if ['ubuntu', 'debian', 'rhel', 'centos'].any? { |platform| server.properties.storage_profile.image_reference.offer.downcase.include? platform }
|
81
|
+
ext_params[:chef_extension] = 'LinuxChefClient'
|
90
82
|
else
|
91
|
-
raise "
|
83
|
+
raise "Offer #{server.properties.storage_profile.image_reference.offer} is not supported in the extension."
|
92
84
|
end
|
93
|
-
|
94
|
-
|
95
|
-
ext_params[:azure_vm_name] = @name_args[0]
|
96
|
-
ext_params[:azure_service_location] = locate_config_value(:azure_service_location)
|
97
|
-
ext_params[:chef_extension_publisher] = get_chef_extension_publisher
|
98
|
-
ext_params[:chef_extension_version] = get_chef_extension_version(ext_params[:chef_extension])
|
99
|
-
ext_params[:chef_extension_public_param] = get_chef_extension_public_params
|
100
|
-
ext_params[:chef_extension_private_param] = get_chef_extension_private_params
|
85
|
+
else
|
86
|
+
raise "OS type #{server.properties.storage_profile.os_disk.os_type} is not supported."
|
101
87
|
end
|
102
|
-
|
103
|
-
|
88
|
+
|
89
|
+
ext_params[:azure_resource_group_name] = locate_config_value(:azure_resource_group_name)
|
90
|
+
ext_params[:azure_vm_name] = @name_args[0]
|
91
|
+
ext_params[:azure_service_location] = locate_config_value(:azure_service_location)
|
92
|
+
ext_params[:chef_extension_publisher] = get_chef_extension_publisher
|
93
|
+
ext_params[:chef_extension_version] = get_chef_extension_version(ext_params[:chef_extension])
|
94
|
+
ext_params[:chef_extension_public_param] = get_chef_extension_public_params
|
95
|
+
ext_params[:chef_extension_private_param] = get_chef_extension_private_params
|
104
96
|
end
|
105
|
-
|
106
|
-
|
107
|
-
Chef::Log.debug("#{error.backtrace.join("\n")}")
|
108
|
-
exit
|
97
|
+
else
|
98
|
+
raise "The given server '#{@name_args[0]}' does not exist under resource group '#{locate_config_value(:azure_resource_group_name)}'"
|
109
99
|
end
|
110
100
|
|
111
101
|
ext_params
|
@@ -113,4 +103,4 @@ class Chef
|
|
113
103
|
|
114
104
|
end
|
115
105
|
end
|
116
|
-
end
|
106
|
+
end
|