appengine 0.4.6 → 0.7.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 +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
|
+
[](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
|