├── .coveragerc ├── .dockerignore ├── .editorconfig ├── .github └── SECURITY.md ├── .gitignore ├── .gitreview ├── .readthedocs.yaml ├── .stestr.conf ├── .zuul.yaml ├── CONTRIBUTING.rst ├── LICENSE ├── Makefile ├── README.rst ├── armada ├── .style.yapf ├── __init__.py ├── api │ ├── __init__.py │ ├── controller │ │ ├── armada.py │ │ ├── health.py │ │ ├── metrics.py │ │ ├── releases.py │ │ ├── test.py │ │ ├── tiller.py │ │ ├── validation.py │ │ └── versions.py │ ├── middleware.py │ └── server.py ├── cli │ ├── __init__.py │ ├── apply.py │ ├── test.py │ └── validate.py ├── common │ ├── __init__.py │ ├── client.py │ ├── i18n.py │ ├── policies │ │ ├── __init__.py │ │ ├── base.py │ │ ├── service.py │ │ └── tiller.py │ ├── policy.py │ └── session.py ├── conf │ ├── __init__.py │ ├── default.py │ ├── opts.py │ └── utils.py ├── const.py ├── exceptions │ ├── __init__.py │ ├── api_exceptions.py │ ├── armada_exceptions.py │ ├── base_exception.py │ ├── chartbuilder_exceptions.py │ ├── helm_exceptions.py │ ├── k8s_exceptions.py │ ├── manifest_exceptions.py │ ├── override_exceptions.py │ ├── source_exceptions.py │ └── validate_exceptions.py ├── handlers │ ├── __init__.py │ ├── armada.py │ ├── chart_delete.py │ ├── chart_deploy.py │ ├── chart_download.py │ ├── chartbuilder.py │ ├── document.py │ ├── helm.py │ ├── k8s.py │ ├── lock.py │ ├── manifest.py │ ├── metrics.py │ ├── override.py │ ├── pre_update_actions.py │ ├── release_diff.py │ ├── schema.py │ ├── test.py │ └── wait.py ├── schemas │ ├── armada-chart-schema-v1.yaml │ ├── armada-chart-schema-v2.yaml │ ├── armada-chartgroup-schema-v1.yaml │ ├── armada-chartgroup-schema-v2.yaml │ ├── armada-manifest-schema-v1.yaml │ └── armada-manifest-schema-v2.yaml ├── shell.py ├── tests │ ├── __init__.py │ ├── test_utils.py │ └── unit │ │ ├── __init__.py │ │ ├── api │ │ ├── __init__.py │ │ ├── base.py │ │ ├── test_api_initialization.py │ │ ├── test_armada_controller.py │ │ ├── test_health_controller.py │ │ ├── test_releases_controller.py │ │ ├── test_test_controller.py │ │ ├── test_tiller_controller.py │ │ ├── test_validation_controller.py │ │ └── test_versions_controller.py │ │ ├── base.py │ │ ├── common │ │ ├── __init__.py │ │ ├── test_policy.py │ │ └── test_session.py │ │ ├── fake_policy.py │ │ ├── fixtures.py │ │ ├── handlers │ │ ├── __init__.py │ │ ├── templates │ │ │ ├── base.yaml │ │ │ ├── override-01-expected.yaml │ │ │ ├── override-01.yaml │ │ │ ├── override-02-expected.yaml │ │ │ └── override-03-expected.yaml │ │ ├── test_armada.py │ │ ├── test_chartbuilder.py │ │ ├── test_lock.py │ │ ├── test_manifest.py │ │ ├── test_override.py │ │ ├── test_release_diff.py │ │ ├── test_test.py │ │ └── test_wait.py │ │ ├── resources │ │ ├── keystone-manifest.yaml │ │ └── valid_armada_document.yaml │ │ └── utils │ │ ├── __init__.py │ │ ├── schema.py │ │ ├── test_release.py │ │ ├── test_source.py │ │ └── test_validate.py ├── utils │ ├── __init__.py │ ├── helm.py │ ├── keystone.py │ ├── release.py │ ├── source.py │ ├── validate.py │ └── validation_message.py └── version.py ├── bindep.txt ├── charts ├── armada │ ├── .helmignore │ ├── Chart.yaml │ ├── crds │ │ └── armada.airshipit.org_armadacharts.yaml │ ├── requirements.yaml │ ├── templates │ │ ├── configmap-bin.yaml │ │ ├── configmap-etc.yaml │ │ ├── configmap-gnp.yaml │ │ ├── daemonset-bootstrap.yaml │ │ ├── deployment-api.yaml │ │ ├── ingress-api.yaml │ │ ├── job-image-repo-sync.yaml │ │ ├── job-ks-endpoints.yaml │ │ ├── job-ks-service.yaml │ │ ├── job-ks-user.yaml │ │ ├── network_policy.yaml │ │ ├── secret-ingress-tls.yaml │ │ ├── secret-keystone-env.yaml │ │ ├── service-ingress.yaml │ │ ├── service.yaml │ │ └── tests │ │ │ └── test-armada-api.yaml │ └── values.yaml └── deps │ └── .gitkeep ├── controller.sh ├── doc ├── requirements.txt └── source │ ├── _static │ ├── .placeholder │ ├── airship.logo.white.svg │ ├── armada.conf.sample │ └── armada.policy.yaml.sample │ ├── commands │ ├── apply.rst │ ├── index.rst │ ├── test.rst │ └── validate.rst │ ├── conf.py │ ├── development │ ├── contributing.rst │ ├── getting-started.rst │ └── index.rst │ ├── index.rst │ └── operations │ ├── documents │ ├── index.rst │ ├── migration-v1-v2.rst │ ├── v1 │ │ ├── document-authoring.rst │ │ ├── index.rst │ │ └── schemas.rst │ └── v2 │ │ ├── document-authoring.rst │ │ ├── index.rst │ │ └── schemas.rst │ ├── exceptions │ ├── api-exceptions.inc │ ├── armada-exceptions.inc │ ├── base-exceptions.inc │ ├── chartbuilder-exceptions.inc │ ├── guide-exceptions.rst │ ├── index.rst │ ├── k8s-exceptions.inc │ ├── manifest-exceptions.inc │ ├── override-exceptions.inc │ ├── source-exceptions.inc │ └── validate-exceptions.inc │ ├── guide-configure.rst │ ├── guide-helm-plugin.rst │ ├── guide-troubleshooting.rst │ ├── guide-use-armada.rst │ ├── index.rst │ ├── metrics.rst │ ├── sampleconf.rst │ └── samplepolicy.rst ├── entrypoint.sh ├── etc └── armada │ ├── api-paste.ini │ ├── armada.conf.sample │ ├── config-generator.conf │ ├── policy-generator.conf │ ├── policy.yaml │ └── policy.yaml.sample ├── examples ├── armada-keystone-manifest.yaml ├── keystone-manifest.yaml ├── podinfo.yaml ├── simple-ovr-values.yaml ├── simple.yaml └── tar_example.yaml ├── images └── armada │ ├── Dockerfile.ubuntu_bionic │ ├── Dockerfile.ubuntu_focal │ └── Dockerfile.ubuntu_jammy ├── plugin.yaml ├── releasenotes ├── notes │ └── .placeholder └── source │ ├── _static │ └── .placeholder │ ├── _templates │ └── .placeholder │ ├── conf.py │ ├── index.rst │ └── unreleased.rst ├── requirements-direct.txt ├── requirements-frozen.txt ├── requirements.txt ├── setup.cfg ├── setup.py ├── test-requirements.txt ├── tools ├── armada_image_run.sh ├── gate │ ├── playbooks │ │ ├── airship-run-scripts.yaml │ │ ├── airskiff-reduce-site.yaml │ │ ├── build-charts.yaml │ │ ├── checkout-treasuremap-ref.yaml │ │ ├── debug-report.yaml │ │ ├── deploy-env.yaml │ │ ├── docker-image-build.yaml │ │ ├── git-config.yaml │ │ ├── mount-volumes.yaml │ │ ├── osh-infra-build.yaml │ │ ├── osh-infra-collect-logs.yaml │ │ ├── prepare-hosts.yaml │ │ ├── roles │ │ └── vars.yaml │ └── roles │ │ └── disable-systemd-resolved │ │ └── tasks │ │ ├── disable-systemd-resolved.yaml │ │ └── main.yaml ├── helm_install.sh ├── helm_tk.sh ├── image_tags.py ├── keystone-account.sh └── whitespace-linter.sh └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | source = armada 4 | omit = armada/tests/* 5 | 6 | [report] 7 | ignore_errors = True 8 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | doc 2 | charts 3 | examples 4 | releasenotes 5 | tools 6 | .editorconfig 7 | .gitreview 8 | .gitignore 9 | .stestr.conf 10 | .zuul.yaml 11 | CODE_OF_CONDUCT.rst 12 | Dockerfile 13 | LICENSE 14 | Makefile 15 | test-requirements.txt 16 | tox.ini 17 | 18 | # Copy of .gitignore below 19 | # ======================== 20 | 21 | # Byte-compiled / optimized / DLL files 22 | __pycache__/ 23 | *.py[cod] 24 | *$py.class 25 | 26 | # C extensions 27 | *.so 28 | 29 | # Distribution / packaging 30 | .Python 31 | env/ 32 | build/ 33 | develop-eggs/ 34 | dist/ 35 | downloads/ 36 | eggs/ 37 | .eggs/ 38 | lib/ 39 | lib64/ 40 | parts/ 41 | sdist/ 42 | var/ 43 | *.egg-info/ 44 | .installed.cfg 45 | *.egg 46 | etc/*.sample 47 | etc/hostname 48 | etc/hosts 49 | etc/resolv.conf 50 | 51 | # PyInstaller 52 | # Usually these files are written by a python script from a template 53 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 54 | *.manifest 55 | *.spec 56 | 57 | # Installer logs 58 | pip-log.txt 59 | pip-delete-this-directory.txt 60 | 61 | # Unit test / coverage reports 62 | htmlcov/ 63 | .tox/ 64 | .stestr 65 | .coverage 66 | .coverage.* 67 | .cache 68 | nosetests.xml 69 | coverage.xml 70 | *,cover 71 | cover 72 | .hypothesis/ 73 | 74 | # Translations 75 | *.mo 76 | *.pot 77 | 78 | # Django stuff: 79 | *.log 80 | local_settings.py 81 | 82 | # Flask stuff: 83 | instance/ 84 | .webassets-cache 85 | 86 | # Scrapy stuff: 87 | .scrapy 88 | 89 | # Sphinx documentation 90 | doc/build/ 91 | doc/source/_static 92 | 93 | # PyBuilder 94 | target/ 95 | 96 | # IPython Notebook 97 | .ipynb_checkpoints 98 | 99 | # pyenv 100 | .python-version 101 | 102 | # celery beat schedule file 103 | celerybeat-schedule 104 | 105 | # dotenv 106 | .env 107 | 108 | # virtualenv 109 | venv/ 110 | ENV/ 111 | 112 | # Spyder project settings 113 | .spyderproject 114 | 115 | # Rope project settings 116 | .ropeproject 117 | 118 | # Helm internals 119 | *.lock 120 | */*.lock 121 | *.tgz 122 | **/*.tgz 123 | **/_partials.tpl 124 | **/_globals.tpl 125 | 126 | # OSX 127 | .DS_STORE 128 | 129 | AUTHORS 130 | ChangeLog 131 | etc/armada/armada.conf 132 | etc/armada/policy.yaml 133 | 134 | # IDEs 135 | .idea/ 136 | .vscode/ 137 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | indent_size = 4 9 | indent_style = space 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [*.py] 14 | # Armada uses PEP8 line length of 79 15 | # Note: for VS Code, set "editor.rulers":[79] in your workspace settings 16 | max_line_length = 79 17 | 18 | [*.{yml,yaml}] 19 | indent_size = 2 20 | 21 | [Makefile] 22 | indent_style = tab 23 | 24 | [*.md] 25 | # Note: VS Code may not honor the following setting 26 | # See: https://github.com/editorconfig/editorconfig-vscode/issues/153 27 | trim_trailing_whitespace = false 28 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | The Airship community is committed to expediently confirming, resolving, and 6 | disclosing all reported security vulnerabilities. To report a security 7 | vulnerabillity, please refer to our [vulnerability management process][1]. 8 | 9 | [1]: https://docs.airshipit.org/learn/vulnerabilities.html 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | etc/*.sample 27 | etc/hostname 28 | etc/hosts 29 | etc/resolv.conf 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .stestr 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *,cover 51 | cover 52 | .hypothesis/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | doc/build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # IPython Notebook 76 | .ipynb_checkpoints 77 | 78 | # pyenv 79 | .python-version 80 | 81 | # celery beat schedule file 82 | celerybeat-schedule 83 | 84 | # dotenv 85 | .env 86 | 87 | # virtualenv 88 | venv/ 89 | ENV/ 90 | 91 | # Spyder project settings 92 | .spyderproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # Chart artifacts 98 | /charts/*.tgz 99 | /charts/*/charts 100 | /charts/*/requirements.lock 101 | /charts/deps/*/ 102 | 103 | # OSX 104 | .DS_STORE 105 | 106 | AUTHORS 107 | ChangeLog 108 | etc/armada/armada.conf 109 | etc/armada/policy.yaml 110 | 111 | # IDEs 112 | .idea/ 113 | .vscode/ 114 | .devcontainer/ 115 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.opendev.org 3 | port=29418 4 | project=airship/armada 5 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the doc/ directory with Sphinx 9 | sphinx: 10 | configuration: doc/source/conf.py 11 | 12 | # Build documentation with MkDocs 13 | #mkdocs: 14 | # configuration: mkdocs.yml 15 | 16 | # Optionally build your docs in additional formats such as PDF and ePub 17 | formats: 18 | - pdf 19 | 20 | build: 21 | os: "ubuntu-22.04" 22 | tools: 23 | python: "3.10" 24 | 25 | # Optionally set the version of Python and requirements required to build your docs 26 | python: 27 | install: 28 | - requirements: doc/requirements.txt 29 | - requirements: requirements-frozen.txt 30 | -------------------------------------------------------------------------------- /.stestr.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | test_path=armada/tests/unit 3 | top_dir=./ 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contribution Guidelines 2 | ======================= 3 | 4 | If you would like to contribute to the development of OpenStack, you must 5 | follow the steps in this page: 6 | 7 | https://docs.openstack.org/infra/manual/developers.html 8 | 9 | If you already have a good understanding of how the system works and your 10 | OpenStack accounts are set up, you can skip to the development workflow 11 | section of this documentation to learn how changes to OpenStack should be 12 | submitted for review via the Gerrit tool: 13 | 14 | https://docs.openstack.org/infra/manual/developers.html#development-workflow 15 | 16 | Pull requests submitted through GitHub will be ignored. 17 | -------------------------------------------------------------------------------- /armada/.style.yapf: -------------------------------------------------------------------------------- 1 | [style] 2 | based_on_style = pep8 3 | spaces_before_comment = 2 4 | column_limit = 79 5 | blank_line_before_nested_class_or_def = false 6 | blank_line_before_module_docstring = true 7 | split_before_logical_operator = true 8 | split_before_first_argument = true 9 | allow_split_before_dict_value = true 10 | split_before_arithmetic_operator = true 11 | -------------------------------------------------------------------------------- /armada/__init__.py: -------------------------------------------------------------------------------- 1 | import pylibyaml # noqa: F401 # patch pyyaml to use libyaml bindings 2 | -------------------------------------------------------------------------------- /armada/api/controller/health.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import falcon 15 | 16 | from armada import api 17 | 18 | 19 | class Health(api.BaseResource): 20 | """ 21 | Return empty response/body to show that Armada is healthy. 22 | """ 23 | def on_get(self, req, resp): 24 | """ 25 | It really does nothing right now. It may do more later. 26 | """ 27 | resp.status = falcon.HTTP_204 28 | -------------------------------------------------------------------------------- /armada/api/controller/metrics.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import falcon 16 | import prometheus_client 17 | 18 | from armada import api 19 | from armada.handlers import metrics 20 | 21 | 22 | class Metrics(api.BaseResource): 23 | '''Controller for exporting prometheus metrics. 24 | ''' 25 | def on_get(self, req, resp): 26 | encoder, content_type = prometheus_client.exposition.choose_encoder( 27 | req.get_header('Accept')) 28 | try: 29 | output = encoder(metrics.REGISTRY) 30 | except Exception as ex: 31 | err_message = 'Failed to generate metric output' 32 | self.logger.error(err_message, exc_info=ex) 33 | return self.return_error( 34 | resp, falcon.HTTP_500, message=err_message) 35 | resp.content_type = content_type 36 | resp.text = output 37 | resp.status = falcon.HTTP_200 38 | -------------------------------------------------------------------------------- /armada/api/controller/releases.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | 17 | import falcon 18 | from oslo_config import cfg 19 | from oslo_log import log as logging 20 | 21 | from armada import api 22 | from armada.common import policy 23 | 24 | CONF = cfg.CONF 25 | LOG = logging.getLogger(__name__) 26 | 27 | 28 | class Releases(api.BaseResource): 29 | @policy.enforce('armada:get_release') 30 | def on_get(self, req, resp): 31 | '''Controller for listing Helm releases. 32 | ''' 33 | try: 34 | with self.get_helm(req, resp) as helm: 35 | releases = self.handle(helm) 36 | resp.text = json.dumps({ 37 | 'releases': releases, 38 | }) 39 | resp.content_type = 'application/json' 40 | resp.status = falcon.HTTP_200 41 | 42 | except Exception as e: 43 | err_message = 'Unable to find Helm Releases: {}'.format(e) 44 | self.error(req.context, err_message) 45 | self.return_error(resp, falcon.HTTP_500, message=err_message) 46 | 47 | def handle(self, helm): 48 | LOG.debug('Getting helm releases') 49 | 50 | releases = {} 51 | for release in helm.list_release_ids(): 52 | releases.setdefault(release.namespace, []) 53 | releases[release.namespace].append(release.name) 54 | return releases 55 | -------------------------------------------------------------------------------- /armada/api/controller/tiller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import json 15 | 16 | import falcon 17 | from oslo_config import cfg 18 | from oslo_log import log as logging 19 | 20 | from armada import api 21 | from armada.common import policy 22 | 23 | CONF = cfg.CONF 24 | LOG = logging.getLogger(__name__) 25 | 26 | 27 | class Status(api.BaseResource): 28 | @policy.enforce('tiller:get_status') 29 | def on_get(self, req, resp): 30 | ''' 31 | get tiller status 32 | ''' 33 | try: 34 | message = self.handle() 35 | resp.status = falcon.HTTP_200 36 | resp.text = json.dumps(message) 37 | resp.content_type = 'application/json' 38 | except Exception as e: 39 | err_message = 'Failed to get Tiller Status: {}'.format(e) 40 | self.error(req.context, err_message) 41 | self.return_error(resp, falcon.HTTP_500, message=err_message) 42 | 43 | def handle(self): 44 | message = {'tiller': {'state': True, 'version': "v1.2.3"}} 45 | return message 46 | -------------------------------------------------------------------------------- /armada/api/controller/validation.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | 17 | import falcon 18 | import yaml 19 | 20 | from armada import api 21 | from armada.common import policy 22 | from armada.utils.validate import validate_armada_documents 23 | from armada.handlers.document import ReferenceResolver 24 | 25 | 26 | class Validate(api.BaseResource): 27 | '''Controller for validating an Armada manifest. 28 | ''' 29 | @policy.enforce('armada:validate_manifest') 30 | def on_post(self, req, resp): 31 | try: 32 | if req.content_type == 'application/json': 33 | self.logger.debug("Validating manifest based on reference.") 34 | json_body = self.req_json(req) 35 | if json_body.get('href', None): 36 | self.logger.debug( 37 | "Validating manifest from reference %s." 38 | % json_body.get('href')) 39 | data = ReferenceResolver.resolve_reference( 40 | json_body.get('href')) 41 | documents = list() 42 | for d in data: 43 | documents.extend(list(yaml.safe_load_all(d.decode()))) 44 | else: 45 | resp.status = falcon.HTTP_400 46 | return 47 | else: 48 | manifest = self.req_yaml(req) 49 | documents = list(manifest) 50 | 51 | self.logger.debug( 52 | "Validating set of %d documents." % len(documents)) 53 | 54 | result, details = validate_armada_documents(documents) 55 | 56 | resp.content_type = 'application/json' 57 | resp_body = { 58 | 'kind': 'Status', 59 | 'apiVersion': 'v1.0', 60 | 'metadata': {}, 61 | 'reason': 'Validation', 62 | 'details': {}, 63 | } 64 | 65 | error_details = [m for m in details if m.get('error', False)] 66 | 67 | resp_body['details']['errorCount'] = len(error_details) 68 | resp_body['details']['messageList'] = details 69 | 70 | if result: 71 | resp.status = falcon.HTTP_200 72 | resp_body['status'] = 'Success' 73 | resp_body['message'] = 'Armada validations succeeded' 74 | resp_body['code'] = 200 75 | else: 76 | resp.status = falcon.HTTP_400 77 | resp_body['status'] = 'Failure' 78 | resp_body['message'] = 'Armada validations failed' 79 | resp_body['code'] = 400 80 | 81 | resp.text = json.dumps(resp_body) 82 | except Exception as ex: 83 | err_message = 'Failed to validate Armada Manifest' 84 | self.logger.error(err_message, exc_info=ex) 85 | self.return_error(resp, falcon.HTTP_400, message=err_message) 86 | -------------------------------------------------------------------------------- /armada/api/controller/versions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | 17 | import falcon 18 | 19 | from armada import api 20 | 21 | 22 | class Versions(api.BaseResource): 23 | """Versions resource 24 | 25 | Returns the list of supported versions of the Armada API. 26 | """ 27 | def on_get(self, req, resp): 28 | resp.status = falcon.HTTP_200 29 | resp.text = json.dumps( 30 | {'v1.0': { 31 | 'path': '/api/v1.0', 32 | 'status': 'stable' 33 | }}) 34 | resp.content_type = 'application/json' 35 | -------------------------------------------------------------------------------- /armada/cli/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import sys 16 | 17 | from oslo_config import cfg 18 | from oslo_log import log as logging 19 | 20 | from armada import conf 21 | from armada.exceptions.base_exception import ArmadaBaseException 22 | 23 | conf.set_app_default_configs() 24 | conf.set_default_for_default_log_levels() 25 | 26 | CONF = cfg.CONF 27 | LOG = logging.getLogger(__name__) 28 | 29 | 30 | class CliAction(object): 31 | def __init__(self): 32 | self.logger = LOG 33 | logging.set_defaults(default_log_levels=CONF.default_log_levels) 34 | logging.setup(CONF, 'armada') 35 | 36 | def safe_invoke(self): 37 | try: 38 | self.invoke() 39 | except ArmadaBaseException: 40 | self.logger.exception('Caught internal exception') 41 | sys.exit(1) 42 | except Exception: 43 | self.logger.exception('Caught unexpected exception') 44 | sys.exit(1) 45 | 46 | def invoke(self): 47 | raise NotImplementedError() 48 | -------------------------------------------------------------------------------- /armada/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/common/__init__.py -------------------------------------------------------------------------------- /armada/common/i18n.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import oslo_i18n 14 | 15 | _translators = oslo_i18n.TranslatorFactory(domain='armada') 16 | 17 | # The primary translation function using the well-known name "_" 18 | _ = _translators.primary 19 | -------------------------------------------------------------------------------- /armada/common/policies/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import itertools 14 | 15 | from armada.common.policies import base 16 | from armada.common.policies import service 17 | from armada.common.policies import tiller 18 | 19 | 20 | def list_rules(): 21 | return itertools.chain( 22 | base.list_rules(), service.list_rules(), tiller.list_rules()) 23 | -------------------------------------------------------------------------------- /armada/common/policies/base.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from oslo_policy import policy 14 | 15 | ARMADA = 'armada:%s' 16 | TILLER = 'tiller:%s' 17 | RULE_ADMIN_REQUIRED = 'rule:admin_required' 18 | RULE_ADMIN_OR_TARGET_PROJECT = ( 19 | 'rule:admin_required or project_id:%(target.project.id)s') 20 | RULE_SERVICE_OR_ADMIN = 'rule:service_or_admin' 21 | RULE_ADMIN_VIEWER = 'rule:admin_viewer' 22 | 23 | rules = [ 24 | policy.RuleDefault( 25 | name='admin_required', check_str='role:admin or role:admin_ucp'), 26 | policy.RuleDefault( 27 | name='service_or_admin', 28 | check_str='rule:admin_required or rule:service_role'), 29 | policy.RuleDefault(name='service_role', check_str='role:service'), 30 | policy.RuleDefault( 31 | name='admin_viewer', 32 | check_str='role:admin_ucp_viewer or {}'.format(RULE_SERVICE_OR_ADMIN)), 33 | ] 34 | 35 | 36 | def list_rules(): 37 | return rules 38 | -------------------------------------------------------------------------------- /armada/common/policies/service.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from oslo_policy import policy 14 | 15 | from armada.common.policies import base 16 | 17 | armada_policies = [ 18 | policy.DocumentedRuleDefault( 19 | name=base.ARMADA % 'create_endpoints', 20 | check_str=base.RULE_ADMIN_REQUIRED, 21 | description='Install manifest charts', 22 | operations=[{ 23 | 'path': '/api/v1.0/apply/', 24 | 'method': 'POST' 25 | }]), 26 | policy.DocumentedRuleDefault( 27 | name=base.ARMADA % 'validate_manifest', 28 | check_str=base.RULE_ADMIN_VIEWER, 29 | description='Validate manifest', 30 | operations=[{ 31 | 'path': '/api/v1.0/validatedesign/', 32 | 'method': 'POST' 33 | }]), 34 | policy.DocumentedRuleDefault( 35 | name=base.ARMADA % 'test_release', 36 | check_str=base.RULE_ADMIN_REQUIRED, 37 | description='Test release', 38 | operations=[{ 39 | 'path': '/api/v1.0/test/{release}', 40 | 'method': 'GET' 41 | }]), 42 | policy.DocumentedRuleDefault( 43 | name=base.ARMADA % 'test_manifest', 44 | check_str=base.RULE_ADMIN_REQUIRED, 45 | description='Test manifest', 46 | operations=[{ 47 | 'path': '/api/v1.0/tests/', 48 | 'method': 'POST' 49 | }]), 50 | policy.DocumentedRuleDefault( 51 | name=base.ARMADA % 'get_release', 52 | check_str=base.RULE_ADMIN_VIEWER, 53 | description='Get helm releases', 54 | operations=[{ 55 | 'path': '/api/v1.0/releases/', 56 | 'method': 'GET' 57 | }]), 58 | ] 59 | 60 | 61 | def list_rules(): 62 | return armada_policies 63 | -------------------------------------------------------------------------------- /armada/common/policies/tiller.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | from oslo_policy import policy 14 | 15 | from armada.common.policies import base 16 | 17 | tiller_policies = [ 18 | policy.DocumentedRuleDefault( 19 | name=base.TILLER % 'get_status', 20 | check_str=base.RULE_ADMIN_VIEWER, 21 | description='Get Tiller status', 22 | operations=[{ 23 | 'path': '/api/v1.0/status/', 24 | 'method': 'GET' 25 | }]), 26 | ] 27 | 28 | 29 | def list_rules(): 30 | return tiller_policies 31 | -------------------------------------------------------------------------------- /armada/common/policy.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import functools 14 | 15 | from oslo_config import cfg 16 | from oslo_log import log as logging 17 | from oslo_policy import policy 18 | from oslo_utils import excutils 19 | 20 | from armada.common import policies 21 | from armada.exceptions import base_exception as exc 22 | 23 | CONF = cfg.CONF 24 | LOG = logging.getLogger(__name__) 25 | _ENFORCER = None 26 | 27 | 28 | def reset_policy(): 29 | global _ENFORCER 30 | if _ENFORCER: 31 | _ENFORCER.clear() 32 | _ENFORCER = None 33 | 34 | 35 | def setup_policy(): 36 | global _ENFORCER 37 | if not _ENFORCER: 38 | _ENFORCER = policy.Enforcer(CONF) 39 | register_rules(_ENFORCER) 40 | 41 | 42 | def _enforce_policy(action, target, credentials, do_raise=True): 43 | extras = {} 44 | if do_raise: 45 | extras.update(exc=exc.ActionForbidden, do_raise=do_raise) 46 | 47 | # `oslo.policy` supports both enforce and authorize. authorize is 48 | # stricter because it'll raise an exception if the policy action is 49 | # not found in the list of registered rules. This means that attempting 50 | # to enforce anything not found in ``armada.common.policies`` will error 51 | # out with a 'Policy not registered' message and 403 status code. 52 | try: 53 | _ENFORCER.authorize( 54 | action, target, credentials.to_policy_view(), **extras) 55 | except policy.PolicyNotRegistered: 56 | LOG.exception( 57 | 'Policy not registered for %(action)s', {'action': action}) 58 | raise exc.ActionForbidden() 59 | except Exception: 60 | with excutils.save_and_reraise_exception(): 61 | LOG.debug( 62 | 'Policy check for %(action)s failed with credentials ' 63 | '%(credentials)s', { 64 | 'action': action, 65 | 'credentials': credentials 66 | }) 67 | 68 | 69 | # NOTE(felipemonteiro): This naming is OK. It's just kept around for legacy 70 | # reasons. What's important is that authorize is used above. 71 | def enforce(rule): 72 | def decorator(func): 73 | @functools.wraps(func) 74 | def handler(*args, **kwargs): 75 | setup_policy() 76 | context = args[1].context 77 | _enforce_policy(rule, {}, context, do_raise=True) 78 | return func(*args, **kwargs) 79 | 80 | return handler 81 | 82 | return decorator 83 | 84 | 85 | def register_rules(enforcer): 86 | enforcer.register_defaults(policies.list_rules()) 87 | -------------------------------------------------------------------------------- /armada/conf/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | import os 17 | import threading 18 | 19 | from oslo_config import cfg 20 | from oslo_log import log 21 | 22 | from armada.conf import default 23 | from armada import const 24 | 25 | CONF = cfg.CONF 26 | 27 | CONFIG_FILES = ['api-paste.ini', 'armada.conf'] 28 | 29 | # Load oslo_log options prior to file/CLI parsing 30 | log.register_options(CONF) 31 | 32 | 33 | def _get_config_files(env=None): 34 | if env is None: 35 | env = os.environ 36 | dirname = env.get('OS_ARMADA_CONFIG_DIR', const.CONFIG_PATH).strip() 37 | config_files = [ 38 | os.path.join(dirname, config_file) for config_file in CONFIG_FILES 39 | ] 40 | return config_files 41 | 42 | 43 | def set_app_default_configs(): 44 | config_files = _get_config_files() 45 | if all([os.path.exists(x) for x in config_files]): 46 | CONF([], project='armada', default_config_files=config_files) 47 | setup_chart_deploy_aware_logging() 48 | set_default_for_default_log_levels() 49 | default.register_opts(CONF) 50 | 51 | 52 | # Stores chart being deployed (if any) in current thread. 53 | current_chart_thread_local = threading.local() 54 | 55 | 56 | def get_current_chart(): 57 | return getattr(current_chart_thread_local, 'chart', None) 58 | 59 | 60 | def set_current_chart(chart): 61 | current_chart_thread_local.chart = chart 62 | 63 | 64 | def setup_chart_deploy_aware_logging(): 65 | logging.setLoggerClass(ChartDeployAwareLogger) 66 | 67 | 68 | def set_default_for_default_log_levels(): 69 | """Set the default for the default_log_levels option for Armada. 70 | Armada uses some packages that other OpenStack services don't use that do 71 | logging. This will set the default_log_levels default level for those 72 | packages. 73 | This function needs to be called before CONF(). 74 | """ 75 | 76 | extra_log_level_defaults = ['kubernetes.client.rest=INFO'] 77 | 78 | log.set_defaults( 79 | default_log_levels=log.get_default_log_levels() 80 | + extra_log_level_defaults, ) 81 | 82 | 83 | class ChartDeployAwareLogger(logging.Logger): 84 | """Includes name of chart currently being deployed (if any) in log 85 | messages. 86 | """ 87 | def _log(self, level, msg, *args, **kwargs): 88 | chart = get_current_chart() 89 | if chart: 90 | name = chart['metadata']['name'] 91 | prefix = '[chart={}]: '.format(name) 92 | else: 93 | prefix = '' 94 | prefixed = '{}{}'.format(prefix, msg) 95 | return super(ChartDeployAwareLogger, 96 | self)._log(level, prefixed, *args, **kwargs) 97 | -------------------------------------------------------------------------------- /armada/conf/opts.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | """Single point of entry to generate the sample configuration file. 14 | 15 | This module collects all the necessary info from the other modules in this 16 | package. It is assumed that: 17 | 18 | * Every other module in this package has a 'list_opts' function which 19 | returns a dict where: 20 | 21 | * The keys are strings which are the group names. 22 | 23 | * The value of each key is a list of config options for that group. 24 | 25 | * The conf package doesn't have further packages with config options. 26 | 27 | * This module is only used in the context of sample file generation. 28 | 29 | """ 30 | 31 | import collections 32 | import importlib 33 | import os 34 | import pkgutil 35 | 36 | LIST_OPTS_FUNC_NAME = 'list_opts' 37 | IGNORED_MODULES = ('opts', 'constants', 'utils') 38 | 39 | 40 | def list_opts(): 41 | opts = collections.defaultdict(list) 42 | module_names = _list_module_names() 43 | imported_modules = _import_modules(module_names) 44 | _append_config_options(imported_modules, opts) 45 | return _tupleize(opts) 46 | 47 | 48 | def _tupleize(d): 49 | """Convert a dict of options to the 2-tuple format.""" 50 | return [(key, value) for key, value in d.items()] 51 | 52 | 53 | def _list_module_names(): 54 | module_names = [] 55 | package_path = os.path.dirname(os.path.abspath(__file__)) 56 | for _, module_name, ispkg in pkgutil.iter_modules(path=[package_path]): 57 | if module_name in IGNORED_MODULES or ispkg: 58 | # Skip this module. 59 | continue 60 | else: 61 | module_names.append(module_name) 62 | return module_names 63 | 64 | 65 | def _import_modules(module_names): 66 | imported_modules = [] 67 | for module_name in module_names: 68 | full_module_path = '.'.join(__name__.split('.')[:-1] + [module_name]) 69 | module = importlib.import_module(full_module_path) 70 | if not hasattr(module, LIST_OPTS_FUNC_NAME): 71 | raise Exception( 72 | "The module '%s' should have a '%s' function which " 73 | "returns the config options." % 74 | (full_module_path, LIST_OPTS_FUNC_NAME)) 75 | else: 76 | imported_modules.append(module) 77 | return imported_modules 78 | 79 | 80 | def _process_old_opts(configs): 81 | """Convert old-style 2-tuple configs to dicts.""" 82 | if isinstance(configs, tuple): 83 | configs = [configs] 84 | return {label: options for label, options in configs} 85 | 86 | 87 | def _append_config_options(imported_modules, config_options): 88 | for module in imported_modules: 89 | configs = module.list_opts() 90 | # TODO(markus_z): Remove this compatibility shim once all list_opts() 91 | # functions have been updated to return dicts. 92 | if not isinstance(configs, dict): 93 | configs = _process_old_opts(configs) 94 | for key, val in configs.items(): 95 | config_options[key].extend(val) 96 | -------------------------------------------------------------------------------- /armada/conf/utils.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | 14 | def fmt(docstr): 15 | """Format a docstring for use as documentation in sample config.""" 16 | # Replace newlines with spaces, as docstrings contain literal newlines that 17 | # should not be rendered into the sample configuration file (instead, line 18 | # wrappings should be applied automatically). 19 | docstr = docstr.replace('\n', ' ') 20 | 21 | # Because it's common for docstrings to begin and end with a newline, there 22 | # is now whitespace at the beginning and end of the documentation as a side 23 | # effect of replacing newlines with spaces. 24 | docstr = docstr.strip() 25 | 26 | return docstr 27 | -------------------------------------------------------------------------------- /armada/const.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Keywords 16 | KEYWORD_DATA = 'data' 17 | KEYWORD_PREFIX = 'release_prefix' 18 | KEYWORD_GROUPS = 'chart_groups' 19 | KEYWORD_CHARTS = 'chart_group' 20 | KEYWORD_RELEASE = 'release' 21 | 22 | # Armada 23 | DEFAULT_CHART_TIMEOUT = 900 24 | DEFAULT_TEST_TIMEOUT = 300 25 | 26 | # Helm 27 | DEFAULT_DELETE_TIMEOUT = 300 28 | 29 | # Kubernetes 30 | DEFAULT_K8S_TIMEOUT = 300 31 | 32 | # Configuration File 33 | CONFIG_PATH = '/etc/armada' 34 | -------------------------------------------------------------------------------- /armada/exceptions/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions.manifest_exceptions import BuildChartException 16 | from armada.exceptions.manifest_exceptions import BuildChartGroupException 17 | from armada.exceptions.manifest_exceptions import ChartDependencyException 18 | from armada.exceptions.manifest_exceptions import ManifestException 19 | 20 | __all__ = [ 21 | 'BuildChartException', 'BuildChartGroupException', 22 | 'ChartDependencyException', 'ManifestException' 23 | ] 24 | -------------------------------------------------------------------------------- /armada/exceptions/api_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions import base_exception as base 16 | 17 | 18 | class ApiException(base.ArmadaBaseException): 19 | ''' 20 | Base class for API exceptions and error handling. 21 | 22 | **Troubleshoot:** 23 | *Coming Soon* 24 | ''' 25 | 26 | message = 'An unknown API error occurred.' 27 | 28 | 29 | class ApiBaseException(ApiException): 30 | '''Exception that occurs during chart cleanup.''' 31 | 32 | message = 'There was an error listing the Helm chart releases.' 33 | 34 | 35 | class ApiJsonException(ApiException): 36 | '''Exception that occurs during chart cleanup.''' 37 | 38 | message = 'There was an error listing the Helm chart releases.' 39 | 40 | 41 | class ClientUnauthorizedError(ApiException): 42 | ''' 43 | Exception that occurs when the server returns a 401 Unauthorized error. 44 | 45 | **Troubleshoot:** 46 | *Coming Soon* 47 | ''' 48 | 49 | message = 'There was an error listing the Helm chart releases.' 50 | 51 | 52 | class ClientForbiddenError(ApiException): 53 | ''' 54 | Exception that occurs when the server returns a 403 Forbidden error. 55 | 56 | **Troubleshoot:** 57 | *Coming Soon* 58 | ''' 59 | 60 | message = 'There was an error listing the Helm chart releases.' 61 | 62 | 63 | class ClientError(ApiException): 64 | ''' 65 | Exception that occurs when the server returns a 500 Internal Server error. 66 | 67 | **Troubleshoot:** 68 | *Coming Soon* 69 | ''' 70 | 71 | message = 'There was an error listing the Helm chart releases.' 72 | -------------------------------------------------------------------------------- /armada/exceptions/chartbuilder_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions import base_exception 16 | 17 | 18 | class ChartBuilderException(base_exception.ArmadaBaseException): 19 | '''Base class for the Chartbuilder handler exception and error handling.''' 20 | 21 | message = 'An unknown Armada handler error occurred.' 22 | 23 | 24 | class HelmChartBuildException(ChartBuilderException): 25 | ''' 26 | Exception that occurs when Helm Chart fails to build. 27 | ''' 28 | def __init__(self, chart_name, details): 29 | self._chart_name = chart_name 30 | self._message = ( 31 | 'Failed to build Helm chart for {chart_name}. ' 32 | 'Details: {details}'.format( 33 | **{ 34 | 'chart_name': chart_name, 35 | 'details': details 36 | })) 37 | 38 | super(HelmChartBuildException, self).__init__(self._message) 39 | -------------------------------------------------------------------------------- /armada/exceptions/helm_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions.base_exception import ArmadaBaseException as ex 16 | 17 | 18 | class HelmCommandException(ex): 19 | ''' 20 | Exception that occurs when a helm command fails. 21 | ''' 22 | def __init__(self, called_process_error): 23 | self.called_process_error = called_process_error 24 | message = 'helm command failed: {}'.format( 25 | self.called_process_error.stderr) 26 | super(HelmCommandException, self).__init__(message) 27 | -------------------------------------------------------------------------------- /armada/exceptions/k8s_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions.base_exception import ArmadaBaseException as ex 16 | 17 | 18 | class KubernetesException(ex): 19 | '''Base class for Kubernetes exceptions and error handling.''' 20 | 21 | message = 'An unknown Kubernetes error occurred.' 22 | 23 | 24 | class KubernetesWatchTimeoutException(KubernetesException): 25 | '''Exception for timing out during a watch on a Kubernetes object''' 26 | 27 | message = 'Kubernetes Watch has timed out.' 28 | 29 | 30 | class KubernetesUnknownStreamingEventTypeException(KubernetesException): 31 | '''Exception for getting an unknown event type from the Kubernetes API''' 32 | 33 | message = 'An unknown event type was returned from the streaming API.' 34 | 35 | 36 | class KubernetesErrorEventException(KubernetesException): 37 | '''Exception for getting an error from the Kubernetes API''' 38 | 39 | message = 'An error event was returned from the streaming API.' 40 | -------------------------------------------------------------------------------- /armada/exceptions/manifest_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions import base_exception as base 16 | 17 | 18 | class ManifestException(base.ArmadaBaseException): 19 | """ 20 | An exception occurred while attempting to build an Armada manifest. The 21 | exception will return with details as to why. 22 | 23 | **Troubleshoot:** 24 | *Coming Soon* 25 | """ 26 | 27 | message = 'An error occurred while generating the manifest: %(details)s.' 28 | 29 | 30 | class BuildChartException(ManifestException): 31 | """ 32 | An exception occurred while attempting to build the chart for an 33 | Armada manifest. The exception will return with details as to why. 34 | 35 | **Troubleshoot:** 36 | *Coming Soon* 37 | """ 38 | 39 | message = 'An error occurred while trying to build chart: %(details)s.' 40 | 41 | 42 | class BuildChartGroupException(ManifestException): 43 | """ 44 | An exception occurred while attempting to build the chart group for an 45 | Armada manifest. The exception will return with details as to why. 46 | 47 | **Troubleshoot:** 48 | *Coming Soon* 49 | """ 50 | 51 | message = 'An error occurred while building chart group: %(details)s.' 52 | 53 | 54 | class ChartDependencyException(ManifestException): 55 | """ 56 | An exception occurred while attempting to build a chart dependency for an 57 | Armada manifest. The exception will return with details as to why. 58 | 59 | **Troubleshoot:** 60 | *Coming Soon* 61 | """ 62 | 63 | message = 'An error occurred while building a dependency chart: ' \ 64 | '%(details)s.' 65 | -------------------------------------------------------------------------------- /armada/exceptions/override_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions import base_exception 16 | 17 | 18 | class OverrideException(base_exception.ArmadaBaseException): 19 | ''' 20 | Base class for Override handler exception and error handling. 21 | ''' 22 | 23 | message = 'An unknown Override handler error occurred.' 24 | 25 | 26 | class InvalidOverrideTypeException(OverrideException): 27 | ''' 28 | Exception that occurs when an invalid override type is used with the 29 | set flag. 30 | ''' 31 | def __init__(self, override_type): 32 | self._message = 'Override type "{}" is invalid'.format(override_type) 33 | 34 | super(InvalidOverrideTypeException, self).__init__(self._message) 35 | 36 | 37 | class InvalidOverrideFileException(OverrideException): 38 | ''' 39 | Exception that occurs when an invalid override file is provided. 40 | 41 | **Troubleshoot:** 42 | *Coming Soon* 43 | ''' 44 | def __init__(self, filename): 45 | self._message = '{} is not a valid override file.'.format(filename) 46 | 47 | super(InvalidOverrideFileException, self).__init__(self._message) 48 | 49 | 50 | class InvalidOverrideValueException(OverrideException): 51 | ''' 52 | Exception that occurs when an invalid value is used with the set flag. 53 | 54 | **Troubleshoot:** 55 | *Coming Soon* 56 | ''' 57 | def __init__(self, override_command): 58 | self._message = '{} is not a valid override statement.'.format( 59 | override_command) 60 | 61 | super(InvalidOverrideValueException, self).__init__(self._message) 62 | 63 | 64 | class UnknownDocumentOverrideException(OverrideException): 65 | ''' 66 | Exception that occurs when an invalid value is used with the set flag. 67 | 68 | **Troubleshoot:** 69 | *Coming Soon* 70 | ''' 71 | def __init__(self, doc_type, doc_name): 72 | self._message = 'Unable to find {1} document schema: {0} '.format( 73 | doc_type, doc_name) 74 | 75 | super(UnknownDocumentOverrideException, self).__init__(self._message) 76 | -------------------------------------------------------------------------------- /armada/exceptions/validate_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.exceptions import base_exception 16 | 17 | 18 | class ValidateException(base_exception.ArmadaBaseException): 19 | '''Base class for linting exceptions and errors.''' 20 | 21 | message = 'An unknown linting error occurred.' 22 | 23 | 24 | class InvalidManifestException(ValidateException): 25 | ''' 26 | Exception for invalid manifests. 27 | 28 | **Troubleshoot:** 29 | *Coming Soon* 30 | ''' 31 | 32 | message = ( 33 | 'Armada manifest(s) failed validation. Details: ' 34 | '%(error_messages)s.') 35 | 36 | 37 | class InvalidChartNameException(ValidateException): 38 | '''Exception that occurs when an invalid filename is encountered.''' 39 | 40 | message = 'Chart name must be a string.' 41 | 42 | 43 | class InvalidChartDefinitionException(ValidateException): 44 | '''Exception when invalid chart definition is encountered.''' 45 | 46 | message = 'Invalid chart definition. Chart definition must be array.' 47 | 48 | 49 | class InvalidReleaseException(ValidateException): 50 | '''Exception that occurs when a release is invalid.''' 51 | 52 | message = 'Release needs to be a string.' 53 | 54 | 55 | class InvalidArmadaObjectException(ValidateException): 56 | ''' 57 | Exception that occurs when an Armada object is not declared. 58 | 59 | **Troubleshoot:** 60 | *Coming Soon* 61 | ''' 62 | 63 | message = ( 64 | 'An Armada object failed internal validation. Details: ' 65 | '%(details)s.') 66 | -------------------------------------------------------------------------------- /armada/handlers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/handlers/__init__.py -------------------------------------------------------------------------------- /armada/handlers/chart_delete.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada import const 16 | 17 | 18 | class ChartDelete(object): 19 | def __init__(self, chart, release_id, helm, purge=True): 20 | """Initialize a chart delete handler. 21 | 22 | :param chart: The armada chart document 23 | :param release_id: HelmReleaseId 24 | :param helm: Helm object 25 | :param purge: Whether to purge the release 26 | 27 | :type chart: object 28 | :type release_name: str 29 | :type helm: Helm object 30 | :type purge: bool 31 | """ 32 | 33 | self.chart = chart 34 | self.release_id = release_id 35 | self.helm = helm 36 | self.purge = purge 37 | self.delete_config = self.chart.get('delete', {}) 38 | # TODO(seaneagan): Consider allowing this to be a percentage of the 39 | # chart's `wait.timeout` so that the timeouts can scale together, and 40 | # likely default to some reasonable value, e.g. "50%". 41 | self.timeout = self.delete_config.get( 42 | 'timeout', const.DEFAULT_DELETE_TIMEOUT) 43 | 44 | def get_timeout(self): 45 | return self.timeout 46 | 47 | def delete(self): 48 | """Delete the release associated with the chart" 49 | """ 50 | self.helm.uninstall_release( 51 | self.release_id, timeout=self.get_timeout(), purge=self.purge) 52 | -------------------------------------------------------------------------------- /armada/handlers/release_diff.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from deepdiff import DeepDiff 16 | 17 | 18 | class ReleaseDiff(object): 19 | ''' 20 | A utility for discovering diffs in helm release inputs, for example to 21 | determine whether an upgrade is needed and what specific changes will be 22 | applied. 23 | 24 | Release inputs which are relevant are the override values given, and 25 | the chart content including: 26 | 27 | * default values (values.yaml), 28 | * templates and their content 29 | * files and their content 30 | * the above for each chart on which the chart depends transitively. 31 | 32 | This excludes Chart.yaml content as that is rarely used by the chart 33 | via ``{{ .Chart }}``, and even when it is does not usually necessitate 34 | an upgrade. 35 | 36 | :param old_chart: The deployed chart. 37 | :type old_chart: Chart 38 | :param old_values: The deployed chart override values. 39 | :type old_values: dict 40 | :param new_chart: The chart to deploy. 41 | :type new_chart: Chart 42 | :param new_values: The chart override values to deploy. 43 | :type new_values: dict 44 | ''' 45 | def __init__(self, old_chart, old_values, new_chart, new_values): 46 | self.old_chart = old_chart 47 | self.old_values = old_values 48 | self.new_chart = new_chart 49 | self.new_values = new_values 50 | 51 | def get_diff(self): 52 | ''' 53 | Get the diff. 54 | 55 | :return: Mapping of difference types to sets of those differences. 56 | :rtype: dict 57 | ''' 58 | 59 | old_input = self.make_release_input(self.old_chart, self.old_values) 60 | new_input = self.make_release_input(self.new_chart, self.new_values) 61 | 62 | return DeepDiff(old_input, new_input, view='tree') 63 | 64 | def make_release_input(self, chart, values): 65 | return {'chart': chart, 'values': values} 66 | -------------------------------------------------------------------------------- /armada/handlers/schema.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import re 17 | from importlib.resources import files 18 | 19 | import yaml 20 | 21 | # Types 22 | TYPE_CHART = 'Chart' 23 | TYPE_CHARTGROUP = 'ChartGroup' 24 | TYPE_MANIFEST = 'Manifest' 25 | 26 | # Versions 27 | VERSION_FORMAT = r'^v(\d+)$' 28 | VERSION_MIN = 1 29 | VERSION_MAX = 2 30 | 31 | # Creates a mapping between ``metadata.name``: ``data`` where the 32 | # ``metadata.name`` is the ``schema`` of a manifest and the ``data`` is the 33 | # JSON schema to be used to validate the manifest in question. 34 | _SCHEMAS = {} 35 | 36 | 37 | class SchemaInfo(object): 38 | def __init__(self, type, version, data): 39 | self.type = type 40 | self.version = version 41 | self.data = data 42 | 43 | def __eq__(self, other): 44 | return self.type == other.type and self.version == other.version 45 | 46 | 47 | def get_schema_info(name): 48 | return _SCHEMAS.get(name) 49 | 50 | 51 | def _get_schema_info(name, data): 52 | parts = name.split('/') 53 | prefix, type, version_string = parts 54 | version_match = re.search(VERSION_FORMAT, version_string) 55 | version = int(version_match.group(1)) 56 | return SchemaInfo(type, version, data) 57 | 58 | 59 | def _get_schema_dir(): 60 | return str(files('armada') / 'schemas') 61 | 62 | 63 | def _load_schemas(): 64 | """Populates ``_SCHEMAS`` with the schemas defined in package 65 | ``armada.schemas``. 66 | 67 | """ 68 | schema_dir = _get_schema_dir() 69 | for schema_file in os.listdir(schema_dir): 70 | with open(os.path.join(schema_dir, schema_file)) as f: 71 | for schema in yaml.safe_load_all(f): 72 | name = schema['metadata']['name'] 73 | if name in _SCHEMAS: 74 | raise RuntimeError( 75 | 'Duplicate schema specified for: %s.' % name) 76 | _SCHEMAS[name] = _get_schema_info(name, schema['data']) 77 | 78 | 79 | # Fill the cache. 80 | _load_schemas() 81 | -------------------------------------------------------------------------------- /armada/schemas/armada-chartgroup-schema-v1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: Do not modify this schema, it is deprecated. 16 | --- 17 | schema: deckhand/DataSchema/v1 18 | metadata: 19 | name: armada/ChartGroup/v1 20 | schema: metadata/Control/v1 21 | data: 22 | $schema: http://json-schema.org/schema# 23 | properties: 24 | name: 25 | type: string 26 | description: 27 | type: string 28 | sequenced: 29 | type: boolean 30 | # TODO(MarshM): Deprecate `test_charts`, it is no longer useful 31 | test_charts: 32 | type: boolean 33 | chart_group: 34 | type: array 35 | items: 36 | type: string 37 | required: 38 | - chart_group 39 | additionalProperties: false 40 | ... 41 | -------------------------------------------------------------------------------- /armada/schemas/armada-chartgroup-schema-v2.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # JSON schema for validating Armada chart groups. 16 | --- 17 | schema: deckhand/DataSchema/v1 18 | metadata: 19 | name: armada/ChartGroup/v2 20 | schema: metadata/Control/v1 21 | data: 22 | $schema: http://json-schema.org/schema# 23 | properties: 24 | name: 25 | type: string 26 | description: 27 | type: string 28 | sequenced: 29 | type: boolean 30 | chart_group: 31 | type: array 32 | items: 33 | type: string 34 | required: 35 | # TODO: Rename to `charts`? 36 | - chart_group 37 | additionalProperties: false 38 | ... 39 | -------------------------------------------------------------------------------- /armada/schemas/armada-manifest-schema-v1.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # NOTE: Do not modify this schema, it is deprecated. 16 | --- 17 | schema: deckhand/DataSchema/v1 18 | metadata: 19 | name: armada/Manifest/v1 20 | schema: metadata/Control/v1 21 | data: 22 | $schema: http://json-schema.org/schema# 23 | properties: 24 | release_prefix: 25 | type: string 26 | chart_groups: 27 | type: array 28 | items: 29 | type: string 30 | required: 31 | - chart_groups 32 | - release_prefix 33 | additionalProperties: false 34 | ... 35 | -------------------------------------------------------------------------------- /armada/schemas/armada-manifest-schema-v2.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # JSON schema for validating Armada manifests. 16 | --- 17 | schema: deckhand/DataSchema/v1 18 | metadata: 19 | name: armada/Manifest/v2 20 | schema: metadata/Control/v1 21 | data: 22 | $schema: http://json-schema.org/schema# 23 | properties: 24 | release_prefix: 25 | type: string 26 | chart_groups: 27 | type: array 28 | items: 29 | type: string 30 | required: 31 | - chart_groups 32 | - release_prefix 33 | additionalProperties: false 34 | ... 35 | -------------------------------------------------------------------------------- /armada/shell.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from urllib.parse import urlparse 16 | 17 | import click 18 | from oslo_config import cfg 19 | from oslo_log import log 20 | 21 | from armada.cli.apply import apply_create 22 | from armada.cli.test import test_charts 23 | from armada.cli.validate import validate_manifest 24 | from armada.common.client import ArmadaClient 25 | from armada.common.session import ArmadaSession 26 | 27 | CONF = cfg.CONF 28 | 29 | 30 | @click.group() 31 | @click.option('--debug', help="Enable debug logging", is_flag=True) 32 | @click.option( 33 | '--api/--no-api', 34 | help="Execute service endpoints. (requires url option)", 35 | default=False) 36 | @click.option( 37 | '--url', help="Armada Service Endpoint", envvar='HOST', default=None) 38 | @click.option( 39 | '--token', help="Keystone Service Token", envvar='TOKEN', default=None) 40 | @click.pass_context 41 | def main(ctx, debug, api, url, token): 42 | """ 43 | Multi Helm Chart Deployment Manager 44 | 45 | Common actions from this point include: 46 | 47 | \b 48 | $ armada apply 49 | $ armada test 50 | $ armada validate 51 | 52 | Environment: 53 | 54 | \b 55 | $TOKEN set auth token 56 | $HOST set armada service host endpoint 57 | """ 58 | 59 | if not ctx.obj: 60 | ctx.obj = {} 61 | 62 | if api: 63 | if not url or not token: 64 | raise click.ClickException( 65 | 'When api option is enabled user needs to pass url and token') 66 | else: 67 | ctx.obj['api'] = api 68 | parsed_url = urlparse(url) 69 | ctx.obj['CLIENT'] = ArmadaClient( 70 | ArmadaSession( 71 | host=parsed_url.netloc, 72 | scheme=parsed_url.scheme, 73 | token=token)) 74 | 75 | if debug: 76 | CONF.debug = debug 77 | 78 | log.set_defaults(default_log_levels=CONF.default_log_levels) 79 | log.setup(CONF, 'armada') 80 | 81 | 82 | main.add_command(apply_create) 83 | main.add_command(test_charts) 84 | main.add_command(validate_manifest) 85 | -------------------------------------------------------------------------------- /armada/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/unit/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/unit/api/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/api/base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | 17 | from falcon import testing as falcon_testing 18 | import mock 19 | 20 | from armada.api import server 21 | import armada.conf 22 | from armada.tests.unit import base as test_base 23 | from armada.tests.unit import fixtures 24 | 25 | 26 | class BaseControllerTest(test_base.ArmadaTestCase): 27 | """Base class for unit testing falcon controllers.""" 28 | def setUp(self): 29 | super(BaseControllerTest, self).setUp() 30 | # Override the default configuration file lookup with references to 31 | # the sample configuration files to avoid oslo.conf errors when 32 | # creating the server below. 33 | current_dir = os.path.dirname(os.path.realpath(__file__)) 34 | sample_conf_dir = os.path.join( 35 | current_dir, os.pardir, os.pardir, os.pardir, os.pardir, 'etc', 36 | 'armada') 37 | sample_conf_files = ['api-paste.ini', 'armada.conf.sample'] 38 | with mock.patch.object(armada.conf, 39 | '_get_config_files') as mock_get_config_files: 40 | mock_get_config_files.return_value = [ 41 | os.path.join(sample_conf_dir, x) for x in sample_conf_files 42 | ] 43 | self.app = falcon_testing.TestClient( 44 | server.create(enable_middleware=False)) 45 | self.policy = self.useFixture(fixtures.RealPolicyFixture()) 46 | -------------------------------------------------------------------------------- /armada/tests/unit/api/test_api_initialization.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import importlib 16 | 17 | import falcon 18 | 19 | from armada.tests.unit.api import base as test_base 20 | 21 | 22 | class TestApi(test_base.BaseControllerTest): 23 | def test_init_application(self): 24 | server = importlib.import_module('armada.api.server') 25 | api = server.create() 26 | self.assertIsInstance(api, falcon.App) 27 | -------------------------------------------------------------------------------- /armada/tests/unit/api/test_health_controller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import falcon 16 | 17 | from armada.tests.unit.api import base 18 | 19 | 20 | class HealthControllerTest(base.BaseControllerTest): 21 | def test_get_health_status(self): 22 | """ 23 | Validate that /api/v1.0/health returns 204. 24 | """ 25 | result = self.app.simulate_get('/api/v1.0/health') 26 | self.assertEqual(result.status, falcon.HTTP_204) 27 | -------------------------------------------------------------------------------- /armada/tests/unit/api/test_tiller_controller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from oslo_config import cfg 16 | 17 | from armada.common.policies import base as policy_base 18 | from armada.tests import test_utils 19 | from armada.tests.unit.api import base 20 | 21 | CONF = cfg.CONF 22 | 23 | 24 | class TillerControllerTest(base.BaseControllerTest): 25 | def test_get_tiller_status(self): 26 | """Tests GET /api/v1.0/status endpoint.""" 27 | rules = {'tiller:get_status': '@'} 28 | self.policy.set_rules(rules) 29 | 30 | result = self.app.simulate_get('/api/v1.0/status') 31 | expected = {'tiller': {'state': True, 'version': "v1.2.3"}} 32 | 33 | self.assertEqual(expected, result.json) 34 | self.assertEqual('application/json', result.headers['content-type']) 35 | 36 | def test_get_tiller_status_with_params(self): 37 | """Tests GET /api/v1.0/status endpoint with query parameters.""" 38 | rules = {'tiller:get_status': '@'} 39 | self.policy.set_rules(rules) 40 | 41 | result = self.app.simulate_get( 42 | '/api/v1.0/status', params_csv=False, params={}) 43 | expected = {'tiller': {'state': True, 'version': "v1.2.3"}} 44 | 45 | self.assertEqual(expected, result.json) 46 | self.assertEqual('application/json', result.headers['content-type']) 47 | 48 | 49 | class TillerControllerNegativeRbacTest(base.BaseControllerTest): 50 | @test_utils.attr(type=['negative']) 51 | def test_get_tiller_status_insufficient_permissions(self): 52 | """Tests the GET /api/v1.0/status endpoint returns 403 following 53 | failed authorization. 54 | """ 55 | rules = {'tiller:get_status': policy_base.RULE_ADMIN_REQUIRED} 56 | self.policy.set_rules(rules) 57 | resp = self.app.simulate_get('/api/v1.0/status') 58 | self.assertEqual(403, resp.status_code) 59 | -------------------------------------------------------------------------------- /armada/tests/unit/api/test_validation_controller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.common.policies import base as policy_base 16 | from armada.tests import test_utils 17 | from armada.tests.unit.api import base 18 | 19 | 20 | class ValidationControllerNegativeRbacTest(base.BaseControllerTest): 21 | @test_utils.attr(type=['negative']) 22 | def test_validate_manifest_insufficient_permissions(self): 23 | """Tests the POST /api/v1.0/validate endpoint returns 403 following 24 | failed authorization. 25 | """ 26 | rules = {'armada:validate_manifest': policy_base.RULE_ADMIN_REQUIRED} 27 | self.policy.set_rules(rules) 28 | resp = self.app.simulate_post('/api/v1.0/validatedesign') 29 | self.assertEqual(403, resp.status_code) 30 | -------------------------------------------------------------------------------- /armada/tests/unit/api/test_versions_controller.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the 'License'); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an 'AS IS' BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from armada.tests.unit.api import base 16 | 17 | 18 | class VersionsControllerTest(base.BaseControllerTest): 19 | def test_list_versions(self): 20 | """ 21 | Validate that /api/v1.0/health returns 204. 22 | """ 23 | result = self.app.simulate_get('/versions') 24 | expected = {'v1.0': {'path': '/api/v1.0', 'status': 'stable'}} 25 | self.assertDictEqual(expected, result.json) 26 | -------------------------------------------------------------------------------- /armada/tests/unit/base.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013 IBM Corp. 2 | # Copyright 2017 AT&T Intellectual Property. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | from __future__ import absolute_import 17 | 18 | import socket 19 | 20 | import fixtures 21 | import mock 22 | from oslo_config import cfg 23 | import testtools 24 | 25 | from armada.conf import default 26 | 27 | CONF = cfg.CONF 28 | 29 | 30 | def is_connected(): 31 | """Verifies whether network connectivity is up. 32 | 33 | :returns: True if connected else False. 34 | """ 35 | try: 36 | host = socket.gethostbyname("opendev.org") 37 | socket.create_connection((host, 80), 2) 38 | return True 39 | except (socket.error, socket.herror, socket.timeout): 40 | pass 41 | return False 42 | 43 | 44 | class ArmadaTestCase(testtools.TestCase): 45 | def setUp(self): 46 | super(ArmadaTestCase, self).setUp() 47 | self.useFixture(fixtures.FakeLogger('armada')) 48 | default.register_opts(CONF) 49 | 50 | def override_config(self, name, override, group=None): 51 | CONF.set_override(name, override, group) 52 | self.addCleanup(CONF.clear_override, name, group) 53 | 54 | def assertEmpty(self, collection): 55 | if isinstance(collection, list): 56 | self.assertEqual(0, len(collection)) 57 | elif isinstance(collection, dict): 58 | self.assertEqual(0, len(collection.keys())) 59 | 60 | def patch(self, target, autospec=True, **kwargs): 61 | """Returns a started `mock.patch` object for the supplied target. 62 | 63 | The caller may then call the returned patcher to create a mock object. 64 | 65 | The caller does not need to call stop() on the returned 66 | patcher object, as this method automatically adds a cleanup 67 | to the test class to stop the patcher. 68 | 69 | :param target: String module.class or module.object expression to patch 70 | :param **kwargs: Passed as-is to `mock.patch`. See mock documentation 71 | for details. 72 | """ 73 | p = mock.patch(target, autospec=autospec, **kwargs) 74 | m = p.start() 75 | self.addCleanup(p.stop) 76 | return m 77 | 78 | def patchobject(self, target, attribute, new=mock.DEFAULT, autospec=True): 79 | """Convenient wrapper around `mock.patch.object` 80 | 81 | Returns a started mock that will be automatically stopped after the 82 | test ran. 83 | """ 84 | 85 | p = mock.patch.object(target, attribute, new, autospec=autospec) 86 | m = p.start() 87 | self.addCleanup(p.stop) 88 | return m 89 | -------------------------------------------------------------------------------- /armada/tests/unit/common/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/unit/common/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/common/test_policy.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 2 | # not use this file except in compliance with the License. You may obtain 3 | # a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 | # License for the specific language governing permissions and limitations 11 | # under the License. 12 | 13 | import mock 14 | from oslo_policy import policy as common_policy 15 | import testtools 16 | 17 | from armada.common import policy 18 | from armada import conf as cfg 19 | from armada.exceptions import base_exception as exc 20 | from armada.tests.unit import fixtures 21 | 22 | CONF = cfg.CONF 23 | 24 | 25 | class PolicyTestCase(testtools.TestCase): 26 | def setUp(self): 27 | super(PolicyTestCase, self).setUp() 28 | self.rules = { 29 | "true": [], 30 | "armada:validate_manifest": [], 31 | "armada:create_endpoints": [["false:false"]] 32 | } 33 | self.useFixture(fixtures.RealPolicyFixture(False)) 34 | self._set_rules() 35 | self.credentials = {} 36 | self.target = {} 37 | 38 | def _set_rules(self): 39 | curr_rules = common_policy.Rules.from_dict(self.rules) 40 | policy._ENFORCER.set_rules(curr_rules) 41 | 42 | @mock.patch.object(policy, 'LOG', autospec=True) 43 | @mock.patch('armada.api.ArmadaRequestContext', autospec=True) 44 | def test_enforce_nonexistent_action(self, mock_ctx, mock_log): 45 | """Validates that unregistered default policy throws exception.""" 46 | action = "example:nope" 47 | mock_ctx.to_policy_view.return_value = self.credentials 48 | 49 | self.assertRaises( 50 | exc.ActionForbidden, policy._enforce_policy, action, self.target, 51 | mock_ctx) 52 | mock_log.exception.assert_called_once_with( 53 | 'Policy not registered for %(action)s', {'action': 'example:nope'}) 54 | 55 | @mock.patch('armada.api.ArmadaRequestContext', autospec=True) 56 | def test_enforce_allowed_action(self, mock_ctx): 57 | """Validates that allowed policy action can be performed.""" 58 | action = "armada:validate_manifest" 59 | mock_ctx.to_policy_view.return_value = self.credentials 60 | 61 | policy._enforce_policy(action, self.target, mock_ctx) 62 | 63 | @mock.patch('armada.api.ArmadaRequestContext', autospec=True) 64 | def test_enforce_disallowed_action(self, mock_ctx): 65 | """Validates that disallowed policy action cannot be performed.""" 66 | action = "armada:create_endpoints" 67 | mock_ctx.to_policy_view.return_value = self.credentials 68 | 69 | self.assertRaises( 70 | exc.ActionForbidden, policy._enforce_policy, action, self.target, 71 | mock_ctx) 72 | -------------------------------------------------------------------------------- /armada/tests/unit/fake_policy.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | policy_data = """ 16 | "admin_required": "role:admin" 17 | "armada:create_endpoints": "rule:admin_required" 18 | "armada:validate_manifest": "rule:admin_required" 19 | "armada:test_release": "rule:admin_required" 20 | "armada:test_manifest": "rule:admin_required" 21 | "armada:get_release": "rule:admin_required" 22 | "tiller:get_status": "rule:admin_required" 23 | """ 24 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/unit/handlers/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/handlers/templates/base.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: blog-1 6 | data: 7 | chart_name: blog-1 8 | release: blog-1 9 | namespace: default 10 | values: {} 11 | source: 12 | type: git 13 | location: https://github.com/namespace/hello-world-chart 14 | subpath: . 15 | reference: master 16 | dependencies: [] 17 | --- 18 | schema: armada/ChartGroup/v1 19 | metadata: 20 | schema: metadata/Document/v1 21 | name: blog-group 22 | data: 23 | description: Deploys Simple Service 24 | sequenced: False 25 | chart_group: 26 | - blog-1 27 | --- 28 | schema: armada/Manifest/v1 29 | metadata: 30 | schema: metadata/Document/v1 31 | name: simple-armada 32 | data: 33 | release_prefix: armada 34 | chart_groups: 35 | - blog-group 36 | --- 37 | schema: armada/Chart/v1 38 | metadata: 39 | schema: metadata/Document/v1 40 | name: blog-3 41 | data: 42 | chart_name: blog-3 43 | release: blog-3 44 | namespace: default 45 | values: {} 46 | source: 47 | type: git 48 | location: https://github.com/namespace/hello-world-chart 49 | subpath: . 50 | reference: master 51 | dependencies: [] 52 | --- 53 | schema: armada/ChartGroup/v1 54 | metadata: 55 | schema: metadata/Document/v1 56 | name: blog-group3 57 | data: 58 | description: Deploys Simple Service 59 | sequenced: False 60 | chart_group: 61 | - blog-3 62 | --- 63 | schema: armada/Chart/v1 64 | metadata: 65 | schema: metadata/Document/v1 66 | name: blog-4 67 | data: 68 | chart_name: blog-4 69 | release: blog-4 70 | namespace: default 71 | values: {} 72 | source: 73 | type: git 74 | location: https://github.com/namespace/hello-world-chart 75 | subpath: . 76 | reference: master 77 | dependencies: [] 78 | --- 79 | schema: armada/ChartGroup/v1 80 | metadata: 81 | schema: metadata/Document/v1 82 | name: blog-group4 83 | data: 84 | description: Deploys Simple Service 85 | sequenced: False 86 | chart_group: 87 | - blog-4 88 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/templates/override-01-expected.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: blog-1 6 | data: 7 | chart_name: blog-1 8 | release: blog-1 9 | namespace: blog-blog 10 | values: {} 11 | source: 12 | type: dev 13 | location: https://github.com/namespace/hello-world-chart 14 | subpath: . 15 | reference: master 16 | dependencies: [] 17 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/templates/override-01.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: blog-1 6 | data: 7 | chart_name: blog-1 8 | release: blog-1 9 | namespace: blog-blog 10 | values: {} 11 | source: 12 | type: dev 13 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/templates/override-02-expected.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: blog-1 6 | data: 7 | chart_name: blog-1 8 | release: blog-1 9 | namespace: default 10 | values: {} 11 | source: 12 | type: git 13 | location: https://github.com/namespace/hello-world-chart 14 | subpath: . 15 | reference: master 16 | dependencies: [] 17 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/templates/override-03-expected.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Manifest/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: simple-armada 6 | data: 7 | release_prefix: armada 8 | chart_groups: 9 | - blog-group3 10 | - blog-group4 11 | --- 12 | schema: armada/Chart/v1 13 | metadata: 14 | schema: metadata/Document/v1 15 | name: blog-3 16 | data: 17 | chart_name: blog-3 18 | release: blog-3 19 | namespace: default 20 | values: {} 21 | source: 22 | type: git 23 | location: https://github.com/namespace/hello-world-chart 24 | subpath: . 25 | reference: master 26 | dependencies: [] 27 | --- 28 | schema: armada/ChartGroup/v1 29 | metadata: 30 | schema: metadata/Document/v1 31 | name: blog-group3 32 | data: 33 | description: Deploys Simple Service 34 | sequenced: False 35 | chart_group: 36 | - blog-3 37 | --- 38 | schema: armada/Chart/v1 39 | metadata: 40 | schema: metadata/Document/v1 41 | name: blog-4 42 | data: 43 | chart_name: blog-4 44 | release: blog-4 45 | namespace: default 46 | values: {} 47 | source: 48 | type: git 49 | location: https://github.com/namespace/hello-world-chart 50 | subpath: . 51 | reference: master 52 | dependencies: [] 53 | --- 54 | schema: armada/ChartGroup/v1 55 | metadata: 56 | schema: metadata/Document/v1 57 | name: blog-group4 58 | data: 59 | description: Deploys Simple Service 60 | sequenced: False 61 | chart_group: 62 | - blog-4 63 | -------------------------------------------------------------------------------- /armada/tests/unit/handlers/test_release_diff.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import mock 16 | 17 | from armada.handlers.release_diff import ReleaseDiff 18 | from armada.tests.unit import base 19 | 20 | 21 | # Test diffs (or absence of) in top-level chart / values. 22 | class ReleaseDiffTestCase(base.ArmadaTestCase): 23 | def test_same_input(self): 24 | diff = ReleaseDiff( 25 | mock.sentinel.chart, mock.sentinel.values, mock.sentinel.chart, 26 | mock.sentinel.values).get_diff() 27 | self.assertFalse(diff) 28 | 29 | def test_diff_input(self): 30 | diff = ReleaseDiff( 31 | mock.sentinel.old_chart, mock.sentinel.old_values, 32 | mock.sentinel.new_chart, mock.sentinel.new_values).get_diff() 33 | self.assertTrue(diff) 34 | -------------------------------------------------------------------------------- /armada/tests/unit/resources/valid_armada_document.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: helm-toolkit 6 | data: 7 | chart_name: helm-toolkit 8 | release: helm-toolkit 9 | namespace: helm-tookit 10 | install: 11 | no_hooks: false 12 | upgrade: 13 | no_hooks: false 14 | values: {} 15 | source: 16 | type: git 17 | location: https://git.openstack.org/openstack/openstack-helm-infra 18 | subpath: helm-toolkit 19 | reference: master 20 | dependencies: [] 21 | --- 22 | schema: armada/Chart/v1 23 | metadata: 24 | schema: metadata/Document/v1 25 | name: mariadb 26 | data: 27 | chart_name: mariadb 28 | release: mariadb 29 | namespace: openstack 30 | timeout: 3600 31 | wait: 32 | timeout: 3600 33 | labels: 34 | release_group: armada-mariadb 35 | install: 36 | no_hooks: false 37 | upgrade: 38 | no_hooks: false 39 | values: {} 40 | source: 41 | type: git 42 | location: https://git.openstack.org/openstack/openstack-helm 43 | subpath: mariadb 44 | reference: master 45 | dependencies: 46 | - helm-toolkit 47 | --- 48 | schema: armada/Chart/v1 49 | metadata: 50 | schema: metadata/Document/v1 51 | name: memcached 52 | data: 53 | chart_name: memcached 54 | release: memcached 55 | namespace: openstack 56 | timeout: 100 57 | wait: 58 | timeout: 100 59 | labels: 60 | release_group: armada-memcached 61 | install: 62 | no_hooks: false 63 | upgrade: 64 | no_hooks: false 65 | values: {} 66 | source: 67 | type: git 68 | location: https://git.openstack.org/openstack/openstack-helm 69 | subpath: memcached 70 | reference: master 71 | dependencies: 72 | - helm-toolkit 73 | --- 74 | schema: armada/Chart/v1 75 | metadata: 76 | schema: metadata/Document/v1 77 | name: keystone 78 | data: 79 | chart_name: keystone 80 | test: true 81 | release: keystone 82 | namespace: openstack 83 | timeout: 100 84 | wait: 85 | timeout: 100 86 | labels: 87 | release_group: armada-keystone 88 | install: 89 | no_hooks: false 90 | upgrade: 91 | no_hooks: false 92 | pre: 93 | delete: 94 | - name: keystone-bootstrap 95 | type: job 96 | labels: 97 | application: keystone 98 | component: bootstrap 99 | values: 100 | replicas: 3 101 | source: 102 | type: git 103 | location: https://git.openstack.org/openstack/openstack-helm 104 | subpath: keystone 105 | reference: master 106 | dependencies: 107 | - helm-toolkit 108 | --- 109 | schema: armada/ChartGroup/v1 110 | metadata: 111 | schema: metadata/Document/v1 112 | name: keystone-infra-services 113 | data: 114 | description: "Keystone Infra Services" 115 | sequenced: True 116 | chart_group: 117 | - mariadb 118 | - memcached 119 | --- 120 | schema: armada/ChartGroup/v1 121 | metadata: 122 | schema: metadata/Document/v1 123 | name: openstack-keystone 124 | data: 125 | description: "Deploying OpenStack Keystone" 126 | sequenced: True 127 | chart_group: 128 | - keystone 129 | --- 130 | schema: armada/Manifest/v1 131 | metadata: 132 | schema: metadata/Document/v1 133 | name: armada-manifest 134 | data: 135 | release_prefix: armada 136 | chart_groups: 137 | - keystone-infra-services 138 | - openstack-keystone 139 | -------------------------------------------------------------------------------- /armada/tests/unit/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/armada/tests/unit/utils/__init__.py -------------------------------------------------------------------------------- /armada/tests/unit/utils/schema.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import unittest 16 | 17 | from armada.utils import schema 18 | 19 | 20 | class SchemaTestCase(unittest.TestCase): 21 | def test_validate_load_schemas(self): 22 | expected_schemas = [ 23 | 'armada/Chart/v1', 'armada/ChartGroup/v1', 'armada/Manifest/v1' 24 | 'armada/Chart/v2', 'armada/ChartGroup/v2', 'armada/Manifest/v2' 25 | ] 26 | for expected_schema in expected_schemas: 27 | self.assertIn(expected_schema, schema._SCHEMAS) 28 | 29 | def test_validate_load_duplicate_schemas_expect_runtime_error(self): 30 | """Validate that calling ``_load_schemas`` results in a 31 | ``RuntimeError`` being thrown, because the call is made during module 32 | import, and importing the schemas again in manually results in 33 | duplicates. 34 | """ 35 | with self.assertRaisesRegex(RuntimeError, 36 | 'Duplicate schema specified for: .*'): 37 | schema._load_schemas() 38 | -------------------------------------------------------------------------------- /armada/tests/unit/utils/test_release.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import unittest 16 | 17 | from armada.utils import release as rel 18 | 19 | 20 | class ReleaseTestCase(unittest.TestCase): 21 | def test_release_prefix_pass(self): 22 | expected = 'armada-test' 23 | prefix, release = ('armada', 'test') 24 | 25 | assert rel.release_prefixer(prefix, release) == expected 26 | 27 | def test_release_prefix_int_string(self): 28 | expected = 'armada-4' 29 | prefix, release = ('armada', 4) 30 | 31 | assert rel.release_prefixer(prefix, release) == expected 32 | 33 | def test_release_prefix_int_int(self): 34 | expected = '4-4' 35 | prefix, release = (4, 4) 36 | 37 | assert rel.release_prefixer(prefix, release) == expected 38 | -------------------------------------------------------------------------------- /armada/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /armada/utils/helm.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | TESTRUN_STATUS_UNKNOWN = 0 16 | TESTRUN_STATUS_SUCCESS = 1 17 | TESTRUN_STATUS_FAILURE = 2 18 | TESTRUN_STATUS_RUNNING = 3 19 | 20 | HELM_HOOK_ANNOTATION = 'helm.sh/hook' 21 | # TODO: Eventually remove 'test-failure' as it is removed in Helm 3, 22 | # leaving for now to ensure test runs leftover from Helm 2 get deleted 23 | # and don't cause name conflicts. 24 | HELM_TEST_HOOKS = ['test', 'test-success', 'test-failure'] 25 | 26 | 27 | def is_test_pod(pod): 28 | annotations = pod.metadata.annotations 29 | 30 | # Retrieve pod's Helm test hooks 31 | test_hooks = None 32 | if annotations: 33 | hook_string = annotations.get(HELM_HOOK_ANNOTATION) 34 | if hook_string: 35 | hooks = hook_string.split(',') 36 | test_hooks = [h for h in hooks if h in HELM_TEST_HOOKS] 37 | 38 | return bool(test_hooks) 39 | 40 | 41 | def get_test_suite_run_success(test_suite_run): 42 | return all( 43 | r.status == TESTRUN_STATUS_SUCCESS for r in test_suite_run.results) 44 | -------------------------------------------------------------------------------- /armada/utils/keystone.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from keystoneauth1 import loading 16 | from keystoneauth1 import session 17 | from oslo_config import cfg 18 | 19 | 20 | def get_keystone_session(): 21 | auth = loading.load_auth_from_conf_options(cfg.CONF, "keystone_authtoken") 22 | return session.Session(auth=auth) 23 | -------------------------------------------------------------------------------- /armada/utils/release.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import time 16 | 17 | import dateutil 18 | 19 | 20 | def release_prefixer(prefix, release): 21 | ''' 22 | attach prefix to release name 23 | ''' 24 | return "{}-{}".format(prefix, release) 25 | 26 | 27 | def label_selectors(labels): 28 | """ 29 | :param labels: dictionary containing k, v 30 | 31 | :return: string of k8s labels 32 | """ 33 | return ",".join(["%s=%s" % (k, v) for k, v in labels.items()]) 34 | 35 | 36 | def get_release_status(release): 37 | """ 38 | :param release: helm release metadata 39 | 40 | :return: status name of release 41 | """ 42 | 43 | return release['info']['status'] 44 | 45 | 46 | def get_last_test_result(release): 47 | """ 48 | :param release: helm release metadata 49 | 50 | :return: whether tests are successful (no tests defined implies success) 51 | """ 52 | test_hooks = ( 53 | hook for hook in release.get('hooks', []) if any( 54 | e in ['test', 'test-success'] for e in hook['events'])) 55 | return all(test['last_run']['phase'] == 'Succeeded' for test in test_hooks) 56 | 57 | 58 | def get_last_deployment_age(release): 59 | """ 60 | :param release: protobuf release object 61 | 62 | :return: age in seconds of last deployment of release 63 | """ 64 | 65 | last_deployed_str = release['info']['last_deployed'] 66 | last_deployed = dateutil.parser.isoparse(last_deployed_str).timestamp() 67 | now = int(time.time()) 68 | last_deployment_age = now - last_deployed 69 | 70 | return last_deployment_age 71 | -------------------------------------------------------------------------------- /armada/utils/validation_message.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import json 16 | 17 | 18 | class ValidationMessage(object): 19 | """ ValidationMessage per Airship convention: 20 | https://docs.airshipit.org/armada/api-conventions.html#output-structure # noqa 21 | 22 | Construction of ValidationMessage message: 23 | 24 | :param string message: Validation failure message. 25 | :param boolean error: True or False, if this is an error message. 26 | :param string name: Identifying name of the validation. 27 | :param string level: The severity of validation result, as "Error", 28 | "Warning", or "Info" 29 | :param string schema: The schema of the document being validated. 30 | :param string doc_name: The name of the document being validated. 31 | :param string diagnostic: Information about what lead to the message, 32 | or details for resolution. 33 | """ 34 | def __init__( 35 | self, 36 | message='Document validation error.', 37 | error=True, 38 | name='Armada error', 39 | level='Error', 40 | schema=None, 41 | doc_name=None, 42 | diagnostic=None): 43 | 44 | # TODO(MarshM) should validate error and level inputs 45 | 46 | self.output = { 47 | 'message': message, 48 | 'error': error, 49 | 'name': name, 50 | 'documents': [], 51 | 'level': level, 52 | 'kind': 'ValidationMessage' 53 | } 54 | if schema and doc_name: 55 | self.output['documents'].append(dict(schema=schema, name=doc_name)) 56 | if diagnostic: 57 | self.output.update(diagnostic=diagnostic) 58 | 59 | def get_output(self): 60 | """ Return ValidationMessage message. 61 | 62 | :returns: The ValidationMessage for the Validation API response. 63 | :rtype: dict 64 | """ 65 | return self.output 66 | 67 | def get_output_json(self): 68 | """ Return ValidationMessage message as JSON. 69 | 70 | :returns: The ValidationMessage formatted in JSON, for logging. 71 | :rtype: json 72 | """ 73 | return json.dumps(self.output, indent=2) 74 | -------------------------------------------------------------------------------- /armada/version.py: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Armada Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import pbr.version 16 | 17 | __all__ = ['__version__'] 18 | 19 | version_info = pbr.version.VersionInfo('armada') 20 | try: 21 | __version__ = version_info.version_string() 22 | except AttributeError: 23 | __version__ = None 24 | -------------------------------------------------------------------------------- /bindep.txt: -------------------------------------------------------------------------------- 1 | # This file contains runtime (non-python) dependencies 2 | # More info at: https://docs.openstack.org/infra/bindep/readme.html 3 | 4 | libffi-dev [test platform:dpkg] 5 | libkrb5-dev [platform:dpkg] 6 | libpq-dev [platform:dpkg] 7 | libsasl2-dev [platform:dpkg] 8 | libssl-dev [platform:dpkg] 9 | libre2-dev [platform:dpkg] 10 | libyaml-dev [platform:dpkg] 11 | ethtool [platform:dpkg] -------------------------------------------------------------------------------- /charts/armada/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | -------------------------------------------------------------------------------- /charts/armada/Chart.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Openstack-Helm Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | description: A Helm chart for Armada 17 | name: armada 18 | version: 0.1.0 19 | keywords: 20 | - armada 21 | home: https://airshipit.org 22 | sources: 23 | - https://opendev.org/airship/armada.git 24 | engine: gotpl 25 | -------------------------------------------------------------------------------- /charts/armada/requirements.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Openstack-Helm Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | dependencies: 16 | - name: helm-toolkit 17 | repository: file://../deps/helm-toolkit 18 | version: ">= 0.1.0" 19 | -------------------------------------------------------------------------------- /charts/armada/templates/configmap-bin.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Armada Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.configmap_bin }} 18 | --- 19 | apiVersion: v1 20 | kind: ConfigMap 21 | metadata: 22 | name: armada-bin 23 | data: 24 | image-repo-sync.sh: | 25 | {{- include "helm-toolkit.scripts.image_repo_sync" . | indent 4 }} 26 | ks-service.sh: | 27 | {{- include "helm-toolkit.scripts.keystone_service" . | indent 4 }} 28 | ks-endpoints.sh: | 29 | {{- include "helm-toolkit.scripts.keystone_endpoints" . | indent 4 }} 30 | ks-user.sh: | 31 | {{- include "helm-toolkit.scripts.keystone_user" . | indent 4 }} 32 | ks-domain-user.sh: | 33 | {{- include "helm-toolkit.scripts.keystone_domain_user" . | indent 4 }} 34 | {{- end }} 35 | -------------------------------------------------------------------------------- /charts/armada/templates/configmap-etc.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Armada Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.configmap_etc }} 18 | {{- $envAll := . }} 19 | 20 | {{- if empty .Values.conf.armada.keystone_authtoken.auth_uri -}} 21 | {{- tuple "identity" "internal" "api" . | include "helm-toolkit.endpoints.keystone_endpoint_uri_lookup" | set .Values.conf.armada.keystone_authtoken "auth_uri" | quote | trunc 0 -}} 22 | {{- end -}} 23 | 24 | {{- if empty .Values.conf.armada.keystone_authtoken.auth_url -}} 25 | {{- tuple "identity" "internal" "api" . | include "helm-toolkit.endpoints.keystone_endpoint_uri_lookup"| set .Values.conf.armada.keystone_authtoken "auth_url" | quote | trunc 0 -}} 26 | {{- end -}} 27 | 28 | {{- $userIdentity := .Values.endpoints.identity.auth.armada -}} 29 | {{- if empty .Values.conf.armada.keystone_authtoken.project_name -}} 30 | {{- set .Values.conf.armada.keystone_authtoken "project_name" $userIdentity.project_name | quote | trunc 0 -}} 31 | {{- end -}} 32 | {{- if empty .Values.conf.armada.keystone_authtoken.project_domain_name -}} 33 | {{- set .Values.conf.armada.keystone_authtoken "project_domain_name" $userIdentity.project_domain_name | quote | trunc 0 -}} 34 | {{- end -}} 35 | {{- if empty .Values.conf.armada.keystone_authtoken.user_domain_name -}} 36 | {{- set .Values.conf.armada.keystone_authtoken "user_domain_name" $userIdentity.user_domain_name | quote | trunc 0 -}} 37 | {{- end -}} 38 | {{- if empty .Values.conf.armada.keystone_authtoken.username -}} 39 | {{- set .Values.conf.armada.keystone_authtoken "username" $userIdentity.username | quote | trunc 0 -}} 40 | {{- end -}} 41 | {{- if empty .Values.conf.armada.keystone_authtoken.password -}} 42 | {{- set .Values.conf.armada.keystone_authtoken "password" $userIdentity.password | quote | trunc 0 -}} 43 | {{- end -}} 44 | --- 45 | apiVersion: v1 46 | kind: ConfigMap 47 | metadata: 48 | name: armada-etc 49 | data: 50 | armada.conf: | 51 | {{ include "helm-toolkit.utils.to_oslo_conf" .Values.conf.armada | indent 4 }} 52 | api-paste.ini: | 53 | {{ include "helm-toolkit.utils.to_ini" .Values.conf.paste | indent 4 }} 54 | policy.yaml: | 55 | {{ toYaml .Values.conf.policy | indent 4 }} 56 | {{- end }} 57 | -------------------------------------------------------------------------------- /charts/armada/templates/configmap-gnp.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2025 The Armada Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.configmap_gnp }} 18 | {{- $envAll := . }} 19 | --- 20 | apiVersion: v1 21 | kind: ConfigMap 22 | metadata: 23 | name: armada-gnp 24 | data: 25 | {{ .Values.global_network_policy.policies_chart_name | default "policy.yaml" | indent 2 }}: | 26 | {{ toYaml .Values.global_network_policy.gnp_template | indent 4 }} 27 | {{- end }} 28 | -------------------------------------------------------------------------------- /charts/armada/templates/ingress-api.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if and .Values.manifests.ingress_api .Values.network.api.ingress.public }} 18 | {{- $ingressOpts := dict "envAll" . "backendServiceType" "armada" "backendPort" "armada-api" -}} 19 | {{ $ingressOpts | include "helm-toolkit.manifests.ingress" }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/job-image-repo-sync.yaml: -------------------------------------------------------------------------------- 1 | {{- if and .Values.manifests.job_image_repo_sync .Values.images.local_registry.active }} 2 | {{- $imageRepoSyncJob := dict "envAll" . "serviceName" "armada" -}} 3 | {{ $imageRepoSyncJob | include "helm-toolkit.manifests.job_image_repo_sync" }} 4 | {{- end }} 5 | -------------------------------------------------------------------------------- /charts/armada/templates/job-ks-endpoints.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.job_ks_endpoints }} 18 | {{- $ksServiceJob := dict "envAll" . "serviceName" "armada" "serviceTypes" ( tuple "armada" ) -}} 19 | {{ $ksServiceJob | include "helm-toolkit.manifests.job_ks_endpoints" }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/job-ks-service.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.job_ks_service }} 18 | {{- $ksServiceJob := dict "envAll" . "serviceName" "armada" "serviceTypes" ( tuple "armada" ) -}} 19 | {{ $ksServiceJob | include "helm-toolkit.manifests.job_ks_service" }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/job-ks-user.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.job_ks_user }} 18 | {{- $ksUserJob := dict "envAll" . "serviceName" "armada" -}} 19 | {{ $ksUserJob | include "helm-toolkit.manifests.job_ks_user" }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/network_policy.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017-2018 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.network_policy -}} 18 | {{- $netpol_opts := dict "envAll" . "name" "application" "label" "armada" -}} 19 | {{ $netpol_opts | include "helm-toolkit.manifests.kubernetes_network_policy" }} 20 | {{- end -}} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/secret-ingress-tls.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */}} 14 | 15 | {{- if .Values.manifests.secret_ingress_tls }} 16 | {{- include "helm-toolkit.manifests.secret_ingress_tls" ( dict "envAll" . "backendServiceType" "armada" ) }} 17 | {{- end }} 18 | -------------------------------------------------------------------------------- /charts/armada/templates/secret-keystone-env.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.secret_keystone }} 18 | {{- $envAll := . }} 19 | {{- range $key1, $userClass := tuple "admin" "armada" }} 20 | {{- $secretName := index $envAll.Values.secrets.identity $userClass }} 21 | --- 22 | apiVersion: v1 23 | kind: Secret 24 | metadata: 25 | name: {{ $secretName }} 26 | type: Opaque 27 | data: 28 | {{- tuple $userClass "internal" $envAll | include "helm-toolkit.snippets.keystone_secret_openrc" | indent 2 -}} 29 | {{- end }} 30 | {{- end }} 31 | -------------------------------------------------------------------------------- /charts/armada/templates/service-ingress.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if and .Values.manifests.service_ingress .Values.network.api.ingress.public }} 18 | {{- $serviceIngressOpts := dict "envAll" . "backendServiceType" "armada" -}} 19 | {{ $serviceIngressOpts | include "helm-toolkit.manifests.service_ingress" }} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/armada/templates/service.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | Copyright 2017 The Openstack-Helm Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */}} 16 | 17 | {{- if .Values.manifests.service }} 18 | {{- $envAll := . }} 19 | --- 20 | apiVersion: v1 21 | kind: Service 22 | metadata: 23 | name: {{ tuple "armada" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }} 24 | spec: 25 | ports: 26 | - name: armada-api 27 | port: {{ tuple "armada" "internal" "api" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }} 28 | {{ if .Values.network.api.node_port.enabled }} 29 | nodePort: {{ .Values.network.api.node_port.port }} 30 | {{ end }} 31 | selector: 32 | {{ tuple $envAll "armada" "api" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }} 33 | {{ if .Values.network.api.node_port.enabled }} 34 | type: NodePort 35 | {{ end }} 36 | {{- end }} 37 | -------------------------------------------------------------------------------- /charts/armada/templates/tests/test-armada-api.yaml: -------------------------------------------------------------------------------- 1 | {{/* 2 | # Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | */}} 16 | {{/* 17 | Test the Armada API, to ensure that the health endpoint is active and able to respond. 18 | */}} 19 | {{- if .Values.manifests.test_armada_api }} 20 | {{- $envAll := . }} 21 | --- 22 | apiVersion: v1 23 | kind: Pod 24 | metadata: 25 | name: armada-api-test 26 | annotations: 27 | "helm.sh/hook": "test" 28 | {{ tuple $envAll | include "helm-toolkit.snippets.release_uuid" }} 29 | {{ dict "envAll" $envAll "podName" "armada-api-test" "containerNames" (list "armada-api-test") | include "helm-toolkit.snippets.kubernetes_mandatory_access_control_annotation" | indent 4 }} 30 | labels: 31 | {{ tuple $envAll "armada" "api-test" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }} 32 | spec: 33 | {{ dict "envAll" $envAll "application" "api_test" | include "helm-toolkit.snippets.kubernetes_pod_security_context" | indent 2 }} 34 | restartPolicy: Never 35 | nodeSelector: 36 | {{ .Values.labels.test.node_selector_key }}: {{ .Values.labels.test.node_selector_value }} 37 | containers: 38 | - name: armada-api-test 39 | env: 40 | - name: 'ARMADA_URL' 41 | value: {{ tuple "armada" "internal" "api" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" | quote }} 42 | image: {{ .Values.images.tags.test }} 43 | imagePullPolicy: {{ .Values.images.pull_policy }} 44 | {{ tuple . .Values.pod.resources.test.api | include "helm-toolkit.snippets.kubernetes_resources" | indent 6 }} 45 | {{ dict "envAll" $envAll "application" "api_test" "container" "armada_api_test" | include "helm-toolkit.snippets.kubernetes_container_security_context" | indent 6 }} 46 | command: ["/bin/bash", "-c", "curl -v -X GET --fail ${ARMADA_URL}/api/v1.0/health; exit $?"] 47 | ... 48 | {{- end }} 49 | -------------------------------------------------------------------------------- /charts/deps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/charts/deps/.gitkeep -------------------------------------------------------------------------------- /controller.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | clean_container(){ 3 | echo "Destroying $1 container..." 4 | docker stop $1 >/dev/null 5 | docker rm $1 >/dev/null 6 | echo "...container destroyed" 7 | } 8 | 9 | readlink(){ 10 | ( 11 | cd $(dirname $1) 12 | echo $PWD/$(basename $1) 13 | ) 14 | } 15 | 16 | # Check to see if the aramada container exists 17 | if [ -n "$( sudo docker ps -a | grep quay.io/airshipit/armada )" ]; then 18 | echo "Armada container already exists..." 19 | clean_container armada 20 | fi 21 | 22 | # Check to see if the user is trying to apply a chart 23 | if [ $1 = "apply" ]; then 24 | # TODO Handle erroneous or missing inputs 25 | # Bring up a new armada container with passed in yaml mounted to the container 26 | echo "Creating an Armada container..." 27 | docker run -d --net host -p 8000:8000 --name armada -v $(readlink $(dirname $2)):$(readlink $(dirname $2)) -v ~/.kube/config:/armada/.kube/config -v ~/.kube/plugins/armada/examples/:/examples quay.io/airshipit/armada:latest 28 | docker exec armada armada apply $(readlink $2) 29 | else 30 | # For any other command the chart does not need to be mounted to the container 31 | # Bring up a new armada container 32 | echo "Creating an Armada container..." 33 | docker run -d --net host -p 8000:8000 --name armada -v ~/.kube/config:/armada/.kube/config -v ~/.kube/plugins/armada/examples/:/examples quay.io/airshipit/armada:latest 34 | docker exec armada armada "$@" 35 | fi 36 | clean_container armada 37 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | # The order of packages is significant, because pip processes them in the order 2 | # of appearance. Changing the order has an impact on the overall integration 3 | # process, which may cause wedges in the gate later. 4 | docutils 5 | plantuml 6 | reno 7 | sphinx-rtd-theme 8 | Sphinx 9 | sphinxcontrib-apidoc 10 | sphinxcontrib-plantuml -------------------------------------------------------------------------------- /doc/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/doc/source/_static/.placeholder -------------------------------------------------------------------------------- /doc/source/_static/armada.policy.yaml.sample: -------------------------------------------------------------------------------- 1 | #"admin_required": "role:admin or role:admin_ucp" 2 | 3 | #"service_or_admin": "rule:admin_required or rule:service_role" 4 | 5 | #"service_role": "role:service" 6 | 7 | #"admin_viewer": "role:admin_ucp_viewer or rule:service_or_admin" 8 | 9 | # Install manifest charts 10 | # POST /api/v1.0/apply/ 11 | #"armada:create_endpoints": "rule:admin_required" 12 | 13 | # Validate manifest 14 | # POST /api/v1.0/validatedesign/ 15 | #"armada:validate_manifest": "rule:admin_viewer" 16 | 17 | # Test release 18 | # GET /api/v1.0/test/{release} 19 | #"armada:test_release": "rule:admin_required" 20 | 21 | # Test manifest 22 | # POST /api/v1.0/tests/ 23 | #"armada:test_manifest": "rule:admin_required" 24 | 25 | # Get helm releases 26 | # GET /api/v1.0/releases/ 27 | #"armada:get_release": "rule:admin_viewer" 28 | 29 | # Get Tiller status 30 | # GET /api/v1.0/status/ 31 | #"tiller:get_status": "rule:admin_viewer" 32 | 33 | -------------------------------------------------------------------------------- /doc/source/commands/index.rst: -------------------------------------------------------------------------------- 1 | .. Armada documentation master file, created by 2 | sphinx-quickstart on Wed May 3 10:39:15 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Commands Guide 7 | ============== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | apply.rst 14 | test.rst 15 | validate.rst 16 | -------------------------------------------------------------------------------- /doc/source/commands/test.rst: -------------------------------------------------------------------------------- 1 | Armada - Test 2 | ============= 3 | 4 | 5 | Commands 6 | -------- 7 | 8 | .. code:: bash 9 | 10 | Usage: armada test [OPTIONS] 11 | 12 | This command test deployed charts 13 | 14 | The test command will run the release chart tests either via a 15 | manifest or by targeting a release. 16 | 17 | To obtain armada deployed releases: 18 | 19 | $ armada test --file examples/simple.yaml 20 | 21 | To test release: 22 | 23 | $ armada test --release blog-1 24 | 25 | Options: 26 | --cleanup Delete test pods after test completion 27 | --enable-all Run disabled chart tests 28 | --file TEXT armada manifest 29 | --release TEXT helm release 30 | --target-manifest TEXT The target manifest to run. Required for 31 | specifying which manifest to run when multiple 32 | are available. 33 | --help Show this message and exit. 34 | 35 | Synopsis 36 | -------- 37 | 38 | The test command will perform helm test defined on the release. Test command can 39 | test a single release or a manifest. 40 | -------------------------------------------------------------------------------- /doc/source/commands/validate.rst: -------------------------------------------------------------------------------- 1 | Armada - Validate 2 | ================= 3 | 4 | 5 | Commands 6 | -------- 7 | 8 | .. code:: bash 9 | 10 | Usage: armada validate [OPTIONS] FILENAME 11 | 12 | This command validates Armada Manifest 13 | 14 | The validate argument must be a relative path to Armada manifest 15 | 16 | $ armada validate examples/simple.yaml 17 | 18 | Options: 19 | --help Show this message and exit. 20 | 21 | Synopsis 22 | -------- 23 | 24 | The validate command will take in an Armada manifest and will validate if it is 25 | correctly defined and consumable. 26 | -------------------------------------------------------------------------------- /doc/source/development/contributing.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../../../CONTRIBUTING.rst 2 | -------------------------------------------------------------------------------- /doc/source/development/index.rst: -------------------------------------------------------------------------------- 1 | .. Armada documentation master file, created by 2 | sphinx-quickstart on Wed May 3 10:39:15 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Developers Guide 7 | ================ 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | getting-started.rst 14 | contributing.rst 15 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. Armada documentation master file, created by 2 | sphinx-quickstart on Wed May 3 10:39:15 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ================================== 7 | Welcome to Armada's documentation! 8 | ================================== 9 | 10 | .. include:: ../../README.rst 11 | 12 | .. toctree:: 13 | :caption: Armada 14 | :hidden: 15 | :maxdepth: 2 16 | 17 | development/index 18 | operations/index 19 | commands/index 20 | 21 | .. toctree:: 22 | :caption: Airship 1 Project Documentation 23 | :hidden: 24 | 25 | Airship Documentation 26 | Armada 27 | Deckhand 28 | Divingbell 29 | Drydock 30 | Pegleg 31 | Promenade 32 | Shipyard 33 | Treasuremap 34 | -------------------------------------------------------------------------------- /doc/source/operations/documents/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2019 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Document Authoring Guide 18 | ======================== 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Contents: 23 | 24 | v1/index 25 | v2/index 26 | migration-v1-v2 27 | -------------------------------------------------------------------------------- /doc/source/operations/documents/v1/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2019 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | v1 18 | == 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Contents: 23 | 24 | document-authoring 25 | schemas 26 | -------------------------------------------------------------------------------- /doc/source/operations/documents/v2/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2019 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | v2 (EXPERIMENTAL!) 18 | ================== 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Contents: 23 | 24 | document-authoring 25 | schemas 26 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/api-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | 18 | API Exceptions 19 | -------------- 20 | 21 | .. currentmodule:: armada.exceptions.api_exceptions 22 | 23 | .. autoexception:: ApiException 24 | :members: 25 | :show-inheritance: 26 | :undoc-members: 27 | 28 | .. autoexception:: ClientError 29 | :members: 30 | :show-inheritance: 31 | :undoc-members: 32 | 33 | .. autoexception:: ClientForbiddenError 34 | :members: 35 | :show-inheritance: 36 | :undoc-members: 37 | 38 | .. autoexception:: ClientUnauthorizedError 39 | :members: 40 | :show-inheritance: 41 | :undoc-members: 42 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/armada-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Armada Exceptions 18 | ----------------- 19 | 20 | .. currentmodule:: armada.exceptions.armada_exceptions 21 | 22 | .. autoexception:: ArmadaTimeoutException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | 27 | .. autoexception:: ProtectedReleaseException 28 | :members: 29 | :show-inheritance: 30 | :undoc-members: 31 | 32 | .. autoexception:: InvalidValuesYamlException 33 | :members: 34 | :show-inheritance: 35 | :undoc-members: 36 | 37 | .. autoexception:: InvalidOverrideValuesYamlException 38 | :members: 39 | :show-inheritance: 40 | :undoc-members: 41 | 42 | .. autoexception:: ChartDeployException 43 | :members: 44 | :show-inheritance: 45 | :undoc-members: 46 | 47 | .. autoexception:: WaitException 48 | :members: 49 | :show-inheritance: 50 | :undoc-members: 51 | 52 | .. autoexception:: DeploymentLikelyPendingException 53 | :members: 54 | :show-inheritance: 55 | :undoc-members: 56 | 57 | .. autoexception:: PreUpdateJobDeleteException 58 | :members: 59 | :show-inheritance: 60 | :undoc-members: 61 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/base-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Base Exceptions 18 | --------------- 19 | 20 | .. currentmodule:: armada.exceptions.base_exception 21 | 22 | .. autoexception:: ActionForbidden 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/chartbuilder-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Chartbuilder Exceptions 18 | ----------------------- 19 | 20 | .. currentmodule:: armada.exceptions.chartbuilder_exceptions 21 | 22 | .. autoexception:: HelmChartBuildException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/guide-exceptions.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Armada Exceptions 18 | ================= 19 | 20 | .. include:: api-exceptions.inc 21 | .. include:: armada-exceptions.inc 22 | .. include:: base-exceptions.inc 23 | .. include:: chartbuilder-exceptions.inc 24 | .. include:: k8s-exceptions.inc 25 | .. include:: manifest-exceptions.inc 26 | .. include:: override-exceptions.inc 27 | .. include:: source-exceptions.inc 28 | .. include:: validate-exceptions.inc 29 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/index.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Exceptions Guide 18 | ================ 19 | 20 | .. toctree:: 21 | :maxdepth: 2 22 | :caption: Contents: 23 | 24 | guide-exceptions.rst 25 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/k8s-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2018 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Kubernetes Exceptions 18 | --------------------- 19 | 20 | .. currentmodule:: armada.exceptions.k8s_exceptions 21 | 22 | .. autoexception:: KubernetesErrorEventException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | 27 | .. autoexception:: KubernetesUnknownStreamingEventTypeException 28 | :members: 29 | :show-inheritance: 30 | :undoc-members: 31 | 32 | .. autoexception:: KubernetesWatchTimeoutException 33 | :members: 34 | :show-inheritance: 35 | :undoc-members: 36 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/manifest-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Manifest Exceptions 18 | ------------------- 19 | 20 | .. currentmodule:: armada.exceptions.manifest_exceptions 21 | 22 | .. autoexception:: ManifestException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/override-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Override Exceptions 18 | ------------------- 19 | 20 | .. currentmodule:: armada.exceptions.override_exceptions 21 | 22 | .. autoexception:: InvalidOverrideFileException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | 27 | .. autoexception:: InvalidOverrideValueException 28 | :members: 29 | :show-inheritance: 30 | :undoc-members: 31 | 32 | .. autoexception:: UnknownDocumentOverrideException 33 | :members: 34 | :show-inheritance: 35 | :undoc-members: 36 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/source-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Source Exceptions 18 | ----------------- 19 | 20 | .. currentmodule:: armada.exceptions.source_exceptions 21 | 22 | .. autoexception:: ChartSourceException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | 27 | .. autoexception:: GitException 28 | :members: 29 | :show-inheritance: 30 | :undoc-members: 31 | 32 | .. autoexception:: InvalidPathException 33 | :members: 34 | :show-inheritance: 35 | :undoc-members: 36 | 37 | .. autoexception:: TarballDownloadException 38 | :members: 39 | :show-inheritance: 40 | :undoc-members: 41 | 42 | .. autoexception:: TarballExtractException 43 | :members: 44 | :show-inheritance: 45 | :undoc-members: 46 | -------------------------------------------------------------------------------- /doc/source/operations/exceptions/validate-exceptions.inc: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. 3 | All Rights Reserved. 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); you may 6 | not use this file except in compliance with the License. You may obtain 7 | a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | License for the specific language governing permissions and limitations 15 | under the License. 16 | 17 | Lint (Validate) Exceptions 18 | -------------------------- 19 | 20 | .. currentmodule:: armada.exceptions.validate_exceptions 21 | 22 | .. autoexception:: InvalidManifestException 23 | :members: 24 | :show-inheritance: 25 | :undoc-members: 26 | 27 | .. autoexception:: InvalidChartDefinitionException 28 | :members: 29 | :show-inheritance: 30 | :undoc-members: 31 | 32 | .. autoexception:: InvalidReleaseException 33 | :members: 34 | :show-inheritance: 35 | :undoc-members: 36 | 37 | .. autoexception:: InvalidArmadaObjectException 38 | :members: 39 | :show-inheritance: 40 | :undoc-members: 41 | -------------------------------------------------------------------------------- /doc/source/operations/guide-configure.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Configuring Armada 3 | ================== 4 | 5 | 6 | Armada uses an INI-like standard oslo_config file. A sample 7 | file can be generated via tox 8 | 9 | .. code-block:: bash 10 | 11 | $ tox -e genconfig 12 | $ tox -e genpolicy 13 | 14 | Customize your configuration based on the information below 15 | 16 | Keystone Integration 17 | ==================== 18 | 19 | Armada requires a service account to use for validating API 20 | tokens 21 | 22 | .. note:: 23 | 24 | If you do not have a keystone already deploy, then armada can deploy a keystone services: 25 | 26 | $ armada apply keystone-manifest.yaml 27 | 28 | .. code-block:: bash 29 | 30 | $ openstack domain create 'ucp' 31 | $ openstack project create --domain 'ucp' 'service' 32 | $ openstack user create --domain ucp --project service --project-domain 'ucp' --password armada armada 33 | $ openstack role add --project-domain ucp --user-domain ucp --user armada --project service admin 34 | 35 | # OR 36 | 37 | $ ./tools/keystone-account.sh 38 | 39 | The service account must then be included in the armada.conf 40 | 41 | .. code-block:: ini 42 | 43 | [keystone_authtoken] 44 | auth_type = password 45 | auth_uri = https://:5000/ 46 | auth_url = https://:35357/ 47 | auth_version = 3 48 | delay_auth_decision = true 49 | password = armada 50 | project_domain_name = ucp 51 | project_name = service 52 | user_domain_name = ucp 53 | user_name = armada 54 | -------------------------------------------------------------------------------- /doc/source/operations/guide-helm-plugin.rst: -------------------------------------------------------------------------------- 1 | Armada Plugin 2 | ============= 3 | 4 | The armada plugin extends all the functionality of Armada to be used as a plugin with Helm. 5 | 6 | Install Plugin 7 | --------------- 8 | 9 | **Install directly from the repository** 10 | 11 | :: 12 | 13 | helm plugin install https://opendev.org/airship/armada.git 14 | 15 | **Clone and install locally** 16 | 17 | :: 18 | 19 | git clone https://opendev.org/airship/armada.git ~/.helm/plugins/ 20 | helm plugin install ~/.helm/plugins/armada 21 | 22 | Usage 23 | ------ 24 | 25 | **helm [options]** 26 | :: 27 | 28 | helm armada apply ~/.helm/plugins/armada/examples/simple.yaml 29 | -------------------------------------------------------------------------------- /doc/source/operations/guide-troubleshooting.rst: -------------------------------------------------------------------------------- 1 | Checking Logs 2 | ------------- 3 | 4 | In order to check the logs the logs file will be in `~/.armada` directory. 5 | 6 | When running Armada in the container you can execute docker logs to retrieve logs 7 | 8 | .. code:: bash 9 | 10 | docker logs [container-name | container-id] 11 | 12 | Errors/Exceptions 13 | ----------------- 14 | 15 | A guide for interpreting errors/exceptions can be found `here `_. 16 | 17 | Working with SSL 18 | ---------------- 19 | 20 | You might run into SSL error with armada if you are not using the correct 21 | versions of SSL. 22 | 23 | Debugging Checklist: 24 | 25 | 1. python -c "import ssl; print ssl.OPENSSL_VERSION" 26 | 27 | If the version that appears is less than 1.0, then problems will occur. 28 | Please update to current or use our docker container solve this issue 29 | 30 | 2. check your urllib3 version, you could run into urllib3 issues. older versions 31 | of this lib can cause SSL errors run ``pip install --upgrade urllib3`` and it 32 | should solve this issue 33 | 34 | 35 | 36 | Issue 37 | ----- 38 | 39 | If the issue that you are having does not appear here please check the Armada 40 | issues on 41 | `GitHub `_. 42 | If the issue does not exist, please create an issue. 43 | -------------------------------------------------------------------------------- /doc/source/operations/index.rst: -------------------------------------------------------------------------------- 1 | .. Armada documentation master file, created by 2 | sphinx-quickstart on Wed May 3 10:39:15 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Operations Guide 7 | ================ 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | documents/index 14 | guide-configure 15 | guide-troubleshooting 16 | guide-use-armada 17 | metrics 18 | exceptions/index 19 | guide-helm-plugin 20 | sampleconf 21 | samplepolicy 22 | -------------------------------------------------------------------------------- /doc/source/operations/metrics.rst: -------------------------------------------------------------------------------- 1 | .. _metrics: 2 | 3 | Metrics 4 | ======= 5 | 6 | Armada exposes metric data, for consumption by `Prometheus`_. 7 | 8 | Exporting 9 | --------- 10 | 11 | Metric data can be exported via: 12 | 13 | * API: Prometheus exporter in the `/metrics` endpoint. The Armada chart 14 | includes the appropriate Prometheus scrape configurations for this endpoint. 15 | * CLI: `--metrics-output=` of `apply` command. The 16 | `node exporter text file collector`_ can then be used to export the produced 17 | text files to Prometheus. 18 | 19 | Metric Names 20 | ------------ 21 | 22 | Metric names are as follows: 23 | 24 | `armada_` + + `_` + 25 | 26 | Supported s 27 | ------------------- 28 | 29 | The below tree of s are measured. Supported prometheus labels are noted. 30 | Labels are inherited by sub-actions except as noted. 31 | 32 | * `apply`: 33 | 34 | * description: apply a manifest 35 | * labels: `manifest` 36 | * sub-actions: 37 | 38 | * `chart_handle`: 39 | 40 | * description: fully handle a chart (see below sub-actions) 41 | * labels: 42 | 43 | * `chart` 44 | * `action` (install|upgrade|noop) (not included in sub-actions) 45 | * sub-actions: 46 | 47 | * `chart_download` 48 | * `chart_deploy` 49 | * `chart_test` 50 | * `chart_delete`: 51 | 52 | * description: delete a chart (e.g. due to `FAILED` status) 53 | * labels: `chart` 54 | 55 | Supported s 56 | ------------------- 57 | 58 | * `failure_total`: total failed attempts 59 | * `attempt_total`: total attempts 60 | * `attempt_inprogress`: total attempts in progress 61 | * `duration_seconds`: duration of each attempt 62 | 63 | Timeouts 64 | ^^^^^^^^ 65 | 66 | The `chart_handle` and `chart_test` actions additionally include the following 67 | metrics: 68 | 69 | * `timeout_duration_seconds`: configured chart timeout duration in seconds 70 | * `timeout_usage_ratio`: `= duration_seconds / timeout_duration_seconds` 71 | 72 | These can help identify charts whose timeouts may need to 73 | be changed to avoid potential failures or to acheive faster failures. 74 | 75 | Chart concurrency 76 | ^^^^^^^^^^^^^^^^^ 77 | 78 | The `chart_handle` action additionally includes the following metric: 79 | 80 | * `concurrency_count`: count of charts being handled concurrently 81 | 82 | This can help identify opportunities for greater chart concurrency. 83 | 84 | .. _Prometheus: https://prometheus.io 85 | .. _`node exporter text file collector`: https://github.com/prometheus/node_exporter#textfile-collector 86 | -------------------------------------------------------------------------------- /doc/source/operations/sampleconf.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. All other rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Sample Configuration File 17 | ========================== 18 | 19 | The following is a sample Armada configuration for adaptation and use. It is 20 | auto-generated from Armada when this documentation is built, so 21 | if you are having issues with an option, please compare your version of 22 | Armada with the version of this documentation. 23 | 24 | The sample configuration can also be viewed in `file form <../_static/armada.conf.sample>`_. 25 | 26 | .. literalinclude:: ../_static/armada.conf.sample 27 | -------------------------------------------------------------------------------- /doc/source/operations/samplepolicy.rst: -------------------------------------------------------------------------------- 1 | .. 2 | Copyright 2017 AT&T Intellectual Property. All other rights reserved. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Sample Policy File 17 | ================== 18 | The following is a sample Armada policy file for adaptation and use. It is 19 | auto-generated from Armada when this documentation is built, so 20 | if you are having issues with an option, please compare your version of 21 | Armada with the version of this documentation. 22 | 23 | The sample policy file can also be viewed in `file form <../_static/armada.policy.yaml.sample>`_. 24 | 25 | .. literalinclude:: ../_static/armada.policy.yaml.sample 26 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -ex 18 | 19 | CMD="armada" 20 | 21 | # Define port 22 | ARMADA_UWSGI_PORT=${ARMADA_UWSGI_PORT:-8000} 23 | # How long uWSGI should wait for each Armada response 24 | ARMADA_UWSGI_TIMEOUT=${ARMADA_UWSGI_TIMEOUT:-3600} 25 | # Number of uWSGI workers to handle API requests 26 | ARMADA_UWSGI_WORKERS=${ARMADA_UWSGI_WORKERS:-4} 27 | # Threads per worker 28 | ARMADA_UWSGI_THREADS=${ARMADA_UWSGI_THREADS:-1} 29 | # Prometheus multiprocess dir 30 | ARMADA_PROMETHEUS_MULTIPROC_DIR=${ARMADA_PROMETHEUS_MULTIPROC_DIR:-$(mktemp -d -p /tmp armada-metrics-XXXXXX)} 31 | 32 | # Start Armada application 33 | # TODO(fmontei): Should be specifying callable too. But Armada spins up the 34 | # server during import in `armada.api.server`. 35 | if [ "$1" = 'server' ]; then 36 | exec uwsgi \ 37 | -b 32768 \ 38 | --die-on-term \ 39 | --http :"${ARMADA_UWSGI_PORT}" \ 40 | --http-timeout "$ARMADA_UWSGI_TIMEOUT" \ 41 | --enable-threads \ 42 | --env prometheus_multiproc_dir="$ARMADA_PROMETHEUS_MULTIPROC_DIR" \ 43 | -L \ 44 | --lazy-apps \ 45 | --master \ 46 | --paste config:/etc/armada/api-paste.ini \ 47 | --pyargv "--config-file /etc/armada/armada.conf" \ 48 | --threads "$ARMADA_UWSGI_THREADS" \ 49 | --workers "$ARMADA_UWSGI_WORKERS" 50 | else 51 | exec $CMD "$@" 52 | fi 53 | -------------------------------------------------------------------------------- /etc/armada/api-paste.ini: -------------------------------------------------------------------------------- 1 | [app:armada-api] 2 | paste.app_factory = armada.api.server:paste_start_armada 3 | 4 | [pipeline:main] 5 | pipeline = authtoken armada-api 6 | 7 | [filter:authtoken] 8 | paste.filter_factory = keystonemiddleware.auth_token:filter_factory 9 | delay_auth_decision = True 10 | -------------------------------------------------------------------------------- /etc/armada/config-generator.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/armada/armada.conf.sample 3 | wrap_width = 79 4 | namespace = armada.conf 5 | namespace = oslo.log 6 | namespace = oslo.policy 7 | namespace = oslo.middleware 8 | namespace = keystonemiddleware.auth_token 9 | -------------------------------------------------------------------------------- /etc/armada/policy-generator.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | output_file = etc/armada/policy.yaml.sample 3 | wrap_width = 79 4 | 5 | namespace = armada 6 | -------------------------------------------------------------------------------- /etc/armada/policy.yaml: -------------------------------------------------------------------------------- 1 | # 2 | #"admin_required": "role:admin or role:admin_ucp" 3 | 4 | # 5 | #"service_or_admin": "rule:admin_required or rule:service_role" 6 | 7 | # 8 | #"service_role": "role:service" 9 | 10 | # 11 | #"admin_viewer": "role:admin_ucp_viewer or rule:service_or_admin" 12 | 13 | # Install manifest charts 14 | # POST /api/v1.0/apply/ 15 | #"armada:create_endpoints": "rule:admin_required" 16 | 17 | # Validate manifest 18 | # POST /api/v1.0/validatedesign/ 19 | #"armada:validate_manifest": "rule:admin_viewer" 20 | 21 | # Test release 22 | # GET /api/v1.0/test/{release} 23 | #"armada:test_release": "rule:admin_required" 24 | 25 | # Test manifest 26 | # POST /api/v1.0/tests/ 27 | #"armada:test_manifest": "rule:admin_required" 28 | 29 | # Get helm releases 30 | # GET /api/v1.0/releases/ 31 | #"armada:get_release": "rule:admin_viewer" 32 | 33 | # Get Tiller status 34 | # GET /api/v1.0/status/ 35 | #"tiller:get_status": "rule:admin_viewer" -------------------------------------------------------------------------------- /etc/armada/policy.yaml.sample: -------------------------------------------------------------------------------- 1 | #"admin_required": "role:admin or role:admin_ucp" 2 | 3 | #"service_or_admin": "rule:admin_required or rule:service_role" 4 | 5 | #"service_role": "role:service" 6 | 7 | #"admin_viewer": "role:admin_ucp_viewer or rule:service_or_admin" 8 | 9 | # Install manifest charts 10 | # POST /api/v1.0/apply/ 11 | #"armada:create_endpoints": "rule:admin_required" 12 | 13 | # Validate manifest 14 | # POST /api/v1.0/validatedesign/ 15 | #"armada:validate_manifest": "rule:admin_viewer" 16 | 17 | # Test release 18 | # GET /api/v1.0/test/{release} 19 | #"armada:test_release": "rule:admin_required" 20 | 21 | # Test manifest 22 | # POST /api/v1.0/tests/ 23 | #"armada:test_manifest": "rule:admin_required" 24 | 25 | # Get helm releases 26 | # GET /api/v1.0/releases/ 27 | #"armada:get_release": "rule:admin_viewer" 28 | 29 | # Get Tiller status 30 | # GET /api/v1.0/status/ 31 | #"tiller:get_status": "rule:admin_viewer" 32 | 33 | -------------------------------------------------------------------------------- /examples/armada-keystone-manifest.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: keystone 6 | data: 7 | values: 8 | bootstrap: 9 | script: | 10 | openstack domain create 'ucp' 11 | openstack project create --domain 'ucp' 'service' 12 | openstack user create --domain ucp --project service --project-domain 'ucp' --password armada armada 13 | openstack role add --project-domain ucp --user-domain ucp --user armada --project service admin 14 | -------------------------------------------------------------------------------- /examples/podinfo.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: helm-toolkit 6 | data: 7 | chart_name: helm-toolkit 8 | release: helm-toolkit 9 | namespace: helm-tookit 10 | install: 11 | no_hooks: false 12 | upgrade: 13 | no_hooks: false 14 | values: {} 15 | source: 16 | type: tar 17 | location: https://tarballs.opendev.org/openstack/openstack-helm-infra/helm-toolkit-0.2.23.tgz 18 | subpath: helm-toolkit 19 | --- 20 | schema: armada/Chart/v1 21 | metadata: 22 | schema: metadata/Document/v1 23 | name: podinfo 24 | data: 25 | chart_name: podinfo 26 | release: podinfo 27 | namespace: podinfo 28 | install: 29 | no_hooks: false 30 | upgrade: 31 | no_hooks: false 32 | values: 33 | foo: bar 34 | dependencies: 35 | - helm-toolkit 36 | source: 37 | type: local 38 | location: /podinfo/charts/podinfo 39 | subpath: . 40 | reference: master 41 | --- 42 | schema: armada/ChartGroup/v1 43 | metadata: 44 | schema: metadata/Document/v1 45 | name: podinfo 46 | data: 47 | description: Deploys Simple Service 48 | sequenced: False 49 | chart_group: 50 | - podinfo 51 | --- 52 | schema: armada/Manifest/v1 53 | metadata: 54 | schema: metadata/Document/v1 55 | name: podinfo 56 | data: 57 | release_prefix: podinfo 58 | chart_groups: 59 | - podinfo 60 | -------------------------------------------------------------------------------- /examples/simple-ovr-values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | name: blog-1 5 | data: 6 | release: chart-example 7 | namespace: blog-blog 8 | --- 9 | schema: armada/Chart/v1 10 | metadata: 11 | name: blog-2 12 | data: 13 | release: chart-example-2 14 | namespace: blog-blog 15 | --- 16 | schema: armada/ChartGroup/v1 17 | metadata: 18 | name: blog-group 19 | data: 20 | description: Change value deploy 21 | chart_group: 22 | - blog-1 23 | -------------------------------------------------------------------------------- /examples/simple.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: blog-1 6 | data: 7 | chart_name: blog-1 8 | release: blog-1 9 | namespace: default 10 | install: 11 | no_hooks: false 12 | upgrade: 13 | no_hooks: false 14 | values: {} 15 | source: 16 | type: git 17 | location: https://github.com/gardlt/hello-world-chart 18 | subpath: . 19 | reference: 87aad18f7d8c6a1a08f3adc8866efd33bee6aa52 20 | --- 21 | schema: armada/Chart/v1 22 | metadata: 23 | schema: metadata/Document/v1 24 | name: blog-2 25 | data: 26 | chart_name: blog-2 27 | release: blog-2 28 | namespace: default 29 | values: 30 | some: value 31 | install: 32 | no_hooks: false 33 | upgrade: 34 | no_hooks: false 35 | source: 36 | type: git 37 | location: https://github.com/gardlt/hello-world-chart 38 | subpath: . 39 | reference: master 40 | --- 41 | schema: armada/ChartGroup/v1 42 | metadata: 43 | schema: metadata/Document/v1 44 | name: blog-group 45 | data: 46 | description: Deploys Simple Service 47 | sequenced: False 48 | chart_group: 49 | - blog-1 50 | - blog-2 51 | --- 52 | schema: armada/Manifest/v1 53 | metadata: 54 | schema: metadata/Document/v1 55 | name: simple-armada 56 | data: 57 | release_prefix: armada 58 | chart_groups: 59 | - blog-group 60 | -------------------------------------------------------------------------------- /examples/tar_example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | schema: armada/Chart/v1 3 | metadata: 4 | schema: metadata/Document/v1 5 | name: helm-toolkit 6 | data: 7 | chart_name: helm-toolkit 8 | release: helm-toolkit 9 | namespace: helm-tookit 10 | values: {} 11 | source: 12 | type: git 13 | location: git://opendev.org/openstack/openstack-helm-infra.git 14 | subpath: helm-toolkit 15 | reference: master 16 | --- 17 | schema: armada/Chart/v1 18 | metadata: 19 | schema: metadata/Document/v1 20 | name: mariadb-tarball 21 | data: 22 | chart_name: mariadb-tarball 23 | release: mariadb-tarball 24 | namespace: tarball 25 | wait: 26 | timeout: 3600 27 | install: 28 | no_hooks: false 29 | upgrade: 30 | no_hooks: false 31 | values: {} 32 | source: 33 | type: tar 34 | location: http://localhost:8879/charts/mariadb-0.1.0.tgz 35 | subpath: mariadb 36 | dependencies: 37 | - helm-toolkit 38 | --- 39 | schema: armada/ChartGroup/v1 40 | metadata: 41 | schema: metadata/Document/v1 42 | name: tar-example 43 | data: 44 | description: "Deploying mariadb tarball URL" 45 | sequenced: True 46 | chart_group: 47 | - mariadb-tarball 48 | --- 49 | schema: armada/Manifest/v1 50 | metadata: 51 | schema: metadata/Document/v1 52 | name: armada-manifest 53 | data: 54 | release_prefix: armada 55 | chart_groups: 56 | - tar-example 57 | -------------------------------------------------------------------------------- /images/armada/Dockerfile.ubuntu_bionic: -------------------------------------------------------------------------------- 1 | ARG FROM=ubuntu:18.04 2 | FROM ${FROM} 3 | 4 | LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ 5 | org.opencontainers.image.url='https://airshipit.org' \ 6 | org.opencontainers.image.documentation='https://docs.airshipit.org/armada' \ 7 | org.opencontainers.image.source='https://opendev.org/airship/armada' \ 8 | org.opencontainers.image.vendor='The Airship Authors' \ 9 | org.opencontainers.image.licenses='Apache-2.0' 10 | 11 | ENV DEBIAN_FRONTEND noninteractive 12 | ENV LANG=C.UTF-8 13 | ENV LC_ALL=C.UTF-8 14 | 15 | EXPOSE 8000 16 | 17 | RUN set -ex && \ 18 | apt-get update && apt-get upgrade -y && \ 19 | apt-get -y install \ 20 | ca-certificates \ 21 | curl \ 22 | git \ 23 | netbase \ 24 | python3-dev \ 25 | python3-setuptools \ 26 | --no-install-recommends \ 27 | && apt-get autoremove -yqq --purge \ 28 | && apt-get clean \ 29 | && rm -rf \ 30 | /var/lib/apt/lists/* \ 31 | /tmp/* \ 32 | /var/tmp/* \ 33 | /usr/share/man \ 34 | /usr/share/doc \ 35 | /usr/share/doc-base 36 | 37 | WORKDIR /armada 38 | 39 | # Add armada user 40 | RUN useradd -u 1000 -g users -d $(pwd) armada 41 | 42 | ENTRYPOINT ["./entrypoint.sh"] 43 | CMD ["server"] 44 | 45 | COPY requirements-frozen-bionic.txt ./requirements.txt 46 | 47 | ENV LD_LIBRARY_PATH=/usr/local/lib 48 | 49 | ARG HELM_ARTIFACT_URL 50 | ARG LIBYAML_VERSION=0.2.5 51 | 52 | # Build 53 | RUN set -ex \ 54 | && buildDeps=' \ 55 | automake \ 56 | gcc \ 57 | libssl-dev \ 58 | libtool \ 59 | make \ 60 | python3-pip \ 61 | ' \ 62 | && apt-get -qq update \ 63 | # Keep git separate so it's not removed below 64 | && apt-get install -y $buildDeps --no-install-recommends \ 65 | && git clone https://github.com/yaml/libyaml.git \ 66 | && cd libyaml \ 67 | && git checkout $LIBYAML_VERSION \ 68 | && ./bootstrap \ 69 | && ./configure \ 70 | && make \ 71 | && make install \ 72 | && cd .. \ 73 | && rm -fr libyaml \ 74 | && python3 -m pip install -U pip \ 75 | && pip3 install -r requirements.txt --no-cache-dir \ 76 | && curl -fSSL -O ${HELM_ARTIFACT_URL} \ 77 | && tar -xvf $(basename ${HELM_ARTIFACT_URL}) \ 78 | && mv linux-amd64/helm /usr/local/bin \ 79 | && apt-get purge -y --auto-remove $buildDeps \ 80 | && apt-get autoremove -yqq --purge \ 81 | && apt-get clean \ 82 | && rm -rf \ 83 | /var/lib/apt/lists/* \ 84 | /tmp/* \ 85 | /var/tmp/* \ 86 | /usr/share/man \ 87 | /usr/share/doc \ 88 | /usr/share/doc-base 89 | 90 | COPY . ./ 91 | 92 | # Setting the version explicitly for PBR 93 | ENV PBR_VERSION 0.8.0 94 | ENV PATH=$PATH:/usr/bin/git 95 | ENV GIT_PYTHON_GIT_EXECUTABLE=/usr/bin/git 96 | 97 | RUN \ 98 | chown -R armada:users . && \ 99 | python3 setup.py install 100 | 101 | USER armada 102 | -------------------------------------------------------------------------------- /images/armada/Dockerfile.ubuntu_focal: -------------------------------------------------------------------------------- 1 | ARG FROM=ubuntu:20.04 2 | ARG ARMADA_GO=quay.io/airshipit/armada-go:latest-ubuntu_focal 3 | FROM ${ARMADA_GO} AS armada_go 4 | FROM ${FROM} 5 | 6 | LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ 7 | org.opencontainers.image.url='https://airshipit.org' \ 8 | org.opencontainers.image.documentation='https://docs.airshipit.org/armada' \ 9 | org.opencontainers.image.source='https://opendev.org/airship/armada' \ 10 | org.opencontainers.image.vendor='The Airship Authors' \ 11 | org.opencontainers.image.licenses='Apache-2.0' 12 | 13 | ENV DEBIAN_FRONTEND noninteractive 14 | ENV LANG=C.UTF-8 15 | ENV LC_ALL=C.UTF-8 16 | 17 | EXPOSE 8000 18 | 19 | RUN set -ex && \ 20 | apt-get update && apt-get upgrade -y && \ 21 | apt-get -y install \ 22 | ca-certificates \ 23 | curl \ 24 | git \ 25 | netbase \ 26 | python3-dev \ 27 | python3-setuptools \ 28 | --no-install-recommends \ 29 | && apt-get autoremove -yqq --purge \ 30 | && apt-get clean \ 31 | && rm -rf \ 32 | /var/lib/apt/lists/* \ 33 | /tmp/* \ 34 | /var/tmp/* \ 35 | /usr/share/man \ 36 | /usr/share/doc \ 37 | /usr/share/doc-base 38 | 39 | WORKDIR /armada 40 | 41 | # Add armada user 42 | RUN useradd -u 1000 -g users -d $(pwd) armada 43 | 44 | ENTRYPOINT ["./entrypoint.sh"] 45 | CMD ["server"] 46 | 47 | COPY requirements-frozen.txt ./ 48 | 49 | ENV LD_LIBRARY_PATH=/usr/local/lib 50 | 51 | ARG HELM_ARTIFACT_URL 52 | ARG LIBYAML_VERSION=0.2.5 53 | 54 | # Build 55 | RUN set -ex \ 56 | && buildDeps=' \ 57 | automake \ 58 | gcc \ 59 | libssl-dev \ 60 | libtool \ 61 | make \ 62 | python3-pip \ 63 | ' \ 64 | && apt-get -qq update \ 65 | # Keep git separate so it's not removed below 66 | && apt-get install -y $buildDeps git --no-install-recommends \ 67 | && git clone https://github.com/yaml/libyaml.git \ 68 | && cd libyaml \ 69 | && git checkout $LIBYAML_VERSION \ 70 | && ./bootstrap \ 71 | && ./configure \ 72 | && make \ 73 | && make install \ 74 | && cd .. \ 75 | && rm -fr libyaml \ 76 | && python3 -m pip install -U pip \ 77 | && pip3 install -r requirements-frozen.txt --no-cache-dir \ 78 | && curl -fSSL -O ${HELM_ARTIFACT_URL} \ 79 | && tar -xvf $(basename ${HELM_ARTIFACT_URL}) \ 80 | && mv linux-amd64/helm /usr/local/bin \ 81 | && apt-get purge -y --auto-remove $buildDeps \ 82 | && apt-get autoremove -yqq --purge \ 83 | && apt-get clean \ 84 | && rm -rf \ 85 | /var/lib/apt/lists/* \ 86 | /tmp/* \ 87 | /var/tmp/* \ 88 | /usr/share/man \ 89 | /usr/share/doc \ 90 | /usr/share/doc-base 91 | 92 | COPY . ./ 93 | COPY --from=armada_go /usr/local/bin/armada /usr/local/bin/armada-go 94 | 95 | # Setting the version explicitly for PBR 96 | ENV PBR_VERSION 0.8.0 97 | 98 | RUN \ 99 | chown -R armada:users . && \ 100 | pip3 install -e . --verbose --use-pep517 \ 101 | && echo "/armada" \ 102 | > /usr/local/lib/python3.8/dist-packages/armada.pth 103 | 104 | USER armada 105 | -------------------------------------------------------------------------------- /images/armada/Dockerfile.ubuntu_jammy: -------------------------------------------------------------------------------- 1 | # 2 | # In order to fix rate limit error 3 | # 4 | # 429 Too Many Requests - Server message: too many requests: 5 | # You have reached your pull rate limit. 6 | # You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit 7 | ARG FROM=quay.io/airshipit/ubuntu:jammy 8 | ARG ARMADA_GO=quay.io/airshipit/armada-go:latest-ubuntu_jammy 9 | FROM ${ARMADA_GO} AS armada_go 10 | FROM ${FROM} 11 | 12 | LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ 13 | org.opencontainers.image.url='https://airshipit.org' \ 14 | org.opencontainers.image.documentation='https://docs.airshipit.org/armada' \ 15 | org.opencontainers.image.source='https://opendev.org/airship/armada' \ 16 | org.opencontainers.image.vendor='The Airship Authors' \ 17 | org.opencontainers.image.licenses='Apache-2.0' 18 | 19 | ENV DEBIAN_FRONTEND noninteractive 20 | ENV LANG=C.UTF-8 21 | ENV LC_ALL=C.UTF-8 22 | 23 | EXPOSE 8000 24 | 25 | RUN set -ex && \ 26 | apt-get update && apt-get upgrade -y && \ 27 | apt-get -y install \ 28 | ca-certificates \ 29 | curl \ 30 | netbase \ 31 | python3-dev \ 32 | python3-setuptools \ 33 | --no-install-recommends \ 34 | && apt-get autoremove -yqq --purge \ 35 | && apt-get clean \ 36 | && rm -rf \ 37 | /var/lib/apt/lists/* \ 38 | /tmp/* \ 39 | /var/tmp/* \ 40 | /usr/share/man \ 41 | /usr/share/doc \ 42 | /usr/share/doc-base 43 | 44 | WORKDIR /armada 45 | 46 | # Add armada user 47 | RUN useradd -u 1000 -g users -d $(pwd) armada 48 | 49 | ENTRYPOINT ["./entrypoint.sh"] 50 | CMD ["server"] 51 | 52 | COPY requirements-frozen.txt ./ 53 | 54 | ENV LD_LIBRARY_PATH=/usr/local/lib 55 | 56 | ARG HELM_ARTIFACT_URL 57 | 58 | 59 | RUN set -ex \ 60 | && buildDeps=' \ 61 | automake \ 62 | gcc \ 63 | libssl-dev \ 64 | libyaml-dev \ 65 | libtool \ 66 | make \ 67 | python3-pip \ 68 | ' \ 69 | && apt-get -qq update \ 70 | # Keep git separate so it's not removed below 71 | && apt-get install -y $buildDeps git --no-install-recommends \ 72 | && python3 -m pip install -U pip \ 73 | && pip3 install -r requirements-frozen.txt --no-cache-dir \ 74 | && curl -fSSL -O ${HELM_ARTIFACT_URL} \ 75 | && tar -xvf $(basename ${HELM_ARTIFACT_URL}) \ 76 | && mv linux-amd64/helm /usr/local/bin \ 77 | && apt-get purge -y --auto-remove $buildDeps \ 78 | && apt-get autoremove -yqq --purge \ 79 | && apt-get clean \ 80 | && rm -rf \ 81 | /var/lib/apt/lists/* \ 82 | /tmp/* \ 83 | /var/tmp/* \ 84 | /usr/share/man \ 85 | /usr/share/doc \ 86 | /usr/share/doc-base 87 | 88 | COPY . ./ 89 | COPY --from=armada_go /usr/local/bin/armada /usr/local/bin/armada-go 90 | 91 | # Setting the version explicitly for PBR 92 | ENV PBR_VERSION 0.8.0 93 | 94 | RUN \ 95 | chown -R armada:users . && \ 96 | pip3 install -e . --verbose --use-pep517 \ 97 | && echo "/armada" \ 98 | > /usr/local/lib/python3.10/dist-packages/armada.pth 99 | 100 | USER armada 101 | -------------------------------------------------------------------------------- /plugin.yaml: -------------------------------------------------------------------------------- 1 | name: "Armada" 2 | version: "0.0.3" 3 | usage: "Manages multiple Helm charts with a centralized Armada yaml" 4 | description: |- 5 | This plugin provides Helm access to Armada. A tool for managing 6 | multiple Helm charts with dependencies by centralizing all configurations 7 | in a single Armada yaml and providing lifecycle hooks for all Helm releases 8 | usage: 9 | $ helm armada apply /examples/openstack-helm.yaml 10 | ignoreFlags: false 11 | useTunnel: false 12 | command: "sh $HELM_PLUGIN_DIR/controller.sh" 13 | -------------------------------------------------------------------------------- /releasenotes/notes/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/releasenotes/notes/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/releasenotes/source/_static/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/_templates/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/airshipit/armada/d29b37e1fb7417b7152d9f1f8be68acbf75ba6c5/releasenotes/source/_templates/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/index.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Armada Release Notes 3 | ==================== 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | unreleased 9 | -------------------------------------------------------------------------------- /releasenotes/source/unreleased.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Current Series Release Notes 3 | ============================= 4 | 5 | .. release-notes:: 6 | 7 | -------------------------------------------------------------------------------- /requirements-direct.txt: -------------------------------------------------------------------------------- 1 | click 2 | deepdiff 3 | falcon 4 | GitPython 5 | jsonschema 6 | kubernetes 7 | mock 8 | paste 9 | PasteDeploy 10 | packaging 11 | pbr 12 | prometheus-client 13 | pylibyaml 14 | python_dateutil 15 | python-memcached 16 | PyYAML 17 | Requests 18 | responses 19 | retry 20 | testtools 21 | urllib3 22 | uWSGI 23 | 24 | # Openstack Caracal 2024.1 25 | # https://releases.openstack.org/caracal/index.html 26 | barbican==18.0.0 27 | 28 | python-barbicanclient==5.7.0 29 | python-keystoneclient==5.4.0 30 | 31 | keystoneauth1==5.6.0 32 | keystonemiddleware==10.6.0 33 | 34 | oslo.cache==3.7.0 35 | oslo.concurrency==6.0.0 36 | oslo.config==9.4.0 37 | oslo.context==5.5.0 38 | oslo.db==15.0.0 39 | oslo.i18n==6.3.0 40 | oslo.log==5.5.1 41 | oslo.messaging==14.7.2 42 | oslo.metrics==0.8.0 43 | oslo.middleware==6.1.0 44 | oslo.policy==4.3.0 45 | oslo.serialization==5.4.1 46 | oslo.service==3.4.1 47 | oslo.upgradecheck==2.3.0 48 | oslo.utils==7.1.0 49 | oslo.versionedobjects==3.3.0 -------------------------------------------------------------------------------- /requirements-frozen.txt: -------------------------------------------------------------------------------- 1 | alembic==1.14.0 2 | amqp==5.3.1 3 | attrs==24.2.0 4 | autopage==0.5.2 5 | barbican==18.0.0 6 | bcrypt==4.2.1 7 | cachetools==5.5.0 8 | castellan==5.2.0 9 | certifi==2024.8.30 10 | cffi==1.17.1 11 | charset-normalizer==3.4.0 12 | click==8.1.7 13 | cliff==4.8.0 14 | cmd2==2.5.8 15 | cryptography==42.0.8 16 | debtcollector==3.0.0 17 | decorator==5.1.1 18 | deepdiff==8.1.1 19 | dnspython==2.7.0 20 | dogpile.cache==1.3.3 21 | eventlet==0.38.1 22 | falcon==4.0.2 23 | fasteners==0.19 24 | futurist==3.0.0 25 | gitdb==4.0.11 26 | GitPython==3.1.43 27 | google-auth==2.36.0 28 | greenlet==3.1.1 29 | idna==3.10 30 | iso8601==2.1.0 31 | Jinja2==3.1.4 32 | jsonschema==4.23.0 33 | jsonschema-specifications==2023.12.1 34 | keystoneauth1==5.6.0 35 | keystonemiddleware==10.6.0 36 | kombu==5.4.2 37 | kubernetes==30.1.0 38 | ldap3==2.9.1 39 | logutils==0.3.5 40 | Mako==1.3.8 41 | MarkupSafe==3.0.2 42 | microversion-parse==2.0.0 43 | mock==5.1.0 44 | msgpack==1.1.0 45 | netaddr==1.3.0 46 | netifaces==0.11.0 47 | oauthlib==3.2.2 48 | orderly-set==5.2.3 49 | os-service-types==1.7.0 50 | oslo.cache==3.7.0 51 | oslo.concurrency==6.0.0 52 | oslo.config==9.4.0 53 | oslo.context==5.5.0 54 | oslo.db==15.0.0 55 | oslo.i18n==6.3.0 56 | oslo.log==5.5.1 57 | oslo.messaging==14.7.2 58 | oslo.metrics==0.8.0 59 | oslo.middleware==6.1.0 60 | oslo.policy==4.3.0 61 | oslo.serialization==5.4.1 62 | oslo.service==3.4.1 63 | oslo.upgradecheck==2.3.0 64 | oslo.utils==7.1.0 65 | oslo.versionedobjects==3.3.0 66 | packaging==24.2 67 | Paste==3.10.1 68 | PasteDeploy==3.1.0 69 | pbr==6.1.0 70 | pecan==1.5.1 71 | pip==24.1 72 | prettytable==3.12.0 73 | prometheus_client==0.21.1 74 | py==1.11.0 75 | pyasn1==0.6.1 76 | pyasn1_modules==0.4.0 77 | pycadf==4.0.0 78 | pycparser==2.22 79 | PyJWT==2.10.1 80 | pylibyaml==0.1.0 81 | pyOpenSSL==24.3.0 82 | pyparsing==3.2.0 83 | pyperclip==1.9.0 84 | python-barbicanclient==5.7.0 85 | python-dateutil==2.9.0.post0 86 | python-keystoneclient==5.4.0 87 | python-memcached==1.62 88 | pytz==2024.2 89 | PyYAML==6.0.2 90 | referencing==0.35.1 91 | repoze.lru==0.7 92 | requests==2.32.3 93 | requests-oauthlib==1.3.1 94 | responses==0.25.3 95 | retry==0.9.2 96 | rfc3986==2.0.0 97 | Routes==2.5.1 98 | rpds-py==0.22.3 99 | rsa==4.9 100 | setuptools==70.1.0 101 | six==1.17.0 102 | smmap==5.0.1 103 | SQLAlchemy==1.4.54 104 | statsd==4.0.1 105 | stevedore==5.4.0 106 | testresources==2.0.1 107 | testscenarios==0.5.0 108 | testtools==2.7.2 109 | typing_extensions==4.12.2 110 | tzdata==2024.2 111 | urllib3==2.2.3 112 | uWSGI==2.0.28 113 | vine==5.1.0 114 | wcwidth==0.2.13 115 | WebOb==1.8.9 116 | websocket-client==1.8.0 117 | wheel==0.43.0 118 | wrapt==1.17.0 119 | yappi==1.6.10 120 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Warning: This file should be empty. 2 | # Specify direct dependencies in requirements-direct.txt instead. 3 | -r requirements-direct.txt 4 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = Armada 3 | version = 1.1 4 | summary = Tool for managing multiple Helm charts with dependencies by centralizing all configurations in a single Armada YAML and providing life-cycle hooks for all Helm releases. 5 | description_file = README.rst 6 | author = The Airship Authors 7 | author_email = airship-discuss@lists.airshipit.org 8 | home_page = https://airshipit.org 9 | 10 | classifier = 11 | Intended Audience :: Information Technology 12 | Intended Audience :: System Administrators 13 | License :: OSI Approved :: Apache Software License 14 | Operating System :: POSIX :: Linux 15 | Programming Language :: Python 16 | Programming Language :: Python :: 3 17 | Programming Language :: Python :: 3.6 18 | Programming Language :: Python :: 3.8 19 | Programming Language :: Python :: 3.10 20 | 21 | [files] 22 | packages = 23 | armada 24 | armada.cli 25 | armada.api 26 | armada.handlers 27 | 28 | [build_sphinx] 29 | source-dir = doc/source 30 | build-dir = doc/build 31 | all_files = 1 32 | warning-is-error = 1 33 | 34 | [upload_sphinx] 35 | upload-dir = doc/build/html 36 | 37 | [entry_points] 38 | console_scripts = 39 | armada = armada.shell:main 40 | oslo.config.opts = 41 | armada.conf = armada.conf.opts:list_opts 42 | oslo.policy.policies = 43 | armada = armada.common.policies:list_rules 44 | 45 | [pbr] 46 | warnerrors = True 47 | 48 | [wheel] 49 | universal = 1 50 | 51 | [nosetests] 52 | verbosity=3 53 | with-doctest=1 54 | 55 | [yapf] 56 | based_on_style = pep8 57 | column_limit = 79 58 | blank_line_before_nested_class_or_def = true 59 | blank_line_before_module_docstring = true 60 | split_before_logical_operator = false 61 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import setuptools 2 | 3 | try: 4 | import multiprocessing # noqa 5 | except ImportError: 6 | pass 7 | 8 | setuptools.setup(package_data={'armada': ['schemas/*.yaml']}, 9 | include_package_data=True, 10 | setup_requires=['pbr>=2.0.0'], 11 | pbr=True) 12 | -------------------------------------------------------------------------------- /test-requirements.txt: -------------------------------------------------------------------------------- 1 | bandit==1.6.0 2 | # cmd2>=1.5.0 3 | coverage==5.3 4 | flake8-import-order 5 | importlib-metadata 6 | flake8 >= 6.0.0 7 | grpcio-tools>=1.16.0 8 | os-testr>=1.0.0 # Apache-2.0 9 | pyflakes 10 | sphinx-rtd-theme==0.5.0 11 | stestr==4.1.0 12 | testrepository==0.0.20 13 | testresources==2.0.1 14 | testscenarios==0.5.0 15 | # testtools==2.5.0 16 | # tox>=3.28.0, <4.0.0 17 | # typing-extensions>=3.7.2 18 | yapf 19 | 20 | -------------------------------------------------------------------------------- /tools/armada_image_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | set -x 17 | 18 | IMAGE=$1 19 | ARMADA_CONTAINER_NAME=armada_test_$(date +%Y%m%d%H%M%s%s) 20 | 21 | function generate_conf { 22 | tox -e genconfig > /dev/null 23 | tox -e genpolicy > /dev/null 24 | ETCDIR=$(mktemp -d)/armada 25 | mkdir -p ${ETCDIR} > /dev/null 26 | cp etc/armada/api-paste.ini ${ETCDIR}/api-paste.ini 27 | cp etc/armada/policy.yaml.sample ${ETCDIR}/policy.yaml 28 | echo ${ETCDIR} 29 | } 30 | 31 | function test_armada { 32 | TMPETC=$1 33 | docker run \ 34 | -d --name "${ARMADA_CONTAINER_NAME}" --net host \ 35 | -v ${TMPETC}:/etc/armada \ 36 | ${IMAGE} 37 | 38 | sleep 10 39 | 40 | RESULT=$(curl --noproxy '*' -i 'http://127.0.0.1:8000/api/v1.0/health' | tr '\r' '\n' | head -1) 41 | GOOD="HTTP/1.1 204 No Content" 42 | if [[ "${RESULT}" != "${GOOD}" ]]; then 43 | if docker exec -t ${CONTAINER_NAME} /bin/bash -c "curl -i 'http://127.0.0.1:8000/api/v1.0/health' --noproxy '*' | tr '\r' '\n' | head -1 "; then 44 | RESULT="${GOOD}" 45 | fi 46 | fi 47 | 48 | if [[ ${RESULT} == ${GOOD} ]] 49 | then 50 | RC=0 51 | else 52 | RC=1 53 | fi 54 | 55 | docker logs "${ARMADA_CONTAINER_NAME}" 56 | return $RC 57 | } 58 | 59 | function cleanup { 60 | TMPDIR=$1 61 | docker stop "${ARMADA_CONTAINER_NAME}" 62 | docker rm "${ARMADA_CONTAINER_NAME}" 63 | rm -rf $TMPDIR 64 | } 65 | 66 | TMPETC=$(generate_conf) 67 | 68 | test_armada $TMPETC 69 | RC=$? 70 | 71 | cleanup $TMPETC 72 | 73 | exit $RC 74 | -------------------------------------------------------------------------------- /tools/gate/playbooks/airship-run-scripts.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: primary 15 | tasks: 16 | - name: Override images 17 | when: buildset_registry is defined 18 | vars: 19 | work_dir: "{{ zuul.project.src_dir }}" 20 | block: 21 | - name: Buildset registry alias 22 | include_role: 23 | name: deploy-env 24 | tasks_from: buildset_registry_alias 25 | 26 | - name: Print zuul 27 | debug: 28 | var: zuul 29 | 30 | - name: Override proposed images from artifacts 31 | shell: > 32 | find {{ override_paths | join(" ") }} -type f -exec sed -Ei 33 | "s#['\"]?docker\.io/({{ repo }}):({{ tag }})['\"]?\$#{{ buildset_registry_alias }}:{{ buildset_registry.port }}/\1:\2#g" {} + 34 | loop: "{{ zuul.artifacts | default([]) }}" 35 | args: 36 | chdir: "{{ work_dir }}" 37 | loop_control: 38 | loop_var: zj_zuul_artifact 39 | when: "'metadata' in zj_zuul_artifact and zj_zuul_artifact.metadata.type | default('') == 'container_image'" 40 | vars: 41 | tag: "{{ zj_zuul_artifact.metadata.tag }}" 42 | repo: "{{ zj_zuul_artifact.metadata.repository }}" 43 | override_paths: 44 | - ../openstack-helm*/*/values* 45 | - ../openstack-helm-infra/tools/deployment/ 46 | 47 | - name: Diff 48 | shell: | 49 | set -ex; 50 | for dir in openstack-helm openstack-helm-infra; do 51 | path="{{ work_dir }}/../${dir}/" 52 | if [ ! -d "${path}" ]; then continue; fi 53 | echo "${dir} diff" 54 | cd "${path}"; git diff; cd -; 55 | done 56 | 57 | - name: "creating directory for run artifacts" 58 | file: 59 | path: "/tmp/artifacts" 60 | state: directory 61 | 62 | - name: Run gate scripts 63 | include_role: 64 | name: "{{ ([item] | flatten | length == 1) | ternary('airship-run-script', 'airship-run-script-set') }}" 65 | vars: 66 | workload: "{{ [item] | flatten }}" 67 | loop: "{{ gate_scripts }}" 68 | 69 | - name: "Downloads artifacts to executor" 70 | synchronize: 71 | src: "/tmp/artifacts" 72 | dest: "{{ zuul.executor.log_root }}/{{ inventory_hostname }}" 73 | mode: pull 74 | ignore_errors: True 75 | ... 76 | -------------------------------------------------------------------------------- /tools/gate/playbooks/airskiff-reduce-site.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - hosts: primary 16 | tasks: 17 | - name: Overwrite Armada manifest 18 | shell: | 19 | git checkout v1.9 20 | mv tools/gate/manifests/full-site.yaml \ 21 | type/skiff/manifests/full-site.yaml 22 | args: 23 | chdir: "{{ zuul.projects['opendev.org/airship/treasuremap'].src_dir }}" 24 | -------------------------------------------------------------------------------- /tools/gate/playbooks/build-charts.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019, AT&T Intellectual Property 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - hosts: primary 16 | tasks: 17 | - name: Execute the make target to package Helm charts. 18 | make: 19 | chdir: "{{ zuul.project.src_dir }}" 20 | target: charts 21 | params: 22 | HTK_COMMIT: "{{ HTK_COMMIT | default('') }}" 23 | register: result 24 | failed_when: result.failed 25 | -------------------------------------------------------------------------------- /tools/gate/playbooks/checkout-treasuremap-ref.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: all 15 | 16 | tasks: 17 | - name: Checkout treasuremap ref 18 | shell: | 19 | set -xe; 20 | 21 | : "${TREASUREMAP_REF:=v1.9}" 22 | 23 | cd ../treasuremap 24 | git fetch https://review.opendev.org/airship/treasuremap ${TREASUREMAP_REF} && git checkout FETCH_HEAD 25 | 26 | args: 27 | chdir: "{{ zuul.project.src_dir }}" 28 | environment: 29 | TREASUREMAP_REF: "{{ treasuremap_ref }}" 30 | 31 | ... -------------------------------------------------------------------------------- /tools/gate/playbooks/debug-report.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - hosts: primary 16 | tasks: 17 | - name: Build debug report 18 | shell: | 19 | ./tools/gate/debug-report.sh 20 | args: 21 | chdir: "{{ zuul.projects['opendev.org/airship/treasuremap'].src_dir }}" 22 | 23 | - name: Extract debug report 24 | shell: | 25 | mkdir -p /tmp/debug 26 | tar -xf debug-* -C /tmp/debug 27 | args: 28 | chdir: "{{ zuul.projects['opendev.org/airship/treasuremap'].src_dir }}" 29 | 30 | - name: Pull logs to executor 31 | synchronize: 32 | src: /tmp/debug 33 | dest: "{{ zuul.executor.log_root }}/{{ inventory_hostname }}" 34 | mode: pull 35 | -------------------------------------------------------------------------------- /tools/gate/playbooks/deploy-env.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: all 15 | become: true 16 | gather_facts: true 17 | 18 | roles: 19 | - ensure-python 20 | - ensure-pip 21 | - clear-firewall 22 | - deploy-apparmor 23 | - deploy-selenium 24 | - deploy-env 25 | - ensure-tox 26 | 27 | tasks: 28 | - name: Install Packaging python module for tools/airship 29 | block: 30 | - pip: 31 | name: packaging 32 | version: 23.1 33 | executable: pip3 34 | become: True 35 | 36 | ... 37 | -------------------------------------------------------------------------------- /tools/gate/playbooks/git-config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - hosts: primary 16 | tasks: 17 | - name: Git config 18 | shell: | 19 | set -xe; 20 | tee .git/config << EOF 21 | [remote "origin"] 22 | url = https://opendev.org/airship/treasuremap.git 23 | EOF 24 | args: 25 | chdir: "{{ zuul.projects['opendev.org/airship/treasuremap'].src_dir }}" 26 | -------------------------------------------------------------------------------- /tools/gate/playbooks/mount-volumes.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: all 15 | roles: 16 | - mount-extra-volume 17 | ... 18 | -------------------------------------------------------------------------------- /tools/gate/playbooks/osh-infra-build.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Openstack-Helm Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - hosts: primary 16 | 17 | vars: 18 | work_dir: "{{ zuul.project.src_dir }}/{{ zuul_osh_infra_relative_path | default('') }}" 19 | gather_facts: True 20 | roles: 21 | - build-helm-packages 22 | tags: 23 | - build-helm-packages 24 | 25 | - hosts: all 26 | 27 | vars: 28 | work_dir: "{{ zuul.project.src_dir }}/{{ zuul_osh_infra_relative_path | default('') }}" 29 | gather_facts: False 30 | become: yes 31 | roles: 32 | - bindep 33 | - build-images 34 | tags: 35 | - bindep 36 | - build-images 37 | -------------------------------------------------------------------------------- /tools/gate/playbooks/osh-infra-collect-logs.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: all 15 | vars_files: 16 | - vars.yaml 17 | vars: 18 | work_dir: "{{ zuul.project.src_dir }}/{{ zuul_osh_infra_relative_path | default('') }}" 19 | logs_dir: "/tmp/logs" 20 | roles: 21 | - gather-host-logs 22 | tags: 23 | - gather-host-logs 24 | 25 | - hosts: primary 26 | vars_files: 27 | - vars.yaml 28 | vars: 29 | work_dir: "{{ zuul.project.src_dir }}/{{ zuul_osh_infra_relative_path | default('') }}" 30 | logs_dir: "/tmp/logs" 31 | roles: 32 | - helm-release-status 33 | - describe-kubernetes-objects 34 | - gather-pod-logs 35 | - gather-prom-metrics 36 | - gather-selenium-data 37 | tags: 38 | - helm-release-status 39 | - describe-kubernetes-objects 40 | - gather-pod-logs 41 | - gather-prom-metrics 42 | - gather-selenium-data 43 | ... 44 | -------------------------------------------------------------------------------- /tools/gate/playbooks/prepare-hosts.yaml: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | --- 14 | - hosts: all 15 | roles: 16 | - bindep 17 | - start-zuul-console 18 | ... 19 | -------------------------------------------------------------------------------- /tools/gate/playbooks/roles: -------------------------------------------------------------------------------- 1 | ../roles -------------------------------------------------------------------------------- /tools/gate/playbooks/vars.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2017 The Openstack-Helm Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | docker_daemon: 16 | group: zuul 17 | registry-mirrors: 18 | - "http://{{ zuul_site_mirror_fqdn }}:8082/" 19 | storage-driver: overlay2 20 | -------------------------------------------------------------------------------- /tools/gate/roles/disable-systemd-resolved/tasks/disable-systemd-resolved.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - name: Disable systemd-resolved service 16 | systemd: 17 | state: stopped 18 | enabled: no 19 | masked: yes 20 | daemon_reload: yes 21 | name: systemd-resolved 22 | become: yes 23 | 24 | - name: Remove local stub dns from resolv.conf, if it exists 25 | lineinfile: 26 | path: /etc/resolv.conf 27 | state: absent 28 | regexp: '^nameserver.*127.0.0.1' 29 | become: yes 30 | 31 | - name: Add upstream nameservers in resolv.conf 32 | blockinfile: 33 | path: /etc/resolv.conf 34 | block: | 35 | nameserver 8.8.8.8 36 | nameserver 8.8.4.4 37 | become: yes 38 | -------------------------------------------------------------------------------- /tools/gate/roles/disable-systemd-resolved/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2020 AT&T Intellectual Property. All other rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | - include: disable-systemd-resolved.yaml 16 | -------------------------------------------------------------------------------- /tools/helm_install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2018 AT&T Intellectual Property. All other rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | set -x 18 | 19 | HELM=$1 20 | HELM_ARTIFACT_URL=${HELM_ARTIFACT_URL:-"https://get.helm.sh/helm-v3.17.3-linux-amd64.tar.gz"} 21 | 22 | 23 | function install_helm_binary { 24 | if [[ -z "${HELM}" ]] 25 | then 26 | echo "No Helm binary target location." 27 | exit -1 28 | fi 29 | 30 | if [[ -w "$(dirname ${HELM})" ]] 31 | then 32 | TMP_DIR=${BUILD_DIR:-$(mktemp -d)} 33 | curl -o "${TMP_DIR}/helm.tar.gz" "${HELM_ARTIFACT_URL}" 34 | cd ${TMP_DIR} 35 | tar -xvzf helm.tar.gz 36 | cp "${TMP_DIR}/linux-amd64/helm" "${HELM}" 37 | else 38 | echo "Cannot write to ${HELM}" 39 | exit -1 40 | fi 41 | } 42 | 43 | install_helm_binary 44 | -------------------------------------------------------------------------------- /tools/helm_tk.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 AT&T Intellectual Property. All other rights reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | set -eux 18 | 19 | HTK_REPO=${HTK_REPO:-"https://opendev.org/openstack/openstack-helm.git"} 20 | HTK_STABLE_COMMIT=${HTK_COMMIT:-"master"} 21 | 22 | TMP_DIR=$(mktemp -d) 23 | 24 | { 25 | HTK_REPO_DIR=$TMP_DIR/htk 26 | git clone "$HTK_REPO" "$HTK_REPO_DIR" 27 | (cd "$HTK_REPO_DIR" && git reset --hard "${HTK_STABLE_COMMIT}") 28 | cp -r "${HTK_REPO_DIR}/helm-toolkit" charts/deps/ 29 | } 30 | 31 | rm -rf "${TMP_DIR}" 32 | -------------------------------------------------------------------------------- /tools/keystone-account.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ -x $(which openstack) ]; then 4 | pip install python-openstackclient 5 | fi 6 | 7 | openstack domain create 'ucp' 8 | openstack project create --domain 'ucp' 'service' 9 | openstack user create --domain ucp --project service --project-domain 'ucp' --password armada armada 10 | openstack role add --project-domain ucp --user-domain ucp --user armada --project service admin 11 | -------------------------------------------------------------------------------- /tools/whitespace-linter.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x 3 | 4 | RES=$(git grep -E -l " +$") 5 | 6 | if [[ -n $RES ]]; then 7 | exit 1 8 | fi 9 | --------------------------------------------------------------------------------