英文:
Is it possible to use Go vendor libraries with Google App Engine?
问题
我正在尝试将一个小的测试应用程序部署到Google App Engine(标准版)。如果我包含任何供应商库,就会出现错误。
这是我在尝试部署时遇到的错误:
% gcloud app deploy
Services to deploy:
descriptor: [/Users/matt/work/appenginetest1/src/hello/default/app.yaml]
source: [/Users/matt/work/appenginetest1/src/hello/default]
target project: REDACTED
target service: [default]
target version: [20170709t220721]
target url: REDACTED
Do you want to continue (Y/n)? y
Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
go-app-builder: build timing: 2×compile (210ms total), 0×link (0s total)
go-app-builder: failed running compile: exit status 2
main.go:6: can't find import: "github.com/julienschmidt/httprouter"
为了提供一些背景信息,这是$GOPATH的目录树:
% tree $GOPATH
/Users/matt/work/appenginetest1
└── src
└── hello
├── default
│ ├── app.yaml
│ └── main.go
├── glide.lock
├── glide.yaml
└── vendor
└── github.com
└── julienschmidt
└── httprouter
├── path.go
├── router.go
└── tree.go
通过dev_appserver.py运行本地服务器可以正常工作。看起来不像是应用引擎找不到供应商目录的问题,因为在运行以下命令后:
% rm -rf ~/work/appenginetest1/src/hello/vendor/github.com
它在推送到云端之前就出现错误了:
% gcloud app deploy
ERROR: (gcloud.app.deploy) Staging command [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/platform/google_appengine/goroot-1.6/bin/go-app-stager /Users/matt/work/appenginetest1/src/hello/default/app.yaml /var/folders/nx/8w2_6q551cl50h3ff6lmy9s40000gn/T/tmp97Kiis/tmpe0MHQ0] failed with return code [1].
------------------------------------ STDOUT ------------------------------------
------------------------------------ STDERR ------------------------------------
2017/07/09 22:12:52 failed analyzing /Users/matt/work/appenginetest1/src/hello/default: cannot find package "github.com/julienschmidt/httprouter" in any of:
/Users/matt/work/appenginetest1/src/hello/vendor/github.com/julienschmidt/httprouter (vendor tree)
($GOROOT not set)
/Users/matt/work/appenginetest1/src/github.com/julienschmidt/httprouter (from $GOPATH)
GOPATH: /Users/matt/work/appenginetest1
--------------------------------------------------------------------------------
如果我将github.com目录从vendor移动到src,部署就可以正常工作。
app.yaml
service: default
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
main.go
package hello
import (
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"
)
func init() {
router := httprouter.New()
router.GET("/hello/:name", Hello)
http.Handle("/", router)
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "Hello, %s!", ps.ByName("name"))
}
如果我在运行glide install之后将github.com目录从vendor移动到src,我可以使这个项目部署成功。
英文:
I'm trying to deploy a small test app to Google App Engine (standard). I get an error if I include any vendor libraries.
This is the error I get when trying to deploy
% gcloud app deploy
Services to deploy:
descriptor: [/Users/matt/work/appenginetest1/src/hello/default/app.yaml]
source: [/Users/matt/work/appenginetest1/src/hello/default]
target project: REDACTED
target service: [default]
target version: [20170709t220721]
target url: REDACTED
Do you want to continue (Y/n)? y
Beginning deployment of service [default]...
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 0 files to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
go-app-builder: build timing: 2×compile (210ms total), 0×link (0s total)
go-app-builder: failed running compile: exit status 2
main.go:6: can't find import: "github.com/julienschmidt/httprouter"
For some context, this is the tree of $GOPATH
% tree $GOPATH
/Users/matt/work/appenginetest1
└── src
└── hello
├── default
│   ├── app.yaml
│   └── main.go
├── glide.lock
├── glide.yaml
└── vendor
└── github.com
└── julienschmidt
└── httprouter
├── path.go
├── router.go
└── tree.go
Running the local server via dev_appserver.py works fine. It doesn't look like a case of app engine not finding the vendor directory as after running
% rm -rf ~/work/appenginetest1/src/hello/vendor/github.com
It errors before even pushing to the cloud
% gcloud app deploy
ERROR: (gcloud.app.deploy) Staging command [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/platform/google_appengine/goroot-1.6/bin/go-app-stager /Users/matt/work/appenginetest1/src/hello/default/app.yaml /var/folders/nx/8w2_6q551cl50h3ff6lmy9s40000gn/T/tmp97Kiis/tmpe0MHQ0] failed with return code [1].
------------------------------------ STDOUT ------------------------------------
------------------------------------ STDERR ------------------------------------
2017/07/09 22:12:52 failed analyzing /Users/matt/work/appenginetest1/src/hello/default: cannot find package "github.com/julienschmidt/httprouter" in any of:
/Users/matt/work/appenginetest1/src/hello/vendor/github.com/julienschmidt/httprouter (vendor tree)
($GOROOT not set)
/Users/matt/work/appenginetest1/src/github.com/julienschmidt/httprouter (from $GOPATH)
GOPATH: /Users/matt/work/appenginetest1
--------------------------------------------------------------------------------
If I move the github.com directory from vendor to src, the deploy works without an issue.
app.yaml
service: default
runtime: go
api_version: go1
handlers:
- url: /.*
script: _go_app
main.go
package hello
import (
"fmt"
"net/http"
"github.com/julienschmidt/httprouter"
)
func init() {
router := httprouter.New()
router.GET("/hello/:name", Hello)
http.Handle("/", router)
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
fmt.Fprintf(w, "Hello, %s!", ps.ByName("name"))
}
I can get this project to deploy if I move the github.com directory from vendor to src after running glide install.
答案1
得分: 1
你可以通过使用$GOPATH
变量来解决这个问题。请注意,你的$GOPATH
环境变量实际上可以是多个位置的列表(详见https://golang.org/cmd/go/#hdr-GOPATH_environment_variable):
GOPATH
环境变量列出了查找Go代码的位置。在Unix上,该值是一个以冒号分隔的字符串。在Windows上,该值是一个以分号分隔的字符串。在Plan 9上,该值是一个列表。
与其将vendor
目录从vendor
移动到src
,你可以编写一个脚本,临时将vendor/github.com
目录添加到你的$GOPATH
环境变量中,执行部署操作,然后从环境变量中删除它。
英文:
You can address this by using your $GOPATH
variable. Note that your $GOPATH
environment variable can actually be a list of multiple places (see https://golang.org/cmd/go/#hdr-GOPATH_environment_variable for more):
> The GOPATH environment variable lists places to look for Go code. On
> Unix, the value is a colon-separated string. On Windows, the value is
> a semicolon-separated string. On Plan 9, the value is a list.
Rather than moving the github.com directory from vendor to src, you could write a script which temporarily adds the vendor/github.com
directory to your $GOPATH
environment variable, performs the deployment, and then removes it from the environment variable.
答案2
得分: 0
根据rudolph1024的回答,我使用的一种将项目推送到App Engine标准环境的方法是在makefile中添加几行代码。最简单的示例是:
GOPATH=./vendor gcloud app deploy
这样做的好处是可以使用Go社区标准的仓库布局(这里)而不是Google的布局(这里)。
App Engine标准环境要求app.yaml文件位于根目录下,并且所有的Go文件都在其下。所以你可以这样做:
cp -r cmd/ ../../cmd && cd ../../cmd && GOPATH=./vendor gcloud app deploy
有很多方法可以简化这个过程,但这个方法有效,并且给出了方法论的一般思路。
英文:
Following from the answer by rudolph1024 one method I use to push projects to app engine standard is to add a few lines in the make file. The most simple example being:
GOPATH=./vendor gcloud app deploy
This has the bonus of allowing you to use the go community standard repo layout from here instead of the google one here
app engine standard likes the app.yaml to be in the root directory and all go files under it will be used. So you can do something like
cp -r cmd/ ../../cmd && cd ../../cmd && GOPATH=./vendor gcloud app deploy
There are many ways to clean this up but this works and gives a general idea on the methodology.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论