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

Материал из noname.com.ua
Перейти к навигацииПерейти к поиску
 
(не показано 13 промежуточных версий этого же участника)
Строка 7: Строка 7:
 
Частный случай - требуется модифицировать params
 
Частный случай - требуется модифицировать params
 
=Суть проблемы=
 
=Суть проблемы=
  +
  +
У дженкинса есть переменная '''params''' которая представляет <BR>
  +
мапу параметров которые переданы на вход билду и которые не модифицируемым простым способом
  +
<PRE>
  +
println(params.getClass().getName()
  +
</PRE>
  +
<PRE>
  +
java.util.Collections$UnmodifiableMap
  +
</PRE>
  +
<BR>
  +
Доступ к ним можно получить по именами параметров
  +
<PRE>
  +
params.PARAMETER_1
  +
params.PARAMETER_2
  +
...
  +
params.PARAMETER_N
  +
</PRE>
  +
  +
Такая организация параметров приносит 2 проблемы
  +
# Если есть сторонний код который требует наличие параметров и подключается из библиотеки и который нельзя по какой-то причине модифицировать
  +
# Параметры попадают в переменные окружения всего исполняемого кода что накладывает ограничение на размер параметров
  +
Другими словами - параметры доступны в коде везде и всегда
  +
<PRE>
  +
sh "env"
  +
</PRE>
  +
<PRE>
  +
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
  +
...
  +
PARAMETER_1=MY_APP
  +
...
  +
</PRE>
  +
  +
=Зачем использовать параметры большого размера?=
  +
* Это удобно - можно не иметь в описании кучу параметров а иметь один, и через него передавать все что нужно
  +
<PRE>
  +
myJobConfiguration = readJSON text: params.SUPER_LARGE_PARAMETER_FOR_JOB_CONFIGURATION
  +
</PRE>
  +
  +
=Размер памяти отведенный под переменные окружения ограничен=
  +
* не помню точное значение для Linux но оно достаточно маленькое что бы в него можно было упереться
  +
<BR>
  +
Проблема преобретает остроту когда параметр оказывается большим - например тектовое поле в несколько килобайт,
  +
<BR>
  +
и в этом случае ломается практически все
  +
<BR>
  +
любой вызов конструкции
  +
<PRE>
  +
sh " ... "
  +
</PRE>
  +
завершается с ошибкой
  +
<PRE>
  +
Caused by: java.io.IOException: Cannot run program "/usr/bin/git" (in directory): error=7, Argument list too long
  +
</PRE>
  +
Если для исполнения простых скриптов можно придумать
  +
<PRE>
  +
withEnv(['LARGE_SIZE_PARAMETER=']) {
  +
sh "env"
  +
}
  +
</PRE>
  +
То для конструкций ниже например scm решение не работает.
  +
При этом плагин не стесняется вызывать под-капотом бинарник гита (и нахуя тогда нужен такой плагин? Вопрос открыт но имеем то что имеем)
  +
<PRE>
  +
withEnv(['LARGE_SIZE_PARAMETER=']) {
  +
dir(applicationName) {
  +
checkout scm: [
  +
$class:'GitSCM',
  +
branches : [[name: branch]],
  +
userRemoteConfigs: [[url: gitUrl, credentialsId: gitCredentialsId]]
  +
]
  +
}
  +
}
  +
</PRE>
  +
  +
=Решение=
  +
Код найден на прострах интернета и он позволяет модифицировать параметры
  +
<PRE>
  +
@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);
  +
}
  +
</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);'''

Текущая версия на 11: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);