Groovy список с именем переменной, содержащей точку (.), Конвертируется в строку - PullRequest
0 голосов
/ 25 сентября 2018

У меня есть список в groovy, определенный как

env.list = ["abc","def"]

Если я попытаюсь использовать это в цикле for

for (letters in env.list) {
  print("Letter is $letters")
}

Он будет перебирать каждую букву и печатать следующее -

Letter is [
Letter is "
Letter is a
.....

Если я определю список следующим образом -

list = ["abc","def"]

Он будет обрабатываться как список.Цикл for выведет следующее:

Letter is abc
Letter is def

Использовал groovy для запуска моего конвейера Jenkins.

  1. Почему существует разница в зависимости от имени?
  2. Как мы можем определить список, используя имя переменной с точкой (.)?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Чтобы объяснить , почему такое происходит, лучше всего обратиться к исходному коду Jenkins.

Имя глобальной переменной - env, что приводит нас к * 1007.*.Это связывает значение со сценарием, который в данном случае является конвейером.

Исходный код :

    @Override public EnvActionImpl getValue(CpsScript script) throws Exception {
        Run<?,?> run = script.$build();
        if (run != null) {
            return EnvActionImpl.forRun(run);
        } else {
            throw new IllegalStateException("no associated build");
        }
    }

EnvActionImpl расширяет тип Groovy GroovyObjectSupport (исходный код) .GroovyObjectSupport имеет это в своей документации:

Полезный базовый класс для объектов Java, желающих быть объектами Groovy

Итак, это Дженкинс позволяет реализации JavaПозвольте ему установить его поведение для Groovy.Методы, которые вы используете, это public java.lang.Object getProperty(java.lang.String property) и public void setProperty(java.lang.String property, java.lang.Object newValue), поэтому мы рассмотрим подробнее их реализацию EnvActionImpl.

Для setProperty реализация здесь :

@Override public void setProperty(String propertyName, Object newValue) {
    env.put(propertyName, String.valueOf(newValue));
    try {
        owner.save();
    } catch (IOException x) {
        throw new RuntimeException(x);
    }
}

Взглянув вверх в классе, мы видим объявление env: private final Map<String,String> env;.В качестве ключа используется имя правильного имени (list в вашем примере), а значением является String.valueOf возвращаемое значение newValue, которое в вашем случае является строковым ["abc","def"].

Взгляд на setProperty:

@Override public String getProperty(String propertyName) {
    try {
        CpsThread t = CpsThread.current();
        return EnvironmentExpander.getEffectiveEnvironment(getEnvironment(), t.getContextVariable(EnvVars.class), t.getContextVariable(EnvironmentExpander.class)).get(propertyName);
    } catch (Exception x) {
        LOGGER.log(Level.WARNING, null, x);
        return null;
    }
}

Это может быть больше для понимания механики EnvironmentExpander и CpsThread, но самый быстрый способ - просто проверить подпись - public String.

Это объясняет, что Дженкинс делает под капотом с переменной env в конвейерных скриптах, и почему ваша итерация происходит по символам String, а не по списку, как вы могли ожидать.Если вы создали свою собственную переменную и попробовали ее самостоятельно, вы увидите разницу в поведении, например, Map и типа EnvActionImpl.

final myVar = [:]
myVar.list = ["abc","def"]
env.list = ["abc","def"]
echo "${myVar.list.getClass()}"
echo "${env.list.getClass()}"
0 голосов
/ 25 сентября 2018

в конвейере jenkins env - это переменная, которая содержит список переменных среды:

https://jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables

, а переменная среды может содержать только строку

поэтому, когда вы пытаетесь присвоить переменной окружения список - он автоматически преобразуется в строку

env.list = ["abc","def"]

, эквивалентную

env.list = ["abc","def"].toString()

, а затем вы перебираете строку по символу ...

...