From 6c45569ecd37a621d09610f02a976b6724014cbf Mon Sep 17 00:00:00 2001 From: Felipe Monteiro Date: Mon, 11 Jun 2018 16:39:07 -0400 Subject: [PATCH] docs: Add developer overview documentation This patchset adds developer overview documentation for providing a high-level introduction to Deckhand, including its architecture, modules, test utilities, Helm utilities, and other errata. This work is based off this Drydock patchset: https://review.openstack.org/#/c/571298/ Change-Id: Ic3382d4e04edf02a65184651d272fe9cd1db56a4 --- REVIEWING.rst | 38 ++++++ doc/requirements.txt | 1 + doc/source/HACKING.rst | 9 +- doc/source/REVIEWING.rst | 5 + doc/source/developer-overview.rst | 141 ++++++++++++++++++++ doc/source/diagrams/architecture-pegleg.uml | 39 ++++++ doc/source/diagrams/architecture.uml | 28 ++++ doc/source/getting-started.rst | 5 + doc/source/images/architecture-pegleg.png | Bin 0 -> 37601 bytes doc/source/images/architecture.png | Bin 0 -> 23231 bytes doc/source/index.rst | 2 + doc/source/revision-history.rst | 2 + doc/source/testing.rst | 10 +- tools/build-docs.sh | 11 ++ tools/whitespace-linter.sh | 1 + tox.ini | 9 +- 16 files changed, 288 insertions(+), 13 deletions(-) create mode 100644 REVIEWING.rst create mode 100644 doc/source/REVIEWING.rst create mode 100644 doc/source/developer-overview.rst create mode 100644 doc/source/diagrams/architecture-pegleg.uml create mode 100644 doc/source/diagrams/architecture.uml create mode 100644 doc/source/images/architecture-pegleg.png create mode 100644 doc/source/images/architecture.png create mode 100755 tools/build-docs.sh diff --git a/REVIEWING.rst b/REVIEWING.rst new file mode 100644 index 00000000..db2280b5 --- /dev/null +++ b/REVIEWING.rst @@ -0,0 +1,38 @@ +Reviewing Deckhand Code +======================= +To start read the `OpenStack Common Review Checklist +`_ + + +Unit Tests +---------- +For any change that adds new functionality to either common functionality or +fixes a bug unit tests are required. This is to ensure we don't introduce +future regressions and to test conditions which we may not hit in the gate +runs. + + +Functional Tests +---------------- +For any change that adds major new functionality functional tests are required. +This is to ensure that the Deckhand API follows the contract it promises. +In addition, functional tests are run against the Deckhand container, which +uses an image built from the latest source code to validate the integrity +of the image. + + +Deprecated Code +--------------- +Deprecated code should go through a deprecation cycle -- long enough for other +Airship projects to modify their code base to reference new code. Features, +APIs or configuration options are marked deprecated in the code. Appropriate +warnings will be sent to the end user, operator or library user. + + +When to approve +--------------- +* Every patch needs two +2s before being approved. +* Its OK to hold off on an approval until a subject matter expert reviews it. +* If a patch has already been approved but requires a trivial rebase to merge, + you do not have to wait for a second +2, since the patch has already had + two +2s. diff --git a/doc/requirements.txt b/doc/requirements.txt index c79deda9..280af85b 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -4,6 +4,7 @@ sphinx>=1.6.2 # BSD sphinx_rtd_theme==0.2.4 reno>=2.5.0 # Apache-2.0 +plantuml # NOTE(fmontei): The requirement below is only included because readthedocs # depends on it to work, since it only takes in one requirements file. diff --git a/doc/source/HACKING.rst b/doc/source/HACKING.rst index 5d9c0f16..53d3411c 100644 --- a/doc/source/HACKING.rst +++ b/doc/source/HACKING.rst @@ -13,7 +13,10 @@ See the License for the specific language governing permissions and limitations under the License. -======= -Hacking -======= +.. _coding-guide: + +===================== +Deckhand Coding Guide +===================== + .. include:: ../../HACKING.rst diff --git a/doc/source/REVIEWING.rst b/doc/source/REVIEWING.rst new file mode 100644 index 00000000..6d84d41e --- /dev/null +++ b/doc/source/REVIEWING.rst @@ -0,0 +1,5 @@ +======================= +Reviewing Deckhand Code +======================= + +.. include:: ../../REVIEWING.rst diff --git a/doc/source/developer-overview.rst b/doc/source/developer-overview.rst new file mode 100644 index 00000000..9ab67c92 --- /dev/null +++ b/doc/source/developer-overview.rst @@ -0,0 +1,141 @@ +.. + 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 Deckhand +============================== + +The core objective of Deckhand is to provide storage, rendering, validation and +version control for declarative YAML documents. Deckhand ingests raw, +Airship-formatted documents and outputs fully rendered documents to other +Airship components. + +Architecture +============ + +.. image:: images/architecture.png + :alt: High level architecture of Deckhand + +From a high-level perspective, Deckhand consists of a RESTful API, a document +rendering engine, and a PostgreSQL relational database for document storage. +Deckhand ingests Airship-formatted documents, validates them, and stores them +in its database for future processing. On demand, Deckhand will fully render +the documents, after which they can be consumed by the other Airship +components. + +Deckhand uses Barbican to securely storage sensitive document data. + +`Pegleg `_ in effect provides +Deckhand with a CLI, which facilitates communication with Deckhand. + +.. image:: images/architecture-pegleg.png + :alt: High level architecture of Deckhand + +Components +========== + +control +------- + +The ``control`` module is simply the RESTful API. It is based on the +`Falcon Framework `_ and utilizes +`oslo.policy `_ +for RBAC enforcement of the API endpoints. The normal deployment of Deckhand +uses `uWSGI `_ and PasteDeploy +to build a pipeline that includes Keystone Middleware for authentication +and role decoration of the request. + +The ``control`` module is also responsible for communicating with +`Barbican `_, which it uses to +store and retrieve document :ref:`secrets `, which it passes to the +``engine`` module for :ref:`rendering`. + +engine +------ + +The ``engine`` module is the interface responsible for all +:ref:`rendering`. Rendering consists of applying a series of algorithms to the +documents, including: topological sorting, :ref:`layering`, +:ref:`substitution`, and :ref:`replacement`. + +db +-- + +The ``db`` module is responsible for implementing the database tables needed +to store all Airship documents. The module also realizes version control and +:ref:`revision-diffing` functionality. + +client +------ + +The API client library provides an interface for other services to communicate +with Deckhand's API. Requires +`Keystone `_ authentication to +use. + +Developer Workflow +================== + +Because Airship is a container-centric platform, the developer workflow heavily +utilizes containers for testing and publishing. It also requires Deckhand 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. + +Deckhand strives to conform to the +`Airship coding conventions `_. + +Python +------ + +The Deckhand code base lives under ``/deckhand``. Deckhand supports py27 +and py35 interpreters. Once OpenStack deprecates usage of py27, Deckhand +will as well. + +See :ref:`coding-guide` for more information on contribution guidelines. + +Docker +------ + +The Deckhand Dockerfile is located in ``/images/deckhand`` 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 Deckhand Docker image. + +Helm +---- + +The Deckhand Helm chart is located in ``/charts/deckhand``. Local testing +currently only supports linting and previewing the rendered artifacts. +Richer functional chart testing is a TODO. + +* ``make charts`` - Pull down dependencies for the Deckhand charts and package + everything into a ``.tgz`` file. +* ``make helm_lint`` - Lint the Helm charts. +* ``make dry-run`` - Render the chart and output the Kubernetes manifest YAML + documents. + +Testing +======= + +All Deckhand tests are nested under ``/deckhand/tests``. + +Deckhand comes equipped with a number of +`tox `_ targets for running unit and +functional tests. See :ref:`development-utilities` for a list of commands. + +See :ref:`testing` for more information on testing guidelines. 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/diagrams/architecture.uml b/doc/source/diagrams/architecture.uml new file mode 100644 index 00000000..9b44c32a --- /dev/null +++ b/doc/source/diagrams/architecture.uml @@ -0,0 +1,28 @@ +' PlantUML file to generate the architecture component diagram +@startuml + +entity "HTTP" +entity "SQL" +entity "WSGI" + +frame "Deckhand" { + [Control] ..> [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] + +@enduml diff --git a/doc/source/getting-started.rst b/doc/source/getting-started.rst index 271ab34b..fcb59452 100644 --- a/doc/source/getting-started.rst +++ b/doc/source/getting-started.rst @@ -206,6 +206,8 @@ After, from the command line, execute: -v $CONF_DIR:/etc/deckhand \ quay.io/attcomdev/deckhand:latest server +.. _development-utilities: + Development Utilities --------------------- @@ -244,6 +246,9 @@ deployment, execute (respectively):: .. _Bandit: https://github.com/openstack/bandit +For additional commands, reference the ``tox.ini`` file for a list of all +the jobs. + Database Model Updates ---------------------- diff --git a/doc/source/images/architecture-pegleg.png b/doc/source/images/architecture-pegleg.png new file mode 100644 index 0000000000000000000000000000000000000000..ca821a8f7fc28428c305b2e8b65823a9de48fc2a GIT binary patch literal 37601 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 as its functional testing framework. Functional tests can be executed via:: - $ tox -e functional + $ tox -e functional-dev You can also run a subset of tests via a regex:: - $ tox -e functional -- gabbi.suitemaker.test_gabbi_document-crud-success-multi-bucket + $ tox -e functional-dev -- gabbi.suitemaker.test_gabbi_document-crud-success-multi-bucket The command executes ``tools/functional-tests.sh`` which: @@ -142,7 +144,7 @@ testing. To test Deckhand against a containerized image, run, for example: :: export DECKHAND_IMAGE=quay.io/attcomdev/deckhand:latest - tox -e functional + tox -e functional-dev Which will result in the following script output: diff --git a/tools/build-docs.sh b/tools/build-docs.sh new file mode 100755 index 00000000..8cd81e74 --- /dev/null +++ b/tools/build-docs.sh @@ -0,0 +1,11 @@ +#!/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 +rm -rf releasenotes/build +sphinx-build -W -b html doc/source doc/build/html +python -m plantuml doc/source/diagrams/*.uml +mv doc/source/diagrams/*.png doc/source/images diff --git a/tools/whitespace-linter.sh b/tools/whitespace-linter.sh index 3709cdf3..51ed41bd 100755 --- a/tools/whitespace-linter.sh +++ b/tools/whitespace-linter.sh @@ -6,6 +6,7 @@ RES=$(find . \ -not -path "*/*.egg-info/*" \ -not -path "*/releasenotes/build/*" \ -not -path "*/doc/build/*" \ + -not -path "*/doc/source/images/*" \ -not -name "*.tgz" \ -type f -exec egrep -l " +$" {} \;) diff --git a/tox.ini b/tox.ini index 50a07df8..6dd700b3 100644 --- a/tox.ini +++ b/tox.ini @@ -118,13 +118,10 @@ ignore = H405 exclude = .venv,.git,.tox,dist,*lib/python*,*egg,build,releasenotes,doc,alembic/versions [testenv:docs] -deps = -r{toxinidir}/doc/requirements.txt +deps = + -r{toxinidir}/doc/requirements.txt commands = - rm -rf doc/build - rm -rf releasenotes/build - sphinx-build -W -b html doc/source doc/build/html -whitelist_externals = - rm + {toxinidir}/tools/build-docs.sh [testenv:releasenotes] deps = -r{toxinidir}/doc/requirements.txt