Jenkins Groovy Modify Params Map: различия между версиями

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 10 промежуточных версий этого же участника)
Строка 8: Строка 8:
 
=Суть проблемы=
 
=Суть проблемы=
   
У дженкинса есть переменная ```params``` которая представляет <BR>
+
У дженкинса есть переменная '''params''' которая представляет <BR>
 
мапу параметров которые переданы на вход билду и которые не модифицируемым простым способом
 
мапу параметров которые переданы на вход билду и которые не модифицируемым простым способом
 
<PRE>
 
<PRE>
Строка 27: Строка 27:
 
Такая организация параметров приносит 2 проблемы
 
Такая организация параметров приносит 2 проблемы
 
# Если есть сторонний код который требует наличие параметров и подключается из библиотеки и который нельзя по какой-то причине модифицировать
 
# Если есть сторонний код который требует наличие параметров и подключается из библиотеки и который нельзя по какой-то причине модифицировать
# Параметры попадают в переменные окружения всего исполняемого кода
+
# Параметры попадают в переменные окружения всего исполняемого кода что накладывает ограничение на размер параметров
 
Другими словами - параметры доступны в коде везде и всегда
 
Другими словами - параметры доступны в коде везде и всегда
 
<PRE>
 
<PRE>
Строка 33: Строка 33:
 
</PRE>
 
</PRE>
 
<PRE>
 
<PRE>
JENKINS_HOME=/var/lib/jenkins
 
...
 
JOB_BASE_NAME=build-frontend-application
 
 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
 
...
 
PARAMETER_1=MY_APP
 
PARAMETER_1=MY_APP
  +
...
 
</PRE>
 
</PRE>
   
 
=Зачем использовать параметры большого размера?=
 
=Зачем использовать параметры большого размера?=
  +
* Это удобно - можно не иметь в описании кучу параметров а иметь один, и через него передавать все что нужно
  +
<PRE>
  +
myJobConfiguration = readJSON text: params.SUPER_LARGE_PARAMETER_FOR_JOB_CONFIGURATION
  +
</PRE>
   
  +
=Размер памяти отведенный под переменные окружения ограничен=
deploymentConfiguration = readJSON text: params.DEPLOYMENT_CONFIGURATION
 
  +
* не помню точное значение для Linux но оно достаточно маленькое что бы в него можно было упереться
 
  +
<BR>
Проблема преобретает остроту когда параметр оказывается большим - например тектовое поле в несколько килобайт, и в этом случае ломается практичесуи все - любой вызов конструкции
+
Проблема преобретает остроту когда параметр оказывается большим - например тектовое поле в несколько килобайт,
 
  +
<BR>
  +
и в этом случае ломается практически все
  +
<BR>
  +
любой вызов конструкции
  +
<PRE>
 
sh " ... "
 
sh " ... "
  +
</PRE>
 
завершается с ошибкой
 
завершается с ошибкой
  +
<PRE>
 
 
Caused by: java.io.IOException: Cannot run program "/usr/bin/git" (in directory): error=7, Argument list too long
 
Caused by: java.io.IOException: Cannot run program "/usr/bin/git" (in directory): error=7, Argument list too long
  +
</PRE>
 
 
Если для исполнения простых скриптов можно придумать
 
Если для исполнения простых скриптов можно придумать
 
<PRE>
 
<PRE>
Строка 56: Строка 65:
 
sh "env"
 
sh "env"
 
}
 
}
  +
</PRE>
 
 
То для конструкций ниже например scm решение не работает.
 
То для конструкций ниже например scm решение не работает.
 
При этом плагин не стесняется вызывать под-капотом бинарник гита (и нахуя тогда нужен такой плагин? Вопрос открыт но имеем то что имеем)
 
При этом плагин не стесняется вызывать под-капотом бинарник гита (и нахуя тогда нужен такой плагин? Вопрос открыт но имеем то что имеем)
Строка 70: Строка 79:
 
}
 
}
 
</PRE>
 
</PRE>
 
   
 
=Решение=
 
=Решение=
  +
Код найден на прострах интернета и он позволяет модифицировать параметры
 
<PRE>
 
<PRE>
 
@NonCPS
 
@NonCPS
Строка 92: Строка 101:
 
}
 
}
 
</PRE>
 
</PRE>
  +
  +
<PRE>
  +
addOrReplaceParamValue("LARGE_SIZE_PARAMETER", "no-data")
  +
</PRE>
  +
  +
У этого решения есть интереснейший side-effect , при попытке вызвать Rebuild в параметре '''LARGE_SIZE_PARAMETER''' окажется не то что было изначально, а '''"no-data"'''
  +
<BR>
  +
Тип параметра может отличаться: <BR>
  +
''' def pv = new hudson.model.StringParameterValue(name,value);'''<BR>
  +
''' def pv = new hudson.model.TextParameterValue(name,value);'''

Текущая версия на 10:38, 29 апреля 2022


Частный случай - требуется модифицировать params

Суть проблемы

У дженкинса есть переменная params которая представляет
мапу параметров которые переданы на вход билду и которые не модифицируемым простым способом

println(params.getClass().getName()
java.util.Collections$UnmodifiableMap


Доступ к ним можно получить по именами параметров

params.PARAMETER_1
params.PARAMETER_2
...
params.PARAMETER_N

Такая организация параметров приносит 2 проблемы

  1. Если есть сторонний код который требует наличие параметров и подключается из библиотеки и который нельзя по какой-то причине модифицировать
  2. Параметры попадают в переменные окружения всего исполняемого кода что накладывает ограничение на размер параметров

Другими словами - параметры доступны в коде везде и всегда

sh "env"
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
...
PARAMETER_1=MY_APP
...

Зачем использовать параметры большого размера?

  • Это удобно - можно не иметь в описании кучу параметров а иметь один, и через него передавать все что нужно
myJobConfiguration = readJSON text: params.SUPER_LARGE_PARAMETER_FOR_JOB_CONFIGURATION

Размер памяти отведенный под переменные окружения ограничен

  • не помню точное значение для Linux но оно достаточно маленькое что бы в него можно было упереться


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

sh " ... "

завершается с ошибкой

Caused by: java.io.IOException: Cannot run program "/usr/bin/git" (in directory): error=7, Argument list too long

Если для исполнения простых скриптов можно придумать

withEnv(['LARGE_SIZE_PARAMETER=']) {
 sh "env"
}

То для конструкций ниже например scm решение не работает. При этом плагин не стесняется вызывать под-капотом бинарник гита (и нахуя тогда нужен такой плагин? Вопрос открыт но имеем то что имеем)

withEnv(['LARGE_SIZE_PARAMETER=']) {
  dir(applicationName) {
    checkout scm: [
      $class:'GitSCM',
      branches         : [[name: branch]],
      userRemoteConfigs: [[url: gitUrl, credentialsId: gitCredentialsId]]
    ]
  }
}

Решение

Код найден на прострах интернета и он позволяет модифицировать параметры

@NonCPS
def addOrReplaceParamValue(name, value) {
    def build = currentBuild.getRawBuild();
    def npl = new ArrayList<StringParameterValue>()
    def pv = new hudson.model.StringParameterValue(name,value);
    npl.add(pv);
    def newPa = null
    def oldPa = build.getAction(hudson.model.ParametersAction.class)
    if (oldPa != null) {
        build.actions.remove(oldPa)
        newPa = oldPa.createUpdated(npl)
    } else {
        newPa = new hudson.model.ParametersAction(npl)
    }

    return build.actions.add(newPa);
}
addOrReplaceParamValue("LARGE_SIZE_PARAMETER", "no-data")

У этого решения есть интереснейший side-effect , при попытке вызвать Rebuild в параметре LARGE_SIZE_PARAMETER окажется не то что было изначально, а "no-data"
Тип параметра может отличаться:
def pv = new hudson.model.StringParameterValue(name,value);
def pv = new hudson.model.TextParameterValue(name,value);