/** * Unified Java + Docker + K3s pipeline runner for this repo. * * Goal: keep service Jenkinsfiles thin by moving per-service differences into cfg.yaml: * project.pipeline: { jdkTool, baseImage, enableSkywalking, deployMode, k8sBackups, ... } * * This file is designed to be backward compatible: if `CONFIG.pipeline` is missing, * defaults match the most common existing Jenkinsfile patterns in this repo. */ def _get(Map m, String k, def dflt=null) { return (m != null && m.containsKey(k) && m[k] != null) ? m[k] : dflt } def _asStringArray(def v) { if (v == null) return [] as String[] if (v instanceof String[]) return v if (v instanceof List) return (v.collect { it.toString() }) as String[] return [v.toString()] as String[] } def _asList(def v) { if (v == null) return [] if (v instanceof List) return v return [v] } def _normalizeModulePath(def module) { def moduleText = module == null ? '' : module.toString().trim() if (!moduleText) return '' return moduleText.endsWith('/') ? moduleText : moduleText + '/' } def _pipelineArgs(def pipeline) { return pipeline instanceof Map ? _get(pipeline, "args", null) : null } def _skywalkingArgs(Map CONFIG) { def p = CONFIG.pipeline ?: [:] if (_get(p, "addSkywalkingArgs", false) != true) return [] return [ "-javaagent:/app/skywalking-agent/skywalking-agent.jar", "-Dskywalking.agent.service_name=${CONFIG.service.name}", "-Dskywalking.collector.backend_service=${CONFIG.skywalking.address}" ] } def _splitJavaArgs(String[] rawArgs) { def jvmArgs = [] def appArgs = [] rawArgs.each { arg -> def text = arg == null ? '' : arg.toString().trim() if (!text) return if (text.startsWith('--')) { appArgs << text return } jvmArgs << text } return [jvmArgs, appArgs] } def _buildJavaArgs(Map CONFIG) { def p = CONFIG.pipeline ?: [:] def args = _pipelineArgs(p) def buildNumberArg = _get(p, "includeBuildNumber", false) ? ["-DBuild.number=${BUILD_NUMBER}"] : [] if (args instanceof List || args instanceof String[]) { def directArgs = _asStringArray(args) if (directArgs.length > 0) { def (jvmArgs, appArgs) = _splitJavaArgs(directArgs) return (jvmArgs + _skywalkingArgs(CONFIG) + buildNumberArg + ["-jar", "/app/target/${CONFIG.service.jar}"] + appArgs) as String[] } } if (args instanceof String && args.toString().trim()) { def (jvmArgs, appArgs) = _splitJavaArgs([args.toString().trim()] as String[]) return (jvmArgs + _skywalkingArgs(CONFIG) + buildNumberArg + ["-jar", "/app/target/${CONFIG.service.jar}"] + appArgs) as String[] } if (args instanceof Map) { def explicitArgs = _asStringArray(_get(args, "javaArgs", null)) if (explicitArgs.length > 0) { def (jvmArgs, appArgs) = _splitJavaArgs(explicitArgs) return (jvmArgs + _skywalkingArgs(CONFIG) + buildNumberArg + ["-jar", "/app/target/${CONFIG.service.jar}"] + appArgs) as String[] } } def explicitArgs = _asStringArray(_get(p, "javaArgs", null)) if (explicitArgs.length > 0) return explicitArgs def jvmArgs = ["-Djava.security.egd=file:/dev/./urandom"] jvmArgs.addAll(_skywalkingArgs(CONFIG)) jvmArgs.addAll(buildNumberArg) def xmx = args instanceof Map ? _get(args, "xmx", _get(p, "xmx", null)) : _get(p, "xmx", null) if (xmx != null && xmx.toString().trim()) { jvmArgs << "-Xmx${xmx.toString().trim()}" } def serverPort = args instanceof Map ? _get(args, "serverPort", _get(p, "serverPort", null)) : _get(p, "serverPort", null) if (serverPort != null && serverPort.toString().trim()) { jvmArgs << "-Dserver.port=${serverPort.toString().trim()}" } def appArgs = [] def springProfile = args instanceof Map ? _get(args, "springProfile", _get(p, "springProfile", null)) : _get(p, "springProfile", null) if (springProfile != null && springProfile.toString().trim()) { appArgs << "--spring.profiles.active=${springProfile.toString().trim()}" } return (jvmArgs + ["-jar", "/app/target/${CONFIG.service.jar}"] + appArgs) as String[] } def _generateDockerfile(Map CONFIG, String pathOfDockerfile='projdir') { def p = CONFIG.pipeline ?: [:] def module = _normalizeModulePath(CONFIG.service.module) def baseImage = _get(p, "baseImage", "swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openjdk:17-jdk-alpine") def addSkywalking = _get(p, "enableSkywalking", false) def jar = CONFIG.service.jar def skywalkingAddLine = addSkywalking ? "ADD skywalking-agent /app/skywalking-agent" : "" sh """cat > ${pathOfDockerfile}/Dockerfile< if (!(deployment instanceof Map)) { error("pipeline.additionalConfigmapEnvOnlyDeployments entries must be maps") } def deploymentTemplate = _get(deployment, "deploymentTemplate", "") def serviceTemplate = _get(deployment, "serviceTemplate", "") if (!deploymentTemplate || !serviceTemplate) { error("additional configmap-env-only deployments require deploymentTemplate and serviceTemplate") } stages.deployWithConfigmapEnvOnlyTemplate( CONFIG.service, CONFIG.k3s, baseBranch, javaArgs, configmapEnv, deploymentTemplate, serviceTemplate, namespace ) } } def run(Map CONFIG, String action, def stages, String baseBranch, String namespace='default', String rollbackBuildNumber='') { // Ensure docker image name is formatted consistently with existing Jenkinsfiles. // 装备docker镜像路径 CONFIG.docker.image = String.format(CONFIG.docker.image, CONFIG.service.name) // 选择jdk环境 def p = CONFIG.pipeline ?: [:] def jdkTool = _get(p, "jdkTool", null) if (jdkTool != null && jdkTool.toString().trim()) { jdk = tool name: jdkTool env.JAVA_HOME = "${jdk}" } def base_branch = baseBranch String[] JAVA_ARGS = _buildJavaArgs(CONFIG) String[] K8S_BACKUPS = _asStringArray(_get(p, "k8sBackups", [])) def deployMode = _get(p, "deployMode", "configmapEnvOnly") // Optional per-service file names; keep defaults matching existing code. def configmapEnv = _get(p, "configmapEnvFile", "./configmap-env.ini") def configmapConf = _get(p, "configmapConfFile", "./configmap") if ("upgrade" == action || "upgrade:selected" == action) { stages.upgrade(CONFIG, base_branch, K8S_BACKUPS, [ 'POST_GITCLONE': { _maybeCopySkywalking(CONFIG) }, 'GENERATEDOCKERFILE': { _generateDockerfile(CONFIG) }, 'K3SDEPLOY': { if (deployMode == "configmapEnvOnly") { stages.deployWithConfigmapEnvOnly(CONFIG.service, CONFIG.k3s, base_branch, JAVA_ARGS, configmapEnv, namespace) _deployAdditionalConfigmapEnvOnly(stages, CONFIG, base_branch, JAVA_ARGS, configmapEnv, namespace) return } if (deployMode == "configmaps") { stages.deployWithConfigmaps(CONFIG.service, CONFIG.k3s, base_branch, JAVA_ARGS, configmapEnv, configmapConf, namespace) return } // Fallback to repo default (env-only). stages.deployWithConfigmapEnvOnly(CONFIG.service, CONFIG.k3s, base_branch, JAVA_ARGS, configmapEnv, namespace) } ]) _maybeCleanupSkywalking(CONFIG) return } if ("rollback" == action) { stages.rollback(CONFIG, rollbackBuildNumber, [ 'K3SDEPLOY': { if (deployMode == "configmapEnvOnly") { stages.deployWithConfigmapEnvOnly_rollback(CONFIG.service, CONFIG.k3s, rollbackBuildNumber, JAVA_ARGS, configmapEnv, namespace) return } if (deployMode == "configmaps") { stages.deployWithConfigmaps_rollback(CONFIG.service, CONFIG.k3s, rollbackBuildNumber, JAVA_ARGS, configmapEnv, configmapConf, namespace) return } stages.deployWithConfigmapEnvOnly_rollback(CONFIG.service, CONFIG.k3s, rollbackBuildNumber, JAVA_ARGS, configmapEnv, namespace) } ]) return } } return this