builder/build/cnb/build_params.go
Rama main · réplica de lectura del repositorio original.
package cnb
import (
"crypto/sha1"
"fmt"
"os"
"strings"
"github.com/goodrain/rainbond/builder/build"
"github.com/goodrain/rainbond/builder/parser/code"
corev1 "k8s.io/api/core/v1"
)
const (
defaultCNBMavenVersion = "3.9.14"
defaultCNBComposerVersion = "2.7.9"
pythonPackageManagerPip = "pip"
pythonPackageManagerPipenv = "pipenv"
pythonPackageManagerPoetry = "poetry"
pythonPackageManagerConda = "conda"
bindingTypeKeyPrefix = "cnb-binding-"
bindingTypeKeySuffix = "-type"
k8sNamePartMaxLength = 63
bindingTypeHashHexLength = 8
)
type platformBinding struct {
Name string
Type string
ConfigMapName string
ConfigMapKey string
TargetFile string
}
func ensureBuildEnvs(re *build.Request) {
if re.BuildEnvs == nil {
re.BuildEnvs = map[string]string{}
}
}
func truthyBuildEnv(value string) bool {
switch strings.ToLower(strings.TrimSpace(value)) {
case "1", "t", "true", "y", "yes", "on":
return true
default:
return false
}
}
func appendEnvVar(envs []corev1.EnvVar, name, value string) []corev1.EnvVar {
value = strings.TrimSpace(value)
if value == "" {
return envs
}
return append(envs, corev1.EnvVar{Name: name, Value: value})
}
func setAnnotationValue(annotations map[string]string, key, value string) {
value = strings.TrimSpace(value)
if value == "" {
return
}
annotations[key] = value
}
func validateSupportedBuildParams(re *build.Request) error {
ensureBuildEnvs(re)
if strings.TrimSpace(re.BuildStrategy) != "cnb" {
return nil
}
switch re.Lang {
case code.JavaMaven, code.Gradle, code.JaveWar:
re.BuildEnvs["BUILD_RUNTIMES_MAVEN"] = defaultCNBMavenVersion
server := firstNonEmptyEnv(re.BuildEnvs, "BP_JAVA_APP_SERVER", "BUILD_RUNTIMES_SERVER")
if server == "" && re.Lang == code.JaveWar {
server = "tomcat"
}
if normalized, err := normalizeJavaAppServer(server); err != nil {
return err
} else if normalized != "" {
re.BuildEnvs["BP_JAVA_APP_SERVER"] = normalized
re.BuildEnvs["BUILD_RUNTIMES_SERVER"] = normalized
}
case code.Python:
manager, err := detectPythonPackageManager(re)
if err != nil {
return err
}
if manager != "" {
re.BuildEnvs["BUILD_PYTHON_PACKAGE_MANAGER"] = manager
}
if manager == pythonPackageManagerConda {
solver := firstNonEmptyEnv(re.BuildEnvs, "BP_CONDA_SOLVER", "BUILD_CONDA_SOLVER")
if solver == "" {
solver = "mamba"
}
re.BuildEnvs["BP_CONDA_SOLVER"] = solver
re.BuildEnvs["BUILD_CONDA_SOLVER"] = solver
}
if version := strings.TrimSpace(re.BuildEnvs["BUILD_PYTHON_PACKAGE_MANAGER_VERSION"]); version != "" {
envName, err := pythonPackageManagerVersionEnv(manager)
if err != nil {
return err
}
re.BuildEnvs[envName] = version
}
case code.PHP:
server := firstNonEmptyEnv(re.BuildEnvs, "BUILD_RUNTIMES_SERVER")
if server == "" {
server = "nginx"
}
if normalized, err := normalizePHPServer(server); err != nil {
return err
} else if normalized != "" {
re.BuildEnvs["BUILD_RUNTIMES_SERVER"] = normalized
}
re.BuildEnvs["BP_COMPOSER_VERSION"] = defaultCNBComposerVersion
re.BuildEnvs["BUILD_COMPOSER_VERSION"] = defaultCNBComposerVersion
if options := firstNonEmptyEnv(re.BuildEnvs, "BP_COMPOSER_INSTALL_OPTIONS", "BUILD_COMPOSER_INSTALL_OPTIONS"); options != "" {
re.BuildEnvs["BP_COMPOSER_INSTALL_OPTIONS"] = options
re.BuildEnvs["BUILD_COMPOSER_INSTALL_OPTIONS"] = options
}
if webDir := firstNonEmptyEnv(re.BuildEnvs, "BP_PHP_WEB_DIR", "BUILD_PHP_WEB_DIR"); webDir != "" {
re.BuildEnvs["BP_PHP_WEB_DIR"] = webDir
re.BuildEnvs["BUILD_PHP_WEB_DIR"] = webDir
}
redirect := firstNonEmptyEnv(re.BuildEnvs, "BP_PHP_ENABLE_HTTPS_REDIRECT", "BUILD_PHP_ENABLE_HTTPS_REDIRECT")
if redirect == "" {
redirect = "false"
}
re.BuildEnvs["BP_PHP_ENABLE_HTTPS_REDIRECT"] = redirect
re.BuildEnvs["BUILD_PHP_ENABLE_HTTPS_REDIRECT"] = redirect
}
return nil
}
func normalizeJavaAppServer(server string) (string, error) {
server = strings.ToLower(strings.TrimSpace(server))
if server == "" {
return "", nil
}
switch {
case strings.Contains(server, "tomcat"):
return "tomcat", nil
case strings.Contains(server, "tomee"):
return "tomee", nil
case strings.Contains(server, "liberty"):
return "liberty", nil
default:
return "", fmt.Errorf("unsupported java app server %q", server)
}
}
func normalizePHPServer(server string) (string, error) {
server = strings.ToLower(strings.TrimSpace(server))
if server == "" {
return "", nil
}
switch server {
case "apache", "httpd":
return "httpd", nil
case "nginx", "php-server":
return server, nil
default:
return "", fmt.Errorf("unsupported php server %q", server)
}
}
func detectPythonPackageManager(re *build.Request) (string, error) {
manager, err := normalizePythonPackageManager(re.BuildEnvs["BUILD_PYTHON_PACKAGE_MANAGER"])
if err != nil {
return "", err
}
if manager != "" {
return manager, nil
}
return code.DetectPythonPackageManager(re.SourceDir), nil
}
func normalizePythonPackageManager(manager string) (string, error) {
switch strings.ToLower(strings.TrimSpace(manager)) {
case "":
return "", nil
case pythonPackageManagerPip, pythonPackageManagerPipenv, pythonPackageManagerPoetry, pythonPackageManagerConda:
return strings.ToLower(strings.TrimSpace(manager)), nil
default:
return "", fmt.Errorf("unsupported python package manager %q", manager)
}
}
func pythonPackageManagerVersionEnv(manager string) (string, error) {
switch manager {
case pythonPackageManagerPip:
return "BP_PIP_VERSION", nil
case pythonPackageManagerPipenv:
return "BP_PIPENV_VERSION", nil
case pythonPackageManagerPoetry:
return "BP_POETRY_VERSION", nil
case pythonPackageManagerConda:
return "", fmt.Errorf("conda package manager does not support BUILD_PYTHON_PACKAGE_MANAGER_VERSION")
default:
return "", fmt.Errorf("python package manager must be set before BUILD_PYTHON_PACKAGE_MANAGER_VERSION can be used")
}
}
func fileExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func bindingTypeAnnotationKey(bindingName string) string {
bindingName = strings.ToLower(strings.TrimSpace(bindingName))
if bindingName == "" {
return bindingTypeKeyPrefix + strings.TrimPrefix(bindingTypeKeySuffix, "-")
}
var normalized strings.Builder
for _, r := range bindingName {
switch {
case r >= 'a' && r <= 'z':
normalized.WriteRune(r)
case r >= '0' && r <= '9':
normalized.WriteRune(r)
case r == '-':
normalized.WriteRune(r)
default:
normalized.WriteRune('-')
}
}
namePart := strings.Trim(normalized.String(), "-")
if namePart == "" {
return bindingTypeKeyPrefix + strings.TrimPrefix(bindingTypeKeySuffix, "-")
}
maxNamePartLength := k8sNamePartMaxLength - len(bindingTypeKeyPrefix) - len(bindingTypeKeySuffix)
if len(namePart) > maxNamePartLength {
sum := sha1.Sum([]byte(namePart))
hashSuffix := fmt.Sprintf("%x", sum[:bindingTypeHashHexLength/2])
prefixLength := maxNamePartLength - len(hashSuffix) - 1
if prefixLength < 1 {
namePart = hashSuffix[:maxNamePartLength]
} else {
prefix := strings.TrimRight(namePart[:prefixLength], "-")
if prefix == "" {
namePart = hashSuffix[:maxNamePartLength]
} else {
namePart = prefix + "-" + hashSuffix
}
}
}
return bindingTypeKeyPrefix + namePart + bindingTypeKeySuffix
}