Class: Chef::Knife::Cloud::GoogleService

Inherits:
Service
  • Object
show all
Includes:
GoogleServiceHelpers
Defined in:
lib/chef/knife/cloud/google_service.rb

Constant Summary collapse

SCOPE_ALIAS_MAP =
{
  "bigquery" => "bigquery",
  "cloud-platform" => "cloud-platform",
  "compute-ro" => "compute.readonly",
  "compute-rw" => "compute",
  "datastore" => "datastore",
  "logging-write" => "logging.write",
  "monitoring" => "monitoring",
  "monitoring-write" => "monitoring.write",
  "service-control" => "servicecontrol",
  "service-management" => "service.management",
  "sql" => "sqlservice",
  "sql-admin" => "sqlservice.admin",
  "storage-full" => "devstorage.full_control",
  "storage-ro" => "devstorage.read_only",
  "storage-rw" => "devstorage.read_write",
  "taskqueue" => "taskqueue",
  "useraccounts-ro" => "cloud.useraccounts.readonly",
  "useraccounts-rw" => "cloud.useraccounts",
  "userinfo-email" => "userinfo.email",
}.freeze
IMAGE_ALIAS_MAP =
{
  "centos-6" => { project: "centos-cloud", prefix: "centos-6" },
  "centos-7" => { project: "centos-cloud", prefix: "centos-7" },
  "centos-8" => { project: "centos-cloud", prefix: "centos-8" },
  "container-vm" => { project: "google-containers", prefix: "container-vm" },
  "coreos" => { project: "coreos-cloud", prefix: "coreos-stable" },
  "debian-9" => { project: "debian-cloud", prefix: "debian-9" },
  "debian-10" => { project: "debian-cloud", prefix: "debian-10" },
  "opensuse-13" => { project: "opensuse-cloud", prefix: "opensuse-13" },
  "rhel-6" => { project: "rhel-cloud", prefix: "rhel-6" },
  "rhel-7" => { project: "rhel-cloud", prefix: "rhel-7" },
  "rhel-8" => { project: "rhel-cloud", prefix: "rhel-8" },
  "sles-12" => { project: "suse-cloud", prefix: "sles-12" },
  "sles-15" => { project: "suse-cloud", prefix: "sles-15" },
  "ubuntu-16-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1604-xenial" },
  "ubuntu-1604-lts" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1604-xenial" },
  "ubuntu-1804-lts" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1804-bionic" },
  "ubuntu-2004-lts" => { project: "ubuntu-os-cloud", prefix: "ubuntu-2004-focal" },
  "ubuntu-minimal-1604-lts" => { project: "ubuntu-os-cloud", prefix: "ubuntu-minimal-1604-xenial" },
  "ubuntu-minimal-1804-lts" => { project: "ubuntu-os-cloud", prefix: "ubuntu-minimal-1804-bionic" },
  "windows-2008-r2" => { project: "windows-cloud", prefix: "windows-server-2008-r2" },
  "windows-2012-r2" => { project: "windows-cloud", prefix: "windows-server-2012-r2" },
  "windows-2012-r2-core" => { project: "windows-cloud", prefix: "windows-server-2012-r2-dc-core" },
  "windows-2016-core" => { project: "windows-cloud", prefix: "windows-server-2016-dc-core" },
  "windows-2016" => { project: "windows-cloud", prefix: "windows-server-2016-dc" },
  "windows-2019-core-for-containers" => { project: "windows-cloud", prefix: "windows-server-2019-dc-core-for-containers" },
  "windows-2019-core" => { project: "windows-cloud", prefix: "windows-server-2019-dc-core" },
  "windows-2019-for-containers" => { project: "windows-cloud", prefix: "windows-server-2019-dc-for-containers" },
  "windows-2019" => { project: "windows-cloud", prefix: "windows-server-2019-dc" },
}.freeze
PUBLIC_PROJECTS =
%w{
  centos-cloud
  coreos-cloud
  debian-cloud
  cos-cloud
  rhel-cloud
  rhel-sap-cloud
  suse-cloud
  suse-sap-cloud
  ubuntu-os-cloud
  windows-cloud
  windows-sql-cloud
}.freeze

Constants included from GoogleServiceHelpers

Chef::Knife::Cloud::GoogleServiceHelpers::REQUIRED_KEYS

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from GoogleServiceHelpers

#check_for_missing_config_values!, #create_service_instance, #private_ip_for, #public_ip_for, #valid_disk_size?

Constructor Details

#initialize(options = {}) ⇒ GoogleService

Returns a new instance of GoogleService.



101
102
103
104
105
106
107
108
# File 'lib/chef/knife/cloud/google_service.rb', line 101

def initialize(options = {})
  @project       = options[:project]
  @zone          = options[:zone]
  @wait_time     = options[:wait_time]
  @refresh_rate  = options[:refresh_rate]
  @max_pages     = options[:max_pages]
  @max_page_size = options[:max_page_size]
end

Instance Attribute Details

#max_page_sizeObject (readonly)

Returns the value of attribute max_page_size.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def max_page_size
  @max_page_size
end

#max_pagesObject (readonly)

Returns the value of attribute max_pages.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def max_pages
  @max_pages
end

#projectObject (readonly)

Returns the value of attribute project.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def project
  @project
end

#refresh_rateObject (readonly)

Returns the value of attribute refresh_rate.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def refresh_rate
  @refresh_rate
end

#wait_timeObject (readonly)

Returns the value of attribute wait_time.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def wait_time
  @wait_time
end

#zoneObject (readonly)

Returns the value of attribute zone.



32
33
34
# File 'lib/chef/knife/cloud/google_service.rb', line 32

def zone
  @zone
end

Instance Method Details

#adding_local_ssd(options) ⇒ Object

To create a instance with an attached local SSD



345
346
347
348
349
350
351
352
# File 'lib/chef/knife/cloud/google_service.rb', line 345

def adding_local_ssd(options)
  disk, params = common_operation(options, "local-ssd")
  disk.type = "SCRATCH"
  disk.interface = options[:interface]

  disk.initialize_params = params
  disk
end

#authorizationObject



123
124
125
126
127
128
129
130
# File 'lib/chef/knife/cloud/google_service.rb', line 123

def authorization
  @authorization ||= Google::Auth.get_application_default(
    [
      "https://www.googleapis.com/auth/cloud-platform",
      "https://www.googleapis.com/auth/compute",
    ]
  )
end

#available_projectsObject



648
649
650
# File 'lib/chef/knife/cloud/google_service.rb', line 648

def available_projects
  [project] | PUBLIC_PROJECTS
end

#boot_disk_name_for(options) ⇒ Object



422
423
424
# File 'lib/chef/knife/cloud/google_service.rb', line 422

def boot_disk_name_for(options)
  options[:boot_disk_name].nil? ? options[:name] : options[:boot_disk_name]
end

#boot_disk_source_image(image, image_project) ⇒ Object



366
367
368
# File 'lib/chef/knife/cloud/google_service.rb', line 366

def boot_disk_source_image(image, image_project)
  @boot_disk_source ||= image_search_for(image, image_project)
end

#boot_disk_type_for(options) ⇒ Object



362
363
364
# File 'lib/chef/knife/cloud/google_service.rb', line 362

def boot_disk_type_for(options)
  options[:boot_disk_ssd] ? "pd-ssd" : "pd-standard"
end

#check_api_callObject



247
248
249
250
251
252
253
# File 'lib/chef/knife/cloud/google_service.rb', line 247

def check_api_call
  yield
rescue Google::Apis::ClientError
  false
else
  true
end

#common_operation(options, disk_type) ⇒ Object



354
355
356
357
358
359
360
# File 'lib/chef/knife/cloud/google_service.rb', line 354

def common_operation(options, disk_type)
  disk = Google::Apis::ComputeV1::AttachedDisk.new
  params = Google::Apis::ComputeV1::AttachedDiskInitializeParams.new
  disk.auto_delete = options[:boot_disk_autodelete]
  params.disk_type = disk_type_url_for(disk_type)
  [disk, params]
end

#connectionObject



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/chef/knife/cloud/google_service.rb', line 110

def connection
  return @connection unless @connection.nil?

  @connection = Google::Apis::ComputeV1::ComputeService.new
  @connection.authorization = authorization
  @connection.client_options = Google::Apis::ClientOptions.new.tap do |opts|
    opts.application_name    = "knife-google"
    opts.application_version = Knife::Google::VERSION
  end

  @connection
end

#create_disk(name, size, type, source_image = nil) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/chef/knife/cloud/google_service.rb', line 168

def create_disk(name, size, type, source_image = nil)
  disk = Google::Apis::ComputeV1::Disk.new
  disk.name    = name
  disk.size_gb = size
  disk.type    = disk_type_url_for(type)

  ui.msg("Creating a #{size} GB disk named #{name}...")

  wait_for_operation(connection.insert_disk(project, zone, disk, source_image: source_image))

  ui.msg("Waiting for disk to be ready...")

  wait_for_status("READY") { connection.get_disk(project, zone, name) }

  ui.msg("Disk created successfully.")
end

#create_server(options = {}) ⇒ Object



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/chef/knife/cloud/google_service.rb', line 132

def create_server(options = {})
  validate_server_create_options!(options)

  ui.msg("Creating instance...")

  instance_object = instance_object_for(options)
  wait_for_operation(connection.insert_instance(project, zone, instance_object))
  wait_for_status("RUNNING") { get_server(options[:name]) }

  ui.msg("Instance created!")

  get_server(options[:name])
end

#delete_disk(name) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/chef/knife/cloud/google_service.rb', line 185

def delete_disk(name)
  begin
    connection.get_disk(project, zone, name)
  rescue Google::Apis::ClientError
    ui.warn("Unable to locate disk #{name} in project #{project}, zone #{zone}")
    return
  end

  ui.confirm("Do you really want to delete disk #{name}")

  ui.msg("Deleting disk #{name}...")
  wait_for_operation(connection.delete_disk(project, zone, name))
  ui.msg("Disk #{name} deleted successfully.")
end

#delete_server(instance_name) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/chef/knife/cloud/google_service.rb', line 146

def delete_server(instance_name)
  begin
    instance = get_server(instance_name)
  rescue Google::Apis::ClientError
    ui.warn("Unable to locate instance #{instance_name} in project #{project}, zone #{zone}")
    return
  end

  server_summary(instance)
  ui.confirm("Do you really want to delete this instance")

  ui.msg("Deleting instance #{instance_name}...")

  wait_for_operation(connection.delete_instance(project, zone, instance_name))

  ui.msg("Instance #{instance_name} deleted successfully.")
end

#disk_type_url_for(type) ⇒ Object



559
560
561
# File 'lib/chef/knife/cloud/google_service.rb', line 559

def disk_type_url_for(type)
  "zones/#{zone}/diskTypes/#{type}"
end

#get_server(instance_name) ⇒ Object



164
165
166
# File 'lib/chef/knife/cloud/google_service.rb', line 164

def get_server(instance_name)
  connection.get_instance(project, zone, instance_name)
end

#image_alias_url(image_alias) ⇒ Object



407
408
409
410
411
412
413
414
415
416
417
418
419
420
# File 'lib/chef/knife/cloud/google_service.rb', line 407

def image_alias_url(image_alias)
  return unless IMAGE_ALIAS_MAP.key?(image_alias)

  image_project = IMAGE_ALIAS_MAP[image_alias][:project]
  image_prefix  = IMAGE_ALIAS_MAP[image_alias][:prefix]

  latest_image = connection.list_images(image_project).items
    .select { |image| image.name.start_with?(image_prefix) }
    .max_by(&:name)

  return if latest_image.nil?

  latest_image.self_link
end

#image_exist?(image_project, image_name) ⇒ Boolean

Returns:

  • (Boolean)


273
274
275
# File 'lib/chef/knife/cloud/google_service.rb', line 273

def image_exist?(image_project, image_name)
  check_api_call { connection.get_image(image_project, image_name) }
end

#image_search_for(image, image_project) ⇒ Object



370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/chef/knife/cloud/google_service.rb', line 370

def image_search_for(image, image_project)
  # if the user provided an image_project, assume they want it, no questions asked
  unless image_project.nil?
    ui.msg("Searching project #{image_project} for image #{image}")
    return image_url_for(image_project, image)
  end

  # no image project has been provided. Check to see if the image is a known alias.
  alias_url = image_alias_url(image)
  unless alias_url.nil?
    ui.msg("image #{image} is a known alias - using image URL: #{alias_url}")
    return alias_url
  end

  # Doesn't match an alias. Let's check the user's project for the image.
  url = image_url_for(project, image)
  unless url.nil?
    ui.msg("Located image #{image} in project #{project} - using image URL: #{url}")
    return url
  end

  # Image not found in user's project. Is there a public project this image might exist in?
  public_project = public_project_for_image(image)
  if public_project
    ui.msg("Searching public image project #{public_project} for image #{image}")
    return image_url_for(public_project, image)
  end

  # No image in user's project or public project, so it doesn't exist.
  ui.error("Image search failed for image #{image} - no suitable image located")
  nil
end

#image_url_for(image_project, image_name) ⇒ Object



403
404
405
# File 'lib/chef/knife/cloud/google_service.rb', line 403

def image_url_for(image_project, image_name)
  return "projects/#{image_project}/global/images/#{image_name}" if image_exist?(image_project, image_name)
end

#instance_access_configs_for(public_ip) ⇒ Object



454
455
456
457
458
459
460
461
462
463
# File 'lib/chef/knife/cloud/google_service.rb', line 454

def instance_access_configs_for(public_ip)
  return [] if public_ip.nil? || public_ip.match(/none/i)

  access_config = Google::Apis::ComputeV1::AccessConfig.new
  access_config.name = "External NAT"
  access_config.type = "ONE_TO_ONE_NAT"
  access_config.nat_ip = public_ip if valid_ip_address?(public_ip)

  Array(access_config)
end

#instance_boot_disk_for(options) ⇒ Object



333
334
335
336
337
338
339
340
341
342
# File 'lib/chef/knife/cloud/google_service.rb', line 333

def instance_boot_disk_for(options)
  disk, params = common_operation(options, boot_disk_type_for(options))
  disk.boot           = true
  params.disk_name    = boot_disk_name_for(options)
  params.disk_size_gb = options[:boot_disk_size]
  params.source_image = boot_disk_source_image(options[:image], options[:image_project])

  disk.initialize_params = params
  disk
end

#instance_disks_for(options) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/chef/knife/cloud/google_service.rb', line 315

def instance_disks_for(options)
  disks = []
  disks << instance_boot_disk_for(options)
  options[:number_of_local_ssd].to_i.times { disks << adding_local_ssd(options) } if options[:local_ssd]
  options[:additional_disks].each do |disk_name|
    begin
      disk = connection.get_disk(project, zone, disk_name)
    rescue Google::Apis::ClientError => e
      ui.error("Unable to attach disk #{disk_name} to the instance: #{e.message}")
      raise
    end

    disks << Google::Apis::ComputeV1::AttachedDisk.new.tap { |x| x.source = disk.self_link }
  end

  disks
end

#instance_metadata_for(metadata) ⇒ Object



430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/chef/knife/cloud/google_service.rb', line 430

def ()
  return if .nil? || .empty?

   = Google::Apis::ComputeV1::Metadata.new
  .items = .each_with_object([]) do |(k, v), memo|
           = Google::Apis::ComputeV1::Metadata::Item.new
    .key   = k
    .value = v

    memo << 
  end

  
end

#instance_network_interfaces_for(options) ⇒ Object



445
446
447
448
449
450
451
452
# File 'lib/chef/knife/cloud/google_service.rb', line 445

def instance_network_interfaces_for(options)
  interface = Google::Apis::ComputeV1::NetworkInterface.new
  interface.network = network_url_for(options[:network])
  interface.subnetwork = subnet_url_for(options[:subnet]) if options[:subnet]
  interface.access_configs = instance_access_configs_for(options[:public_ip])

  Array(interface)
end

#instance_object_for(options) ⇒ Object



300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/chef/knife/cloud/google_service.rb', line 300

def instance_object_for(options)
  inst_obj                    = Google::Apis::ComputeV1::Instance.new
  inst_obj.name               = options[:name]
  inst_obj.can_ip_forward     = options[:can_ip_forward]
  inst_obj.disks              = instance_disks_for(options)
  inst_obj.machine_type       = machine_type_url_for(options[:machine_type])
  inst_obj.           = (options[:metadata])
  inst_obj.network_interfaces = instance_network_interfaces_for(options)
  inst_obj.scheduling         = instance_scheduling_for(options)
  inst_obj.service_accounts   = instance_service_accounts_for(options) unless instance_service_accounts_for(options).nil?
  inst_obj.tags               = instance_tags_for(options[:tags])

  inst_obj
end

#instance_scheduling_for(options) ⇒ Object



473
474
475
476
477
478
479
480
# File 'lib/chef/knife/cloud/google_service.rb', line 473

def instance_scheduling_for(options)
  scheduling = Google::Apis::ComputeV1::Scheduling.new
  scheduling.automatic_restart   = options[:auto_restart].to_s
  scheduling.on_host_maintenance = migrate_setting_for(options[:auto_migrate])
  scheduling.preemptible         = options[:preemptible].to_s

  scheduling
end

#instance_service_accounts_for(options) ⇒ Object



486
487
488
489
490
491
492
493
494
# File 'lib/chef/knife/cloud/google_service.rb', line 486

def instance_service_accounts_for(options)
  return if options[:service_account_scopes].nil? || options[:service_account_scopes].empty?

   = Google::Apis::ComputeV1::ServiceAccount.new
  .email  = options[:service_account_name]
  .scopes = options[:service_account_scopes].map { |scope| (scope) }

  Array()
end

#instance_tags_for(tags) ⇒ Object



506
507
508
509
510
511
512
513
# File 'lib/chef/knife/cloud/google_service.rb', line 506

def instance_tags_for(tags)
  return if tags.nil? || tags.empty?

  tag_obj = Google::Apis::ComputeV1::Tags.new
  tag_obj.items = tags

  tag_obj
end

#list_disksObject



226
227
228
# File 'lib/chef/knife/cloud/google_service.rb', line 226

def list_disks
  paginated_results(:list_disks, :items, project, zone) || []
end

#list_imagesObject

Retrieves the list of custom images and public images. Custom images are images you create that belong to your project.



222
223
224
# File 'lib/chef/knife/cloud/google_service.rb', line 222

def list_images
  available_projects.map { |project| paginated_results(:list_images, :items, project) || [] }.flatten
end

#list_project_quotasObject



234
235
236
# File 'lib/chef/knife/cloud/google_service.rb', line 234

def list_project_quotas
  connection.get_project(project).quotas || []
end

#list_regionsObject



230
231
232
# File 'lib/chef/knife/cloud/google_service.rb', line 230

def list_regions
  paginated_results(:list_regions, :items, project) || []
end

#list_serversObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/chef/knife/cloud/google_service.rb', line 200

def list_servers
  instances = paginated_results(:list_instances, :items, project, zone)
  return [] if instances.nil?

  instances.each_with_object([]) do |instance, memo|
    memo << OpenStruct.new(
      name:         instance.name,
      status:       instance.status,
      machine_type: machine_type_for(instance),
      network:      network_for(instance),
      private_ip:   private_ip_for(instance),
      public_ip:    public_ip_for(instance)
    )
  end
end

#list_zonesObject



216
217
218
# File 'lib/chef/knife/cloud/google_service.rb', line 216

def list_zones
  paginated_results(:list_zones, :items, project) || []
end

#machine_type_for(instance) ⇒ Object



521
522
523
# File 'lib/chef/knife/cloud/google_service.rb', line 521

def machine_type_for(instance)
  instance.machine_type.split("/").last
end

#machine_type_url_for(machine_type) ⇒ Object



426
427
428
# File 'lib/chef/knife/cloud/google_service.rb', line 426

def machine_type_url_for(machine_type)
  "zones/#{zone}/machineTypes/#{machine_type}"
end

#migrate_setting_for(auto_migrate) ⇒ Object



482
483
484
# File 'lib/chef/knife/cloud/google_service.rb', line 482

def migrate_setting_for(auto_migrate)
  auto_migrate ? "MIGRATE" : "TERMINATE"
end

#network_for(instance) ⇒ Object



515
516
517
518
519
# File 'lib/chef/knife/cloud/google_service.rb', line 515

def network_for(instance)
  instance.network_interfaces.first.network.split("/").last
rescue NoMethodError
  "unknown"
end

#network_url_for(network) ⇒ Object



465
466
467
# File 'lib/chef/knife/cloud/google_service.rb', line 465

def network_url_for(network)
  "projects/#{project}/global/networks/#{network}"
end

#operation_errors(operation_name) ⇒ Object



641
642
643
644
645
646
# File 'lib/chef/knife/cloud/google_service.rb', line 641

def operation_errors(operation_name)
  operation = zone_operation(operation_name)
  return [] if operation.error.nil?

  operation.error.errors
end

#paginated_results(api_method, items_method, *args) ⇒ Object



563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'lib/chef/knife/cloud/google_service.rb', line 563

def paginated_results(api_method, items_method, *args)
  items      = []
  next_token = nil
  loop_num   = 0

  loop do
    loop_num += 1

    response       = connection.send(api_method.to_sym, *args, max_results: max_page_size, page_token: next_token)
    response_items = response.send(items_method.to_sym)

    break if response_items.nil?

    items += response_items

    next_token = response.next_page_token
    break if next_token.nil?

    if loop_num >= max_pages
      ui.warn("Max pages (#{max_pages}) reached, but more results exist - truncating results...")
      break
    end
  end

  items
end

#public_project_for_image(image) ⇒ Object



536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'lib/chef/knife/cloud/google_service.rb', line 536

def public_project_for_image(image)
  case image
  when /centos/
    "centos-cloud"
  when /container-vm/
    "google-containers"
  when /coreos/
    "coreos-cloud"
  when /debian/
    "debian-cloud"
  when /opensuse-cloud/
    "opensuse-cloud"
  when /rhel/
    "rhel-cloud"
  when /sles/
    "suse-cloud"
  when /ubuntu/
    "ubuntu-os-cloud"
  when /windows/
    "windows-cloud"
  end
end

#regionObject



296
297
298
# File 'lib/chef/knife/cloud/google_service.rb', line 296

def region
  @region ||= connection.get_zone(project, zone).region.split("/").last
end

#server_summary(server, _columns_with_info = nil) ⇒ Object



525
526
527
528
529
530
531
532
533
534
# File 'lib/chef/knife/cloud/google_service.rb', line 525

def server_summary(server, _columns_with_info = nil)
  msg_pair("Instance Name", server.name)
  msg_pair("Status", server.status)
  msg_pair("Machine Type", machine_type_for(server))
  msg_pair("Project", project)
  msg_pair("Zone", zone)
  msg_pair("Network", network_for(server))
  msg_pair("Private IP", private_ip_for(server))
  msg_pair("Public IP", public_ip_for(server))
end

#service_account_scope_url(scope) ⇒ Object



496
497
498
499
500
# File 'lib/chef/knife/cloud/google_service.rb', line 496

def (scope)
  return scope if scope.start_with?("https://www.googleapis.com/auth/")

  "https://www.googleapis.com/auth/#{translate_scope_alias(scope)}"
end

#subnet_url_for(subnet) ⇒ Object



469
470
471
# File 'lib/chef/knife/cloud/google_service.rb', line 469

def subnet_url_for(subnet)
  "projects/#{project}/regions/#{region}/subnetworks/#{subnet}"
end

#translate_scope_alias(scope_alias) ⇒ Object



502
503
504
# File 'lib/chef/knife/cloud/google_service.rb', line 502

def translate_scope_alias(scope_alias)
  SCOPE_ALIAS_MAP.fetch(scope_alias, scope_alias)
end

#valid_ip_address?(ip_address) ⇒ Boolean

Returns:

  • (Boolean)


288
289
290
291
292
293
294
# File 'lib/chef/knife/cloud/google_service.rb', line 288

def valid_ip_address?(ip_address)
  IPAddr.new(ip_address)
rescue IPAddr::InvalidAddressError
  false
else
  true
end

#valid_machine_type?(machine_type) ⇒ Boolean

Returns:

  • (Boolean)


255
256
257
258
259
# File 'lib/chef/knife/cloud/google_service.rb', line 255

def valid_machine_type?(machine_type)
  return false if machine_type.nil?

  check_api_call { connection.get_machine_type(project, zone, machine_type) }
end

#valid_network?(network) ⇒ Boolean

Returns:

  • (Boolean)


261
262
263
264
265
# File 'lib/chef/knife/cloud/google_service.rb', line 261

def valid_network?(network)
  return false if network.nil?

  check_api_call { connection.get_network(project, network) }
end

#valid_public_ip_setting?(public_ip) ⇒ Boolean

Returns:

  • (Boolean)


277
278
279
280
281
282
283
284
285
286
# File 'lib/chef/knife/cloud/google_service.rb', line 277

def valid_public_ip_setting?(public_ip)
  case
  when public_ip.nil? || public_ip.match(/(ephemeral|none)/i)
    true
  when valid_ip_address?(public_ip)
    true
  else
    false
  end
end

#valid_subnet?(subnet) ⇒ Boolean

Returns:

  • (Boolean)


267
268
269
270
271
# File 'lib/chef/knife/cloud/google_service.rb', line 267

def valid_subnet?(subnet)
  return false if subnet.nil?

  check_api_call { connection.get_subnetwork(project, region, subnet) }
end

#validate_server_create_options!(options) ⇒ Object



238
239
240
241
242
243
244
245
# File 'lib/chef/knife/cloud/google_service.rb', line 238

def validate_server_create_options!(options)
  raise "Invalid machine type: #{options[:machine_type]}" unless valid_machine_type?(options[:machine_type])
  raise "Invalid network: #{options[:network]}" unless valid_network?(options[:network])
  raise "Invalid subnet: #{options[:subnet]}" if options[:subnet] && !valid_subnet?(options[:subnet])
  raise "Invalid Public IP setting: #{options[:public_ip]}" unless valid_public_ip_setting?(options[:public_ip])
  raise "Invalid image: #{options[:image]} - check your image name, or set an image project if needed" if boot_disk_source_image(options[:image], options[:image_project]).nil?
  raise "Maximum number of local SSDs for an instance should be 8, while #{options[:number_of_local_ssd]} is requested." if options[:number_of_local_ssd].to_i > 8
end

#wait_for_operation(operation) ⇒ Object



622
623
624
625
626
627
628
629
630
631
632
633
634
635
# File 'lib/chef/knife/cloud/google_service.rb', line 622

def wait_for_operation(operation)
  operation_name = operation.name

  wait_for_status("DONE") { zone_operation(operation_name) }

  errors = operation_errors(operation_name)
  return if errors.empty?

  errors.each do |error|
    ui.error("#{ui.color(error.code, :bold)}: #{error.message}")
  end

  raise "Operation #{operation_name} failed."
end

#wait_for_status(requested_status) ⇒ Object



590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
# File 'lib/chef/knife/cloud/google_service.rb', line 590

def wait_for_status(requested_status)
  last_status = ""

  begin
    Timeout.timeout(wait_time) do
      loop do
        item = yield
        current_status = item.status

        if current_status == requested_status
          print "\n"
          break
        end

        if last_status == current_status
          print "."
        else
          last_status = current_status
          print "\n"
          print "Current status: #{current_status}."
        end

        sleep refresh_rate
      end
    end
  rescue Timeout::Error
    ui.msg("")
    ui.error("Request did not complete in #{wait_time} seconds. Check the Google Cloud Console for more info.")
    exit 1
  end
end

#zone_operation(operation_name) ⇒ Object



637
638
639
# File 'lib/chef/knife/cloud/google_service.rb', line 637

def zone_operation(operation_name)
  connection.get_zone_operation(project, zone, operation_name)
end