tcr-vagrant-google 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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