knife-azure 1.8.0 → 1.8.6

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.
@@ -23,8 +23,6 @@ class Chef
23
23
  class AzureAgList < Knife
24
24
  include Knife::AzureBase
25
25
 
26
- deps { require 'highline' }
27
-
28
26
  banner 'knife azure ag list (options)'
29
27
 
30
28
  def run
@@ -124,7 +124,77 @@ class Chef
124
124
  end
125
125
 
126
126
  # validate command pre-requisites (cli options)
127
+ # (locate_config_value(:winrm_password).length <= 6 && locate_config_value(:winrm_password).length >= 72)
127
128
  def validate_params!
129
+ if locate_config_value(:winrm_password) && !locate_config_value(:winrm_password).strip.size.between?(6, 72)
130
+ ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
131
+ exit 1
132
+ end
133
+
134
+ if locate_config_value(:ssh_password) && !locate_config_value(:ssh_password).empty? && !locate_config_value(:ssh_password).strip.size.between?(6, 72)
135
+ ui.error("The supplied ssh password must be 6-72 characters long and meet password complexity requirements")
136
+ exit 1
137
+ end
138
+
139
+ if locate_config_value(:azure_connect_to_existing_dns) && locate_config_value(:azure_vm_name).nil?
140
+ ui.error("Specify the VM name using --azure-vm-name option, since you are connecting to existing dns")
141
+ exit 1
142
+ end
143
+
144
+ if locate_config_value(:azure_service_location) && locate_config_value(:azure_affinity_group)
145
+ ui.error("Cannot specify both --azure-service-location and --azure-affinity-group, use one or the other.")
146
+ exit 1
147
+ elsif locate_config_value(:azure_service_location).nil? && locate_config_value(:azure_affinity_group).nil?
148
+ ui.error("Must specify either --azure-service-location or --azure-affinity-group.")
149
+ exit 1
150
+ end
151
+
152
+ if locate_config_value(:winrm_authentication_protocol) && ! %w{basic negotiate kerberos}.include?(locate_config_value(:winrm_authentication_protocol).downcase)
153
+ ui.error("Invalid value for --winrm-authentication-protocol option. Use valid protocol values i.e [basic, negotiate, kerberos]")
154
+ exit 1
155
+ end
156
+
157
+ if !(service.valid_image?(locate_config_value(:azure_source_image)))
158
+ ui.error("Image '#{locate_config_value(:azure_source_image)}' is invalid")
159
+ exit 1
160
+ end
161
+
162
+ # Validate join domain requirements.
163
+ if locate_config_value(:azure_domain_name) || locate_config_value(:azure_domain_user)
164
+ if locate_config_value(:azure_domain_user).nil? || locate_config_value(:azure_domain_passwd).nil?
165
+ ui.error("Must specify both --azure-domain-user and --azure-domain-passwd.")
166
+ exit 1
167
+ end
168
+ end
169
+
170
+ if locate_config_value(:winrm_transport) == "ssl" && locate_config_value(:thumbprint).nil? && ( locate_config_value(:winrm_ssl_verify_mode).nil? || locate_config_value(:winrm_ssl_verify_mode) == :verify_peer )
171
+ ui.error("The SSL transport was specified without the --thumbprint option. Specify a thumbprint, or alternatively set the --winrm-ssl-verify-mode option to 'verify_none' to skip verification.")
172
+ exit 1
173
+ end
174
+
175
+ if locate_config_value(:extended_logs) && locate_config_value(:bootstrap_protocol) != 'cloud-api'
176
+ ui.error("--extended-logs option only works with --bootstrap-protocol cloud-api")
177
+ exit 1
178
+ end
179
+
180
+ if locate_config_value(:bootstrap_protocol) == 'cloud-api' && locate_config_value(:azure_vm_name).nil? && locate_config_value(:azure_dns_name).nil?
181
+ ui.error("Specifying the DNS name using --azure-dns-name or VM name using --azure-vm-name option is required with --bootstrap-protocol cloud-api")
182
+ exit 1
183
+ end
184
+
185
+ if locate_config_value(:daemon)
186
+ unless is_image_windows?
187
+ raise ArgumentError, "The daemon option is only supported for Windows nodes."
188
+ end
189
+
190
+ unless locate_config_value(:bootstrap_protocol) == 'cloud-api'
191
+ raise ArgumentError, "The --daemon option requires the use of --bootstrap-protocol cloud-api"
192
+ end
193
+
194
+ unless %w{none service task}.include?(locate_config_value(:daemon).downcase)
195
+ raise ArgumentError, "Invalid value for --daemon option. Valid values are 'none', 'service' and 'task'."
196
+ end
197
+ end
128
198
  end
129
199
 
130
200
  # validates keys
File without changes
@@ -23,8 +23,6 @@ class Chef
23
23
  class AzureInternalLbList < Knife
24
24
  include Knife::AzureBase
25
25
 
26
- deps { require 'highline' }
27
-
28
26
  banner 'knife azure internal lb list (options)'
29
27
 
30
28
  def run
@@ -232,7 +232,6 @@ class Chef
232
232
 
233
233
  def wait_until_virtual_machine_ready(retry_interval_in_seconds = 30)
234
234
  vm_status = nil
235
-
236
235
  begin
237
236
  azure_vm_startup_timeout = locate_config_value(:azure_vm_startup_timeout).to_i
238
237
  azure_vm_ready_timeout = locate_config_value(:azure_vm_ready_timeout).to_i
@@ -355,12 +354,9 @@ class Chef
355
354
  if role.at_css("RoleName").text == locate_config_value(:azure_vm_name)
356
355
  lnx_waagent_fail_msg = "Failed to deserialize the status reported by the Guest Agent"
357
356
  waagent_status_msg = role.at_css("GuestAgentStatus FormattedMessage Message").text
358
-
359
357
  if role.at_css("GuestAgentStatus Status").text == "Ready"
360
358
  extn_status = role.at_css("ResourceExtensionStatusList Status").text
361
-
362
359
  Chef::Log.debug("Resource extension status is #{extn_status}")
363
-
364
360
  if extn_status == "Installing"
365
361
  extension_status[:status] = :extension_installing
366
362
  extension_status[:message] = role.at_css("ResourceExtensionStatusList FormattedMessage Message").text
@@ -387,30 +383,20 @@ class Chef
387
383
  else
388
384
  extension_status[:status] = :extension_status_not_detected
389
385
  end
390
-
391
386
  return extension_status
392
387
  end
393
388
 
394
389
  def run
395
390
  $stdout.sync = true
396
-
397
391
  storage = nil
398
-
399
392
  Chef::Log.info("validating...")
400
393
  validate_asm_keys!(:azure_source_image)
401
-
402
394
  validate_params!
403
-
404
395
  ssh_override_winrm if !is_image_windows?
405
-
406
396
  Chef::Log.info("creating...")
407
-
408
397
  config[:azure_dns_name] = get_dns_name(locate_config_value(:azure_dns_name))
409
-
410
- if not locate_config_value(:azure_vm_name)
411
- config[:azure_vm_name] = locate_config_value(:azure_dns_name)
412
- end
413
-
398
+ config[:azure_vm_name] = locate_config_value(:azure_dns_name) unless locate_config_value(:azure_vm_name)
399
+ config[:chef_node_name] = locate_config_value(:azure_vm_name) unless locate_config_value(:chef_node_name)
414
400
  service.create_server(create_server_def)
415
401
  wait_until_virtual_machine_ready()
416
402
  if locate_config_value(:bootstrap_protocol) == 'cloud-api' && locate_config_value(:extended_logs)
@@ -423,73 +409,6 @@ class Chef
423
409
  bootstrap_exec(server) unless locate_config_value(:bootstrap_protocol) == 'cloud-api'
424
410
  end
425
411
 
426
- def validate_params!
427
- if locate_config_value(:winrm_password) && (locate_config_value(:winrm_password).length <= 6 && locate_config_value(:winrm_password).length >= 72)
428
- ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
429
- exit 1
430
- end
431
-
432
- if locate_config_value(:ssh_password) && (locate_config_value(:ssh_password).length <= 6 && locate_config_value(:ssh_password).length >= 72)
433
- ui.error("The supplied password must be 6-72 characters long and meet password complexity requirements")
434
- exit 1
435
- end
436
-
437
- if locate_config_value(:azure_connect_to_existing_dns) && locate_config_value(:azure_vm_name).nil?
438
- ui.error("Specify the VM name using --azure-vm-name option, since you are connecting to existing dns")
439
- exit 1
440
- end
441
-
442
- if locate_config_value(:azure_service_location) && locate_config_value(:azure_affinity_group)
443
- ui.error("Cannot specify both --azure-service-location and --azure-affinity-group, use one or the other.")
444
- exit 1
445
- elsif locate_config_value(:azure_service_location).nil? && locate_config_value(:azure_affinity_group).nil?
446
- ui.error("Must specify either --azure-service-location or --azure-affinity-group.")
447
- exit 1
448
- end
449
-
450
- if locate_config_value(:winrm_authentication_protocol) && ! %w{basic negotiate kerberos}.include?(locate_config_value(:winrm_authentication_protocol))
451
- ui.error("Invalid value for --winrm-authentication-protocol option. Use valid protocol values i.e [basic, negotiate, kerberos]")
452
- exit 1
453
- end
454
-
455
- if !(service.valid_image?(locate_config_value(:azure_source_image)))
456
- ui.error("Image provided is invalid")
457
- exit 1
458
- end
459
-
460
- # Validate join domain requirements.
461
- if locate_config_value(:azure_domain_name) || locate_config_value(:azure_domain_user)
462
- if locate_config_value(:azure_domain_user).nil? || locate_config_value(:azure_domain_passwd).nil?
463
- ui.error("Must specify both --azure-domain-user and --azure-domain-passwd.")
464
- exit 1
465
- end
466
- end
467
-
468
- if locate_config_value(:winrm_transport) == "ssl" && locate_config_value(:thumbprint).nil? && ( locate_config_value(:winrm_ssl_verify_mode).nil? || locate_config_value(:winrm_ssl_verify_mode) == :verify_peer )
469
- ui.error("The SSL transport was specified without the --thumbprint option. Specify a thumbprint, or alternatively set the --winrm-ssl-verify-mode option to 'verify_none' to skip verification.")
470
- exit 1
471
- end
472
-
473
- if locate_config_value(:extended_logs) && locate_config_value(:bootstrap_protocol) != 'cloud-api'
474
- ui.error("--extended-logs option works with --bootstrap-protocol cloud-api")
475
- exit 1
476
- end
477
-
478
- if locate_config_value(:daemon)
479
- unless is_image_windows?
480
- raise ArgumentError, "The daemon option is only support for Windows nodes."
481
- end
482
-
483
- unless locate_config_value(:bootstrap_protocol) == 'cloud-api'
484
- raise ArgumentError, "--daemon option works with --bootstrap-protocol cloud-api"
485
- end
486
-
487
- unless %w{none service task}.include?(locate_config_value(:daemon))
488
- raise ArgumentError, "Invalid value for --daemon option. Use valid daemon values i.e 'none', 'service' and 'task'."
489
- end
490
- end
491
- end
492
-
493
412
  def create_server_def
494
413
  server_def = {
495
414
  :azure_storage_account => locate_config_value(:azure_storage_account),
File without changes
File without changes
File without changes
@@ -23,8 +23,6 @@ class Chef
23
23
  class AzureVnetList < Knife
24
24
  include Knife::AzureBase
25
25
 
26
- deps { require 'highline' }
27
-
28
26
  banner 'knife azure vnet list (options)'
29
27
 
30
28
  def run
@@ -1,7 +1,7 @@
1
1
 
2
2
  # Author:: Aliasgar Batterywala (aliasgar.batterywala@clogeny.com)
3
3
  #
4
- # Copyright:: Copyright (c) 2016 Opscode, Inc.
4
+ # Copyright:: Copyright 2009-2018, Chef Software Inc.
5
5
  # License:: Apache License, Version 2.0
6
6
  #
7
7
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -40,7 +40,6 @@ class Chef
40
40
 
41
41
  def self.included(includer)
42
42
  includer.class_eval do
43
-
44
43
  deps do
45
44
  require 'readline'
46
45
  require 'chef/json_compat'
@@ -50,7 +49,6 @@ class Chef
50
49
  :short => "-r RESOURCE_GROUP_NAME",
51
50
  :long => "--azure-resource-group-name RESOURCE_GROUP_NAME",
52
51
  :description => "The Resource Group name."
53
-
54
52
  end
55
53
  end
56
54
 
@@ -71,13 +69,13 @@ class Chef
71
69
 
72
70
  # validates ARM mandatory keys
73
71
  def validate_arm_keys!(*keys)
74
- parse_publish_settings_file(locate_config_value(:azure_publish_settings_file)) if(locate_config_value(:azure_publish_settings_file) != nil)
72
+ parse_publish_settings_file(locate_config_value(:azure_publish_settings_file)) unless locate_config_value(:azure_publish_settings_file).nil?
75
73
  keys.push(:azure_subscription_id)
76
74
 
77
- if(locate_config_value(:azure_tenant_id).nil? || locate_config_value(:azure_client_id).nil? || locate_config_value(:azure_client_secret).nil?)
75
+ if azure_cred?
78
76
  validate_azure_login
79
77
  else
80
- keys.concat([:azure_tenant_id, :azure_client_id, :azure_client_secret])
78
+ keys.concat([:azure_tenant_id, :azure_client_id, :azure_client_secret])
81
79
  end
82
80
 
83
81
  errors = []
@@ -92,7 +90,7 @@ class Chef
92
90
  end
93
91
 
94
92
  def authentication_details
95
- if(locate_config_value(:azure_tenant_id) && locate_config_value(:azure_client_id) && locate_config_value(:azure_client_secret))
93
+ if is_azure_cred?
96
94
  return {:azure_tenant_id => locate_config_value(:azure_tenant_id), :azure_client_id => locate_config_value(:azure_client_id), :azure_client_secret => locate_config_value(:azure_client_secret)}
97
95
  elsif Chef::Platform.windows?
98
96
  token_details = token_details_for_windows()
@@ -103,16 +101,13 @@ class Chef
103
101
  token_details
104
102
  end
105
103
 
106
- def current_xplat_cli_version
107
- shell_out!("azure -v", { returns: [0] }).stdout
108
- end
109
-
110
- def is_old_xplat?
111
- Gem::Version.new(current_xplat_cli_version) < Gem::Version.new(XPLAT_VERSION_WITH_WCM_DEPRECATED)
112
- end
113
-
114
- def is_WCM_env_var_set?
115
- ENV['AZURE_USE_SECURE_TOKEN_STORAGE'].nil? ? false : true
104
+ def get_azure_cli_version
105
+ if @azure_version != ""
106
+ get_version = shell_out!("azure -v || az -v | grep azure-cli", { returns: [0] }).stdout
107
+ @azure_version = get_version.gsub(/[^0-9.]/, '')
108
+ end
109
+ @azure_prefix = @azure_version.to_i < 2 ? "azure" : "az"
110
+ @azure_version
116
111
  end
117
112
 
118
113
  def token_details_for_windows
@@ -141,56 +136,49 @@ class Chef
141
136
  return false
142
137
  elsif time_difference <= 600 # 600sec = 10min
143
138
  # This is required otherwise a long running command may fail inbetween if the token gets expired.
144
- raise "Token will expire within 10 minutes. Please run 'azure login' command"
139
+ raise "Token will expire within 10 minutes. Please run '#{@azure_prefix} login' command"
145
140
  else
146
141
  return true
147
142
  end
148
143
  end
149
144
 
150
145
  def refresh_token
146
+ azure_authentication
147
+ token_details = Chef::Platform.windows? ? token_details_for_windows() : token_details_for_linux()
148
+ end
149
+
150
+ def azure_authentication
151
151
  begin
152
152
  ui.log("Authenticating...")
153
- Mixlib::ShellOut.new("azure vm show 'knifetest@resourcegroup' testvm", :timeout => 30).run_command
153
+ Mixlib::ShellOut.new("#{@azure_prefix} vm show 'knifetest@resourcegroup' testvm", :timeout => 30).run_command
154
154
  rescue Mixlib::ShellOut::CommandTimeout
155
155
  rescue Exception
156
- raise "Token has expired. Please run 'azure login' command"
156
+ raise_azure_status
157
157
  end
158
- if Chef::Platform.windows?
159
- token_details = token_details_for_windows()
160
- else
161
- token_details = token_details_for_linux()
162
- end
163
- token_details
164
158
  end
165
159
 
166
160
  def check_token_validity(token_details)
167
- if !is_token_valid?(token_details)
168
- token_details = refresh_token()
169
- if !is_token_valid?(token_details)
170
- raise "Token has expired. Please run 'azure login' command"
161
+ unless is_token_valid?(token_details)
162
+ token_details = refresh_token
163
+ unless is_token_valid?(token_details)
164
+ raise_azure_status
171
165
  end
172
166
  end
173
167
  token_details
174
168
  end
175
169
 
176
170
  def validate_azure_login
177
- err_string = "Please run XPLAT's 'azure login' command OR specify azure_tenant_id, azure_subscription_id, azure_client_id, azure_client_secret in your knife.rb"
178
-
179
- ## Older versions of the Azure CLI on Windows stored credentials in a unique way
180
- ## in Windows Credentails Manager (WCM).
181
- ## Newer versions use the same pattern across platforms where credentials gets
182
- ## stored in ~/.azure/accessTokens.json file.
183
171
  if Chef::Platform.windows? && (is_old_xplat? || is_WCM_env_var_set?)
184
172
  # cmdkey command is used for accessing windows credential manager
185
173
  xplat_creds_cmd = Mixlib::ShellOut.new("cmdkey /list | findstr AzureXplatCli")
186
174
  result = xplat_creds_cmd.run_command
187
175
  if result.stdout.nil? || result.stdout.empty?
188
- raise err_string
176
+ raise login_message
189
177
  end
190
178
  else
191
179
  home_dir = File.expand_path('~')
192
180
  if !File.exists?(home_dir + "/.azure/accessTokens.json") || File.size?(home_dir + '/.azure/accessTokens.json') <= 2
193
- raise err_string
181
+ raise login_message
194
182
  end
195
183
  end
196
184
  end
@@ -238,20 +226,6 @@ class Chef
238
226
  file
239
227
  end
240
228
 
241
- def pretty_key(key)
242
- key.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
243
- end
244
-
245
- def is_image_windows?
246
- locate_config_value(:azure_image_reference_offer) =~ /WindowsServer.*/
247
- end
248
-
249
- def msg_pair(label, value, color=:cyan)
250
- if value && !value.to_s.empty?
251
- puts "#{ui.color(label, color)}: #{value}"
252
- end
253
- end
254
-
255
229
  def msg_server_summary(server)
256
230
  puts "\n\n"
257
231
  if server.provisioningstate == 'Succeeded'
@@ -335,6 +309,51 @@ class Chef
335
309
  config[:ohai_hints] = format_ohai_hints(locate_config_value(:ohai_hints))
336
310
  validate_ohai_hints if ! locate_config_value(:ohai_hints).casecmp('default').zero?
337
311
  end
312
+
313
+ private
314
+
315
+ def msg_pair(label, value, color=:cyan)
316
+ if value && !value.to_s.empty?
317
+ puts "#{ui.color(label, color)}: #{value}"
318
+ end
319
+ end
320
+
321
+ def pretty_key(key)
322
+ key.to_s.gsub(/_/, ' ').gsub(/\w+/){ |w| (w =~ /(ssh)|(aws)/i) ? w.upcase : w.capitalize }
323
+ end
324
+
325
+ def is_image_windows?
326
+ locate_config_value(:azure_image_reference_offer) =~ /WindowsServer.*/
327
+ end
328
+
329
+ def is_azure_cred?
330
+ locate_config_value(:azure_tenant_id) && locate_config_value(:azure_client_id) && locate_config_value(:azure_client_secret)
331
+ end
332
+
333
+ def azure_cred?
334
+ locate_config_value(:azure_tenant_id).nil? || locate_config_value(:azure_client_id).nil? || locate_config_value(:azure_client_secret).nil?
335
+ end
336
+
337
+ def is_old_xplat?
338
+ return true unless @azure_version
339
+ Gem::Version.new(@azure_version) < Gem::Version.new(XPLAT_VERSION_WITH_WCM_DEPRECATED)
340
+ end
341
+
342
+ def is_WCM_env_var_set?
343
+ ENV['AZURE_USE_SECURE_TOKEN_STORAGE'].nil? ? false : true
344
+ end
345
+
346
+ def raise_azure_status
347
+ raise "Token has expired. Please run '#{@azure_prefix} login' command"
348
+ end
349
+
350
+ def login_message
351
+ ## Older versions of the Azure CLI on Windows stored credentials in a unique way
352
+ ## in Windows Credentails Manager (WCM).
353
+ ## Newer versions use the same pattern across platforms where credentials gets
354
+ ## stored in ~/.azure/accessTokens.json file.
355
+ "Please run XPLAT's '#{@azure_prefix} login' command OR specify azure_tenant_id, azure_subscription_id, azure_client_id, azure_client_secret in your knife.rb"
356
+ end
338
357
  end
339
358
  end
340
359
  end