GoogleCloudPlatform / functions-framework-go

FaaS (Function as a service) framework for writing portable Go functions
https://godoc.org/github.com/GoogleCloudPlatform/functions-framework-go
Apache License 2.0
464 stars 63 forks source link

Cloud Function Gen2 error when using vendor dependencies #162

Closed TheAxZim closed 1 year ago

TheAxZim commented 2 years ago

Hi, I'm having some errors using go mod vendor when deploying a gen2 cloud function.

I'm using https://github.com/GoogleCloudPlatform/golang-samples/blob/main/functions/functionsv2/hellopubsub/hello_pubsub.go with changes to the function name and registered Entry point.

module examplemodule

go 1.16

require (
    github.com/GoogleCloudPlatform/functions-framework-go v1.6.1
    github.com/cloudevents/sdk-go/v2 v2.12.0
)

If I use go mod vendor before deploying, here is the error I receive.

ERROR: (gcloud.beta.functions.deploy) OperationError: code=3, message=Build failed with status: FAILURE and message: vendor/functions.local/app/main.go:19:2: cannot find package "." in:
        /workspace/serverless_function_source_code/vendor/github.com/GoogleCloudPlatform/functions-framework-go/funcframework.

If I leave out go mod vendor, it works without any issues and my Cloud Function is deployed with no issues. As long as I don't submit my vendor folder...Any help would be appreciated.

Edit: Wanted to clarify that I'm using the vendor folder because I'd like to package my private dependencies in the cloud function later.

TheAxZim commented 2 years ago

As a note, I believe I've managed to resolve this issue. But need to confirm with a private dependency later.

I added a .gcloudignore file to ignore as shown below:

go.mod
go.sum

This way, the .mod and .sum files are not uploaded. Only the vendor folder is, which should be used alongside the function.

martesoid11 commented 1 year ago

Hi, I also experienced a similar issue. Here's the workaround that I found:

I'm trying to use vendor directories in a CF (v2 using golang 1.19), but the command gcloud functions deploy results in the same error:

OperationError: code=3, message=Build failed with status: FAILURE and message: vendor/functions.local/app/main.go:19:2: cannot find package "." in:
        /workspace/serverless_function_source_code/vendor/github.com/GoogleCloudPlatform/functions-framework-go/funcframework.

In my case, adding the go.mod and go.sum files to .gcloudignore solves the error above, and I'm able to deploy the function. Nonetheless, my function returns 404 errors whenever I call it. Considering that the documentation recommends that the .gcloudignore path should be used for versions < 1.16, I determined that I shouldn't be using that option and decided to troubleshoot the cannot find package error instead.

For troubleshooting, I used a helloworld sample provided by the GCP documentation. The steps that I followed to consistently replicate the error were:

  1. Clone sample app
  2. Set my directory to where the same app is contained
  3. Run the go mod vendor command
  4. Run the following gcloud deploy command:
    gcloud functions deploy go-http-function-vendor --gen2 --runtime=go119 --region=us-central1 --source=. --entry-point=HelloGet --trigger-http --allow-unauthenticated

    This consistently resulted in the cannot find package error. Note that skipping the step 3 resulted in no errors during deployment, and the CF was able to serve requests without any problem.

For me, the error can be solved by adding the github.com/GoogleCloudPlatform/functions-framework-go/funcframework package to the list of dependencies to be downloaded by go mod vendor. We achieved a successful deployment of a function with vendor directory doing the following:

  1. Clone sample app
  2. Set directory to where the same app is contained
  3. Add the github.com/GoogleCloudPlatform/functions-framework-go/funcframework package to the helloworld.go file
  4. Run the go mod tidy command
  5. Run the go mod vendor command
  6. Delete the github.com/GoogleCloudPlatform/functions-framework-go/funcframework line from the helloworld.go file
  7. Run the gcloud deploy command:
    gcloud functions deploy go-http-function-vendor --gen2 --runtime=go119 --region=us-central1 --source=. --entry-point=HelloGet --trigger-http --allow-unauthenticated
garethgeorge commented 1 year ago

Thanks for the detailed bug reports and investigation that you both have done! It's greatly appreciated and really made my investigation to understand this issue easy. I've been able to reproduce the issue as well as both of the workarounds reported in this thread both on Google Cloud Platform and with our buildpacks.

I'd like to +1 @martesoid11 's workaround as a good fix in the short term as it is close to doing what our functions framework builder should be (and I expect it to be forward compatible with the fix). I think that fix can be refined slightly to include that you don't need to remove any dependencies between running go mod vendor and deploying your function.

Short term workaround:

  1. Introduce function framework dependencies
    _ "github.com/GoogleCloudPlatform/functions-framework-go/funcframework"
    "github.com/GoogleCloudPlatform/functions-framework-go/functions"
  2. go mod vendor
  3. Deploy your function, no need to delete the funcframework import first.

Introducing the unused dependency on funcframework tricks go mod vendor into downloading the package that is later used by code our build system adds but is not installed correctly, we'll work on fixing that properly upstream so this workaround won't be needed.

garethgeorge commented 1 year ago

We have released an updated version of the function framework Go buildpack which gives a much more intuitive error message when the dependency on github.com/GoogleCloudPlatform/functions-framework-go/funcframework is missing and provides instructions for installing it.

For future readers, see https://cloud.google.com/functions/docs/writing/specifying-dependencies-go#specify_dependencies_with_a_vendor_directory for instructions on using vendor dependencies. We've settled on keeping an explicit dependency on _ "github.com/GoogleCloudPlatform/functions-framework-go/funcframework" as the proper approach.