Конвейер Jenkins readJSON будет читать логическое значение false как ноль

Допустим, у меня есть 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? Мне не удалось это воспроизвести, MyVal1 установлено на false. Также вы можете попробовать упростить выражения до props.vm.MyVal1 и так далее — это тоже работает.

Alexander Pletnev 27.07.2024 22:58

Файл JSON тот же, но в процессе работы у меня было несколько if, чтобы определить, является ли он логическим значением или нет. Теперь я отредактировал вопрос и добавил туда операторы if. Моя цель — проверить переменную JSON и, если она верна, добавить ее в переменную среды, если нет, то сохранить ошибку, и я обработаю ее позже.

Darwick 27.07.2024 23:39

Вам нужно дважды проверить свое первое if состояние. Дело не в том, что Дженкинс не может прочитать значение — кажется, что null появляется, потому что env.MYVAL1 никогда не присваивалось реальное значение.

Alexander Pletnev 28.07.2024 01:16

Звучит логично, и вы, кажется, правы. Но вопрос остается вопросом: что плохого в этих утверждениях if? Я не могу себе представить. Тем более, что MyVal2 работает так, как и ожидалось, с теми же утверждениями.

Darwick 28.07.2024 12:45
Как сделать HTTP-запрос в Javascript?
Как сделать HTTP-запрос в Javascript?
В JavaScript вы можете сделать HTTP-запрос, используя объект XMLHttpRequest или более новый API fetch. Вот пример для обоих методов:
0
4
52
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

ваша проверка «логическое значение» неверна

рассмотрим следующий код, который соответствует утверждению 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 выдаст ошибку. Этот метод работает только в том случае, если переменная точно определена. Именно поэтому для проверки я использовал вышеописанный метод.

Darwick 30.07.2024 12:17
if ( props?.vm?.MyVal1 instanceof Boolean) не должен генерировать исключение, даже если MyVal1 не определен.
daggett 30.07.2024 13:30

Нет, не будет: groovy.lang.MissingPropertyException: No such property: MyVal1 for class: groovy.lang.Binding

Darwick 30.07.2024 14:06

это звучит как несвязанное (я не говорю, что вы не правы). groovy.lang.Binding — сообщает, что вы пытаетесь получить свойство MyVal1 без указания темы (поэтому groovy пытается получить его из текущего скрипта. Вы можете проверить, присутствует ли ключ на карте, с помощью props?.vm?.containsKey('MyVal1')

daggett 30.07.2024 15:02

Спасибо, если я сделаю так, то это сработает. Странно, что не по-другому.

Darwick 30.07.2024 15:10

Другие вопросы по теме