可以在Google App Engine中使用Go供应商库吗?

huangapple go评论70阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2017年7月9日 21:15:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/44996818.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定