【问题标题】:gcloud app deploy fails "cannot import internal package"gcloud app deploy 失败“无法导入内部包”
【发布时间】:2017-09-19 08:25:10
【问题描述】:

我正在编译一个 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” "

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"

我可以正常运行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: 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"

gcloud app deploy 却抱怨根本找不到包:

[...]
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

编辑解决方法:我发现我可以通过将供应商目录(github.comgolang.org)符号链接到应用程序目录(ln -s ../vendor/* .),并手动下载 appengine 包(go get google.golang.org/appengine)。但是,我需要删除符号链接才能运行dev_appserver.py,所以这不是最佳的。

【问题讨论】:

    标签: google-app-engine go gcloud


    【解决方案1】:

    发生这种情况的原因是 App Engine 构建 Go 应用的方式。

    由于 App Engine 标准环境 security sandbox 和容器模型,它们禁止 Go 代码导入任何可能会干扰其系统的包,例如 unsafe。出于同样的原因,它们还阻止直接导入内部 appengine 包 (google.golang.org/appengine/internal/whatever)。

    对于这个项目,您已经在本地供应了您的依赖项。但是,对于应用程序引擎应用程序构建器来说,这看起来与您刚刚在应用程序中创建另一个子包并将依赖项放在那里没有什么不同。它的功能与您刚刚将appengine/search 直接复制并粘贴到您的项目中一样。

    因为appengine/search 导入其对应的内部包appengine/internal/search,并且Go 应用程序构建器并没有真正区分应用程序代码中的内容和vendor 目录中的内容,因此构建失败。对于 App Engine,you 看起来像是导入了 appengine/internal/search,这是安全模型所禁止的。它不知道appengine/internal/search 是如何被使用的,因为它不控制vendor 中的内容,所以为了保证沙盒的安全,它不允许你导入它。

    这个问题的解决方案基本上是不提供您的依赖项。

    如果您从vendor 中删除所有appengine/whatever 包,则App Engine 构建器将在Google 的构建服务器上而不是在您的项目中查找它们。 App Builder 相信自己的 appengine 库的本地副本不会出现错误行为,因此允许它们导入 appengine/whatever/internal 包。

    (顺便说一句,如果您还没有,请确保 gcloud 和所有相关组件都是最新的。这有时可以解决棘手的依赖问题)

    【讨论】:

    • 这很好地解释了部署案例,谢谢。问题是我无法让 appserver 在本地运行 供应库,我想找到一种方法可以同时运行而不会弄乱符号链接和移动东西。
    • 我之前遇到过这个问题——我记得一个特别笨拙的解决方案是将 go get 依赖项直接添加到 appengine 的本地 $GOROOT 中。不过,我认为,最终为我修复它的是对 gcloud 和所有组件的更新。
    • 如果你使用 cloudbuild 来部署你的应用程序 vendoring 是可以的
    猜你喜欢
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-27
    • 2020-09-03
    • 2019-03-22
    • 1970-01-01
    相关资源
    最近更新 更多