SlideShare uma empresa Scribd logo
1 de 36
Baixar para ler offline
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

Mais conteúdo relacionado

Mais procurados

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

Mais procurados (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
 

Semelhante 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
 

Semelhante 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
 
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
 
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
 

Último (20)

VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
ManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide DeckManageIQ - Sprint 236 Review - Slide Deck
ManageIQ - Sprint 236 Review - Slide Deck
 
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
OpenChain - The Ramifications of ISO/IEC 5230 and ISO/IEC 18974 for Legal Pro...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
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
 
10 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 202410 Trends Likely to Shape Enterprise Technology in 2024
10 Trends Likely to Shape Enterprise Technology in 2024
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
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
 
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
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
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
 
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
 
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
 
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
 
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
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
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 Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 

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