tcr-vagrant-google 0.1.4
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.
- data/.gitignore +17 -0
- data/CHANGELOG.md +20 -0
- data/CONTRIB.md +64 -0
- data/Gemfile +24 -0
- data/LICENSE +201 -0
- data/README.md +237 -0
- data/Rakefile +35 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/google.box +0 -0
- data/lib/vagrant-google.rb +31 -0
- data/lib/vagrant-google/action.rb +140 -0
- data/lib/vagrant-google/action/connect_google.rb +49 -0
- data/lib/vagrant-google/action/is_created.rb +31 -0
- data/lib/vagrant-google/action/message_already_created.rb +29 -0
- data/lib/vagrant-google/action/message_not_created.rb +29 -0
- data/lib/vagrant-google/action/message_will_not_destroy.rb +29 -0
- data/lib/vagrant-google/action/read_ssh_info.rb +54 -0
- data/lib/vagrant-google/action/read_state.rb +59 -0
- data/lib/vagrant-google/action/run_instance.rb +145 -0
- data/lib/vagrant-google/action/sync_folders.rb +87 -0
- data/lib/vagrant-google/action/terminate_instance.rb +40 -0
- data/lib/vagrant-google/action/timed_provision.rb +34 -0
- data/lib/vagrant-google/action/warn_networks.rb +32 -0
- data/lib/vagrant-google/config.rb +265 -0
- data/lib/vagrant-google/errors.rb +32 -0
- data/lib/vagrant-google/plugin.rb +86 -0
- data/lib/vagrant-google/provider.rb +63 -0
- data/lib/vagrant-google/util/timer.rb +30 -0
- data/lib/vagrant-google/version.rb +18 -0
- data/locales/en.yml +105 -0
- data/spec/vagrant-google/config_spec.rb +202 -0
- data/tcr-vagrant-google.gemspec +75 -0
- metadata +173 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "log4r"
|
15
|
+
|
16
|
+
module VagrantPlugins
|
17
|
+
module Google
|
18
|
+
module Action
|
19
|
+
# This action reads the state of the machine and puts it in the
|
20
|
+
# `:machine_state_id` key in the environment.
|
21
|
+
class ReadState
|
22
|
+
def initialize(app, env)
|
23
|
+
@app = app
|
24
|
+
@logger = Log4r::Logger.new("vagrant_google::action::read_state")
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(env)
|
28
|
+
env[:machine_state_id] = read_state(env[:google_compute], env[:machine])
|
29
|
+
|
30
|
+
@app.call(env)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_state(google, machine)
|
34
|
+
return :not_created if machine.id.nil?
|
35
|
+
|
36
|
+
# Find the machine
|
37
|
+
zone = machine.provider_config.zone
|
38
|
+
# TODO(erjohnso): not sure why this is necessary, 'server' should be nil
|
39
|
+
begin
|
40
|
+
server = google.servers.get(machine.id, zone)
|
41
|
+
rescue Exception => e
|
42
|
+
@logger.info("TODO: this shouldn't be happening. Call should return nil")
|
43
|
+
@logger.info(e.message)
|
44
|
+
server = nil
|
45
|
+
end
|
46
|
+
if server.nil? || [:"shutting-down", :terminated].include?(server.state.to_sym)
|
47
|
+
# The machine can't be found
|
48
|
+
@logger.info("Machine '#{zone}:#{machine.id}' not found or terminated, assuming it got destroyed.")
|
49
|
+
machine.id = nil
|
50
|
+
return :not_created
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the state
|
54
|
+
return server.state.to_sym
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "log4r"
|
15
|
+
require 'vagrant/util/retryable'
|
16
|
+
require 'vagrant-google/util/timer'
|
17
|
+
|
18
|
+
module VagrantPlugins
|
19
|
+
module Google
|
20
|
+
module Action
|
21
|
+
# This runs the configured instance.
|
22
|
+
class RunInstance
|
23
|
+
include Vagrant::Util::Retryable
|
24
|
+
|
25
|
+
def initialize(app, env)
|
26
|
+
@app = app
|
27
|
+
@logger = Log4r::Logger.new("vagrant_google::action::run_instance")
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
# Initialize metrics if they haven't been
|
32
|
+
env[:metrics] ||= {}
|
33
|
+
|
34
|
+
# Get the zone we're going to booting up in
|
35
|
+
zone = env[:machine].provider_config.zone
|
36
|
+
|
37
|
+
# Get the configs
|
38
|
+
zone_config = env[:machine].provider_config.get_zone_config(zone)
|
39
|
+
image = zone_config.image
|
40
|
+
name = zone_config.name
|
41
|
+
machine_type = zone_config.machine_type
|
42
|
+
disk_size = zone_config.disk_size
|
43
|
+
network = zone_config.network
|
44
|
+
metadata = zone_config.metadata
|
45
|
+
tags = zone_config.tags
|
46
|
+
service_accounts = zone_config.service_accounts
|
47
|
+
|
48
|
+
# Launch!
|
49
|
+
env[:ui].info(I18n.t("vagrant_google.launching_instance"))
|
50
|
+
env[:ui].info(" -- Name: #{name}")
|
51
|
+
env[:ui].info(" -- Type: #{machine_type}")
|
52
|
+
env[:ui].info(" -- Disk size: #{disk_size} GB")
|
53
|
+
env[:ui].info(" -- Image: #{image}")
|
54
|
+
env[:ui].info(" -- Zone: #{zone}") if zone
|
55
|
+
env[:ui].info(" -- Network: #{network}") if network
|
56
|
+
env[:ui].info(" -- Metadata: '#{metadata}'")
|
57
|
+
env[:ui].info(" -- Tags: '#{tags}'")
|
58
|
+
env[:ui].info(" -- Scopes: #{service_accounts}")
|
59
|
+
begin
|
60
|
+
request_start_time = Time.now().to_i
|
61
|
+
disk = env[:google_compute].disks.create(
|
62
|
+
name: name,
|
63
|
+
size_gb: disk_size,
|
64
|
+
zone_name: zone,
|
65
|
+
source_image: image
|
66
|
+
)
|
67
|
+
disk.wait_for { disk.ready? }
|
68
|
+
|
69
|
+
defaults = {
|
70
|
+
:name => name,
|
71
|
+
:zone_name => zone,
|
72
|
+
:machine_type => machine_type,
|
73
|
+
:disk_size => disk_size,
|
74
|
+
:image => image,
|
75
|
+
:network => network,
|
76
|
+
:metadata => metadata,
|
77
|
+
:tags => tags,
|
78
|
+
# Second arg to get_as_boot_disk is 'autodelete_disk', defaulting
|
79
|
+
# to true
|
80
|
+
:disks => [disk.get_as_boot_disk(true, true)],
|
81
|
+
:service_accounts => service_accounts,
|
82
|
+
}
|
83
|
+
server = env[:google_compute].servers.create(defaults)
|
84
|
+
@logger.info("Machine '#{zone}:#{name}' created.")
|
85
|
+
rescue Fog::Compute::Google::NotFound => e
|
86
|
+
raise
|
87
|
+
rescue Fog::Compute::Google::Error => e
|
88
|
+
raise Errors::FogError, :message => e.message
|
89
|
+
end
|
90
|
+
|
91
|
+
# Immediately save the name since the instance has been created
|
92
|
+
env[:machine].id = server.name
|
93
|
+
server.reload
|
94
|
+
|
95
|
+
env[:ui].info(I18n.t("vagrant_google.waiting_for_ready"))
|
96
|
+
begin
|
97
|
+
server.wait_for { ready? }
|
98
|
+
env[:metrics]["instance_ready_time"] = Time.now().to_i - request_start_time
|
99
|
+
@logger.info("Time for instance ready: #{env[:metrics]["instance_ready_time"]}")
|
100
|
+
env[:ui].info(I18n.t("vagrant_google.ready"))
|
101
|
+
rescue
|
102
|
+
env[:interrupted] = true
|
103
|
+
end
|
104
|
+
|
105
|
+
if !env[:terminated]
|
106
|
+
env[:metrics]["instance_ssh_time"] = Util::Timer.time do
|
107
|
+
# Wait for SSH to be ready.
|
108
|
+
env[:ui].info(I18n.t("vagrant_google.waiting_for_ssh"))
|
109
|
+
while true
|
110
|
+
# If we're interrupted just back out
|
111
|
+
break if env[:interrupted]
|
112
|
+
break if env[:machine].communicate.ready?
|
113
|
+
sleep 2
|
114
|
+
end
|
115
|
+
end
|
116
|
+
@logger.info("Time for SSH ready: #{env[:metrics]["instance_ssh_time"]}")
|
117
|
+
env[:ui].info(I18n.t("vagrant_google.ready_ssh"))
|
118
|
+
end
|
119
|
+
|
120
|
+
# Terminate the instance if we were interrupted
|
121
|
+
terminate(env) if env[:interrupted]
|
122
|
+
|
123
|
+
@app.call(env)
|
124
|
+
end
|
125
|
+
|
126
|
+
def recover(env)
|
127
|
+
return if env["vagrant.error"].is_a?(Vagrant::Errors::VagrantError)
|
128
|
+
|
129
|
+
if env[:machine].provider.state.id != :not_created
|
130
|
+
# Undo the import
|
131
|
+
terminate(env)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def terminate(env)
|
136
|
+
destroy_env = env.dup
|
137
|
+
destroy_env.delete(:interrupted)
|
138
|
+
destroy_env[:config_validate] = false
|
139
|
+
destroy_env[:force_confirm_destroy] = true
|
140
|
+
env[:action_runner].run(Action.action_destroy, destroy_env)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "log4r"
|
15
|
+
require "vagrant/util/subprocess"
|
16
|
+
require "vagrant/util/scoped_hash_override"
|
17
|
+
|
18
|
+
module VagrantPlugins
|
19
|
+
module Google
|
20
|
+
module Action
|
21
|
+
# This middleware uses `rsync` to sync the folders over to the
|
22
|
+
# Google instance.
|
23
|
+
class SyncFolders
|
24
|
+
include Vagrant::Util::ScopedHashOverride
|
25
|
+
|
26
|
+
def initialize(app, env)
|
27
|
+
@app = app
|
28
|
+
@logger = Log4r::Logger.new("vagrant_google::action::sync_folders")
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
@app.call(env)
|
33
|
+
|
34
|
+
ssh_info = env[:machine].ssh_info
|
35
|
+
|
36
|
+
env[:machine].config.vm.synced_folders.each do |id, data|
|
37
|
+
data = scoped_hash_override(data, :google)
|
38
|
+
|
39
|
+
# Ignore disabled shared folders
|
40
|
+
next if data[:disabled]
|
41
|
+
|
42
|
+
hostpath = File.expand_path(data[:hostpath], env[:root_path])
|
43
|
+
guestpath = data[:guestpath]
|
44
|
+
|
45
|
+
# Make sure there is a trailing slash on the host path to
|
46
|
+
# avoid creating an additional directory with rsync
|
47
|
+
hostpath = "#{hostpath}/" if hostpath !~ /\/$/
|
48
|
+
|
49
|
+
env[:ui].info(I18n.t("vagrant_google.rsync_folder",
|
50
|
+
:hostpath => hostpath,
|
51
|
+
:guestpath => guestpath))
|
52
|
+
|
53
|
+
# Create the guest path
|
54
|
+
env[:machine].communicate.sudo("mkdir -p '#{guestpath}'")
|
55
|
+
env[:machine].communicate.sudo(
|
56
|
+
"chown #{ssh_info[:username]} '#{guestpath}'")
|
57
|
+
|
58
|
+
# patch from https://github.com/tmatilai/vagrant-aws/commit/4a043a96076c332220ec4ec19470c4af5597dd51
|
59
|
+
def ssh_key_options(ssh_info)
|
60
|
+
# Ensure that `private_key_path` is an Array (for Vagrant < 1.4)
|
61
|
+
Array(ssh_info[:private_key_path]).map { |path| "-i '#{path}' " }.join
|
62
|
+
end
|
63
|
+
|
64
|
+
#collect rsync excludes specified :rsync__excludes=>['path1',...] in synced_folder options
|
65
|
+
excludes = ['.vagrant/', *Array(data[:rsync__excludes])]
|
66
|
+
|
67
|
+
# Rsync over to the guest path using the SSH info
|
68
|
+
command = [
|
69
|
+
"rsync", "--verbose", "--archive", "-z",
|
70
|
+
*excludes.map{|e|['--exclude', e]}.flatten,
|
71
|
+
"-e", "ssh -p #{ssh_info[:port]} -o StrictHostKeyChecking=no #{ssh_key_options(ssh_info)}",
|
72
|
+
hostpath,
|
73
|
+
"#{ssh_info[:username]}@#{ssh_info[:host]}:#{guestpath}"]
|
74
|
+
|
75
|
+
r = Vagrant::Util::Subprocess.execute(*command)
|
76
|
+
if r.exit_code != 0
|
77
|
+
raise Errors::RsyncError,
|
78
|
+
:guestpath => guestpath,
|
79
|
+
:hostpath => hostpath,
|
80
|
+
:stderr => r.stderr
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "log4r"
|
15
|
+
|
16
|
+
module VagrantPlugins
|
17
|
+
module Google
|
18
|
+
module Action
|
19
|
+
# This terminates the running instance.
|
20
|
+
class TerminateInstance
|
21
|
+
def initialize(app, env)
|
22
|
+
@app = app
|
23
|
+
@logger = Log4r::Logger.new("vagrant_google::action::terminate_instance")
|
24
|
+
end
|
25
|
+
|
26
|
+
def call(env)
|
27
|
+
server = env[:google_compute].servers.get(env[:machine].id, env[:machine].provider_config.zone)
|
28
|
+
|
29
|
+
# Destroy the server and remove the tracking ID
|
30
|
+
env[:ui].info(I18n.t("vagrant_google.terminating"))
|
31
|
+
server.destroy if not server.nil?
|
32
|
+
server.wait_for { not ready? }
|
33
|
+
env[:machine].id = nil
|
34
|
+
|
35
|
+
@app.call(env)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "vagrant-google/util/timer"
|
15
|
+
|
16
|
+
module VagrantPlugins
|
17
|
+
module Google
|
18
|
+
module Action
|
19
|
+
# This is the same as the builtin provision except it times the
|
20
|
+
# provisioner runs.
|
21
|
+
class TimedProvision < Vagrant::Action::Builtin::Provision
|
22
|
+
def run_provisioner(env, name, p)
|
23
|
+
timer = Util::Timer.time do
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
env[:metrics] ||= {}
|
28
|
+
env[:metrics]["provisioner_times"] ||= []
|
29
|
+
env[:metrics]["provisioner_times"] << [name, timer]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
module VagrantPlugins
|
15
|
+
module Google
|
16
|
+
module Action
|
17
|
+
class WarnNetworks
|
18
|
+
def initialize(app, env)
|
19
|
+
@app = app
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(env)
|
23
|
+
if env[:machine].config.vm.networks.length > 0
|
24
|
+
env[:ui].warn(I18n.t("vagrant_google.warn_networks"))
|
25
|
+
end
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,265 @@
|
|
1
|
+
# Copyright 2013 Google Inc. All Rights Reserved.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require "vagrant"
|
15
|
+
|
16
|
+
module VagrantPlugins
|
17
|
+
module Google
|
18
|
+
class Config < Vagrant.plugin("2", :config)
|
19
|
+
# The Service Account Client ID Email address
|
20
|
+
#
|
21
|
+
# @return [String]
|
22
|
+
attr_accessor :google_client_email
|
23
|
+
|
24
|
+
# The path to the Service Account private key
|
25
|
+
#
|
26
|
+
# @return [String]
|
27
|
+
attr_accessor :google_key_location
|
28
|
+
|
29
|
+
# The Google Cloud Project ID (not name or number)
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
attr_accessor :google_project_id
|
33
|
+
|
34
|
+
# The image name of the instance to use.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
attr_accessor :image
|
38
|
+
|
39
|
+
# The type of machine to launch, such as "n1-standard-1"
|
40
|
+
#
|
41
|
+
# @return [String]
|
42
|
+
attr_accessor :machine_type
|
43
|
+
|
44
|
+
# The size of disk in GB
|
45
|
+
#
|
46
|
+
# @return [Int]
|
47
|
+
attr_accessor :disk_size
|
48
|
+
|
49
|
+
# The user metadata string
|
50
|
+
#
|
51
|
+
# @return [Hash<String, String>]
|
52
|
+
attr_accessor :metadata
|
53
|
+
|
54
|
+
# The name of the instance
|
55
|
+
#
|
56
|
+
# @return [String]
|
57
|
+
attr_accessor :name
|
58
|
+
|
59
|
+
# The name of the network
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
attr_accessor :network
|
63
|
+
|
64
|
+
# Tags to apply to the instance
|
65
|
+
#
|
66
|
+
# @return [Array]
|
67
|
+
attr_accessor :tags
|
68
|
+
|
69
|
+
# The timeout value waiting for instance ready
|
70
|
+
#
|
71
|
+
# @return [Int]
|
72
|
+
attr_accessor :instance_ready_timeout
|
73
|
+
|
74
|
+
# The tags for the machine.
|
75
|
+
# TODO(erjohnso): not supported in fog
|
76
|
+
#
|
77
|
+
# @return [Hash<String, String>]
|
78
|
+
#attr_accessor :tags
|
79
|
+
|
80
|
+
# The zone to launch the instance into. If nil, it will
|
81
|
+
# use the default us-central1-f.
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
attr_accessor :zone
|
85
|
+
|
86
|
+
# The list of access controls for service accounts.
|
87
|
+
#
|
88
|
+
# @return [Array]
|
89
|
+
attr_accessor :service_accounts
|
90
|
+
|
91
|
+
def initialize(zone_specific=false)
|
92
|
+
@google_client_email = UNSET_VALUE
|
93
|
+
@google_key_location = UNSET_VALUE
|
94
|
+
@google_project_id = UNSET_VALUE
|
95
|
+
@image = UNSET_VALUE
|
96
|
+
@machine_type = UNSET_VALUE
|
97
|
+
@disk_size = UNSET_VALUE
|
98
|
+
@metadata = {}
|
99
|
+
@name = UNSET_VALUE
|
100
|
+
@network = UNSET_VALUE
|
101
|
+
@tags = []
|
102
|
+
@instance_ready_timeout = UNSET_VALUE
|
103
|
+
@zone = UNSET_VALUE
|
104
|
+
@service_accounts = UNSET_VALUE
|
105
|
+
|
106
|
+
# Internal state (prefix with __ so they aren't automatically
|
107
|
+
# merged)
|
108
|
+
@__compiled_zone_configs = {}
|
109
|
+
@__finalized = false
|
110
|
+
@__zone_config = {}
|
111
|
+
@__zone_specific = zone_specific
|
112
|
+
end
|
113
|
+
|
114
|
+
# Allows zone-specific overrides of any of the settings on this
|
115
|
+
# configuration object. This allows the user to override things like
|
116
|
+
# image and machine type name for zones. Example:
|
117
|
+
#
|
118
|
+
# google.zone_config "us-central1-f" do |zone|
|
119
|
+
# zone.image = "debian-7-wheezy-v20140926"
|
120
|
+
# zone.machine_type = "n1-standard-4"
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# @param [String] zone The zone name to configure.
|
124
|
+
# @param [Hash] attributes Direct attributes to set on the configuration
|
125
|
+
# as a shortcut instead of specifying a full block.
|
126
|
+
# @yield [config] Yields a new Google configuration.
|
127
|
+
def zone_config(zone, attributes=nil, &block)
|
128
|
+
# Append the block to the list of zone configs for that zone.
|
129
|
+
# We'll evaluate these upon finalization.
|
130
|
+
@__zone_config[zone] ||= []
|
131
|
+
|
132
|
+
# Append a block that sets attributes if we got one
|
133
|
+
if attributes
|
134
|
+
attr_block = lambda do |config|
|
135
|
+
config.set_options(attributes)
|
136
|
+
end
|
137
|
+
|
138
|
+
@__zone_config[zone] << attr_block
|
139
|
+
end
|
140
|
+
|
141
|
+
# Append a block if we got one
|
142
|
+
@__zone_config[zone] << block if block_given?
|
143
|
+
end
|
144
|
+
|
145
|
+
#-------------------------------------------------------------------
|
146
|
+
# Internal methods.
|
147
|
+
#-------------------------------------------------------------------
|
148
|
+
|
149
|
+
def merge(other)
|
150
|
+
super.tap do |result|
|
151
|
+
# Copy over the zone specific flag. "True" is retained if either
|
152
|
+
# has it.
|
153
|
+
new_zone_specific = other.instance_variable_get(:@__zone_specific)
|
154
|
+
result.instance_variable_set(
|
155
|
+
:@__zone_specific, new_zone_specific || @__zone_specific)
|
156
|
+
|
157
|
+
# Go through all the zone configs and prepend ours onto
|
158
|
+
# theirs.
|
159
|
+
new_zone_config = other.instance_variable_get(:@__zone_config)
|
160
|
+
@__zone_config.each do |key, value|
|
161
|
+
new_zone_config[key] ||= []
|
162
|
+
new_zone_config[key] = value + new_zone_config[key]
|
163
|
+
end
|
164
|
+
|
165
|
+
# Set it
|
166
|
+
result.instance_variable_set(:@__zone_config, new_zone_config)
|
167
|
+
|
168
|
+
# Merge in the metadata
|
169
|
+
result.metadata.merge!(self.metadata)
|
170
|
+
result.metadata.merge!(other.metadata)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def finalize!
|
175
|
+
# Try to get access keys from standard Google environment variables; they
|
176
|
+
# will default to nil if the environment variables are not present.
|
177
|
+
@google_client_email = ENV['GOOGLE_CLIENT_EMAIL'] if @google_client_email == UNSET_VALUE
|
178
|
+
@google_key_location = ENV['GOOGLE_KEY_LOCATION'] if @google_key_location == UNSET_VALUE
|
179
|
+
@google_project_id = ENV['GOOGLE_PROJECT_ID'] if @google_project_id == UNSET_VALUE
|
180
|
+
|
181
|
+
# Image must be nil, since we can't default that
|
182
|
+
@image = "debian-7-wheezy-v20140926" if @image == UNSET_VALUE
|
183
|
+
|
184
|
+
# Default instance type is an n1-standard-1
|
185
|
+
@machine_type = "n1-standard-1" if @machine_type == UNSET_VALUE
|
186
|
+
|
187
|
+
# Default disk size is 10 GB
|
188
|
+
@disk_size = 10 if @disk_size == UNSET_VALUE
|
189
|
+
|
190
|
+
# Instance name defaults to a new datetime value (hour granularity)
|
191
|
+
t = Time.now
|
192
|
+
@name = "i-#{t.year}#{t.month.to_s.rjust(2,'0')}#{t.day.to_s.rjust(2,'0')}#{t.hour.to_s.rjust(2,'0')}" if @name == UNSET_VALUE
|
193
|
+
|
194
|
+
# Network defaults to 'default'
|
195
|
+
@network = "default" if @network == UNSET_VALUE
|
196
|
+
|
197
|
+
# Default zone is us-central1-f.
|
198
|
+
@zone = "us-central1-f" if @zone == UNSET_VALUE
|
199
|
+
|
200
|
+
# Default instance_ready_timeout
|
201
|
+
@instance_ready_timeout = 20 if @instance_ready_timeout == UNSET_VALUE
|
202
|
+
|
203
|
+
# Default service_accounts
|
204
|
+
@service_accounts = nil if @service_accounts == UNSET_VALUE
|
205
|
+
|
206
|
+
# Compile our zone specific configurations only within
|
207
|
+
# NON-zone-SPECIFIC configurations.
|
208
|
+
if !@__zone_specific
|
209
|
+
@__zone_config.each do |zone, blocks|
|
210
|
+
config = self.class.new(true).merge(self)
|
211
|
+
|
212
|
+
# Execute the configuration for each block
|
213
|
+
blocks.each { |b| b.call(config) }
|
214
|
+
|
215
|
+
# The zone name of the configuration always equals the
|
216
|
+
# zone config name:
|
217
|
+
config.zone = zone
|
218
|
+
|
219
|
+
# Finalize the configuration
|
220
|
+
config.finalize!
|
221
|
+
|
222
|
+
# Store it for retrieval
|
223
|
+
@__compiled_zone_configs[zone] = config
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Mark that we finalized
|
228
|
+
@__finalized = true
|
229
|
+
end
|
230
|
+
|
231
|
+
def validate(machine)
|
232
|
+
errors = _detected_errors
|
233
|
+
|
234
|
+
errors << I18n.t("vagrant_google.config.zone_required") if @zone.nil?
|
235
|
+
|
236
|
+
if @zone
|
237
|
+
config = get_zone_config(@zone)
|
238
|
+
|
239
|
+
errors << I18n.t("vagrant_google.config.google_project_id_required") if \
|
240
|
+
config.google_project_id.nil?
|
241
|
+
errors << I18n.t("vagrant_google.config.google_client_email_required") if \
|
242
|
+
config.google_client_email.nil?
|
243
|
+
errors << I18n.t("vagrant_google.config.google_key_location_required") if \
|
244
|
+
config.google_key_location.nil?
|
245
|
+
end
|
246
|
+
|
247
|
+
errors << I18n.t("vagrant_google.config.image_required") if config.image.nil?
|
248
|
+
errors << I18n.t("vagrant_google.config.name_required") if @name.nil?
|
249
|
+
|
250
|
+
{ "Google Provider" => errors }
|
251
|
+
end
|
252
|
+
|
253
|
+
# This gets the configuration for a specific zone. It shouldn't
|
254
|
+
# be called by the general public and is only used internally.
|
255
|
+
def get_zone_config(name)
|
256
|
+
if !@__finalized
|
257
|
+
raise "Configuration must be finalized before calling this method."
|
258
|
+
end
|
259
|
+
|
260
|
+
# Return the compiled zone config
|
261
|
+
@__compiled_zone_configs[name] || self
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|