Retire repo
This removes all content and updates the README with instructions on how to access the last version before retirement. Change-Id: I48b201ea662cd9527bc316b9ad5adc777309ebb1
This commit is contained in:
parent
8ca7ece349
commit
acd9d54547
|
@ -1,24 +0,0 @@
|
|||
*.pyc
|
||||
*.swp
|
||||
*.sqlite3
|
||||
.coverage*
|
||||
.noseids
|
||||
.DS_STORE
|
||||
*.egg/
|
||||
*.egg-info/
|
||||
coverage.xml
|
||||
nosetests.xml
|
||||
pep8.txt
|
||||
pylint.txt
|
||||
doc/build/
|
||||
.venv
|
||||
.tox
|
||||
build
|
||||
dist
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
tags
|
||||
.testrepository/
|
||||
*.lock
|
||||
subunit.log
|
||||
.DS_Store
|
|
@ -1,4 +0,0 @@
|
|||
[gerrit]
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/evoque.git
|
|
@ -1,8 +0,0 @@
|
|||
[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 ./ ./evoque/tests $LISTOPT $IDOPTION
|
||||
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
|
@ -1,16 +0,0 @@
|
|||
If you would like to contribute to the development of OpenStack,
|
||||
you must follow the steps in this page:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html
|
||||
|
||||
Once those steps have been completed, changes to OpenStack
|
||||
should be submitted for review via the Gerrit tool, following
|
||||
the workflow documented at:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
Bugs should be filed on Launchpad, not GitHub:
|
||||
|
||||
https://bugs.launchpad.net/evoque
|
|
@ -1,5 +0,0 @@
|
|||
Evoque Style Commandments
|
||||
=========================
|
||||
|
||||
- Step 1: Read the OpenStack Style Commandments
|
||||
http://docs.openstack.org/developer/hacking/
|
176
LICENSE
176
LICENSE
|
@ -1,176 +0,0 @@
|
|||
|
||||
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.
|
||||
|
30
README.rst
30
README.rst
|
@ -1,24 +1,10 @@
|
|||
OpenStack Evoque README
|
||||
=======================
|
||||
This project is no longer maintained.
|
||||
|
||||
OpenStack Evoque provides ticket service.
|
||||
The contents of this repository are still available in the Git
|
||||
source code management system. To see the contents of this
|
||||
repository before it reached its end of life, please check out the
|
||||
previous commit with "git checkout HEAD^1".
|
||||
|
||||
Wiki
|
||||
-----
|
||||
https://wiki.openstack.org/wiki/Evoque
|
||||
|
||||
Launchpad Projects
|
||||
------------------
|
||||
https://launchpad.net/evoque
|
||||
|
||||
Code Repository
|
||||
---------------
|
||||
https://github.com/openstack/evoque
|
||||
|
||||
Blueprints
|
||||
----------
|
||||
https://blueprints.launchpad.net/evoque
|
||||
|
||||
Bug Tracking
|
||||
------------
|
||||
https://bugs.launchpad.net/evoque
|
||||
For any further questions, please email
|
||||
openstack-dev@lists.openstack.org or join #openstack-dev on
|
||||
Freenode.
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
# -- 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.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'oslosphinx',
|
||||
]
|
||||
|
||||
# autodoc generation is a bit aggressive and a nuisance when doing heavy
|
||||
# text edit cycles.
|
||||
# execute "export SPHINX_DEBUG=1" in your terminal to disable
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'evoque'
|
||||
copyright = u'2015, OpenStack Foundation'
|
||||
|
||||
# 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
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# -- 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'
|
||||
# html_static_path = []
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = '%sdoc' % project
|
|
@ -1 +0,0 @@
|
|||
.. include:: ../../README.rst
|
|
@ -1,737 +0,0 @@
|
|||
[DEFAULT]
|
||||
|
||||
#
|
||||
# From evoque
|
||||
#
|
||||
|
||||
# The listen IP for the Evoque engine server. (string value)
|
||||
#host = jingliuqing-devstack.novalocal
|
||||
|
||||
# The Evoque workflow engine driver. (string value)
|
||||
#workflow_engine = spiff
|
||||
|
||||
#
|
||||
# From oslo.log
|
||||
#
|
||||
|
||||
# Print debugging output (set logging level to DEBUG instead of default INFO
|
||||
# level). (boolean value)
|
||||
#debug = false
|
||||
|
||||
# If set to false, will disable INFO logging level, making WARNING the default.
|
||||
# (boolean value)
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
#verbose = true
|
||||
|
||||
# The name of a logging configuration file. This file is appended to any
|
||||
# existing logging configuration files. For details about logging configuration
|
||||
# files, see the Python logging module documentation. Note that when logging
|
||||
# configuration files are used then all logging configuration is set in the
|
||||
# configuration file and other logging configuration options are ignored (for
|
||||
# example, log_format). (string value)
|
||||
# Deprecated group/name - [DEFAULT]/log_config
|
||||
#log_config_append = <None>
|
||||
|
||||
# DEPRECATED. A logging.Formatter log message format string which may use any
|
||||
# of the available logging.LogRecord attributes. This option is deprecated.
|
||||
# Please use logging_context_format_string and logging_default_format_string
|
||||
# instead. This option is ignored if log_config_append is set. (string value)
|
||||
#log_format = <None>
|
||||
|
||||
# Format string for %%(asctime)s in log records. Default: %(default)s . This
|
||||
# option is ignored if log_config_append is set. (string value)
|
||||
#log_date_format = %Y-%m-%d %H:%M:%S
|
||||
|
||||
# (Optional) Name of log file to output to. If no default is set, logging will
|
||||
# go to stdout. This option is ignored if log_config_append is set. (string
|
||||
# value)
|
||||
# Deprecated group/name - [DEFAULT]/logfile
|
||||
#log_file = <None>
|
||||
|
||||
# (Optional) The base directory used for relative --log-file paths. This option
|
||||
# is ignored if log_config_append is set. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/logdir
|
||||
#log_dir = <None>
|
||||
|
||||
# (Optional) Uses logging handler designed to watch file system. When log file
|
||||
# is moved or removed this handler will open a new log file with specified path
|
||||
# instantaneously. It makes sense only if log-file option is specified and
|
||||
# Linux platform is used. This option is ignored if log_config_append is set.
|
||||
# (boolean value)
|
||||
#watch_log_file = false
|
||||
|
||||
# Use syslog for logging. Existing syslog format is DEPRECATED and will be
|
||||
# changed later to honor RFC5424. This option is ignored if log_config_append
|
||||
# is set. (boolean value)
|
||||
#use_syslog = false
|
||||
|
||||
# (Optional) Enables or disables syslog rfc5424 format for logging. If enabled,
|
||||
# prefixes the MSG part of the syslog message with APP-NAME (RFC5424). The
|
||||
# format without the APP-NAME is deprecated in Kilo, and will be removed in
|
||||
# Mitaka, along with this option. This option is ignored if log_config_append
|
||||
# is set. (boolean value)
|
||||
# This option is deprecated for removal.
|
||||
# Its value may be silently ignored in the future.
|
||||
#use_syslog_rfc_format = true
|
||||
|
||||
# Syslog facility to receive log lines. This option is ignored if
|
||||
# log_config_append is set. (string value)
|
||||
#syslog_log_facility = LOG_USER
|
||||
|
||||
# Log output to standard error. This option is ignored if log_config_append is
|
||||
# set. (boolean value)
|
||||
#use_stderr = true
|
||||
|
||||
# Format string to use for log messages with context. (string value)
|
||||
#logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s
|
||||
|
||||
# Format string to use for log messages without context. (string value)
|
||||
#logging_default_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
|
||||
|
||||
# Data to append to log format when level is DEBUG. (string value)
|
||||
#logging_debug_format_suffix = %(funcName)s %(pathname)s:%(lineno)d
|
||||
|
||||
# Prefix each line of exception output with this format. (string value)
|
||||
#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d ERROR %(name)s %(instance)s
|
||||
|
||||
# List of logger=LEVEL pairs. This option is ignored if log_config_append is
|
||||
# set. (list value)
|
||||
#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN,taskflow=WARN
|
||||
|
||||
# Enables or disables publication of error events. (boolean value)
|
||||
#publish_errors = false
|
||||
|
||||
# The format for an instance that is passed with the log message. (string
|
||||
# value)
|
||||
#instance_format = "[instance: %(uuid)s] "
|
||||
|
||||
# The format for an instance UUID that is passed with the log message. (string
|
||||
# value)
|
||||
#instance_uuid_format = "[instance: %(uuid)s] "
|
||||
|
||||
# Format string for user_identity field of the logging_context_format_string
|
||||
# (string value)
|
||||
#logging_user_identity_format = %(user)s %(tenant)s %(domain)s %(user_domain)s %(project_domain)s
|
||||
|
||||
# Enables or disables fatal status of deprecations. (boolean value)
|
||||
#fatal_deprecations = false
|
||||
|
||||
#
|
||||
# From oslo.messaging
|
||||
#
|
||||
|
||||
# Size of RPC connection pool. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/rpc_conn_pool_size
|
||||
#rpc_conn_pool_size = 30
|
||||
|
||||
# ZeroMQ bind address. Should be a wildcard (*), an ethernet interface, or IP.
|
||||
# The "host" option should point or resolve to this address. (string value)
|
||||
#rpc_zmq_bind_address = *
|
||||
|
||||
# MatchMaker driver. (string value)
|
||||
#rpc_zmq_matchmaker = redis
|
||||
|
||||
# Use REQ/REP pattern for all methods CALL/CAST/FANOUT. (boolean value)
|
||||
#rpc_zmq_all_req_rep = true
|
||||
|
||||
# Type of concurrency used. Either "native" or "eventlet" (string value)
|
||||
#rpc_zmq_concurrency = eventlet
|
||||
|
||||
# Number of ZeroMQ contexts, defaults to 1. (integer value)
|
||||
#rpc_zmq_contexts = 1
|
||||
|
||||
# Maximum number of ingress messages to locally buffer per topic. Default is
|
||||
# unlimited. (integer value)
|
||||
#rpc_zmq_topic_backlog = <None>
|
||||
|
||||
# Directory for holding IPC sockets. (string value)
|
||||
#rpc_zmq_ipc_dir = /var/run/openstack
|
||||
|
||||
# Name of this node. Must be a valid hostname, FQDN, or IP address. Must match
|
||||
# "host" option, if running Nova. (string value)
|
||||
#rpc_zmq_host = localhost
|
||||
|
||||
# Seconds to wait before a cast expires (TTL). Only supported by impl_zmq.
|
||||
# (integer value)
|
||||
#rpc_cast_timeout = 30
|
||||
|
||||
# The default number of seconds that poll should wait. Poll raises timeout
|
||||
# exception when timeout expired. (integer value)
|
||||
#rpc_poll_timeout = 1
|
||||
|
||||
# Configures zmq-messaging to use broker or not. (boolean value)
|
||||
#zmq_use_broker = false
|
||||
|
||||
# Minimal port number for random ports range. (port value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65535
|
||||
#rpc_zmq_min_port = 49152
|
||||
|
||||
# Maximal port number for random ports range. (integer value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65536
|
||||
#rpc_zmq_max_port = 65536
|
||||
|
||||
# Number of retries to find free port number before fail with ZMQBindError.
|
||||
# (integer value)
|
||||
#rpc_zmq_bind_port_retries = 100
|
||||
|
||||
# Host to locate redis. (string value)
|
||||
#host = 127.0.0.1
|
||||
|
||||
# Use this port to connect to redis host. (port value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65535
|
||||
#port = 6379
|
||||
|
||||
# Password for Redis server (optional). (string value)
|
||||
#password =
|
||||
|
||||
# Size of executor thread pool. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/rpc_thread_pool_size
|
||||
#executor_thread_pool_size = 64
|
||||
|
||||
# The Drivers(s) to handle sending notifications. Possible values are
|
||||
# messaging, messagingv2, routing, log, test, noop (multi valued)
|
||||
# Deprecated group/name - [DEFAULT]/notification_driver
|
||||
#driver =
|
||||
|
||||
# A URL representing the messaging driver to use for notifications. If not set,
|
||||
# we fall back to the same configuration used for RPC. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/notification_transport_url
|
||||
#transport_url = <None>
|
||||
|
||||
# AMQP topic used for OpenStack notifications. (list value)
|
||||
# Deprecated group/name - [rpc_notifier2]/topics
|
||||
# Deprecated group/name - [DEFAULT]/notification_topics
|
||||
#topics = notifications
|
||||
|
||||
# Seconds to wait for a response from a call. (integer value)
|
||||
#rpc_response_timeout = 60
|
||||
|
||||
# A URL representing the messaging driver to use and its full configuration. If
|
||||
# not set, we fall back to the rpc_backend option and driver specific
|
||||
# configuration. (string value)
|
||||
#transport_url = <None>
|
||||
|
||||
# The messaging driver to use, defaults to rabbit. Other drivers include amqp
|
||||
# and zmq. (string value)
|
||||
#rpc_backend = rabbit
|
||||
|
||||
# The default exchange under which topics are scoped. May be overridden by an
|
||||
# exchange name specified in the transport_url option. (string value)
|
||||
#control_exchange = openstack
|
||||
|
||||
|
||||
[api]
|
||||
|
||||
#
|
||||
# From evoque
|
||||
#
|
||||
|
||||
# The port for the Evoque API server. (port value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65535
|
||||
#port = 8888
|
||||
|
||||
# The listen IP for the Evoque API server. (string value)
|
||||
#host = 0.0.0.0
|
||||
|
||||
# Toggle Pecan Debug Middleware. (boolean value)
|
||||
#pecan_debug = false
|
||||
|
||||
# Number of workers for Evoque API server. (integer value)
|
||||
#workers = 4
|
||||
|
||||
# The maximum number of items returned in a single response from a collection
|
||||
# resource (integer value)
|
||||
#max_limit = 1000
|
||||
|
||||
# This option enables or disables user authentication via Keystone. Default
|
||||
# value is True. (boolean value)
|
||||
#enable_authentication = true
|
||||
|
||||
|
||||
[database]
|
||||
|
||||
#
|
||||
# From oslo.db
|
||||
#
|
||||
|
||||
# The file name to use with SQLite. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/sqlite_db
|
||||
#sqlite_db = oslo.sqlite
|
||||
|
||||
# If True, SQLite uses synchronous mode. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/sqlite_synchronous
|
||||
#sqlite_synchronous = true
|
||||
|
||||
# The back end to use for the database. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/db_backend
|
||||
#backend = sqlalchemy
|
||||
|
||||
# The SQLAlchemy connection string to use to connect to the database. (string
|
||||
# value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_connection
|
||||
# Deprecated group/name - [DATABASE]/sql_connection
|
||||
# Deprecated group/name - [sql]/connection
|
||||
#connection = <None>
|
||||
|
||||
# The SQLAlchemy connection string to use to connect to the slave database.
|
||||
# (string value)
|
||||
#slave_connection = <None>
|
||||
|
||||
# The SQL mode to be used for MySQL sessions. This option, including the
|
||||
# default, overrides any server-set SQL mode. To use whatever SQL mode is set
|
||||
# by the server configuration, set this to no value. Example: mysql_sql_mode=
|
||||
# (string value)
|
||||
#mysql_sql_mode = TRADITIONAL
|
||||
|
||||
# Timeout before idle SQL connections are reaped. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_idle_timeout
|
||||
# Deprecated group/name - [DATABASE]/sql_idle_timeout
|
||||
# Deprecated group/name - [sql]/idle_timeout
|
||||
#idle_timeout = 3600
|
||||
|
||||
# Minimum number of SQL connections to keep open in a pool. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_min_pool_size
|
||||
# Deprecated group/name - [DATABASE]/sql_min_pool_size
|
||||
#min_pool_size = 1
|
||||
|
||||
# Maximum number of SQL connections to keep open in a pool. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_max_pool_size
|
||||
# Deprecated group/name - [DATABASE]/sql_max_pool_size
|
||||
#max_pool_size = <None>
|
||||
|
||||
# Maximum number of database connection retries during startup. Set to -1 to
|
||||
# specify an infinite retry count. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_max_retries
|
||||
# Deprecated group/name - [DATABASE]/sql_max_retries
|
||||
#max_retries = 10
|
||||
|
||||
# Interval between retries of opening a SQL connection. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_retry_interval
|
||||
# Deprecated group/name - [DATABASE]/reconnect_interval
|
||||
#retry_interval = 10
|
||||
|
||||
# If set, use this value for max_overflow with SQLAlchemy. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_max_overflow
|
||||
# Deprecated group/name - [DATABASE]/sqlalchemy_max_overflow
|
||||
#max_overflow = <None>
|
||||
|
||||
# Verbosity of SQL debugging information: 0=None, 100=Everything. (integer
|
||||
# value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_connection_debug
|
||||
#connection_debug = 0
|
||||
|
||||
# Add Python stack traces to SQL as comment strings. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/sql_connection_trace
|
||||
#connection_trace = false
|
||||
|
||||
# If set, use this value for pool_timeout with SQLAlchemy. (integer value)
|
||||
# Deprecated group/name - [DATABASE]/sqlalchemy_pool_timeout
|
||||
#pool_timeout = <None>
|
||||
|
||||
# Enable the experimental use of database reconnect on connection lost.
|
||||
# (boolean value)
|
||||
#use_db_reconnect = false
|
||||
|
||||
# Seconds between retries of a database transaction. (integer value)
|
||||
#db_retry_interval = 1
|
||||
|
||||
# If True, increases the interval between retries of a database operation up to
|
||||
# db_max_retry_interval. (boolean value)
|
||||
#db_inc_retry_interval = true
|
||||
|
||||
# If db_inc_retry_interval is set, the maximum seconds between retries of a
|
||||
# database operation. (integer value)
|
||||
#db_max_retry_interval = 10
|
||||
|
||||
# Maximum retries in case of connection error or deadlock error before error is
|
||||
# raised. Set to -1 to specify an infinite retry count. (integer value)
|
||||
#db_max_retries = 20
|
||||
|
||||
|
||||
[keystone_authtoken]
|
||||
|
||||
#
|
||||
# From keystonemiddleware.auth_token
|
||||
#
|
||||
|
||||
# Complete public Identity API endpoint. (string value)
|
||||
#auth_uri = <None>
|
||||
|
||||
# API version of the admin Identity API endpoint. (string value)
|
||||
#auth_version = <None>
|
||||
|
||||
# Do not handle authorization requests within the middleware, but delegate the
|
||||
# authorization decision to downstream WSGI components. (boolean value)
|
||||
#delay_auth_decision = false
|
||||
|
||||
# Request timeout value for communicating with Identity API server. (integer
|
||||
# value)
|
||||
#http_connect_timeout = <None>
|
||||
|
||||
# How many times are we trying to reconnect when communicating with Identity
|
||||
# API Server. (integer value)
|
||||
#http_request_max_retries = 3
|
||||
|
||||
# Env key for the swift cache. (string value)
|
||||
#cache = <None>
|
||||
|
||||
# Required if identity server requires client certificate (string value)
|
||||
#certfile = <None>
|
||||
|
||||
# Required if identity server requires client certificate (string value)
|
||||
#keyfile = <None>
|
||||
|
||||
# A PEM encoded Certificate Authority to use when verifying HTTPs connections.
|
||||
# Defaults to system CAs. (string value)
|
||||
#cafile = <None>
|
||||
|
||||
# Verify HTTPS connections. (boolean value)
|
||||
#insecure = false
|
||||
|
||||
# The region in which the identity server can be found. (string value)
|
||||
#region_name = <None>
|
||||
|
||||
# Directory used to cache files related to PKI tokens. (string value)
|
||||
#signing_dir = <None>
|
||||
|
||||
# Optionally specify a list of memcached server(s) to use for caching. If left
|
||||
# undefined, tokens will instead be cached in-process. (list value)
|
||||
# Deprecated group/name - [DEFAULT]/memcache_servers
|
||||
#memcached_servers = <None>
|
||||
|
||||
# In order to prevent excessive effort spent validating tokens, the middleware
|
||||
# caches previously-seen tokens for a configurable duration (in seconds). Set
|
||||
# to -1 to disable caching completely. (integer value)
|
||||
#token_cache_time = 300
|
||||
|
||||
# Determines the frequency at which the list of revoked tokens is retrieved
|
||||
# from the Identity service (in seconds). A high number of revocation events
|
||||
# combined with a low cache duration may significantly reduce performance.
|
||||
# (integer value)
|
||||
#revocation_cache_time = 10
|
||||
|
||||
# (Optional) If defined, indicate whether token data should be authenticated or
|
||||
# authenticated and encrypted. Acceptable values are MAC or ENCRYPT. If MAC,
|
||||
# token data is authenticated (with HMAC) in the cache. If ENCRYPT, token data
|
||||
# is encrypted and authenticated in the cache. If the value is not one of these
|
||||
# options or empty, auth_token will raise an exception on initialization.
|
||||
# (string value)
|
||||
#memcache_security_strategy = <None>
|
||||
|
||||
# (Optional, mandatory if memcache_security_strategy is defined) This string is
|
||||
# used for key derivation. (string value)
|
||||
#memcache_secret_key = <None>
|
||||
|
||||
# (Optional) Number of seconds memcached server is considered dead before it is
|
||||
# tried again. (integer value)
|
||||
#memcache_pool_dead_retry = 300
|
||||
|
||||
# (Optional) Maximum total number of open connections to every memcached
|
||||
# server. (integer value)
|
||||
#memcache_pool_maxsize = 10
|
||||
|
||||
# (Optional) Socket timeout in seconds for communicating with a memcached
|
||||
# server. (integer value)
|
||||
#memcache_pool_socket_timeout = 3
|
||||
|
||||
# (Optional) Number of seconds a connection to memcached is held unused in the
|
||||
# pool before it is closed. (integer value)
|
||||
#memcache_pool_unused_timeout = 60
|
||||
|
||||
# (Optional) Number of seconds that an operation will wait to get a memcached
|
||||
# client connection from the pool. (integer value)
|
||||
#memcache_pool_conn_get_timeout = 10
|
||||
|
||||
# (Optional) Use the advanced (eventlet safe) memcached client pool. The
|
||||
# advanced pool will only work under python 2.x. (boolean value)
|
||||
#memcache_use_advanced_pool = false
|
||||
|
||||
# (Optional) Indicate whether to set the X-Service-Catalog header. If False,
|
||||
# middleware will not ask for service catalog on token validation and will not
|
||||
# set the X-Service-Catalog header. (boolean value)
|
||||
#include_service_catalog = true
|
||||
|
||||
# Used to control the use and type of token binding. Can be set to: "disabled"
|
||||
# to not check token binding. "permissive" (default) to validate binding
|
||||
# information if the bind type is of a form known to the server and ignore it
|
||||
# if not. "strict" like "permissive" but if the bind type is unknown the token
|
||||
# will be rejected. "required" any form of token binding is needed to be
|
||||
# allowed. Finally the name of a binding method that must be present in tokens.
|
||||
# (string value)
|
||||
#enforce_token_bind = permissive
|
||||
|
||||
# If true, the revocation list will be checked for cached tokens. This requires
|
||||
# that PKI tokens are configured on the identity server. (boolean value)
|
||||
#check_revocations_for_cached = false
|
||||
|
||||
# Hash algorithms to use for hashing PKI tokens. This may be a single algorithm
|
||||
# or multiple. The algorithms are those supported by Python standard
|
||||
# hashlib.new(). The hashes will be tried in the order given, so put the
|
||||
# preferred one first for performance. The result of the first hash will be
|
||||
# stored in the cache. This will typically be set to multiple values only while
|
||||
# migrating from a less secure algorithm to a more secure one. Once all the old
|
||||
# tokens are expired this option should be set to a single value for better
|
||||
# performance. (list value)
|
||||
#hash_algorithms = md5
|
||||
|
||||
# Prefix to prepend at the beginning of the path. Deprecated, use identity_uri.
|
||||
# (string value)
|
||||
#auth_admin_prefix =
|
||||
|
||||
# Host providing the admin Identity API endpoint. Deprecated, use identity_uri.
|
||||
# (string value)
|
||||
#auth_host = 127.0.0.1
|
||||
|
||||
# Port of the admin Identity API endpoint. Deprecated, use identity_uri.
|
||||
# (integer value)
|
||||
#auth_port = 35357
|
||||
|
||||
# Protocol of the admin Identity API endpoint (http or https). Deprecated, use
|
||||
# identity_uri. (string value)
|
||||
#auth_protocol = https
|
||||
|
||||
# Complete admin Identity API endpoint. This should specify the unversioned
|
||||
# root endpoint e.g. https://localhost:35357/ (string value)
|
||||
#identity_uri = <None>
|
||||
|
||||
# This option is deprecated and may be removed in a future release. Single
|
||||
# shared secret with the Keystone configuration used for bootstrapping a
|
||||
# Keystone installation, or otherwise bypassing the normal authentication
|
||||
# process. This option should not be used, use `admin_user` and
|
||||
# `admin_password` instead. (string value)
|
||||
#admin_token = <None>
|
||||
|
||||
# Service username. (string value)
|
||||
#admin_user = <None>
|
||||
|
||||
# Service user password. (string value)
|
||||
#admin_password = <None>
|
||||
|
||||
# Service tenant name. (string value)
|
||||
#admin_tenant_name = admin
|
||||
|
||||
# Authentication type to load (unknown value)
|
||||
# Deprecated group/name - [DEFAULT]/auth_plugin
|
||||
#auth_type = <None>
|
||||
|
||||
# Config Section from which to load plugin specific options (unknown value)
|
||||
#auth_section = <None>
|
||||
|
||||
|
||||
[matchmaker_redis]
|
||||
|
||||
#
|
||||
# From oslo.messaging
|
||||
#
|
||||
|
||||
# Host to locate redis. (string value)
|
||||
#host = 127.0.0.1
|
||||
|
||||
# Use this port to connect to redis host. (port value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65535
|
||||
#port = 6379
|
||||
|
||||
# Password for Redis server (optional). (string value)
|
||||
#password =
|
||||
|
||||
|
||||
[oslo_messaging_amqp]
|
||||
|
||||
#
|
||||
# From oslo.messaging
|
||||
#
|
||||
|
||||
# address prefix used when sending to a specific server (string value)
|
||||
# Deprecated group/name - [amqp1]/server_request_prefix
|
||||
#server_request_prefix = exclusive
|
||||
|
||||
# address prefix used when broadcasting to all servers (string value)
|
||||
# Deprecated group/name - [amqp1]/broadcast_prefix
|
||||
#broadcast_prefix = broadcast
|
||||
|
||||
# address prefix when sending to any server in group (string value)
|
||||
# Deprecated group/name - [amqp1]/group_request_prefix
|
||||
#group_request_prefix = unicast
|
||||
|
||||
# Name for the AMQP container (string value)
|
||||
# Deprecated group/name - [amqp1]/container_name
|
||||
#container_name = <None>
|
||||
|
||||
# Timeout for inactive connections (in seconds) (integer value)
|
||||
# Deprecated group/name - [amqp1]/idle_timeout
|
||||
#idle_timeout = 0
|
||||
|
||||
# Debug: dump AMQP frames to stdout (boolean value)
|
||||
# Deprecated group/name - [amqp1]/trace
|
||||
#trace = false
|
||||
|
||||
# CA certificate PEM file to verify server certificate (string value)
|
||||
# Deprecated group/name - [amqp1]/ssl_ca_file
|
||||
#ssl_ca_file =
|
||||
|
||||
# Identifying certificate PEM file to present to clients (string value)
|
||||
# Deprecated group/name - [amqp1]/ssl_cert_file
|
||||
#ssl_cert_file =
|
||||
|
||||
# Private key PEM file used to sign cert_file certificate (string value)
|
||||
# Deprecated group/name - [amqp1]/ssl_key_file
|
||||
#ssl_key_file =
|
||||
|
||||
# Password for decrypting ssl_key_file (if encrypted) (string value)
|
||||
# Deprecated group/name - [amqp1]/ssl_key_password
|
||||
#ssl_key_password = <None>
|
||||
|
||||
# Accept clients using either SSL or plain TCP (boolean value)
|
||||
# Deprecated group/name - [amqp1]/allow_insecure_clients
|
||||
#allow_insecure_clients = false
|
||||
|
||||
# Space separated list of acceptable SASL mechanisms (string value)
|
||||
# Deprecated group/name - [amqp1]/sasl_mechanisms
|
||||
#sasl_mechanisms =
|
||||
|
||||
# Path to directory that contains the SASL configuration (string value)
|
||||
# Deprecated group/name - [amqp1]/sasl_config_dir
|
||||
#sasl_config_dir =
|
||||
|
||||
# Name of configuration file (without .conf suffix) (string value)
|
||||
# Deprecated group/name - [amqp1]/sasl_config_name
|
||||
#sasl_config_name =
|
||||
|
||||
# User name for message broker authentication (string value)
|
||||
# Deprecated group/name - [amqp1]/username
|
||||
#username =
|
||||
|
||||
# Password for message broker authentication (string value)
|
||||
# Deprecated group/name - [amqp1]/password
|
||||
#password =
|
||||
|
||||
|
||||
[oslo_messaging_rabbit]
|
||||
|
||||
#
|
||||
# From oslo.messaging
|
||||
#
|
||||
|
||||
# Use durable queues in AMQP. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/amqp_durable_queues
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_durable_queues
|
||||
#amqp_durable_queues = false
|
||||
|
||||
# Auto-delete queues in AMQP. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/amqp_auto_delete
|
||||
#amqp_auto_delete = false
|
||||
|
||||
# Send a single AMQP reply to call message. The current behaviour since oslo-
|
||||
# incubator is to send two AMQP replies - first one with the payload, a second
|
||||
# one to ensure the other have finish to send the payload. We are going to
|
||||
# remove it in the N release, but we must keep backward compatible at the same
|
||||
# time. This option provides such compatibility - it defaults to False in
|
||||
# Liberty and can be turned on for early adopters with a new installations or
|
||||
# for testing. Please note, that this option will be removed in the Mitaka
|
||||
# release. (boolean value)
|
||||
#send_single_reply = false
|
||||
|
||||
# SSL version to use (valid only if SSL enabled). Valid values are TLSv1 and
|
||||
# SSLv23. SSLv2, SSLv3, TLSv1_1, and TLSv1_2 may be available on some
|
||||
# distributions. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_ssl_version
|
||||
#kombu_ssl_version =
|
||||
|
||||
# SSL key file (valid only if SSL enabled). (string value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_ssl_keyfile
|
||||
#kombu_ssl_keyfile =
|
||||
|
||||
# SSL cert file (valid only if SSL enabled). (string value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_ssl_certfile
|
||||
#kombu_ssl_certfile =
|
||||
|
||||
# SSL certification authority file (valid only if SSL enabled). (string value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_ssl_ca_certs
|
||||
#kombu_ssl_ca_certs =
|
||||
|
||||
# How long to wait before reconnecting in response to an AMQP consumer cancel
|
||||
# notification. (floating point value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_reconnect_delay
|
||||
#kombu_reconnect_delay = 1.0
|
||||
|
||||
# How long to wait a missing client beforce abandoning to send it its replies.
|
||||
# This value should not be longer than rpc_response_timeout. (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/kombu_reconnect_timeout
|
||||
#kombu_missing_consumer_retry_timeout = 5
|
||||
|
||||
# Determines how the next RabbitMQ node is chosen in case the one we are
|
||||
# currently connected to becomes unavailable. Takes effect only if more than
|
||||
# one RabbitMQ node is provided in config. (string value)
|
||||
# Allowed values: round-robin, shuffle
|
||||
#kombu_failover_strategy = round-robin
|
||||
|
||||
# The RabbitMQ broker address where a single node is used. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_host
|
||||
#rabbit_host = localhost
|
||||
|
||||
# The RabbitMQ broker port where a single node is used. (port value)
|
||||
# Minimum value: 1
|
||||
# Maximum value: 65535
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_port
|
||||
#rabbit_port = 5672
|
||||
|
||||
# RabbitMQ HA cluster host:port pairs. (list value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_hosts
|
||||
#rabbit_hosts = $rabbit_host:$rabbit_port
|
||||
|
||||
# Connect over SSL for RabbitMQ. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_use_ssl
|
||||
#rabbit_use_ssl = false
|
||||
|
||||
# The RabbitMQ userid. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_userid
|
||||
#rabbit_userid = guest
|
||||
|
||||
# The RabbitMQ password. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_password
|
||||
#rabbit_password = guest
|
||||
|
||||
# The RabbitMQ login method. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_login_method
|
||||
#rabbit_login_method = AMQPLAIN
|
||||
|
||||
# The RabbitMQ virtual host. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_virtual_host
|
||||
#rabbit_virtual_host = /
|
||||
|
||||
# How frequently to retry connecting with RabbitMQ. (integer value)
|
||||
#rabbit_retry_interval = 1
|
||||
|
||||
# How long to backoff for between retries when connecting to RabbitMQ. (integer
|
||||
# value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_retry_backoff
|
||||
#rabbit_retry_backoff = 2
|
||||
|
||||
# Maximum number of RabbitMQ connection retries. Default is 0 (infinite retry
|
||||
# count). (integer value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_max_retries
|
||||
#rabbit_max_retries = 0
|
||||
|
||||
# Use HA queues in RabbitMQ (x-ha-policy: all). If you change this option, you
|
||||
# must wipe the RabbitMQ database. (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/rabbit_ha_queues
|
||||
#rabbit_ha_queues = false
|
||||
|
||||
# Number of seconds after which the Rabbit broker is considered down if
|
||||
# heartbeat's keep-alive fails (0 disable the heartbeat). EXPERIMENTAL (integer
|
||||
# value)
|
||||
#heartbeat_timeout_threshold = 60
|
||||
|
||||
# How often times during the heartbeat_timeout_threshold we check the
|
||||
# heartbeat. (integer value)
|
||||
#heartbeat_rate = 2
|
||||
|
||||
# Deprecated, use rpc_backend=kombu+memory or rpc_backend=fake (boolean value)
|
||||
# Deprecated group/name - [DEFAULT]/fake_rabbit
|
||||
#fake_rabbit = false
|
|
@ -1,8 +0,0 @@
|
|||
[DEFAULT]
|
||||
output_file = etc/evoque/evoque.conf.sample
|
||||
wrap_width = 79
|
||||
namespace = evoque
|
||||
namespace = oslo.db
|
||||
namespace = oslo.log
|
||||
namespace = oslo.messaging
|
||||
namespace = keystonemiddleware.auth_token
|
|
@ -1,47 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import pecan
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from evoque.api import auth
|
||||
from evoque.api import config as api_config
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def get_pecan_config():
|
||||
# Set up the pecan configuration
|
||||
filename = api_config.__file__.replace('.pyc', '.py')
|
||||
return pecan.configuration.conf_from_file(filename)
|
||||
|
||||
|
||||
def setup_app(config=None):
|
||||
if not config:
|
||||
config = get_pecan_config()
|
||||
|
||||
app_conf = dict(config.app)
|
||||
|
||||
app = pecan.make_app(
|
||||
app_conf.pop('root'),
|
||||
logging=getattr(config, 'logging', {}),
|
||||
**app_conf
|
||||
)
|
||||
|
||||
# TODO(liuqing): Add oslo.middleware cors
|
||||
# http://docs.openstack.org/developer/oslo.middleware/cors.html
|
||||
|
||||
# Keystone auth middleware
|
||||
app = auth.install(app, CONF, config.app.acl_public_routes)
|
||||
|
||||
return app
|
|
@ -1,35 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Access Control Lists (ACL's) control access the API server."""
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from evoque.api.middleware import auth_token
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
def install(app, conf, public_routes):
|
||||
"""Install ACL check on application.
|
||||
:param app: A WSGI application.
|
||||
:param conf: Settings. Dict'ified and passed to keystone middleware
|
||||
:param public_routes: The list of the routes which will be allowed to
|
||||
access without authentication.
|
||||
:return: The same WSGI application with ACL installed.
|
||||
"""
|
||||
if not cfg.CONF.api.get('enable_authentication'):
|
||||
return app
|
||||
return auth_token.AuthTokenMiddleware(app,
|
||||
conf=dict(conf),
|
||||
public_api_routes=public_routes)
|
|
@ -1,34 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.api import hooks
|
||||
|
||||
# Pecan Application Configurations
|
||||
app = {
|
||||
'root': 'evoque.api.controllers.root.RootController',
|
||||
'modules': ['evoque.api'],
|
||||
'debug': False,
|
||||
'hooks': [
|
||||
hooks.ContextHook(),
|
||||
hooks.RPCHook(),
|
||||
],
|
||||
'acl_public_routes': [
|
||||
'/'
|
||||
],
|
||||
}
|
||||
|
||||
# Custom Configurations must be in Python dictionary format::
|
||||
#
|
||||
# foo = {'bar':'baz'}
|
||||
#
|
||||
# All configurations are accessible at::
|
||||
# pecan.conf
|
|
@ -1,34 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import pecan
|
||||
|
||||
from evoque.api.controllers import v1
|
||||
|
||||
|
||||
class RootController(object):
|
||||
v1 = v1.Controller()
|
||||
|
||||
@staticmethod
|
||||
@pecan.expose('json')
|
||||
def index():
|
||||
return {
|
||||
"versions": [{
|
||||
"status": "CURRENT",
|
||||
"links": [{
|
||||
"rel": "self",
|
||||
"href": pecan.request.application_url + "/v1/"
|
||||
}],
|
||||
"id": "v1.0",
|
||||
"updated": "2015-03-19"
|
||||
}]
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import pecan
|
||||
|
||||
from evoque.api.controllers.v1 import ticket
|
||||
from evoque.api.controllers.v1 import workflow
|
||||
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self):
|
||||
self.sub_controllers = {
|
||||
"ticket": ticket.Controller(),
|
||||
"workflow": workflow.Controller(),
|
||||
}
|
||||
|
||||
for name, ctrl in self.sub_controllers.items():
|
||||
setattr(self, name, ctrl)
|
||||
|
||||
@pecan.expose('json')
|
||||
def index(self):
|
||||
return {
|
||||
"version": "1.0",
|
||||
"links": [
|
||||
{"rel": "self",
|
||||
"href": pecan.request.application_url + "/v1"}
|
||||
] + [
|
||||
{"rel": name,
|
||||
"href": pecan.request.application_url + "/v1/" + name}
|
||||
for name in sorted(self.sub_controllers)
|
||||
]
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
|
||||
|
||||
class Controller(rest.RestController):
|
||||
|
||||
@pecan.expose('json')
|
||||
def get(self):
|
||||
return {"version": "1.0.0"}
|
||||
|
||||
@pecan.expose('json')
|
||||
def post(self, **kwargs):
|
||||
ticket = pecan.request.ticket_api.ticket_create(
|
||||
name=kwargs['name'])
|
||||
|
||||
return ticket
|
||||
|
||||
@pecan.expose('json')
|
||||
def get_all(self):
|
||||
tickets = pecan.request.ticket_api.ticket_list()
|
||||
|
||||
return tickets
|
|
@ -1,34 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import pecan
|
||||
from pecan import rest
|
||||
|
||||
|
||||
class Controller(rest.RestController):
|
||||
|
||||
@pecan.expose('json')
|
||||
def get(self):
|
||||
return {"version": "1.0.0"}
|
||||
|
||||
@pecan.expose('json')
|
||||
def post(self, **kwargs):
|
||||
workflow = pecan.request.workflow_api.workflow_create(
|
||||
name=kwargs['name'], wf_spec=kwargs['wf_spec'])
|
||||
|
||||
return workflow
|
||||
|
||||
@pecan.expose('json')
|
||||
def get_all(self):
|
||||
workflows = pecan.request.workflow_api.workflow_list()
|
||||
|
||||
return workflows
|
|
@ -1,84 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from pecan import hooks
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from evoque.common import context
|
||||
from evoque.engine.ticket import api as ticket_api
|
||||
from evoque.engine.workflow import api as workflow_api
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.import_opt('auth_uri', 'keystonemiddleware.auth_token',
|
||||
group='keystone_authtoken')
|
||||
|
||||
|
||||
class ContextHook(hooks.PecanHook):
|
||||
"""Configures a request context and attaches it to the request.
|
||||
|
||||
The following HTTP request headers are used:
|
||||
|
||||
X-User-Name:
|
||||
Used for context.user_name.
|
||||
|
||||
X-User-Id:
|
||||
Used for context.user_id.
|
||||
|
||||
X-Project-Name:
|
||||
Used for context.project.
|
||||
|
||||
X-Project-Id:
|
||||
Used for context.project_id.
|
||||
|
||||
X-Auth-Token:
|
||||
Used for context.auth_token.
|
||||
|
||||
X-Roles:
|
||||
Used for context.roles.
|
||||
"""
|
||||
|
||||
def before(self, state):
|
||||
headers = state.request.headers
|
||||
user_name = headers.get('X-User-Name')
|
||||
user_id = headers.get('X-User-Id')
|
||||
project = headers.get('X-Project-Name')
|
||||
project_id = headers.get('X-Project-Id')
|
||||
domain_id = headers.get('X-User-Domain-Id')
|
||||
domain_name = headers.get('X-User-Domain-Name')
|
||||
auth_token = headers.get('X-Auth-Token')
|
||||
roles = headers.get('X-Roles', '').split(',')
|
||||
auth_token_info = state.request.environ.get('keystone.token_info')
|
||||
|
||||
auth_url = CONF.keystone_authtoken.auth_uri
|
||||
|
||||
state.request.context = context.make_context(
|
||||
auth_token=auth_token,
|
||||
auth_url=auth_url,
|
||||
auth_token_info=auth_token_info,
|
||||
user_name=user_name,
|
||||
user_id=user_id,
|
||||
project_name=project,
|
||||
project_id=project_id,
|
||||
domain_id=domain_id,
|
||||
domain_name=domain_name,
|
||||
roles=roles)
|
||||
|
||||
|
||||
class RPCHook(hooks.PecanHook):
|
||||
"""Attach the rpcapi object to the request so controllers can get to it."""
|
||||
|
||||
def before(self, state):
|
||||
state.request.ticket_api = ticket_api.API(
|
||||
context=state.request.context)
|
||||
state.request.workflow_api = workflow_api.API(
|
||||
context=state.request.context)
|
|
@ -1,60 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import re
|
||||
|
||||
from keystonemiddleware import auth_token
|
||||
from oslo_log import log
|
||||
|
||||
from evoque.common import exceptions
|
||||
from evoque.common.i18n import _
|
||||
from evoque.common import utils
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class AuthTokenMiddleware(auth_token.AuthProtocol):
|
||||
"""A wrapper on Keystone auth_token middleware.
|
||||
|
||||
Does not perform verification of authentication tokens
|
||||
for public routes in the API.
|
||||
|
||||
"""
|
||||
def __init__(self, app, conf, public_api_routes=None):
|
||||
if public_api_routes is None:
|
||||
public_api_routes = []
|
||||
route_pattern_tpl = '%s\.json?$'
|
||||
|
||||
try:
|
||||
self.public_api_routes = [re.compile(route_pattern_tpl % route_tpl)
|
||||
for route_tpl in public_api_routes]
|
||||
except re.error as e:
|
||||
msg = _('Cannot compile public API routes: %s') % e
|
||||
|
||||
LOG.error(msg)
|
||||
raise exceptions.ConfigInvalid(error_msg=msg)
|
||||
|
||||
super(AuthTokenMiddleware, self).__init__(app, conf)
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
path = utils.safe_rstrip(env.get('PATH_INFO'), '/')
|
||||
|
||||
# The information whether the API call is being performed against the
|
||||
# public API is required for some other components. Saving it to the
|
||||
# WSGI environment is reasonable thereby.
|
||||
env['is_public_api'] = any(map(lambda pattern: re.match(pattern, path),
|
||||
self.public_api_routes))
|
||||
|
||||
if env['is_public_api']:
|
||||
return self._app(env, start_response)
|
||||
|
||||
return super(AuthTokenMiddleware, self).__call__(env, start_response)
|
|
@ -1,50 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Evoque API service."""
|
||||
|
||||
import os
|
||||
from werkzeug import serving
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from evoque.api import app as api_app
|
||||
from evoque.common.i18n import _LI
|
||||
from evoque.common import service
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class WerkzeugApp(object):
|
||||
# NOTE(lawrancejing): The purpose of this class is only to be used
|
||||
# with werkzeug to create the wsgi app
|
||||
|
||||
def __init__(self, conf):
|
||||
self.app = None
|
||||
self.conf = conf
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
if self.app is None:
|
||||
self.app = api_app.setup_app()
|
||||
return self.app(environ, start_response)
|
||||
|
||||
|
||||
def main():
|
||||
service.prepare_service()
|
||||
|
||||
LOG.info(_LI('Starting evoque api in PID %s') % os.getpid())
|
||||
|
||||
serving.run_simple(cfg.CONF.api.host, cfg.CONF.api.port,
|
||||
WerkzeugApp(cfg.CONF),
|
||||
processes=cfg.CONF.api.workers)
|
|
@ -1,47 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Evoque engine service."""
|
||||
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_service import service
|
||||
|
||||
from evoque.common.i18n import _LI
|
||||
from evoque.common import rpc_service
|
||||
from evoque.common import service as evoque_service
|
||||
from evoque.engine.ticket import endpoint as ticket_endpoint
|
||||
from evoque.engine.workflow import endpoint as workflow_endpoint
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
evoque_service.prepare_service()
|
||||
|
||||
LOG.info(_LI('Starting evoque engine in PID %s') % os.getpid())
|
||||
|
||||
conductor_id = str(uuid.uuid4())
|
||||
|
||||
endpoints = [
|
||||
ticket_endpoint.Handler(),
|
||||
workflow_endpoint.Handler(),
|
||||
]
|
||||
|
||||
server = rpc_service.Service.create("evoque-engine",
|
||||
conductor_id, endpoints,
|
||||
binary='evoque-engine')
|
||||
launcher = service.launch(cfg.CONF, server)
|
||||
launcher.wait()
|
|
@ -1,82 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Evoque Management Utility
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from evoque.db import api
|
||||
from evoque import version
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
# If ../evoque/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(possible_topdir, 'evoque', '__init__.py')):
|
||||
sys.path.insert(0, possible_topdir)
|
||||
|
||||
|
||||
def do_db_version():
|
||||
'''Print database's current migration level.'''
|
||||
print(api.db_version(api.get_engine()))
|
||||
|
||||
|
||||
def do_db_sync():
|
||||
'''Place a database under migration control and upgrade.
|
||||
|
||||
DB is created first if necessary.
|
||||
'''
|
||||
api.db_sync(api.get_engine(), CONF.command.version)
|
||||
|
||||
|
||||
def add_command_parsers(subparsers):
|
||||
parser = subparsers.add_parser('db_version')
|
||||
parser.set_defaults(func=do_db_version)
|
||||
|
||||
parser = subparsers.add_parser('db_sync')
|
||||
parser.set_defaults(func=do_db_sync)
|
||||
parser.add_argument('version', nargs='?')
|
||||
parser.add_argument('current_version', nargs='?')
|
||||
|
||||
|
||||
command_opt = cfg.SubCommandOpt('command',
|
||||
title='Commands',
|
||||
help='Show available commands.',
|
||||
handler=add_command_parsers)
|
||||
|
||||
|
||||
def main():
|
||||
logging.register_options(CONF)
|
||||
logging.setup(CONF, 'evoque-manage')
|
||||
CONF.register_cli_opt(command_opt)
|
||||
|
||||
try:
|
||||
default_config_files = cfg.find_config_files('evoque', 'evoque-manage')
|
||||
CONF(sys.argv[1:], project='evoque', prog='evoque-manage',
|
||||
version=version.version_info.version_string(),
|
||||
default_config_files=default_config_files)
|
||||
except RuntimeError as e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
try:
|
||||
CONF.command.func()
|
||||
except Exception as e:
|
||||
sys.exit("ERROR: %s" % e)
|
|
@ -1,77 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from oslo_context import context
|
||||
|
||||
|
||||
class RequestContext(context.RequestContext):
|
||||
"""Extends security contexts from the OpenStack common library."""
|
||||
|
||||
def __init__(self, auth_token=None, auth_url=None, domain_id=None,
|
||||
domain_name=None, user_name=None, user_id=None,
|
||||
project_name=None, project_id=None, roles=None,
|
||||
is_admin=False, read_only=False, show_deleted=False,
|
||||
request_id=None, trust_id=None, auth_token_info=None,
|
||||
all_tenants=False, **kwargs):
|
||||
"""Stores several additional request parameters:
|
||||
|
||||
:param domain_id: The ID of the domain.
|
||||
:param domain_name: The name of the domain.
|
||||
|
||||
"""
|
||||
self.user_name = user_name
|
||||
self.user_id = user_id
|
||||
self.project_name = project_name
|
||||
self.project_id = project_id
|
||||
self.domain_id = domain_id
|
||||
self.domain_name = domain_name
|
||||
self.roles = roles
|
||||
self.auth_url = auth_url
|
||||
self.auth_token_info = auth_token_info
|
||||
self.trust_id = trust_id
|
||||
self.all_tenants = all_tenants
|
||||
|
||||
super(RequestContext, self).__init__(auth_token=auth_token,
|
||||
user=user_name,
|
||||
tenant=project_name,
|
||||
is_admin=is_admin,
|
||||
read_only=read_only,
|
||||
show_deleted=show_deleted,
|
||||
request_id=request_id)
|
||||
|
||||
def to_dict(self):
|
||||
value = super(RequestContext, self).to_dict()
|
||||
value.update({'auth_token': self.auth_token,
|
||||
'auth_url': self.auth_url,
|
||||
'domain_id': self.domain_id,
|
||||
'domain_name': self.domain_name,
|
||||
'user_name': self.user_name,
|
||||
'user_id': self.user_id,
|
||||
'project_name': self.project_name,
|
||||
'project_id': self.project_id,
|
||||
'is_admin': self.is_admin,
|
||||
'read_only': self.read_only,
|
||||
'roles': self.roles,
|
||||
'show_deleted': self.show_deleted,
|
||||
'request_id': self.request_id,
|
||||
'trust_id': self.trust_id,
|
||||
'auth_token_info': self.auth_token_info,
|
||||
'all_tenants': self.all_tenants})
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, values):
|
||||
return cls(**values)
|
||||
|
||||
|
||||
def make_context(*args, **kwargs):
|
||||
return RequestContext(*args, **kwargs)
|
|
@ -1,67 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from evoque.common.i18n import _
|
||||
from evoque.common.i18n import _LE
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class NotImplementedError(NotImplementedError):
|
||||
pass
|
||||
|
||||
|
||||
class EvoqueException(Exception):
|
||||
"""Base Evoque Exception
|
||||
To correctly use this class, inherit from it and define
|
||||
a 'message' property. That message will get printf'd
|
||||
with the keyword arguments provided to the constructor.
|
||||
"""
|
||||
message = _("An unknown exception occurred.")
|
||||
code = 500
|
||||
|
||||
def __init__(self, message=None, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
|
||||
if 'code' not in self.kwargs and hasattr(self, 'code'):
|
||||
self.kwargs['code'] = self.code
|
||||
|
||||
if message:
|
||||
self.message = message
|
||||
|
||||
try:
|
||||
self.message = self.message % kwargs
|
||||
except Exception as e:
|
||||
# kwargs doesn't match a variable in the message
|
||||
# log the issue and the kwargs
|
||||
LOG.exception(_LE('Exception in string format operation, '
|
||||
'kwargs: %s') % kwargs)
|
||||
raise e
|
||||
|
||||
super(EvoqueException, self).__init__(self.message)
|
||||
|
||||
|
||||
class ConfigInvalid(EvoqueException):
|
||||
message = _("Invalid configuration file. %(error_msg)s")
|
||||
|
||||
|
||||
class Invalid(EvoqueException):
|
||||
message = _("Unacceptable parameters.")
|
||||
code = 400
|
||||
|
||||
|
||||
# Cannot be templated as the error syntax varies.
|
||||
# msg needs to be constructed when raised.
|
||||
class InvalidParameterValue(Invalid):
|
||||
message = _("%(err)s")
|
|
@ -1,41 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""oslo.i18n integration module.
|
||||
|
||||
See http://docs.openstack.org/developer/oslo.i18n/usage.html
|
||||
|
||||
"""
|
||||
|
||||
import oslo_i18n
|
||||
|
||||
|
||||
_translators = oslo_i18n.TranslatorFactory(domain='evoque')
|
||||
|
||||
# The primary translation function using the well-known name "_"
|
||||
_ = _translators.primary
|
||||
|
||||
# The contextual translation function using the name "_C"
|
||||
_C = _translators.contextual_form
|
||||
|
||||
# The plural translation function using the name "_P"
|
||||
_P = _translators.plural_form
|
||||
|
||||
# Translators for log levels.
|
||||
#
|
||||
# The abbreviated names are meant to reflect the usual use of a short
|
||||
# name like '_'. The "L" is for "log" and the other letter comes from
|
||||
# the level.
|
||||
_LI = _translators.log_info
|
||||
_LW = _translators.log_warning
|
||||
_LE = _translators.log_error
|
||||
_LC = _translators.log_critical
|
|
@ -1,81 +0,0 @@
|
|||
# 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.
|
||||
|
||||
__all__ = [
|
||||
'init',
|
||||
'RequestContextSerializer',
|
||||
'get_client',
|
||||
'get_server',
|
||||
]
|
||||
|
||||
from oslo_config import cfg
|
||||
import oslo_messaging as messaging
|
||||
from oslo_serialization import jsonutils
|
||||
|
||||
from evoque.common import context as evoque_context
|
||||
|
||||
CONF = cfg.CONF
|
||||
TRANSPORT = None
|
||||
|
||||
|
||||
def init():
|
||||
global TRANSPORT
|
||||
if not TRANSPORT:
|
||||
TRANSPORT = messaging.get_transport(CONF)
|
||||
return TRANSPORT
|
||||
|
||||
|
||||
class JsonPayloadSerializer(messaging.NoOpSerializer):
|
||||
@staticmethod
|
||||
def serialize_entity(context, entity):
|
||||
return jsonutils.to_primitive(entity, convert_instances=True)
|
||||
|
||||
|
||||
class RequestContextSerializer(messaging.Serializer):
|
||||
|
||||
def __init__(self, base):
|
||||
self._base = base
|
||||
|
||||
def serialize_entity(self, context, entity):
|
||||
if not self._base:
|
||||
return entity
|
||||
return self._base.serialize_entity(context, entity)
|
||||
|
||||
def deserialize_entity(self, context, entity):
|
||||
if not self._base:
|
||||
return entity
|
||||
return self._base.deserialize_entity(context, entity)
|
||||
|
||||
def serialize_context(self, context):
|
||||
return context.to_dict()
|
||||
|
||||
def deserialize_context(self, context):
|
||||
return evoque_context.RequestContext.from_dict(context)
|
||||
|
||||
|
||||
def get_client(target, version_cap=None, serializer=None):
|
||||
assert TRANSPORT is not None
|
||||
serializer = RequestContextSerializer(serializer)
|
||||
return messaging.RPCClient(TRANSPORT,
|
||||
target,
|
||||
version_cap=version_cap,
|
||||
serializer=serializer)
|
||||
|
||||
|
||||
def get_server(target, endpoints, serializer=None):
|
||||
assert TRANSPORT is not None
|
||||
serializer = RequestContextSerializer(serializer)
|
||||
return messaging.get_rpc_server(TRANSPORT,
|
||||
target,
|
||||
endpoints,
|
||||
executor='eventlet',
|
||||
serializer=serializer)
|
|
@ -1,72 +0,0 @@
|
|||
# Copyright 2014 - Rackspace Hosting
|
||||
#
|
||||
# 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.
|
||||
|
||||
"""Common RPC service and API tools for Evoque."""
|
||||
|
||||
import eventlet
|
||||
from oslo_config import cfg
|
||||
import oslo_messaging as messaging
|
||||
from oslo_service import service
|
||||
|
||||
from evoque.common import rpc
|
||||
|
||||
# NOTE(paulczar):
|
||||
# Ubuntu 14.04 forces librabbitmq when kombu is used
|
||||
# Unfortunately it forces a version that has a crash
|
||||
# bug. Calling eventlet.monkey_patch() tells kombu
|
||||
# to use libamqp instead.
|
||||
eventlet.monkey_patch()
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class Service(service.Service):
|
||||
|
||||
def __init__(self, topic, server, handlers, binary):
|
||||
super(Service, self).__init__()
|
||||
rpc.init()
|
||||
target = messaging.Target(topic=topic, server=server)
|
||||
self._server = rpc.get_server(target, handlers)
|
||||
|
||||
self.binary = binary
|
||||
|
||||
def start(self):
|
||||
self._server.start()
|
||||
|
||||
def wait(self):
|
||||
self._server.wait()
|
||||
|
||||
@classmethod
|
||||
def create(cls, topic, server, handlers, binary):
|
||||
service_obj = cls(topic, server, handlers, binary)
|
||||
return service_obj
|
||||
|
||||
|
||||
class API(object):
|
||||
def __init__(self, transport=None, context=None, topic=None, server=None,
|
||||
timeout=None):
|
||||
self._context = context
|
||||
|
||||
rpc.init()
|
||||
target = messaging.Target(topic=topic, server=server)
|
||||
self._client = rpc.get_client(target)
|
||||
|
||||
def _call(self, method, *args, **kwargs):
|
||||
return self._client.call(self._context, method, *args, **kwargs)
|
||||
|
||||
def _cast(self, method, *args, **kwargs):
|
||||
self._client.cast(self._context, method, *args, **kwargs)
|
||||
|
||||
def echo(self, message):
|
||||
self._cast('echo', message=message)
|
|
@ -1,33 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
from evoque import opts
|
||||
|
||||
|
||||
def prepare_service():
|
||||
|
||||
# Register Evoque options
|
||||
for group, options in opts.list_opts():
|
||||
cfg.CONF.register_opts(
|
||||
list(options),
|
||||
group=None if group == "DEFAULT" else group)
|
||||
|
||||
logging.register_options(cfg.CONF)
|
||||
cfg.CONF(sys.argv[1:], project='evoque')
|
||||
|
||||
logging.setup(cfg.CONF, 'evoque')
|
|
@ -1,37 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Utilities and helper functions."""
|
||||
|
||||
import six
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from evoque.common.i18n import _LW
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def safe_rstrip(value, chars=None):
|
||||
"""Removes trailing characters from a string if that does not make it empty
|
||||
:param value: A string value that will be stripped.
|
||||
:param chars: Characters to remove.
|
||||
:return: Stripped value.
|
||||
"""
|
||||
if not isinstance(value, six.string_types):
|
||||
LOG.warn(_LW("Failed to remove trailing character. Returning "
|
||||
"original object. Supplied object is not a string: %s,"),
|
||||
value)
|
||||
return value
|
||||
|
||||
return value.rstrip(chars) or value
|
|
@ -1,67 +0,0 @@
|
|||
# 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.
|
||||
|
||||
'''
|
||||
Interface for database access.
|
||||
|
||||
SQLAlchemy is currently the only supported backend.
|
||||
'''
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db import api
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
_BACKEND_MAPPING = {'sqlalchemy': 'evoque.db.sqlalchemy.api'}
|
||||
|
||||
IMPL = api.DBAPI.from_config(CONF, backend_mapping=_BACKEND_MAPPING)
|
||||
|
||||
|
||||
def get_engine():
|
||||
return IMPL.get_engine()
|
||||
|
||||
|
||||
def get_session():
|
||||
return IMPL.get_session()
|
||||
|
||||
|
||||
# Tickets
|
||||
def ticket_create(context, values):
|
||||
return IMPL.ticket_create(context, values)
|
||||
|
||||
|
||||
def ticket_get_all(context, filters=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
return IMPL.ticket_get_all(context, filters=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None)
|
||||
|
||||
|
||||
# Workflows
|
||||
def workflow_create(context, values):
|
||||
return IMPL.workflow_create(context, values)
|
||||
|
||||
|
||||
def workflow_get_all(context, filters=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
return IMPL.workflow_get_all(context, filters=None, limit=None,
|
||||
marker=None, sort_key=None, sort_dir=None)
|
||||
|
||||
|
||||
# Utils
|
||||
def db_sync(engine, version=None):
|
||||
"""Migrate the database to `version` or the most recent version."""
|
||||
return IMPL.db_sync(engine, version=version)
|
||||
|
||||
|
||||
def db_version(engine):
|
||||
"""Display the current database version."""
|
||||
return IMPL.db_version(engine)
|
|
@ -1,115 +0,0 @@
|
|||
# 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.
|
||||
|
||||
'''
|
||||
Implementation of SQLAlchemy backend.
|
||||
'''
|
||||
|
||||
import sys
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db import exception as db_exc
|
||||
from oslo_db.sqlalchemy import session as db_session
|
||||
from oslo_db.sqlalchemy import utils as db_utils
|
||||
|
||||
from evoque.common import exceptions
|
||||
from evoque.common.i18n import _
|
||||
from evoque.db.sqlalchemy import migration
|
||||
from evoque.db.sqlalchemy import models
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
_facade = None
|
||||
|
||||
|
||||
def get_facade():
|
||||
global _facade
|
||||
|
||||
if not _facade:
|
||||
_facade = db_session.EngineFacade.from_config(CONF)
|
||||
return _facade
|
||||
|
||||
get_engine = lambda: get_facade().get_engine()
|
||||
get_session = lambda: get_facade().get_session()
|
||||
|
||||
|
||||
def get_backend():
|
||||
"""The backend is this module itself."""
|
||||
return sys.modules[__name__]
|
||||
|
||||
|
||||
def _session():
|
||||
return get_session()
|
||||
|
||||
|
||||
def model_query(model, *args):
|
||||
session = _session()
|
||||
query = session.query(model, *args)
|
||||
return query
|
||||
|
||||
|
||||
def _paginate_query(model, limit=None, marker=None, sort_key=None,
|
||||
sort_dir=None, query=None):
|
||||
if not query:
|
||||
query = model_query(model)
|
||||
sort_keys = ['id']
|
||||
if sort_key and sort_key not in sort_keys:
|
||||
sort_keys.insert(0, sort_key)
|
||||
try:
|
||||
query = db_utils.paginate_query(query, model, limit, sort_keys,
|
||||
marker=marker, sort_dir=sort_dir)
|
||||
except db_exc.InvalidSortKey:
|
||||
raise exceptions.InvalidParameterValue(
|
||||
_('The sort_key value "%(key)s" is an invalid field for sorting')
|
||||
% {'key': sort_key})
|
||||
return query.all()
|
||||
|
||||
|
||||
# Tickets
|
||||
def ticket_create(context, values):
|
||||
ticket_ref = models.Ticket()
|
||||
ticket_ref.update(values)
|
||||
ticket_ref.save(_session())
|
||||
return ticket_ref
|
||||
|
||||
|
||||
def ticket_get_all(context, filters=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
query = model_query(models.Ticket)
|
||||
return _paginate_query(models.Ticket, limit, marker,
|
||||
sort_key, sort_dir, query)
|
||||
|
||||
|
||||
# Workflows
|
||||
def workflow_create(context, values):
|
||||
workflow_ref = models.Workflow()
|
||||
workflow_ref.update(values)
|
||||
workflow_ref.save(_session())
|
||||
return workflow_ref
|
||||
|
||||
|
||||
def workflow_get_all(context, filters=None, limit=None, marker=None,
|
||||
sort_key=None, sort_dir=None):
|
||||
query = model_query(models.Workflow)
|
||||
return _paginate_query(models.Workflow, limit, marker,
|
||||
sort_key, sort_dir, query)
|
||||
|
||||
|
||||
# Utils
|
||||
def db_sync(engine, version=None):
|
||||
"""Migrate the database to `version` or the most recent version."""
|
||||
return migration.db_sync(engine, version=version)
|
||||
|
||||
|
||||
def db_version(engine):
|
||||
"""Display the current database version."""
|
||||
return migration.db_version(engine)
|
|
@ -1,4 +0,0 @@
|
|||
This is a database migration repository.
|
||||
|
||||
More information at
|
||||
http://code.google.com/p/sqlalchemy-migrate/
|
|
@ -1,5 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
from migrate.versioning.shell import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(debug='False')
|
|
@ -1,25 +0,0 @@
|
|||
[db_settings]
|
||||
# Used to identify which repository this database is versioned under.
|
||||
# You can use the name of your project.
|
||||
repository_id=evoque
|
||||
|
||||
# The name of the database table used to track the schema version.
|
||||
# This name shouldn't already be used by your project.
|
||||
# If this is changed once a database is under version control, you'll need to
|
||||
# change the table name in each database too.
|
||||
version_table=migrate_version
|
||||
|
||||
# When committing a change script, Migrate will attempt to generate the
|
||||
# sql for all supported databases; normally, if one of them fails - probably
|
||||
# because you don't have that database installed - it is ignored and the
|
||||
# commit continues, perhaps ending successfully.
|
||||
# Databases in this list MUST compile successfully during a commit, or the
|
||||
# entire commit will fail. List the databases your application will actually
|
||||
# be using to ensure your updates to that database work properly.
|
||||
# This must be a list; example: ['postgres','sqlite']
|
||||
required_dbs=[]
|
||||
|
||||
# When creating new change scripts, Migrate will stamp the new script with
|
||||
# a version number. By default this is latest_version + 1. You can set this
|
||||
# to 'true' to tell Migrate to use the UTC timestamp instead.
|
||||
use_timestamp_numbering=False
|
|
@ -1,82 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import sqlalchemy
|
||||
|
||||
from evoque.db.sqlalchemy import types
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
ticket = sqlalchemy.Table(
|
||||
'ticket', meta,
|
||||
sqlalchemy.Column('id', sqlalchemy.String(36),
|
||||
primary_key=True, nullable=False),
|
||||
sqlalchemy.Column('name', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('type', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('status', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('workflow_id', sqlalchemy.String(36),
|
||||
sqlalchemy.ForeignKey('workflow.id')),
|
||||
sqlalchemy.Column('user', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('project', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('domain', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('user_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('project_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('domain_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('metadata', types.Dict),
|
||||
sqlalchemy.Column('created_at', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('updated_at', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('deleted_at', sqlalchemy.DateTime),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
workflow = sqlalchemy.Table(
|
||||
'workflow', meta,
|
||||
sqlalchemy.Column('id', sqlalchemy.String(36),
|
||||
primary_key=True, nullable=False),
|
||||
sqlalchemy.Column('name', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('spec', types.MediumText()),
|
||||
sqlalchemy.Column('user', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('project', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('domain', sqlalchemy.String(32)),
|
||||
sqlalchemy.Column('user_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('project_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('domain_id', sqlalchemy.String(255)),
|
||||
sqlalchemy.Column('metadata', types.Dict),
|
||||
sqlalchemy.Column('created_at', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('updated_at', sqlalchemy.DateTime),
|
||||
sqlalchemy.Column('deleted_at', sqlalchemy.DateTime),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
tables = (
|
||||
ticket,
|
||||
workflow
|
||||
)
|
||||
|
||||
for index, table in enumerate(tables):
|
||||
try:
|
||||
table.create()
|
||||
except Exception:
|
||||
# If an error occurs, drop all tables created so far to return
|
||||
# to the previously existing state.
|
||||
meta.drop_all(tables=tables[:index])
|
||||
raise
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
raise NotImplementedError('Database downgrade not supported - '
|
||||
'would drop all tables')
|
|
@ -1,31 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import os
|
||||
|
||||
from oslo_db.sqlalchemy import migration as oslo_migration
|
||||
|
||||
|
||||
INIT_VERSION = 000
|
||||
|
||||
|
||||
def db_sync(engine, version=None):
|
||||
path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'migrate_repo')
|
||||
return oslo_migration.db_sync(engine, path, version,
|
||||
init_version=INIT_VERSION)
|
||||
|
||||
|
||||
def db_version(engine):
|
||||
path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
|
||||
'migrate_repo')
|
||||
return oslo_migration.db_version(engine, path, INIT_VERSION)
|
|
@ -1,66 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
SQLAlchemy models for Evoque data.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from oslo_db.sqlalchemy import models
|
||||
import sqlalchemy
|
||||
from sqlalchemy.ext import declarative
|
||||
|
||||
from evoque.db.sqlalchemy import types
|
||||
|
||||
BASE = declarative.declarative_base()
|
||||
|
||||
|
||||
class EvoqueBase(models.TimestampMixin,
|
||||
models.ModelBase):
|
||||
"""Base class for Evoque Models."""
|
||||
|
||||
__table_args__ = {'mysql_engine': 'InnoDB'}
|
||||
|
||||
metadata = sqlalchemy.Column(types.Dict)
|
||||
|
||||
user = sqlalchemy.Column(sqlalchemy.String(32))
|
||||
project = sqlalchemy.Column(sqlalchemy.String(32))
|
||||
domain = sqlalchemy.Column(sqlalchemy.String(32))
|
||||
user_id = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
project_id = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
domain_id = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
|
||||
|
||||
class Ticket(BASE, EvoqueBase):
|
||||
"""Represents a ticket created by the Evoque engine."""
|
||||
|
||||
__tablename__ = 'ticket'
|
||||
|
||||
id = sqlalchemy.Column('id', sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
workflow_id = sqlalchemy.Column(sqlalchemy.String(36),
|
||||
sqlalchemy.ForeignKey('workflow.id'))
|
||||
name = sqlalchemy.Column('name', sqlalchemy.String(255))
|
||||
type = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
status = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
|
||||
|
||||
class Workflow(BASE, EvoqueBase):
|
||||
"""Represents a workflow created by the Evoque engine."""
|
||||
|
||||
__tablename__ = 'workflow'
|
||||
|
||||
id = sqlalchemy.Column('id', sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
name = sqlalchemy.Column('name', sqlalchemy.String(255))
|
||||
spec = sqlalchemy.Column('spec', types.MediumText())
|
|
@ -1,39 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import json
|
||||
|
||||
from sqlalchemy.dialects import mysql
|
||||
from sqlalchemy import Text
|
||||
from sqlalchemy import types
|
||||
|
||||
|
||||
class Dict(types.TypeDecorator):
|
||||
impl = types.Text
|
||||
|
||||
def load_dialect_impl(self, dialect):
|
||||
if dialect.name == 'mysql':
|
||||
return dialect.type_descriptor(mysql.LONGTEXT())
|
||||
else:
|
||||
return self.impl
|
||||
|
||||
def process_bind_param(self, value, dialect):
|
||||
return json.dumps(value)
|
||||
|
||||
def process_result_value(self, value, dialect):
|
||||
if value is None:
|
||||
return None
|
||||
return json.loads(value)
|
||||
|
||||
|
||||
def MediumText():
|
||||
return Text().with_variant(mysql.MEDIUMTEXT(), 'mysql')
|
|
@ -1,25 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.common import rpc_service
|
||||
|
||||
|
||||
class API(rpc_service.API):
|
||||
def __init__(self, transport=None, context=None, topic=None):
|
||||
super(API, self).__init__(transport, context,
|
||||
topic="evoque-engine")
|
||||
|
||||
def ticket_create(self, name):
|
||||
return self._call('ticket_create', name=name)
|
||||
|
||||
def ticket_list(self):
|
||||
return self._call('ticket_list')
|
|
@ -1,28 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.db import api as db_api
|
||||
|
||||
|
||||
class Handler(object):
|
||||
|
||||
def __init__(self):
|
||||
super(Handler, self).__init__()
|
||||
|
||||
def ticket_create(self, context, name):
|
||||
values = {'name': name}
|
||||
ticket = db_api.ticket_create(context, values)
|
||||
return {'ticket': ticket}
|
||||
|
||||
def ticket_list(self, context):
|
||||
tickets = db_api.ticket_get_all(context)
|
||||
return {'tickets': tickets}
|
|
@ -1,51 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import abc
|
||||
import six
|
||||
|
||||
from oslo_config import cfg
|
||||
from stevedore import driver
|
||||
|
||||
from evoque.common.i18n import _
|
||||
|
||||
OPTS = [
|
||||
cfg.StrOpt('workflow_engine',
|
||||
default='spiff',
|
||||
help=_('The Evoque workflow engine driver.')),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(OPTS)
|
||||
|
||||
|
||||
def get_workflow(engine=CONF.workflow_engine, namespace='evoque.workflow'):
|
||||
"""Get workflow driver and load it.
|
||||
|
||||
:param engine: workflow engine
|
||||
:param namespace: Namespace to use to look for drivers.
|
||||
"""
|
||||
|
||||
loaded_driver = driver.DriverManager(namespace, engine)
|
||||
return loaded_driver.driver()
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class Base(object):
|
||||
"""Base class for workflow operations."""
|
||||
|
||||
def __init__(self):
|
||||
super(Base, self).__init__()
|
||||
|
||||
@abc.abstractmethod
|
||||
def workflow_create(self, wf_spec):
|
||||
"""Create a workflow"""
|
|
@ -1,25 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.common import rpc_service
|
||||
|
||||
|
||||
class API(rpc_service.API):
|
||||
def __init__(self, transport=None, context=None, topic=None):
|
||||
super(API, self).__init__(transport, context,
|
||||
topic="evoque-engine")
|
||||
|
||||
def workflow_create(self, name, wf_spec):
|
||||
return self._call('workflow_create', name=name, wf_spec=wf_spec)
|
||||
|
||||
def workflow_list(self):
|
||||
return self._call('workflow_list')
|
|
@ -1,30 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.engine import workflow
|
||||
|
||||
|
||||
class Handler(object):
|
||||
|
||||
def __init__(self):
|
||||
super(Handler, self).__init__()
|
||||
self.workflow_driver = workflow.get_workflow()
|
||||
|
||||
def workflow_create(self, context, name, wf_spec):
|
||||
workflow = self.workflow_driver.workflow_create(
|
||||
context, name, wf_spec)
|
||||
return {'workflow': workflow}
|
||||
|
||||
def workflow_list(self, context):
|
||||
workflows = self.workflow_driver.workflow_list(
|
||||
context)
|
||||
return {'workflows': workflows}
|
|
@ -1,37 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.db import api as db_api
|
||||
from evoque.engine import workflow
|
||||
|
||||
|
||||
class Workflow(workflow.Base):
|
||||
"""Workflow engine powered by `SpiffWorkflow`
|
||||
|
||||
https://github.com/knipknap/SpiffWorkflow
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(Workflow, self).__init__()
|
||||
|
||||
def workflow_create(self, context, name, wf_spec):
|
||||
"""Create a workflow"""
|
||||
values = {
|
||||
'name': name,
|
||||
'spec': wf_spec
|
||||
}
|
||||
workflow = db_api.workflow_create(context, values)
|
||||
return workflow
|
||||
|
||||
def workflow_list(self, context):
|
||||
workflows = db_api.workflow_get_all(context)
|
||||
return workflows
|
|
@ -1,59 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import multiprocessing
|
||||
import socket
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from evoque.common.i18n import _
|
||||
|
||||
|
||||
try:
|
||||
default_workers = multiprocessing.cpu_count() or 1
|
||||
except NotImplementedError:
|
||||
default_workers = 1
|
||||
|
||||
|
||||
def list_opts():
|
||||
return [
|
||||
("api", (
|
||||
cfg.PortOpt('port',
|
||||
default=8888,
|
||||
help=_('The port for the Evoque API server.')),
|
||||
cfg.StrOpt('host',
|
||||
default='0.0.0.0',
|
||||
help=_('The listen IP for the Evoque API server.')),
|
||||
cfg.BoolOpt('pecan_debug',
|
||||
default=False,
|
||||
help=_('Toggle Pecan Debug Middleware.')),
|
||||
cfg.IntOpt('workers', default=default_workers,
|
||||
help=_('Number of workers for Evoque API server.')),
|
||||
cfg.IntOpt('max_limit',
|
||||
default=1000,
|
||||
help=_('The maximum number of items returned in a '
|
||||
'single response from a collection resource')),
|
||||
cfg.BoolOpt('enable_authentication',
|
||||
default=True,
|
||||
help=_('This option enables or disables user '
|
||||
'authentication via Keystone. '
|
||||
'Default value is True.')),
|
||||
)),
|
||||
("DEFAULT", (
|
||||
cfg.StrOpt('host',
|
||||
default=socket.getfqdn(),
|
||||
help=_('The listen IP for the Evoque engine server.')),
|
||||
cfg.StrOpt('workflow_engine',
|
||||
default='spiff',
|
||||
help=_('The Evoque workflow engine driver.')),
|
||||
)),
|
||||
]
|
|
@ -1,28 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.api import app as api_app
|
||||
from evoque.api import config as api_config
|
||||
from evoque.api import hooks
|
||||
from evoque.tests.unit import base
|
||||
|
||||
|
||||
class TestAppConfig(base.BaseTestCase):
|
||||
|
||||
def test_get_pecan_config(self):
|
||||
config = api_app.get_pecan_config()
|
||||
|
||||
config_d = dict(config.app)
|
||||
|
||||
self.assertEqual(api_config.app['modules'], config_d['modules'])
|
||||
self.assertEqual(api_config.app['root'], config_d['root'])
|
||||
self.assertIsInstance(config_d['hooks'][0], hooks.ContextHook)
|
|
@ -1,55 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import testscenarios
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslotest import base
|
||||
|
||||
from evoque.common import context as evoque_context
|
||||
from evoque.tests.unit import fixture
|
||||
|
||||
CONF = cfg.CONF
|
||||
log.register_options(CONF)
|
||||
CONF.set_override('use_stderr', False)
|
||||
|
||||
|
||||
class BaseTestCase(testscenarios.WithScenarios, base.BaseTestCase):
|
||||
"""Test base class."""
|
||||
|
||||
def setUp(self):
|
||||
super(BaseTestCase, self).setUp()
|
||||
self.addCleanup(cfg.CONF.reset)
|
||||
|
||||
|
||||
class DBTestCase(base.BaseTestCase):
|
||||
"""Test case base class for all unit tests."""
|
||||
|
||||
def setUp(self):
|
||||
super(DBTestCase, self).setUp()
|
||||
self.useFixture(fixture.DBTestFixture())
|
||||
|
||||
token_info = {
|
||||
'token': {
|
||||
'project': {
|
||||
'id': 'fake_project'
|
||||
},
|
||||
'user': {
|
||||
'id': 'fake_user'
|
||||
}
|
||||
}
|
||||
}
|
||||
self.context = evoque_context.RequestContext(
|
||||
auth_token_info=token_info,
|
||||
project_id='fake_project',
|
||||
user_id='fake_user')
|
|
@ -1,56 +0,0 @@
|
|||
# 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.
|
||||
|
||||
import logging
|
||||
import os
|
||||
|
||||
import fixtures
|
||||
import testscenarios
|
||||
import testtools
|
||||
|
||||
|
||||
TEST_DEFAULT_LOGLEVELS = {'migrate': logging.WARN,
|
||||
'sqlalchemy': logging.WARN}
|
||||
_LOG_FORMAT = "%(levelname)8s [%(name)s] %(message)s"
|
||||
_TRUE_VALUES = ('True', 'true', '1', 'yes')
|
||||
|
||||
|
||||
class FakeLogMixin(object):
|
||||
def setup_logging(self):
|
||||
# Assign default logs to self.LOG so we can still
|
||||
# assert on evoque logs.
|
||||
default_level = logging.INFO
|
||||
if os.environ.get('OS_DEBUG') in _TRUE_VALUES:
|
||||
default_level = logging.DEBUG
|
||||
|
||||
self.LOG = self.useFixture(
|
||||
fixtures.FakeLogger(level=default_level, format=_LOG_FORMAT))
|
||||
base_list = set([nlog.split('.')[0]
|
||||
for nlog in logging.Logger.manager.loggerDict])
|
||||
for base in base_list:
|
||||
if base in TEST_DEFAULT_LOGLEVELS:
|
||||
self.useFixture(fixtures.FakeLogger(
|
||||
level=TEST_DEFAULT_LOGLEVELS[base],
|
||||
name=base, format=_LOG_FORMAT))
|
||||
elif base != 'evoque':
|
||||
self.useFixture(fixtures.FakeLogger(
|
||||
name=base, format=_LOG_FORMAT))
|
||||
|
||||
|
||||
class EvoqueTestCase(testscenarios.WithScenarios,
|
||||
testtools.TestCase, FakeLogMixin):
|
||||
|
||||
TIME_STEP = 0.1
|
||||
|
||||
def setUp(self):
|
||||
super(EvoqueTestCase, self).setUp()
|
||||
self.setup_logging()
|
|
@ -1,30 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# 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.
|
||||
|
||||
"""Tests for manipulating Bays via the DB API"""
|
||||
|
||||
from evoque.tests.unit import base
|
||||
from evoque.tests.unit.db import utils
|
||||
|
||||
|
||||
class DBTicketTestCase(base.DBTestCase):
|
||||
|
||||
def test_ticket_create(self):
|
||||
ticket = utils.ticket_create(self.context)
|
||||
self.assertEqual(ticket.name, 'test-ticket')
|
||||
|
||||
def test_ticket_list(self):
|
||||
tickets = utils.ticket_list(self.context)
|
||||
self.assertFalse(tickets)
|
|
@ -1,30 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# 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.
|
||||
|
||||
"""Tests for manipulating Bays via the DB API"""
|
||||
|
||||
from evoque.tests.unit import base
|
||||
from evoque.tests.unit.db import utils
|
||||
|
||||
|
||||
class DBWorkflowTestCase(base.DBTestCase):
|
||||
|
||||
def test_workflow_create(self):
|
||||
workflow = utils.workflow_create(self.context)
|
||||
self.assertEqual(workflow.name, 'test-workflow')
|
||||
|
||||
def test_workflow_list(self):
|
||||
workflows = utils.workflow_list(self.context)
|
||||
self.assertFalse(workflows)
|
|
@ -1,42 +0,0 @@
|
|||
# Copyright 2015 OpenStack Foundation
|
||||
# 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.
|
||||
|
||||
"""Evoque test utilities."""
|
||||
|
||||
from evoque.db import api as db_api
|
||||
|
||||
|
||||
# Tickets
|
||||
def ticket_create(context):
|
||||
values = {"name": "test-ticket"}
|
||||
ticket = db_api.ticket_create(context, values)
|
||||
return ticket
|
||||
|
||||
|
||||
def ticket_list(context):
|
||||
tickets = db_api.ticket_get_all(context)
|
||||
return tickets
|
||||
|
||||
|
||||
# Workflows
|
||||
def workflow_create(context):
|
||||
values = {"name": "test-workflow"}
|
||||
workflow = db_api.workflow_create(context, values)
|
||||
return workflow
|
||||
|
||||
|
||||
def workflow_list(context):
|
||||
workflows = db_api.workflow_get_all(context)
|
||||
return workflows
|
|
@ -1,54 +0,0 @@
|
|||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# 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.
|
||||
|
||||
import fixtures
|
||||
import sqlalchemy
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from evoque.db import api as db_api
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class DBTestFixture(fixtures.Fixture):
|
||||
|
||||
def __init__(self):
|
||||
# Use sqlite as test DB
|
||||
self.sqlite_db = '/tmp/evoque.db'
|
||||
|
||||
CONF.set_default('connection', "sqlite://", group='database')
|
||||
CONF.set_default('sqlite_db', self.sqlite_db, group='database')
|
||||
CONF.set_default('sqlite_synchronous', False, group='database')
|
||||
|
||||
def _setUp(self):
|
||||
self._setup_test_db()
|
||||
self.addCleanup(self._reset_test_db)
|
||||
|
||||
def _setup_test_db(self):
|
||||
engine = db_api.get_engine()
|
||||
db_api.db_sync(engine)
|
||||
engine.connect()
|
||||
|
||||
def _reset_test_db(self):
|
||||
engine = db_api.get_engine()
|
||||
meta = sqlalchemy.MetaData()
|
||||
meta.reflect(bind=engine)
|
||||
|
||||
for table in reversed(meta.sorted_tables):
|
||||
if table.name == 'migrate_version':
|
||||
continue
|
||||
engine.execute(table.delete())
|
|
@ -1,81 +0,0 @@
|
|||
# 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.
|
||||
|
||||
from evoque.common import context
|
||||
from evoque.tests.unit.common import base
|
||||
|
||||
|
||||
class TestRequestContext(base.EvoqueTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.ctx = {
|
||||
'auth_token': '123',
|
||||
'auth_url': 'http://xyz',
|
||||
'domain_id': 'domain-id',
|
||||
'domain_name': 'domain-name',
|
||||
'user_name': 'mick',
|
||||
'user_id': 'user-id',
|
||||
'project_name': 'a project',
|
||||
'project_id': 'project-id',
|
||||
'roles': ['arole', 'notadmin'],
|
||||
'is_admin': False,
|
||||
'read_only': False,
|
||||
'show_deleted': False,
|
||||
'trust_id': "trust-id",
|
||||
'auth_token_info': {'123info': 'woop'},
|
||||
'all_tenants': False,
|
||||
}
|
||||
|
||||
super(TestRequestContext, self).setUp()
|
||||
|
||||
def test_request_context_init(self):
|
||||
ctx = context.RequestContext(
|
||||
auth_token=self.ctx.get('auth_token'),
|
||||
auth_url=self.ctx.get('auth_url'),
|
||||
domain_id=self.ctx.get('domain_id'),
|
||||
domain_name=self.ctx.get('domain_name'),
|
||||
user_name=self.ctx.get('user_name'),
|
||||
user_id=self.ctx.get('user_id'),
|
||||
project_domain=self.ctx.get('project_domain'),
|
||||
project_name=self.ctx.get('project_name'),
|
||||
project_id=self.ctx.get('project_id'),
|
||||
roles=self.ctx.get('roles'),
|
||||
is_admin=self.ctx.get('is_admin'),
|
||||
read_only=self.ctx.get('read_only'),
|
||||
show_deleted=self.ctx.get('show_deleted'),
|
||||
trust_id=self.ctx.get('trust_id'),
|
||||
auth_token_info=self.ctx.get('auth_token_info'),
|
||||
all_tenants=self.ctx.get('all_tenants'))
|
||||
|
||||
ctx_dict = ctx.to_dict()
|
||||
del(ctx_dict['request_id'])
|
||||
del(ctx_dict['user'])
|
||||
del(ctx_dict['domain'])
|
||||
del(ctx_dict['user_domain'])
|
||||
del(ctx_dict['user_identity'])
|
||||
del(ctx_dict['resource_uuid'])
|
||||
del(ctx_dict['project_domain'])
|
||||
del(ctx_dict['tenant'])
|
||||
self.assertEqual(self.ctx, ctx_dict)
|
||||
|
||||
def test_request_context_from_dict(self):
|
||||
ctx = context.RequestContext.from_dict(self.ctx)
|
||||
ctx_dict = ctx.to_dict()
|
||||
del(ctx_dict['request_id'])
|
||||
del(ctx_dict['user'])
|
||||
del(ctx_dict['domain'])
|
||||
del(ctx_dict['user_domain'])
|
||||
del(ctx_dict['user_identity'])
|
||||
del(ctx_dict['resource_uuid'])
|
||||
del(ctx_dict['project_domain'])
|
||||
del(ctx_dict['tenant'])
|
||||
self.assertEqual(self.ctx, ctx_dict)
|
|
@ -1,16 +0,0 @@
|
|||
# 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.
|
||||
|
||||
|
||||
import pbr.version
|
||||
|
||||
version_info = pbr.version.VersionInfo('evoque')
|
|
@ -1,22 +0,0 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr>=1.6
|
||||
keystonemiddleware!=2.4.0,>=2.0.0
|
||||
oslo.config>=2.6.0 # Apache-2.0
|
||||
oslo.context>=0.2.0 # Apache-2.0
|
||||
oslo.db>=3.0.0 # Apache-2.0
|
||||
oslo.i18n>=1.5.0 # Apache-2.0
|
||||
oslo.log>=1.8.0 # Apache-2.0
|
||||
oslo.messaging!=1.17.0,!=1.17.1,!=2.6.0,!=2.6.1,>=1.16.0 # Apache-2.0
|
||||
oslo.serialization>=1.10.0 # Apache-2.0
|
||||
oslo.service>=0.10.0 # Apache-2.0
|
||||
oslo.utils!=2.6.0,>=2.4.0 # Apache-2.0
|
||||
pecan>=1.0.0
|
||||
SQLAlchemy<1.1.0,>=0.9.9
|
||||
sqlalchemy-migrate>=0.9.6
|
||||
WebOb>=1.2.3
|
||||
Werkzeug>=0.7 # BSD License
|
||||
osprofiler>=0.3.0 # Apache-2.0
|
||||
MySQL-python>=1.2.5
|
250
run_tests.sh
250
run_tests.sh
|
@ -1,250 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 [OPTION]..."
|
||||
echo "Run Evoque's test suite(s)"
|
||||
echo ""
|
||||
echo " -V, --virtual-env Always use virtualenv. Install automatically if not present"
|
||||
echo " -N, --no-virtual-env Don't use virtualenv. Run tests in local environment"
|
||||
echo " -s, --no-site-packages Isolate the virtualenv from the global Python environment"
|
||||
echo " -f, --force Force a clean re-build of the virtual environment. Useful when dependencies have been added."
|
||||
echo " -u, --update Update the virtual environment with any newer package versions"
|
||||
echo " -p, --pep8 Just run PEP8 and HACKING compliance check"
|
||||
echo " -8, --pep8-only-changed Just run PEP8 and HACKING compliance check on files changed since HEAD~1"
|
||||
echo " -P, --no-pep8 Don't run static code checks"
|
||||
echo " -c, --coverage Generate coverage report"
|
||||
echo " -d, --debug Run tests with testtools instead of testr. This allows you to use the debugger."
|
||||
echo " -h, --help Print this usage message"
|
||||
echo " --virtual-env-path <path> Location of the virtualenv directory"
|
||||
echo " Default: \$(pwd)"
|
||||
echo " --virtual-env-name <name> Name of the virtualenv directory"
|
||||
echo " Default: .venv"
|
||||
echo " --tools-path <dir> Location of the tools directory"
|
||||
echo " Default: \$(pwd)"
|
||||
echo " --concurrency <concurrency> How many processes to use when running the tests. A value of 0 autodetects concurrency from your CPU count"
|
||||
echo " Default: 0"
|
||||
echo ""
|
||||
echo "Note: with no options specified, the script will try to run the tests in a virtual environment,"
|
||||
echo " If no virtualenv is found, the script will ask if you would like to create one. If you "
|
||||
echo " prefer to run tests NOT in a virtual environment, simply pass the -N option."
|
||||
exit
|
||||
}
|
||||
|
||||
function process_options {
|
||||
i=1
|
||||
while [ $i -le $# ]; do
|
||||
case "${!i}" in
|
||||
-h|--help) usage;;
|
||||
-V|--virtual-env) always_venv=1; never_venv=0;;
|
||||
-N|--no-virtual-env) always_venv=0; never_venv=1;;
|
||||
-s|--no-site-packages) no_site_packages=1;;
|
||||
-f|--force) force=1;;
|
||||
-u|--update) update=1;;
|
||||
-p|--pep8) just_pep8=1;;
|
||||
-8|--pep8-only-changed) just_pep8_changed=1;;
|
||||
-P|--no-pep8) no_pep8=1;;
|
||||
-c|--coverage) coverage=1;;
|
||||
-d|--debug) debug=1;;
|
||||
--virtual-env-path)
|
||||
(( i++ ))
|
||||
venv_path=${!i}
|
||||
;;
|
||||
--virtual-env-name)
|
||||
(( i++ ))
|
||||
venv_dir=${!i}
|
||||
;;
|
||||
--tools-path)
|
||||
(( i++ ))
|
||||
tools_path=${!i}
|
||||
;;
|
||||
--concurrency)
|
||||
(( i++ ))
|
||||
concurrency=${!i}
|
||||
;;
|
||||
-*) testropts="$testropts ${!i}";;
|
||||
*) testrargs="$testrargs ${!i}"
|
||||
esac
|
||||
(( i++ ))
|
||||
done
|
||||
}
|
||||
|
||||
tool_path=${tools_path:-$(pwd)}
|
||||
venv_path=${venv_path:-$(pwd)}
|
||||
venv_dir=${venv_name:-.venv}
|
||||
with_venv=tools/with_venv.sh
|
||||
always_venv=0
|
||||
never_venv=0
|
||||
force=0
|
||||
no_site_packages=0
|
||||
installvenvopts=
|
||||
testrargs=
|
||||
testropts=
|
||||
wrapper=""
|
||||
just_pep8=0
|
||||
just_pep8_changed=0
|
||||
no_pep8=0
|
||||
coverage=0
|
||||
debug=0
|
||||
update=0
|
||||
concurrency=0
|
||||
|
||||
LANG=en_US.UTF-8
|
||||
LANGUAGE=en_US:en
|
||||
LC_ALL=C
|
||||
|
||||
process_options $@
|
||||
# Make our paths available to other scripts we call
|
||||
export venv_path
|
||||
export venv_dir
|
||||
export venv_name
|
||||
export tools_dir
|
||||
export venv=${venv_path}/${venv_dir}
|
||||
|
||||
if [ $no_site_packages -eq 1 ]; then
|
||||
installvenvopts="--no-site-packages"
|
||||
fi
|
||||
|
||||
function run_tests {
|
||||
# Cleanup *pyc
|
||||
${wrapper} find . -type f -name "*.pyc" -delete
|
||||
|
||||
if [ $debug -eq 1 ]; then
|
||||
if [ "$testropts" = "" ] && [ "$testrargs" = "" ]; then
|
||||
# Default to running all tests if specific test is not
|
||||
# provided.
|
||||
testrargs="discover ./evoque/tests"
|
||||
fi
|
||||
${wrapper} python -m testtools.run $testropts $testrargs
|
||||
|
||||
# Short circuit because all of the testr and coverage stuff
|
||||
# below does not make sense when running testtools.run for
|
||||
# debugging purposes.
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [ $coverage -eq 1 ]; then
|
||||
TESTRTESTS="$TESTRTESTS --coverage"
|
||||
else
|
||||
TESTRTESTS="$TESTRTESTS"
|
||||
fi
|
||||
|
||||
# Just run the test suites in current environment
|
||||
set +e
|
||||
testrargs=`echo "$testrargs" | sed -e's/^\s*\(.*\)\s*$/\1/'`
|
||||
TESTRTESTS="$TESTRTESTS --testr-args='--subunit --concurrency $concurrency $testropts $testrargs'"
|
||||
if [ setup.cfg -nt evoque.egg-info/entry_points.txt ]
|
||||
then
|
||||
${wrapper} python setup.py egg_info
|
||||
fi
|
||||
echo "Running \`${wrapper} $TESTRTESTS\`"
|
||||
if ${wrapper} which subunit-2to1 2>&1 > /dev/null
|
||||
then
|
||||
# subunit-2to1 is present, testr subunit stream should be in version 2
|
||||
# format. Convert to version one before colorizing.
|
||||
bash -c "${wrapper} $TESTRTESTS | ${wrapper} subunit-2to1 | ${wrapper} tools/colorizer.py"
|
||||
else
|
||||
bash -c "${wrapper} $TESTRTESTS | ${wrapper} tools/colorizer.py"
|
||||
fi
|
||||
RESULT=$?
|
||||
set -e
|
||||
|
||||
copy_subunit_log
|
||||
|
||||
if [ $coverage -eq 1 ]; then
|
||||
echo "Generating coverage report in covhtml/"
|
||||
${wrapper} coverage combine
|
||||
${wrapper} coverage html --include='evoque/*' -d covhtml -i
|
||||
fi
|
||||
|
||||
return $RESULT
|
||||
}
|
||||
|
||||
function copy_subunit_log {
|
||||
LOGNAME=`cat .testrepository/next-stream`
|
||||
LOGNAME=$(($LOGNAME - 1))
|
||||
LOGNAME=".testrepository/${LOGNAME}"
|
||||
cp $LOGNAME subunit.log
|
||||
}
|
||||
|
||||
function warn_on_flake8_without_venv {
|
||||
if [ $never_venv -eq 1 ]; then
|
||||
echo "**WARNING**:"
|
||||
echo "Running flake8 without virtual env may miss OpenStack HACKING detection"
|
||||
fi
|
||||
}
|
||||
|
||||
function run_pep8 {
|
||||
echo "Running flake8 ..."
|
||||
warn_on_flake8_without_venv
|
||||
bash -c "${wrapper} flake8"
|
||||
}
|
||||
|
||||
|
||||
TESTRTESTS="python setup.py testr"
|
||||
|
||||
if [ $never_venv -eq 0 ]
|
||||
then
|
||||
# Remove the virtual environment if --force used
|
||||
if [ $force -eq 1 ]; then
|
||||
echo "Cleaning virtualenv..."
|
||||
rm -rf ${venv}
|
||||
fi
|
||||
if [ $update -eq 1 ]; then
|
||||
echo "Updating virtualenv..."
|
||||
python tools/install_venv.py $installvenvopts
|
||||
fi
|
||||
if [ -e ${venv} ]; then
|
||||
wrapper="${with_venv}"
|
||||
else
|
||||
if [ $always_venv -eq 1 ]; then
|
||||
# Automatically install the virtualenv
|
||||
python tools/install_venv.py $installvenvopts
|
||||
wrapper="${with_venv}"
|
||||
else
|
||||
echo -e "No virtual environment found...create one? (Y/n) \c"
|
||||
read use_ve
|
||||
if [ "x$use_ve" = "xY" -o "x$use_ve" = "x" -o "x$use_ve" = "xy" ]; then
|
||||
# Install the virtualenv and run the test suite in it
|
||||
python tools/install_venv.py $installvenvopts
|
||||
wrapper=${with_venv}
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Delete old coverage data from previous runs
|
||||
if [ $coverage -eq 1 ]; then
|
||||
${wrapper} coverage erase
|
||||
fi
|
||||
|
||||
if [ $just_pep8 -eq 1 ]; then
|
||||
run_pep8
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ $just_pep8_changed -eq 1 ]; then
|
||||
# NOTE(gilliard) We want use flake8 to check the entirety of every file that has
|
||||
# a change in it. Unfortunately the --filenames argument to flake8 only accepts
|
||||
# file *names* and there are no files named (eg) "nova/compute/manager.py". The
|
||||
# --diff argument behaves surprisingly as well, because although you feed it a
|
||||
# diff, it actually checks the file on disk anyway.
|
||||
files=$(git diff --name-only HEAD~1 | tr '\n' ' ')
|
||||
echo "Running flake8 on ${files}"
|
||||
warn_on_flake8_without_venv
|
||||
bash -c "diff -u --from-file /dev/null ${files} | ${wrapper} flake8 --diff"
|
||||
exit
|
||||
fi
|
||||
|
||||
run_tests
|
||||
|
||||
# NOTE(sirp): we only want to run pep8 when we're running the full-test suite,
|
||||
# not when we're running tests individually. To handle this, we need to
|
||||
# distinguish between options (testropts), which begin with a '-', and
|
||||
# arguments (testrargs).
|
||||
if [ -z "$testrargs" ]; then
|
||||
if [ $no_pep8 -eq 0 ]; then
|
||||
run_pep8
|
||||
fi
|
||||
fi
|
58
setup.cfg
58
setup.cfg
|
@ -1,58 +0,0 @@
|
|||
[metadata]
|
||||
name = evoque
|
||||
summary = OpenStack Ticket
|
||||
description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.openstack.org/
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.4
|
||||
|
||||
[files]
|
||||
packages =
|
||||
evoque
|
||||
|
||||
[entry_points]
|
||||
console_scripts =
|
||||
evoque-api = evoque.cmd.api:main
|
||||
evoque-manage = evoque.cmd.manage:main
|
||||
evoque-engine = evoque.cmd.engine:main
|
||||
|
||||
evoque.workflow =
|
||||
spiff = evoque.engine.workflow.spiff:Workflow
|
||||
|
||||
oslo.config.opts =
|
||||
evoque = evoque.opts:list_opts
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
pbr.hooks.setup_hook
|
||||
|
||||
[build_sphinx]
|
||||
all_files = 1
|
||||
build-dir = doc/build
|
||||
source-dir = doc/source
|
||||
|
||||
[compile_catalog]
|
||||
directory = evoque/locale
|
||||
domain = evoque
|
||||
|
||||
[update_catalog]
|
||||
domain = evoque
|
||||
output_dir = sevoque/locale
|
||||
input_file = evoque/locale/evoque.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = evoque/locale/evoque.pot
|
29
setup.py
29
setup.py
|
@ -1,29 +0,0 @@
|
|||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
||||
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
||||
# setuptools if some other modules registered functions in `atexit`.
|
||||
# solution from: http://bugs.python.org/issue15881#msg170215
|
||||
try:
|
||||
import multiprocessing # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr>=1.3'],
|
||||
pbr=True)
|
|
@ -1,21 +0,0 @@
|
|||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
# Hacking already pins down pep8, pyflakes and flake8
|
||||
coverage>=3.6
|
||||
discover
|
||||
flake8<=2.4.1,>=2.2.4
|
||||
hacking<0.11,>=0.10.2
|
||||
mock>=1.2
|
||||
mox>=0.5.3
|
||||
mox3>=0.7.0
|
||||
oslosphinx>=2.5.0 # Apache-2.0
|
||||
oslotest>=1.10.0 # Apache-2.0
|
||||
os-testr>=0.1.0
|
||||
paramiko>=1.13.0
|
||||
PyMySQL>=0.6.2 # MIT License
|
||||
sphinx!=1.2.0,!=1.3b1,<1.3,>=1.1.2
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=1.4.0
|
|
@ -1,303 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# 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.
|
||||
|
||||
"""Display a subunit stream through a colorized unittest test runner."""
|
||||
|
||||
import heapq
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import subunit
|
||||
import testtools
|
||||
|
||||
|
||||
class _AnsiColorizer(object):
|
||||
"""A colorizer is an object that loosely wraps around a stream.
|
||||
|
||||
That allows callers to write text to the stream in a particular color.
|
||||
Colorizer classes must implement C{supported()} and C{write(text, color)}.
|
||||
"""
|
||||
_colors = dict(black=30, red=31, green=32, yellow=33,
|
||||
blue=34, magenta=35, cyan=36, white=37)
|
||||
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
@staticmethod
|
||||
def supported(stream=sys.stdout):
|
||||
"""Method that checks if the current terminal supports coloring.
|
||||
|
||||
Returns True or False.
|
||||
"""
|
||||
if not stream.isatty():
|
||||
return False # auto color only on TTYs
|
||||
try:
|
||||
import curses
|
||||
except ImportError:
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
try:
|
||||
return curses.tigetnum("colors") > 2
|
||||
except curses.error:
|
||||
curses.setupterm()
|
||||
return curses.tigetnum("colors") > 2
|
||||
except Exception:
|
||||
# guess false in case of error
|
||||
return False
|
||||
|
||||
def write(self, text, color):
|
||||
"""Write the given text to the stream in the given color.
|
||||
|
||||
@param text: Text to be written to the stream.
|
||||
|
||||
@param color: A string label for a color. e.g. 'red', 'white'.
|
||||
|
||||
"""
|
||||
color = self._colors[color]
|
||||
self.stream.write('\x1b[%s;1m%s\x1b[0m' % (color, text))
|
||||
|
||||
|
||||
class _Win32Colorizer(object):
|
||||
"""See _AnsiColorizer docstring."""
|
||||
def __init__(self, stream):
|
||||
import win32console
|
||||
red, green, blue, bold = (win32console.FOREGROUND_RED,
|
||||
win32console.FOREGROUND_GREEN,
|
||||
win32console.FOREGROUND_BLUE,
|
||||
win32console.FOREGROUND_INTENSITY)
|
||||
self.stream = stream
|
||||
self.screenBuffer = win32console.GetStdHandle(
|
||||
win32console.STD_OUT_HANDLE)
|
||||
self._colors = {
|
||||
'normal': red | green | blue,
|
||||
'red': red | bold,
|
||||
'green': green | bold,
|
||||
'blue': blue | bold,
|
||||
'yellow': red | green | bold,
|
||||
'magenta': red | blue | bold,
|
||||
'cyan': green | blue | bold,
|
||||
'white': red | green | blue | bold
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def supported(stream=sys.stdout):
|
||||
try:
|
||||
import win32console
|
||||
screenBuffer = win32console.GetStdHandle(
|
||||
win32console.STD_OUT_HANDLE)
|
||||
except ImportError:
|
||||
return False
|
||||
import pywintypes
|
||||
try:
|
||||
screenBuffer.SetConsoleTextAttribute(
|
||||
win32console.FOREGROUND_RED |
|
||||
win32console.FOREGROUND_GREEN |
|
||||
win32console.FOREGROUND_BLUE)
|
||||
except pywintypes.error:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def write(self, text, color):
|
||||
color = self._colors[color]
|
||||
self.screenBuffer.SetConsoleTextAttribute(color)
|
||||
self.stream.write(text)
|
||||
self.screenBuffer.SetConsoleTextAttribute(self._colors['normal'])
|
||||
|
||||
|
||||
class _NullColorizer(object):
|
||||
"""See _AnsiColorizer docstring."""
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
@staticmethod
|
||||
def supported(stream=sys.stdout):
|
||||
return True
|
||||
|
||||
def write(self, text, color):
|
||||
self.stream.write(text)
|
||||
|
||||
|
||||
def get_elapsed_time_color(elapsed_time):
|
||||
if elapsed_time > 1.0:
|
||||
return 'red'
|
||||
elif elapsed_time > 0.25:
|
||||
return 'yellow'
|
||||
else:
|
||||
return 'green'
|
||||
|
||||
|
||||
class SubunitTestResult(testtools.TestResult):
|
||||
def __init__(self, stream, descriptions, verbosity):
|
||||
super(SubunitTestResult, self).__init__()
|
||||
self.stream = stream
|
||||
self.showAll = verbosity > 1
|
||||
self.num_slow_tests = 10
|
||||
self.slow_tests = [] # this is a fixed-sized heap
|
||||
self.colorizer = None
|
||||
# NOTE(vish): reset stdout for the terminal check
|
||||
stdout = sys.stdout
|
||||
sys.stdout = sys.__stdout__
|
||||
for colorizer in [_Win32Colorizer, _AnsiColorizer, _NullColorizer]:
|
||||
if colorizer.supported():
|
||||
self.colorizer = colorizer(self.stream)
|
||||
break
|
||||
sys.stdout = stdout
|
||||
self.start_time = None
|
||||
self.last_time = {}
|
||||
self.results = {}
|
||||
self.last_written = None
|
||||
|
||||
def _writeElapsedTime(self, elapsed):
|
||||
color = get_elapsed_time_color(elapsed)
|
||||
self.colorizer.write(" %.2f" % elapsed, color)
|
||||
|
||||
def _addResult(self, test, *args):
|
||||
try:
|
||||
name = test.id()
|
||||
except AttributeError:
|
||||
name = 'Unknown.unknown'
|
||||
test_class, test_name = name.rsplit('.', 1)
|
||||
|
||||
elapsed = (self._now() - self.start_time).total_seconds()
|
||||
item = (elapsed, test_class, test_name)
|
||||
if len(self.slow_tests) >= self.num_slow_tests:
|
||||
heapq.heappushpop(self.slow_tests, item)
|
||||
else:
|
||||
heapq.heappush(self.slow_tests, item)
|
||||
|
||||
self.results.setdefault(test_class, [])
|
||||
self.results[test_class].append((test_name, elapsed) + args)
|
||||
self.last_time[test_class] = self._now()
|
||||
self.writeTests()
|
||||
|
||||
def _writeResult(self, test_name, elapsed, long_result, color,
|
||||
short_result, success):
|
||||
if self.showAll:
|
||||
self.stream.write(' %s' % str(test_name).ljust(66))
|
||||
self.colorizer.write(long_result, color)
|
||||
if success:
|
||||
self._writeElapsedTime(elapsed)
|
||||
self.stream.writeln()
|
||||
else:
|
||||
self.colorizer.write(short_result, color)
|
||||
|
||||
def addSuccess(self, test):
|
||||
super(SubunitTestResult, self).addSuccess(test)
|
||||
self._addResult(test, 'OK', 'green', '.', True)
|
||||
|
||||
def addFailure(self, test, err):
|
||||
if test.id() == 'process-returncode':
|
||||
return
|
||||
super(SubunitTestResult, self).addFailure(test, err)
|
||||
self._addResult(test, 'FAIL', 'red', 'F', False)
|
||||
|
||||
def addError(self, test, err):
|
||||
super(SubunitTestResult, self).addFailure(test, err)
|
||||
self._addResult(test, 'ERROR', 'red', 'E', False)
|
||||
|
||||
def addSkip(self, test, reason=None, details=None):
|
||||
super(SubunitTestResult, self).addSkip(test, reason, details)
|
||||
self._addResult(test, 'SKIP', 'blue', 'S', True)
|
||||
|
||||
def startTest(self, test):
|
||||
self.start_time = self._now()
|
||||
super(SubunitTestResult, self).startTest(test)
|
||||
|
||||
def writeTestCase(self, cls):
|
||||
if not self.results.get(cls):
|
||||
return
|
||||
if cls != self.last_written:
|
||||
self.colorizer.write(cls, 'white')
|
||||
self.stream.writeln()
|
||||
for result in self.results[cls]:
|
||||
self._writeResult(*result)
|
||||
del self.results[cls]
|
||||
self.stream.flush()
|
||||
self.last_written = cls
|
||||
|
||||
def writeTests(self):
|
||||
time = self.last_time.get(self.last_written, self._now())
|
||||
if not self.last_written or (self._now() - time).total_seconds() > 2.0:
|
||||
diff = 3.0
|
||||
while diff > 2.0:
|
||||
classes = self.results.keys()
|
||||
oldest = min(classes, key=lambda x: self.last_time[x])
|
||||
diff = (self._now() - self.last_time[oldest]).total_seconds()
|
||||
self.writeTestCase(oldest)
|
||||
else:
|
||||
self.writeTestCase(self.last_written)
|
||||
|
||||
def done(self):
|
||||
self.stopTestRun()
|
||||
|
||||
def stopTestRun(self):
|
||||
for cls in list(self.results.iterkeys()):
|
||||
self.writeTestCase(cls)
|
||||
self.stream.writeln()
|
||||
self.writeSlowTests()
|
||||
|
||||
def writeSlowTests(self):
|
||||
# Pare out 'fast' tests
|
||||
slow_tests = [item for item in self.slow_tests
|
||||
if get_elapsed_time_color(item[0]) != 'green']
|
||||
if slow_tests:
|
||||
slow_total_time = sum(item[0] for item in slow_tests)
|
||||
slow = ("Slowest %i tests took %.2f secs:"
|
||||
% (len(slow_tests), slow_total_time))
|
||||
self.colorizer.write(slow, 'yellow')
|
||||
self.stream.writeln()
|
||||
last_cls = None
|
||||
# sort by name
|
||||
for elapsed, cls, name in sorted(slow_tests,
|
||||
key=lambda x: x[1] + x[2]):
|
||||
if cls != last_cls:
|
||||
self.colorizer.write(cls, 'white')
|
||||
self.stream.writeln()
|
||||
last_cls = cls
|
||||
self.stream.write(' %s' % str(name).ljust(68))
|
||||
self._writeElapsedTime(elapsed)
|
||||
self.stream.writeln()
|
||||
|
||||
def printErrors(self):
|
||||
if self.showAll:
|
||||
self.stream.writeln()
|
||||
self.printErrorList('ERROR', self.errors)
|
||||
self.printErrorList('FAIL', self.failures)
|
||||
|
||||
def printErrorList(self, flavor, errors):
|
||||
for test, err in errors:
|
||||
self.colorizer.write("=" * 70, 'red')
|
||||
self.stream.writeln()
|
||||
self.colorizer.write(flavor, 'red')
|
||||
self.stream.writeln(": %s" % test.id())
|
||||
self.colorizer.write("-" * 70, 'red')
|
||||
self.stream.writeln()
|
||||
self.stream.writeln("%s" % err)
|
||||
|
||||
|
||||
test = subunit.ProtocolTestCase(sys.stdin, passthrough=None)
|
||||
|
||||
if sys.version_info[0:2] <= (2, 6):
|
||||
runner = unittest.TextTestRunner(verbosity=2)
|
||||
else:
|
||||
runner = unittest.TextTestRunner(
|
||||
verbosity=2, resultclass=SubunitTestResult)
|
||||
|
||||
if runner.run(test).wasSuccessful():
|
||||
exit_code = 0
|
||||
else:
|
||||
exit_code = 1
|
||||
sys.exit(exit_code)
|
|
@ -1,66 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""
|
||||
Installation script for Evoque's development virtualenv
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import install_venv_common as install_venv # noqa
|
||||
|
||||
|
||||
def print_help():
|
||||
help = """
|
||||
Evoque development environment setup is complete.
|
||||
|
||||
Evoque development uses virtualenv to track and manage Python dependencies
|
||||
while in development and testing.
|
||||
|
||||
To activate the Evoque virtualenv for the extent of your current shell session
|
||||
you can run:
|
||||
|
||||
$ source .venv/bin/activate
|
||||
|
||||
Or, if you prefer, you can run commands in the virtualenv on a case by case
|
||||
basis by running:
|
||||
|
||||
$ tools/with_venv.sh <your command>
|
||||
|
||||
Also, make test will automatically use the virtualenv.
|
||||
"""
|
||||
print(help)
|
||||
|
||||
|
||||
def main(argv):
|
||||
root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
||||
venv = os.path.join(root, '.venv')
|
||||
pip_requires = os.path.join(root, 'requirements.txt')
|
||||
test_requires = os.path.join(root, 'test-requirements.txt')
|
||||
py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1])
|
||||
project = 'Evoque'
|
||||
install = install_venv.InstallVenv(root, venv, pip_requires, test_requires,
|
||||
py_version, project)
|
||||
options = install.parse_args(argv)
|
||||
install.check_python_version()
|
||||
install.check_dependencies()
|
||||
install.create_virtualenv(no_site_packages=options.no_site_packages)
|
||||
install.install_dependencies()
|
||||
install.run_command([os.path.join(venv, 'bin/python'),
|
||||
'setup.py', 'develop'])
|
||||
print_help()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
|
@ -1,169 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Provides methods needed by installation script for OpenStack development
|
||||
virtual environments.
|
||||
|
||||
Since this script is used to bootstrap a virtualenv from the system's Python
|
||||
environment, it should be kept strictly compatible with Python 2.6.
|
||||
|
||||
Synced in from openstack-common
|
||||
"""
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import optparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
class InstallVenv(object):
|
||||
|
||||
def __init__(self, root, venv, requirements,
|
||||
test_requirements, py_version,
|
||||
project):
|
||||
self.root = root
|
||||
self.venv = venv
|
||||
self.requirements = requirements
|
||||
self.test_requirements = test_requirements
|
||||
self.py_version = py_version
|
||||
self.project = project
|
||||
|
||||
def die(self, message, *args):
|
||||
print(message % args, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def check_python_version(self):
|
||||
if sys.version_info < (2, 6):
|
||||
self.die("Need Python Version >= 2.6")
|
||||
|
||||
def run_command_with_code(self, cmd, redirect_output=True,
|
||||
check_exit_code=True):
|
||||
"""Runs a command in an out-of-process shell.
|
||||
|
||||
Returns the output of that command. Working directory is self.root.
|
||||
"""
|
||||
if redirect_output:
|
||||
stdout = subprocess.PIPE
|
||||
else:
|
||||
stdout = None
|
||||
|
||||
proc = subprocess.Popen(cmd, cwd=self.root, stdout=stdout)
|
||||
output = proc.communicate()[0]
|
||||
if check_exit_code and proc.returncode != 0:
|
||||
self.die('Command "%s" failed.\n%s', ' '.join(cmd), output)
|
||||
return (output, proc.returncode)
|
||||
|
||||
def run_command(self, cmd, redirect_output=True, check_exit_code=True):
|
||||
return self.run_command_with_code(cmd, redirect_output,
|
||||
check_exit_code)[0]
|
||||
|
||||
def get_distro(self):
|
||||
if (os.path.exists('/etc/fedora-release') or
|
||||
os.path.exists('/etc/redhat-release')):
|
||||
return Fedora(
|
||||
self.root, self.venv, self.requirements,
|
||||
self.test_requirements, self.py_version, self.project)
|
||||
else:
|
||||
return Distro(
|
||||
self.root, self.venv, self.requirements,
|
||||
self.test_requirements, self.py_version, self.project)
|
||||
|
||||
def check_dependencies(self):
|
||||
self.get_distro().install_virtualenv()
|
||||
|
||||
def create_virtualenv(self, no_site_packages=True):
|
||||
"""Creates the virtual environment and installs PIP.
|
||||
|
||||
Creates the virtual environment and installs PIP only into the
|
||||
virtual environment.
|
||||
"""
|
||||
if not os.path.isdir(self.venv):
|
||||
print('Creating venv...', end=' ')
|
||||
if no_site_packages:
|
||||
self.run_command(['virtualenv', '-q', '--no-site-packages',
|
||||
self.venv])
|
||||
else:
|
||||
self.run_command(['virtualenv', '-q', self.venv])
|
||||
print('done.')
|
||||
else:
|
||||
print("venv already exists...")
|
||||
pass
|
||||
|
||||
def pip_install(self, *args):
|
||||
self.run_command(['tools/with_venv.sh',
|
||||
'pip', 'install', '--upgrade'] + list(args),
|
||||
redirect_output=False)
|
||||
|
||||
def install_dependencies(self):
|
||||
print('Installing dependencies with pip (this can take a while)...')
|
||||
|
||||
# First things first, make sure our venv has the latest pip and
|
||||
# setuptools and pbr
|
||||
self.pip_install('pip>=1.4')
|
||||
self.pip_install('setuptools')
|
||||
self.pip_install('pbr')
|
||||
|
||||
self.pip_install('-r', self.requirements, '-r', self.test_requirements)
|
||||
|
||||
def parse_args(self, argv):
|
||||
"""Parses command-line arguments."""
|
||||
parser = optparse.OptionParser()
|
||||
parser.add_option('-n', '--no-site-packages',
|
||||
action='store_true',
|
||||
help="Do not inherit packages from global Python "
|
||||
"install.")
|
||||
return parser.parse_args(argv[1:])[0]
|
||||
|
||||
|
||||
class Distro(InstallVenv):
|
||||
|
||||
def check_cmd(self, cmd):
|
||||
return bool(self.run_command(['which', cmd],
|
||||
check_exit_code=False).strip())
|
||||
|
||||
def install_virtualenv(self):
|
||||
if self.check_cmd('virtualenv'):
|
||||
return
|
||||
|
||||
if self.check_cmd('easy_install'):
|
||||
print('Installing virtualenv via easy_install...', end=' ')
|
||||
if self.run_command(['easy_install', 'virtualenv']):
|
||||
print('Succeeded')
|
||||
return
|
||||
else:
|
||||
print('Failed')
|
||||
|
||||
self.die('ERROR: virtualenv not found.\n\n%s development'
|
||||
' requires virtualenv, please install it using your'
|
||||
' favorite package management tool' % self.project)
|
||||
|
||||
|
||||
class Fedora(Distro):
|
||||
"""This covers all Fedora-based distributions.
|
||||
|
||||
Includes: Fedora, RHEL, CentOS, Scientific Linux
|
||||
"""
|
||||
|
||||
def check_pkg(self, pkg):
|
||||
return self.run_command_with_code(['rpm', '-q', pkg],
|
||||
check_exit_code=False)[1] == 0
|
||||
|
||||
def install_virtualenv(self):
|
||||
if self.check_cmd('virtualenv'):
|
||||
return
|
||||
|
||||
if not self.check_pkg('python-virtualenv'):
|
||||
self.die("Please install 'python-virtualenv'.")
|
||||
|
||||
super(Fedora, self).install_virtualenv()
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
TOOLS_PATH=${TOOLS_PATH:-$(dirname $0)}
|
||||
VENV_PATH=${VENV_PATH:-${TOOLS_PATH}}
|
||||
VENV_DIR=${VENV_NAME:-/../.venv}
|
||||
TOOLS=${TOOLS_PATH}
|
||||
VENV=${VENV:-${VENV_PATH}/${VENV_DIR}}
|
||||
source ${VENV}/bin/activate && "$@"
|
38
tox.ini
38
tox.ini
|
@ -1,38 +0,0 @@
|
|||
[tox]
|
||||
minversion = 1.6
|
||||
envlist = py27,pep8
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args="{posargs}"
|
||||
whitelist_externals = bash
|
||||
passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY
|
||||
|
||||
[testenv:pep8]
|
||||
commands =
|
||||
flake8 {posargs}
|
||||
|
||||
[testenv:cover]
|
||||
setenv = VIRTUAL_ENV={envdir}
|
||||
commands = python setup.py testr --coverage --testr-args='^(?!.*test.*coverage).*$'
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:docs]
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[testenv:genconfig]
|
||||
commands = oslo-config-generator --config-file=evoque-config-generator.conf
|
||||
|
||||
[flake8]
|
||||
ignore = E711,E712,H404,H405
|
||||
exclude = .venv,.git,.tox,dist,doc,etc,*lib/python*,*egg,build
|
||||
|
||||
[hacking]
|
||||
import_exceptions = evoque.common.i18n
|
Loading…
Reference in New Issue