From adb23bc2a6b441cd3c2509bed2aa4c8b9d512374 Mon Sep 17 00:00:00 2001 From: Felipe Monteiro Date: Thu, 13 Sep 2018 15:50:13 -0600 Subject: [PATCH] docs: Add developer overview guide This patch set introduces a developer overview documentation page to Pegleg to help developers onboard. Change-Id: Ia453d76f024db39c6bdd97a44bfe1db1c25193f9 --- doc/requirements.txt | 6 ++ doc/source/cli.rst | 2 + doc/source/developer-overview.rst | 104 ++++++++++++++++++++ doc/source/diagrams/architecture-pegleg.uml | 39 ++++++++ doc/source/images/architecture-pegleg.png | Bin 0 -> 37597 bytes doc/source/index.rst | 8 ++ tools/gate/build-docs.sh | 10 ++ tools/gate/playbooks/zuul-linter.yaml | 2 +- tox.ini | 20 ++-- 9 files changed, 179 insertions(+), 12 deletions(-) create mode 100644 doc/source/developer-overview.rst create mode 100644 doc/source/diagrams/architecture-pegleg.uml create mode 100644 doc/source/images/architecture-pegleg.png create mode 100755 tools/gate/build-docs.sh diff --git a/doc/requirements.txt b/doc/requirements.txt index 38d8f59d..d3cd9da8 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,3 +1,9 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. + # Documentation sphinx>=1.6.2 sphinx_rtd_theme==0.2.4 +# UML image generation +plantuml diff --git a/doc/source/cli.rst b/doc/source/cli.rst index a0c39555..9cc297a0 100644 --- a/doc/source/cli.rst +++ b/doc/source/cli.rst @@ -14,6 +14,8 @@ License for the specific language governing permissions and limitations under the License. +.. _pegleg-cli: + ========== Pegleg CLI ========== diff --git a/doc/source/developer-overview.rst b/doc/source/developer-overview.rst new file mode 100644 index 00000000..7db0eed6 --- /dev/null +++ b/doc/source/developer-overview.rst @@ -0,0 +1,104 @@ +.. + Copyright 2018 AT&T Intellectual Property. + All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); you may + not use this file except in compliance with the License. You may obtain + a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + License for the specific language governing permissions and limitations + under the License. + +============================ +Developer Overview of Pegleg +============================ + +Pegleg's core mission is to, alongside Deckhand, facilitate document authoring +strategies within `Airship`_, by: + +* aggregating documents across multiple revisioned repositories, each of + which contains multiple documents defining sites' software and hardware + stacks +* providing early linting of documents prior to their collection and + eventual deployment +* including utility functions enabling operators and developers alike to list + available sites, render individual manifests via `Deckhand`_, bootstrap + repositories with Pegleg-compliant directory layouts, to name a few + +Architecture +============ + +Pegleg, as a CLI, has a rather simplistic architecture. It is meaningful to +visualize Pegleg alongside Deckhand: + +.. image:: images/architecture-pegleg.png + :alt: High level architecture of Pegleg + Deckhand + +Components +========== + +cli +--- + +The Pegleg ``cli`` module implements the user-facing CLI. For more information +about this module, reference the :ref:`CLI documentation `. + +engine +------ + +The ``engine`` module implements the following functionality: + +* document linting +* document rendering via `Deckhand`_ +* document aggregation +* additional document utility functions + +Developer Workflow +================== + +Because Airship is a container-centric platform, the developer workflow heavily +utilizes containers for testing and publishing. It also requires Pegleg to +produce multiple artifacts that are related, but separate: the Python package, +the Docker image and the Helm chart. The code is published via the +Docker image artifact. + +Pegleg strives to conform to the `Airship coding conventions`_. + +Python +------ + +The Pegleg code base lives under ``/src/bin/pegleg``. Pegleg supports py35 +interpreters. + +Docker +------ + +The Pegleg Dockerfile is located in ``/images/pegleg`` along with any +artifacts built specifically to enable the container image. Make targets are +used for generating and testing the artifacts. + +* ``make images`` - Build the Pegleg Docker image. + +Pegleg, as a containerized CLI, uses Docker via ``tools/pegleg.sh`` to +execute CLI commands. Commands can also be executed using the ``Makefile`` +target: ``run_pegleg``. + +Testing +======= + +All Pegleg tests are nested under ``/src/bin/pegleg/tests``. + +Pegleg comes equipped with a number of `tox`_ targets for running unit tests, +as well as `pep8`_ and `Bandit`_ checks. + +.. _Airship: https://airshipit.readthedocs.io +.. _Deckhand: https://airship-deckhand.readthedocs.io/en/latest/ +.. _Airship coding conventions: http://airshipit.readthedocs.io/en/latest/conventions.html +.. _tox: https://tox.readthedocs.io/en/latest/ +.. _pep8: https://www.python.org/dev/peps/pep-0008/ +.. _Bandit: https://github.com/PyCQA/bandit diff --git a/doc/source/diagrams/architecture-pegleg.uml b/doc/source/diagrams/architecture-pegleg.uml new file mode 100644 index 00000000..0d4017f7 --- /dev/null +++ b/doc/source/diagrams/architecture-pegleg.uml @@ -0,0 +1,39 @@ +' PlantUML file to generate the architecture component diagram +@startuml + +actor "DE" +entity "HTTP" +entity "SQL" +entity "WSGI" + +frame "Deckhand" { + [Control] ..> [Engine] +} + +frame "Pegleg" { + [Pegleg CLI] ..> [Pegleg Engine] +} + +frame "OpenStack Components" { + [Barbican] ..> [Secret Store Back-end] + [Keystone] +} + +database "PostgreSQL" { + SQL - [deckhand_db] +} + +HTTP - [uWSGI] +[uWSGI] --> [Keystone Middleware] +[Keystone Middleware] --> WSGI +WSGI - [Control] +[Engine] --> [SQL] +[Control] --> [Barbican] +[Pegleg Engine] --> [Engine] +DE -> [Pegleg CLI] + +legend right + DE: Deployment Engineer +endlegend + +@enduml diff --git a/doc/source/images/architecture-pegleg.png b/doc/source/images/architecture-pegleg.png new file mode 100644 index 0000000000000000000000000000000000000000..173c7aef4cac90ce225f918cf1db61a4b57ab89a GIT binary patch literal 37597 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
L{7)H^zPy7M&xP--h*ZhKHARlPd9G^BKeS^rIC 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%0DTIGSNFk(@D84 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 U=akrVi|`eBX%#8#{fE!~57)wP&j0`b literal 0 HcmV?d00001 diff --git a/doc/source/index.rst b/doc/source/index.rst index 07299691..365a21b5 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -35,6 +35,14 @@ Design artifacts authoring_strategy +Developer's Guide +----------------- + +.. toctree:: + :maxdepth: 2 + + developer-overview + Operator's Guide ---------------- diff --git a/tools/gate/build-docs.sh b/tools/gate/build-docs.sh new file mode 100755 index 00000000..04f9750f --- /dev/null +++ b/tools/gate/build-docs.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# Builds documentation and generates documentation diagrams from .uml +# files. Must be run from root project directory. + +set -ex +rm -rf doc/build +sphinx-build -b html doc/source doc/build/html -W -n -v +python -m plantuml doc/source/diagrams/*.uml +mv doc/source/diagrams/*.png doc/source/images diff --git a/tools/gate/playbooks/zuul-linter.yaml b/tools/gate/playbooks/zuul-linter.yaml index dd379553..7a903715 100644 --- a/tools/gate/playbooks/zuul-linter.yaml +++ b/tools/gate/playbooks/zuul-linter.yaml @@ -15,6 +15,6 @@ - hosts: primary tasks: - name: Execute a Whitespace Linter check - command: find . -not -path "*/\.*" -not -path "*/doc/build/*" -not -name "*.tgz" -type f -exec egrep -l " +$" {} \; + command: find . -not -path "*/\.*" -not -path "*/doc/build/*" -not -path "*/doc/source/images/*" -not -name "*.tgz" -type f -exec egrep -l " +$" {} \; register: result failed_when: result.stdout != "" diff --git a/tox.ini b/tox.ini index ce96fd4f..093a2bd8 100644 --- a/tox.ini +++ b/tox.ini @@ -17,35 +17,33 @@ commands = {posargs} [testenv:py35] basepython = python3.5 commands = - # Run all unit tests under src/bin/pegleg - tox -c src/bin/pegleg/tox.ini -e py35 + # Run all unit tests under src/bin/pegleg + tox -c src/bin/pegleg/tox.ini -e py35 whitelist_externals = tox [testenv:py36] basepython = python3.6 commands = - # Run all unit tests under src/bin/pegleg - tox -c src/bin/pegleg/tox.ini -e py36 + # Run all unit tests under src/bin/pegleg + tox -c src/bin/pegleg/tox.ini -e py36 whitelist_externals = tox [testenv:fmt] basepython = python3 commands = - tox -c src/bin/pegleg/tox.ini -e fmt + tox -c src/bin/pegleg/tox.ini -e fmt whitelist_externals = tox [testenv:pep8] basepython = python3 commands = - tox -c src/bin/pegleg/tox.ini -e pep8 + tox -c src/bin/pegleg/tox.ini -e pep8 whitelist_externals = tox [testenv:docs] basepython = python3 deps = - -r{toxinidir}/src/bin/pegleg/requirements.txt - -r{toxinidir}/doc/requirements.txt + -r{toxinidir}/src/bin/pegleg/requirements.txt + -r{toxinidir}/doc/requirements.txt commands = - rm -rf doc/build - sphinx-build -b html doc/source doc/build -n -W -v -whitelist_externals = rm + {toxinidir}/tools/gate/build-docs.sh