codegen/runner/runner.go (211 lines of code) (raw):
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/uber/zanzibar/codegen"
zanzibar "github.com/uber/zanzibar/runtime"
)
const _defaultParallelizeFactor = 2
type stackTracer interface {
StackTrace() errors.StackTrace
}
func checkError(err error, message string) {
if err != nil {
fmt.Fprintf(
os.Stderr, "%s:\n%s\n", message, err,
)
causeErr := errors.Cause(err)
if causeErr, ok := causeErr.(stackTracer); ok {
fmt.Fprintf(
os.Stderr, "%+v \n", causeErr.StackTrace(),
)
}
os.Exit(1)
}
}
func main() {
configFile := flag.String("config", "", "the config file path")
moduleName := flag.String("instance", "", "")
moduleClass := flag.String("type", "", "")
selectiveModule := flag.Bool("selective", false, "")
flag.Parse()
if *configFile == "" {
flag.Usage()
os.Exit(1)
return
}
configRoot := filepath.Dir(*configFile)
config := zanzibar.NewStaticConfigOrDie([]*zanzibar.ConfigOption{
zanzibar.ConfigFilePath(*configFile),
}, nil)
configRoot, err := filepath.Abs(configRoot)
checkError(
err, fmt.Sprintf("can not get abs path of config dir %s", configRoot),
)
copyright := []byte("")
if config.ContainsKey("copyrightHeader") {
bytes, err := ioutil.ReadFile(filepath.Join(
configRoot,
config.MustGetString("copyrightHeader"),
))
if err == nil {
copyright = bytes
}
}
stagingReqHeader := "X-Zanzibar-Use-Staging"
if config.ContainsKey("stagingReqHeader") {
stagingReqHeader = config.MustGetString("stagingReqHeader")
}
deputyReqHeader := "x-deputy-forwarded"
if config.ContainsKey("deputyReqHeader") {
deputyReqHeader = config.MustGetString("deputyReqHeader")
}
relMiddlewareConfigDir := ""
if config.ContainsKey("middlewareConfig") {
relMiddlewareConfigDir = config.MustGetString("middlewareConfig")
}
relDefaultMiddlewareConfigDir := ""
if config.ContainsKey("defaultMiddlewareConfig") {
relDefaultMiddlewareConfigDir = config.MustGetString("defaultMiddlewareConfig")
}
searchPaths := make(map[string][]string, 0)
config.MustGetStruct("moduleSearchPaths", &searchPaths)
defaultDependencies := make(map[string][]string, 0)
if config.ContainsKey("defaultDependencies") {
config.MustGetStruct("defaultDependencies", &defaultDependencies)
}
defaultHeaders := make([]string, 0)
if config.ContainsKey("defaultHeaders") {
config.MustGetStruct("defaultHeaders", &defaultHeaders)
}
moduleIdlSubDir := map[string]string{}
config.MustGetStruct("moduleIdlSubDir", &moduleIdlSubDir)
genCodePackage := map[string]string{}
config.MustGetStruct("genCodePackage", &genCodePackage)
options := &codegen.PackageHelperOptions{
RelIdlRootDir: config.MustGetString("idlRootDir"),
ModuleIdlSubDir: moduleIdlSubDir,
RelTargetGenDir: config.MustGetString("targetGenDir"),
RelMiddlewareConfigDir: relMiddlewareConfigDir,
RelDefaultMiddlewareConfigDir: relDefaultMiddlewareConfigDir,
AnnotationPrefix: config.MustGetString("annotationPrefix"),
GenCodePackage: genCodePackage,
CopyrightHeader: string(copyright),
StagingReqHeader: stagingReqHeader,
DeputyReqHeader: deputyReqHeader,
TraceKey: config.MustGetString("traceKey"),
ModuleSearchPaths: searchPaths,
DefaultDependencies: defaultDependencies,
DefaultHeaders: defaultHeaders,
}
options.QPSLevelsEnabled = true
if config.ContainsKey("qpsLevelsEnabled") {
options.QPSLevelsEnabled = config.MustGetBoolean("qpsLevelsEnabled")
}
options.CustomInitialisationEnabled = false
if config.ContainsKey("customInitialisationEnabled") {
options.CustomInitialisationEnabled = config.MustGetBoolean("customInitialisationEnabled")
}
packageHelper, err := codegen.NewPackageHelper(
config.MustGetString("packageRoot"),
configRoot,
options,
)
checkError(
err, fmt.Sprintf("Can't build package helper %s", configRoot),
)
genMock := config.ContainsKey("genMock")
if genMock {
genMock = config.MustGetBoolean("genMock")
}
var moduleSystem *codegen.ModuleSystem
if genMock {
parallelizeFactor := _defaultParallelizeFactor
if config.ContainsKey("parallelizeFactor") {
parallelizeFactor = int(config.MustGetInt("parallelizeFactor"))
}
moduleSystem, err = codegen.NewDefaultModuleSystemWithMockHook(packageHelper, true,
true, true, "test.yaml", parallelizeFactor, true)
} else {
moduleSystem, err = codegen.NewDefaultModuleSystem(packageHelper, true)
}
checkError(
err, fmt.Sprintf("Error creating module system %s", configRoot),
)
fmt.Printf("Generating module system components:\n")
if *moduleClass != "" && *moduleName != "" {
resolvedModules, err := moduleSystem.ResolveModules(
packageHelper.PackageRoot(),
configRoot,
packageHelper.CodeGenTargetPath(),
codegen.Options{
EnableCustomInitialisation: options.CustomInitialisationEnabled,
},
)
checkError(err, "error resolving modules")
for _, instance := range resolvedModules[*moduleClass] {
if instance.InstanceName == *moduleName {
physicalGenDir := filepath.Join(packageHelper.CodeGenTargetPath(), instance.Directory)
err := moduleSystem.Build(
packageHelper.PackageRoot(),
configRoot,
physicalGenDir,
instance,
codegen.Options{
CommitChange: true,
},
)
checkError(err, "error generating code")
}
}
} else {
customTemplates, _ := codegen.NewDefaultTemplate()
resolvedModules, err := moduleSystem.ResolveModules(
packageHelper.PackageRoot(),
configRoot,
packageHelper.CodeGenTargetPath(),
codegen.Options{
EnableCustomInitialisation: options.CustomInitialisationEnabled,
CustomTemplates: customTemplates,
},
)
checkError(err, "error resolving modules")
var dependencies []codegen.ModuleDependency
if *selectiveModule {
dependencies = getSelectiveModule()
}
_, err = moduleSystem.IncrementalBuild(
packageHelper.PackageRoot(),
configRoot,
packageHelper.CodeGenTargetPath(),
dependencies,
resolvedModules,
codegen.Options{
CommitChange: true,
QPSLevelsEnabled: options.QPSLevelsEnabled,
},
)
checkError(err, "Failed to generate module system components")
}
}
func getSelectiveModule() []codegen.ModuleDependency {
dependencies := []codegen.ModuleDependency{
{
ClassName: "endpoint",
InstanceName: "bounce",
},
{
ClassName: "client",
InstanceName: "echo",
},
{
ClassName: "client",
InstanceName: "mirror",
},
}
return dependencies
}