使用地图列表进行 Groovy 字符串插值

问题描述 投票:0回答:1

我正在 Jenkins 脚本化管道中构建一个参数化的 yaml 字符串。 问题是我在使用地图列表变量插入字符串时出错。 我不认为我可以在詹金斯管道中使用外部库。安装了一些 Jenkins 插件。不确定哪些库可用于将这些对象正确序列化为 json 或 yaml。 FWIW我对groovy非常缺乏经验。我通常写Python。

def yaml, volumeMounts

volumeMounts = [
    ['mountPath': '/build/toolchain',      'name': 'volume-0'],
    ['mountPath': '/build/apps',           'name': 'volume-1'],
    ['mountPath': '/horizonci/automation', 'name': 'volume-2'],
    ['mountPath': '/home/jenkins',         'name': 'workspace-volume']
]

volumes = [
    ['name': 'volume-0', 'nfs': ['path': '/toolchain',           'readOnly': true, 'server': 'tools.company.com']],
    ['name': 'volume-1', 'nfs': ['path': '/apps',                'readOnly': true, 'server': 'tools.company.com']],
    ['name': 'volume-2', 'nfs': ['path': '/ifs/standard/devops', 'readOnly': true, 'server': 'my.server.company.com']]
]

yaml = """
kind: Pod
spec:
  containers:
  - volumeMounts: ${volumeMounts}
  volumes: ${volumesYml.toString()}
"""

println(yaml)

错误:

com.fasterxml.jackson.databind.exc.MismatchedInputException:
Cannot deserialize value of type `io.fabric8.kubernetes.api.model.VolumeMount`
from Array value (token `JsonToken.START_ARRAY`)
   at [Source: (String)"{"apiVersion":"v1","kind":"Pod","spec":{"containers":[{"name":"app","image":"jenkins/agent:latest","volumeMounts":[["mountPath:/build/toolchain","name:volume-0"],
        ["mountPath:/build/apps","name:vol"[truncated 1028 chars]; line: 1, column: 420] (through reference chain: io.fabric8.kubernetes.api.model.Pod["spec"]->io.fabric8.kubernetes.api.model.PodSpec["containers"]->java.util.ArrayList[0]->io.fabric8.kubernetes.api.model.Container["volumeMounts"]->java.util.ArrayList[0])

      at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
      at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1601)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:324)
      at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:187)
      at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
      at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
      at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
      at io.fabric8.kubernetes.client.utils.Serialization.unmarshalJsonStr(Serialization.java:311)
      at io.fabric8.kubernetes.client.utils.Serialization.unmarshalYaml(Serialization.java:306)
      at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:245)
  Caused: io.fabric8.kubernetes.client.KubernetesClientException: An error has occurred.
      at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:64)
      at io.fabric8.kubernetes.client.KubernetesClientException.launderThrowable(KubernetesClientException.java:53)
      at io.fabric8.kubernetes.client.utils.Serialization.unmarshal(Serialization.java:249)
      at io.fabric8.kubernetes.client.dsl.base.OperationSupport.unmarshal(OperationSupport.java:656)
      at io.fabric8.kubernetes.client.dsl.base.BaseOperation.load(BaseOperation.java:315)
      at io.fabric8.kubernetes.client.dsl.base.BaseOperation.load(BaseOperation.java:86)
      at org.csanchez.jenkins.plugins.kubernetes.PodTemplateUtils.parseFromYaml(PodTemplateUtils.java:566)
      at org.csanchez.jenkins.plugins.kubernetes.PodTemplateUtils.validateYamlContainerNames(PodTemplateUtils.java:595)
      at org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateStepExecution.start(PodTemplateStepExecution.java:142)
      at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:319)
      at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:193)
      at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
      at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:48)
      at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
      at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
      at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
  Caused: java.lang.RuntimeException: Failed to parse yaml:

我尝试使用文字字符串,但代码看起来很难看。难以阅读和维护。

json jenkins groovy yaml string-interpolation
1个回答
0
投票

解决方案是将 Groovy 对象转换为 JSON,并使用可在 Jenkins 管道中导入的内置 JSON 库序列化 JSON 对象。 使用 yaml 字符串很棘手,因此放弃了。 解决办法如下:

import groovy.json.JsonOutput

def yaml, volumeMounts

volumeMounts = [
    ['mountPath': '/build/toolchain',      'name': 'volume-0'],
    ['mountPath': '/build/apps',           'name': 'volume-1'],
    ['mountPath': '/horizonci/automation', 'name': 'volume-2'],
    ['mountPath': '/home/jenkins',         'name': 'workspace-volume']
]

volumes = [
    ['name': 'volume-0', 'nfs': ['path': '/toolchain',           'readOnly': true, 'server': 'tools.company.com']],
    ['name': 'volume-1', 'nfs': ['path': '/apps',                'readOnly': true, 'server': 'tools.company.com']],
    ['name': 'volume-2', 'nfs': ['path': '/ifs/standard/devops', 'readOnly': true, 'server': 'my.server.company.com']]
]

yaml = """
kind: Pod
spec:
  containers:
  - volumeMounts: ${JsonOutput.toJson(volumeMounts)}
  volumes: ${JsonOutput.toJson(volumes)}
"""

println(yaml)
© www.soinside.com 2019 - 2024. All rights reserved.