diff --git a/Dockerfile b/Dockerfile index ec41b44eb747545bf6ae84c2230cfd28f7c47c41..7f502471536c343db811715e2a80ebb817ef8064 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,6 +14,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ GOOS=linux go build -o orchestrator ./cmd/csbi/main.go FROM golang:1.16-alpine +RUN apk add --no-cache git make build-base +RUN apk add --update --no-cache alpine-sdk COPY --from=builder /build/orchestrator . COPY --from=builder /build/models ./models COPY --from=builder /build/resources ./resources diff --git a/generate.go b/generate.go index bcdfbecbc766661e97e917253642f8e2124dc475..52afe888a81bb71d4d728a4246d27c8a188b61b6 100644 --- a/generate.go +++ b/generate.go @@ -3,7 +3,6 @@ package csbi import ( "fmt" "io/fs" - "os" "path/filepath" "strings" @@ -17,33 +16,8 @@ import ( log "github.com/sirupsen/logrus" ) -var csbiDockerfile []string - func init() { log.SetReportCaller(true) - gitlabToken := os.Getenv("GITLAB_ACCESS_TOKEN") - csbiDockerfile = []string{ - "# syntax = docker/dockerfile:1.2", - "FROM golang:1.16-alpine AS builder", - "ARG GITLAB_USER", - "ARG GITLAB_TOKEN", - "WORKDIR /src/csbi", - "RUN apk add --no-cache git", - "RUN git config --global url.\"https://csbi-develop:" + gitlabToken + "@code.fbi.h-da.de\".insteadOf \"https://code.fbi.h-da.de\"", - "RUN go env -w GOPRIVATE=code.fbi.h-da.de/*", - "COPY go.mod .", - "COPY go.sum .", - "RUN go mod download", - "COPY . .", - "RUN GOOS=linux go build -o csbi", - - "FROM alpine", - "COPY --from=builder /src/csbi/csbi .", - "COPY --from=builder /src/csbi/.csbi.toml .", - "EXPOSE 6030", - "ENTRYPOINT [ \"./csbi\" ]", - "CMD [\"\"]", - } } // Generate takes gnmi.ModelData, a Repository, and an southbound.Type diff --git a/resources/Dockerfile b/resources/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..a553836c15fbaa11a5d8b8776054c5c8871cd058 --- /dev/null +++ b/resources/Dockerfile @@ -0,0 +1,18 @@ +# syntax = docker/dockerfile:1.2 +FROM golang:1.16-alpine AS build +ARG GITLAB_USER +ARG GITLAB_TOKEN +WORKDIR /src/csbi +RUN apk add --no-cache git +COPY go.mod . +COPY go.sum . +RUN go mod download +COPY . . +RUN GOOS=linux go build -o csbi + +FROM alpine +COPY --from=builder /src/csbi/cs . +COPY --from=builder /src/csbi/.ci.toml . +EXPOSE 6030 +ENTRYPOINT [ \"./csbi\" ] +CMD [\"\"] \ No newline at end of file diff --git a/resources/plugin_deps.json b/resources/plugin_deps.json new file mode 100644 index 0000000000000000000000000000000000000000..8c1fb4346ee1a0b4d8050c8aca299ff4aaaa1862 --- /dev/null +++ b/resources/plugin_deps.json @@ -0,0 +1,30 @@ +{ + "name": "code.fbi.h-da.de/danet/plugin-sbi", + "go_version": "1.16", + "dependencies": [ + { + "name": "code.fbi.h-da.de/danet/api", + "version": "thesis-mk" + }, + { + "name": "github.com/google/uuid", + "version":"v1.2.0" + }, + { + "name": "github.com/openconfig/gnmi", + "version":"v0.0.0-20210707145734-c69a5df04b53" + }, + { + "name": "github.com/openconfig/goyang", + "version":"v0.2.7" + }, + { + "name": "github.com/openconfig/ygot", + "version":"v0.11.2" + }, + { + "name": "github.com/sirupsen/logrus", + "version":"v1.8.1" + } + ] +} \ No newline at end of file diff --git a/boilerplate.go b/templates.go similarity index 83% rename from boilerplate.go rename to templates.go index 2ec5709efde7148a5e7332e59c28cbe60d445223..8753098a76369374a137e35f61db842a2fc4eba6 100644 --- a/boilerplate.go +++ b/templates.go @@ -1,8 +1,12 @@ package csbi -import "github.com/openconfig/ygot/ygen" +import ( + "html/template" -var pluginBoilerplate = ygen.GoStructCodeSnippet{ + "github.com/openconfig/ygot/ygen" +) + +var pluginStruct = ygen.GoStructCodeSnippet{ StructName: "Csbi", StructDef: `type Csbi struct { schema *ytypes.Schema @@ -123,7 +127,7 @@ func getField(inStruct ygot.ValidatedGoStruct, fields []string) (ygot.ValidatedG }`, } -var pluginImports = ` +const pluginImportAmendmend = ` spb "code.fbi.h-da.de/danet/api/go/gosdn/southbound" "github.com/google/uuid" @@ -134,16 +138,35 @@ var pluginImports = ` var PluginSymbol Csbi ` -var pluginGoMod = `module code.fbi.h-da.de/danet/plugin-autogen - -go 1.16 - -require ( +/* code.fbi.h-da.de/danet/api thesis-mk github.com/google/uuid v1.2.0 github.com/openconfig/gnmi v0.0.0-20210707145734-c69a5df04b53 github.com/openconfig/goyang v0.2.7 github.com/openconfig/ygot v0.11.2 github.com/sirupsen/logrus v1.8.1 -) +*/ + +var templater *template.Template + +const pluginGoModTemplate = `module << .ModuleName >> + +go << .GoVersion >> + +require (<<range $element := .Dependencies>> + <<$element.Name>> <<$element.Version>> +<<end>>) ` + +// Module represents a Go module entry in go.mod. Name and version needed. +type Module struct { + Name string `json:"name"` + Version string `json:"version"` +} + +// GoMod represents a go.mod file used for templates. +type GoMod struct { + ModuleName string `json:"name"` + GoVersion string `json:"go_version"` + Dependencies []Module `json:"dependencies"` +} diff --git a/write.go b/write.go index 7eeeda46c9d719ebcf429cab15e4cb23a99faf6a..8e858df2523e8c05218f8052d341203b5844c138 100644 --- a/write.go +++ b/write.go @@ -1,11 +1,13 @@ package csbi import ( - "bufio" + "bytes" + "encoding/json" "fmt" - "io" + "html/template" "io/fs" "os" + "os/exec" "path/filepath" "strings" @@ -60,11 +62,11 @@ func writeCsbi(code *ygen.GeneratedGoCode, path string) error { return err } - if err := writeCode(path, code); err != nil { + if err := copyFile(path, "Dockerfile"); err != nil { return err } - return writeDockerfile(path, csbiDockerfile) + return writeCode(path, code) } func writePlugin(code *ygen.GeneratedGoCode, path string) error { @@ -76,35 +78,28 @@ func writePlugin(code *ygen.GeneratedGoCode, path string) error { } func copyFile(path, filename string) error { - dstFile := filepath.Join(path, filename) - dst, err := os.OpenFile(dstFile, os.O_CREATE|os.O_WRONLY, 0755) - if err != nil { - return err - } - defer dst.Sync() - + var stderr bytes.Buffer srcFile := filepath.Join("resources", filename) - src, err := os.OpenFile(srcFile, os.O_RDONLY, 0755) + dstFile := filepath.Join(path, filename) + cmd := exec.Command("cp", srcFile, dstFile) + cmd.Stderr = &stderr + err := cmd.Run() if err != nil { + log.Error(stderr.String()) return err } - defer src.Sync() - n, err := io.Copy(dst, src) - if err != nil { - return err - } log.WithFields(log.Fields{ "source file": srcFile, "dst file": dstFile, - }).Infof("%v bytes copied", n) + }).Infof("file copied") return nil } func writeCode(path string, code *ygen.GeneratedGoCode) error { code.CommonHeader = strings.TrimSuffix(code.CommonHeader, ")\n") - code.CommonHeader = code.CommonHeader + pluginImports - code.Structs = append(code.Structs, pluginBoilerplate) + code.CommonHeader = code.CommonHeader + pluginImportAmendmend + code.Structs = append(code.Structs, pluginStruct) file := filepath.Join(path, "gostructs.go") generatedCode := genutil.OpenFile(file) defer genutil.SyncFile(generatedCode) @@ -150,18 +145,28 @@ func writeDockerfile(path string, buffer []string) error { } func writeGoMod(path string) error { + // Read dependencies from JSON file + deps, err := os.ReadFile(filepath.Join("resources", "plugin_deps.json")) + if err != nil { + return err + } + module := GoMod{} + if err := json.Unmarshal(deps, &module); err != nil { + return err + } + + // Create go.mod in destination directory and write template file := filepath.Join(path, "go.mod") goMod, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY, 0755) - defer goMod.Sync() if err != nil { return err } - w := bufio.NewWriter(goMod) - n, err := w.WriteString(pluginGoMod) + defer goMod.Sync() + + templater := template.New("goMod").Delims("<<", ">>") + _, err = templater.Parse(pluginGoModTemplate) if err != nil { return err } - log.WithField("n", n).Trace("wrote bytes") - w.Flush() - return nil + return templater.Execute(goMod, module) }