From 20873ad4f9e837f030184073fddf5ebe9285e2e8 Mon Sep 17 00:00:00 2001 From: Scott Hussey Date: Wed, 30 May 2018 14:31:53 -0500 Subject: [PATCH] Update docs for developer overview - New diagrams and documents for developer overview - Update conf.py for docs to work w/ readthedocs.io - Add policy and config gen to `make docs` - Update zuul-linter to support checked in images - Last fix to document publishing Change-Id: I4faa1b87032ae5b0e786aa0fd998f809124b7987 --- .zuul.yaml | 20 +-- Makefile | 20 ++- docs/diagrams/architecture.uml | 23 ++++ docs/diagrams/basic_task_sequence.uml | 43 ++++++ docs/requirements-doc.txt | 4 + docs/source/conf.py | 2 - docs/source/development.rst | 148 +++++++++++++++++++++ docs/source/getting_started.rst | 45 +++---- docs/source/images/architecture.png | Bin 0 -> 21469 bytes docs/source/images/basic_task_sequence.png | Bin 0 -> 58414 bytes docs/source/index.rst | 8 +- docs/source/policy-enforcement.rst | 4 +- drydock_provisioner/config.py | 1 - drydock_provisioner/error.py | 2 +- etc/drydock/drydock-config-generator.conf | 1 - etc/drydock/drydock-policy-generator.conf | 1 - etc/drydock/drydock.conf.sample | 44 +++++- etc/drydock/policy.yaml.sample | 12 +- requirements-host.txt | 1 + tools/gate/playbooks/doc-publish.yaml | 2 +- tools/gate/playbooks/zuul-linter.yaml | 4 +- tox.ini | 11 +- 22 files changed, 329 insertions(+), 67 deletions(-) create mode 100644 docs/diagrams/architecture.uml create mode 100644 docs/diagrams/basic_task_sequence.uml create mode 100644 docs/requirements-doc.txt create mode 100644 docs/source/development.rst create mode 100644 docs/source/images/architecture.png create mode 100644 docs/source/images/basic_task_sequence.png diff --git a/.zuul.yaml b/.zuul.yaml index d0f01dfa..82f1667f 100644 --- a/.zuul.yaml +++ b/.zuul.yaml @@ -122,13 +122,13 @@ XapfJuj7tAkFF+jeaWamB5CMiC+4M3zsrReB2/kqbxGFXC0nQ9q9AbVg48zCZFxNTVMLj J5K79voMoMmFoP14trhneFDs1Ki8FOLU1fqU7KrBYrlixI4FJwJ6ljEM9C/OvU= token: !encrypted/pkcs1-oaep - - StrExdiOzIVLYO5xvvqXkIWXCWhdXREnl2VcgmPdfQnKgZ5KgDbtOnATMmowkijOtk3ov - zH3O5arOdjawoqwWQ/9mHDfTLQZfphU6S3J2PrUoMOkWs0UoXVyS577ECSxbA9m4t6x+G - Vfe2Uq8u12CUAomXGUlDBPgpTcKCFFLuQX9qF7FwEQ6I218QlzncVlwo2mGQ0PEGRzVWK - l/KrZxrH8HzNPsB2+SqvYakj/7Ps3q3gedmk8Wq3q6xcdaXvKxmk4zcdvi03bzcmptDhE - meRw/FZCHWEfclgWTDM+MbjqFXdhUTXO/JcjsofwrL3hOEV/3xm8+5XJhdfjUeFUbVw2t - E/ZrJYscRzrTtSA4FAbS9XKO2YwixwvCsm7jSHkfQVf3P9bhczveOWllmTmWEzSvPxN+P - 4oXPNnbxVRLgkISuh5kzBIcbXv8aWpcr9/EHTZCPLXqmY2x1sE1RbPOsNxDZqvllgM87k - gHzCDPd39o2KnrNpS++f2hB7xv8DonnyAqFLsH3os/BbkIIdkRwF2p5I/1az47aheET8m - QuZdGYtIzn0OeHfrKmUoF21D6G+zilwo9Gcy1qZQhWzvnIWgswCgzmnImVVT1DaEW97cW - lgKmZ4uApQ6/TitoiFb4l3R/6iQqqHA+yLl3LvFkmGbGwt4fB9su0+r5BpASQ8= + - i6Js243rxTsL0V1l5UWsJalCiRh3kYs54nBz0M9KKrE5YYdAYkD59jKSPncUeG7V+VTkr + LuwGpI837r/oaYqD7g4ZZhsE/X+xSE1PSdtsSY3t5GZZAPdKG4oSLxl0buTd23JsS6cU4 + 7IAh4Q28wtaIXg8fZ69KVkGm2f2nXPNKbUH/yPTjFW51yEXI55AClNKzv+mVKLd1PNdCN + USQkmF4fvgFreQym+NkZrUh78YMQI1uNT1e7rhD/jxYCjhZGAEr0Clxiu8UmLIRvxHgc2 + 2SM99xT8s0/dRudePkSz3zXSagwWvdat8bHqpGHJrakjZvePtGeZrdk20v7JQHt8T3XBp + InfWRB8ad/gDvgpstXiag4EHsJ7tnFuwsFDh+KSYySBjtkbYqY8Rx8lQ5qW/Qgk96LagJ + yzpin6EquBcnnPNTGTYLRF9jtowzbI8G9ItRRWdvkIQSlMQDxROI4bVEnfLHgRMbAKVjF + 1oSaiEzMwMHj356qYBS06pBBF3Dr/OCIZNiBy3UU8J6OJt2XchMgy9TVhsGkj+HE092d+ + mADSwkA5TpfWJCo8rqTDO8cCXIeiG8kBoxjph5m7YNWUcbuRDQdbga1FjV4lMe9bMyOo5 + AJ6O8hl3q7CJElLw6Z7p9vW2wHUf/xr242pZnk70DiMkyXxzJFLLqvRsWctTDc= diff --git a/Makefile b/Makefile index d79f4e8a..efb3dd82 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,10 @@ BUILD_DIR := $(shell mktemp -d) DOCKER_REGISTRY ?= quay.io IMAGE_NAME ?= drydock -IMAGE_PREFIX ?= attcomdev -IMAGE_TAG ?= latest +IMAGE_PREFIX ?= airshipit +IMAGE_TAG ?= dev HELM := $(BUILD_DIR)/helm -PROXY ?= http://one.proxy.att.com:8080 +PROXY ?= http://proxy.foo.com:8000 USE_PROXY ?= false PUSH_IMAGE ?= false LABEL ?= commit-id @@ -108,9 +108,21 @@ security: external_dep tox -e bandit .PHONY: drydock_docs -drydock_docs: external_dep +drydock_docs: external_dep render_diagrams genpolicy genconfig tox -e docs +.PHONY: render_diagrams +render_diagrams: + plantuml -v -tpng -o ../source/images docs/diagrams/*.uml + +.PHONY: genpolicy +genpolicy: + tox -e genpolicy + +.PHONY: genconfig +genconfig: + tox -e genconfig + .PHONY: clean clean: rm -rf $(BUILD_DIR)/* diff --git a/docs/diagrams/architecture.uml b/docs/diagrams/architecture.uml new file mode 100644 index 00000000..fa2a586a --- /dev/null +++ b/docs/diagrams/architecture.uml @@ -0,0 +1,23 @@ +' PlantUML file to generate the architecture component diagram +@startuml + +frame "Drydock" { + [Control] ..> [Statemgr] + [Orchestrator] ..> [Statemgr] + [Orchestrator] ..> [Ingester] + [Orchestrator] ..> [Driver] +} + +database "Postgres" { + SQL - [drydock_db] +} + +HTTP - [uWSGI] +[uWSGI] --> [Keystone Middleware] +[Keystone Middleware] --> WSGI +WSGI - [Control] +[Statemgr] --> [SQL] +[Driver] --> [MAAS] + + +@enduml diff --git a/docs/diagrams/basic_task_sequence.uml b/docs/diagrams/basic_task_sequence.uml new file mode 100644 index 00000000..8947992e --- /dev/null +++ b/docs/diagrams/basic_task_sequence.uml @@ -0,0 +1,43 @@ +' PlantUML file describing the basic task execution +' sequence diagram +@startuml +actor User + +== Task Creation == + +User -> TasksAPI : POST task body +TasksAPI -> oslo_policy : Enforce RBAC +oslo_policy -> TasksAPI : Approved +TasksAPI -> Statemgr : Insert Task as Queued +Statemgr -> TasksAPI : Result +TasksAPI -> User : Serialized Task + +== Task Execution == + +Orchestrator -> Statemgr : Poll for Queued Tasks +Statemgr -> Orchestrator : Task ID of Queued Task +Orchestrator -> Statemgr : Update Task to Running +Statemgr -> Orchestrator : Result +Orchestrator -> Orchestrator : Execute task +Orchestrator -> Ingester : Ingest Site Design +Ingester -> Statemgr : Resolve Design Reference +Statemgr -> Ingester : Raw Site Design +Ingester -> Orchestrator : Parsed Site Design +Orchestrator -> Orchestrator : Create Subtask +Orchestrator ->> Driver : Execute Subtask +par Threaded Task Execution + Driver -> Driver : Execute 1 or More Actions + Driver -> Statemgr : Update Subtask to Complete + Statemgr -> Driver : Result + loop Until Subtask Complete or Timeout + Orchestrator -> Statemgr : Poll Subtask Status + Statemgr -> Orchestrator : Subtask Status + end +end +Orchestrator -> Statemgr : Update Task to Complete + +== Task Query == + +User -> TasksAPI : GET task + +@enduml diff --git a/docs/requirements-doc.txt b/docs/requirements-doc.txt new file mode 100644 index 00000000..17d655b1 --- /dev/null +++ b/docs/requirements-doc.txt @@ -0,0 +1,4 @@ +sphinx>=1.6.2 +sphinx_rtd_theme==0.2.4 +oslo.versionedobjects +falcon diff --git a/docs/source/conf.py b/docs/source/conf.py index e1579ca6..16e1c81b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -34,8 +34,6 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.viewcode', - 'oslo_config.sphinxconfiggen', - 'oslo_policy.sphinxpolicygen' ] # oslo_config.sphinxconfiggen options diff --git a/docs/source/development.rst b/docs/source/development.rst new file mode 100644 index 00000000..a179947d --- /dev/null +++ b/docs/source/development.rst @@ -0,0 +1,148 @@ +.. + 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 Drydock +============================= + +The core objective of Drydock is to fully deploy physical servers based on +a declarative YAML topology. The actual provisioning work is completed by +a downstream 3rd party tool managed by a pluggable driver. The initial use-case +is Canonical MAAS. + +Architecture +============ + +.. image:: images/architecture.png + :alt: High level architecture of Drydock + +At a very high level Drydock is a very simple workflow engine fronted by a RESTful +API and maintains state in a Postgres relational database. Clients create a task +via the API that defines two main attributes of an action and a reference to a site design +or topology. The Drydock orchestrator will asynchronously execute the task while +the client polls the API for task status. Once execution is complete, the task status +is updated with results and the orchestrator will move to the next queued task. + +.. image:: images/basic_task_sequence.png + :alt: Sequence diagram of basic task execution. + +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 Drydock +uses `uWSGI `_ and PasteDeploy +to build a pipeline that includes Keystone Middleware for authentication +and role decoration of the request. + +Statemgr +-------- + +The ``statemgr`` module is the interface into all backing stores for Drydock. +This is mainly a `Postgres `_, but Drydock +also uses the state manager for accessing external URLs to ingest site designs. +Interactions with Postgres use the core libraries of +`SQLAlchemy `_ (not the ORM). + +Ingester +-------- + +The ``ingester`` module is basically a pluggable translator between external site definitions +(currently supports YAML formats) and the internal object model. Most of the internal object +model utilizes oslo_versionedobjects, much to my regret. + +Orchestrator +------------ + +The ``orchestrator`` module is the brain of the task execution. It requests queued tasks +from the state manager and when one is available, it executes it. The orchestrator is +single-threaded in that only a single user-created task is executed at once. However, that +task can spawn many subtasks that may be executed concurrently depending on their synchronization +requirements. For some actions, the orchestrator creates subtasks that are handed off to the +driver for execution. A common question about this module is why Drydock doesn't use Celery +as a task management engine. The simple answer is that it wasn't considered due to unfamiliarity +at the time. + +Driver +------ + +The ``driver`` module is a framework that supports pluggable drivers to execute task actions. The +subtle difference between the ``driver`` and ``orchestrator`` modules is the orchestrator manages +a wide scope of task execution that may cross the boundaries of a single driver plugin. Each driver +plugin is more focused on using a single downstream tool to accomplish the actions. + +Developer Workflow / Test Cycle +=============================== + +Because Airship is a container-centric platform, the developer workflow heavily utilizes containers +for testing and publishing. It also requires Drydock 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. + +Drydock strives to conform to the `Airship coding conventions `_. + +Python +------ + +The Drydock Python codebase is under ``/drydock_provisioner`` and the testing is under ``/tests``. The +developer tools expect to run on Ubuntu 16.04 and you'll need GNU ``make`` available. With that you +should be able to use make targets for testing code changes: + + * ``make pep8`` - Lint the Python code against the PEP8 coding standard + * ``make unit_tests`` - Run the local unit tests + * ``make security`` - Scan the code with `Bandit `_ + * ``make coverage_test`` - Run unit tests and Postgres integration tests + +Docker +------ + +The Drydock dockerfile is located in ``/images/drydock`` along with any artifacts built specifically +to enable the container image. Again make targets are used for generating and testing the artifacts. + + * ``make images`` - Build the Drydock Docker image. See :ref:`make-options` below. + * ``make run_images`` - Build the image and then run a rudimentary local test + +Helm +---- + +The Drydock helm chart is located in ``/charts/drydock``. Local testing currently only supports linting +and previewing the rendered artifacts. Richer functional chart testing is a TODO. + + * ``make helm_lint`` - Lint the Helm chart + * ``make dry-run`` - Render the chart and output the Kubernetes manifest YAML documents + +.. _make-options: + +Makefile Options +---------------- + +The Makefile supports a few options that override default values to allow use behind +a proxy or for geneting the Docker image with custom tags. + + * ``DOCKER_REGISTRY`` - Defaults to ``quay.io``, used as the Docker registry for tagging images + * ``IMAGE_NAME`` - Defaults to ``drydock``, the image name. + * ``IMAGE_PREFIX`` - Defaults to ``airshipit``, the registry organization to push images into + * ``IMAGE_TAG`` - Defaults to ``dev``, a tag to apply to the image + * ``PUSH_IMAGE`` - Defaults to ``false``, set to ``true`` if you want the build process to also + push the image. Likely will require you have previously run ``docker login``. + * ``PROXY`` - A HTTP/HTTPS proxy server to add to the image build environment. Required if you + are building the image behind a proxy. + * ``USE_PROXY`` - Defaults to ``false``, set to ``true`` to include the ``PROXY`` configuration + above in the build. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 73118693..dbb5e4ba 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -22,56 +22,43 @@ Bootstrap Kubernetes -------------------- You can bootstrap your Helm-enabled Kubernetes cluster via the Openstack-Helm -`AIO `_ -or the `Promenade `_ tools. +`AIO `_ +or the `Promenade `_ tools. Deploy Drydock and Dependencies ------------------------------- Drydock is most easily deployed using Armada to deploy the Drydock container into a Kubernetes cluster via Helm charts. The Drydock chart -is in `aic-helm `_. It depends on -the deployments of the `MaaS `_ -chart and the `Keystone `_ chart. +is in the ``charts/drydock`` directory. It depends on +the deployments of the `MaaS `_ +chart and the `Keystone `_ chart. A integrated deployment of these charts can be accomplished using the -`Armada `_ tool. An example integration +`Armada `_ tool. An example integration chart can be found in the -`UCP-Integration `_ repo in the -``./manifests/basic_ucp`` directory. - -.. code:: bash - - $ git clone https://github.com/att-comdev/ucp-integration - $ sudo docker run -ti -v $(pwd):/target -v ~/.kube:/armaada/.kube quay.io/attcomdev/armada:master apply --tiller-host --tiller-port 44134 /target/manifests/basic_ucp/ucp-armada.yaml - $ # wait for all pods in kubectl get pods -n ucp are 'Running' - $ KS_POD=$(kubectl get pods -n ucp | grep keystone | cut -d' ' -f1) - $ TOKEN=$(docker run --rm --net=host -e 'OS_AUTH_URL=http://keystone-api.ucp.svc.cluster.local:80/v3' -e 'OS_PASSWORD=password' -e 'OS_PROJECT_DOMAIN_NAME=default' -e 'OS_PROJECT_NAME=service' -e 'OS_REGION_NAME=RegionOne' -e 'OS_USERNAME=drydock' -e 'OS_USER_DOMAIN_NAME=default' -e 'OS_IDENTITY_API_VERSION=3' kolla/ubuntu-source-keystone:3.0.3 openstack token issue -f shell | grep ^id | cut -d'=' -f2 | tr -d '"') - $ docker run --rm -ti --net=host -e "DD_TOKEN=$TOKEN" -e "DD_URL=http://drydock-api.ucp.svc.cluster.local:9000" -e "LC_ALL=C.UTF-8" -e "LANG=C.UTF-8" $DRYDOCK_IMAGE /bin/bash - +`Airship in a Bottle `_ repo in the +``./manifests/dev_single_node`` directory. Load Site --------- To use Drydock for site configuration, you must craft and load a site topology -YAML. An example of this is in ``./examples/designparts_v1.0.yaml``. +YAML. An example of this is in ``./test/yaml_samples/deckhand_fullsite.yaml``. Documentation on building your topology document is at :ref:`topology_label`. -Use the Drydock CLI create a design and load the configuration - -.. code:: bash - - # drydock design create - # drydock part create -d -f +Drydock requires that the YAML topology be hosted somewhere, either the preferred +method of using `Deckhand `_ +or through a simple HTTP server like Nginx or Apache. Use the CLI to create tasks to deploy your site .. code:: bash - # drydock task create -d -a verify_site - # drydock task create -d -a prepare_site - # drydock task create -d -a prepare_node - # drydock task create -d -a deploy_node + # drydock task create -d -a verify_site + # drydock task create -d -a prepare_site + # drydock task create -d -a prepare_nodes + # drydock task create -d -a deploy_nodes A demo of this process is available at https://asciinema.org/a/133906 diff --git a/docs/source/images/architecture.png b/docs/source/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..00a6f936b0a89471aadbd4aa408d7c9a78b4b3b7 GIT binary patch literal 21469 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 literal 0 HcmV?d00001 diff --git a/docs/source/index.rst b/docs/source/index.rst index 7656dc82..ac1fef2e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -37,7 +37,6 @@ Drydock Configuration Guide policy-enforcement exceptions/index - API Documentation ----------------- .. toctree:: @@ -48,6 +47,13 @@ API Documentation bootaction validatedesign +Developer Overview +------------------ +.. toctree:: + :maxdepth: 1 + + development + Client Documentation -------------------- diff --git a/docs/source/policy-enforcement.rst b/docs/source/policy-enforcement.rst index bb7d8525..83b33f0e 100644 --- a/docs/source/policy-enforcement.rst +++ b/docs/source/policy-enforcement.rst @@ -20,6 +20,6 @@ auto-generated from Drydock when this documentation is built, so if you are having issues with an option, please compare your version of Drydock with the version of this documentation. -The sample policy file can also be viewed in `file form <_static/drydock.policy.yaml.sample>`_. +The sample policy file can also be viewed in `file form <_static/policy.yaml.sample>`_. -.. literalinclude:: _static/drydock.policy.yaml.sample +.. literalinclude:: _static/policy.yaml.sample diff --git a/drydock_provisioner/config.py b/drydock_provisioner/config.py index f47074dd..51981a54 100644 --- a/drydock_provisioner/config.py +++ b/drydock_provisioner/config.py @@ -238,7 +238,6 @@ def _import_modules(module_names): for module_name in module_names: module = importlib.import_module(module_name) if hasattr(module, 'list_opts'): - print("Pulling options from module %s" % module.__name__) imported_modules.append(module) return imported_modules diff --git a/drydock_provisioner/error.py b/drydock_provisioner/error.py index 7d65a1d6..fe353f7a 100644 --- a/drydock_provisioner/error.py +++ b/drydock_provisioner/error.py @@ -187,7 +187,7 @@ class InvalidAssetLocation(BootactionError): class BuildDataError(Exception): """ **Message:** *Error saving build data - data_element type - could not be cast to string. + could not be cast to string*. **Troubleshoot:** diff --git a/etc/drydock/drydock-config-generator.conf b/etc/drydock/drydock-config-generator.conf index f5c4cef9..097e92b8 100644 --- a/etc/drydock/drydock-config-generator.conf +++ b/etc/drydock/drydock-config-generator.conf @@ -1,5 +1,4 @@ [DEFAULT] -output_file = etc/drydock/drydock.conf.sample wrap_width = 80 namespace = drydock_provisioner diff --git a/etc/drydock/drydock-policy-generator.conf b/etc/drydock/drydock-policy-generator.conf index ec019203..71c08309 100644 --- a/etc/drydock/drydock-policy-generator.conf +++ b/etc/drydock/drydock-policy-generator.conf @@ -1,5 +1,4 @@ [DEFAULT] -output_file = etc/drydock/policy.yaml.sample wrap_width = 80 namespace = drydock_provisioner diff --git a/etc/drydock/drydock.conf.sample b/etc/drydock/drydock.conf.sample index 47772415..0ba497f2 100644 --- a/etc/drydock/drydock.conf.sample +++ b/etc/drydock/drydock.conf.sample @@ -8,15 +8,23 @@ # value) #poll_interval = 10 +# How long a leader has to check-in before leadership can be usurped, in seconds +# (integer value) +#leader_grace_period = 300 -[bootdata] +# How often will an instance attempt to claim leadership, in seconds (integer +# value) +#leadership_claim_interval = 30 + + +[database] # # From drydock_provisioner # -# Path to file to distribute for prom_init.sh (string value) -#prom_init = /etc/drydock/bootdata/join.sh +# The URI database connect string. (string value) +#database_connect_string = [keystone_authtoken] @@ -218,6 +226,16 @@ #auth_section = +[libvirt_driver] + +# +# From drydock_provisioner +# + +# Polling interval in seconds for querying libvirt status (integer value) +#poll_interval = 10 + + [logging] # @@ -228,7 +246,7 @@ #log_level = INFO # Logger name for the top-level logger (string value) -#global_logger_name = drydock +#global_logger_name = drydock_provisioner # Logger name for OOB driver logging (string value) #oobdriver_logger_name = ${global_logger_name}.oobdriver @@ -285,10 +303,10 @@ # From drydock_provisioner # -# Module path string of a input ingester to enable (multi valued) +# Module path string of a input ingester to enable (string value) #ingester = drydock_provisioner.ingester.plugins.yaml.YamlIngester -# Module path string of a OOB driver to enable (multi valued) +# List of module path strings of OOB drivers to enable (list value) #oob_driver = drydock_provisioner.drivers.oob.pyghmi_driver.PyghmiDriver # Module path string of the Node driver to enable (string value) @@ -298,6 +316,16 @@ #network_driver = +[pyghmi_driver] + +# +# From drydock_provisioner +# + +# Polling interval in seconds for querying IPMI status (integer value) +#poll_interval = 10 + + [timeouts] # @@ -331,3 +359,7 @@ # Timeout in minutes for deploying a node (integer value) #deploy_node = 45 + +# Timeout in minutes between deployment completion and the all boot actions +# reporting status (integer value) +#bootaction_final_status = 15 diff --git a/etc/drydock/policy.yaml.sample b/etc/drydock/policy.yaml.sample index 33dd92a3..65706bf5 100644 --- a/etc/drydock/policy.yaml.sample +++ b/etc/drydock/policy.yaml.sample @@ -38,6 +38,10 @@ # POST /api/v1.0/tasks #"physical_provisioner:destroy_nodes": "role:admin" +# Read build data for a node +# GET /api/v1.0/nodes/{nodename}/builddata +#"physical_provisioner:read_build_data": "role:admin" + # Read loaded design data # GET /api/v1.0/designs # GET /api/v1.0/designs/{design_id} @@ -48,11 +52,11 @@ # POST /api/v1.0/designs/{design_id}/parts #"physical_provisioner:ingest_data": "role:admin" +# et health status +# GET /api/v1.0/health/extended +#"physical_provisioner:health_data": "role:admin" + # Validate site design # POST /api/v1.0/validatedesign #"physical_provisioner:validate_site_design": "role:admin" -# Get health status -# GET /api/v1.0/health/extended -#"physical_provisioner:health_data": "role:admin" - diff --git a/requirements-host.txt b/requirements-host.txt index dde8818a..6b7b68ad 100644 --- a/requirements-host.txt +++ b/requirements-host.txt @@ -6,3 +6,4 @@ python3-dev python-tox docker.io gcc +plantuml diff --git a/tools/gate/playbooks/doc-publish.yaml b/tools/gate/playbooks/doc-publish.yaml index c174fd95..b444ac55 100644 --- a/tools/gate/playbooks/doc-publish.yaml +++ b/tools/gate/playbooks/doc-publish.yaml @@ -13,5 +13,5 @@ - hosts: primary tasks: - name: Publish current merged documents on readthedocs - shell: 'set -x && curl -X POST -d "token={{ airship_drydock_readthedocs.token }}" "{{ airship_drydock_readthedocs.url }}"' + shell: 'set -x && curl -X POST -d "token={{ airship_drydock_readthedocs.token | trim }}" "{{ airship_drydock_readthedocs.url | trim }}"' register: result diff --git a/tools/gate/playbooks/zuul-linter.yaml b/tools/gate/playbooks/zuul-linter.yaml index 7b6fb37f..3da76231 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 "*/docs/build/*" -not -path "*/docs/source/images/*" -not -name "*.tgz" -type f -exec egrep -l " +$" {} \; register: result - failed_when: result.stdout != "" \ No newline at end of file + failed_when: result.stdout != "" diff --git a/tox.ini b/tox.ini index 35f63859..bce63ab0 100644 --- a/tox.ini +++ b/tox.ini @@ -56,10 +56,14 @@ commands= {toxinidir}/tests/unit/ {toxinidir}/tests/integration/postgres [testenv:genconfig] -commands = oslo-config-generator --config-file=etc/drydock/drydock-config-generator.conf +whitelist_externals=tee + sh +commands = sh -c 'oslo-config-generator --config-file=etc/drydock/drydock-config-generator.conf | tee etc/drydock/drydock.conf.sample docs/source/_static/drydock.conf.sample' [testenv:genpolicy] -commands = oslopolicy-sample-generator --config-file etc/drydock/drydock-policy-generator.conf +whitelist_externals=tee + sh +commands = sh -c 'oslopolicy-sample-generator --config-file etc/drydock/drydock-policy-generator.conf | tee etc/drydock/policy.yaml.sample docs/source/_static/policy.yaml.sample' [testenv:pep8] commands = flake8 \ @@ -74,7 +78,10 @@ exclude= venv,.venv,.git,.idea,.tox,*.egg-info,*.eggs,bin,dist,./build/,alembic/ max-line-length=119 [testenv:docs] +deps= + -rdocs/requirements-doc.txt whitelist_externals=rm +recreate=true commands = rm -rf docs/build sphinx-build -b html docs/source docs/build