golang-http-template: Unable to use vendoring with golang-http
Why do you need this?
I need to be able to use vendoring with the golang-http template because it is how I get private Go code into my functions.
Expected Behaviour
This should work without error, when using a vendor folder and any other stack.yml flags or build-args required:
faas-cli build
Current Behaviour
Step 29/42 : RUN ${GO} build --ldflags "-s -w" -a -installsuffix cgo -o handler .
---> Running in b9e5d187d314
Setting vendor mode env variables
main.go:18:2: cannot find package "github.com/openfaas/templates-sdk/go-http" in any of:
/usr/local/go/src/github.com/openfaas/templates-sdk/go-http (from $GOROOT)
/go/src/github.com/openfaas/templates-sdk/go-http (from $GOPATH)
The command '/bin/sh -c ${GO} build --ldflags "-s -w" -a -installsuffix cgo -o handler .' returned a non-zero code: 1
[0] < Building go1 done in 5.91s.
[0] Worker done.
Total build time: 5.91s
Errors received during build:
- [go1] received non-zero exit code from build, error: The command '/bin/sh -c ${GO} build --ldflags "-s -w" -a -installsuffix cgo -o handler .' returned a non-zero code: 1
List All Possible Solutions and Workarounds
- Create a new separate template
golang-http-vendoringthat only works with vendoring - Stop maintaining a golang-http template at all, migrate everyone to golang-middleware
- Use interfaces instead of structs, so that the main.go module doesn’t have to reference the SDK, which seems to be the source of the problem - full example, and it’s a breaking change: https://github.com/alexellis/golang-http-template
- Consider a new direction that looks like AWS Lambda’s Go handler - https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html
- Use Go’s plugin capability, to build the function and entry point separately, and link them after the fact. Unfortunately this seems to require CGO and breaks portability - https://github.com/golang/go/issues/19569
For 4), the function’s handler owns the main() entrypoint instead of the hidden underlying code, and calls a utility method to set up the HTTP server etc.
package main
import (
"fmt"
"context"
"github.com/openfaas/golang-http/entrypoint"
)
type MyEvent struct {
Name string `json:"name"`
}
func HandleRequest(ctx context.Context, name MyEvent) (string, error) {
return fmt.Sprintf("Hello %s!", name.Name ), nil
}
func main() {
entrypoint.Start(HandleRequest)
}
For 3), the code would end up looking like this for a handler:
(this can be compared to the second code sample to see what’s different)
package function
import (
"fmt"
"net/http"
gohttp "github.com/alexellis/templates-sdk/go-http"
logrus "github.com/sirupsen/logrus"
)
// Handle a function invocation
func Handle(req gohttp.Request) (gohttp.Response, error) {
var err error
logrus.Info("Value of body: ", string(req.GetBody()))
message := fmt.Sprintf("Body: %s", string(req.GetBody()))
return &gohttp.FunctionResponse{
Body: []byte(message),
StatusCode: http.StatusOK,
}, err
}
What is your preferred solution?
I like 3) and to lessen its impact to existing users, we could consider promoting golang-http into the primary community templates repository and deprecating the one we use here.
Alternatively, we could call it "go-http1.18orgolang-http1.18as a new template, withgolang-http1.19` and so on coming after that.
Steps to Reproduce (for bugs)
faas-cli template store pull golang-http-template
faas-cli new --lang golang-http --prefix alexellis2 withlogrus
Edit withlogrus/handler.go:
package function
import (
"fmt"
"io"
"net/http"
"github.com/sirupsen/logrus"
)
func Handle(w http.ResponseWriter, r *http.Request) {
var input []byte
if r.Body != nil {
defer r.Body.Close()
body, _ := io.ReadAll(r.Body)
input = body
}
logrus.Debug(fmt.Sprintf("Handle; %q", input))
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("Body: %q", string(input))))
}
Then edit withlogrus.yml, adding:
build_args:
GO111MODULE: off
GOFLAGS: "-mod=vendor"
Then try a build:
cd golang-http-template
go get
go mod vendor
cd ..
faas-cli build -f withlogrus.yml
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 16 (12 by maintainers)
Commits related to this issue
- Fix vendoring for golang-http Tested with a private Go module which was vendored, setting GO111MODULE: off in build_args in stack.yml I also created a nested package called pkg and referenced it as ... — committed to openfaas/golang-http-template by alexellis 2 years ago
- Fix vendoring for golang-http Tested with a private Go module which was vendored, setting GO111MODULE: off in build_args in stack.yml I also created a nested package called pkg and referenced it as ... — committed to openfaas/golang-http-template by alexellis 2 years ago
- Fix vendoring for golang-http Tested with a private Go module which was vendored, setting GO111MODULE: off in build_args in stack.yml I also created a nested package called pkg and referenced it as ... — committed to openfaas/golang-http-template by alexellis 2 years ago
- Fix vendoring for golang-http Tested with a private Go module which was vendored, setting GO111MODULE: off in build_args in stack.yml I also created a nested package called pkg and referenced it as ... — committed to openfaas/golang-http-template by alexellis 2 years ago
- Fix vendoring for golang-http Tested with a private Go module which was vendored, setting GO111MODULE: off in build_args in stack.yml I also created a nested package called pkg and referenced it as ... — committed to openfaas/golang-http-template by alexellis 2 years ago
@alexellis and @MrWormHole
I think after a lot of time thinking on this, that just reverting to the previous behavior before workspaces makes the most sense. I am not a purist on this, if a little bash makes the template work smoothly for 99% of use-cases, then let’s use some bash. Especially because the bash script is just calling some
go mod editcommands vs directly editing the files, it is relatively stable.Originally, I thought the workspaces would allow us to really remove the bash scripts, but they don’t seem to work as expected.
I have prepared a branch for re-adding the bash scripts and tested it against my golang template sandbox https://github.com/LucasRoesler/golang-http-template-examples it seems to behave well. But I could be missing an important test case, so please take a look and let me know.
Here is the branch I created https://github.com/openfaas/golang-http-template/compare/master...LucasRoesler:feat-revert-to-bash-scripts?expand=1
As an aside, but something I saw in the conversation above. In general, I would expect most projects to use only one or the other template, not a mix of both. Just for code consistency in the project to ease the developer experience, I would avoid mixing and matching templates within a project. Within an organization, sure use whichever fits best for your project, but stick with just one for a project.
It looks like we have three main options for going forward.
I’d be interested in speed differences between 2 and 3 for an uncached container build, or one with
--no-cachepassed in.Alex
i will just make the changes whenever needed and roll the new ones out. Maintaining a classic may be a good idea but everyone has to change anyway since it’s a core go problem. With enough notice and planned upgrade it shouldn’t be an issue.