in tools/lambda-compat/cmd/lambda-build/main.go [249:379]
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
exe, err := os.Executable()
if err != nil {
log.Fatal().Err(err).Msg("unable to determine binary location")
}
templateDir = fmt.Sprintf("%s/templates/", filepath.Dir(exe))
log.Info().Msg("Lambda compatibility tool for Cloud Run")
flag.StringVar(&templateDir, "template-dir", templateDir, "location of Dockerfile and Terraform templates")
flag.StringVar(&targetDir, "target-dir", targetDir, "directory to create Dockerfile and Terraform files in")
flag.BoolVar(&generateDockerfile, "dockerfile", true, "generate Dockerfile")
flag.StringVar(&dockerfilePath, "dockerfile-path", dockerfilePath, "path and filename for Dockerfile")
flag.BoolVar(&generateTerraform, "terraform", true, "generate Terraform files")
flag.StringVar(&terraformPath, "terraform-path", terraformPath, "path for Terraform files")
flag.StringVar(&projectId, "project-id", projectId, "GCP project ID")
flag.StringVar(&containerRegistry, "registry", containerRegistry, "Container registry to use (eg. docker.pkg.dev/project-id/registry)")
flag.StringVar(&containerTag, "tag", containerTag, "Container image tag")
flag.Var(&additionalVars, "var", "Additional template variable (key=value)")
flag.Var(&additionalVarsJson, "var-json", "Additional template variable in JSON (key={\"foo\":\"bar\"})")
flag.Parse()
if !strings.HasSuffix(templateDir, "/") {
templateDir = templateDir + "/"
}
if _, err := os.Stat(templateDir + "common.tpl"); errors.Is(err, os.ErrNotExist) {
if _, err := os.Stat(templateDir + "common.tpl"); errors.Is(err, os.ErrNotExist) {
log.Info().Str("directory", templateDir).Msg("Creating template directory")
err = os.MkdirAll(templateDir, 0770)
if err != nil {
log.Fatal().Err(err).Str("directory", templateDir).Msg("Failed to create template directory")
}
}
templates := []string{
"common.tpl",
"dotnetcore.tpl",
"go.tpl",
"java.tpl",
"nodejs.tpl",
"python.tpl",
"ruby.tpl",
"terraform_main.tf.tpl",
"terraform_outputs.tf.tpl",
"terraform_variables.tf.tpl",
"terraform_versions.tf.tpl",
}
log.Info().Str("directory", templateDir).Msg("Writing embedded templates to disk")
for _, tpl := range templates {
contents, err := fs.ReadFile(fmt.Sprintf("templates/%s", tpl))
if err != nil {
log.Fatal().Err(err).Msg("Failed to retrieve embedded template")
}
err = ioutil.WriteFile(fmt.Sprintf("%s/%s", templateDir, tpl), contents, 0664)
if err != nil {
log.Fatal().Err(err).Msg("Failed to write embedded template")
}
}
}
var containerBuilders []string = []string{
"buildah",
"podman",
"nerdctl",
}
var containerBuilder string = "docker"
for _, bin := range containerBuilders {
_, err := exec.LookPath(bin)
if err == nil {
containerBuilder = bin
break
}
}
if !strings.HasSuffix(containerRegistry, "/") {
containerRegistry = strings.TrimSuffix(containerRegistry, "/")
}
if len(flag.Args()) == 0 {
log.Fatal().Msg("Specify at least one template to process")
}
for _, fileName := range flag.Args() {
var template SamTemplate
yamlFile, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatal().Str("file", fileName).Err(err).Msg("Failed to load configuration file")
}
err = yaml.Unmarshal(yamlFile, &template)
if err != nil {
log.Fatal().Str("file", fileName).Err(err).Msg("Failed to decode YAML")
}
log.Info().Str("file", fileName).Msg("Processing SAM template file")
for name, resource := range template.Resources {
if resource.Type == "AWS::Serverless::Function" {
subdir := filepath.Clean(fmt.Sprintf("%s/%s", filepath.Clean(targetDir), name)) + "/"
if generateDockerfile {
ensureDirectory(subdir)
dockerfile := fmt.Sprintf("%s%s", subdir, dockerfilePath)
err := resource.renderDockerfile(name, dockerfile)
if err != nil {
log.Fatal().Str("file", fileName).Str("resource", name).Err(err).Msg("Failed to render Dockerfile for resource")
}
if containerRegistry != "" {
log.Info().Msg("To build container, run:")
log.Info().Msg(fmt.Sprintf(" %s build -t %s/%s:%s -f %s/Dockerfile .", containerBuilder, containerRegistry, strings.ToLower(name), containerTag, name))
}
}
if generateTerraform {
terraformSubdir := fmt.Sprintf("%s%s", subdir, terraformPath)
ensureDirectory(terraformSubdir)
err := resource.renderTerraform(name, terraformSubdir)
if err != nil {
log.Fatal().Str("file", fileName).Str("resource", name).Err(err).Msg("Failed to render Terraform for resource")
}
}
} else {
log.Debug().Str("type", resource.Type).Msg("Unknown resource type ignored")
}
}
}
}