pax_global_header 0000666 0000000 0000000 00000000064 13174010367 0014514 g ustar 00root root 0000000 0000000 52 comment=ddf8d562a9df0c23e6d206dea67fbbc5e2a488f9
glare-0.5.0/ 0000775 0000000 0000000 00000000000 13174010367 0012610 5 ustar 00root root 0000000 0000000 glare-0.5.0/.gitignore 0000664 0000000 0000000 00000002160 13174010367 0014577 0 ustar 00root root 0000000 0000000 # Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
.installed.cfg
*.egg*
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.testrepository/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
ChangeLog
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# IPython Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# dotenv
.env
# virtualenv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
# IDE files
.idea
# Files created by doc build
AUTHORS
ChangeLog
doc/source/api
glare-0.5.0/.gitreview 0000664 0000000 0000000 00000000112 13174010367 0014610 0 ustar 00root root 0000000 0000000 [gerrit]
host=review.openstack.org
port=29418
project=openstack/glare.git
glare-0.5.0/.testr.conf 0000664 0000000 0000000 00000000515 13174010367 0014677 0 ustar 00root root 0000000 0000000 [DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-160} \
${PYTHON:-python} -m subunit.run discover -t ./ ./glare/tests $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
glare-0.5.0/LICENSE 0000664 0000000 0000000 00000026135 13174010367 0013624 0 ustar 00root root 0000000 0000000 Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
glare-0.5.0/README.rst 0000664 0000000 0000000 00000001264 13174010367 0014302 0 ustar 00root root 0000000 0000000 Glare
=====
Glare (from GLare Artifact REpository) is a service that provides access to a
unified catalog of structured meta-information as well as related binary data
(these structures are also called 'artifacts').
* Get Started: https://github.com/openstack/glare/blob/master/doc/source/quickstart.rst
* Documentation: https://github.com/openstack/glare/blob/master/doc
* Source: https://git.openstack.org/cgit/openstack/glare
* Bugs: https://bugs.launchpad.net/glare
* Blueprints:** https://blueprints.launchpad.net/glare
* REST Client:** https://git.openstack.org/cgit/openstack/python-glareclient
License
-------
Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
glare-0.5.0/babel.cfg 0000664 0000000 0000000 00000000020 13174010367 0014326 0 ustar 00root root 0000000 0000000 [python: **.py]
glare-0.5.0/bandit.yaml 0000664 0000000 0000000 00000025533 13174010367 0014745 0 ustar 00root root 0000000 0000000 # optional: after how many files to update progress
#show_progress_every: 100
# optional: plugins directory name
#plugins_dir: 'plugins'
# optional: plugins discovery name pattern
plugin_name_pattern: '*.py'
# optional: terminal escape sequences to display colors
#output_colors:
# DEFAULT: '\033[0m'
# HEADER: '\033[95m'
# LOW: '\033[94m'
# MEDIUM: '\033[93m'
# HIGH: '\033[91m'
# optional: log format string
#log_format: "[%(module)s]\t%(levelname)s\t%(message)s"
# globs of files which should be analyzed
include:
- '*.py'
- '*.pyw'
# a list of strings, which if found in the path will cause files to be excluded
# for example /tests/ - to remove all all files in tests directory
exclude_dirs:
- '/tests/'
profiles:
gate:
include:
- any_other_function_with_shell_equals_true
- assert_used
- blacklist_calls
- blacklist_import_func
# One of the blacklisted imports is the subprocess module. Keystone
# has to import the subprocess module in a single module for
# eventlet support so in most cases bandit won't be able to detect
# that subprocess is even being imported. Also, Bandit's
# recommendation is just to check that the use is safe without any
# documentation on what safe or unsafe usage is. So this test is
# skipped.
# - blacklist_imports
- exec_used
- execute_with_run_as_root_equals_true
# - hardcoded_bind_all_interfaces # TODO: enable this test
# Not working because wordlist/default-passwords file not bundled,
# see https://bugs.launchpad.net/bandit/+bug/1451575 :
# - hardcoded_password
# Not used because it's prone to false positives:
# - hardcoded_sql_expressions
# - hardcoded_tmp_directory # TODO: enable this test
- jinja2_autoescape_false
- linux_commands_wildcard_injection
- paramiko_calls
- password_config_option_not_marked_secret
- request_with_no_cert_validation
- set_bad_file_permissions
- subprocess_popen_with_shell_equals_true
# - subprocess_without_shell_equals_true # TODO: enable this test
- start_process_with_a_shell
# - start_process_with_no_shell # TODO: enable this test
- start_process_with_partial_path
- ssl_with_bad_defaults
- ssl_with_bad_version
- ssl_with_no_version
# - try_except_pass # TODO: enable this test
- use_of_mako_templates
blacklist_calls:
bad_name_sets:
# - pickle:
# qualnames: [pickle.loads, pickle.load, pickle.Unpickler,
# cPickle.loads, cPickle.load, cPickle.Unpickler]
# message: "Pickle library appears to be in use, possible security issue."
# TODO: enable this test
- marshal:
qualnames: [marshal.load, marshal.loads]
message: "Deserialization with the marshal module is possibly dangerous."
# - md5:
# qualnames: [hashlib.md5, Crypto.Hash.MD2.new, Crypto.Hash.MD4.new, Crypto.Hash.MD5.new, cryptography.hazmat.primitives.hashes.MD5]
# message: "Use of insecure MD2, MD4, or MD5 hash function."
# TODO: enable this test
- mktemp_q:
qualnames: [tempfile.mktemp]
message: "Use of insecure and deprecated function (mktemp)."
- eval:
qualnames: [eval]
message: "Use of possibly insecure function - consider using safer ast.literal_eval."
- mark_safe:
names: [mark_safe]
message: "Use of mark_safe() may expose cross-site scripting vulnerabilities and should be reviewed."
- httpsconnection:
qualnames: [httplib.HTTPSConnection]
message: "Use of HTTPSConnection does not provide security, see https://wiki.openstack.org/wiki/OSSN/OSSN-0033"
- yaml_load:
qualnames: [yaml.load]
message: "Use of unsafe yaml load. Allows instantiation of arbitrary objects. Consider yaml.safe_load()."
- urllib_urlopen:
qualnames: [urllib.urlopen, urllib.urlretrieve, urllib.URLopener, urllib.FancyURLopener, urllib2.urlopen, urllib2.Request]
message: "Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected."
- random:
qualnames: [random.random, random.randrange, random.randint, random.choice, random.uniform, random.triangular]
message: "Standard pseudo-random generators are not suitable for security/cryptographic purposes."
level: "LOW"
# Most of this is based off of Christian Heimes' work on defusedxml:
# https://pypi.python.org/pypi/defusedxml/#defusedxml-sax
# TODO(jaegerandi): Enable once defusedxml is in global requirements.
#- xml_bad_cElementTree:
# qualnames: [xml.etree.cElementTree.parse,
# xml.etree.cElementTree.iterparse,
# xml.etree.cElementTree.fromstring,
# xml.etree.cElementTree.XMLParser]
# message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
#- xml_bad_ElementTree:
# qualnames: [xml.etree.ElementTree.parse,
# xml.etree.ElementTree.iterparse,
# xml.etree.ElementTree.fromstring,
# xml.etree.ElementTree.XMLParser]
# message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_expatreader:
qualnames: [xml.sax.expatreader.create_parser]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_expatbuilder:
qualnames: [xml.dom.expatbuilder.parse,
xml.dom.expatbuilder.parseString]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_sax:
qualnames: [xml.sax.parse,
xml.sax.parseString,
xml.sax.make_parser]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_minidom:
qualnames: [xml.dom.minidom.parse,
xml.dom.minidom.parseString]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_pulldom:
qualnames: [xml.dom.pulldom.parse,
xml.dom.pulldom.parseString]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
- xml_bad_etree:
qualnames: [lxml.etree.parse,
lxml.etree.fromstring,
lxml.etree.RestrictedElement,
lxml.etree.GlobalParserTLS,
lxml.etree.getDefaultParser,
lxml.etree.check_docinfo]
message: "Using {func} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {func} with it's defusedxml equivalent function."
shell_injection:
# Start a process using the subprocess module, or one of its wrappers.
subprocess: [subprocess.Popen, subprocess.call, subprocess.check_call,
subprocess.check_output, utils.execute, utils.execute_with_timeout]
# Start a process with a function vulnerable to shell injection.
shell: [os.system, os.popen, os.popen2, os.popen3, os.popen4,
popen2.popen2, popen2.popen3, popen2.popen4, popen2.Popen3,
popen2.Popen4, commands.getoutput, commands.getstatusoutput]
# Start a process with a function that is not vulnerable to shell injection.
no_shell: [os.execl, os.execle, os.execlp, os.execlpe, os.execv,os.execve,
os.execvp, os.execvpe, os.spawnl, os.spawnle, os.spawnlp,
os.spawnlpe, os.spawnv, os.spawnve, os.spawnvp, os.spawnvpe,
os.startfile]
blacklist_imports:
bad_import_sets:
- telnet:
imports: [telnetlib]
level: HIGH
message: "Telnet is considered insecure. Use SSH or some other encrypted protocol."
- info_libs:
imports: [pickle, cPickle, subprocess, Crypto]
level: LOW
message: "Consider possible security implications associated with {module} module."
# Most of this is based off of Christian Heimes' work on defusedxml:
# https://pypi.python.org/pypi/defusedxml/#defusedxml-sax
- xml_libs:
imports: [xml.etree.cElementTree,
xml.etree.ElementTree,
xml.sax.expatreader,
xml.sax,
xml.dom.expatbuilder,
xml.dom.minidom,
xml.dom.pulldom,
lxml.etree,
lxml]
message: "Using {module} to parse untrusted XML data is known to be vulnerable to XML attacks. Replace {module} with the equivalent defusedxml package."
level: LOW
- xml_libs_high:
imports: [xmlrpclib]
message: "Using {module} to parse untrusted XML data is known to be vulnerable to XML attacks. Use defused.xmlrpc.monkey_patch() function to monkey-patch xmlrpclib and mitigate XML vulnerabilities."
level: HIGH
hardcoded_tmp_directory:
tmp_dirs: ['/tmp', '/var/tmp', '/dev/shm']
hardcoded_password:
# Support for full path, relative path and special "%(site_data_dir)s"
# substitution (/usr/{local}/share)
word_list: "%(site_data_dir)s/wordlist/default-passwords"
ssl_with_bad_version:
bad_protocol_versions:
- 'PROTOCOL_SSLv2'
- 'SSLv2_METHOD'
- 'SSLv23_METHOD'
- 'PROTOCOL_SSLv3' # strict option
- 'PROTOCOL_TLSv1' # strict option
- 'SSLv3_METHOD' # strict option
- 'TLSv1_METHOD' # strict option
password_config_option_not_marked_secret:
function_names:
- oslo.config.cfg.StrOpt
- oslo_config.cfg.StrOpt
execute_with_run_as_root_equals_true:
function_names:
- ceilometer.utils.execute
- cinder.utils.execute
- neutron.agent.linux.utils.execute
- nova.utils.execute
- nova.utils.trycmd
try_except_pass:
check_typed_exception: True
glare-0.5.0/devstack/ 0000775 0000000 0000000 00000000000 13174010367 0014414 5 ustar 00root root 0000000 0000000 glare-0.5.0/devstack/README.rst 0000664 0000000 0000000 00000001033 13174010367 0016100 0 ustar 00root root 0000000 0000000 ====================
Enabling in Devstack
====================
1. Download DevStack::
git clone https://github.com/openstack-dev/devstack.git
cd devstack
2. Add this repo as an external repository::
> cat local.conf
[[local|localrc]]
enable_plugin glare https://github.com/openstack/glare
.. note::
To enable installation of glare client from git repo instead of pypi execute
a shell command:
.. code-block:: bash
export LIBS_FROM_GIT+=python-glareclient
3. run ``stack.sh``
glare-0.5.0/devstack/plugin.sh 0000664 0000000 0000000 00000015356 13174010367 0016260 0 ustar 00root root 0000000 0000000 #!/usr/bin/env bash
# Plugin file for Glare services
# -------------------------------
# Dependencies:
# ``functions`` file
# ``DEST``, ``DATA_DIR``, ``STACK_USER`` must be defined
# Save trace setting
XTRACE=$(set +o | grep xtrace)
set -o xtrace
echo_summary "glare's plugin.sh was called..."
# create_glare_accounts() - Set up common required glare accounts
#
# Tenant User Roles
# ------------------------------
# service glare admin
function create_glare_accounts() {
create_service_user "glare"
# required for swift access
if is_service_enabled s-proxy; then
create_service_user "glare-swift" "ResellerAdmin"
fi
get_or_create_service "glare" "artifact" "Artifact repository"
get_or_create_endpoint "artifact" \
"$REGION_NAME" \
"$GLARE_SERVICE_PROTOCOL://$GLARE_SERVICE_HOST:$GLARE_SERVICE_PORT" \
"$GLARE_SERVICE_PROTOCOL://$GLARE_SERVICE_HOST:$GLARE_SERVICE_PORT" \
"$GLARE_SERVICE_PROTOCOL://$GLARE_SERVICE_HOST:$GLARE_SERVICE_PORT"
}
function mkdir_chown_stack {
if [[ ! -d "$1" ]]; then
sudo mkdir -p "$1"
fi
sudo chown $STACK_USER "$1"
}
function configure_glare {
# create and clean up auth cache dir
mkdir_chown_stack "$GLARE_AUTH_CACHE_DIR"
rm -f "$GLARE_AUTH_CACHE_DIR"/*
mkdir_chown_stack "$GLARE_CONF_DIR"
# Generate Glare configuration file and configure common parameters.
oslo-config-generator --config-file $GLARE_DIR/etc/oslo-config-generator/glare.conf --output-file $GLARE_CONF_FILE
# Glare Configuration
#-------------------------
iniset $GLARE_CONF_FILE DEFAULT debug $GLARE_DEBUG
# Specify additional modules with external artifact types
if [ -n "$GLARE_CUSTOM_MODULES" ]; then
iniset $GLARE_CONF_FILE DEFAULT custom_artifact_types_modules $GLARE_CUSTOM_MODULES
fi
# Specify a list of enabled artifact types
if [ -n "$GLARE_ENABLED_TYPES" ]; then
iniset $GLARE_CONF_FILE DEFAULT enabled_artifact_types $GLARE_ENABLED_TYPES
fi
oslopolicy-sample-generator --namespace=glare --output-file=$GLARE_POLICY_FILE
sed -i 's/^#"//' $GLARE_POLICY_FILE
cp -p $GLARE_DIR/etc/glare-paste.ini $GLARE_CONF_DIR
iniset $GLARE_CONF_FILE paste_deploy flavor $GLARE_FLAVOR
# Setup keystone_authtoken section
configure_auth_token_middleware $GLARE_CONF_FILE glare $GLARE_AUTH_CACHE_DIR
# Setup RabbitMQ credentials
iniset $GLARE_CONF_FILE oslo_messaging_rabbit rabbit_userid $RABBIT_USERID
iniset $GLARE_CONF_FILE oslo_messaging_rabbit rabbit_password $RABBIT_PASSWORD
# Enable notifications support
iniset $GLARE_CONF_FILE oslo_messaging_notifications driver messaging
# Configure the database.
iniset $GLARE_CONF_FILE database connection `database_connection_url glare`
iniset $GLARE_CONF_FILE database max_overflow -1
iniset $GLARE_CONF_FILE database max_pool_size 1000
# Path of policy.yaml file.
iniset $GLARE_CONF_FILE oslo_policy policy_file $GLARE_POLICY_FILE
if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
setup_colorized_logging $GLARE_CONF_FILE DEFAULT tenant user
fi
if [ "$GLARE_RPC_IMPLEMENTATION" ]; then
iniset $GLARE_CONF_FILE DEFAULT rpc_implementation $GLARE_RPC_IMPLEMENTATION
fi
# Configuring storage
iniset $GLARE_CONF_FILE glance_store filesystem_store_datadir $GLARE_ARTIFACTS_DIR
# Store the artifacts in swift if enabled.
if is_service_enabled s-proxy; then
GLARE_SWIFT_STORE_CONF=$GLARE_CONF_DIR/glare-swift-store.conf
cp -p $GLARE_DIR/etc/glare-swift.conf.sample $GLARE_CONF_DIR
iniset $GLARE_CONF_FILE glance_store default_store swift
iniset $GLARE_CONF_FILE glance_store swift_store_create_container_on_put True
iniset $GLARE_CONF_FILE glance_store swift_store_config_file $GLARE_SWIFT_STORE_CONF
iniset $GLARE_CONF_FILE glance_store default_swift_reference ref1
iniset $GLARE_CONF_FILE glance_store stores "file, http, swift"
iniset $GLARE_SWIFT_STORE_CONF ref1 user $SERVICE_PROJECT_NAME:glare-swift
iniset $GLARE_SWIFT_STORE_CONF ref1 key $SERVICE_PASSWORD
iniset $GLARE_SWIFT_STORE_CONF ref1 auth_address $KEYSTONE_SERVICE_URI/v3
iniset $GLARE_SWIFT_STORE_CONF ref1 user_domain_name $SERVICE_DOMAIN_NAME
iniset $GLARE_SWIFT_STORE_CONF ref1 project_domain_name $SERVICE_DOMAIN_NAME
iniset $GLARE_SWIFT_STORE_CONF ref1 auth_version 3
# commenting is not strictly necessary but it's confusing to have bad values in conf
inicomment $GLARE_CONF_FILE glance_store swift_store_user
inicomment $GLARE_CONF_FILE glance_store swift_store_key
inicomment $GLARE_CONF_FILE glance_store swift_store_auth_address
fi
}
# init_glare - Initialize the database
function init_glare {
# Delete existing artifacts
rm -rf $GLARE_ARTIFACTS_DIR
mkdir -p $GLARE_ARTIFACTS_DIR
# (re)create Glare database
recreate_database glare utf8
# Migrate glare database
$GLARE_BIN_DIR/glare-db-manage --config-file $GLARE_CONF_FILE upgrade
}
# install_glare - Collect source and prepare
function install_glare {
setup_develop $GLARE_DIR
}
function install_glare_pythonclient {
if use_library_from_git "python-glareclient"; then
git_clone $GLARE_PYTHONCLIENT_REPO $GLARE_PYTHONCLIENT_DIR $GLARE_PYTHONCLIENT_BRANCH
setup_develop $GLARE_PYTHONCLIENT_DIR
else
# nothing actually "requires" glareclient, so force installation from pypi
pip_install_gr python-glareclient
fi
}
# start_glare - Start running processes, including screen
function start_glare {
run_process glare "$GLARE_BIN_DIR/glare-api --config-file $GLARE_CONF_DIR/glare.conf"
}
# stop_glare - Stop running processes
function stop_glare {
# Kill the Glare screen windows
for serv in glare-api; do
stop_process $serv
done
}
function cleanup_glare {
sudo rm -rf $GLARE_ARTIFACTS_DIR $GLARE_AUTH_CACHE_DIR
}
if is_service_enabled glare; then
if [[ "$1" == "stack" && "$2" == "install" ]]; then
echo_summary "Installing glare"
install_glare
install_glare_pythonclient
elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then
echo_summary "Configuring glare"
create_glare_accounts
configure_glare
elif [[ "$1" == "stack" && "$2" == "extra" ]]; then
echo_summary "Initializing glare"
init_glare
echo_summary "Starting Glare process"
start_glare
fi
if [[ "$1" == "unstack" ]]; then
echo_summary "Shutting down glare"
stop_glare
fi
if [[ "$1" == "clean" ]]; then
echo_summary "Cleaning glare"
cleanup_glare
fi
fi
# Restore xtrace
$XTRACE
# Local variables:
# mode: shell-script
# End:
glare-0.5.0/devstack/settings 0000664 0000000 0000000 00000002644 13174010367 0016205 0 ustar 00root root 0000000 0000000 # Devstack settings
enable_service glare
# Set up default directories
GLARE_PYTHONCLIENT_REPO=${GLARE_PYTHONCLIENT_REPO:-${GIT_BASE}/openstack/python-glareclient.git}
GLARE_PYTHONCLIENT_BRANCH=${GLARE_PYTHONCLIENT_BRANCH:-master}
GLARE_PYTHONCLIENT_DIR=$DEST/python-glareclient
GLARE_DIR=$DEST/glare
GLARE_REPO=${GLARE_REPO:-${GIT_BASE}/openstack/glare.git}
GLARE_BRANCH=${GLARE_BRANCH:-master}
# Glare virtual environment
if [[ ${USE_VENV} = True ]]; then
PROJECT_VENV["glare"]=${GLARE_DIR}.venv
GLARE_BIN_DIR=${PROJECT_VENV["glare"]}/bin
else
GLARE_BIN_DIR=$(get_python_exec_prefix)
fi
GLARE_ARTIFACTS_DIR=${GLARE_ARTIFACTS_DIR:=$DATA_DIR/glare/artifacts}
GLARE_AUTH_CACHE_DIR=${GLARE_AUTH_CACHE_DIR:-/var/cache/glare}
GLARE_CONF_DIR=${GLARE_CONF_DIR:-/etc/glare}
GLARE_CONF_FILE=$GLARE_CONF_DIR/glare.conf
GLARE_PASTE_INI=$GLARE_CONF_DIR/glare-paste.ini
GLARE_POLICY_FILE=$GLARE_CONF_DIR/policy.yaml
GLARE_SWIFT_STORE_CONF=$GLARE_CONF_DIR/glare-swift-store.conf
if is_ssl_enabled_service "glare" || is_service_enabled tls-proxy; then
GLARE_SERVICE_PROTOCOL="https"
fi
# Glare connection info. Note the port must be specified.
GLARE_SERVICE_PORT=${GLARE_SERVICE_PORT:-9494}
GLARE_SERVICE_HOST=${GLARE_SERVICE_HOST:-$SERVICE_HOST}
GLARE_SERVICE_PROTOCOL=${GLARE_SERVICE_PROTOCOL:-$SERVICE_PROTOCOL}
GLARE_DEBUG=${GLARE_DEBUG:-True}
GLARE_ADMIN_USER=${GLARE_ADMIN_USER:-glare}
GLARE_FLAVOR=${GLARE_FLAVOR:-keystone}
glare-0.5.0/doc/ 0000775 0000000 0000000 00000000000 13174010367 0013355 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/ 0000775 0000000 0000000 00000000000 13174010367 0014655 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/_static/ 0000775 0000000 0000000 00000000000 13174010367 0016303 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/_static/.placeholder 0000664 0000000 0000000 00000000000 13174010367 0020554 0 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/_templates/ 0000775 0000000 0000000 00000000000 13174010367 0017012 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/_templates/sidebarlinks.html 0000664 0000000 0000000 00000000455 13174010367 0022356 0 ustar 00root root 0000000 0000000
{% if READTHEDOCS %}
{% endif %}
glare-0.5.0/doc/source/_theme/ 0000775 0000000 0000000 00000000000 13174010367 0016116 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/_theme/layout.css 0000664 0000000 0000000 00000000206 13174010367 0020143 0 ustar 00root root 0000000 0000000 {% extends "basic/layout.html" %}
{% set css_files = css_files + ['_static/tweaks.css'] %}
{% block relbar1 %}{% endblock relbar1 %}
glare-0.5.0/doc/source/_theme/theme.conf 0000664 0000000 0000000 00000000110 13174010367 0020057 0 ustar 00root root 0000000 0000000 [theme]
inherit = nature
stylesheet = nature.css
pygments_style = tango
glare-0.5.0/doc/source/architecture.rst 0000664 0000000 0000000 00000011251 13174010367 0020071 0 ustar 00root root 0000000 0000000 ..
Copyright 2017 - Nokia Networks
All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may
not use this file except in compliance with the License. You may obtain
a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.
==================
Basic architecture
==================
OpenStack Glare has a client-server architecture that provides a Unified REST API,
which then transfers control to the appropriate artifact type. The API consists of
* *Router*, that converts WSGI requests into appropriate Glare API methods;
* *Deserializer*, that parses parameters from user input and performs initial
validation checks;
* *Controller*, which is responsible for interactions with Glare Engine;
* *Serializer*, that prepares information for responses (inserts status code,
content-type, response content length, and so on).
But before the requests reach the API they have to pass trough the set of
middlewares, and each performs some actions over Request or Response objects.
For example, *Auth* middleware checks that authentication token provided in request
header is valid by sending auth requests to Identity service, obtains user
information and injects it in Request object as a context objects;
*Fault middleware*, on the other hand, is responsible for converting inner
Glare exceptions to appropriate http error codes.
Almost all business logic is provided by Glare *Engine*. It is responsible
for *Policy* checking, when operator may define what operations users may execute,
based on their contexts; for sending broadcast *Notifications* about performed
actions; then it is *Access Control*, when Engine checks if user has rights to
modify desired artifact; and finally – *Locking*, that is used to prevent race
conditions during artifact updates, when the artifact is locked until the
modification operation is finished.
All the file (Blob data) operations are performed using
*glance_store* library, which is responsible for interaction with external
storage back ends and (or) local filesystem(s). The glance_store library
provides a uniform interface to access the backend stores. Also there is
an adapter layer *Store Manager* between Engine and glance_store that is
responsible for converting glance_store exceptions and adding some additional
logic, like sha256 calculation.
All database operations are organized with artifact types. Each type installed
in the system must implement Glare Artifact Type Interface (GATI) and use
appropriate data types to describe its attributes.
Glare uses several data types from a declarative framework *oslo.versionedobjects*:
Integer, Float, String, Boolean, which complemented with the following home-grown
data types:
* Version — specifies the version of the artifact in ‘SemVer’ format and
implements comparison operations.
* Dependency — sets a reference to another artifact. At the request of the
‘dependency’ field, Glare will get the dependent artifact meta-information.
* Blob — specifies a binary object. When a user assigns a value to this field,
data will be automatically redirected to one of the connected storages.
* List and Dict — define complex data structures such as Lists and Dictionaries
of primitive types respectively.
*Base artifact type* is an abstract class that has a reference implementation
of GATI. It contains only common fields, like "id", "name", "version",
"created_at”, "owner", and so on.
Each artifact type is inherited from the Base and adds some additional fields.
For example, for Image artifact type there were added "container_format" and
"disk_format" string fields, for Heat Template it was "nested_templates" Blob
Dictionary.
*Validators* are objects that can be attached to a filed to perform additional
checks. For example, if validator MinLen(1) is attached to a string field it
checks that the string value is non empty. Validator ForbiddenChars("/", ",")
validates that there shouldn't be slashes and commas in the string.
Glare uses a central *Database* that is shared amongst all
the components in the system and is sql-based by default. Other types
of database backends are somewhat supported and used by operators
but are not extensively tested upstream.
.. figure:: ./images/glare-architecture.png
:figwidth: 100%
:align: center
.. centered:: Image 1. OpenStack Glare Architecture
glare-0.5.0/doc/source/conf.py 0000664 0000000 0000000 00000020422 13174010367 0016154 0 ustar 00root root 0000000 0000000 # Copyright (c) 2010 OpenStack Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Glare documentation build configuration file, created by
# sphinx-quickstart on Tue May 18 13:50:15 2010.
#
# This file is execfile()'d with the current directory set to its containing
# dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import os
import subprocess
import sys
import warnings
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path = [
os.path.abspath('../..'),
os.path.abspath('../../bin')
] + sys.path
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.coverage',
'sphinx.ext.ifconfig',
'sphinx.ext.graphviz',
'oslosphinx',
'stevedore.sphinxext',
'oslo_config.sphinxext',
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'oslo_config.sphinxconfiggen',
]
config_generator_config_file = [
('../../etc/oslo-config-generator/glare.conf',
'_static/glare'),
]
# Add any paths that contain templates here, relative to this directory.
# templates_path = []
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Glare'
copyright = u'2016-present, OpenStack Foundation.'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
from glare.version import version_info as glare_version
# The full version, including alpha/beta/rc tags.
release = glare_version.version_string_with_vcs()
# The short X.Y version.
version = glare_version.canonical_version_string()
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
#exclude_trees = ['api']
exclude_patterns = [
# The man directory includes some snippet files that are included
# in other documents during the build but that should not be
# included in the toctree themselves, so tell Sphinx to ignore
# them when scanning for input files.
'man/footer.rst',
'man/general_options.rst',
'man/openstack_options.rst',
]
# The reST default role (for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
modindex_common_prefix = ['glare.']
# -- Options for man page output --------------------------------------------
# Grouping the document tree for man pages.
# List of tuples 'sourcefile', 'target', u'title', u'Authors name', 'manual'
man_pages = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
# html_theme_path = ["."]
# html_theme = '_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = ['_theme']
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
html_title = 'Glare'
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
git_cmd = ["git", "log", "--pretty=format:'%ad, commit %h'", "--date=local",
"-n1"]
try:
html_last_updated_fmt = subprocess.check_output(git_cmd).decode('utf-8')
except Exception:
warnings.warn('Cannot get last updated time from git repository. '
'Not setting "html_last_updated_fmt".')
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
html_use_modindex = True
# If false, no index is generated.
html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'glareedoc'
# -- Options for LaTeX output ------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author,
# documentclass [howto/manual]).
#latex_documents = [
# ('index', 'Glare.tex', u'Glare Documentation',
# u'Glare Team', 'manual'),
#]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
glare-0.5.0/doc/source/developer/ 0000775 0000000 0000000 00000000000 13174010367 0016642 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/developer/creating_custom_artifact_type.rst 0000664 0000000 0000000 00000012523 13174010367 0025503 0 ustar 00root root 0000000 0000000 How to create new Artifact Type
===============================
Basics
------
Each artifact type must realize **Glare Artifact Type Interface** (GATI)
and be inherited from ``glare.objects.base.BaseArtifact`` class.
GATI obliges to specify only one class method – ``get_type_name``
that returns a string with unique artifact type name. Other methods
and fields are optional.
.. note::
Conventionally it is recommended to give names in the plural, in
lowercase, with words separated by underscores.
Example of code for minimal artifact type:
.. code-block:: python
from glare.objects import base
class HelloWorld(base.BaseArtifact):
@classmethod
def get_type_name(cls):
return "hello_worlds"
Custom artifact fields
----------------------
Users can add type specific fields to their artifact type to extend
its logic and functionality. Follow the requirements of
oslo.versionedobjects library all new fields must be placed in class
dictionary attribute called ``fields``:
.. code-block:: python
from glare.objects import base
class HelloWorld(base.BaseArtifact):
...
fields = {...}
There is a large number of possible field options. Let’s look at the
most popular ones.
Fields of primitive types
^^^^^^^^^^^^^^^^^^^^^^^^^
Users are allowed to create additional fields of 5 primitive types:
* IntegerField
* FloatField
* FlexibleBooleanField
* StringField
* Link
First four are taken from oslo.versionedobjects directly, Link is a
glare-specific field which stores links in specific format to other
artifacts in the system.
.. note::
It’s recommended to use FlexibleBoolean field instead of just
Boolean, because it has more sophisticated coercing. For instance,
it accepts string parameters like “true”, “yes”, “1” and so on,
and successfully coerces it to boolean value True.
Users can create their own fields with method ``init`` from Attribute class.
This method’s first parameter must be an appropriate field class, other
parameters are optional and will be discussed later. In next example we
will create 5 new custom fields, one for each primitive type:
.. code-block:: python
from oslo_versionedobjects import fields
from glare.objects import base
from glare.objects.meta import wrappers
from glare.objects.meta import fields as glare_fields
Field = wrappers.Field.init
class HelloWorld(base.BaseArtifact):
@classmethod
def get_type_name(cls):
return "hello_worlds"
fields = {
'my_int': Field(fields.IntegerField),
'my_float': Field(fields.FloatField),
'my_bool': Field(fields.FlexibleBooleanField),
'my_string': Field(fields.StringField),
'my_link': Field(glare_fields.Link)
}
Compound types
^^^^^^^^^^^^^^
There are two collections, that may contain fields of primitive types:
*List* and *Dict*. Fields of compound types are created with method ``init``
of classes ListAttribute and DictAttribute respectively.
Unlike Attribute class’ ``init``, this method takes field type class as
a first parameter, but not just field class. So, *IntegerField* must be changed
to *Integer*, *FloatField* to *Float*, and so on. Finally for collection of
links user should use *LinkType*. Let’s add several new compound fields to
*HelloWorld* class.
.. code-block:: python
from oslo_versionedobjects import fields
from glare.objects import base
from glare.objects.meta import wrappers
from glare.objects.meta import fields as glare_fields
Field = wrappers.Field.init
Dict = wrappers.DictField.init
List = wrappers.ListField.init
class HelloWorld(base.BaseArtifact):
@classmethod
def get_type_name(cls):
return "hello_worlds"
fields = {
...
'my_list_of_str': List(fields.String),
'my_dict_of_int': Dict(fields.Integer),
'my_list_of_float': List(fields.Float),
'my_dict_of_bools': Dict(fields.FlexibleBoolean),
'my_list_of_links': List(glare_fields.LinkType)
}
Other parameters, like collection max size, possible item values,
and so on, also can be specified with additional parameters to ``init``
method. They will be discussed later.
Blob and Folder types
^^^^^^^^^^^^^^^^^^^^^
The most interesting fields in glare framework are *Blob* and
*Folder* (or *BlobDict*). These fields allow users to work binary data,
which is stored in a standalone cloud storage, like Swift or Ceph.
The difference between Blob and Folder is that Blob sets unique endpoint
and may contain only one binary object, on the other hand Folder may
contain lots of binaries with names specified by user.
Example of Blob and Folder fields:
.. code-block:: python
from oslo_versionedobjects import fields
from glare.objects import base
from glare.objects.meta import wrappers
from glare.objects.meta import fields as glare_fields
Field = wrappers.Field.init
Dict = wrappers.DictField.init
List = wrappers.ListField.init
Blob = wrappers.BlobField.init
Folder = wrappers.FolderField.init
class HelloWorld(base.BaseArtifact):
@classmethod
def get_type_name(cls):
return "hello_worlds"
fields = {
...
'my_blob': Blob(),
'my_folder': Folder(),
}
glare-0.5.0/doc/source/developer/devstack.rst 0000664 0000000 0000000 00000000074 13174010367 0021201 0 ustar 00root root 0000000 0000000 Glare Devstack Installation
===========================
TBD glare-0.5.0/doc/source/developer/index.rst 0000664 0000000 0000000 00000000233 13174010367 0020501 0 ustar 00root root 0000000 0000000 Developer's Reference
=====================
.. toctree::
:maxdepth: 3
webapi/index
creating_custom_artifact_type
devstack
troubleshooting
glare-0.5.0/doc/source/developer/troubleshooting.rst 0000664 0000000 0000000 00000000101 13174010367 0022613 0 ustar 00root root 0000000 0000000 Troubleshooting And Debugging
=============================
TBD
glare-0.5.0/doc/source/developer/webapi/ 0000775 0000000 0000000 00000000000 13174010367 0020111 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/developer/webapi/index.rst 0000664 0000000 0000000 00000000123 13174010367 0021746 0 ustar 00root root 0000000 0000000 REST API Specification
======================
.. toctree::
:maxdepth: 2
v1
glare-0.5.0/doc/source/developer/webapi/v1.rst 0000664 0000000 0000000 00000116626 13174010367 0021205 0 ustar 00root root 0000000 0000000 V1 API
======
This API describes the different ways of interacting with Glare service via HTTP protocol
using Representational State Transfer concept (ReST).
**Glossary**
* *Glare* (from GLare Artifact REpository) - a service that provides access
to a unified catalog of immutable objects with structured meta-information as
well as related binary data (these structures are also called *'artifacts'*).
Glare controls artifact consistency and guaranties that binary data and
fields won't change during artifact lifetime.
.. note::
Artifact type developer can declare fields whose values may be
changed, but he has to do it explicitly, because by default all fields
are considered as immutable.
* *Artifact* - in terms of Glare, an Artifact is a structured immutable object
with some fields, related binary data, and metadata.
* *Artifact Version* - field of an artifact that defines its version in SemVer
format.
* *Artifact type* - defines artifact structure of both its binary data and
fields. Examples of OpenStack artifact types that will be supported
in Glare are: Heat templates, Murano Packages, Nova Images, Tacker VNFs and
so on. All artifact types are inherited from abstract Base type and extended
with new fields. Base type is inherited from Base class
from oslo_versionedobjects library (oslo_vo).
* *Artifact status* - specifies the state of the artifact and the possible
actions that can be done with it. List of possible artifact statuses:
* *drafted* - Artifact is created but not activated, so it can be changed by
Artifact owner or Administrator.
* *active* - Artifact is activated and marked as ready for usage.
Only mutable fields can be changed since that.
* *deactivated* - Artifact is not available to other users except
administrators. Used when Cloud Admin need to check the artifact.
* *deleted* - Artifact's deleted.
.. list-table:: **Artifact status transition table**
:header-rows: 1
* - Artifacts Status
- drafted
- active
- deactivated
- deleted
* - **drafted**
- X
- activate Artifact
- N/A
- delete Artifact
* - **active**
- N/A
- X
- deactivate Artifact
- delete Artifact
* - **deactivated**
- N/A
- reactivate Artifact
- X
- delete Artifact
* - **deleted**
- N/A
- N/A
- N/A
- X
* *Artifact Field* - field of an artifact that defines some information
about the artifact. Artifact fields always have name, type, value and
several additional parameters, described below.
Glare uses several primitive types from oslo.versionedobjects directly:
* *String*;
* *Integer*;
* *Float*;
* *Boolean*;
And also Glare expands this list with custom types:
* *Blob*;
* *Link*;
* Structured generic types *Dict* or *List*.
Each field has additional properties:
* **required_on_activate** - boolean value indicating if the field value
should be specified for the artifact before activation. (Default: True)
* **mutable** - boolean value indicating if the field value may be changed
after the artifact is activated. (Default: False)
* **system** - boolean value indicating if the field value cannot be edited
by User. (Default: False)
* **sortable** - boolean value indicating if there is a possibility to sort by
this field's values. (Default: False)
.. note::
Only the fields of 4 primitive types may be sortable: integer, string, float
and boolean.
* **nullable** - boolean value indicating if field's value can be empty
(Default: True).
* **default** - a default value for the field may be specified by the Artifact
Type. (Default: None)
* **validators** - a list of objects. When a user sets a value to the field with
additional validators, Glare applies them before setting the value and
raises `ValueError` if at least one of the validator requirements is not
satisfied.
* **filter_ops** - a list of available filter operators for the field. There
are seven available operators: 'eq', 'neq', 'lt', 'lte', 'gt', 'gte', 'in'.
* *Artifact Link* - field type that defines soft dependency of the
Artifact from another Artifact. It is an url that allows user to obtain
some Artifact data. For external links the format is the following:
*http(s):///*
For internal links its value contains only .
Example of :
``/artifacts//``
* *Artifact Blob* - field type that defines binary data for Artifact.
User can download Artifact blob from Glare. Each blob field has a flag
*external*, that indicates if the field was created during file upload
(False) or by direct user request (True). In other words, “external” means
that blob field url is just a reference to some external file and Glare
does not manage the blob operations in that case.
Json schema that defines blob format:
.. code-block:: javascript
{
"type": "object",
"properties": {
"url": {"type": ["string", "null"], "format": "uri",
"maxLength": 2048},
"size": {"type": ["number", "null"]},
"md5": {"type": ["string", "null"]},
"sha1": {"type": ["string", "null"]},
"sha256": {"type": ["string", "null"]},
"external": {"type": "boolean"},
"id": {"type": "string"},
"status": {"type": "string",
"enum": ["saving", "active"]},
"content_type": {"type": ["string", "null"]},
},
"required": ["url", "size", "md5", "sha1", "sha256", "external",
"status", "id", "content_type"]
}
Artifact blob fields may have the following statuses:
* *saving* - Artifact blob record created in table, blob upload started.
* *active* - blob upload successfully finished.
.. list-table:: **Blob status transition table**
:header-rows: 1
* - Blob Status
- saving
- active
* - **saving**
- X
- finish blob upload
* - **active**
- N/A
- X
* *Artifact Dict and List* - compound generic field types that
implement Dict or List interfaces respectively, and contain values of some
primitive type, defined by `element_type` attribute.
* *Artifact visibility* - defines who may have an access to Artifact.
Initially there are 2 options:
* `private` artifact is accessible by its owner and
admin only. When artifact is 'drafted' its visibility is always `private`.
* `public`, when all users have an access to the artifact by default.
It's allowed to change visibility only when artifact has `active` status.
* *Artifact immutability* - when artifact is *drafted* all its fields
are editable, but when it becomes *active* it is "immutable" and cannot be modified
(except for those fields explicitly declared as `mutable`).
* *Base type json-schema*:
.. code-block:: javascript
{
"name": "Base artifact type",
"properties": {
"activated_at": {
"description": "Datetime when artifact has became active.",
"filter_ops": ["eq",
"neq",
"in",
"gt",
"gte",
"lt",
"lte"
],
"format": "date-time",
"glareType": "DateTime",
"readOnly": true,
"required_on_activate": false,
"sortable": true,
"type": ["string",
"null"
]
},
"created_at": {
"description": "Datetime when artifact has been created.",
"filter_ops": ["eq",
"neq",
"in",
"gt",
"gte",
"lt",
"lte"
],
"format": "date-time",
"glareType": "DateTime",
"readOnly": true,
"sortable": true,
"type": "string"
},
"description": {
"default": "",
"description": "Artifact description.",
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "String",
"maxLength": 4096,
"mutable": true,
"required_on_activate": false,
"type": ["string",
"null"
]
},
"id": {
"description": "Artifact UUID.",
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "String",
"maxLength": 255,
"pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$",
"readOnly": true,
"sortable": true,
"type": "string"
},
"metadata": {
"additionalProperties": {
"type": "string"
},
"default": {},
"description": "Key-value dict with useful information about an artifact.",
"filter_ops": ["eq",
"neq"
],
"glareType": "StringDict",
"maxProperties": 255,
"required_on_activate": false,
"type": ["object",
"null"
]
},
"name": {
"description": "Artifact Name.",
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "String",
"maxLength": 255,
"required_on_activate": false,
"sortable": true,
"type": "string"
},
"owner": {
"description": "ID of user/tenant who uploaded artifact.",
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "String",
"maxLength": 255,
"readOnly": true,
"required_on_activate": false,
"sortable": true,
"type": "string"
},
"status": {
"default": "drafted",
"description": "Artifact status.",
"enum": ["drafted",
"active",
"deactivated",
"deleted"
],
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "String",
"sortable": true,
"type": "string"
},
"tags": {
"default": [],
"description": "List of tags added to Artifact.",
"filter_ops": ["eq",
"neq",
"in"
],
"glareType": "StringList",
"items": {
"type": "string"
},
"maxItems": 255,
"mutable": true,
"required_on_activate": false,
"type": ["array",
"null"
]
},
"updated_at": {
"description": "Datetime when artifact has been updated last time.",
"filter_ops": ["eq",
"neq",
"in",
"gt",
"gte",
"lt",
"lte"
],
"format": "date-time",
"glareType": "DateTime",
"readOnly": true,
"sortable": true,
"type": "string"
},
"version": {
"default": "0.0.0",
"description": "Artifact version(semver).",
"filter_ops": ["eq",
"neq",
"in",
"gt",
"gte",
"lt",
"lte"
],
"glareType": "String",
"pattern": "/^([0-9]+)\\.([0-9]+)\\.([0-9]+)(?:-([0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*))?(?:\\+[0-9A-Za-z-]+)?$/",
"required_on_activate": false,
"sortable": true,
"type": "string"
},
"visibility": {
"default": "private",
"description": "Artifact visibility that defines if artifact can be available to other users.",
"filter_ops": ["eq"],
"glareType": "String",
"maxLength": 255,
"sortable": true,
"type": "string"
}
},
"required": ["name"],
"type": "object"
}
Basics
------
Glare API complies with OpenStack API-WG guidelines:
* `Filtering, sorting and pagination
`_
* `Errors
`_
For updating artifact field values, Glare API uses `json-patch
`_.
Glare supports microversions to define what API version it should use:
`API-WG microversion guidelines `_.
For description of artifact type `json-schema `_ is
used.
Media types
^^^^^^^^^^^
Currently this API relies on JSON to represent states of REST resources.
Error states
^^^^^^^^^^^^
The common HTTP Response Status Codes (https://github.com/for-GET/know-your-http-well/blob/master/status-codes.md) are used.
Application root [/]
^^^^^^^^^^^^^^^^^^^^
Application Root provides links to all possible API versions for Glare. URLs
for other resources described below are relative to Application Root.
API schemas root [/schemas/]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All the API urls are relative to schemas of artifact types.
* **List of enabled artifact type schemas**
* **GET /schemas** - JSON-schemas list of all enabled artifact types
* HTTP Responses:
* 200
* Response schema: JSON dictionary with elements :
* **Get artifact type schema**
* **GET /schemas/{artifact_type}** - get JSON-schema of artifact type `artifact_type`
* HTTP Responses:
* 200 if `artifact_type` is enabled
* 404 if no artifact type is defined to handle the specified value of `artifact_type`
* Response schema: JSON-schema for requested type
API artifacts root [/artifacts/]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All the API urls are relative to artifacts.
All the APIs which are specific to the particular artifact type are
placed to `/artifacts/{artifact_type}`, where `artifact_type` is a constant
defined by the artifact type definition (i.e. by the related oslo_vo class).
For example, for artifacts of type "images" the API endpoints will start
with `/artifacts/images`.
The `artifact_type` constant should unambiguously identify the
artifact type, so the values of this constants should be unique among all the
enabled artifact types.
* **List artifacts**
* **GET /artifacts/{artifact_type}** - list artifacts of given type
Returns the list of artifacts having the specified type and scoped
by the current tenant. If the user is ``administrator``, it
returns the artifacts owned by all the tenants.
* **GET /artifacts/all** - list artifacts regardless of their type
Returns the list of artifacts of all types for given tenant. Only
common fields will be shown in the output. All type-specific fields
are skipped.
* URL parameters:
* `artifact_type` identifier of the artifact type, should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* Query parameters:
Query may contain parameters intended for filtering and soring by most
of the common and type-specific artifact fields.
The set of parameters and their values should be compliant to the
schema defined by the artifact type and its version.
**Filtering**:
* Filter keys may be any common or type-specific fields of
primitive type, like 'String', 'Float', 'Integer' and 'Boolean'. Also
it is possible to filter artifacts by Dict keys and Dict or List
values.
Direct comparison requires a field name to be specified as query
parameter and the filtering value as its value, e.g. `?name=some_name`
Parameter names and values are case sensitive.
* Artifact API supports filtering operations in the format
`?name=:some_name`, where `op` is one of the following:
1. **eq**: equal;
2. **neq**: not equal;
3. **gt**: greater than;
4. **gte**: greater or equal than;
5. **lt**: lesser than;
6. **lte**: lesser or equal than;
7. **in**: in a list of.
Operator `eq` is default and may be omitted, i.e. filter
`=eq:` is equal to `=`
* Set comparison requires a field name to be specified as query
parameter. The parameter may be repeated several times, e.g. the query
`?name=qwerty&version=gt:1.0&version=lt:5.0` will filter the artifacts
having name `qwerty` and versions from 1.0 to 5.0 excluding.
* If it's required to filter the artifacts by any of the values, **in** operator
should be used. List of comma-separated values should be provided for
this operator. Query `?name=in:abc,def,ghi` will return all artifacts
with names `abc`, `def` and `ghi`.
* Filtering by Dict values is performed in format
`.=[:]`. This filter returns only
those artifacts, that have the key `key_name` in their Dict `dict_name`
and the `value` of the key satisfies the right part of the filter.
It is allowed to filter values for Dict of primitive types only.
* Dicts can be filtered by their keys in format
`dict_name`=[:]. Only `eq`, `neq`, `in` can be used
as filtering operators. For `eq`, it returns all artifacts, that have
key `value` in their Dict field `dict_name`; for `neq`, it returns all artifacts
that don't have that key in Dict `dict_name`; for `in`, it returns
artifacts with any of the keys in comma-separated list `value`.
* Filtering by List values may be performed in the same manner as by
Dict keys.
**Sorting**
In order to retrieve data in any sort order and direction, artifacts
REST API accepts multiple sort keys and directions.
Artifacts API will align with the `API Working group sorting guidelines
`_ and support the following parameter on
the request:
* sort: Comma-separated list of sort keys. Each key is optionally
appended with <:dir>, where 'dir' is the direction for the
corresponding sort key (supported values are 'asc' for ascending
and 'desc' for descending)
Sort keys may be any generic and type-specific metadata fields of
primitive type, like 'string', 'numeric', 'int' and 'bool'. But sorting
by type-specific fields is allowed only when artifact version
is provided.
Default value for sort direction is 'desc'. Default value for sort key
is 'created_at'.
**Pagination**
`limit` and `marker` query parameters may be used to paginate through
the artifacts collection in the same way as it is done in the current
version of Glance "List Images" API.
Maximum `limit` number is 1000. It is done for security reasons to protect
the system from intruders to prevent them from sending requests that can
pull the entire database at a time.
* HTTP Responses:
* 200 if `artifact_type` is enabled
* 400 if query has incorrect filter or sort parameters
* 404 if no artifact type is defined to handle the specified value of `artifact_type`
* Response schema:
.. code-block:: javascript
{
"": [],
"first": "/artifacts/",
"schema": "/schemas/",
"next": ""
}
* **Create a new artifact**
* **POST /artifacts/{artifact_type}**
* Creates a new artifact record in database. The status of artifact is set
to `drafted`. Request body may contain initial metadata of the artifact.
It's mandatory to define at least artifact `name` and `version` in the request
body.
* URL parameters:
* `artifact_type` identifier of the artifact type. It should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* HTTP Responses:
* 201 if everything went fine.
* 409 if an artifact of this type with the same name and version already
exists for tenant.
* 400 if incorrect initial values were provided in request body.
* 404 if no Artifact Type is defined to handle the specified value of `artifact_type`.
* Request content-type: `application/json`
* Response content-type: `application/json`
* Response schema: JSON with definition of created artifact
* **Get an artifact info**
* **GET /artifacts/{artifact_type}/{id}**
* Returns an artifact record with all the common and type-specific fields
* URL parameters:
* `artifact_type` identifier of the artifact type. It should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact.
* HTTP Responses:
* 200 if everything went fine.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from the type specified by `artifact_type`
parameter.
* Response content-type: `application/json`.
* Response body: JSON with artifact definition.
* **GET /artifacts/all/{id}**
* Returns an artifact record with common fields only, regardless of its type.
* URL parameters:
* `id` identifier of the artifact
* HTTP Responses:
* 200 if everything went fine
* 404 if no artifact with the given ID was found
* Response content-type: `application/json`
* Response schema: JSON with artifact definition
* **Update an Artifact**
* **PATCH /artifacts/{artifact_type}/{id}**
* Updates artifact's fields using json-patch notation. If the artifact
has a status other than `drafted` then only mutable fields may be updated.
* URL parameters:
* `artifact_type` identifier of the artifact type, should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact.
* HTTP Responses:
* 200 if everything went fine.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from type specified by
`artifact_type` parameter.
* 403 if the PATCH attempts to modify the immutable field while the
artifact's state is other than `drafted`.
* 400 if incorrect initial values were provided in request body.
* 409 if artifact with updated name and version already exists for the
tenant.
* Request content-type: `application/json-patch+json`
* Response content-type: `application/json`
* Response body: JSON definition of updated artifact
* **Delete an Artifact**
* **DELETE /artifacts/{artifact_type}/{id}**
* Deletes an artifact db record and all its binary data from store.
* URL parameters:
* `artifact_type` identifier of the artifact type. It should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact
* HTTP Responses:
* 204 if everything went fine.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from type specified by
`artifact_type` parameter.
* **Upload a blob**
* **PUT /artifacts/{artifact_type}/{id}/{blob_name}[/{key_name}]**
* Uploads binary data to a blob field.
* URL parameters:
* `artifact_type` identifier of the artifact type, should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact.
* `blob_name` name of blob field.
* optional: `key_name` name of a key if user uploads data in blob
dictionary.
* HTTP Responses:
* 200 if everything went fine.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from type specified by.
`artifact_type` parameter.
* 400 if `blob_name` field doesn't exist in `artifact_type` or it's not
a blob field.
* 409 if blob is already uploaded and has status `active`.
* 409 if blob has status `saving`.
* 413 if blob size exceeds the limit specified by artifact type.
* Request content-type: any, except
`application/vnd+openstack.glare-custom-location+json`.
* Response content-type: `application/json`.
* Response body: JSON definition of the artifact.
* **Download a blob**
* **GET /artifacts/{artifact_type}/{id}/{blob_name}[/{key_name}]**
* Downloads binary data from a blob field.
* URL parameters:
* `artifact_type` identifier of the artifact type, should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact.
* `blob_name` name of blob field.
* optional: `key_name` name of a key if user downloads data from blob
dictionary.
* HTTP Responses:
* 200 if everything went fine.
* 301 if blob has `external` location.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from type specified by
`artifact_type` parameter.
* 400 if `blob_name` field doesn't exist in `artifact_type` or it's not
a blob field.
* 403 if artifact has status `deactivated`.
* Response content-type: specified by `content-type` field from the blob
description.
* Response body: binary data of the blob.
* **Add location to a blob**
* **PUT /artifacts/{artifact_type}/{id}/{blob_name}[/{key_name}]**
* Adds external location to a blob field instead of upload data.
* URL parameters:
* `artifact_type` identifier of the artifact type, should be equal to a
valid constant defined in one of the enabled oslo_vo classes.
* `id` identifier of the artifact.
* `blob_name` name of blob field.
* optional: `key_name` name of a key if user inserts location in blob
dictionary.
* HTTP Responses:
* 200 if everything went fine.
* 404 if no artifact with the given ID was found.
* 404 if the type of the found artifact differs from type specified by
`artifact_type` parameter.
* 400 if `blob_name` field doesn't exist in `artifact_type` or it's not
a blob field.
* 409 if blob is already uploaded and has status `active`.
* 409 if blob has status `saving`.
* Request content-type: `application/vnd+openstack.glare-custom-location+json`.
* Response content-type: `application/json`.
* Response body: JSON definition of the artifact.
.. note::
Json-schema for `application/vnd+openstack.glare-external-location+json` and
`application/vnd+openstack.glare-internal-location+json`:
.. code-block:: javascript
{
"type": "object",
"properties": {
"url": {"type": ["string", "null"], "format": "uri",
"max_length": 255}
},
"required": ["url"]
}
A detailed example
^^^^^^^^^^^^^^^^^^
For this example, we have an artifact type 'example_type' with fields:
* id: StringField
* name: StringField
* visibility: StringField
* status: StringField
* blob_file: BlobField
* metadata: DictOfStringsField
* version: VersionField
.. note::
For output simplicity this artifact type doesn't contain all required
fields from Base artifact type.
1. Create artifact
Request:
* Method: POST
* URL: http://host:port/artifacts/example_type
* Body:
.. code-block:: javascript
{
"name": "new_art",
"version": "1.0"
}
Response:
201 Created
.. code-block:: javascript
{
"status": "drafted",
"name": "new_art",
"id": "art_id1",
"version": "1.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}
2. Get artifact
Request:
* Method: GET
* URL: http://host:port/artifacts/example_type/art_id1
Response:
200 OK
.. code-block:: javascript
{
"status": "drafted",
"name": "new_art",
"id": "art_id1",
"version": "1.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}
3. List artifacts
Request:
* Method: GET
* URL: http://host:port/artifacts/example_type
Response:
200 OK
.. code-block:: javascript
{
"example_type": [{
"status": "drafted",
"name": "new_art",
"id": "art_id1",
"version": "1.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}, {
"status": "drafted",
"name": "old_art",
"id": "art_id2",
"version": "0.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}, {
"status": "drafted",
"name": "old_art",
"id": "art_id3",
"version": "1.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}],
"first": "/artifacts/example_type",
"schema": "/schemas/example_type"
}
Request:
* Method: GET
* URL: http://host:port/artifacts/example_type?name=eq:old_art
Response:
200 OK
.. code-block:: javascript
{
"example_type": [{
"status": "drafted",
"name": "old_art",
"id": "art_id2",
"version": "0.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}, {
"status": "drafted",
"name": "old_art",
"id": "art_id3",
"version": "1.0.0",
"blob_file": null,
"metadata": {},
"visibility": "private"
}],
"first": "/artifacts/example_type?name=eq%3Aold_art",
"schema": "/schemas/example_type"
}
4. Update artifact
Request:
* Method: PATCH
* URL: http://host:port/artifacts/example_type/art_id1
* Body:
.. code-block:: javascript
[{
"op": "replace",
"path": "/name",
"value": "another_artifact"
}, {
"op": "add",
"path": "/metadata/item",
"value": "qwerty"
}]
Response:
200 OK
.. code-block:: javascript
{
"status": "drafted",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"blob_file": null,
"metadata": {
"item": "qwerty"
},
"visibility": "private"
}
5. Upload blob
Request:
* Method: PUT
* URL: http://host:port/artifacts/example_type/art_id1/blob_file
* Body: ``some binary data``
Response:
200 OK
.. code-block:: javascript
{
"status": "drafted",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"metadata": {
"item": "qwerty"
},
"blob_file": {
"status": "active",
"checksum": "8452e47f27b9618152a2b172357a547d",
"external": false,
"size": 594,
"content_type": "application/octet-stream",
"md5": "35d83e8eedfbdb87ff97d1f2761f8ebf",
"sha1": "942854360eeec1335537702399c5aed940401602",
"sha256": "d8a7834fc6652f316322d80196f6dcf294417030e37c15412e4deb7a67a367dd",
"url": "/artifacts//example_type/art_id1/blob_file"
},
"visibility": "private"
}
6. Download blob
Request:
* Method: GET
* URL: http://host:port/artifacts/example_type/art_id1/blob_file
Response:
200 OK
Body: ``blob binary data``
7. Activate artifact
Request:
* Method: PATCH
* URL: http://host:port/artifacts/example_type/art_id1
* Body:
.. code-block:: javascript
[{
"op": "replace",
"path": "/status",
"value": "active"
}]
Response:
200 OK
.. code-block:: javascript
{
"status": "active",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"metadata": {
"item": "qwerty"
},
"blob_file": {
"status": "active",
"checksum": "8452e47f27b9618152a2b172357a547d",
"external": false,
"size": 594,
"content_type": "application/octet-stream",
"md5": "35d83e8eedfbdb87ff97d1f2761f8ebf",
"sha1": "942854360eeec1335537702399c5aed940401602",
"sha256": "d8a7834fc6652f316322d80196f6dcf294417030e37c15412e4deb7a67a367dd",
"url": "/artifacts//example_type/art_id1/blob_file"
},
"visibility": "private"
}
8. Deactivate artifact
Request:
* Method: PATCH
* URL: http://host:port/artifacts/example_type/art_id1
* Body:
.. code-block:: javascript
[{
"op": "replace",
"path": "/status",
"value": "deactivated"
}]
Response:
200 OK
.. code-block:: javascript
{
"status": "deactivated",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"metadata": {
"item": "qwerty"
},
"blob_file": {
"status": "active",
"checksum": "8452e47f27b9618152a2b172357a547d",
"external": false,
"size": 594,
"content_type": "application/octet-stream",
"md5": "35d83e8eedfbdb87ff97d1f2761f8ebf",
"sha1": "942854360eeec1335537702399c5aed940401602",
"sha256": "d8a7834fc6652f316322d80196f6dcf294417030e37c15412e4deb7a67a367dd",
"url": "/artifacts//example_type/art_id1/blob_file"
},
"visibility": "private"
}
9. Reactivate artifact
Request:
* Method: PATCH
* URL: http://host:port/artifacts/example_type/art_id1
* Body:
.. code-block:: javascript
[{
"op": "replace",
"path": "/status",
"value": "active"
}]
Response:
200 OK
.. code-block:: javascript
{
"status": "active",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"metadata": {
"item": "qwerty"
},
"blob_file": {
"status": "active",
"checksum": "8452e47f27b9618152a2b172357a547d",
"external": false,
"size": 594,
"content_type": "application/octet-stream",
"md5": "35d83e8eedfbdb87ff97d1f2761f8ebf",
"sha1": "942854360eeec1335537702399c5aed940401602",
"sha256": "d8a7834fc6652f316322d80196f6dcf294417030e37c15412e4deb7a67a367dd",
"url": "/artifacts//example_type/art_id1/blob_file"
},
"visibility": "private"
}
10. Publish artifact
Request:
* Method: PATCH
* URL: http://host:port/artifacts/example_type/art_id1
* Body:
.. code-block:: javascript
[{
"op": "replace",
"path": "/visibility",
"value": "public"
}]
Response:
200 OK
.. code-block:: javascript
{
"status": "active",
"name": "another_artifact",
"id": "art_id1",
"version": "1.0.0",
"metadata": {
"item": "qwerty"
},
"blob_file": {
"status": "active",
"checksum": "8452e47f27b9618152a2b172357a547d",
"external": false,
"size": 594,
"content_type": "application/octet-stream",
"md5": "35d83e8eedfbdb87ff97d1f2761f8ebf",
"sha1": "942854360eeec1335537702399c5aed940401602",
"sha256": "d8a7834fc6652f316322d80196f6dcf294417030e37c15412e4deb7a67a367dd",
"url": "/artifacts//example_type/art_id1/blob_file"
},
"visibility": "public"
}
11. Delete artifact
Request:
* Method: DELETE
* URL: http://host:port/artifacts/example_type/art_id1
Response:
204 No Content
References
==========
#. `Filtering and sorting API-WG guideline `_
#. `Errors API-WG guideline `_
#. `json-patch description `_
#. `json-schema description `_
glare-0.5.0/doc/source/guides/ 0000775 0000000 0000000 00000000000 13174010367 0016135 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/guides/configuration_guide.rst 0000664 0000000 0000000 00000000071 13174010367 0022711 0 ustar 00root root 0000000 0000000 Glare Configuration Guide
=========================
TBD
glare-0.5.0/doc/source/guides/dashboard_guide.rst 0000664 0000000 0000000 00000000113 13174010367 0021766 0 ustar 00root root 0000000 0000000 Glare Dashboard Installation Guide
==================================
TBD
glare-0.5.0/doc/source/guides/glareclient_guide.rst 0000664 0000000 0000000 00000006001 13174010367 0022332 0 ustar 00root root 0000000 0000000 Glare Client Installation Guide
===============================
To install ``python-glareclient``, it is required to have ``pip``
(in most cases). Make sure that ``pip`` is installed. Then type::
$ pip install python-glareclient
Or, if it is needed to install ``python-glareclient`` from master branch,
type::
$ pip install git+https://github.com/openstack/python-glareclient.git
After ``python-glareclient`` is installed you will see command ``glare``
in your environment.
Glare client also provides a plugin ``openstack artifact`` to OpenStack client.
If glare client is supposed to be used with OpenStack cloud then additionally
``python-openstackclient`` has to be installed::
$ pip install python-openstackclient
Configure authentication against Keystone
-----------------------------------------
If Keystone is used for authentication in Glare, then the interraction has to
be organized with openstackclient plugin ``openstack artifact`` and the
environment should have auth variables::
$ export OS_AUTH_URL=http://:5000/v3
$ export OS_TENANT_NAME=tenant
$ export OS_USERNAME=admin
$ export OS_PASSWORD=secret
$ export OS_GLARE_URL=http://:9494 (optional, by default URL=http://localhost:9494/)
And in the case when you are authenticating against keystone over https::
$ export OS_CACERT=
.. note:: In client, we can use both Keystone auth versions - v2.0 and v3. But server supports only v3.
You can see the list of available commands by typing::
$ openstack artifact --help
To make sure Glare client works, type::
$ openstack artifact type-list
Configure authentication against Keycloak
-----------------------------------------
Glare also supports authentication against Keycloak server via OpenID Connect protocol.
In this case ``glare`` command must be used.
In order to use it on the client side the environment should look as follows::
$ export KEYCLOAK_AUTH_URL=https://:/auth
$ export KEYCLOAK_REALM_NAME=my_keycloak_realm
$ export KEYCLOAK_USERNAME=admin
$ export KEYCLOAK_PASSWORD=secret
$ export OPENID_CLIENT_ID=my_keycloak_client
$ export OS_GLARE_URL=http://:9494 (optional, by default URL=http://localhost:9494)
.. note:: If KEYCLOAK_AUTH_URL is set then authentication against KeyCloak will be used
You can see the list of available commands by typing::
$ glare --help
To make sure Glare client works, type::
$ glare type-list
Send tokens directly without authentication
-------------------------------------------
Glare has a possibility to send tokens directly.
In order to use it on the client side the environment should look as follows::
$ export OS_GLARE_URL=http://:9494 (optional, by default URL=http://localhost:9494)
$ export AUTH_TOKEN=secret_token
.. note:: It's more convenient to specify token as a command parameter in format ``--auth-token``,
for example, ``glare --auth-token secret_token type-list``
glare-0.5.0/doc/source/guides/hooks_guide.rst 0000664 0000000 0000000 00000000073 13174010367 0021167 0 ustar 00root root 0000000 0000000 Custom Actions Hooks Guide
==========================
TBD
glare-0.5.0/doc/source/guides/installation_guide.rst 0000664 0000000 0000000 00000000067 13174010367 0022550 0 ustar 00root root 0000000 0000000 Glare Installation Guide
========================
TBD
glare-0.5.0/doc/source/guides/upgrade_guide.rst 0000664 0000000 0000000 00000000120 13174010367 0021464 0 ustar 00root root 0000000 0000000 Glare Upgrade Guide
===================
Database Upgrade
----------------
TBD
glare-0.5.0/doc/source/images/ 0000775 0000000 0000000 00000000000 13174010367 0016122 5 ustar 00root root 0000000 0000000 glare-0.5.0/doc/source/images/glare-architecture.png 0000664 0000000 0000000 00000120421 13174010367 0022402 0 ustar 00root root 0000000 0000000 PNG
IHDR $ DF IDATxPU
EoѪŪFq5JP˕xMZUZIDb,QUhP ADF5hbib26f2yg0^{Կ m(. l l [ l [ [ l8###CKQQON:餓Nz`K}?x7n+}| ZG/-kMJJ CZZY__ hd<5O)u ͛7oܸf^UUUYYs7Hl 9ֺu
֭رciiisqi [l s5eʔ>}={VvÆ
blׯ.555ǎb!ߐ-@ _[nE˗oݺeS>ҒÇRWWwIY)++g3I>S{gj*Ǫd]A;
/^(+U
*r.R}'8WWl 9CILLt\m&V/)2~W.\('N6lبQDb>9*;W^'[/A!}嗥z:{ѣG%Ν+9}t)YN79:d :͛7aq1ZDbbb֬Ycx&6gff
KBNNNxx z3f0FFF_}QMtK.ׯ_cc^!3cs] _#$c#<8zMG-2!!$3bl>aaa)ݺu+--y>7o?~d҇ݷ냮\rȐ!xa=~[)$44Z4{xR NKK4:"%%%֎RSS3vX3fe#ye)G0C\C*++o644H~$ŋ%u}Z 0|D{Ѧl
2$55I|g+[ׯ/mmm<@JJB*L8Q8}oDLi9u0f `ժUƸ%Dz
?dKXn]έGRBl@DIζ̦lڜ-@ nܸ1vZZZonSDD>z=//ODͱlm9,,XիbBr3>}]M-33SFt\̓ʛ3f̠A-dkÆ
d۬ե9g- pׯ/]TBׯ7e;Jiii=2k,qDz%lڴIvRxllMJIIC_:d
wH+W:-aݺuRvze