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,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
+ require "vagrant"
15
+
16
+ module VagrantPlugins
17
+ module Google
18
+ module Errors
19
+ class VagrantGoogleError < Vagrant::Errors::VagrantError
20
+ error_namespace("vagrant_google.errors")
21
+ end
22
+
23
+ class FogError < VagrantGoogleError
24
+ error_key(:fog_error)
25
+ end
26
+
27
+ class RsyncError < VagrantGoogleError
28
+ error_key(:rsync_error)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,86 @@
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
+ begin
15
+ require "vagrant"
16
+ rescue LoadError
17
+ raise "The Vagrant Google plugin must be run within Vagrant."
18
+ end
19
+
20
+ # This is a sanity check to make sure no one is attempting to install
21
+ # this into an early Vagrant version.
22
+ if Vagrant::VERSION < "1.2.0"
23
+ raise "The Vagrant Google plugin is only compatible with Vagrant 1.2+"
24
+ end
25
+
26
+ module VagrantPlugins
27
+ module Google
28
+ class Plugin < Vagrant.plugin("2")
29
+ name "Google"
30
+ description <<-DESC
31
+ This plugin installs a provider that allows Vagrant to manage
32
+ Google Compute Engine instances.
33
+ DESC
34
+
35
+ config(:google, :provider) do
36
+ require_relative "config"
37
+ Config
38
+ end
39
+
40
+ provider(:google, parallel: true) do
41
+ # Setup logging and i18n
42
+ setup_logging
43
+ setup_i18n
44
+
45
+ # Return the provider
46
+ require_relative "provider"
47
+ Provider
48
+ end
49
+
50
+ # This initializes the internationalization strings.
51
+ def self.setup_i18n
52
+ I18n.load_path << File.expand_path("locales/en.yml", Google.source_root)
53
+ I18n.reload!
54
+ end
55
+
56
+ # This sets up our log level to be whatever VAGRANT_LOG is.
57
+ def self.setup_logging
58
+ require "log4r"
59
+
60
+ level = nil
61
+ begin
62
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
63
+ rescue NameError
64
+ # This means that the logging constant wasn't found,
65
+ # which is fine. We just keep `level` as `nil`. But
66
+ # we tell the user.
67
+ level = nil
68
+ end
69
+
70
+ # Some constants, such as "true" resolve to booleans, so the
71
+ # above error checking doesn't catch it. This will check to make
72
+ # sure that the log level is an integer, as Log4r requires.
73
+ level = nil if !level.is_a?(Integer)
74
+
75
+ # Set the logging level on all "vagrant" namespaced
76
+ # logs as long as we have a valid level.
77
+ if level
78
+ logger = Log4r::Logger.new("vagrant_google")
79
+ logger.outputters = Log4r::Outputter.stderr
80
+ logger.level = level
81
+ logger = nil
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,63 @@
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"
16
+
17
+ module VagrantPlugins
18
+ module Google
19
+ class Provider < Vagrant.plugin("2", :provider)
20
+ def initialize(machine)
21
+ @machine = machine
22
+ end
23
+
24
+ def action(name)
25
+ # Attempt to get the action method from the Action class if it
26
+ # exists, otherwise return nil to show that we don't support the
27
+ # given action.
28
+ action_method = "action_#{name}"
29
+ return Action.send(action_method) if Action.respond_to?(action_method)
30
+ nil
31
+ end
32
+
33
+ def ssh_info
34
+ # Run a custom action called "read_ssh_info" which does what it
35
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
36
+ # key in the environment.
37
+ env = @machine.action("read_ssh_info")
38
+ env[:machine_ssh_info]
39
+ end
40
+
41
+ def state
42
+ # Run a custom action we define called "read_state" which does
43
+ # what it says. It puts the state in the `:machine_state_id`
44
+ # key in the environment.
45
+ env = @machine.action("read_state")
46
+
47
+ state_id = env[:machine_state_id]
48
+
49
+ # Get the short and long description
50
+ short = I18n.t("vagrant_google.states.short_#{state_id}")
51
+ long = I18n.t("vagrant_google.states.long_#{state_id}")
52
+
53
+ # Return the MachineState object
54
+ Vagrant::MachineState.new(state_id, short, long)
55
+ end
56
+
57
+ def to_s
58
+ id = @machine.id.nil? ? "new" : @machine.id
59
+ "Google (#{id})"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,30 @@
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 Util
17
+ class Timer
18
+ # A basic utility method that times the execution of the given
19
+ # block and returns it.
20
+ def self.time
21
+ start_time = Time.now.to_f
22
+ yield
23
+ end_time = Time.now.to_f
24
+
25
+ end_time - start_time
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
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
+ VERSION = "0.1.4"
17
+ end
18
+ end
@@ -0,0 +1,105 @@
1
+ en:
2
+ vagrant_google:
3
+ already_created: |-
4
+ The machine is already created.
5
+ launching_instance: |-
6
+ Launching an instance with the following settings...
7
+ launch_vpc_warning: |-
8
+ Warning! You're launching this instance into a VPC without an
9
+ elastic IP. Please verify you're properly connected to a VPN so
10
+ you can access this machine, otherwise Vagrant will not be able
11
+ to SSH into it.
12
+ not_created: |-
13
+ Instance is not created. Please run `vagrant up` first.
14
+ ready: |-
15
+ Machine is booted and ready for use!
16
+ ready_ssh: |-
17
+ Machine is ready for SSH access!
18
+ rsync_folder: |-
19
+ Rsyncing folder: %{hostpath} => %{guestpath}
20
+ terminating: |-
21
+ Terminating the instance...
22
+ waiting_for_ready: |-
23
+ Waiting for instance to become "ready"...
24
+ waiting_for_ssh: |-
25
+ Waiting for SSH to become available...
26
+ warn_networks: |-
27
+ Warning! The Google provider doesn't support any of the Vagrant
28
+ high-level network configurations (`config.vm.network`). They
29
+ will be silently ignored.
30
+ will_not_destroy: |-
31
+ The instance '%{name}' will not be destroyed, since the confirmation
32
+ was declined.
33
+
34
+ config:
35
+ google_client_email_required: |-
36
+ A Google Service Account client email is required via "google_client_email"
37
+ machine_required: |-
38
+ An MACHINE_TYPE must be configured via "machine"
39
+ private_key_missing: |-
40
+ The specified private key for Google could not be found
41
+ zone_required: |-
42
+ A zone must be specified via "zone"
43
+ name_required: |-
44
+ An instance name must be specified via "name"
45
+ google_key_location_required: |-
46
+ A private key pathname is required via "google_key_location"
47
+ google_project_id_required: |-
48
+ A Google Cloud Project ID is required via "google_project_id"
49
+
50
+ errors:
51
+ fog_error: |-
52
+ There was an error talking to Google. The error message is shown
53
+ below:
54
+
55
+ %{message}
56
+ instance_ready_timeout: |-
57
+ The instance never became "ready" in Google. The timeout currently
58
+ set waiting for the instance to become ready is %{timeout} seconds.
59
+ Please verify that the machine properly boots. If you need more time
60
+ set the `instance_ready_timeout` configuration on the Google provider.
61
+ rsync_error: |-
62
+ There was an error when attemping to rsync a share folder.
63
+ Please inspect the error message below for more info.
64
+
65
+ Host path: %{hostpath}
66
+ Guest path: %{guestpath}
67
+ Error: %{stderr}
68
+
69
+ states:
70
+ short_not_created: |-
71
+ not created
72
+ long_not_created: |-
73
+ The Google instance is not created. Run `vagrant up` to create it.
74
+
75
+ short_PROVISIONING: |-
76
+ provsioning
77
+ long_PROVISIONING: |-
78
+ Resources are being reserved for this instance. This instance is
79
+ not yet running.
80
+
81
+ short_STAGING: |-
82
+ staging
83
+ long_STAGING: |-
84
+ Resources have been acquired and the instance is being prepared for
85
+ launch and should be in the RUNNING state soon.
86
+
87
+ short_RUNNING: |-
88
+ running
89
+ long_RUNNING: |-
90
+ The Google instance is running. To stop this machine, you can run
91
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
92
+
93
+ short_STOPPED: |-
94
+ stopped
95
+ long_STOPPED: |-
96
+ The Google instance is not currently running, either due to a failure
97
+ , or the instance is being shut down. This is a temporary status;
98
+ the instance will move to either PROVISIONING or TERMINATED.
99
+
100
+ short_TERMINATED: |-
101
+ terminated
102
+ long_TERMINATED: |-
103
+ The Google instance failed for some reason or was shutdown. This is
104
+ a permanent status, and the only way to repair the instance is to
105
+ delete it with `vagrant destroy`.
@@ -0,0 +1,202 @@
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/config"
15
+
16
+ describe VagrantPlugins::Google::Config do
17
+ let(:instance) { described_class.new }
18
+
19
+ # Ensure tests are not affected by Google credential environment variables
20
+ before :each do
21
+ ENV.stub(:[] => nil)
22
+ end
23
+
24
+ describe "defaults" do
25
+ subject do
26
+ instance.tap do |o|
27
+ o.finalize!
28
+ end
29
+ end
30
+ t = Time.now
31
+
32
+ its("name") { should == "i-#{t.year}#{t.month.to_s.rjust(2,'0')}#{t.day.to_s.rjust(2,'0')}#{t.hour.to_s.rjust(2,'0')}" }
33
+ its("image") { should == "debian-7-wheezy-v20140926" }
34
+ its("zone") { should == "us-central1-f" }
35
+ its("network") { should == "default" }
36
+ its("machine_type") { should == "n1-standard-1" }
37
+ its("disk_size") { should == 10 }
38
+ its("instance_ready_timeout") { should == 20 }
39
+ its("metadata") { should == {} }
40
+ its("tags") { should == [] }
41
+ its("service_accounts") { should == nil }
42
+ end
43
+
44
+ describe "overriding defaults" do
45
+ # I typically don't meta-program in tests, but this is a very
46
+ # simple boilerplate test, so I cut corners here. It just sets
47
+ # each of these attributes to "foo" in isolation, and reads the value
48
+ # and asserts the proper result comes back out.
49
+ [:name, :image, :zone, :instance_ready_timeout, :machine_type, :disk_size,
50
+ :network, :metadata].each do |attribute|
51
+
52
+ it "should not default #{attribute} if overridden" do
53
+ instance.send("#{attribute}=".to_sym, "foo")
54
+ instance.finalize!
55
+ instance.send(attribute).should == "foo"
56
+ end
57
+ end
58
+ end
59
+
60
+ describe "getting credentials from environment" do
61
+ context "without Google credential environment variables" do
62
+ subject do
63
+ instance.tap do |o|
64
+ o.finalize!
65
+ end
66
+ end
67
+
68
+ its("google_client_email") { should be_nil }
69
+ its("google_key_location") { should be_nil }
70
+ end
71
+
72
+ context "with Google credential environment variables" do
73
+ before :each do
74
+ ENV.stub(:[]).with("GOOGLE_CLIENT_EMAIL").and_return("client_id_email")
75
+ ENV.stub(:[]).with("GOOGLE_KEY_LOCATION").and_return("/path/to/key")
76
+ end
77
+
78
+ subject do
79
+ instance.tap do |o|
80
+ o.finalize!
81
+ end
82
+ end
83
+
84
+ its("google_client_email") { should == "client_id_email" }
85
+ its("google_key_location") { should == "/path/to/key" }
86
+ end
87
+ end
88
+
89
+ describe "zone config" do
90
+ let(:config_image) { "foo" }
91
+ let(:config_machine_type) { "foo" }
92
+ let(:config_disk_size) { 99 }
93
+ let(:config_name) { "foo" }
94
+ let(:config_zone) { "foo" }
95
+ let(:config_network) { "foo" }
96
+
97
+ def set_test_values(instance)
98
+ instance.name = config_name
99
+ instance.network = config_network
100
+ instance.image = config_image
101
+ instance.machine_type = config_machine_type
102
+ instance.disk_size = config_disk_size
103
+ instance.zone = config_zone
104
+ end
105
+
106
+ it "should raise an exception if not finalized" do
107
+ expect { instance.get_zone_config("us-central1-f") }.
108
+ to raise_error
109
+ end
110
+
111
+ context "with no specific config set" do
112
+ subject do
113
+ # Set the values on the top-level object
114
+ set_test_values(instance)
115
+
116
+ # Finalize so we can get the zone config
117
+ instance.finalize!
118
+
119
+ # Get a lower level zone
120
+ instance.get_zone_config("us-central1-f")
121
+ end
122
+
123
+ its("name") { should == config_name }
124
+ its("image") { should == config_image }
125
+ its("machine_type") { should == config_machine_type }
126
+ its("disk_size") { should == config_disk_size }
127
+ its("network") { should == config_network }
128
+ its("zone") { should == config_zone }
129
+ end
130
+
131
+ context "with a specific config set" do
132
+ let(:zone_name) { "hashi-zone" }
133
+
134
+ subject do
135
+ # Set the values on a specific zone
136
+ instance.zone_config zone_name do |config|
137
+ set_test_values(config)
138
+ end
139
+
140
+ # Finalize so we can get the zone config
141
+ instance.finalize!
142
+
143
+ # Get the zone
144
+ instance.get_zone_config(zone_name)
145
+ end
146
+
147
+ its("name") { should == config_name }
148
+ its("image") { should == config_image }
149
+ its("machine_type") { should == config_machine_type }
150
+ its("disk_size") { should == config_disk_size }
151
+ its("network") { should == config_network }
152
+ its("zone") { should == zone_name }
153
+ end
154
+
155
+ describe "inheritance of parent config" do
156
+ let(:zone) { "hashi-zone" }
157
+
158
+ subject do
159
+ # Set the values on a specific zone
160
+ instance.zone_config zone do |config|
161
+ config.image = "child"
162
+ end
163
+
164
+ # Set some top-level values
165
+ instance.image = "parent"
166
+
167
+ # Finalize and get the zone
168
+ instance.finalize!
169
+ instance.get_zone_config(zone)
170
+ end
171
+
172
+ its("image") { should == "child" }
173
+ end
174
+
175
+ describe "shortcut configuration" do
176
+ subject do
177
+ # Use the shortcut configuration to set some values
178
+ instance.zone_config "us-central1-f", :image => "child"
179
+ instance.finalize!
180
+ instance.get_zone_config("us-central1-f")
181
+ end
182
+
183
+ its("image") { should == "child" }
184
+ end
185
+
186
+ describe "merging" do
187
+ let(:first) { described_class.new }
188
+ let(:second) { described_class.new }
189
+
190
+ it "should merge the metadata" do
191
+ first.metadata["one"] = "foo"
192
+ second.metadata["two"] = "bar"
193
+
194
+ third = first.merge(second)
195
+ third.metadata.should == {
196
+ "one" => "foo",
197
+ "two" => "bar"
198
+ }
199
+ end
200
+ end
201
+ end
202
+ end