lib/appengine/tasks.rb in appengine-0.4.6 vs lib/appengine/tasks.rb in appengine-0.5.0
- old
+ new
@@ -1,6 +1,8 @@
-# Copyright 2017 Google Inc. All rights reserved.
+# frozen_string_literal: true
+
+# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
@@ -9,23 +11,18 @@
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-;
-# This file should be loaded or required from a Rakefile to define AppEngine
-# related tasks.
require "shellwords"
require "appengine/util/gcloud"
require "appengine/exec"
-
module AppEngine
-
##
# # App Engine Rake Tasks.
#
# To make these tasks available, add the line `require "appengine/tasks"`
# to your Rakefile. If your app uses Ruby on Rails, then the appengine gem
@@ -64,35 +61,66 @@
# Be sure to set these parameters before the double dash. Any arguments
# following the double dash are interpreted as part of the command itself.
#
# The following environment variable parameters are supported:
#
+ # #### GAE_TIMEOUT
+ #
+ # Amount of time to wait before appengine:exec terminates the command.
+ # Expressed as a string formatted like: "2h15m10s". Default is "10m".
+ #
+ # #### GAE_PROJECT
+ #
+ # The ID of your Google Cloud project. If not specified, uses the current
+ # project from gcloud.
+ #
# #### GAE_CONFIG
#
# Path to the App Engine config file, used when your app has multiple
# services, or the config file is otherwise not called `./app.yaml`. The
# config file is used to determine the name of the App Engine service.
#
# #### GAE_SERVICE
#
- # Name of the service to be used. If both `GAE_CONFIG` and `GAE_SERVICE` are
- # provided and imply different service names, an error will be raised.
+ # Name of the service to be used. Overrides any service name specified in
+ # your config file.
#
+ # #### GAE_EXEC_STRATEGY
+ #
+ # The execution strategy to use. Valid values are "deployment" (which is the
+ # default for App Engine Standard apps) and "cloud_build" (which is the
+ # default for App Engine Flexible apps).
+ #
+ # Normally you should leave the strategy set to the default. The main reason
+ # to change it is if your app runs on the Flexible Environment and talks to
+ # a database over a VPC (using a private IP address). The "cloud_build"
+ # strategy used by default for Flexible apps cannot connect to a VPC, so you
+ # should use "deployment" in this case. (But note that, otherwise, the
+ # "deployment" strategy is significantly slower for apps on the Flexible
+ # environment.)
+ #
# #### GAE_VERSION
#
# The version of the service, used to identify which application image to
# use to run your command. If not specified, uses the most recently created
# version, regardless of whether that version is actually serving traffic.
+ # Applies only to the "cloud_build" strategy. (The "deployment" strategy
+ # deploys its own temporary version of your app.)
#
- # #### GAE_TIMEOUT
+ # #### GAE_EXEC_WRAPPER_IMAGE
#
- # Amount of time to wait before appengine:exec terminates the command.
- # Expressed as a string formatted like: "2h15m10s". Default is "10m".
+ # The fully-qualified name of the wrapper image to use. (This is a Docker
+ # image that emulates the App Engine environment in Google Cloud Build for
+ # the "cloud_build" strategy, and applies only to that strategy.) Normally,
+ # you should not override this unless you are testing a new wrapper.
#
module Tasks
-
## @private
+ PROJECT_ENV = "GAE_PROJECT"
+ ## @private
+ STRATEGY_ENV = "GAE_EXEC_STRATEGY"
+ ## @private
CONFIG_ENV = "GAE_CONFIG"
## @private
SERVICE_ENV = "GAE_SERVICE"
## @private
VERSION_ENV = "GAE_VERSION"
@@ -102,11 +130,10 @@
WRAPPER_IMAGE_ENV = "GAE_EXEC_WRAPPER_IMAGE"
@defined = false
class << self
-
##
# @private
# Define rake tasks.
#
def define
@@ -121,191 +148,226 @@
private
def setup_exec_task
::Rake.application.last_description =
- "Execute the given command in Google App Engine."
- ::Rake::Task.define_task "appengine:exec", [:cmd] do |t, args|
+ "Execute the given command in Google App Engine."
+ ::Rake::Task.define_task "appengine:exec", [:cmd] do |_t, args|
verify_gcloud_and_report_errors
- if args[:cmd]
- command = ::Shellwords.split args[:cmd]
- else
- i = (::ARGV.index{ |a| a.to_s == "--" } || -1) + 1
- if i == 0
- report_error <<-MESSAGE
-No command provided for appengine:exec.
-Did you remember to delimit it with two dashes? e.g.
- bundle exec rake appengine:exec -- bundle exec ruby myscript.rb
-For detailed usage instructions, provide two dashes but no command:
- bundle exec rake appengine:exec --
- MESSAGE
- end
- command = ::ARGV[i..-1]
- if command.empty?
- show_usage
- exit
- end
- end
- app_exec = Exec.new \
- command,
- service: ::ENV[SERVICE_ENV],
- config_path: ::ENV[CONFIG_ENV],
- version: ::ENV[VERSION_ENV],
- timeout: ::ENV[TIMEOUT_ENV],
- wrapper_image: ::ENV[WRAPPER_IMAGE_ENV]
+ command = extract_command args[:cmd], ::ARGV
+ app_exec = Exec.new command,
+ project: ::ENV[PROJECT_ENV],
+ service: ::ENV[SERVICE_ENV],
+ config_path: ::ENV[CONFIG_ENV],
+ version: ::ENV[VERSION_ENV],
+ timeout: ::ENV[TIMEOUT_ENV],
+ wrapper_image: ::ENV[WRAPPER_IMAGE_ENV],
+ strategy: ::ENV[STRATEGY_ENV]
start_and_report_errors app_exec
exit
end
end
+ def extract_command cmd, argv
+ if cmd
+ ::Shellwords.split cmd
+ else
+ i = (argv.index { |a| a.to_s == "--" } || -1) + 1
+ if i.zero?
+ report_error <<~MESSAGE
+ No command provided for appengine:exec.
+ Did you remember to delimit it with two dashes? e.g.
+ bundle exec rake appengine:exec -- bundle exec ruby myscript.rb
+ For detailed usage instructions, provide two dashes but no command:
+ bundle exec rake appengine:exec --
+ MESSAGE
+ end
+ command = ::ARGV[i..-1]
+ if command.empty?
+ show_usage
+ exit
+ end
+ command
+ end
+ end
+
def show_usage
- puts <<-USAGE
-rake appengine:exec
+ puts <<~USAGE
+ rake appengine:exec
-This Rake task executes a given command in the context of an App Engine
-application, using App Engine remote execution. For more information,
-on this capability, see the AppEngine::Exec documentation at
-http://www.rubydoc.info/gems/appengine/AppEngine/Exec
+ This Rake task executes a given command in the context of an App Engine
+ application, using App Engine remote execution. For more information,
+ on this capability, see the AppEngine::Exec documentation at
+ http://www.rubydoc.info/gems/appengine/AppEngine/Exec
-The command to be run may either be provided as a rake argument, or as
-command line arguments delimited by two dashes `--`. (The dashes are
-needed to separate your command from rake arguments and flags.)
-For example, to run a production database migration, you can run either
-of the following equivalent commands:
+ The command to be run may either be provided as a rake argument, or as
+ command line arguments delimited by two dashes `--`. (The dashes are
+ needed to separate your command from rake arguments and flags.)
+ For example, to run a production database migration, you can run either
+ of the following equivalent commands:
- bundle exec rake "appengine:exec[bundle exec bin/rails db:migrate]"
- bundle exec rake appengine:exec -- bundle exec bin/rails db:migrate
+ bundle exec rake "appengine:exec[bundle exec bin/rails db:migrate]"
+ bundle exec rake appengine:exec -- bundle exec bin/rails db:migrate
-To display these usage instructions, provide two dashes but no command:
+ To display these usage instructions, provide two dashes but no command:
- bundle exec rake appengine:exec --
+ bundle exec rake appengine:exec --
-You may customize the behavior of App Engine execution through a few
-enviroment variable parameters. These are set via the normal mechanism at
-the end of a rake command line. For example, to set GAE_CONFIG:
+ You may customize the behavior of App Engine execution through a few
+ enviroment variable parameters. These are set via the normal mechanism at
+ the end of a rake command line but before the double dash. For example, to
+ set GAE_CONFIG:
- bundle exec rake appengine:exec GAE_CONFIG=myservice.yaml -- bundle exec bin/rails db:migrate
+ bundle exec rake appengine:exec GAE_CONFIG=myservice.yaml -- bundle exec bin/rails db:migrate
-Be sure to set these parameters before the double dash. Any arguments
-following the double dash are interpreted as part of the command itself.
+ Be sure to set these parameters before the double dash. Any arguments
+ following the double dash are interpreted as part of the command itself.
-The following environment variable parameters are supported:
+ The following environment variable parameters are supported:
-GAE_CONFIG
+ GAE_TIMEOUT
- Path to the App Engine config file, used when your app has multiple
- services, or the config file is otherwise not called `./app.yaml`. The
- config file is used to determine the name of the App Engine service.
+ Amount of time to wait before appengine:exec terminates the command.
+ Expressed as a string formatted like: "2h15m10s". Default is "10m".
-GAE_SERVICE
+ GAE_PROJECT
- Name of the service to be used. If both `GAE_CONFIG` and `GAE_SERVICE`
- are provided and imply different service names, an error will be raised.
+ The ID of your Google Cloud project. If not specified, uses the current
+ project from gcloud.
-GAE_VERSION
+ GAE_CONFIG
- The version of the service, used to identify which application image to
- use to run your command. If not specified, uses the most recently created
- version, regardless of whether that version is actually serving traffic.
+ Path to the App Engine config file, used when your app has multiple
+ services, or the config file is otherwise not called `./app.yaml`. The
+ config file is used to determine the name of the App Engine service.
-GAE_TIMEOUT
+ GAE_SERVICE
- Amount of time to wait before appengine:exec terminates the command.
- Expressed as a string formatted like: "2h15m10s". Default is "10m".
+ Name of the service to be used. Overrides any service name specified in
+ your config file.
-This rake task is provided by the "appengine" gem. To make these tasks
-available, add the following line to your Rakefile:
+ GAE_EXEC_STRATEGY
- require "appengine/tasks"
+ The execution strategy to use. Valid values are "deployment" (which is the
+ default for App Engine Standard apps) and "cloud_build" (which is the
+ default for App Engine Flexible apps).
-If your app uses Ruby on Rails, the gem provides a railtie that adds its
-tasks automatically, so you don't have to do anything beyond adding the
-gem to your Gemfile.
+ Normally you should leave the strategy set to the default. The main reason
+ to change it is if your app runs on the Flexible Environment and talks to
+ a database over a VPC (using a private IP address). The "cloud_build"
+ strategy used by default for Flexible apps cannot connect to a VPC, so you
+ should use "deployment" in this case. (But note that, otherwise, the
+ "deployment" strategy is significantly slower for apps on the Flexible
+ environment.)
-For more information or to report issues, visit the Github page:
-https://github.com/GoogleCloudPlatform/appengine-ruby
+ GAE_VERSION
+
+ The version of the service, used to identify which application image to
+ use to run your command. If not specified, uses the most recently created
+ version, regardless of whether that version is actually serving traffic.
+ Applies only to the "cloud_build" strategy. (The "deployment" strategy
+ deploys its own temporary version of your app.)
+
+ GAE_EXEC_WRAPPER_IMAGE
+
+ The fully-qualified name of the wrapper image to use. (This is a Docker
+ image that emulates the App Engine environment in Google Cloud Build for
+ the "cloud_build" strategy, and applies only to that strategy.) Normally,
+ you should not override this unless you are testing a new wrapper.
+
+ This rake task is provided by the "appengine" gem. To make these tasks
+ available, add the following line to your Rakefile:
+
+ require "appengine/tasks"
+
+ If your app uses Ruby on Rails, the gem provides a railtie that adds its
+ tasks automatically, so you don't have to do anything beyond adding the
+ gem to your Gemfile.
+
+ For more information or to report issues, visit the Github page:
+ https://github.com/GoogleCloudPlatform/appengine-ruby
USAGE
end
def verify_gcloud_and_report_errors
Util::Gcloud.verify!
rescue Util::Gcloud::BinaryNotFound
- report_error <<-MESSAGE
-Could not find the `gcloud` binary in your system path.
-This tool requires the Google Cloud SDK. To download and install it,
-visit https://cloud.google.com/sdk/downloads
+ report_error <<~MESSAGE
+ Could not find the `gcloud` binary in your system path.
+ This tool requires the Google Cloud SDK. To download and install it,
+ visit https://cloud.google.com/sdk/downloads
MESSAGE
rescue Util::Gcloud::GcloudNotAuthenticated
- report_error <<-MESSAGE
-The gcloud authorization has not been completed. If you have not yet
-initialized the Google Cloud SDK, we recommend running the `gcloud init`
-command as described at https://cloud.google.com/sdk/docs/initializing
-Alternately, you may log in directly by running `gcloud auth login`.
+ report_error <<~MESSAGE
+ The gcloud authorization has not been completed. If you have not yet
+ initialized the Google Cloud SDK, we recommend running the `gcloud init`
+ command as described at https://cloud.google.com/sdk/docs/initializing
+ Alternately, you may log in directly by running `gcloud auth login`.
MESSAGE
rescue Util::Gcloud::ProjectNotSet
- report_error <<-MESSAGE
-The gcloud project configuration has not been set. If you have not yet
-initialized the Google Cloud SDK, we recommend running the `gcloud init`
-command as described at https://cloud.google.com/sdk/docs/initializing
-Alternately, you may set the default project configuration directly by
-running `gcloud config set project <project-name>`.
+ report_error <<~MESSAGE
+ The gcloud project configuration has not been set. If you have not yet
+ initialized the Google Cloud SDK, we recommend running the `gcloud init`
+ command as described at https://cloud.google.com/sdk/docs/initializing
+ Alternately, you may set the default project configuration directly by
+ running `gcloud config set project <project-name>`.
MESSAGE
end
def start_and_report_errors app_exec
app_exec.start
- rescue Exec::ConfigFileNotFound => ex
- report_error <<-MESSAGE
-Could not determine which service should run this command because the App
-Engine config file "#{ex.config_path}" was not found.
-Specify the config file using the GAE_CONFIG argument. e.g.
- bundle exec rake appengine:exec GAE_CONFIG=myapp.yaml -- myscript.sh
-Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
- bundle exec rake appengine:exec GAE_SERVICE=myservice -- myscript.sh
-MESSAGE
- rescue Exec::BadConfigFileFormat => ex
- report_error <<-MESSAGE
-Could not determine which service should run this command because the App
-Engine config file "#{ex.config_path}" was malformed.
-It must be a valid YAML file.
-Specify the config file using the GAE_CONFIG argument. e.g.
- bundle exec rake appengine:exec GAE_CONFIG=myapp.yaml -- myscript.sh
-Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
- bundle exec rake appengine:exec GAE_SERVICE=myservice -- myscript.sh
-MESSAGE
- rescue Exec::NoSuchVersion => ex
- if ex.version
- report_error <<-MESSAGE
-Could not find version "#{ex.version}" of service "#{ex.service}".
-Please double-check the version exists. To use the most recent version by
-default, omit the GAE_VERSION argument.
-MESSAGE
+ rescue Exec::ConfigFileNotFound => e
+ report_error <<~MESSAGE
+ Could not determine which service should run this command because the App
+ Engine config file "#{e.config_path}" was not found.
+ Specify the config file using the GAE_CONFIG argument. e.g.
+ bundle exec rake appengine:exec GAE_CONFIG=myapp.yaml -- myscript.sh
+ Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
+ bundle exec rake appengine:exec GAE_SERVICE=myservice -- myscript.sh
+ MESSAGE
+ rescue Exec::BadConfigFileFormat => e
+ report_error <<~MESSAGE
+ Could not determine which service should run this command because the App
+ Engine config file "#{e.config_path}" was malformed.
+ It must be a valid YAML file.
+ Specify the config file using the GAE_CONFIG argument. e.g.
+ bundle exec rake appengine:exec GAE_CONFIG=myapp.yaml -- myscript.sh
+ Alternately, you may specify a service name directly with GAE_SERVICE. e.g.
+ bundle exec rake appengine:exec GAE_SERVICE=myservice -- myscript.sh
+ MESSAGE
+ rescue Exec::NoSuchVersion => e
+ if e.version
+ report_error <<~MESSAGE
+ Could not find version "#{e.version}" of service "#{e.service}".
+ Please double-check the version exists. To use the most recent version by
+ default, omit the GAE_VERSION argument.
+ MESSAGE
else
- report_error <<-MESSAGE
-Could not find any versions of service "#{ex.service}".
-Please double-check that you have deployed this service. If you want to run
-a command against a different service, you may provide a GAE_CONFIG argument
-pointing to your App Engine config file, or a GAE_SERVICE argument to specify
-a service directly.
-MESSAGE
+ report_error <<~MESSAGE
+ Could not find any versions of service "#{e.service}".
+ Please double-check that you have deployed this service. If you want to run
+ a command against a different service, you may provide a GAE_CONFIG argument
+ pointing to your App Engine config file, or a GAE_SERVICE argument to specify
+ a service directly.
+ MESSAGE
end
- rescue Exec::ServiceNameConflict => ex
- report_error <<-MESSAGE
-The explicit service name "#{ex.service_name}" was requested
-but conflicts with the service "#{ex.config_name}" from the
-config file "#{ex.config_path}"
-You should specify either GAE_SERVICE or GAE_CONFIG but not both.
-MESSAGE
+ rescue Exec::NoDefaultProject
+ report_error <<~MESSAGE
+ Could not get the default project from gcloud.
+ Please either set the current project using
+ gcloud config set project my-project-id
+ or specify the project by setting the GAE_PROJECT argument. e.g.
+ bundle exec rake appengine:exec GAE_PROJECT=my-project-id -- myscript.sh
+ MESSAGE
+ rescue Exec::UsageError => e
+ report_error e.message
end
def report_error str
::STDERR.puts str
exit 1
end
-
end
-
end
end
-
::AppEngine::Tasks.define