Skip to content

Commit

Permalink
Merge branch 'master' into feature/meta-data
Browse files Browse the repository at this point in the history
  • Loading branch information
dldinternet committed Aug 14, 2017
2 parents a76ea82 + 61f5cd4 commit c97efb6
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 250 deletions.
56 changes: 37 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ which to run your test-kitchen instances, create one, noting the

### Authentication and Authorization

The [underlying API](https://github.com/google/google-api-ruby-client) this plugin uses relies on the
The [underlying API](https://github.com/google/google-api-ruby-client) this plugin uses relies on the
[Google Auth Library](https://github.com/google/google-auth-library-ruby) to handle authentication to the
Google Cloud API. The auth library expects that there is a JSON credentials file located at:

Expand All @@ -39,7 +39,7 @@ If you already have a file you'd like to use that is in a different location, se
### SSH Keys

In order to bootstrap Linux nodes, you will first need to ensure your SSH
keys are set up correctly. Ensure your SSH public key is properly entered
keys are set up correctly. Ensure your SSH public key is properly entered
into your project's Metadata tab in the GCP Console. GCE will add your key
to the appropriate user's `~/.ssh/authorized_keys` file when Chef first
connects to perform the bootstrap process.
Expand Down Expand Up @@ -113,26 +113,38 @@ Note that this parameter requires the "Project ID", not the "Project Name."

Example: "funky-penguin-12345"

### `image_project`

The project ID of the GCP project to search for the configured image or image
family. This must be specified to find either public images or your own images
that exist in another project.

Example: "ubuntu-os-cloud"

### `image_family`

The family of the image to initialize your boot disk from, the latest
non-deprecated image will be used.

Note that this parameter will be ignored if `image_name` is also specified.

Example: "ubuntu-1604-lts"

### `image_name`

**Required**. The name of the disk image to use as the source image for
the boot disk. Example: `centos-6-v20160219`
The name of the disk image to use as the source image for the boot disk.

The GCP project specified with the `project` configuration parameter will
be searched first. If the image cannot be found and it looks like a common
public image, the appropriate public project will be searched.
Example: `centos-7-v20170124`

You can override the project in which to search for the image with the
`image_project` parameter.
This parameter will override `image_family` if they are both specified.

Additionally, you can supply an image alias supported by the `gcloud compute instances create`
command and kitchen-google will find the latest version of that image to use.
For a full list of aliases, see the output of `gcloud compute instances create --help`.
If `image_project` is not specified, only the GCP project specified in `project`
will be searched.

### `zone`

**Required if `region` is left blank.** The name of the GCE zone in which to
launch your instances.
launch your instances.

Example: `us-east1-b`

Expand Down Expand Up @@ -166,7 +178,7 @@ to a host in the event of host maintenance. Default: `false`
Size, in gigabytes, of boot disk. Default: `10`.

Some images, such as windows images, have a larger source image size
and require the disk_size to be the same size or larger than the source.
and require the disk_size to be the same size or larger than the source.
An error message will be displayed to you indicating this requirement
if necessary.

Expand Down Expand Up @@ -194,8 +206,8 @@ GCE subnetwork that instance will be attached to. Only applies to custom network
### `preemptible`

If set to `true`, GCE instance will be brought up as a [preemptible](https://cloud.google.com/compute/docs/instances/preemptible) virtual machine,
that runs at a much lower price than normal instances. However, Compute
Engine might terminate (preempt) these instances if it requires access
that runs at a much lower price than normal instances. However, Compute
Engine might terminate (preempt) these instances if it requires access
to those resources for other tasks; default: `false`

### `service_account_name`
Expand Down Expand Up @@ -285,12 +297,18 @@ transport:
username: chefuser
platforms:
- name: centos
- name: centos-7
driver:
image_project: centos-cloud
image_name: centos-7-v20170124
- name: ubuntu-16.04
driver:
image_name: centos-6-v20160219
image_project: ubuntu-os-cloud
image_family: ubuntu-1604-lts
- name: windows
driver:
image_name: windows-server-2012-r2-dc-v20160112
image_project: windows-cloud
image_name: windows-server-2012-r2-dc-v20170117
disk_size: 50
suites:
Expand Down
119 changes: 21 additions & 98 deletions lib/kitchen/driver/gce.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,32 +53,10 @@ class Gce < Kitchen::Driver::Base
"userinfo-email" => "userinfo.email",
}

IMAGE_ALIAS_MAP = {
"centos-6" => { project: "centos-cloud", prefix: "centos-6" },
"centos-7" => { project: "centos-cloud", prefix: "centos-7" },
"container-vm" => { project: "google-containers", prefix: "container-vm" },
"coreos" => { project: "coreos-cloud", prefix: "coreos-stable" },
"debian-7" => { project: "debian-cloud", prefix: "debian-7-wheezy" },
"debian-7-backports" => { project: "debian-cloud", prefix: "backports-debian-7-wheezy" },
"debian-8" => { project: "debian-cloud", prefix: "debian-8-jessie" },
"opensuse-13" => { project: "opensuse-cloud", prefix: "opensuse-13" },
"rhel-6" => { project: "rhel-cloud", prefix: "rhel-6" },
"rhel-7" => { project: "rhel-cloud", prefix: "rhel-7" },
"sles-11" => { project: "suse-cloud", prefix: "sles-11" },
"sles-12" => { project: "suse-cloud", prefix: "sles-12" },
"ubuntu-12-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1204-precise" },
"ubuntu-14-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1404-trusty" },
"ubuntu-15-04" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1504-vivid" },
"ubuntu-15-10" => { project: "ubuntu-os-cloud", prefix: "ubuntu-1510-wily" },
"windows-2008-r2" => { project: "windows-cloud", prefix: "windows-server-2008-r2" },
"windows-2012-r2" => { project: "windows-cloud", prefix: "windows-server-2012-r2" },
}

kitchen_driver_api_version 2
plugin_version Kitchen::Driver::GCE_VERSION

required_config :project
required_config :image_name

default_config :region, nil
default_config :zone, nil
Expand All @@ -96,6 +74,8 @@ class Gce < Kitchen::Driver::Base
default_config :preemptible, false
default_config :auto_restart, false
default_config :auto_migrate, false
default_config :image_family, nil
default_config :image_name, nil
default_config :image_project, nil
default_config :email, nil
default_config :use_private_ip, false
Expand Down Expand Up @@ -167,12 +147,15 @@ def validate!
raise "Region #{config[:region]} is not a valid region" if config[:region] && !valid_region?
raise "Machine type #{config[:machine_type]} is not valid" unless valid_machine_type?
raise "Disk type #{config[:disk_type]} is not valid" unless valid_disk_type?
raise "Either image family or name must be specified" unless config[:image_family] || config[:image_name]
raise "Disk image #{config[:image_name]} is not valid - check your image name and image project" if boot_disk_source_image.nil?
raise "Network #{config[:network]} is not valid" unless valid_network?
raise "Subnet #{config[:subnet]} is not valid" if config[:subnet] && !valid_subnet?
raise "Email address of GCE user is not set" if winrm_transport? && config[:email].nil?

warn("Both zone and region specified - region will be ignored.") if config[:zone] && config[:region]
warn("Both image family and name specified - image family will be ignored") if config[:image_family] && config[:image_name]
warn("Image project not specified - searching current project only") unless config[:image_project]
warn("Auto-migrate disabled for preemptible instance") if preemptible? && config[:auto_migrate]
warn("Auto-restart disabled for preemptible instance") if preemptible? && config[:auto_restart]
end
Expand Down Expand Up @@ -200,7 +183,7 @@ def authorization
end

def winrm_transport?
instance.transport.name.casecmp("winrm").zero?
instance.transport.name.casecmp("winrm") == 0
end

def update_windows_password(server_name)
Expand Down Expand Up @@ -264,7 +247,7 @@ def valid_disk_type?
check_api_call { connection.get_disk_type(project, zone, config[:disk_type]) }
end

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

Expand All @@ -276,6 +259,14 @@ def project
config[:project]
end

def image_name
@image_name ||= config[:image_name] || image_name_for_family(config[:image_family])
end

def image_project
config[:image_project].nil? ? project : config[:image_project]
end

def region
config[:region].nil? ? region_for_zone : config[:region]
end
Expand Down Expand Up @@ -367,84 +358,16 @@ def disk_type_url_for(type)
end

def boot_disk_source_image
@boot_disk_source ||= disk_image_url
@boot_disk_source ||= image_url
end

def disk_image_url
# if the user provided an image_project, assume they want it, no questions asked
unless config[:image_project].nil?
debug("Searching project #{config[:image_project]} for image #{config[:image_name]}")
return image_url_for(config[:image_project], config[:image_name])
end

# No image project has been provided. Check to see if the image is a known alias.
alias_url = image_alias_url
unless alias_url.nil?
debug("Image #{config[:image_name]} 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, config[:image_name])
unless url.nil?
debug("Located image #{config[:image_name]} 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(config[:image_name])
if public_project
debug("Searching public image project #{public_project} for image #{config[:image_name]}")
return image_url_for(public_project, config[:image_name])
end

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

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

def image_alias_url
image_alias = config[:image_name]
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) }
.sort_by(&:name)
.last

return if latest_image.nil?

latest_image.self_link
end

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
def image_name_for_family(image_family)
image = connection.get_image_from_family(image_project, image_family)
image.name
end

def machine_type_url
Expand Down
2 changes: 1 addition & 1 deletion lib/kitchen/driver/gce_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@

module Kitchen
module Driver
GCE_VERSION = "1.1.0".freeze
GCE_VERSION = "1.2.0".freeze
end
end
Loading

0 comments on commit c97efb6

Please sign in to comment.