Was bewirkt @NonCPS in einem Jenkins-Pipeline-Skript?

110

Ich habe ein Pipeline-Skript in Jenkins.

Ich habe diese Ausnahme bekommen:

org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Skripte dürfen die Methode groovy.json.JsonSlurperClassic parseText java.lang.String nicht verwenden

Ich habe die Ausnahme nachgeschlagen und einige Hinweise gefunden, dass ich die Methode, bei der die Ausnahme auftritt, mit Anmerkungen versehen sollte @NonCPS. Ich habe das getan, ohne wirklich zu verstehen, was das tut.

Danach wurde eine Ausnahme, die ich in diese Methode geworfen habe, nicht mehr von einer tryKlausel erfasst.

Was ist die Idee dahinter @NonCPS? Welche Auswirkungen hat die Verwendung?

Oktavian
quelle
1
Der offizielle Blog von Jenkins enthält einen Artikel, der diese Anmerkung einführt und Ihnen möglicherweise hilft. jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice
袁文涛

Antworten:

141

Die Ausnahme, die Sie sehen, ist auf die Skriptsicherheit und das Sandboxing zurückzuführen. Wenn Sie ein Pipeline-Skript ausführen, wird es standardmäßig in einer Sandbox ausgeführt, in der nur bestimmte Methoden und Klassen verwendet werden können. Es gibt Möglichkeiten, Vorgänge auf die Whitelist zu setzen. Überprüfen Sie den obigen Link.

Die @NonCPSAnmerkung ist nützlich, wenn Sie Methoden haben, die Objekte verwenden, die nicht serialisierbar sind. Normalerweise müssen alle Objekte, die Sie in Ihrem Pipeline-Skript erstellen, serialisierbar sein (der Grund dafür ist, dass Jenkins den Status des Skripts serialisieren kann, damit es angehalten und auf der Festplatte gespeichert werden kann).

Wenn Sie @NonCPSeine Methode anwenden, führt Jenkins die gesamte Methode auf einmal aus, ohne pausieren zu können. Außerdem dürfen Sie innerhalb einer mit @NonCPSAnmerkungen versehenen Methode keine Pipeline-Schritte oder CPS-transformierten Methoden referenzieren . Weitere Informationen hierzu finden Sie hier .

Was die Ausnahmebehandlung betrifft: Nicht 100% sicher, was Sie erleben; Ich habe Folgendes versucht und es funktioniert wie erwartet:

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

try {
    myFunction();
} catch (Exception e) {
    echo "Caught";
}

und

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

def mySecondFunction() {
    try {
        myFunction();
    } catch (Exception e) {
        echo "Caught";
    }
}

mySecondFunction();

und schlussendlich:

@NonCPS
def myFunction() {
    throw new RuntimeException();
}

@NonCPS
def mySecondFunction() {
    try {
        myFunction();
    } catch (Exception e) {
        echo "Caught";
    }
}

mySecondFunction();

Alle drucken "Gefangen" wie erwartet.

Jon S.
quelle