2016-10-09 23 views
9

Tôi đang cố gắng giới thiệu Tìm nạp tiền (lưu trữ các phụ thuộc trong một thư mục có tên là vendor) vào một dự án App Engine hiện có. Tôi đã lưu trữ tất cả phụ thuộc vào thư mục nhà cung cấp (sử dụng Godep như một helper) và có vẻ đúng, nhưng chạy ứng dụng tại địa phương tôi nhận được lỗi sau:Tôi làm cách nào để thực hiện công việc bán hàng với Google App Engine?

go-app-builder: Failed parsing input: package "golang.org/x/net/context" is imported from multiple locations: "/Users/erik/go/src/github.com/xyz/abc/vendor/golang.org/x/net/context" and "/Users/erik/go/src/golang.org/x/net/context"

Tôi tin rằng hai địa điểm sẽ giải quyết đến cùng một vị trí, như ứng dụng Go nên tìm trong thư mục vendor trước tiên. Có cách nào để làm cho Appengine hiểu rằng cả hai phụ thuộc đều giống nhau không?

+0

Tôi đã nhìn thấy vấn đề này trong quá khứ, nó thường được giải quyết bằng cách đảm bảo rằng tất cả thư mục 'vendor' cho các kho lưu trữ mà tôi đang xây dựng được thiết lập đúng cách. Lệnh bạn đang chạy dẫn đến lỗi này là gì? – Aaron

+0

Lỗi này là từ dev_appserver.py. Nó có vẻ hợp lý để giả định các thư mục của nhà cung cấp không được thiết lập đúng, nhưng bạn có bất kỳ đầu mối nào không? Nó có vẻ ok với tôi và unittests của chúng tôi chạy mà không có bất kỳ vấn đề. – emidander

+0

Như tôi đã hiểu, công cụ 'go-app-builder' hoạt động hơi khác so với công cụ chuẩn đi để tạo thuận lợi cho các bản dựng cụ thể của App Engine, do đó có thể là lý do tại sao bạn thấy sự khác biệt trong hành vi. Bạn đang sử dụng phiên bản SDK nào? – Aaron

Trả lời

2

Tôi đã giải quyết được lỗi này bằng cách sử dụng govendor thay vì Godeps. Nguyên nhân gốc rễ dường như đã được rằng tài liệu tham khảo vendored với tài liệu tham khảo vendored của chính họ đã không được giải quyết một cách chính xác bởi Godeps.

Câu trả lời được cung cấp bởi Su-Au Hwang cũng chính xác - bạn phải giữ app.yaml riêng biệt với nguồn của bạn.

1

Tôi chỉ thực sự gặp sự cố này. Vấn đề xảy ra khi bạn đang sử dụng các công cụ App Engine để xây dựng bất kỳ gói nào nhập một cái gì đó đang sử dụng vendoring, nhưng gói bạn đang cố gắng chạy không có nhập trong thư mục vendor của nó.

Vì vậy, ví dụ, nếu tôi đang cố gắng để chạy gói foo, mà nhập khẩu gói bar, và cả hai đều sử dụng thư viện github.com/gorilla/mux, nếu kho bar có một thư mục có chứa vendor/ khỉ đột/MUX, nhưng foo gói không có gorilla mux trong thư mục vendor/, lỗi này sẽ xảy ra.

Lý do điều này xảy ra là các gói bar sẽ ưu tiên riêng của nó vendor gói trong một trong GOPATH, đó là những gì foo sẽ được sử dụng, gây ra một sự khác biệt trong vị trí thực tế của những con đường nhập khẩu.

Giải pháp mà tôi tìm thấy trong số này là đảm bảo rằng thư mục foo nằm trong số GOPATH và đã cài đặt đúng thư mục của nhà cung cấp. Điều quan trọng cần lưu ý là quy ước vendor/ chỉ hoạt động từ trong phạm vi GOPATH.

7

Thư mục dự án của bạn (trong đó app.yaml là) có thể nằm trong GOPATH/src. Không nên. Trình go-app-builder sẽ lấy mọi thứ trong thư mục app.yaml (và bên dưới) và bổ sung hợp nhất GOPATH của bạn vào nó, có nghĩa là bây giờ bạn có nó hai lần.

Giải pháp là di chuyển app.yaml ra khỏi thư mục GOPATH/src. Ngoài ra, bạn sẽ thấy rằng goapp test hoạt động khác với goapp servegoapp deploy khi nói đến giải quyết các phụ thuộc. Vì vậy, đây là giải pháp tôi đã sử dụng (đã không sử dụng công cụ ứng dụng golang trong một thời gian) và nó là thiết lập duy nhất tôi đã tìm thấy hoạt động đúng cho tất cả các lệnh goapp và cho govendor hoạt động đúng cách (không chắc chắn về godep)

/GOPATH 
├──/appengine 
| ├── app.yaml 
| └── aeloader.go 
└──/src 
    └── /MYPROJECT 
     ├── main.go 
     ├── /handler 
     | └── handler.go 
     └── /vendor 

chi tiết:

file: GOPATH/appengine/aeloader.go (NOTE the init function is necessary, probably a bug though) 
package mypackage 

import (
    _ "MYPROJECT" 
) 

func init() { 
} 

bây giờ chạy goapp servegoapp deploy từ ../GOPATH/appengine/goapp test ./... từ ../GOPATH/src/MYPROJECT

P.S. Tôi tìm thấy điều GOPATH toàn cầu ngớ ngẩn và chỉ cần đặt GOPATH của tôi vào thư mục dự án hiện tại (trong ví dụ trên /GOPATH) và kiểm tra toàn bộ điều đó trong điều khiển phiên bản.

+0

Đây là sự điên rồ. Bây giờ nó phải sống * bên ngoài * GOPATH? Nó kết thúc với việc xây dựng idiosyncracies ở đâu? Cảm ơn bạn mặc dù. Nghiêm túc. – hraban

+0

Câu trả lời hay.Tôi đã tạo một ứng dụng đơn giản trên GitHub để kiểm tra phương pháp này, nó hoạt động: https://github.com/nikolay-turpitko/x-gae-dep –

1

Cũng gặp vấn đề tương tự. Trong docs Google gợi ý như sau:

For best results, we recommend the following:

  • Create a separate directory in your app's directory for each service.
  • Each service's directory should contain the service's app.yaml file and one or more .go files.
  • Do not include any subdirectories in a service's directory.
  • Your GOPATH should specify a directory that is outside your app's directory and contain all the dependencies that your app imports.

Nhưng điều này messes lên cấu trúc dự án của tôi, trông như thế này:

GOPATH/ 
└── src 
    └── github.com 
     └── username 
      └── myproject 
       ├── app.yaml 
       ├── cmd 
       │   └── myproject 
       │    └── main.go 
       ├── handlers 
       │   └── api.go 
       ├── mw 
       │   ├── auth.go 
       │   └── logger.go 
       └── vendor 

Trong trường hợp thư mục myproject là một dự án git và vendor thư mục chứa tất cả phụ thuộc. Chạy gcloud deploy từ myproject thư mục nơi app.yaml cuộc sống tập không hiệu quả vì đầu tiên, main.go tập tin không nằm trong cùng một thư mục và thứ hai (từ doc giống nhau):

you must be careful not to place your source code at or below your app's directory where the app.yaml file is located

Những gì tôi đã kết thúc làm đang xây dựng của tôi thay vào đó là thời gian chạy tùy chỉnh của riêng mình, hóa ra đó là một giải pháp rất sạch sẽ.
Đơn giản chỉ cần tạo ra Dockerfile với lệnh sau đây:

gcloud beta app gen-config --custom 

Sửa đổi nó, sau đó chỉ định runtime: custom trong app.yaml bạn và triển khai bình thường.
Bí quyết ở đây tất nhiên là bạn có quyền kiểm soát những gì được sao chép ở đâu.
Đây là tôi Dockerfile:

# Dockerfile extending the generic Go image with application files for a 
# single application. 
FROM gcr.io/google-appengine/golang 

ENV GOPATH /go 

# The files which are copied are specified in the .dockerignore file 
COPY . /go/src/github.com/username/myproject/ 

WORKDIR /go/src/github.com/username/myproject/ 

RUN go build -o dist/bin/myproject ./cmd/myproject 

# All configuration parameters are passed through environment variables and specified in app.yaml 
CMD ["/go/src/github.com/username/myproject/dist/bin/myproject"] 

Đừng quên rằng App Engine hy vọng ứng dụng của bạn lắng nghe trên cổng 8080. Kiểm tra Building Custom Runtimes doc để biết thêm chi tiết.

0

Tôi sử dụng tập lệnh bash đơn giản hoặc Makefile làm giải pháp thay thế.

TMPGOPATH := $(shell mktemp -d) 

deploy: 
    cp -r vendor/ $(TMPGOPATH)/src 
    GOPATH=$(TMPGOPATH) gcloud app deploy 
    rm -fr $(TMPGOPATH) 

tôi lưu trữ này Makefile tại thư mục gốc của dịch vụ của tôi gần mục vendor/ và chỉ cần sử dụng make deploy để triển khai thủ công hoặc từ CI.

Nó hoạt động với Glide, Godeps hoặc bất kỳ công cụ nào tôn trọng đặc điểm của nhà cung cấp dịch vụ Go.

Các vấn đề liên quan