github.com/fnproject/cli@v0.0.0-20240508150455-e5d88bd86117/langs/go.go (about) 1 /* 2 * Copyright (c) 2019, 2020 Oracle and/or its affiliates. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package langs 18 19 import ( 20 "errors" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "path/filepath" 25 ) 26 27 type GoLangHelper struct { 28 BaseHelper 29 Version string 30 } 31 32 func (h *GoLangHelper) Handles(lang string) bool { 33 return defaultHandles(h, lang) 34 } 35 func (h *GoLangHelper) Runtime() string { 36 return h.LangStrings()[0] 37 } 38 39 func (h *GoLangHelper) CustomMemory() uint64 { 40 return 0 41 } 42 43 func (lh *GoLangHelper) LangStrings() []string { 44 return []string{"go", fmt.Sprintf("go%s", lh.Version)} 45 } 46 func (lh *GoLangHelper) Extensions() []string { 47 return []string{".go"} 48 } 49 50 func (lh *GoLangHelper) BuildFromImage() (string, error) { 51 return fmt.Sprintf("fnproject/go:%s-dev", lh.Version), nil 52 } 53 54 func (lh *GoLangHelper) RunFromImage() (string, error) { 55 return fmt.Sprintf("fnproject/go:%s", lh.Version), nil 56 } 57 58 func (h *GoLangHelper) DockerfileBuildCmds() []string { 59 r := []string{} 60 // more info on Go multi-stage builds: https://medium.com/travis-on-docker/multi-stage-docker-builds-for-creating-tiny-go-images-e0e1867efe5a 61 // TODO: if we keep the go.sum on user's drive, we can put this after the dep commands and then the dep layers will be cached. 62 vendor := exists("vendor/") 63 // skip dep tool install if vendor is there 64 if !vendor && exists("Gopkg.toml") { 65 r = append(r, "RUN go get -u github.com/golang/dep/cmd/dep") 66 if exists("Gopkg.lock") { 67 r = append(r, "ADD Gopkg.* /go/src/func/") 68 r = append(r, "RUN cd /go/src/func/ && dep ensure --vendor-only") 69 r = append(r, "ADD . /go/src/func/") 70 } else { 71 r = append(r, "ADD . /go/src/func/") 72 r = append(r, "RUN cd /go/src/func/ && dep ensure") 73 } 74 } else if exists("go.mod") { 75 r = append(r, "WORKDIR /go/src/func/") 76 r = append(r, "ENV GO111MODULE=on") 77 if vendor { 78 r = append(r, "ENV GOFLAGS=\"-mod=vendor\"") 79 } 80 r = append(r, "COPY . .") 81 r = append(r, "RUN go mod tidy") 82 } else { 83 r = append(r, "ADD . /go/src/func/") 84 } 85 86 r = append(r, "RUN go build -o func -v") 87 88 return r 89 } 90 91 func (h *GoLangHelper) DockerfileCopyCmds() []string { 92 return []string{ 93 "COPY --from=build-stage /go/src/func/func /function/", 94 } 95 } 96 97 func (lh *GoLangHelper) Entrypoint() (string, error) { 98 return "./func", nil 99 } 100 101 func (lh *GoLangHelper) HasBoilerplate() bool { return true } 102 103 func (lh *GoLangHelper) GenerateBoilerplate(path string) error { 104 codeFile := filepath.Join(path, "func.go") 105 if exists(codeFile) { 106 return errors.New("func.go already exists, canceling init") 107 } 108 if err := ioutil.WriteFile(codeFile, []byte(helloGoSrcBoilerplate), os.FileMode(0644)); err != nil { 109 return err 110 } 111 modFile := "go.mod" 112 fdkVersion, _ := lh.GetLatestFDKVersion() 113 if err := ioutil.WriteFile(modFile, []byte(fmt.Sprintf(modBoilerplate, fdkVersion)), os.FileMode(0644)); err != nil { 114 return err 115 } 116 117 return nil 118 } 119 120 func (h *GoLangHelper) GetLatestFDKVersion() (string, error) { 121 return getLatestFDKVersionFromGithub("fnproject/fdk-go") 122 } 123 124 const ( 125 helloGoSrcBoilerplate = `package main 126 127 import ( 128 "context" 129 "encoding/json" 130 "fmt" 131 "io" 132 "log" 133 134 fdk "github.com/fnproject/fdk-go" 135 ) 136 137 func main() { 138 fdk.Handle(fdk.HandlerFunc(myHandler)) 139 } 140 141 type Person struct { 142 Name string ` + "`json:\"name\"`" + ` 143 } 144 145 func myHandler(ctx context.Context, in io.Reader, out io.Writer) { 146 p := &Person{Name: "World"} 147 json.NewDecoder(in).Decode(p) 148 msg := struct { 149 Msg string ` + "`json:\"message\"`" + ` 150 }{ 151 Msg: fmt.Sprintf("Hello %s", p.Name), 152 } 153 log.Print("Inside Go Hello World function") 154 json.NewEncoder(out).Encode(&msg) 155 } 156 ` 157 158 modBoilerplate = ` 159 module func 160 161 require github.com/fnproject/fdk-go %s 162 ` 163 ) 164 165 func (h *GoLangHelper) FixImagesOnInit() bool { 166 return true 167 }