google-serverless-exec 0.1.0
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.
- checksums.yaml +7 -0
- data/.yardopts +10 -0
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +27 -0
- data/LICENSE +202 -0
- data/README.md +49 -0
- data/lib/google/serverless/exec.rb +914 -0
- data/lib/google/serverless/exec/gcloud.rb +200 -0
- data/lib/google/serverless/exec/tasks.rb +381 -0
- data/lib/google/serverless/exec/version.rb +24 -0
- metadata +199 -0
@@ -0,0 +1,200 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2021 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
require "shellwords"
|
19
|
+
require "English"
|
20
|
+
|
21
|
+
module Google
|
22
|
+
module Serverless
|
23
|
+
class Exec
|
24
|
+
##
|
25
|
+
# A collection of utility functions and classes for interacting with an
|
26
|
+
# installation of the gcloud SDK.
|
27
|
+
#
|
28
|
+
module Gcloud
|
29
|
+
##
|
30
|
+
# Base class for gcloud related errors.
|
31
|
+
#
|
32
|
+
class Error < ::StandardError
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Exception raised when the gcloud binary could not be found.
|
37
|
+
#
|
38
|
+
class BinaryNotFound < Gcloud::Error
|
39
|
+
def initialize
|
40
|
+
super "GCloud binary not found in path"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Exception raised when the project gcloud config is not set.
|
46
|
+
#
|
47
|
+
class ProjectNotSet < Gcloud::Error
|
48
|
+
def initialize
|
49
|
+
super "GCloud project configuration not set"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Exception raised when gcloud auth has not been completed.
|
55
|
+
#
|
56
|
+
class GcloudNotAuthenticated < Gcloud::Error
|
57
|
+
def initialize
|
58
|
+
super "GCloud not authenticated"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Exception raised when gcloud fails and returns an error.
|
64
|
+
#
|
65
|
+
class GcloudFailed < Gcloud::Error
|
66
|
+
def initialize code
|
67
|
+
super "GCloud failed with result code #{code}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class << self
|
72
|
+
##
|
73
|
+
# @private
|
74
|
+
# Returns the path to the gcloud binary, or nil if the binary could
|
75
|
+
# not be found.
|
76
|
+
#
|
77
|
+
# @return [String,nil] Path to the gcloud binary.
|
78
|
+
#
|
79
|
+
def binary_path
|
80
|
+
unless defined? @binary_path
|
81
|
+
@binary_path =
|
82
|
+
if ::Gem.win_platform?
|
83
|
+
`where gcloud` == "" ? nil : "gcloud"
|
84
|
+
else
|
85
|
+
path = `which gcloud`.strip
|
86
|
+
path.empty? ? nil : path
|
87
|
+
end
|
88
|
+
end
|
89
|
+
@binary_path
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# @private
|
94
|
+
# Returns the path to the gcloud binary. Raises BinaryNotFound if the
|
95
|
+
# binary could not be found.
|
96
|
+
#
|
97
|
+
# @return [String] Path to the gcloud binary.
|
98
|
+
# @raise [BinaryNotFound] The gcloud binary is not present.
|
99
|
+
#
|
100
|
+
def binary_path!
|
101
|
+
value = binary_path
|
102
|
+
raise BinaryNotFound unless value
|
103
|
+
value
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# @private
|
108
|
+
# Returns the ID of the current project, or nil if no project has
|
109
|
+
# been set.
|
110
|
+
#
|
111
|
+
# @return [String,nil] ID of the current project.
|
112
|
+
#
|
113
|
+
def current_project
|
114
|
+
unless defined? @current_project
|
115
|
+
params = [
|
116
|
+
"config", "list", "core/project", "--format=value(core.project)"
|
117
|
+
]
|
118
|
+
@current_project = execute params, capture: true
|
119
|
+
@current_project = nil if @current_project.empty?
|
120
|
+
end
|
121
|
+
@current_project
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# @private
|
126
|
+
# Returns the ID of the current project. Raises ProjectNotSet if no
|
127
|
+
# project has been set in the gcloud configuration.
|
128
|
+
#
|
129
|
+
# @return [String] ID of the current project.
|
130
|
+
# @raise [ProjectNotSet] The project config has not been set.
|
131
|
+
#
|
132
|
+
def current_project!
|
133
|
+
value = current_project
|
134
|
+
raise ProjectNotSet if value.empty?
|
135
|
+
value
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# @private
|
140
|
+
# Verifies that all gcloud related dependencies are satisfied.
|
141
|
+
# Specifically, verifies that the gcloud binary is installed and
|
142
|
+
# authenticated, and a project has been set.
|
143
|
+
#
|
144
|
+
# @raise [BinaryNotFound] The gcloud binary is not present.
|
145
|
+
# @raise [ProjectNotSet] The project config has not been set.
|
146
|
+
# @raise [GcloudNotAuthenticated] Gcloud has not been authenticated.
|
147
|
+
#
|
148
|
+
def verify!
|
149
|
+
binary_path!
|
150
|
+
current_project!
|
151
|
+
auths = execute ["auth", "list", "--format=value(account)"],
|
152
|
+
capture: true
|
153
|
+
raise GcloudNotAuthenticated if auths.empty?
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# @private
|
158
|
+
# Execute a given gcloud command in a subshell.
|
159
|
+
#
|
160
|
+
# @param args [Array<String>] The gcloud args.
|
161
|
+
# @param echo [boolean] Whether to echo the command to the terminal.
|
162
|
+
# Defaults to false.
|
163
|
+
# @param capture [boolean] If true, return the output. If false, return
|
164
|
+
# a boolean indicating success or failure. Defaults to false.
|
165
|
+
# @param assert [boolean] If true, raise GcloudFailed on failure.
|
166
|
+
# Defaults to true.
|
167
|
+
# @return [String,Integer] Either the output or the success status,
|
168
|
+
# depending on the value of the `capture` parameter.
|
169
|
+
#
|
170
|
+
def execute args, echo: false, capture: false, assert: true
|
171
|
+
cmd_array = [binary_path!] + args
|
172
|
+
cmd =
|
173
|
+
if ::Gem.win_platform?
|
174
|
+
cmd_array.join " "
|
175
|
+
else
|
176
|
+
::Shellwords.join cmd_array
|
177
|
+
end
|
178
|
+
puts cmd if echo
|
179
|
+
result = capture ? `#{cmd}` : system(cmd)
|
180
|
+
code = $CHILD_STATUS.exitstatus
|
181
|
+
raise GcloudFailed, code if assert && code != 0
|
182
|
+
result
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# @private
|
187
|
+
# Execute a given gcloud command in a subshell, and return the output
|
188
|
+
# as a string.
|
189
|
+
#
|
190
|
+
# @param args [Array<String>] The gcloud args.
|
191
|
+
# @return [String] The command output.
|
192
|
+
#
|
193
|
+
def capture args
|
194
|
+
execute args, capture: true
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,381 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2021 Google LLC
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
|
18
|
+
require "shellwords"
|
19
|
+
|
20
|
+
require "google/serverless/exec/gcloud"
|
21
|
+
require "google/serverless/exec"
|
22
|
+
|
23
|
+
module Google
|
24
|
+
module Serverless
|
25
|
+
class Exec
|
26
|
+
##
|
27
|
+
# # Serverless Rake Tasks.
|
28
|
+
#
|
29
|
+
# To make these tasks available, add the line `require "google/serverless/exec/tasks"`
|
30
|
+
# to your Rakefile. If your app uses Ruby on Rails, then the serverless gem
|
31
|
+
# provides a railtie that adds its tasks automatically, so you don't have
|
32
|
+
# to do anything beyond adding the gem to your Gemfile.
|
33
|
+
#
|
34
|
+
# The following tasks are defined:
|
35
|
+
#
|
36
|
+
# ## Rake serverless:exec
|
37
|
+
#
|
38
|
+
# Executes a given command in the context of a serverless application.
|
39
|
+
# See {Google::Serverless::Exec} for more information on this capability.
|
40
|
+
#
|
41
|
+
# The command to be run may either be provided as a rake argument, or as
|
42
|
+
# command line arguments, delimited by two dashes `--`. (The dashes are
|
43
|
+
# needed to separate your command from rake arguments and flags.)
|
44
|
+
# For example, to run a production database migration, you can run either of
|
45
|
+
# the following equivalent commands:
|
46
|
+
#
|
47
|
+
# bundle exec rake "serverless:exec[bundle exec bin/rails db:migrate]"
|
48
|
+
# bundle exec rake serverless:exec -- bundle exec bin/rails db:migrate
|
49
|
+
#
|
50
|
+
# To display usage instructions, provide two dashes but no command:
|
51
|
+
#
|
52
|
+
# bundle exec rake serverless:exec --
|
53
|
+
#
|
54
|
+
# ### Parameters
|
55
|
+
#
|
56
|
+
# You may customize the behavior of the serverless execution through a few
|
57
|
+
# enviroment variable parameters. These are set via the normal mechanism at
|
58
|
+
# the end of a rake command line. For example, to set GAE_CONFIG:
|
59
|
+
#
|
60
|
+
# bundle exec rake serverless:exec GAE_CONFIG=myservice.yaml -- bundle exec bin/rails db:migrate
|
61
|
+
#
|
62
|
+
# Be sure to set these parameters before the double dash. Any arguments
|
63
|
+
# following the double dash are interpreted as part of the command itself.
|
64
|
+
#
|
65
|
+
# The following environment variable parameters are supported:
|
66
|
+
#
|
67
|
+
# #### GAE_TIMEOUT
|
68
|
+
#
|
69
|
+
# Amount of time to wait before serverless:exec terminates the command.
|
70
|
+
# Expressed as a string formatted like: "2h15m10s". Default is "10m".
|
71
|
+
#
|
72
|
+
# #### GAE_PROJECT
|
73
|
+
#
|
74
|
+
# The ID of your Google Cloud project. If not specified, uses the current
|
75
|
+
# project from gcloud.
|
76
|
+
#
|
77
|
+
# #### GAE_CONFIG
|
78
|
+
#
|
79
|
+
# Path to the App Engine config file, used when your app has multiple
|
80
|
+
# services, or the config file is otherwise not called `./app.yaml`. The
|
81
|
+
# config file is used to determine the name of the App Engine service.
|
82
|
+
#
|
83
|
+
# #### GAE_SERVICE
|
84
|
+
#
|
85
|
+
# Name of the service to be used. Overrides any service name specified in
|
86
|
+
# your config file.
|
87
|
+
#
|
88
|
+
# #### GAE_EXEC_STRATEGY
|
89
|
+
#
|
90
|
+
# The execution strategy to use. Valid values are "deployment" (which is the
|
91
|
+
# default for App Engine Standard apps) and "cloud_build" (which is the
|
92
|
+
# default for App Engine Flexible and Cloud Run apps).
|
93
|
+
#
|
94
|
+
# Normally you should leave the strategy set to the default. The main reason
|
95
|
+
# to change it is if your app runs on the Flexible Environment and talks to
|
96
|
+
# a database over a VPC (using a private IP address). The "cloud_build"
|
97
|
+
# strategy used by default for Flexible apps cannot connect to a VPC, so you
|
98
|
+
# should use "deployment" in this case. (But note that, otherwise, the
|
99
|
+
# "deployment" strategy is significantly slower for apps on the Flexible
|
100
|
+
# environment.)
|
101
|
+
#
|
102
|
+
# #### GAE_VERSION
|
103
|
+
#
|
104
|
+
# The version of the service, used to identify which application image to
|
105
|
+
# use to run your command. If not specified, uses the most recently created
|
106
|
+
# version, regardless of whether that version is actually serving traffic.
|
107
|
+
# Applies only to the "cloud_build" strategy. (The "deployment" strategy
|
108
|
+
# deploys its own temporary version of your app.)
|
109
|
+
#
|
110
|
+
# #### GAE_EXEC_WRAPPER_IMAGE
|
111
|
+
#
|
112
|
+
# The fully-qualified name of the wrapper image to use. (This is a Docker
|
113
|
+
# image that emulates the App Engine environment in Google Cloud Build for
|
114
|
+
# the "cloud_build" strategy, and applies only to that strategy.) Normally,
|
115
|
+
# you should not override this unless you are testing a new wrapper.
|
116
|
+
#
|
117
|
+
# #### CLOUD_BUILD_GCS_LOG_DIR
|
118
|
+
#
|
119
|
+
# GCS bucket name of the cloud build log when GAE_STRATEGY is "cloud_build".
|
120
|
+
# (ex. "gs://BUCKET-NAME/FOLDER-NAME")
|
121
|
+
module Tasks
|
122
|
+
## @private
|
123
|
+
PROJECT_ENV = "GAE_PROJECT"
|
124
|
+
## @private
|
125
|
+
STRATEGY_ENV = "GAE_EXEC_STRATEGY"
|
126
|
+
## @private
|
127
|
+
CONFIG_ENV = "GAE_CONFIG"
|
128
|
+
## @private
|
129
|
+
SERVICE_ENV = "GAE_SERVICE"
|
130
|
+
## @private
|
131
|
+
VERSION_ENV = "GAE_VERSION"
|
132
|
+
## @private
|
133
|
+
TIMEOUT_ENV = "GAE_TIMEOUT"
|
134
|
+
## @private
|
135
|
+
WRAPPER_IMAGE_ENV = "GAE_EXEC_WRAPPER_IMAGE"
|
136
|
+
## @private
|
137
|
+
GCS_LOG_DIR = "CLOUD_BUILD_GCS_LOG_DIR"
|
138
|
+
## @private
|
139
|
+
PRODUCT_ENV = "PRODUCT"
|
140
|
+
|
141
|
+
@defined = false
|
142
|
+
|
143
|
+
class << self
|
144
|
+
##
|
145
|
+
# @private
|
146
|
+
# Define rake tasks.
|
147
|
+
#
|
148
|
+
def define
|
149
|
+
if @defined
|
150
|
+
puts "Serverless rake tasks already defined."
|
151
|
+
return
|
152
|
+
end
|
153
|
+
@defined = true
|
154
|
+
|
155
|
+
setup_exec_task
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def setup_exec_task
|
161
|
+
::Rake.application.last_description =
|
162
|
+
"Execute the given command in a Google serverless application."
|
163
|
+
::Rake::Task.define_task "serverless:exec", [:cmd] do |_t, args|
|
164
|
+
verify_gcloud_and_report_errors
|
165
|
+
command = extract_command args[:cmd], ::ARGV
|
166
|
+
selected_product = extract_product ::ENV[PRODUCT_ENV]
|
167
|
+
app_exec = Exec.new command,
|
168
|
+
project: ::ENV[PROJECT_ENV],
|
169
|
+
service: ::ENV[SERVICE_ENV],
|
170
|
+
config_path: ::ENV[CONFIG_ENV],
|
171
|
+
version: ::ENV[VERSION_ENV],
|
172
|
+
timeout: ::ENV[TIMEOUT_ENV],
|
173
|
+
wrapper_image: ::ENV[WRAPPER_IMAGE_ENV],
|
174
|
+
strategy: ::ENV[STRATEGY_ENV],
|
175
|
+
gcs_log_dir: ::ENV[GCS_LOG_DIR],
|
176
|
+
product: selected_product
|
177
|
+
start_and_report_errors app_exec
|
178
|
+
exit
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def extract_command cmd, argv
|
183
|
+
if cmd
|
184
|
+
::Shellwords.split cmd
|
185
|
+
else
|
186
|
+
i = (argv.index { |a| a.to_s == "--" } || -1) + 1
|
187
|
+
if i.zero?
|
188
|
+
report_error <<~MESSAGE
|
189
|
+
No command provided for serverless:exec.
|
190
|
+
Did you remember to delimit it with two dashes? e.g.
|
191
|
+
bundle exec rake serverless:exec -- bundle exec ruby myscript.rb
|
192
|
+
For detailed usage instructions, provide two dashes but no command:
|
193
|
+
bundle exec rake serverless:exec --
|
194
|
+
MESSAGE
|
195
|
+
end
|
196
|
+
command = ::ARGV[i..-1]
|
197
|
+
if command.empty?
|
198
|
+
show_usage
|
199
|
+
exit
|
200
|
+
end
|
201
|
+
command
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def extract_product product
|
206
|
+
if product
|
207
|
+
product = product.dup
|
208
|
+
product.downcase!
|
209
|
+
|
210
|
+
case product
|
211
|
+
when "app_engine"
|
212
|
+
APP_ENGINE
|
213
|
+
when "cloud_run"
|
214
|
+
CLOUD_RUN
|
215
|
+
end
|
216
|
+
else
|
217
|
+
nil
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def show_usage
|
222
|
+
puts <<~USAGE
|
223
|
+
rake serverless:exec
|
224
|
+
This Rake task executes a given command in the context of a serverless
|
225
|
+
application. For more information,
|
226
|
+
on this capability, see the Google::Serverless::Exec documentation at
|
227
|
+
http://www.rubydoc.info/gems/appengine/AppEngine/Exec
|
228
|
+
The command to be run may either be provided as a rake argument, or as
|
229
|
+
command line arguments delimited by two dashes `--`. (The dashes are
|
230
|
+
needed to separate your command from rake arguments and flags.)
|
231
|
+
For example, to run a production database migration, you can run either
|
232
|
+
of the following equivalent commands:
|
233
|
+
bundle exec rake "serverless:exec[bundle exec bin/rails db:migrate]"
|
234
|
+
bundle exec rake serverless:exec -- bundle exec bin/rails db:migrate
|
235
|
+
To display these usage instructions, provide two dashes but no command:
|
236
|
+
bundle exec rake serverless:exec --
|
237
|
+
You may customize the behavior of the serverless execution through a few
|
238
|
+
enviroment variable parameters. These are set via the normal mechanism at
|
239
|
+
the end of a rake command line but before the double dash. For example, to
|
240
|
+
set GAE_CONFIG:
|
241
|
+
bundle exec rake serverless:exec GAE_CONFIG=myservice.yaml -- bundle exec bin/rails db:migrate
|
242
|
+
Be sure to set these parameters before the double dash. Any arguments
|
243
|
+
following the double dash are interpreted as part of the command itself.
|
244
|
+
The following environment variable parameters are supported:
|
245
|
+
GAE_TIMEOUT
|
246
|
+
Amount of time to wait before serverless:exec terminates the command.
|
247
|
+
Expressed as a string formatted like: "2h15m10s". Default is "10m".
|
248
|
+
GAE_PROJECT
|
249
|
+
The ID of your Google Cloud project. If not specified, uses the current
|
250
|
+
project from gcloud.
|
251
|
+
GAE_CONFIG
|
252
|
+
Path to the App Engine config file, used when your app has multiple
|
253
|
+
services, or the config file is otherwise not called `./app.yaml`. The
|
254
|
+
config file is used to determine the name of the App Engine service.
|
255
|
+
GAE_SERVICE
|
256
|
+
Name of the service to be used. Overrides any service name specified in
|
257
|
+
your config file.
|
258
|
+
GAE_EXEC_STRATEGY
|
259
|
+
The execution strategy to use. Valid values are "deployment" (which is the
|
260
|
+
default for App Engine Standard apps) and "cloud_build" (which is the
|
261
|
+
default for App Engine Flexible and Cloud Run apps).
|
262
|
+
Normally you should leave the strategy set to the default. The main reason
|
263
|
+
to change it is if your app runs on the Flexible Environment and talks to
|
264
|
+
a database over a VPC (using a private IP address). The "cloud_build"
|
265
|
+
strategy used by default for Flexible apps cannot connect to a VPC, so you
|
266
|
+
should use "deployment" in this case. (But note that, otherwise, the
|
267
|
+
"deployment" strategy is significantly slower for apps on the Flexible
|
268
|
+
environment.)
|
269
|
+
GAE_VERSION
|
270
|
+
The version of the service, used to identify which application image to
|
271
|
+
use to run your command. If not specified, uses the most recently created
|
272
|
+
version, regardless of whether that version is actually serving traffic.
|
273
|
+
Applies only to the "cloud_build" strategy. (The "deployment" strategy
|
274
|
+
deploys its own temporary version of your app.)
|
275
|
+
GAE_EXEC_WRAPPER_IMAGE
|
276
|
+
The fully-qualified name of the wrapper image to use. (This is a Docker
|
277
|
+
image that emulates the App Engine environment in Google Cloud Build for
|
278
|
+
the "cloud_build" strategy, and applies only to that strategy.) Normally,
|
279
|
+
you should not override this unless you are testing a new wrapper.
|
280
|
+
CLOUD_BUILD_GCS_LOG_DIR
|
281
|
+
GCS bucket name of the cloud build log when GAE_STRATEGY is "cloud_build".
|
282
|
+
(ex. "gs://BUCKET-NAME/FOLDER-NAME")
|
283
|
+
PRODUCT
|
284
|
+
The serverless product to use. Valid values are "app_engine" and "cloud_run".
|
285
|
+
If not specified, autodetects the serverless product to use.
|
286
|
+
This rake task is provided by the "serverless" gem. To make these tasks
|
287
|
+
available, add the following line to your Rakefile:
|
288
|
+
require "google/serverless/exec/tasks"
|
289
|
+
If your app uses Ruby on Rails, the gem provides a railtie that adds its
|
290
|
+
tasks automatically, so you don't have to do anything beyond adding the
|
291
|
+
gem to your Gemfile.
|
292
|
+
For more information or to report issues, visit the Github page:
|
293
|
+
https://github.com/GoogleCloudPlatform/google-serverless-exec
|
294
|
+
USAGE
|
295
|
+
end
|
296
|
+
|
297
|
+
def verify_gcloud_and_report_errors
|
298
|
+
Exec::Gcloud.verify!
|
299
|
+
rescue Exec::Gcloud::BinaryNotFound
|
300
|
+
report_error <<~MESSAGE
|
301
|
+
Could not find the `gcloud` binary in your system path.
|
302
|
+
This tool requires the Google Cloud SDK. To download and install it,
|
303
|
+
visit https://cloud.google.com/sdk/downloads
|
304
|
+
MESSAGE
|
305
|
+
rescue Exec::Gcloud::GcloudNotAuthenticated
|
306
|
+
report_error <<~MESSAGE
|
307
|
+
The gcloud authorization has not been completed. If you have not yet
|
308
|
+
initialized the Google Cloud SDK, we recommend running the `gcloud init`
|
309
|
+
command as described at https://cloud.google.com/sdk/docs/initializing
|
310
|
+
Alternately, you may log in directly by running `gcloud auth login`.
|
311
|
+
MESSAGE
|
312
|
+
rescue Exec::Gcloud::ProjectNotSet
|
313
|
+
report_error <<~MESSAGE
|
314
|
+
The gcloud project configuration has not been set. If you have not yet
|
315
|
+
initialized the Google Cloud SDK, we recommend running the `gcloud init`
|
316
|
+
command as described at https://cloud.google.com/sdk/docs/initializing
|
317
|
+
Alternately, you may set the default project configuration directly by
|
318
|
+
running `gcloud config set project <project-name>`.
|
319
|
+
MESSAGE
|
320
|
+
end
|
321
|
+
|
322
|
+
def start_and_report_errors app_exec
|
323
|
+
app_exec.start
|
324
|
+
rescue Exec::ConfigFileNotFound => e
|
325
|
+
report_error <<~MESSAGE
|
326
|
+
Could not determine which service should run this command because the App
|
327
|
+
Engine config file "#{e.config_path}" was not found.
|
328
|
+
Specify the config file using the GAE_CONFIG argument. e.g.
|
329
|
+
bundle exec rake serverless:exec GAE_CONFIG=myapp.yaml -- myscript.sh
|
330
|
+
Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
|
331
|
+
bundle exec rake serverless:exec GAE_SERVICE=myservice -- myscript.sh
|
332
|
+
MESSAGE
|
333
|
+
rescue Exec::BadConfigFileFormat => e
|
334
|
+
report_error <<~MESSAGE
|
335
|
+
Could not determine which service should run this command because the App
|
336
|
+
Engine config file "#{e.config_path}" was malformed.
|
337
|
+
It must be a valid YAML file.
|
338
|
+
Specify the config file using the GAE_CONFIG argument. e.g.
|
339
|
+
bundle exec rake serverless:exec GAE_CONFIG=myapp.yaml -- myscript.sh
|
340
|
+
Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
|
341
|
+
bundle exec rake serverless:exec GAE_SERVICE=myservice -- myscript.sh
|
342
|
+
MESSAGE
|
343
|
+
rescue Exec::NoSuchVersion => e
|
344
|
+
if e.version
|
345
|
+
report_error <<~MESSAGE
|
346
|
+
Could not find version "#{e.version}" of service "#{e.service}".
|
347
|
+
Please double-check the version exists. To use the most recent version by
|
348
|
+
default, omit the GAE_VERSION argument.
|
349
|
+
MESSAGE
|
350
|
+
else
|
351
|
+
report_error <<~MESSAGE
|
352
|
+
Could not find any versions of service "#{e.service}".
|
353
|
+
Please double-check that you have deployed this service. If you want to run
|
354
|
+
a command against a different service, you may provide a GAE_CONFIG argument
|
355
|
+
pointing to your App Engine config file, or a GAE_SERVICE argument to specify
|
356
|
+
a service directly.
|
357
|
+
MESSAGE
|
358
|
+
end
|
359
|
+
rescue Exec::NoDefaultProject
|
360
|
+
report_error <<~MESSAGE
|
361
|
+
Could not get the default project from gcloud.
|
362
|
+
Please either set the current project using
|
363
|
+
gcloud config set project my-project-id
|
364
|
+
or specify the project by setting the GAE_PROJECT argument. e.g.
|
365
|
+
bundle exec rake serverless:exec GAE_PROJECT=my-project-id -- myscript.sh
|
366
|
+
MESSAGE
|
367
|
+
rescue Exec::UsageError => e
|
368
|
+
report_error e.message
|
369
|
+
end
|
370
|
+
|
371
|
+
def report_error str
|
372
|
+
::STDERR.puts str
|
373
|
+
exit 1
|
374
|
+
end
|
375
|
+
end
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
::Google::Serverless::Exec::Tasks.define
|