appengine 0.4.6 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +2 -1
- data/CHANGELOG.md +26 -0
- data/README.md +34 -27
- data/lib/appengine/env.rb +4 -5
- data/lib/appengine/exec.rb +10 -406
- data/lib/appengine/railtie.rb +4 -9
- data/lib/appengine/tasks.rb +218 -144
- data/lib/appengine/util/gcloud.rb +25 -22
- data/lib/appengine/version.rb +5 -5
- data/lib/appengine.rb +12 -5
- metadata +94 -20
- data/Rakefile +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 316bcfd3b1413ddbb299da04099876fc58f2b38f91bef06d6f9d7d23de0b2a7d
|
4
|
+
data.tar.gz: 787086e724920361bf91caa2a8320a84d5b9e794c15175bb70dec0ab1337d30d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81bc955696cda3b5042fa75b3c1e14b99724721a49e262fd178e9ec0c6c99442ab3c7598f484cb289a651f93eb4dfd61e6b811a4857a41e6da8d56290f7f4071
|
7
|
+
data.tar.gz: 52fe0dd05a899f5f9c09929e5dcf245cc4a64cbdd72b8a1e9adee0087928efe1d11b14379a1bdab549c47b025ddae9cab62cb383fc4bfa343321b5d891d8a53a
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,32 @@
|
|
2
2
|
|
3
3
|
This is the change history for the appengine gem.
|
4
4
|
|
5
|
+
### 0.7.0 (2022-04-22)
|
6
|
+
|
7
|
+
#### Features
|
8
|
+
|
9
|
+
* add gcs log dir option
|
10
|
+
* Replace the appengine exec class with an alias to serverless-exec
|
11
|
+
* Update stackdriver dependency
|
12
|
+
#### Bug Fixes
|
13
|
+
|
14
|
+
* Fix exception when a shell command rather than a command array is given in Exec
|
15
|
+
* Fix failure in the appengine:exec cloud_build strategy when App Engine doesn't provide the image
|
16
|
+
|
17
|
+
## v0.6.0 (2020-12-02)
|
18
|
+
|
19
|
+
* Fix failure in the appengine:exec cloud_build strategy when App Engine doesn't provide the image
|
20
|
+
* Fix exception when appengine:exec is provided a shell command rather than a command array (tpbowden)
|
21
|
+
* Update stackdriver dependency to 0.20 and google-cloud-env dependency to 1.4
|
22
|
+
|
23
|
+
## v0.5.0 (2019-07-15)
|
24
|
+
|
25
|
+
* appengine:exec supports the App Engine standard environment.
|
26
|
+
* appengine:exec supports setting the project via `GAE_PROJECT`.
|
27
|
+
* Support for an alternate appengine:exec strategy for flexible environment apps that talk to a database via a private IP.
|
28
|
+
* Fix crash when the gcloud path includes directories with spaces.
|
29
|
+
* Escape `$` symbols in environment configs. (tpbowden)
|
30
|
+
|
5
31
|
## v0.4.6 (2018-09-17)
|
6
32
|
|
7
33
|
* Use gcloud builds submit instead of gcloud container builds submit. (tbpg)
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
Google App Engine Integration Tools
|
2
2
|
===================================
|
3
3
|
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/appengine.svg)](https://badge.fury.io/rb/appengine)
|
5
|
+
|
4
6
|
This repository contains the "appengine" gem, a collection of libraries and
|
5
7
|
plugins for integrating Ruby apps with Google App Engine. It is not required
|
6
8
|
for deploying a ruby application to Google App Engine, but it provides a
|
@@ -18,7 +20,7 @@ Currently, it includes:
|
|
18
20
|
* Convenient access to environment information such as project ID and VM
|
19
21
|
properties.
|
20
22
|
|
21
|
-
|
23
|
+
Potential future directions:
|
22
24
|
|
23
25
|
* Tools for generating "app.yaml" configuration files for Ruby applications.
|
24
26
|
* Streamlined implementation of health checks and other lifecycle hooks.
|
@@ -64,17 +66,25 @@ Rakefile:
|
|
64
66
|
|
65
67
|
require "appengine/tasks"
|
66
68
|
|
67
|
-
###
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
### Setting up appengine:exec remote execution
|
70
|
+
|
71
|
+
This gem is commonly used for its `appengine:exec` Rake task that provides a
|
72
|
+
way to run production tasks such as database migrations in the cloud. If you
|
73
|
+
are getting started with this feature, you should read the documentation
|
74
|
+
(available on the
|
75
|
+
[AppEngine::Exec module](http://www.rubydoc.info/gems/appengine/AppEngine/Exec))
|
76
|
+
carefully, for important tips. In particular:
|
77
|
+
|
78
|
+
* The strategy used by the gem is different depending on whether your app is
|
79
|
+
deployed to the App Engine standard environment or flexible environment.
|
80
|
+
It is important to understand which strategy is in use, because it affects
|
81
|
+
which version of your application code is used to run the task, and various
|
82
|
+
other factors.
|
83
|
+
* You may need to grant additional permissions to the service account that
|
84
|
+
runs the task. Again, the documentation will describe this in detail.
|
85
|
+
* If your app is running on the flexible environment and uses a VPC (and
|
86
|
+
connects to your database via a private IP address), then you will need to
|
87
|
+
use a special configuration for the task.
|
78
88
|
|
79
89
|
## Using this library
|
80
90
|
|
@@ -92,7 +102,9 @@ monitoring features of Google App Engine, see:
|
|
92
102
|
|
93
103
|
Rails applications automatically activate this instrumentation when the gem
|
94
104
|
is present. You may opt out of individual services by providing appropriate
|
95
|
-
Rails configuration. See
|
105
|
+
Rails configuration. See
|
106
|
+
[AppEngine::Railtie](http://www.rubydoc.info/gems/appengine/AppEngine/Railtie)
|
107
|
+
for more information.
|
96
108
|
|
97
109
|
Non-Rails applications must provide initialization code to activate this
|
98
110
|
instrumentation, typically by installing a Rack middleware. You can find the
|
@@ -110,24 +122,19 @@ example, you could run a production database migration in a Rails app using:
|
|
110
122
|
|
111
123
|
bundle exec rake appengine:exec -- bundle exec rake db:migrate
|
112
124
|
|
113
|
-
The migration would be run in
|
114
|
-
|
115
|
-
|
116
|
-
is often much easier and safer than running the task on a local workstation and
|
117
|
-
granting that workstation direct access to those Cloud SQL instances.
|
125
|
+
The migration would be run in containers on Google Cloud infrastructure, which
|
126
|
+
is much easier and safer than running the task on a local workstation and
|
127
|
+
granting that workstation direct access to your production database.
|
118
128
|
|
119
|
-
See
|
129
|
+
See [AppEngine::Exec](http://www.rubydoc.info/gems/appengine/AppEngine/Exec)
|
130
|
+
for more information on App Engine remote execution.
|
120
131
|
|
121
|
-
See
|
122
|
-
|
123
|
-
|
132
|
+
See [AppEngine::Tasks](http://www.rubydoc.info/gems/appengine/AppEngine/Tasks)
|
133
|
+
for more information on running the Rake tasks. The tasks are available
|
134
|
+
automatically in Rails applications when the gem is present. Non-Rails
|
135
|
+
applications may install the tasks by adding the line
|
124
136
|
`require "appengine/tasks"` to the `Rakefile`.
|
125
137
|
|
126
|
-
Note that you may need to grant additional roles to the Container Builder
|
127
|
-
service account that runs your tasks. If your task is failing with API
|
128
|
-
authorization errors, try granting the Project Editor role to the CloudBuild
|
129
|
-
service account.
|
130
|
-
|
131
138
|
## Development and support
|
132
139
|
|
133
140
|
The source code for this gem is available on Github at
|
data/lib/appengine/env.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Google LLC
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
6
|
# you may not use this file except in compliance with the License.
|
@@ -11,13 +13,11 @@
|
|
11
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
14
|
# See the License for the specific language governing permissions and
|
13
15
|
# limitations under the License.
|
14
|
-
;
|
15
16
|
|
16
|
-
require "google/cloud/env"
|
17
17
|
|
18
|
+
require "google/cloud/env"
|
18
19
|
|
19
20
|
module AppEngine
|
20
|
-
|
21
21
|
##
|
22
22
|
# A convenience object that provides information on the Google Cloud
|
23
23
|
# hosting environment. For example, you can call
|
@@ -34,5 +34,4 @@ module AppEngine
|
|
34
34
|
# directly instead. See the documentation for the `google-cloud-env` gem.
|
35
35
|
#
|
36
36
|
Env = ::Google::Cloud.env
|
37
|
-
|
38
37
|
end
|
data/lib/appengine/exec.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Google LLC
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
6
|
# you may not use this file except in compliance with the License.
|
@@ -11,415 +13,17 @@
|
|
11
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
14
|
# See the License for the specific language governing permissions and
|
13
15
|
# limitations under the License.
|
14
|
-
;
|
15
|
-
|
16
|
-
require "yaml"
|
17
|
-
require "json"
|
18
|
-
require "shellwords"
|
19
|
-
require "tempfile"
|
20
16
|
|
21
|
-
require "appengine/util/gcloud"
|
22
17
|
|
18
|
+
require "google/serverless/exec"
|
23
19
|
|
24
20
|
module AppEngine
|
25
|
-
|
26
|
-
##
|
27
|
-
# # App Engine remote execution
|
28
|
-
#
|
29
|
-
# This class provides a client for App Engine remote execution, allowing
|
30
|
-
# App Engine applications to perform on-demand tasks in the App Engine
|
31
|
-
# environment. This may be used for safe running of ops and maintenance
|
32
|
-
# tasks, such as database migrations, that access production cloud resources.
|
33
|
-
#
|
34
|
-
# ## About App Engine execution
|
35
|
-
#
|
36
|
-
# App Engine execution spins up an image of a deployed App Engine app, and
|
37
|
-
# runs a command in that image. For example, if your app runs on Ruby on
|
38
|
-
# Rails, then your app provides a `bin/rails` tool, and you may invoke it
|
39
|
-
# using App Engine execution---for example to run a command such as
|
40
|
-
# `bundle exec bin/rails db:migrate` in the image.
|
41
|
-
#
|
42
|
-
# When App Engine execution runs your command, it provides access to key
|
43
|
-
# elements of the App Engine environment, including:
|
44
|
-
#
|
45
|
-
# * The same runtime that runs your application in App Engine itself.
|
46
|
-
# * Any Cloud SQL connections requested by your application.
|
47
|
-
# * Any environment variables set by your application.
|
48
|
-
#
|
49
|
-
# The command runs on virtual machines provided by Google Cloud Container
|
50
|
-
# Builder, and has access to the credentials of the Cloud Container Builder
|
51
|
-
# service account.
|
52
|
-
#
|
53
|
-
# ## Prerequisites
|
54
|
-
#
|
55
|
-
# To use App Engine remote execution, you will need:
|
56
|
-
#
|
57
|
-
# * An app deployed to Google App Engine, of course!
|
58
|
-
# * The gcloud SDK installed and configured. See https://cloud.google.com/sdk/
|
59
|
-
# * The `appengine` gem.
|
60
|
-
#
|
61
|
-
# You may also need to grant the Cloud Container Builder service account
|
62
|
-
# any permissions needed by your command. Often, Project Editor permissions
|
63
|
-
# will be sufficient for most tasks. You can find the service account
|
64
|
-
# configuration in the IAM tab in the Cloud Console under the name
|
65
|
-
# `[your-project-number]@cloudbuild.gserviceaccount.com`.
|
66
|
-
#
|
67
|
-
# You may use the `AppEngine::Exec` class to run commands directly. However,
|
68
|
-
# in most cases, it will be easier to run commands via the provided rake
|
69
|
-
# tasks. See {AppEngine::Tasks} for more info.
|
70
|
-
#
|
71
|
-
# ## Configuring
|
72
|
-
#
|
73
|
-
# This class uses three parameters to specify which application image to use
|
74
|
-
# to run your command: `service`, `config_path`, and `version`.
|
75
21
|
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
# provides the application image that runs your command.
|
82
|
-
#
|
83
|
-
# If your app has multiple services, you may specify which config file
|
84
|
-
# (other than `./app.yaml`) describes the desired service, by providing the
|
85
|
-
# `config_path` parameter. Alternately, you may specify a service name
|
86
|
-
# directly by providing the `service` parameter. If you provide both
|
87
|
-
# parameters, `service` takes precedence.
|
88
|
-
#
|
89
|
-
# Usually, App Engine execution uses the image for the most recently created
|
90
|
-
# version of the service. (Note: the most recently created version is used,
|
91
|
-
# regardless of whether that version is currently receiving traffic.) If you
|
92
|
-
# want to use the image for a different version, you may specify a version
|
93
|
-
# by providing the `version` parameter.
|
94
|
-
#
|
95
|
-
# You may also provide a timeout, which is the length of time that App
|
96
|
-
# Engine execution will allow your command to run before it is considered to
|
97
|
-
# have stalled and is terminated. The timeout should be a string of the form
|
98
|
-
# `2h15m10s`. The default is `10m`.
|
99
|
-
#
|
100
|
-
# ## Resource usage and billing
|
101
|
-
#
|
102
|
-
# App Engine remote execution uses virtual machine resources provided by
|
103
|
-
# Google Cloud Container Builder. Generally, a certain number of usage
|
104
|
-
# minutes per day is covered under a free tier, but additional compute usage
|
105
|
-
# beyond that time is billed to your Google Cloud account. For more details,
|
106
|
-
# see https://cloud.google.com/container-builder/pricing
|
107
|
-
#
|
108
|
-
# If your command makes API calls or utilizes other cloud resources, you may
|
109
|
-
# also be billed for that usage. However, remote execution does not use
|
110
|
-
# actual App Engine instances, and you will not be billed for additional App
|
111
|
-
# Engine instance usage.
|
112
|
-
#
|
113
|
-
class Exec
|
114
|
-
|
115
|
-
@default_timeout = "10m".freeze
|
116
|
-
@default_service = "default".freeze
|
117
|
-
@default_config_path = "./app.yaml".freeze
|
118
|
-
@default_wrapper_image = "gcr.io/google-appengine/exec-wrapper:latest".freeze
|
119
|
-
|
120
|
-
|
121
|
-
##
|
122
|
-
# Base class for exec-related usage errors.
|
123
|
-
#
|
124
|
-
class UsageError < ::StandardError
|
125
|
-
end
|
126
|
-
|
127
|
-
|
128
|
-
##
|
129
|
-
# Exception raised when the App Engine config file could not be found.
|
130
|
-
#
|
131
|
-
class ConfigFileNotFound < UsageError
|
132
|
-
def initialize config_path
|
133
|
-
@config_path = config_path
|
134
|
-
super "Config file #{config_path} not found."
|
135
|
-
end
|
136
|
-
attr_reader :config_path
|
137
|
-
end
|
138
|
-
|
139
|
-
##
|
140
|
-
# Exception raised when the App Engine config file could not be parsed.
|
141
|
-
#
|
142
|
-
class BadConfigFileFormat < UsageError
|
143
|
-
def initialize config_path
|
144
|
-
@config_path = config_path
|
145
|
-
super "Config file #{config_path} malformed."
|
146
|
-
end
|
147
|
-
attr_reader :config_path
|
148
|
-
end
|
149
|
-
|
150
|
-
##
|
151
|
-
# Exception raised when the given version could not be found, or no
|
152
|
-
# versions at all could be found for the given service.
|
153
|
-
#
|
154
|
-
class NoSuchVersion < UsageError
|
155
|
-
def initialize service, version=nil
|
156
|
-
@service = service
|
157
|
-
@version = version
|
158
|
-
if version
|
159
|
-
super "No such version \"#{version}\" for service \"#{service}\""
|
160
|
-
else
|
161
|
-
super "No versions found for service \"#{service}\""
|
162
|
-
end
|
163
|
-
end
|
164
|
-
attr_reader :service
|
165
|
-
attr_reader :version
|
166
|
-
end
|
167
|
-
|
168
|
-
##
|
169
|
-
# Exception raised when an explicitly-specified service name conflicts with
|
170
|
-
# a config-specified service name.
|
171
|
-
#
|
172
|
-
class ServiceNameConflict < UsageError
|
173
|
-
def initialize service_name, config_name, config_path
|
174
|
-
@service_name = service_name
|
175
|
-
@config_name = config_name
|
176
|
-
@config_path = config_path
|
177
|
-
super "Service name conflicts with config file"
|
178
|
-
end
|
179
|
-
attr_reader :service_name
|
180
|
-
attr_reader :config_name
|
181
|
-
attr_reader :config_path
|
182
|
-
end
|
183
|
-
|
184
|
-
|
185
|
-
class << self
|
186
|
-
|
187
|
-
## @return [String] Default command timeout.
|
188
|
-
attr_accessor :default_timeout
|
189
|
-
|
190
|
-
## @return [String] Default service name if the config doesn't specify.
|
191
|
-
attr_accessor :default_service
|
192
|
-
|
193
|
-
## @return [String] Path to default config file.
|
194
|
-
attr_accessor :default_config_path
|
195
|
-
|
196
|
-
## @return [String] Docker image that implements the app engine wrapper.
|
197
|
-
attr_accessor :default_wrapper_image
|
198
|
-
|
199
|
-
##
|
200
|
-
# Create an execution for a rake task.
|
201
|
-
#
|
202
|
-
# @param name [String] Name of the task
|
203
|
-
# @param args [Array<String>] Args to pass to the task
|
204
|
-
# @param env_args [Array<String>] Environment variable settings, each
|
205
|
-
# of the form `NAME=value`.
|
206
|
-
# @param service [String,nil] Name of the service. If omitted, obtains
|
207
|
-
# the service name from the config file.
|
208
|
-
# @param config_path [String,nil] App Engine config file to get the
|
209
|
-
# service name from if the service name is not provided directly.
|
210
|
-
# Defaults to the value of `AppEngine::Exec.default_config_path`.
|
211
|
-
# @param version [String,nil] Version string. Defaults to the most
|
212
|
-
# recently created version of the given service (which may not be the
|
213
|
-
# one currently receiving traffic).
|
214
|
-
# @param timeout [String,nil] Timeout string. Defaults to the value of
|
215
|
-
# `AppEngine::Exec.default_timeout`.
|
216
|
-
#
|
217
|
-
def new_rake_task name, args: [], env_args: [],
|
218
|
-
service: nil, config_path: nil, version: nil,
|
219
|
-
timeout: nil
|
220
|
-
escaped_args = args.map{ |arg|
|
221
|
-
arg.gsub(/[,\[\]]/){ |m| "\\#{m}" }
|
222
|
-
}
|
223
|
-
if escaped_args.empty?
|
224
|
-
name_with_args = name
|
225
|
-
else
|
226
|
-
name_with_args = "#{name}[#{escaped_args.join ','}]"
|
227
|
-
end
|
228
|
-
new ["bundle", "exec", "rake", name_with_args] + env_args,
|
229
|
-
service: service, config_path: config_path, version: version,
|
230
|
-
timeout: timeout
|
231
|
-
end
|
232
|
-
|
233
|
-
end
|
234
|
-
|
235
|
-
|
236
|
-
##
|
237
|
-
# Create an execution for the given command.
|
238
|
-
#
|
239
|
-
# @param command [Array<String>] The command in array form.
|
240
|
-
# @param service [String,nil] Name of the service. If omitted, obtains
|
241
|
-
# the service name from the config file.
|
242
|
-
# @param config_path [String,nil] App Engine config file to get the
|
243
|
-
# service name from if the service name is not provided directly.
|
244
|
-
# Defaults to the value of `AppEngine::Exec.default_config_path`.
|
245
|
-
# @param version [String,nil] Version string. Defaults to the most
|
246
|
-
# recently created version of the given service (which may not be the
|
247
|
-
# one currently receiving traffic).
|
248
|
-
# @param timeout [String,nil] Timeout string. Defaults to the value of
|
249
|
-
# `AppEngine::Exec.default_timeout`.
|
250
|
-
#
|
251
|
-
def initialize command,
|
252
|
-
service: nil, config_path: nil, version: nil, timeout: nil,
|
253
|
-
wrapper_image: nil
|
254
|
-
@command = command
|
255
|
-
@service = service
|
256
|
-
@config_path = config_path
|
257
|
-
@version = version
|
258
|
-
@timeout = timeout
|
259
|
-
@wrapper_image = wrapper_image
|
260
|
-
|
261
|
-
yield self if block_given?
|
262
|
-
end
|
263
|
-
|
264
|
-
|
265
|
-
## @return [String,nil] The service name, or nil to read from the config.
|
266
|
-
attr_accessor :service
|
267
|
-
|
268
|
-
## @return [String,nil] Path to the config file, or nil to use the default.
|
269
|
-
attr_accessor :config_path
|
270
|
-
|
271
|
-
## @return [String,nil] Service version, or nil to use the most recent.
|
272
|
-
attr_accessor :version
|
273
|
-
|
274
|
-
## @return [String,nil] Command timeout, or nil to use the default.
|
275
|
-
attr_accessor :timeout
|
276
|
-
|
277
|
-
## @return [String,Array<String>] Command to run.
|
278
|
-
attr_accessor :command
|
279
|
-
|
280
|
-
## @return [String] Custom wrapper image to use, or nil to use the default.
|
281
|
-
attr_accessor :wrapper_image
|
282
|
-
|
283
|
-
|
284
|
-
##
|
285
|
-
# Executes the command synchronously. Streams the logs back to standard out
|
286
|
-
# and does not return until the command has completed or timed out.
|
287
|
-
#
|
288
|
-
def start
|
289
|
-
resolve_parameters
|
290
|
-
|
291
|
-
version_info = version_info @service, @version
|
292
|
-
env_variables = version_info["envVariables"] || {}
|
293
|
-
beta_settings = version_info["betaSettings"] || {}
|
294
|
-
cloud_sql_instances = beta_settings["cloud_sql_instances"] || []
|
295
|
-
image = version_info["deployment"]["container"]["image"]
|
296
|
-
|
297
|
-
config = build_config command, image, env_variables, cloud_sql_instances
|
298
|
-
file = ::Tempfile.new ["cloudbuild_", ".json"]
|
299
|
-
begin
|
300
|
-
::JSON.dump config, file
|
301
|
-
file.flush
|
302
|
-
Util::Gcloud.execute [
|
303
|
-
"builds", "submit",
|
304
|
-
"--no-source",
|
305
|
-
"--config=#{file.path}",
|
306
|
-
"--timeout=#{@timeout}"]
|
307
|
-
ensure
|
308
|
-
file.close!
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
|
313
|
-
private
|
314
|
-
|
315
|
-
##
|
316
|
-
# @private
|
317
|
-
# Resolves and canonicalizes all the parameters.
|
318
|
-
#
|
319
|
-
def resolve_parameters
|
320
|
-
unless @command.is_a? Array
|
321
|
-
@command = ::Shellwords.parse @command.to_s
|
322
|
-
end
|
323
|
-
|
324
|
-
config_service = config_path = nil
|
325
|
-
if @config_path || !@service
|
326
|
-
config_service = begin
|
327
|
-
config_path = @config_path || Exec.default_config_path
|
328
|
-
::YAML.load_file(config_path)["service"] || Exec.default_service
|
329
|
-
rescue ::Errno::ENOENT
|
330
|
-
raise ConfigFileNotFound.new config_path
|
331
|
-
rescue
|
332
|
-
raise BadConfigFileFormat.new config_path
|
333
|
-
end
|
334
|
-
end
|
335
|
-
if @service && config_service && @service != config_service
|
336
|
-
raise ServiceNameConflict.new @service, config_service, config_path
|
337
|
-
end
|
338
|
-
|
339
|
-
@service ||= config_service
|
340
|
-
@version ||= latest_version @service
|
341
|
-
@timeout ||= Exec.default_timeout
|
342
|
-
@wrapper_image ||= Exec.default_wrapper_image
|
343
|
-
end
|
344
|
-
|
345
|
-
##
|
346
|
-
# @private
|
347
|
-
# Builds a cloudbuild config as a data structure.
|
348
|
-
#
|
349
|
-
# @param command [Array<String>] The command in array form.
|
350
|
-
# @param image [String] The fully qualified image path.
|
351
|
-
# @param env_variables[Hash<String,String>] Environment variables.
|
352
|
-
# @param cloud_sql_instances[String,Array<String>] Names of cloud sql
|
353
|
-
# instances to connect to.
|
354
|
-
#
|
355
|
-
def build_config command, image, env_variables, cloud_sql_instances
|
356
|
-
args = ["-i", image]
|
357
|
-
env_variables.each do |k, v|
|
358
|
-
args << "-e" << "#{k}=#{v}"
|
359
|
-
end
|
360
|
-
unless cloud_sql_instances.empty?
|
361
|
-
cloud_sql_instances = Array(cloud_sql_instances)
|
362
|
-
cloud_sql_instances.each do |sql|
|
363
|
-
args << "-s" << sql
|
364
|
-
end
|
365
|
-
end
|
366
|
-
args << "--"
|
367
|
-
args += command
|
368
|
-
|
369
|
-
{
|
370
|
-
"steps" => [
|
371
|
-
"name" => @wrapper_image,
|
372
|
-
"args" => args
|
373
|
-
]
|
374
|
-
}
|
375
|
-
end
|
376
|
-
|
377
|
-
##
|
378
|
-
# @private
|
379
|
-
# Returns the name of the most recently created version of the given
|
380
|
-
# service.
|
381
|
-
#
|
382
|
-
# @param service [String] Name of the service.
|
383
|
-
# @return [String] Name of the most recent version.
|
384
|
-
#
|
385
|
-
def latest_version service
|
386
|
-
result = Util::Gcloud.execute [
|
387
|
-
"app", "versions", "list",
|
388
|
-
"--service=#{service}",
|
389
|
-
"--format=get(version.id)",
|
390
|
-
"--sort-by=~version.createTime",
|
391
|
-
"--limit=1"],
|
392
|
-
capture: true, assert: false
|
393
|
-
result = result.split.first
|
394
|
-
raise NoSuchVersion.new(service) unless result
|
395
|
-
result
|
396
|
-
end
|
397
|
-
|
398
|
-
##
|
399
|
-
# @private
|
400
|
-
# Returns full information on the given version of the given service.
|
401
|
-
#
|
402
|
-
# @param service [String] Name of the service. If omitted, the service
|
403
|
-
# "default" is used.
|
404
|
-
# @param version [String] Name of the version. If omitted, the most
|
405
|
-
# recently deployed is used.
|
406
|
-
# @return [Hash,nil] A collection of fields parsed from the JSON
|
407
|
-
# representation of the version, or nil if the requested version
|
408
|
-
# doesn't exist.
|
409
|
-
#
|
410
|
-
def version_info service, version
|
411
|
-
service ||= "default"
|
412
|
-
version ||= latest_version service
|
413
|
-
result = Util::Gcloud.execute [
|
414
|
-
"app", "versions", "describe", version,
|
415
|
-
"--service=#{service}",
|
416
|
-
"--format=json"],
|
417
|
-
capture: true, assert: false
|
418
|
-
result.strip!
|
419
|
-
raise NoSuchVersion.new(service, version) if result.empty?
|
420
|
-
::JSON.parse result
|
421
|
-
end
|
422
|
-
|
423
|
-
end
|
22
|
+
# The Appengine gem uses the Google Serverless gem for remote execution.
|
23
|
+
# This may be used for safe running of ops and maintenance tasks, such as
|
24
|
+
# database migrations in a production serverless environment.
|
25
|
+
# See [Google Serverless Exec](https://www.rubydoc.info/gems/google-serverless-exec)
|
26
|
+
# for more information on the usage documentation
|
424
27
|
|
28
|
+
Exec = Google::Serverless::Exec
|
425
29
|
end
|
data/lib/appengine/railtie.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright 2019 Google LLC
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
6
|
# you may not use this file except in compliance with the License.
|
@@ -11,11 +13,9 @@
|
|
11
13
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
14
|
# See the License for the specific language governing permissions and
|
13
15
|
# limitations under the License.
|
14
|
-
;
|
15
16
|
|
16
17
|
|
17
18
|
module AppEngine
|
18
|
-
|
19
19
|
##
|
20
20
|
# # AppEngine Rails integration
|
21
21
|
#
|
@@ -74,16 +74,11 @@ module AppEngine
|
|
74
74
|
# disable debugging.
|
75
75
|
#
|
76
76
|
class Railtie < ::Rails::Railtie
|
77
|
-
|
78
77
|
config.appengine = ::ActiveSupport::OrderedOptions.new
|
79
78
|
config.appengine.define_tasks = true
|
80
79
|
|
81
80
|
rake_tasks do |app|
|
82
|
-
if app.config.appengine.define_tasks
|
83
|
-
require "appengine/tasks"
|
84
|
-
end
|
81
|
+
require "appengine/tasks" if app.config.appengine.define_tasks
|
85
82
|
end
|
86
|
-
|
87
83
|
end
|
88
|
-
|
89
84
|
end
|