2016-07-07 8 views
5

Ich muss Werte aus einer Datei in meiner Pipeline lesen. Ich benutze split(), die sie in eine Array setzt. Ich muss sie in eine Arraylist setzen, also verwende ich Arrays.asList(). Das Problem, das ich habe ist, ich bin nicht in der Lage, die size() oder Länge() verwenden Methoden so kann ich nicht für eine Schleife bilden, wie beispielsweiseJenkins pipeline - Wie man durch eine Liste iteriert

for (ii = 0; ii < var.length; ii++) 

oder

for (ii = 0; ii < var.size; ii++) 

weil ich Fehler: nicht klassifiziert Feld java.util.Arrays $ Arraylist Länge

So habe ich versucht, eine für jede Schleife zu verwenden, aber wenn ich nehme eine Aktion (wie ls Befehl zum Beispiel) in meinem finally Block es iteriert nur 1 mal. Aber wenn ich nur den Befehl 'echo' benutze, dann iteriert es für jedes Element wie es sein soll. Gibt es einen Ratschlag, wie Sie meinen Code so ändern können, dass er für jedes Element in der Liste bei jedem Befehl iteriert wird?

richtig funktioniert ....

node{ 
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) { 
     HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n")) 
     deploy(HOST) 
    } 
} 

@NonCPS 
def deploy(host){ 
    for (String target : host){ 
     try { 
      echo target 
     } 
     finally { 
      echo target 
     } 
    } 
} 

OUTPUT (Iterierten für jedes Element):

[Pipeline] node 
Running on <obfuscated> 
[Pipeline] { 
[Pipeline] wrap 
provisoning config files... 
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated> 
[Pipeline] { 
[Pipeline] readFile 
[Pipeline] echo 
www.testhost.com 
[Pipeline] echo 
www.testhost.com 
[Pipeline] echo 
www.testhost2.com 
[Pipeline] echo 
www.testhost2.com 
[Pipeline] } 
Deleting 1 temporary files 
[Pipeline] // wrap 
[Pipeline] } 
[Pipeline] // node 
[Pipeline] End of Pipeline 
Finished: SUCCESS 

Aber wenn ich nehme eine Aktion wie 'ls -l' es nur Iterierten 1 Mal

node{ 
    wrap([$class: 'ConfigFileBuildWrapper', managedFiles: [[fileId: 'dest_hosts.txt', targetLocation: '', variable: 'DEST_HOST']]]) { 
     HOST = Arrays.asList(readFile(env.DEST_HOST).split("\\r?\\n")) 
     deploy(HOST) 
    } 
} 

@NonCPS 
def deploy(host){ 
    for (String target : host){ 
     try { 
      echo target 
     } 
     finally { 
      sh 'ls -l' 
     } 
    } 
} 

OUTPUT (nur 1 Mal iteriert):

[Pipeline] node 
Running on <obfuscated> 
[Pipeline] { 
[Pipeline] wrap 
provisoning config files... 
copy managed file [<obfuscated>] to file:/var/lib/jenkins/<obfuscated> 
[Pipeline] { 
[Pipeline] readFile 
[Pipeline] echo 
www.testhost.com 
[Pipeline] sh 
[sandbox%2Fpipeline-test-new1] Running shell script 
+ ls -l 
total 8 
-rw-r--r-- 1 jenkins jenkins 10 Jun 17 16:07 someFile 
[Pipeline] } 
Deleting 1 temporary files 
[Pipeline] // wrap 
[Pipeline] } 
[Pipeline] // node 
[Pipeline] End of Pipeline 
Finished: SUCCESS 

Antwort

5

ArrayList (und in der Regel Lists) keine Länge oder Größe Bereich haben, haben sie eine size() Methode. So verwenden, die im für:

for (ii = 0; ii < var.size(); ii++) 
+0

Danke das funktioniert. Obwohl ich immer noch neugierig bin, warum die zweite for-Schleife oben nur einmal iteriert, irgendwelche Ideen? – mdo123

+0

Ich habe jetzt etwas ähnliches erlebt. Soweit ich das beurteilen kann, hängt es mit dem 'sh'-Aufruf zusammen. Hast du etwas darüber herausgefunden? – pmmaga

+0

@pmmaga nein Entschuldigung, ich habe nicht darüber nachgedacht. Ich habe gerade @ krzyks Antwort verwendet, aber ich habe @ krzyks Antwort nicht akzeptiert, weil ich glaube, dass ein Teil der Antwort eine Erklärung zu dem oben beschriebenen Verhalten enthalten sollte. Warum arbeitet die Schleife für jede Schleife mit "echo" im finally-Block, sondern iteriert nur einmal, wenn der Befehl sh ausgeführt wird. Ich dachte, vielleicht würde der sh cmd einen Nicht-Null-Exit-Status zurückgeben, aber der für jede Schleife sollte für jedes Element fortfahren, also bin ich mir nicht sicher. – mdo123

1

Ich kann Ihnen nicht genau sagen, warum, wie ich nicht gedacht habe, wie alle notwendigen Informationen über Jenkins zu finden, ohne stundenlang googeln, aber ich kann Ihnen sagen, dieses:

Für einen Moment dachte ich, Sie können es gut laufen lassen, indem Sie 'echo line' NACH dem sh 'echo $ line' hinzufügen, aber es stellte sich heraus, dass Jenkins eine VORHERIGE Version des Skripts ausgeführt hat ...

Ich habe alle möglichen Dinge ausprobiert und keiner von ihnen hat funktioniert, dann habe ich folgendes gefunden:

Why an each loop in a Jenkinsfile stops at first iteration

Es ist ein bekannter Bug in Jenkins Pipeline!

(die bekannten Fehler ist JENKINS-26481, die "nur einmal vom Workflow-Plugin verwaltet innerhalb von Groovy CPS DSL-Skripte Mindestens einige Schließungen werden ausgeführt", sagt)

2

Gemäß diesem Tutorial: https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md#serializing-local-variables

...a method marked with the annotation @NonCPS ... will be treated as “native” by the Pipeline engine, and its local variables never saved. However it may not make any calls to Pipeline steps

In Ihrem Fall ist der Aufruf sh ein Pipeline-Schritt-Vorgang, den Sie anscheinend nicht innerhalb einer @NonCPS annotierten Methode ausführen können.

In Bezug auf das Drehen eines Arrays in eine List, dann, da wir in Groovy Land sind, können Sie einfach die .toList() Methode auf dem Array verwenden.

Verwandte Themen