英文:
gcloud app deploy fails "cannot import internal package"
问题
我正在编译一个GO应用程序,我想要将其上传并在Google Cloud Platform上运行。我正在导入appengine/datastore
包,并且在包的依赖项中遇到了一些问题。由于我想要提供稳定的构建,我希望在我的源代码树中有尽可能多的依赖项,但是当我将appengine/datastore
作为依赖项时,运行gcloud app deploy
时遇到了问题:
OperationError: 错误响应:[9] 部署包含无法编译的文件:编译失败:
2017/09/19 01:07:31 go-app-builder: 解析输入失败:包“vendor/google.golang.org/appengine/search”无法导入内部包“google.golang.org/appengine/internal/search”
错误:(gcloud.app.deploy) 错误响应:[9] 部署包含无法编译的文件:编译失败:
2017/09/19 01:07:31 go-app-builder: 解析输入失败:包“vendor/google.golang.org/appengine/search”无法导入内部包“google.golang.org/appengine/internal/search”
我可以成功运行dev_appserver.py
脚本,应用程序在本地平稳运行,并且go test
成功编译和运行了所有模块测试。
如果我尝试删除任何appengine包的依赖项,并使用go get
在版本控制之外安装它们,dev_appserver.py
将不再运行,并抱怨有重复的包:
rm -rf ../vendor/google.golang.org/appengine
go get google.golang.org/appengine
dev_appserver.py app.yaml
[....]
2017/09/19 10:20:10 go-app-builder: 解析输入失败:包“golang.org/x/net/context”从多个位置导入:“/home/peter/src/myproject/go/src/myproject/vendor/golang.org/x/net/context”和“/home/peter/src/myproject/go/src/golang.org/x/net/context”
而gcloud app deploy
则抱怨根本找不到这些包:
[...]
文件上传完成。
正在更新服务[default]...失败。
错误:(gcloud.app.deploy) 错误响应:[9] 部署包含无法编译的文件:编译失败:
编译失败:
2017/09/19 01:22:13 go-app-builder: 构建时间:7×编译(总计1.749秒),0×链接(总计0秒)
2017/09/19 01:22:13 go-app-builder: 编译运行失败:退出状态2
myproject/vendor/golang.org/x/text/unicode/norm/normalize.go:15: 找不到导入:“golang.org/x/text/transform”
$ find .. -name transform
../vendor/golang.org/x/text/transform
编辑:解决方法:我发现通过将供应商目录(github.com
和golang.org
)符号链接到应用程序目录(ln -s ../vendor/* .
),并手动下载appengine包(go get google.golang.org/appengine
),可以使其与gcloud
编译。但是,我需要删除符号链接才能运行dev_appserver.py
,所以这并不是最佳解决方案。
英文:
I am compiling a GO app that I want to upload and run on the Google Cloud Platform. I am importing the appengine/datastore
package and am running into problems with vendoring of the packages. Since I want to provide stable builds I want to have as much of the dependencies vendored in my source tree, but when I vendor appengine/datastore
I run in to problems runnning gcloud app deploy
:
OperationError: Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
2017/09/19 01:07:31 go-app-builder: Failed parsing input: package "vendor/google.golang.org/appengine/search" cannot import internal package "google.golang.org/appengine/internal/search"
ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
2017/09/19 01:07:31 go-app-builder: Failed parsing input: package "vendor/google.golang.org/appengine/search" cannot import internal package "google.golang.org/appengine/internal/search"
I can run the dev_appserver.py
script just fine, the application runs smoothly locally, and go test
succeeds compiling and running all the module tests.
If I try to remove the vendoring of any of the appengine packages and instead use go get
to install them outside of the version control, dev_appserver.py
no longer runs, complaining about duplicate packages:
rm -rf ../vendor/google.golang.org/appengine
go get google.golang.org/appengine
dev_appserver.py app.yaml
[....]
2017/09/19 10:20:10 go-app-builder: Failed parsing input: package "golang.org/x/net/context" is imported from multiple locations: "/home/peter/src/myproject/go/src/myproject/vendor/golang.org/x/net/context" and "/home/peter/src/myproject/go/src/golang.org/x/net/context"
while gcloud app deploy
instead complains about not finding the packages at all:
[...]
File upload done.
Updating service [default]...failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Deployment contains files that cannot be compiled: Compile failed:
Compile failed:
2017/09/19 01:22:13 go-app-builder: build timing: 7×compile (1.749s total), 0×link (0s total)
2017/09/19 01:22:13 go-app-builder: failed running compile: exit status 2
myproject/vendor/golang.org/x/text/unicode/norm/normalize.go:15: can't find import: "golang.org/x/text/transform"
$ find .. -name transform
../vendor/golang.org/x/text/transform
EDIT: WORKAROUND: I have found that I can make it compile with gcloud
by symlinking the vendored directories (github.com
and golang.org
) into the application directory (ln -s ../vendor/* .
), and downloading the appengine package manually (go get google.golang.org/appengine
). However, I need to delete the symlinks to be able to run dev_appserver.py
, so this is not nearly optimal.
答案1
得分: 3
这种情况发生的原因是因为App Engine构建Go应用程序的方式。
由于App Engine标准环境的安全沙箱和容器模型,它们禁止Go代码导入可能干扰其系统的任何包,比如unsafe
。它们还出于同样的原因阻止直接导入内部的appengine包(google.golang.org/appengine/internal/whatever
)。
对于这个项目,你已经在本地存储了你的依赖项。然而,对于App Engine应用程序构建器来说,这看起来与你只是在应用程序中创建了另一个子包并将依赖项放在其中没有什么不同。从功能上讲,这与你直接将appengine/search
复制粘贴到你的项目中是一样的。
因为appengine/search
导入了它对应的内部包appengine/internal/search
,而Go应用程序构建器在你的应用程序代码和vendor
目录中的内容之间并没有真正区分,所以构建失败了。对于App Engine来说,它看起来好像是你导入了appengine/internal/search
,而这是安全模型所禁止的。它不知道appengine/internal/search
的使用方式,因为它无法控制vendor
中的内容,所以为了保持沙箱的安全性,它不允许你导入它。
解决这个问题的方法基本上是不要将你的依赖项存储在vendor
中。
如果你从vendor
中移除所有的appengine/whatever
包,那么App Engine构建器将在Google的构建服务器上查找它们,而不是在你的项目中查找。应用程序构建器相信它自己本地的appengine
库不会出现问题,所以它们被允许导入appengine/whatever/internal
包。
(顺便说一句,如果你还没有这样做,请确保gcloud
和所有相关组件都是最新的。这有时可以解决棘手的依赖问题)
英文:
The reason this happens is because of how App Engine builds Go apps.
Because of the App Engine standard environment security sandbox and container model, they prohibit Go code from importing any packages which could potentially mess with their systems--like unsafe
, for instance. They also block direct imports of the internal appengine packages (google.golang.org/appengine/internal/whatever
) for the same reason.
For this project, you've locally vendored your dependencies. For the app engine app builder, though, this looks no different then if you had just made another sub-package in your app and put the dependencies in there. It's functionally the same as if you had just copied and pasted appengine/search
straight into your project.
Because appengine/search
imports its corresponding internal package, appengine/internal/search
, and the Go app builder doesn't really differentiate between what's in your application code and what's in your vendor
directory, it fails the build. To App Engine, it looks like you imported appengine/internal/search
, which is prohibited by the security model. It doesn't know how appengine/internal/search
is being used, because it doesn't control what's in vendor
, so to keep the sandbox secure it doesn't let you import it.
The solution to this problem is, basically, to not vendor your dependencies.
If you remove all the appengine/whatever
packages from vendor
, then the App Engine builder will look for them on Google's build servers instead of in your project. The App Builder trusts its own local copies of the appengine
libraries not to misbehave, so they're permitted to import appengine/whatever/internal
packages.
(As an aside, if you haven't already, make sure gcloud
and all related components are up to date. This can sometimes resolve gnarly dependency issues)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论