У нас есть несколько классов в общей библиотеке, где мы должны получить доступ к шагам конвейера, используя объект DSL, поэтому я подумал, что он будет работать с кодом ниже:
Версия 1
class T {
def dsl
def T(def dsl) {
this.dsl = dsl
}
def F() {
this.dsl.with {
echo "Hello World"
}
}
}
new T(this).F()
Тем не менее, он генерирует следующее исключение безопасности скрипта:
Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object (T echo java.lang.String). Administrators can decide whether to approve or reject this signature.
[Pipeline] End of Pipeline
org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object (T echo java.lang.String)
Похоже, dsl.with { echo ... }
не переводится в dsl.echo
и вместо этого приводит к поиску echo
метод по class T
.Предполагая, что это какая-то проблема с делегатом замыкания, я попробовал следующее, и оно все еще не работало (та же ошибка, что и выше):
Версия 2
def withDsl(def body) {
body.delegate = this
this.with body
}
class T {
def dsl
def T(def dsl) {
this.dsl = dsl
}
def F() {
dsl.withDsl {
echo "Hello World"
}
}
}
new T(this).F()
Наконец-то это сработало, когда я создал оболочку поверх DSL и создал методы, которые просто делегировали вызовы DSL.Мне также пришлось изменить делегат замыкания, чтобы он работал:
Версия 3
class MyDsl {
def dsl
def MyDsl(def dsl) {
this.dsl = dsl
}
def echo(msg) {
dsl.echo msg
}
}
def withDsl(def body) {
def mydsl = new MyDsl(this)
body.delegate = mydsl
mydsl.with body
}
class T {
def dsl
def T(def dsl) {
this.dsl = dsl
}
def F() {
dsl.withDsl {
echo "Hello World"
}
}
}
new T(this).F()
Кто-нибудь может объяснить, почему первые две версии не будут работать?Есть ли что-то, что я могу сделать, чтобы избежать создания класса-обертки (что было бы больно)?