Допустим, у меня есть JSON-файл myfile.json с таким содержимым:
{
"vm": {
"MyVal1": false,
"MyVal2": true,
"MyVal3": "some string",
}
}
И мой конвейер Jenkins выглядит так:
pipeline {
agent any
options {
ansiColor('xterm')
}
stages {
stage('Parse VM details') {
steps {
echo "Read VM JSON file"
script {
def props = readJSON file: 'myfile.json'
if (props['vm'].get("MyVal1") && (props['vm'].get("MyVal1") == true || props['vm'].get("MyVal1") == false)) {
env.MYVAL1 = props['vm'].get("MyVal1")
//} else {
// env.VM_ERRORMSG = "MyVal1 is not a boolean."
}
if (props['vm'].get("MyVal2") && (props['vm'].get("MyVal2") == true || props['vm'].get("MyVal2") == false))
env.MYVAL2 = props['vm'].get("MyVal2")
//} else {
// env.VM_ERRORMSG = "MyVal2 is not a boolean."
}
if (props['vm'].get("MyVal3")) {
env.MYVAL3 = props['vm'].get("MyVal3")
} else {
env.VM_ERRORMSG = "MyVal3 is not defined or empty"
}
echo "MyVal1 will be: ${env.MYVAL1}"
echo "MyVal2 will be: ${env.MYVAL2}"
echo "MyVal3 will be: ${env.MYVAL3}"
if (env.VM_ERRORMSG) {
echo "${env.VM_ERRORMSG}"
}
}
}
}
}
}
Когда я запустил конвейер, я получил следующие результаты:
[Pipeline] echo
MyVal1 will be: null
[Pipeline] echo
MyVal2 will be: true
[Pipeline] echo
MyVal3 will be: some string
Итак, для MyVal2
я получаю логическое значение как true
, но для MyVal1
это всегда null
, что бы я ни пробовал. Я попробовал env.MYVAL1 = toBoolean(props['vm'].get("MyVal1"))
, но это не помогло.
Допустим, файл JSON не слишком гибок, поэтому мне нужно решить его на стороне Дженкинса. Как я могу заставить MyVal1
отображаться как логическое значение, даже если это false
?
ОБНОВЛЯТЬ:
Как подсказали в комментариях, я нашел причину, по которой я получаю null
вместо false
. Это потому, что во время тестирования он не входит в оператор if
. Если я изменю соответствующие строки в конвейере на:
if (props['vm'].get("MyVal1")) {
env.MYVAL1 = props['vm'].get("MyVal1")
}
if (props['vm'].get("MyVal2"))
env.MYVAL2 = props['vm'].get("MyVal2")
}
то все равно не входит в MyVal1
, а в MyVal2
оно входит. Я не понимаю, почему это работает таким образом, поскольку я не понимаю, как еще я могу проверить, что переменная определена, а не пуста. Если кто-то знает причину и/или у него есть предложения по достижению моей цели, я открываюсь для него. :)
Файл JSON тот же, но в процессе работы у меня было несколько if, чтобы определить, является ли он логическим значением или нет. Теперь я отредактировал вопрос и добавил туда операторы if. Моя цель — проверить переменную JSON и, если она верна, добавить ее в переменную среды, если нет, то сохранить ошибку, и я обработаю ее позже.
Вам нужно дважды проверить свое первое if
состояние. Дело не в том, что Дженкинс не может прочитать значение — кажется, что null
появляется, потому что env.MYVAL1
никогда не присваивалось реальное значение.
Звучит логично, и вы, кажется, правы. Но вопрос остается вопросом: что плохого в этих утверждениях if? Я не могу себе представить. Тем более, что MyVal2
работает так, как и ожидалось, с теми же утверждениями.
ваша проверка «логическое значение» неверна
рассмотрим следующий код, который соответствует утверждению if
в вопросе:
def x = false
if ( x && (x==false || x==true) ){
println "OK"
}
он никогда не напечатает «ОК», потому что x = false
и первая часть if
требует, чтобы x
было true
.
if ( x && (x==false || x==true) ){
//^ this requires x to be true or groovy "truth"
println "OK"
}
утверждение в обновленном вопросе также неверно для проверки наличия значения
if ( x ){
//^ this still requires x to be true or groovy "truth"
println "OK"
}
подробнее о крутой истине: https://groovy-lang.org/semantics.html#the-groovy-truth
итак, для решения проблемы - лучше переделать if
так:
if ( x==true || x==false ) {...}
или вот так:
if ( x instanceof Boolean ) {...}
и, наконец, способ получения свойств можно упростить:
if ( props?.vm?.MyVal1 instanceof Boolean ){
env.MYVAL1=props.vm.MyVal1
} else {
env.VM_ERRORMSG = "MyVal1 is not a boolean"
}
Спасибо, это поможет, но в этом случае я потерял возможность проверить «если определено». Например, если MyVal1
не определен в файле JSON, конвейер Jenkins выдаст ошибку. Этот метод работает только в том случае, если переменная точно определена. Именно поэтому для проверки я использовал вышеописанный метод.
if ( props?.vm?.MyVal1 instanceof Boolean)
не должен генерировать исключение, даже если MyVal1 не определен.
Нет, не будет: groovy.lang.MissingPropertyException: No such property: MyVal1 for class: groovy.lang.Binding
это звучит как несвязанное (я не говорю, что вы не правы). groovy.lang.Binding — сообщает, что вы пытаетесь получить свойство MyVal1
без указания темы (поэтому groovy пытается получить его из текущего скрипта. Вы можете проверить, присутствует ли ключ на карте, с помощью props?.vm?.containsKey('MyVal1')
Спасибо, если я сделаю так, то это сработает. Странно, что не по-другому.
Вы уверены, что ваш скрипт получает именно этот JSON? Мне не удалось это воспроизвести,
MyVal1
установлено наfalse
. Также вы можете попробовать упростить выражения доprops.vm.MyVal1
и так далее — это тоже работает.