Upgrade to Pro — share decks privately, control downloads, hide ads and more …

zc.buildout

 zc.buildout

Обзор инструмента для автоматизации сборки программ
и подготовки окружения для их выполнения.

Kirill Kuzminykh

November 11, 2017
Tweet

Other Decks in Programming

Transcript

  1. zc.buildout
    Обзор инструмента для автоматизации сборки программ
    и подготовки окружения для их выполнения.
    Кирилл Кузьминых (Cykooz)
    ASD Technologies
    2017

    View Slide

  2. 2
    История создания

    View Slide

  3. 3
    История создания
    Zope Corporation, начало 2000-ых:
    – помощь клиентам в соборке приложений на базе Zope;
    – очень большое разнообразие окружения - главная сложность в
    развёртывании приложения;
    – получение предскажуемого результата требует как то изолироваться
    от клиентского окружения.
    Решение:
    – собственная сборка Python в которую устанавливалось приложение;
    – автоматизация с помощью make.

    View Slide

  4. 4
    История создания
    2005 год:
    – приложения становятся сложнее – возникает желание
    использовать Python для автоматизации развёртывания;
    – внутренний прототип системы с конфигом на базе формата
    ConfigParser – секции описывали вещи, которые надо собирать;
    – несколько встроенных рецептов для сборки и возможность
    создавать сторонние рецепты;
    – всё ещё используется своя сборка Python для изоляции.
    Результат: решенно сделать zc.buildout.

    View Slide

  5. 5
    История создания
    Появились setuptools и easy_install. Они автоматизировали
    скачивание и установку пакетов и их зависимостей.
    Результат: новая версия zc.buildout использует setuptools.
    Но easy_install устанавливал зависимости, но не обновлял их.
    Результат: следующая версия zc.buildout использует setuptools
    на более низком уровне, реализуя свою логику работы с
    пакетами.

    View Slide

  6. 6
    Что это такое?

    View Slide

  7. 7
    Что это такое?
    Инструмент для автоматизации сборки программного
    обеспечения
    – Запуск инструментов для сборки программ
    – Выполнение программ и шаблонов для создания скриптов и
    конфигов
    – Применим на всех стадиях, от разработки до выкатки

    View Slide

  8. 8
    Что это такое?
    Это не совсем:
    – Make или Apache Ant
    Buildout – более высокоуровневый.
    Он сам может использовать make и ant как часть процесса сборки.
    – Puppet, chef и др.
    Buildout – сфокусирован на конкретном приложении.
    Puppet, chef и др. могут использовать buildout для решения своих
    задач.

    View Slide

  9. 9
    Что это такое?
    Принципы:
    – Воспроизводимость – результат сборки должен быть одинаков в
    одинаковом окружении (OS и версия Python).
    – Автоматизация – с помощью одной/двух простых команд должна
    получаться готовая к работе система.
    – Приложение должно быть самодостаточным настолько насколько
    это возможно.

    View Slide

  10. 10
    Как это выглядит?

    View Slide

  11. 11
    Как это выглядит?
    $ git clone myproject.git
    $ cd myproject
    .
    ├── src/
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  12. 12
    Как это выглядит?
    $ python bootstrap.py
    $ ./bin/buildout

    View Slide

  13. 13
    Как это выглядит?
    .
    ├── bin/
    │ ├── buildout
    │ ├── myscript
    │ └── ...
    ├── eggs/
    │ ├── requests-2.18.4-py2.7.egg/
    │ └── ...
    ├── src/
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  14. 14
    Как это выглядит?
    .
    ├── bin/
    │ ├── buildout
    │ ├── myscript
    │ └── ...
    ├── eggs/
    │ ├── requests-2.18.4-py2.7.egg/
    │ └── ...
    ├── src/
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  15. 15
    Как это выглядит?
    $ ./bin/myscript
    GET https://www.helloworld.org/data/helloworld
    Response body:
    #!/bin/bash
    echo "Hello world"

    View Slide

  16. 16
    А что там внутри?

    View Slide

  17. 17
    А что там внутри?
    .
    ├── bin/
    │ ├── buildout
    │ ├── myscript
    │ └── ...
    ├── eggs/
    │ ├── requests-2.18.4-py2.7.egg/
    │ └── ...
    ├── src/
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  18. 18
    А что там внутри?
    .
    └── src/
    ├── myapp/
    │ ├── __init__.py
    │ └── main.py
    └── setup.py

    View Slide

  19. 19
    А что там внутри?
    .
    └── src/
    ├── myapp/
    │ ├── __init__.py
    │ └── main.py
    └── setup.py

    View Slide

  20. 20
    ./src/setup.py
    from setuptools import setup
    setup(
    name='myapp',
    install_requires=[
    'setuptools',
    'requests',
    ],
    entry_points={
    'console_scripts': [
    'myscript = myapp.main:main',
    ]
    }
    )

    View Slide

  21. 21
    А что там внутри?
    .
    ├── src/
    │ ├── myapp/
    │ │ ├── __init__.py
    │ │ └── main.py
    │ └── setup.py
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  22. 22
    ./buildout.cfg
    [buildout]
    develop = ./src
    parts =
    myproject
    [myproject]
    recipe = zc.recipe.egg:scripts
    eggs =
    myapp

    View Slide

  23. 23
    А что там внутри?
    .
    ├── bin/
    │ ├── buildout
    │ ├── myscript
    │ └── ...
    ├── eggs/
    │ ├── requests-2.18.4-py2.7.egg/
    │ └── ...
    ├── src/
    ├── bootstrap.py
    └── buildout.cfg

    View Slide

  24. 24
    ./bin/myscipt
    #!/usr/bin/python
    import sys
    sys.path[0:0] = [
    '/home/user/myproject/src',
    '/home/user/myproject/eggs/requests-2.18.4-py2.7.egg',
    '/home/user/myproject/eggs/urllib3-1.22-py2.7.egg',
    ...
    ]
    import myapp.main
    if __name__ == '__main__':
    sys.exit(myapp.main.main())

    View Slide

  25. 25
    Возможности формата конфига

    View Slide

  26. 26
    Подстановка значений
    ${SECTION:OPTION}
    [myproject]
    recipe = zc.recipe.egg
    eggs = myapp
    initialization =
    import os
    os.environ['HOST'] = '${settings:host}'
    os.environ['POST'] = '${settings:port}'
    [settings]
    host = localhost
    port = 8080

    View Slide

  27. 27
    Наследование
    [buildout]
    extends =
    base.cfg
    https://example.com/kgs/versions-1.2.cfg
    [myproject]
    eggs +=
    myapp[test]
    ipython<6.0

    View Slide

  28. 28
    Добавление, вычитание, переопределение
    [buildout]
    extends = base.cfg
    parts +=
    tests
    build_docs
    parts -=
    nginx
    [myproject]
    eggs = myapp[test]

    View Slide

  29. 29
    Макросы
    [server]
    recipe = zc.zdaemonrecipe
    port = 8080
    program = ${buildout:bin-directory}/serve
    --port ${:port}
    --name ${:_buildout_section_name_}
    [server1]
    <= server
    port = 8081
    [server2]
    <= server
    port = 8082

    View Slide

  30. 30
    Зависимости
    [buildout]
    develop = .
    parts = run_app
    [run_app]
    => app
    recipe = collective.recipe.cmd
    on_install = true
    cmds = ${buildout:bin-directory}/app ${config:location}
    [app]
    recipe = zc.recipe.egg:scripts
    eggs = myapp

    View Slide

  31. 31
    Условные секции
    [create_dirs]
    recipe = collective.recipe.cmd
    on_install = true
    cmds = mkdir ${buildout:directory}/var
    [create_dirs:windows]
    cmds = md ${buildout:directory}\var
    [buildout:os.environ.get('ALPINELINUX')]
    find-links +=
    http://privat-pypi.com/simple/numpy

    View Slide

  32. 32
    Рецепты

    View Slide

  33. 33
    Рецепты
    Рецепт:
    – это компонент реализующий логику "части";
    – является обычным питонячим классом с методами:

    install()

    update()
    – в одном пакете может быть несколько рецептов;
    – Buildout автоматически скачивает и устнаваливает пакеты с
    рецептами.

    View Slide

  34. 34
    zc.recipe.egg:scripts
    [myproject]
    revipe = zc.recipe.egg:scripts
    eggs =
    myapp
    ipython<6.0
    interpreter = python
    find-links = https://domain.com/Django
    index = https://private-pypi.com/simple
    setting = myapp.production
    initialisation =
    import os
    os.environ.setdefault('DJANGO_SETTINGS_MODULE',
    '${:settings}')

    View Slide

  35. 35
    zc.recipe.egg:scripts
    ./bin/manage.py
    #!/usr/bin/python
    import sys
    sys.path[0:0] = [
    '/home/user/myproject/src',
    '/home/user/myproject/eggs/ipython-5.0.0-py2.7.egg',
    ...
    ]
    import os
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.production')
    import myapp.manage
    if __name__ == '__main__':
    sys.exit(myapp.manage.main())

    View Slide

  36. 36
    zc.recipe.egg:custom
    [pillow-simd-env]
    CC = cc -mavx2
    [pillow-simd]
    recipe = zc.recipe.egg:custom
    egg = Pillow-SIMD
    environment = pillow-simd-env

    View Slide

  37. 37
    zc.recipe.cmmi (configure-make-make-install)
    [librsync]
    recipe = zc.recipe.cmmi
    url = https://domain.com/librsync-0.9.7.tar.gz
    extra_options = --enable-shared
    [rdiff-backup]
    recipe = zc.recipe.egg:custom
    egg = rdiff-backup
    rpath = ${librsync:location}/lib
    include-dirs = ${librsync:location}/include
    library-dirs = ${librsync:location}/lib

    View Slide

  38. 38
    sact.recipe.jinjatemplate
    [configs]
    recipe = sact.recipe.jinjatemplate
    template-file =
    etc/templates/uwsgi.ini
    etc/templates/systemd/user/backend_uwsgi.service
    target-file =
    etc/uwsgi.ini
    etc/systemd/user/backend_uwsgi.service

    View Slide

  39. 39
    Расширения

    View Slide

  40. 40
    Расширения

    buildout.gc

    buildout.wheel

    mr.developer

    cykooz.buildout.basicauth

    cykooz.buildout.venv

    ...

    View Slide

  41. 41
    mr.developer
    [buildout]
    extensions = mr.developer
    auto-checkout = *
    sources-dir = ext_src
    [sources]
    twisted = git [email protected]:twisted/twisted.git
    six = git [email protected]:benjaminp/six.git rev=1.8.0

    View Slide

  42. 42
    mr.developer
    .
    ├── ext_src/
    │ ├── twisted/
    │ └── six/
    ├── src/
    └── buildout.cfg

    View Slide

  43. 43
    Воспроизводимость

    View Slide

  44. 44
    Воспроизводимость
    [buildout]
    allow-picked-versions = true
    show-picked-versions = true
    [versions]
    zc.buildout = 2.9.5
    zc.recipe.egg = 2.0.3
    setuptools = 36.6.0
    six = 1.8.0
    pyramid = 1.9.1

    View Slide

  45. 45
    Воспроизводимость
    [buildout]
    extends = versions.cfg
    allow-picked-versions = true
    show-picked-versions = true

    View Slide

  46. 46
    Воспроизводимость
    [buildout]
    extends = versions.cfg
    allow-picked-versions = true
    show-picked-versions = true
    update-versions-file = versions.cfg

    View Slide

  47. 47
    Интеграция с IDE

    View Slide

  48. 48
    PyCharm + zc.buildout

    View Slide

  49. 49
    Eclipse + PyDev + zc.buildout
    [buildout]
    develop = ./src
    parts =
    myproject
    pydev
    [myproject]
    recipe = zc.recipe.egg:scripts
    eggs = myapp
    [pydev]
    recipe = pb.recipes.pydev
    eggs = ${myproject:eggs}

    View Slide

  50. 50
    Other + zc.buildout
    [buildout]
    develop = ./src
    parts =
    myproject
    omelette
    [myproject]
    recipe = zc.recipe.egg:scripts
    eggs = myapp
    [omelette]
    recipe = collective.recipe.omelette
    eggs = ${myproject:eggs}

    View Slide

  51. 51
    Other + zc.buildout
    .
    └── parts/
    └── omelette/
    ├── certifi/
    ├── chardet/
    ├── idna/
    ├── myapp/
    ├── pkg_resources/
    ├── requests/
    ├── setuptools/
    ├── urllib3/
    └── easy_install.py

    View Slide

  52. 52
    Упссс...

    View Slide

  53. 53
    А как же Docker, Vagrant и т.п.?

    View Slide

  54. 54
    А как же Docker, Vagrant и т.п.?
    Пускай будут – они тоже полезные,
    но не заменяют Buildout.

    View Slide

  55. 55
    Вопросы

    View Slide

  56. 56
    Ссылки

    http://docs.buildout.org

    https://pypi.python.org/pypi/zc.buildout

    View Slide

  57. 57
    Ещё примеры...

    View Slide

  58. 58
    zc.recipe.cmmi (configure-make-make-install)
    [nginx]
    recipe = zc.recipe.cmmi
    url = http://sysoev.ru/nginx/nginx-0.7.65.tar.gz
    md5sum = abc4f76af450eedeb063158bd963feaa
    patch =
    ${buildout:directory}/nginx/upstream_hash.patch
    extra_options =
    --add-module=${buildout:directory}/nginx/upstream_hash

    View Slide