SlideShare una empresa de Scribd logo
1 de 36
Descargar para leer sin conexión
The Snake and theThe Snake and the
ButlerButler
Jenkins as a Python execution
platform
Who am I?Who am I?
Barak Korren
bkorren@redhat.com
http://ifireball.wordpress.com
https://twitter.com/BKorren
AgendaAgenda
● What is Jenkins / Why do it
● Running Python code
● Doing I/O
● Persisting state
Jenkins?Jenkins?
“CI/CD Automation tool"
Jenkins?Jenkins?
Jenkins?Jenkins?
Jenkins?Jenkins?
Why?Why?
Jenkins JobsJenkins Jobs
“Free Style" Pipeline
String code
String status_file = 'calculator_status.dat'
stage('Load code') {
dir('python-on-jenkins') {
git(
poll: false,
url: repo_url
)
code = readFile code_file
}
}
stage('Load data') {
step([
$class: 'CopyArtifact',
filter: status_file,
fingerprintArtifacts: true,
projectName: env.JOB_NAME,
optional: true,
])
}
RunningRunning
Python codePython code
Python cmd linePython cmd line
def main():
args = parse_args()
print("Hello {}".format(args.who))
def parse_args():
"""Parse command line arguments
"""
parser = argparse.ArgumentParser(
Description=
'Tool that says hello'
)
parser.add_argument(
'who',
default='world',
nargs='?'
)
return parser.parse_args()
Python pluginsPython plugins
● "python"
● "ShiningPanda"
● "jython"
Python for “free”Python for “free”
node {
stage('Say hello') {
sh '''
#!/usr/bin/env python
from __future__ import 
print_function
print('Hello world!')
'''.stripIndent()
}
}
Doing I/ODoing I/O
InputInput
from os import environ
name = environ.get('YOUR_NAME', 'World')
print('Hello {0}!'.format(name))
OutputOutput
with open('job_params.properties', 'w') as f:
f.write('YOUR_NAME={0}n'.format(name))
Move ObjectsMove Objects
def object_to_param_str(obj):
return b64encode(compress(
cPickle.dumps(obj)
)).decode('utf8')
def param_str_to_object(param_str):
return cPickle.loads(decompress(
b64decode(param_str.encode('utf8'))
))
Output to GroovyOutput to Groovy
build_spec = dict(
job='hello-with-params',
parameters=[{
'$class': 
'StringParameterValue',
'name': 'YOUR_NAME',
'value': name
}]
)
with open('bld_spec.json', 'w') as f:
json.dump(build_spec, f)
Output to GroovyOutput to Groovy
build_spec = dict(
job='hello-with-params',
parameters=[{
'$class': 
'StringParameterValue',
'name': 'YOUR_NAME',
'value': name
}]
)
with open('bld_spec.json', 'w') as f:
json.dump(build_spec, f)
build readJSON(
file: 'bld_spec.json'
)
Persisting statePersisting state
Persisting statePersisting state
Build #8Build #8 Build #9Build #9
Artifact StorageArtifact Storage
Archive Load
Persisting statePersisting state
def object_from_artifact(artifact_file, fallback_cls):
try:
with open(artifact_file) as fd:
return cPickle.load(fd)
except IOError as e:
# errno 2 is 'No such file or directory'
if e.errno == 2:
return fallback_cls()
raise
def object_to_artifact(obj, artifact_file):
with open(artifact_file, 'w') as fd:
cPickle.dump(obj, fd)
Persisting statePersisting state
@contextmanager
def persist_in_artifacts(artifact_file, fallback_cls):
obj = object_from_artifact(artifact_file,
fallback_cls)
yield obj
object_to_artifact(obj, artifact_file)
Persisting statePersisting state
@contextmanager
def persist_in_artifacts(artifact_file, fallback_cls):
obj = object_from_artifact(artifact_file,
fallback_cls)
yield obj
object_to_artifact(obj, artifact_file)
class CalculatorStatus(object):
def __init__(self):
self.current_value = 0
Persisting statePersisting state
@contextmanager
def persist_in_artifacts(artifact_file, fallback_cls):
obj = object_from_artifact(artifact_file,
fallback_cls)
yield obj
object_to_artifact(obj, artifact_file)
class CalculatorStatus(object):
def __init__(self):
self.current_value = 0
with persist_in_artifacts(status_file,
CalculatorStatus) as status:
status.current_value = ...
Persisting statePersisting state
stage('Load data') {
dir('state') { deleteDir(); touch(file: '_dummy_') }
step([
$class: 'CopyArtifact',
filter: status_file,
projectName: env.JOB_NAME,
optional: true,
])
}
stage('Run python') {
// ...
}
stage('Save data') {
archive status_file
}
RecapRecap
●
Running code via simple "shell" build
steps
● Input via env vars
●
Output via files (properties, json,
Pickle)
●
Object persistence via archived Pickle
files
Sharing the JVMSharing the JVM
● Jython:
– http://www.jython.org/
● Java classes in Jython
– https://github.com/jythontools/clamp/
● Python (Jython) Plugins
– https://github.com/jenkinsci/jenkins.py
Jython from GroovyJython from Groovy
// load interpreter from Maven
@Grab(group='org.python', module='jython-standalone',
version='2.7.0')
import org.python.util.PythonInterpreter
import org.python.core.PyString
Jython from GroovyJython from Groovy
@NonCPS
def loadPython() {
// create interpreter object
PythonInterpreter interpreter = new PythonInterpreter()
// compile and run python
interpreter.exec """
def some_python_func(some_arg):
# python code here...
""".stripIndent()
// return some functions
return interpreter.get('some_python_func')
}
Jython from GroovyJython from Groovy
pyfunc = loadPython()
# Call Python function
pyfunc.__call__(new PyString("some str..."))
ApplicationsApplications
//
DemoDemo
Thank You!Thank You!
● Slides:
– http://wp.me/p7png-Ct
● Source code:
– https://github.com/ifireball/python-on-jenkins
● Contact me:
– bkorren@redhat.com
Jenkins Job BuilderJenkins Job Builder
https://docs.openstack.org/infra/jenkins-job-builder/
- job-template:
name: some_job_a
parameters:
- name-params
builders:
- shell: !include-raw-escape: code.py
publishers:
- trigger-parameterized-builds:
- project: some_job_b
property-file: job_params.properties
condition: SUCCESS
ApplicationsApplications
● oVirt "Standard-CI":
– oVirt has many
different sub-projects
– The CI system is
project-agnostic
– Each project tell the CI
what to do
– We have local tool to
emulate CI system
ApplicationsApplications
●
oVirt “change-gating" flow:
– Runs “heavy” tests on batches of changes
– Runs bisection on failure to find root cause
Project 1Project 1
Project 2Project 2
Project NProject N
Change
queue
Change
queue
TestsTests

Más contenido relacionado

La actualidad más candente

Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
Chris Saylor
 

La actualidad más candente (20)

Redux Sagas - React Alicante
Redux Sagas - React AlicanteRedux Sagas - React Alicante
Redux Sagas - React Alicante
 
Memory Management on iOS
Memory Management on iOSMemory Management on iOS
Memory Management on iOS
 
Functional Reactive Programming - RxSwift
Functional Reactive Programming - RxSwiftFunctional Reactive Programming - RxSwift
Functional Reactive Programming - RxSwift
 
Callbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascriptCallbacks, promises, generators - asynchronous javascript
Callbacks, promises, generators - asynchronous javascript
 
Asynchronous programming done right - Node.js
Asynchronous programming done right - Node.jsAsynchronous programming done right - Node.js
Asynchronous programming done right - Node.js
 
Ian 20150116 java script oop
Ian 20150116 java script oopIan 20150116 java script oop
Ian 20150116 java script oop
 
Testable Javascript
Testable JavascriptTestable Javascript
Testable Javascript
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
Containers & Dependency in Ember.js
Containers & Dependency in Ember.jsContainers & Dependency in Ember.js
Containers & Dependency in Ember.js
 
Realm.io par Clement Sauvage
Realm.io par Clement SauvageRealm.io par Clement Sauvage
Realm.io par Clement Sauvage
 
JavaScript Promises
JavaScript PromisesJavaScript Promises
JavaScript Promises
 
JavaScript promise
JavaScript promiseJavaScript promise
JavaScript promise
 
React Native Evening
React Native EveningReact Native Evening
React Native Evening
 
Intro to Advanced JavaScript
Intro to Advanced JavaScriptIntro to Advanced JavaScript
Intro to Advanced JavaScript
 
Javascript: the important bits
Javascript: the important bitsJavascript: the important bits
Javascript: the important bits
 
Managing parallelism using coroutines
Managing parallelism using coroutinesManaging parallelism using coroutines
Managing parallelism using coroutines
 
Node Boot Camp
Node Boot CampNode Boot Camp
Node Boot Camp
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
jQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journeyjQuery Data Manipulate API - A source code dissecting journey
jQuery Data Manipulate API - A source code dissecting journey
 
History of jQuery
History of jQueryHistory of jQuery
History of jQuery
 

Similar a The Snake and the Butler

用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
Felinx Lee
 
Projeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdfProjeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdf
AdrianoSantos888423
 
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
bradburgess22840
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
Adam Getchell
 
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
Jerry Chou
 
Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012
Anton Arhipov
 

Similar a The Snake and the Butler (20)

Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...Python Functions Tutorial | Working With Functions In Python | Python Trainin...
Python Functions Tutorial | Working With Functions In Python | Python Trainin...
 
Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0Building an api using golang and postgre sql v1.0
Building an api using golang and postgre sql v1.0
 
Declarative Data Modeling in Python
Declarative Data Modeling in PythonDeclarative Data Modeling in Python
Declarative Data Modeling in Python
 
Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...
 
Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)Django for IoT: From hackathon to production (DjangoCon US)
Django for IoT: From hackathon to production (DjangoCon US)
 
用Tornado开发RESTful API运用
用Tornado开发RESTful API运用用Tornado开发RESTful API运用
用Tornado开发RESTful API运用
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Building l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground upBuilding l10n Payroll Structures from the Ground up
Building l10n Payroll Structures from the Ground up
 
Projeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdfProjeto-web-services-Spring-Boot-JPA.pdf
Projeto-web-services-Spring-Boot-JPA.pdf
 
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docxIn Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
In Class AssignmetzCST280W13a-1.pdfCST 280 In-Class Pract.docx
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
An Overview Of Python With Functional Programming
An Overview Of Python With Functional ProgrammingAn Overview Of Python With Functional Programming
An Overview Of Python With Functional Programming
 
Functional Core, Reactive Shell
Functional Core, Reactive ShellFunctional Core, Reactive Shell
Functional Core, Reactive Shell
 
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
[PyCon 2014 APAC] How to integrate python into a scala stack to build realtim...
 
Pruebas unitarias con django
Pruebas unitarias con djangoPruebas unitarias con django
Pruebas unitarias con django
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012Binary patching for fun and profit @ JUG.ru, 25.02.2012
Binary patching for fun and profit @ JUG.ru, 25.02.2012
 
Тестирование и Django
Тестирование и DjangoТестирование и Django
Тестирование и Django
 
High Performance tDiary
High Performance tDiaryHigh Performance tDiary
High Performance tDiary
 

Último

introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
VishalKumarJha10
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
shinachiaurasa2
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 

Último (20)

introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
SHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions PresentationSHRMPro HRMS Software Solutions Presentation
SHRMPro HRMS Software Solutions Presentation
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 

The Snake and the Butler

  • 1. The Snake and theThe Snake and the ButlerButler Jenkins as a Python execution platform
  • 2. Who am I?Who am I? Barak Korren bkorren@redhat.com http://ifireball.wordpress.com https://twitter.com/BKorren
  • 3. AgendaAgenda ● What is Jenkins / Why do it ● Running Python code ● Doing I/O ● Persisting state
  • 9. Jenkins JobsJenkins Jobs “Free Style" Pipeline String code String status_file = 'calculator_status.dat' stage('Load code') { dir('python-on-jenkins') { git( poll: false, url: repo_url ) code = readFile code_file } } stage('Load data') { step([ $class: 'CopyArtifact', filter: status_file, fingerprintArtifacts: true, projectName: env.JOB_NAME, optional: true, ]) }
  • 11. Python cmd linePython cmd line def main(): args = parse_args() print("Hello {}".format(args.who)) def parse_args(): """Parse command line arguments """ parser = argparse.ArgumentParser( Description= 'Tool that says hello' ) parser.add_argument( 'who', default='world', nargs='?' ) return parser.parse_args()
  • 12. Python pluginsPython plugins ● "python" ● "ShiningPanda" ● "jython"
  • 13. Python for “free”Python for “free” node { stage('Say hello') { sh ''' #!/usr/bin/env python from __future__ import print_function print('Hello world!') '''.stripIndent() } }
  • 15. InputInput from os import environ name = environ.get('YOUR_NAME', 'World') print('Hello {0}!'.format(name))
  • 16. OutputOutput with open('job_params.properties', 'w') as f: f.write('YOUR_NAME={0}n'.format(name))
  • 17. Move ObjectsMove Objects def object_to_param_str(obj): return b64encode(compress( cPickle.dumps(obj) )).decode('utf8') def param_str_to_object(param_str): return cPickle.loads(decompress( b64decode(param_str.encode('utf8')) ))
  • 18. Output to GroovyOutput to Groovy build_spec = dict( job='hello-with-params', parameters=[{ '$class': 'StringParameterValue', 'name': 'YOUR_NAME', 'value': name }] ) with open('bld_spec.json', 'w') as f: json.dump(build_spec, f)
  • 19. Output to GroovyOutput to Groovy build_spec = dict( job='hello-with-params', parameters=[{ '$class': 'StringParameterValue', 'name': 'YOUR_NAME', 'value': name }] ) with open('bld_spec.json', 'w') as f: json.dump(build_spec, f) build readJSON( file: 'bld_spec.json' )
  • 21. Persisting statePersisting state Build #8Build #8 Build #9Build #9 Artifact StorageArtifact Storage Archive Load
  • 22. Persisting statePersisting state def object_from_artifact(artifact_file, fallback_cls): try: with open(artifact_file) as fd: return cPickle.load(fd) except IOError as e: # errno 2 is 'No such file or directory' if e.errno == 2: return fallback_cls() raise def object_to_artifact(obj, artifact_file): with open(artifact_file, 'w') as fd: cPickle.dump(obj, fd)
  • 23. Persisting statePersisting state @contextmanager def persist_in_artifacts(artifact_file, fallback_cls): obj = object_from_artifact(artifact_file, fallback_cls) yield obj object_to_artifact(obj, artifact_file)
  • 24. Persisting statePersisting state @contextmanager def persist_in_artifacts(artifact_file, fallback_cls): obj = object_from_artifact(artifact_file, fallback_cls) yield obj object_to_artifact(obj, artifact_file) class CalculatorStatus(object): def __init__(self): self.current_value = 0
  • 25. Persisting statePersisting state @contextmanager def persist_in_artifacts(artifact_file, fallback_cls): obj = object_from_artifact(artifact_file, fallback_cls) yield obj object_to_artifact(obj, artifact_file) class CalculatorStatus(object): def __init__(self): self.current_value = 0 with persist_in_artifacts(status_file, CalculatorStatus) as status: status.current_value = ...
  • 26. Persisting statePersisting state stage('Load data') { dir('state') { deleteDir(); touch(file: '_dummy_') } step([ $class: 'CopyArtifact', filter: status_file, projectName: env.JOB_NAME, optional: true, ]) } stage('Run python') { // ... } stage('Save data') { archive status_file }
  • 27. RecapRecap ● Running code via simple "shell" build steps ● Input via env vars ● Output via files (properties, json, Pickle) ● Object persistence via archived Pickle files
  • 28. Sharing the JVMSharing the JVM ● Jython: – http://www.jython.org/ ● Java classes in Jython – https://github.com/jythontools/clamp/ ● Python (Jython) Plugins – https://github.com/jenkinsci/jenkins.py
  • 29. Jython from GroovyJython from Groovy // load interpreter from Maven @Grab(group='org.python', module='jython-standalone', version='2.7.0') import org.python.util.PythonInterpreter import org.python.core.PyString
  • 30. Jython from GroovyJython from Groovy @NonCPS def loadPython() { // create interpreter object PythonInterpreter interpreter = new PythonInterpreter() // compile and run python interpreter.exec """ def some_python_func(some_arg): # python code here... """.stripIndent() // return some functions return interpreter.get('some_python_func') }
  • 31. Jython from GroovyJython from Groovy pyfunc = loadPython() # Call Python function pyfunc.__call__(new PyString("some str..."))
  • 33. Thank You!Thank You! ● Slides: – http://wp.me/p7png-Ct ● Source code: – https://github.com/ifireball/python-on-jenkins ● Contact me: – bkorren@redhat.com
  • 34. Jenkins Job BuilderJenkins Job Builder https://docs.openstack.org/infra/jenkins-job-builder/ - job-template: name: some_job_a parameters: - name-params builders: - shell: !include-raw-escape: code.py publishers: - trigger-parameterized-builds: - project: some_job_b property-file: job_params.properties condition: SUCCESS
  • 35. ApplicationsApplications ● oVirt "Standard-CI": – oVirt has many different sub-projects – The CI system is project-agnostic – Each project tell the CI what to do – We have local tool to emulate CI system
  • 36. ApplicationsApplications ● oVirt “change-gating" flow: – Runs “heavy” tests on batches of changes – Runs bisection on failure to find root cause Project 1Project 1 Project 2Project 2 Project NProject N Change queue Change queue TestsTests