mirror of
https://github.com/resf/distro-tools.git
synced 2024-12-03 10:16:26 +00:00
Initial commit
This commit is contained in:
commit
6d955c9925
1
.bazelignore
Normal file
1
.bazelignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
35
.bazelrc
Normal file
35
.bazelrc
Normal file
@ -0,0 +1,35 @@
|
||||
# Java
|
||||
test --test_env='LC_ALL=en_US.UTF-8'
|
||||
test --test_env='LANG=en_US.UTF-8'
|
||||
test --jvmopt='-Dsun.jnu.encoding=UTF-8'
|
||||
test --jvmopt='-Dfile.encoding=UTF-8'
|
||||
build --test_env='LC_ALL=en_US.UTF-8'
|
||||
build --jvmopt='-Dsun.jnu.encoding=UTF-8'
|
||||
build --jvmopt='-Dfile.encoding=UTF-8'
|
||||
build --test_env='LANG=en_US.UTF-8'
|
||||
test --test_env=PATH
|
||||
|
||||
build --java_language_version=11
|
||||
test --java_language_version=11
|
||||
|
||||
# C++
|
||||
build --client_env=CC=clang
|
||||
build --copt=-DGRPC_BAZEL_BUILD
|
||||
build --cxxopt='-std=c++14'
|
||||
build --action_env=GRPC_BAZEL_RUNTIME=1
|
||||
build --define=use_fast_cpp_protos=true
|
||||
|
||||
# Just build tests when testing
|
||||
test --build_tests_only
|
||||
|
||||
build --incompatible_strict_action_env=true
|
||||
|
||||
# Minimize what is downloaded
|
||||
build:inmemory --experimental_inmemory_jdeps_files
|
||||
build:inmemory --experimental_inmemory_dotd_files
|
||||
|
||||
# Minimize what is downloaded
|
||||
build:toplevel --config=inmemory
|
||||
build:toplevel --experimental_remote_download_outputs=toplevel
|
||||
|
||||
build --stamp=true
|
1
.bazelversion
Normal file
1
.bazelversion
Normal file
@ -0,0 +1 @@
|
||||
5.4.0
|
1
.clang-format
Normal file
1
.clang-format
Normal file
@ -0,0 +1 @@
|
||||
BasedOnStyle: Google
|
1
.env
Normal file
1
.env
Normal file
@ -0,0 +1 @@
|
||||
DATABASE_URL="postgres://postgres:postgres@localhost:5432/apollo2development?sslmode=disable"
|
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
.idea
|
||||
.ijwb
|
||||
/.*.venv
|
||||
.venv
|
||||
*.pyc
|
||||
bazel-*
|
||||
__pycache__
|
||||
node_modules
|
4
.prettierrc
Normal file
4
.prettierrc
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true
|
||||
}
|
432
.pylintrc
Normal file
432
.pylintrc
Normal file
@ -0,0 +1,432 @@
|
||||
# This Pylint rcfile contains a best-effort configuration to uphold the
|
||||
# best-practices and style described in the Google Python style guide:
|
||||
# https://google.github.io/styleguide/pyguide.html
|
||||
#
|
||||
# Its canonical open-source location is:
|
||||
# https://google.github.io/styleguide/pylintrc
|
||||
|
||||
[MASTER]
|
||||
|
||||
# Files or directories to be skipped. They should be base names, not paths.
|
||||
ignore-paths=third_party
|
||||
|
||||
# Files or directories matching the regex patterns are skipped. The regex
|
||||
# matches against base names, not paths.
|
||||
ignore-patterns=^third_party/.*$,
|
||||
^generated/.*$
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=no
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=tortoise.contrib.pylint
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=4
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=abstract-method,
|
||||
apply-builtin,
|
||||
arguments-differ,
|
||||
attribute-defined-outside-init,
|
||||
backtick,
|
||||
bad-option-value,
|
||||
basestring-builtin,
|
||||
buffer-builtin,
|
||||
c-extension-no-member,
|
||||
consider-using-enumerate,
|
||||
cmp-builtin,
|
||||
cmp-method,
|
||||
coerce-builtin,
|
||||
coerce-method,
|
||||
delslice-method,
|
||||
div-method,
|
||||
duplicate-code,
|
||||
eq-without-hash,
|
||||
execfile-builtin,
|
||||
file-builtin,
|
||||
filter-builtin-not-iterating,
|
||||
fixme,
|
||||
getslice-method,
|
||||
global-statement,
|
||||
hex-method,
|
||||
idiv-method,
|
||||
implicit-str-concat,
|
||||
import-error,
|
||||
import-self,
|
||||
import-star-module-level,
|
||||
inconsistent-return-statements,
|
||||
input-builtin,
|
||||
intern-builtin,
|
||||
invalid-str-codec,
|
||||
locally-disabled,
|
||||
long-builtin,
|
||||
long-suffix,
|
||||
map-builtin-not-iterating,
|
||||
misplaced-comparison-constant,
|
||||
missing-function-docstring,
|
||||
missing-module-docstring,
|
||||
missing-class-docstring,
|
||||
metaclass-assignment,
|
||||
next-method-called,
|
||||
next-method-defined,
|
||||
no-absolute-import,
|
||||
no-else-break,
|
||||
no-else-continue,
|
||||
no-else-raise,
|
||||
no-else-return,
|
||||
no-init, # added
|
||||
no-member,
|
||||
no-name-in-module,
|
||||
no-self-use,
|
||||
nonzero-method,
|
||||
oct-method,
|
||||
old-division,
|
||||
old-ne-operator,
|
||||
old-octal-literal,
|
||||
old-raise-syntax,
|
||||
parameter-unpacking,
|
||||
print-statement,
|
||||
raising-string,
|
||||
range-builtin-not-iterating,
|
||||
raw_input-builtin,
|
||||
rdiv-method,
|
||||
reduce-builtin,
|
||||
relative-import,
|
||||
reload-builtin,
|
||||
round-builtin,
|
||||
setslice-method,
|
||||
signature-differs,
|
||||
standarderror-builtin,
|
||||
suppressed-message,
|
||||
sys-max-int,
|
||||
too-few-public-methods,
|
||||
too-many-ancestors,
|
||||
too-many-arguments,
|
||||
too-many-boolean-expressions,
|
||||
too-many-branches,
|
||||
too-many-instance-attributes,
|
||||
too-many-locals,
|
||||
too-many-nested-blocks,
|
||||
too-many-public-methods,
|
||||
too-many-return-statements,
|
||||
too-many-statements,
|
||||
trailing-newlines,
|
||||
unichr-builtin,
|
||||
unicode-builtin,
|
||||
unnecessary-pass,
|
||||
unpacking-in-except,
|
||||
useless-else-on-loop,
|
||||
useless-object-inheritance,
|
||||
useless-suppression,
|
||||
using-cmp-argument,
|
||||
wrong-import-order,
|
||||
xrange-builtin,
|
||||
zip-builtin-not-iterating,
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html. You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=no
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=main,_
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
|
||||
|
||||
# Regular expression matching correct function names
|
||||
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct variable names
|
||||
variable-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct constant names
|
||||
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||
|
||||
# Regular expression matching correct attribute names
|
||||
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct argument names
|
||||
argument-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct class attribute names
|
||||
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||
|
||||
# Regular expression matching correct inline iteration names
|
||||
inlinevar-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct class names
|
||||
class-rgx=^_?[A-Z][a-zA-Z0-9]*$
|
||||
|
||||
# Regular expression matching correct module names
|
||||
module-rgx=^(_?[a-z][a-z0-9_]*|__init__|__main__)$
|
||||
|
||||
# Regular expression matching correct method names
|
||||
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=10
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=160
|
||||
|
||||
# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
|
||||
# lines made too long by directives to pytype.
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=(?x)(
|
||||
^\s*(\#\ )?<?https?://\S+>?$|
|
||||
^\s*(from\s+\S+\s+)?import\s+.+$)
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=yes
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=99999
|
||||
|
||||
# String used as indentation unit. The internal Google style guide mandates 2
|
||||
# spaces. Google's externaly-published style guide says 4, consistent with
|
||||
# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google
|
||||
# projects (like TensorFlow).
|
||||
indent-string=' '
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=TODO
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=yes
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||
# not used).
|
||||
dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,_cb
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format
|
||||
logging-modules=logging,absl.logging,tensorflow.io.logging
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||
# install python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,
|
||||
TERMIOS,
|
||||
Bastion,
|
||||
rexec,
|
||||
sets
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant, absl
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls,
|
||||
class_
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=StandardError,
|
||||
Exception,
|
||||
BaseException
|
3
.style.yapf
Normal file
3
.style.yapf
Normal file
@ -0,0 +1,3 @@
|
||||
[style]
|
||||
based_on_style = facebook
|
||||
indent_width = 4
|
18
.vscode/settings.json
vendored
Normal file
18
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"python.analysis.extraPaths": [
|
||||
"bazel-bin",
|
||||
".venv/lib/python3.9/site-packages"
|
||||
],
|
||||
"protoc": {
|
||||
"options": ["--proto_path=third_party/googleapis"]
|
||||
},
|
||||
"python.linting.enabled": true,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.formatting.provider": "yapf",
|
||||
"editor.tabSize": 2,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.formatOnSave": true,
|
||||
"[python]": {
|
||||
"editor.tabSize": 4
|
||||
}
|
||||
}
|
2
.yapfignore
Normal file
2
.yapfignore
Normal file
@ -0,0 +1,2 @@
|
||||
generated/**/*.py
|
||||
third_party/**/*.py
|
79
BUILD.bazel
Normal file
79
BUILD.bazel
Normal file
@ -0,0 +1,79 @@
|
||||
load("@bazel_gazelle//:def.bzl", "gazelle", "gazelle_binary")
|
||||
load("@pypi//:requirements.bzl", "all_whl_requirements")
|
||||
load("@rules_python_gazelle_plugin//:def.bzl", "GAZELLE_PYTHON_RUNTIME_DEPS")
|
||||
load("@rules_python_gazelle_plugin//manifest:defs.bzl", "gazelle_python_manifest")
|
||||
load("@rules_python_gazelle_plugin//modules_mapping:def.bzl", "modules_mapping")
|
||||
load("@rules_python//python:defs.bzl", "py_runtime", "py_runtime_pair")
|
||||
load("@rules_python//python/pip_install:requirements.bzl", "compile_pip_requirements")
|
||||
load("@npm//:defs.bzl", "npm_link_all_packages")
|
||||
|
||||
# gazelle:prefix github.com/rocky-linux/peridot
|
||||
# gazelle:go_generate_proto false
|
||||
|
||||
# gazelle:python_library_naming_convention $package_name$_lib
|
||||
# gazelle:python_binary_naming_convention $package_name$
|
||||
# gazelle:map_kind py_binary py_binary @aspect_rules_py//py:defs.bzl
|
||||
# gazelle:map_kind py_library py_library @aspect_rules_py//py:defs.bzl
|
||||
|
||||
# gazelle:exclude *.venv
|
||||
# gazelle:exclude third_party/googleapis
|
||||
|
||||
# gazelle:resolve py grpc @pypi_grpcio//:pkg
|
||||
# gazelle:resolve py apollo.proto.v1.apollo_pb2_grpc //apollo/proto/v1:apollopb_py_pb2_grpc
|
||||
|
||||
gazelle_python_manifest(
|
||||
name = "gazelle_python_manifest",
|
||||
modules_mapping = ":modules_map",
|
||||
pip_repository_name = "pypi",
|
||||
requirements = "requirements_lock.txt",
|
||||
)
|
||||
|
||||
gazelle_binary(
|
||||
name = "gazelle_bin",
|
||||
languages = [
|
||||
"@bazel_gazelle//language/go",
|
||||
"@bazel_gazelle//language/proto",
|
||||
"@rules_python_gazelle_plugin//python",
|
||||
],
|
||||
)
|
||||
|
||||
gazelle(
|
||||
name = "gazelle",
|
||||
data = GAZELLE_PYTHON_RUNTIME_DEPS,
|
||||
gazelle = ":gazelle_bin",
|
||||
)
|
||||
|
||||
compile_pip_requirements(
|
||||
name = "requirements",
|
||||
extra_args = ["--allow-unsafe"],
|
||||
requirements_in = "requirements.txt",
|
||||
requirements_txt = "requirements_lock.txt",
|
||||
)
|
||||
|
||||
modules_mapping(
|
||||
name = "modules_map",
|
||||
wheels = all_whl_requirements,
|
||||
)
|
||||
|
||||
py_runtime(
|
||||
name = "container_py3_runtime",
|
||||
interpreter_path = "/usr/bin/python3",
|
||||
python_version = "PY3",
|
||||
)
|
||||
|
||||
py_runtime_pair(
|
||||
name = "container_py_runtime_pair",
|
||||
py2_runtime = None,
|
||||
py3_runtime = ":container_py3_runtime",
|
||||
)
|
||||
|
||||
toolchain(
|
||||
name = "container_py_toolchain",
|
||||
exec_compatible_with = [
|
||||
"@io_bazel_rules_docker//platforms:run_in_container",
|
||||
],
|
||||
toolchain = ":container_py_runtime_pair",
|
||||
toolchain_type = "@bazel_tools//tools/python:toolchain_type",
|
||||
)
|
||||
|
||||
npm_link_all_packages(name = "node_modules")
|
217
WORKSPACE
Normal file
217
WORKSPACE
Normal file
@ -0,0 +1,217 @@
|
||||
workspace(
|
||||
name = "depot",
|
||||
)
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Aspect Bazel Lib
|
||||
http_archive(
|
||||
name = "aspect_bazel_lib",
|
||||
sha256 = "79623d656aa23ad3fd4692ab99786c613cd36e49f5566469ed97bc9b4c655f03",
|
||||
strip_prefix = "bazel-lib-1.23.3",
|
||||
url = "https://github.com/aspect-build/bazel-lib/archive/refs/tags/v1.23.3.tar.gz",
|
||||
)
|
||||
|
||||
load("@aspect_bazel_lib//lib:repositories.bzl", "aspect_bazel_lib_dependencies", "register_copy_directory_toolchains", "register_copy_to_directory_toolchains")
|
||||
|
||||
aspect_bazel_lib_dependencies()
|
||||
|
||||
# Python
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "aspect_rules_py",
|
||||
sha256 = "66da30b09cf47ee40f2ae1c46346cc9a412940965d04899bd68d06a9d3380085",
|
||||
strip_prefix = "rules_py-0.1.0",
|
||||
url = "https://github.com/aspect-build/rules_py/archive/refs/tags/v0.1.0.tar.gz",
|
||||
)
|
||||
|
||||
# Fetches the rules_py dependencies.
|
||||
# If you want to have a different version of some dependency,
|
||||
# you should fetch it *before* calling this.
|
||||
# Alternatively, you can skip calling this function, so long as you've
|
||||
# already fetched all the dependencies.
|
||||
load("@aspect_rules_py//py:repositories.bzl", "rules_py_dependencies")
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
patch_args = ["-p1"],
|
||||
patch_cmds = ["""\
|
||||
cat >> python/BUILD.bazel <<EOF
|
||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||
bzl_library(
|
||||
name = "defs",
|
||||
srcs = [
|
||||
":bzl",
|
||||
"@bazel_tools//tools/python:srcs_version.bzl",
|
||||
"@bazel_tools//tools/python:utils.bzl",
|
||||
"@bazel_tools//tools/python:private/defs.bzl",
|
||||
"@bazel_tools//tools/python:toolchain.bzl",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
EOF
|
||||
"""],
|
||||
patches = ["//build/patches:0001-Fix-Quart-and-Hypercorn-failing-to-install-with-rule.patch"],
|
||||
sha256 = "8c15896f6686beb5c631a4459a3aa8392daccaab805ea899c9d14215074b60ef",
|
||||
strip_prefix = "rules_python-0.17.3",
|
||||
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.17.3.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python_gazelle_plugin",
|
||||
sha256 = "8c15896f6686beb5c631a4459a3aa8392daccaab805ea899c9d14215074b60ef",
|
||||
strip_prefix = "rules_python-0.17.3/gazelle",
|
||||
url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.17.3.tar.gz",
|
||||
)
|
||||
|
||||
rules_py_dependencies()
|
||||
|
||||
# Load the Python toolchain for rules_docker
|
||||
register_toolchains("//:container_py_toolchain")
|
||||
|
||||
load("@rules_python//python:repositories.bzl", "python_register_toolchains")
|
||||
|
||||
python_register_toolchains(
|
||||
name = "python_toolchain",
|
||||
python_version = "3.9",
|
||||
)
|
||||
|
||||
load("@rules_python//python:pip.bzl", "pip_parse")
|
||||
load("@python_toolchain//:defs.bzl", "interpreter")
|
||||
|
||||
pip_parse(
|
||||
name = "pypi",
|
||||
python_interpreter_target = interpreter,
|
||||
requirements_lock = "//:requirements_lock.txt",
|
||||
)
|
||||
|
||||
load("@pypi//:requirements.bzl", "install_deps")
|
||||
|
||||
install_deps()
|
||||
|
||||
# Go
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "56d8c5a5c91e1af73eca71a6fab2ced959b67c86d12ba37feedb0a2dfea441a6",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.37.0/rules_go-v0.37.0.zip",
|
||||
],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "bazel_gazelle",
|
||||
sha256 = "448e37e0dbf61d6fa8f00aaa12d191745e14f07c31cabfa731f0c8e8a4f41b97",
|
||||
urls = [
|
||||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
|
||||
"https://github.com/bazelbuild/bazel-gazelle/releases/download/v0.28.0/bazel-gazelle-v0.28.0.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains(version = "1.19.5")
|
||||
|
||||
gazelle_dependencies()
|
||||
|
||||
# Python Gazelle
|
||||
|
||||
load("@rules_python//gazelle:deps.bzl", _py_gazelle_deps = "gazelle_deps")
|
||||
|
||||
_py_gazelle_deps()
|
||||
|
||||
# Docker
|
||||
http_archive(
|
||||
name = "io_bazel_rules_docker",
|
||||
sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf",
|
||||
urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"],
|
||||
)
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_docker//repositories:repositories.bzl",
|
||||
container_repositories = "repositories",
|
||||
)
|
||||
|
||||
container_repositories()
|
||||
|
||||
load("@io_bazel_rules_docker//repositories:deps.bzl", container_deps = "deps")
|
||||
|
||||
container_deps()
|
||||
|
||||
# esbuild
|
||||
http_archive(
|
||||
name = "aspect_rules_esbuild",
|
||||
sha256 = "f05e9a53ae4b394ca45742ac35f7e658a8ba32cba14b5d531b79466ae86dc7f0",
|
||||
strip_prefix = "rules_esbuild-0.14.0",
|
||||
url = "https://github.com/aspect-build/rules_esbuild/archive/refs/tags/v0.14.0.tar.gz",
|
||||
)
|
||||
|
||||
######################
|
||||
# rules_esbuild setup #
|
||||
######################
|
||||
|
||||
# Fetches the rules_esbuild dependencies.
|
||||
# If you want to have a different version of some dependency,
|
||||
# you should fetch it *before* calling this.
|
||||
# Alternatively, you can skip calling this function, so long as you've
|
||||
# already fetched all the dependencies.
|
||||
load("@aspect_rules_esbuild//esbuild:dependencies.bzl", "rules_esbuild_dependencies")
|
||||
|
||||
rules_esbuild_dependencies()
|
||||
|
||||
# Fetch and register node, if you haven't already
|
||||
load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")
|
||||
|
||||
nodejs_register_toolchains(
|
||||
name = "node",
|
||||
node_version = "18.11.0",
|
||||
)
|
||||
|
||||
load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock")
|
||||
|
||||
npm_translate_lock(
|
||||
name = "npm",
|
||||
npmrc = "//:.npmrc",
|
||||
pnpm_lock = "//:pnpm-lock.yaml",
|
||||
verify_node_modules_ignored = "//:.bazelignore",
|
||||
)
|
||||
|
||||
load("@npm//:repositories.bzl", "npm_repositories")
|
||||
|
||||
npm_repositories()
|
||||
|
||||
# Register a toolchain containing esbuild npm package and native bindings
|
||||
load("@aspect_rules_esbuild//esbuild:repositories.bzl", "esbuild_register_toolchains")
|
||||
|
||||
esbuild_register_toolchains(
|
||||
name = "esbuild",
|
||||
esbuild_version = "0.16.7",
|
||||
)
|
||||
|
||||
register_copy_directory_toolchains()
|
||||
|
||||
register_copy_to_directory_toolchains()
|
||||
|
||||
# Copybara
|
||||
http_archive(
|
||||
name = "com_github_google_copybara",
|
||||
sha256 = "5ad1e07646025d69818cffd29a6b4869861242a0b4659570a222efe0a018c879",
|
||||
strip_prefix = "copybara-2fc63380448609af90b5c2a46fd0f8655377cba5",
|
||||
url = "https://github.com/google/copybara/archive/2fc63380448609af90b5c2a46fd0f8655377cba5.zip",
|
||||
)
|
||||
|
||||
load("@com_github_google_copybara//:repositories.bzl", "copybara_repositories")
|
||||
|
||||
copybara_repositories()
|
||||
|
||||
load("@com_github_google_copybara//:repositories.maven.bzl", "copybara_maven_repositories")
|
||||
|
||||
copybara_maven_repositories()
|
||||
|
||||
load("@com_github_google_copybara//:repositories.go.bzl", "copybara_go_repositories")
|
||||
|
||||
copybara_go_repositories()
|
0
apollo/BUILD.bazel
Normal file
0
apollo/BUILD.bazel
Normal file
18
apollo/README.md
Normal file
18
apollo/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# Apollo
|
||||
|
||||
Errata mirroring and publishing system
|
||||
|
||||
# Features
|
||||
|
||||
* Mirror advisories published by Red Hat
|
||||
* Supports EUS
|
||||
* Supports x86_64, aarch64, ppc64, ppc64le and s390x
|
||||
* Create custom advisories
|
||||
* CVE indexer and lifecycle tracker (Only Red Hat Security Data API for now)
|
||||
* Publish updateinfo to RPM repositories
|
||||
* Support for Peridot and Koji build systems
|
||||
|
||||
# Requirements
|
||||
* Redis
|
||||
* PostgreSQL
|
||||
* Gunicorn
|
22
apollo/cveindexer/BUILD.bazel
Normal file
22
apollo/cveindexer/BUILD.bazel
Normal file
@ -0,0 +1,22 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_library")
|
||||
|
||||
py_binary(
|
||||
name = "cveindexer",
|
||||
srcs = ["__main__.py"],
|
||||
imports = ["../.."],
|
||||
main = "__main__.py",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
":cveindexer_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_click//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
],
|
||||
)
|
||||
|
||||
py_library(
|
||||
name = "cveindexer_lib",
|
||||
srcs = ["temporal.py"],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
39
apollo/cveindexer/__main__.py
Normal file
39
apollo/cveindexer/__main__.py
Normal file
@ -0,0 +1,39 @@
|
||||
"""
|
||||
Apollo CVE Indexer
|
||||
|
||||
Only indexes Red Hat advisory CVEs for now.
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
from temporalio.worker import Worker
|
||||
import click
|
||||
|
||||
from common.database import Database
|
||||
from common.info import Info
|
||||
from common.temporal import Temporal
|
||||
|
||||
from apollo.cveindexer.temporal import TASK_QUEUE
|
||||
|
||||
|
||||
async def run():
|
||||
db = Database(True)
|
||||
await db.init(["apollo.db"])
|
||||
|
||||
temporal = Temporal(True)
|
||||
await temporal.connect()
|
||||
|
||||
worker = Worker(
|
||||
temporal.client, task_queue=TASK_QUEUE, workflows=[], activities=[]
|
||||
)
|
||||
|
||||
await worker.run()
|
||||
|
||||
|
||||
@click.command()
|
||||
def main():
|
||||
Info("apollocveindexer", "apollo2")
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1
apollo/cveindexer/temporal.py
Normal file
1
apollo/cveindexer/temporal.py
Normal file
@ -0,0 +1 @@
|
||||
TASK_QUEUE = "v2-cveindexer"
|
9
apollo/db/BUILD.bazel
Normal file
9
apollo/db/BUILD.bazel
Normal file
@ -0,0 +1,9 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
|
||||
py_library(
|
||||
name = "db_lib",
|
||||
srcs = ["__init__.py"],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = ["@pypi_tortoise_orm//:pkg"],
|
||||
)
|
356
apollo/db/__init__.py
Normal file
356
apollo/db/__init__.py
Normal file
@ -0,0 +1,356 @@
|
||||
import datetime
|
||||
|
||||
from tortoise.models import Model
|
||||
from tortoise import fields
|
||||
|
||||
|
||||
class Code(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
archived_at = fields.DatetimeField(null=True)
|
||||
code = fields.CharField(max_length=255, unique=True)
|
||||
description = fields.TextField()
|
||||
|
||||
supported_products: fields.ReverseRelation["SupportedProduct"]
|
||||
|
||||
class Meta:
|
||||
table = "codes"
|
||||
|
||||
|
||||
class SupportedProduct(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
eol_at = fields.DatetimeField(null=True)
|
||||
name = fields.CharField(max_length=255, unique=True)
|
||||
variant = fields.CharField(max_length=255)
|
||||
code = fields.ForeignKeyField(
|
||||
"models.Code",
|
||||
related_name="supported_products",
|
||||
)
|
||||
vendor = fields.TextField()
|
||||
|
||||
rh_mirrors: fields.ReverseRelation["SupportedProductsRhMirror"]
|
||||
advisory_packages: fields.ReverseRelation["AdvisoryPackage"]
|
||||
advisory_affected_products: fields.ReverseRelation["AdvisoryAffectedProduct"
|
||||
]
|
||||
|
||||
class Meta:
|
||||
table = "supported_products"
|
||||
|
||||
|
||||
class RedHatIndexState(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
last_indexed_at = fields.DatetimeField(null=True)
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_index_state"
|
||||
|
||||
|
||||
class RedHatAdvisory(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
red_hat_issued_at = fields.DatetimeField()
|
||||
name = fields.CharField(max_length=255, unique=True)
|
||||
synopsis = fields.TextField()
|
||||
description = fields.TextField()
|
||||
kind = fields.CharField(max_length=255)
|
||||
severity = fields.CharField(max_length=255)
|
||||
topic = fields.TextField()
|
||||
|
||||
packages: fields.ReverseRelation["RedHatAdvisoryPackage"]
|
||||
cves: fields.ReverseRelation["RedHatAdvisoryCVE"]
|
||||
bugzilla_tickets: fields.ReverseRelation["RedHatAdvisoryBugzillaBug"]
|
||||
affected_products: fields.ReverseRelation["RedHatAdvisoryAffectedProduct"]
|
||||
rpm_rh_overrides: fields.ReverseRelation["SupportedProductsRpmRhOverride"]
|
||||
rh_blocks: fields.ReverseRelation["SupportedProductsRhBlock"]
|
||||
published_advisories: fields.ReverseRelation["Advisory"]
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_advisories"
|
||||
|
||||
class PydanticMeta:
|
||||
exclude = ("rpm_rh_overrides", "rh_blocks", "published_advisories")
|
||||
|
||||
|
||||
class RedHatAdvisoryPackage(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="packages",
|
||||
)
|
||||
nevra = fields.TextField()
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_advisory_packages"
|
||||
unique_together = ("red_hat_advisory_id", "nevra")
|
||||
|
||||
|
||||
class RedHatAdvisoryCVE(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="cves",
|
||||
)
|
||||
cve = fields.TextField()
|
||||
cvss3_scoring_vector = fields.TextField(null=True)
|
||||
cvss3_base_score = fields.TextField(null=True)
|
||||
cwe = fields.TextField(null=True)
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_advisory_cves"
|
||||
unique_together = ("red_hat_advisory_id", "cve")
|
||||
|
||||
|
||||
class RedHatAdvisoryBugzillaBug(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="bugzilla_tickets",
|
||||
)
|
||||
bugzilla_bug_id = fields.TextField()
|
||||
description = fields.TextField(null=True)
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_advisory_bugzilla_bugs"
|
||||
unique_together = ("red_hat_advisory_id", "bugzilla_bug_id")
|
||||
|
||||
|
||||
class RedHatAdvisoryAffectedProduct(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="affected_products",
|
||||
)
|
||||
variant = fields.TextField()
|
||||
name = fields.TextField()
|
||||
major_version = fields.IntField()
|
||||
minor_version = fields.IntField(null=True)
|
||||
arch = fields.TextField()
|
||||
|
||||
class Meta:
|
||||
table = "red_hat_advisory_affected_products"
|
||||
unique_together = (
|
||||
"red_hat_advisory_id", "variant", "name", "major_version",
|
||||
"minor_version", "arch"
|
||||
)
|
||||
|
||||
|
||||
class User(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
archived_at = fields.DatetimeField(null=True)
|
||||
email = fields.CharField(max_length=255, unique=True)
|
||||
password = fields.CharField(max_length=255)
|
||||
name = fields.CharField(max_length=255)
|
||||
role = fields.CharField(max_length=255)
|
||||
|
||||
class Meta:
|
||||
table = "users"
|
||||
|
||||
class PydanticMeta:
|
||||
exclude = ("password", )
|
||||
|
||||
|
||||
class Settings(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
name = fields.CharField(max_length=255, unique=True)
|
||||
value = fields.TextField()
|
||||
|
||||
class Meta:
|
||||
table = "settings"
|
||||
|
||||
|
||||
class SupportedProductsRhMirror(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
supported_product = fields.ForeignKeyField(
|
||||
"models.SupportedProduct",
|
||||
related_name="rh_mirrors",
|
||||
)
|
||||
name = fields.CharField(max_length=255)
|
||||
match_variant = fields.CharField(max_length=255)
|
||||
match_major_version = fields.IntField()
|
||||
match_minor_version = fields.IntField(null=True)
|
||||
match_arch = fields.CharField(max_length=255)
|
||||
|
||||
rpm_repomds: fields.ReverseRelation["SupportedProductsRpmRepomd"]
|
||||
rpm_rh_overrides: fields.ReverseRelation["SupportedProductsRpmRhOverride"]
|
||||
rh_blocks: fields.ReverseRelation["SupportedProductsRhBlock"]
|
||||
advisory_packages: fields.ReverseRelation["AdvisoryPackage"]
|
||||
|
||||
class Meta:
|
||||
table = "supported_products_rh_mirrors"
|
||||
|
||||
|
||||
class SupportedProductsRpmRepomd(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
supported_products_rh_mirror = fields.ForeignKeyField(
|
||||
"models.SupportedProductsRhMirror",
|
||||
related_name="rpm_repomds",
|
||||
)
|
||||
production = fields.BooleanField()
|
||||
arch = fields.CharField(max_length=255)
|
||||
url = fields.TextField()
|
||||
debug_url = fields.TextField()
|
||||
source_url = fields.TextField()
|
||||
repo_name = fields.CharField(max_length=255)
|
||||
|
||||
class Meta:
|
||||
table = "supported_products_rpm_repomds"
|
||||
|
||||
|
||||
class SupportedProductsRpmRhOverride(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
supported_products_rh_mirror = fields.ForeignKeyField(
|
||||
"models.SupportedProductsRhMirror",
|
||||
related_name="rpm_rh_overrides",
|
||||
)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="rpm_rh_overrides",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
table = "supported_products_rpm_rh_overrides"
|
||||
|
||||
|
||||
class SupportedProductsRhBlock(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
supported_products_rh_mirror = fields.ForeignKeyField(
|
||||
"models.SupportedProductsRhMirror",
|
||||
related_name="rh_blocks",
|
||||
)
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="rh_blocks",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
table = "supported_products_rh_blocks"
|
||||
|
||||
|
||||
class Advisory(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
created_at = fields.DatetimeField(auto_now_add=True)
|
||||
updated_at = fields.DatetimeField(auto_now=True, null=True)
|
||||
published_at = fields.DatetimeField()
|
||||
name = fields.CharField(max_length=255, unique=True)
|
||||
synopsis = fields.TextField()
|
||||
description = fields.TextField()
|
||||
kind = fields.CharField(max_length=255)
|
||||
severity = fields.CharField(max_length=255)
|
||||
topic = fields.TextField()
|
||||
red_hat_advisory = fields.ForeignKeyField(
|
||||
"models.RedHatAdvisory",
|
||||
related_name="published_advisories",
|
||||
)
|
||||
|
||||
packages: fields.ReverseRelation["AdvisoryPackage"]
|
||||
cves: fields.ReverseRelation["AdvisoryCVE"]
|
||||
fixes: fields.ReverseRelation["AdvisoryFix"]
|
||||
affected_products: fields.ReverseRelation["AdvisoryAffectedProduct"]
|
||||
|
||||
class Meta:
|
||||
table = "advisories"
|
||||
|
||||
|
||||
class AdvisoryPackage(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
advisory = fields.ForeignKeyField(
|
||||
"models.Advisory",
|
||||
related_name="packages",
|
||||
)
|
||||
nevra = fields.TextField()
|
||||
checksum = fields.TextField()
|
||||
checksum_type = fields.CharField(max_length=255)
|
||||
module_context = fields.TextField(null=True)
|
||||
module_name = fields.TextField(null=True)
|
||||
module_stream = fields.TextField(null=True)
|
||||
module_version = fields.TextField(null=True)
|
||||
repo_name = fields.TextField()
|
||||
package_name = fields.TextField()
|
||||
product_name = fields.TextField()
|
||||
supported_products_rh_mirror = fields.ForeignKeyField(
|
||||
"models.SupportedProductsRhMirror",
|
||||
related_name="advisory_packages",
|
||||
)
|
||||
supported_product = fields.ForeignKeyField(
|
||||
"models.SupportedProduct",
|
||||
related_name="advisory_packages",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
table = "advisory_packages"
|
||||
unique_together = ("advisory_id", "nevra")
|
||||
|
||||
|
||||
class AdvisoryCVE(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
advisory = fields.ForeignKeyField(
|
||||
"models.Advisory",
|
||||
related_name="cves",
|
||||
)
|
||||
cve = fields.TextField()
|
||||
cvss3_scoring_vector = fields.TextField(null=True)
|
||||
cvss3_base_score = fields.TextField(null=True)
|
||||
cwe = fields.TextField(null=True)
|
||||
|
||||
class Meta:
|
||||
table = "advisory_cves"
|
||||
unique_together = ("advisory_id", "cve")
|
||||
|
||||
|
||||
class AdvisoryFix(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
advisory = fields.ForeignKeyField(
|
||||
"models.Advisory",
|
||||
related_name="fixes",
|
||||
)
|
||||
ticket_id = fields.TextField()
|
||||
source = fields.TextField()
|
||||
description = fields.TextField(null=True)
|
||||
|
||||
class Meta:
|
||||
table = "advisory_fixes"
|
||||
unique_together = ("advisory_id", "ticket_id")
|
||||
|
||||
|
||||
class AdvisoryAffectedProduct(Model):
|
||||
id = fields.BigIntField(pk=True)
|
||||
advisory = fields.ForeignKeyField(
|
||||
"models.Advisory",
|
||||
related_name="affected_products",
|
||||
)
|
||||
variant = fields.TextField()
|
||||
name = fields.TextField()
|
||||
major_version = fields.IntField()
|
||||
minor_version = fields.IntField(null=True)
|
||||
arch = fields.TextField()
|
||||
supported_product = fields.ForeignKeyField(
|
||||
"models.SupportedProduct",
|
||||
related_name="advisory_affected_products",
|
||||
)
|
||||
|
||||
class Meta:
|
||||
table = "advisory_affected_products"
|
||||
unique_together = (
|
||||
"advisory_id",
|
||||
"variant",
|
||||
"name",
|
||||
"major_version",
|
||||
"minor_version",
|
||||
"arch",
|
||||
)
|
13
apollo/db/serialize/BUILD.bazel
Normal file
13
apollo/db/serialize/BUILD.bazel
Normal file
@ -0,0 +1,13 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
|
||||
py_library(
|
||||
name = "serialize_lib",
|
||||
srcs = ["__init__.py"],
|
||||
imports = ["../../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//apollo/db:db_lib",
|
||||
"@pypi_pydantic//:pkg",
|
||||
"@pypi_tortoise_orm//:pkg",
|
||||
],
|
||||
)
|
102
apollo/db/serialize/__init__.py
Normal file
102
apollo/db/serialize/__init__.py
Normal file
@ -0,0 +1,102 @@
|
||||
import datetime
|
||||
from typing import Optional
|
||||
|
||||
from tortoise.contrib.pydantic import pydantic_model_creator, pydantic_queryset_creator
|
||||
from pydantic import BaseModel
|
||||
|
||||
from apollo import db
|
||||
|
||||
RedHatAdvisoryCVE_Pydantic = pydantic_model_creator(
|
||||
db.RedHatAdvisoryCVE,
|
||||
name="RedHatAdvisoryCVE",
|
||||
)
|
||||
RedHatAdvisoryBugzillaBug_Pydantic = pydantic_model_creator(
|
||||
db.RedHatAdvisoryBugzillaBug,
|
||||
name="RedHatAdvisoryBugzillaBug",
|
||||
)
|
||||
RedHatAdvisoryAffectedProduct_Pydantic = pydantic_model_creator(
|
||||
db.RedHatAdvisoryAffectedProduct,
|
||||
name="RedHatAdvisoryAffectedProduct",
|
||||
)
|
||||
RedHatAdvisoryPackage_Pydantic = pydantic_model_creator(
|
||||
db.RedHatAdvisoryPackage,
|
||||
name="RedHatAdvisoryPackage",
|
||||
)
|
||||
RedHatAdvisory_Pydantic = pydantic_model_creator(
|
||||
db.RedHatAdvisory,
|
||||
name="RedHatAdvisory",
|
||||
)
|
||||
|
||||
AdvisoryCVE_Pydantic = pydantic_model_creator(
|
||||
db.AdvisoryCVE,
|
||||
name="AdvisoryCVE",
|
||||
)
|
||||
AdvisoryFix_Pydantic = pydantic_model_creator(
|
||||
db.AdvisoryFix,
|
||||
name="AdvisoryFix",
|
||||
)
|
||||
AdvisoryAffectedProduct_Pydantic = pydantic_model_creator(
|
||||
db.AdvisoryAffectedProduct,
|
||||
name="AdvisoryAffectedProduct",
|
||||
)
|
||||
AdvisoryPackage_Pydantic = pydantic_model_creator(
|
||||
db.AdvisoryPackage,
|
||||
name="AdvisoryPackage",
|
||||
)
|
||||
Advisory_Pydantic = pydantic_model_creator(
|
||||
db.Advisory,
|
||||
name="Advisory",
|
||||
exclude=(
|
||||
"red_hat_advisory",
|
||||
"packages.supported_product",
|
||||
"packages.supported_product_id",
|
||||
"packages.supported_products_rh_mirror",
|
||||
"packages.supported_products_rh_mirror_id",
|
||||
"cves.advisory",
|
||||
"cves.advisory_id",
|
||||
"fixes.advisory",
|
||||
"fixes.advisory_id",
|
||||
"affected_products.advisory",
|
||||
"affected_products.advisory_id",
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Legacy API models
|
||||
# pylint: disable=invalid-name
|
||||
class Advisory_Pydantic_V2_Fix(BaseModel):
|
||||
ticket: str
|
||||
sourceBy: str
|
||||
sourceLink: str
|
||||
description: str
|
||||
|
||||
|
||||
class Advisory_Pydantic_V2_CVE(BaseModel):
|
||||
name: str
|
||||
sourceBy: str
|
||||
sourceLink: str
|
||||
cvss3ScoringVector: str
|
||||
cvss3BaseScore: str
|
||||
cwe: str
|
||||
|
||||
|
||||
class Advisory_Pydantic_V2(BaseModel):
|
||||
type: str
|
||||
shortCode: str
|
||||
name: str
|
||||
synopsis: str
|
||||
severity: str
|
||||
topic: str
|
||||
description: str
|
||||
solution: Optional[str]
|
||||
affectedProducts: list[str]
|
||||
fixes: list[Advisory_Pydantic_V2_Fix]
|
||||
cves: list[Advisory_Pydantic_V2_CVE]
|
||||
references: list[str]
|
||||
publishedAt: datetime.datetime
|
||||
rpms: dict[str, list[str]]
|
||||
rebootSuggested: bool
|
||||
buildReferences: list[str]
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
272
apollo/migrations/20230128201227_init.sql
Normal file
272
apollo/migrations/20230128201227_init.sql
Normal file
@ -0,0 +1,272 @@
|
||||
-- migrate:up
|
||||
create table codes (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
archived_at timestamp,
|
||||
code text not null,
|
||||
description text not null
|
||||
);
|
||||
|
||||
create table supported_products (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
eol_at timestamptz,
|
||||
variant text not null,
|
||||
name text not null unique,
|
||||
vendor text not null,
|
||||
code_id bigint references codes(id)
|
||||
);
|
||||
create index supported_products_eol_atx on supported_products(eol_at);
|
||||
create index supported_products_variantx on supported_products(variant);
|
||||
create index supported_products_namex on supported_products(name);
|
||||
|
||||
create table red_hat_index_state (
|
||||
id bigserial primary key,
|
||||
last_indexed_at timestamptz
|
||||
);
|
||||
|
||||
create table red_hat_advisories (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
red_hat_issued_at timestamptz not null,
|
||||
name text not null unique,
|
||||
synopsis text not null,
|
||||
description text not null,
|
||||
kind text not null,
|
||||
severity text not null,
|
||||
topic text not null
|
||||
);
|
||||
create index red_hat_advisories_red_hat_issued_atx on red_hat_advisories(red_hat_issued_at);
|
||||
create index red_hat_advisories_namex on red_hat_advisories(name);
|
||||
create index red_hat_advisories_synopsisx on red_hat_advisories(synopsis);
|
||||
create index red_hat_advisories_kindx on red_hat_advisories(kind);
|
||||
create index red_hat_advisories_severityx on red_hat_advisories(severity);
|
||||
|
||||
create table red_hat_advisory_packages (
|
||||
id bigserial primary key,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade,
|
||||
nevra text not null,
|
||||
|
||||
unique (red_hat_advisory_id, nevra)
|
||||
);
|
||||
create index red_hat_advisory_packages_nevrax on red_hat_advisory_packages(nevra);
|
||||
|
||||
create table red_hat_advisory_cves (
|
||||
id bigserial primary key,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade,
|
||||
cve text not null,
|
||||
cvss3_scoring_vector text,
|
||||
cvss3_base_score text,
|
||||
cwe text,
|
||||
|
||||
unique (red_hat_advisory_id, cve)
|
||||
);
|
||||
create index red_hat_advisory_cvex on red_hat_advisory_cves(cve);
|
||||
|
||||
create table red_hat_advisory_bugzilla_bugs (
|
||||
id bigserial primary key,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade,
|
||||
bugzilla_bug_id text not null,
|
||||
description text not null,
|
||||
|
||||
unique (red_hat_advisory_id, bugzilla_bug_id)
|
||||
);
|
||||
create index red_hat_advisory_bugzilla_bugs_bugzilla_bug_idx on red_hat_advisory_bugzilla_bugs(bugzilla_bug_id);
|
||||
|
||||
create table red_hat_advisory_affected_products (
|
||||
id bigserial primary key,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade,
|
||||
variant text not null,
|
||||
name text not null,
|
||||
major_version numeric not null,
|
||||
minor_version numeric,
|
||||
arch text not null,
|
||||
|
||||
unique (red_hat_advisory_id, variant, name, major_version, minor_version, arch)
|
||||
);
|
||||
create index red_hat_advisory_affected_products_variantx on red_hat_advisory_affected_products(variant);
|
||||
create index red_hat_advisory_affected_products_namex on red_hat_advisory_affected_products(name);
|
||||
create index red_hat_advisory_affected_products_major_versionx on red_hat_advisory_affected_products(major_version);
|
||||
create index red_hat_advisory_affected_products_minor_versionx on red_hat_advisory_affected_products(minor_version);
|
||||
create index red_hat_advisory_affected_products_archx on red_hat_advisory_affected_products(arch);
|
||||
create unique index red_hat_advisory_affected_products_variant_namex on red_hat_advisory_affected_products(red_hat_advisory_id, variant, name, major_version, minor_version, arch) where minor_version is not null;
|
||||
create unique index red_hat_advisory_affected_products_variant_namenx on red_hat_advisory_affected_products(red_hat_advisory_id, variant, name, major_version, minor_version, arch) where minor_version is null;
|
||||
|
||||
insert into red_hat_index_state (last_indexed_at) values ('2019-05-06');
|
||||
|
||||
create table users (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
archived_at timestamp,
|
||||
email text not null unique,
|
||||
password text not null,
|
||||
name text not null,
|
||||
role text not null
|
||||
);
|
||||
|
||||
create table settings (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
name text not null unique,
|
||||
value text not null
|
||||
);
|
||||
create index settings_namex on settings(name);
|
||||
|
||||
create table events (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
archived_at timestamp,
|
||||
description text not null,
|
||||
user_id bigint references users(id) on delete set null
|
||||
);
|
||||
|
||||
create table supported_products_rh_mirrors (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
supported_product_id bigint references supported_products(id) on delete cascade,
|
||||
name text not null,
|
||||
match_variant text not null,
|
||||
match_major_version numeric not null,
|
||||
match_minor_version numeric,
|
||||
match_arch text not null
|
||||
);
|
||||
create index supported_products_rh_mirrors_supported_product_idx on supported_products_rh_mirrors(supported_product_id);
|
||||
create index supported_products_rh_mirrors_match_variant_idx on supported_products_rh_mirrors(match_variant);
|
||||
create index supported_products_rh_mirrors_match_major_version_idx on supported_products_rh_mirrors(match_major_version);
|
||||
create index supported_products_rh_mirrors_match_minor_version_idx on supported_products_rh_mirrors(match_minor_version);
|
||||
create index supported_products_rh_mirrors_match_arch_idx on supported_products_rh_mirrors(match_arch);
|
||||
|
||||
create table supported_products_rpm_repomds (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
supported_products_rh_mirror_id bigint references supported_products_rh_mirrors(id) on delete cascade,
|
||||
production boolean not null,
|
||||
arch text not null,
|
||||
url text not null,
|
||||
debug_url text not null,
|
||||
source_url text not null,
|
||||
repo_name text not null
|
||||
);
|
||||
create index supported_products_rpm_repomds_supporteds_rh_mirror_idx on supported_products_rpm_repomds(supported_products_rh_mirror_id);
|
||||
create index supported_products_rpm_repomds_production_idx on supported_products_rpm_repomds(production);
|
||||
create index supported_products_rpm_repomds_arch_idx on supported_products_rpm_repomds(arch);
|
||||
|
||||
create table supported_products_rpm_rh_overrides (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
supported_products_rh_mirror_id bigint references supported_products_rh_mirrors(id) on delete cascade,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade
|
||||
);
|
||||
create index supported_products_rpm_rh_overrides_supported_products_rh_mirror_idx on supported_products_rpm_rh_overrides(supported_products_rh_mirror_id);
|
||||
create index supported_products_rpm_rh_overrides_red_hat_advisory_idx on supported_products_rpm_rh_overrides(red_hat_advisory_id);
|
||||
|
||||
create table supported_products_rh_blocks (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
supported_products_rh_mirror_id bigint references supported_products_rh_mirrors(id) on delete cascade,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade,
|
||||
|
||||
unique (supported_products_rh_mirror_id, red_hat_advisory_id)
|
||||
);
|
||||
create index supported_products_rh_blocks_supported_products_rh_mirror_idx on supported_products_rh_blocks(supported_products_rh_mirror_id);
|
||||
create index supported_products_rh_blocks_red_hat_advisory_idx on supported_products_rh_blocks(red_hat_advisory_id);
|
||||
|
||||
create table advisories (
|
||||
id bigserial primary key,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz,
|
||||
published_at timestamptz,
|
||||
name text not null unique,
|
||||
synopsis text not null,
|
||||
description text not null,
|
||||
kind text not null,
|
||||
severity text not null,
|
||||
topic text not null,
|
||||
red_hat_advisory_id bigint references red_hat_advisories(id) on delete cascade
|
||||
);
|
||||
create index advisories_published_atx on advisories(published_at);
|
||||
create index advisories_namex on advisories(name);
|
||||
create index advisories_synopsisx on advisories(synopsis);
|
||||
create index advisories_kindx on advisories(kind);
|
||||
create index advisories_severityx on advisories(severity);
|
||||
create index advisories_red_hat_advisory_id on advisories(red_hat_advisory_id);
|
||||
|
||||
create table advisory_packages (
|
||||
id bigserial primary key,
|
||||
advisory_id bigint references advisories(id) on delete cascade,
|
||||
nevra text not null,
|
||||
checksum text not null,
|
||||
checksum_type text not null,
|
||||
module_context text,
|
||||
module_name text,
|
||||
module_stream text,
|
||||
module_version text,
|
||||
repo_name text not null,
|
||||
package_name text not null,
|
||||
supported_products_rh_mirror_id bigint references supported_products_rh_mirrors(id) on delete cascade,
|
||||
supported_product_id bigint references supported_products(id) on delete cascade,
|
||||
product_name text not null,
|
||||
|
||||
unique (advisory_id, nevra, repo_name, supported_products_rh_mirror_id)
|
||||
);
|
||||
create index advisory_packages_advisory_id on advisory_packages(advisory_id);
|
||||
create index advisory_packages_nevrax on advisory_packages(nevra);
|
||||
create index advisory_packages_checksumx on advisory_packages(checksum);
|
||||
create index advisory_packages_supported_products_rh_mirror_idx on advisory_packages(supported_products_rh_mirror_id);
|
||||
create index advisory_packages_supported_product_idx on advisory_packages(supported_product_id);
|
||||
create index advisory_packages_product_name_idx on advisory_packages(product_name);
|
||||
|
||||
create table advisory_cves (
|
||||
id bigserial primary key,
|
||||
advisory_id bigint references advisories(id) on delete cascade,
|
||||
cve text not null,
|
||||
cvss3_scoring_vector text,
|
||||
cvss3_base_score text,
|
||||
cwe text,
|
||||
|
||||
unique (advisory_id, cve)
|
||||
);
|
||||
create index advisory_cvex on advisory_cves(cve);
|
||||
|
||||
create table advisory_fixes (
|
||||
id bigserial primary key,
|
||||
advisory_id bigint references advisories(id) on delete cascade,
|
||||
ticket_id text not null,
|
||||
source text not null,
|
||||
description text,
|
||||
|
||||
unique (advisory_id, ticket_id)
|
||||
);
|
||||
create index advisory_fixes_advisory_id on advisory_fixes(advisory_id);
|
||||
create index advisory_fixes_ticket_id on advisory_fixes(ticket_id);
|
||||
|
||||
create table advisory_affected_products (
|
||||
id bigserial primary key,
|
||||
advisory_id bigint references advisories(id) on delete cascade,
|
||||
variant text not null,
|
||||
name text not null,
|
||||
major_version numeric not null,
|
||||
minor_version numeric,
|
||||
arch text not null,
|
||||
supported_product_id bigint references supported_products(id) on delete cascade,
|
||||
|
||||
unique (advisory_id, name)
|
||||
);
|
||||
create index advisory_affected_products_variantx on advisory_affected_products(variant);
|
||||
create index advisory_affected_products_namex on advisory_affected_products(name);
|
||||
create index advisory_affected_products_major_versionx on advisory_affected_products(major_version);
|
||||
create index advisory_affected_products_minor_versionx on advisory_affected_products(minor_version);
|
||||
create index advisory_affected_products_archx on advisory_affected_products(arch);
|
||||
create index advisory_affected_products_supported_product_idx on advisory_affected_products(supported_product_id);
|
||||
|
||||
-- migrate:down
|
15
apollo/rherrata/BUILD.bazel
Normal file
15
apollo/rherrata/BUILD.bazel
Normal file
@ -0,0 +1,15 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
|
||||
# gazelle:exclude example.py
|
||||
|
||||
py_library(
|
||||
name = "rherrata_lib",
|
||||
srcs = ["__init__.py"],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"@pypi_aiohttp//:pkg",
|
||||
"@pypi_dataclass_wizard//:pkg",
|
||||
"@pypi_yarl//:pkg",
|
||||
],
|
||||
)
|
195
apollo/rherrata/__init__.py
Normal file
195
apollo/rherrata/__init__.py
Normal file
@ -0,0 +1,195 @@
|
||||
# pylint: disable=invalid-name
|
||||
"""
|
||||
This module provides a Python interface to the Red Hat Errata API.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from dataclasses import dataclass
|
||||
from urllib.parse import quote
|
||||
|
||||
import aiohttp
|
||||
from dataclass_wizard import JSONWizard
|
||||
from yarl import URL
|
||||
|
||||
DEFAULT_URL = "https://access.redhat.com/hydra/rest/search/kcs"
|
||||
|
||||
|
||||
class DocumentKind(str, Enum):
|
||||
"""
|
||||
The kind of document.
|
||||
"""
|
||||
ERRATA = "Errata"
|
||||
|
||||
|
||||
class Distro(str, Enum):
|
||||
"""
|
||||
The distribution.
|
||||
"""
|
||||
RHEL = "Red Hat Enterprise Linux"
|
||||
|
||||
|
||||
class Architecture(str, Enum):
|
||||
"""
|
||||
The architecture.
|
||||
"""
|
||||
X86_64 = "x86_64"
|
||||
AARCH64 = "aarch64"
|
||||
PPC64 = "ppc64"
|
||||
PPC64LE = "ppc64le"
|
||||
S390X = "s390x"
|
||||
|
||||
|
||||
@dataclass
|
||||
class PortalProduct:
|
||||
"""
|
||||
Red Hat advisory product
|
||||
"""
|
||||
variant: str
|
||||
name: str
|
||||
major_version: int
|
||||
minor_version: int
|
||||
arch: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class Advisory(JSONWizard):
|
||||
"""
|
||||
An advisory.
|
||||
"""
|
||||
documentKind: str = None
|
||||
uri: str = None
|
||||
view_uri: str = None
|
||||
language: str = None
|
||||
id: str = None
|
||||
portal_description: str = None
|
||||
abstract: str = None
|
||||
allTitle: str = None
|
||||
sortTitle: str = None
|
||||
portal_title: list[str] = None
|
||||
lastModifiedDate: str = None
|
||||
displayDate: str = None
|
||||
portal_advisory_type: str = None
|
||||
portal_synopsis: str = None
|
||||
portal_severity: str = None
|
||||
portal_type: str = None
|
||||
portal_package: list[str] = None
|
||||
portal_CVE: list[str] = None
|
||||
portal_BZ: list[str] = None
|
||||
portal_publication_date: str = None
|
||||
portal_requires_subscription: str = None
|
||||
portal_product_names: list[str] = None
|
||||
title: str = None
|
||||
portal_child_ids: list[str] = None
|
||||
portal_product_filter: list[str] = None
|
||||
boostProduct: str = None
|
||||
boostVersion: int = None
|
||||
detectedProducts: list[str] = None
|
||||
caseCount: int = None
|
||||
caseCount_365: int = None
|
||||
timestamp: str = None
|
||||
body: list[str] = None
|
||||
_version_: int = None
|
||||
|
||||
__products: list[PortalProduct] = None
|
||||
|
||||
def get_products(self) -> list[PortalProduct]:
|
||||
if self.__products:
|
||||
return self.__products
|
||||
|
||||
self.__products = []
|
||||
for product in self.portal_product_filter:
|
||||
try:
|
||||
if product.startswith("Red Hat Enterprise Linux"):
|
||||
variant, name, version, arch = product.split("|")
|
||||
major_version = version
|
||||
if "." in version:
|
||||
version_split = version.split(".")
|
||||
major_version = int(version_split[0])
|
||||
minor_version = int(version_split[1])
|
||||
else:
|
||||
major_version = int(version)
|
||||
minor_version = None
|
||||
self.__products.append(
|
||||
PortalProduct(
|
||||
variant, name, major_version, minor_version, arch
|
||||
)
|
||||
)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return self.__products
|
||||
|
||||
def affects_rhel_version_arch(
|
||||
self, major_version: int, minor_version: int | None, arch: Architecture
|
||||
) -> bool:
|
||||
"""
|
||||
Returns whether this advisory affects the given RHEL version and architecture.
|
||||
"""
|
||||
for product in self.get_products():
|
||||
if product.variant == "Red Hat Enterprise Linux" and product.major_version == major_version and product.minor_version == minor_version and product.arch == arch.value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class API:
|
||||
"""
|
||||
The Red Hat Errata API.
|
||||
"""
|
||||
|
||||
url = None
|
||||
|
||||
def __init__(self, url=DEFAULT_URL):
|
||||
if not url:
|
||||
url = DEFAULT_URL
|
||||
self.url = url
|
||||
|
||||
async def search(
|
||||
self,
|
||||
kind: DocumentKind = DocumentKind.ERRATA,
|
||||
sort_asc: bool = False,
|
||||
rows: int = 10,
|
||||
query: str = "*:*",
|
||||
distro: str = "Red%5C+Hat%5C+Enterprise%5C+Linux%7C%2A%7C%2A%7C%2A",
|
||||
detected_product: str = "rhel",
|
||||
from_date: str = None
|
||||
) -> list[Advisory]:
|
||||
params = ""
|
||||
|
||||
# Set query
|
||||
params += f"q={query}"
|
||||
|
||||
# Set rows
|
||||
params += f"&rows={rows}"
|
||||
|
||||
# Set sorting
|
||||
sorting = "portal_publication_date+asc" if sort_asc else "portal_publication_date+desc"
|
||||
params += f"&sort={sorting}"
|
||||
|
||||
# Set start
|
||||
params += "&start=0"
|
||||
|
||||
# Set distribution
|
||||
params += f"&fq=portal_product_filter:{distro}"
|
||||
|
||||
# Set from-to
|
||||
if from_date:
|
||||
params += f"&fq=portal_publication_date%3A%5B{quote(from_date)}%20TO%20NOW%5D"
|
||||
|
||||
# Set document kind
|
||||
params += f"&fq=documentKind:{kind.value}"
|
||||
|
||||
# Set detected product
|
||||
if detected_product:
|
||||
params += f"&fq=detectedProducts:{detected_product}"
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
URL(f"{self.url}?{params}", encoded=True)
|
||||
) as response:
|
||||
body = await response.json()
|
||||
if response.status != 200:
|
||||
raise Exception((await response.text()))
|
||||
elif body.get("response", {}).get("numFound", 0) == 0:
|
||||
return []
|
||||
return Advisory.from_list(list(body["response"]["docs"]))
|
34
apollo/rherrata/example.py
Normal file
34
apollo/rherrata/example.py
Normal file
@ -0,0 +1,34 @@
|
||||
import asyncio
|
||||
import datetime
|
||||
from __init__ import API, Architecture
|
||||
|
||||
|
||||
async def main():
|
||||
api = API()
|
||||
res = await api.search(
|
||||
detected_product="rhel",
|
||||
rows=1000,
|
||||
from_date="2019-05-05T22:00:00Z",
|
||||
sort_asc=True
|
||||
)
|
||||
contains_9 = 0
|
||||
contains_8 = 0
|
||||
contains_90eus = 0
|
||||
for advisory in res:
|
||||
if advisory.affects_rhel_version_arch(9, None, Architecture.X86_64):
|
||||
print(f"{advisory.id} affects RHEL 9 x86_64")
|
||||
contains_9 += 1
|
||||
elif advisory.affects_rhel_version_arch(9, 0, Architecture.X86_64):
|
||||
print(f"{advisory.id} affects RHEL 9.0 EUS x86_64")
|
||||
contains_90eus += 1
|
||||
elif advisory.affects_rhel_version_arch(8, None, Architecture.X86_64):
|
||||
print(f"{advisory.id} affects RHEL 8 x86_64")
|
||||
contains_8 += 1
|
||||
print(f"Found {contains_9} advisories that affect RHEL 9 x86_64")
|
||||
print(f"Found {contains_8} advisories that affect RHEL 8 x86_64")
|
||||
print(f"Found {contains_90eus} advisories that affect RHEL 9.0 EUS x86_64")
|
||||
print(f"Found {len(res)} advisories in total")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
14
apollo/rhwebscraper/BUILD.bazel
Normal file
14
apollo/rhwebscraper/BUILD.bazel
Normal file
@ -0,0 +1,14 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
|
||||
# gazelle:exclude example.py
|
||||
|
||||
py_library(
|
||||
name = "rhwebscraper_lib",
|
||||
srcs = ["__init__.py"],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"@pypi_aiohttp//:pkg",
|
||||
"@pypi_beautifulsoup4//:pkg",
|
||||
],
|
||||
)
|
50
apollo/rhwebscraper/__init__.py
Normal file
50
apollo/rhwebscraper/__init__.py
Normal file
@ -0,0 +1,50 @@
|
||||
from typing import Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
import aiohttp
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
@dataclass
|
||||
class RHWebAdvisoryFix:
|
||||
id: str
|
||||
description: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class PartialRHWebAdvisory:
|
||||
name: str
|
||||
topic: Optional[str]
|
||||
fixes: Optional[list[RHWebAdvisoryFix]]
|
||||
|
||||
|
||||
async def get_advisory_topic_and_fixes(
|
||||
advisory_name: str
|
||||
) -> Optional[PartialRHWebAdvisory]:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(
|
||||
f"https://access.redhat.com/errata/{advisory_name}"
|
||||
) as response:
|
||||
if response.status == 200:
|
||||
html = await response.text()
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
|
||||
topic = soup.select("div#topic > p")
|
||||
if topic:
|
||||
topic = "\n\n".join([p.text for p in topic])
|
||||
|
||||
parsed_fixes = []
|
||||
fixes = soup.select("div#fixes > ul > li")
|
||||
if fixes:
|
||||
for fix in fixes:
|
||||
bugzilla_id = fix.find("a").attrs.get("href"
|
||||
).split("id=")[1]
|
||||
description = fix.find("a").next_sibling.text.strip(
|
||||
).removeprefix("- ")
|
||||
parsed_fixes.append(
|
||||
RHWebAdvisoryFix(bugzilla_id, description)
|
||||
)
|
||||
|
||||
return PartialRHWebAdvisory(advisory_name, topic, parsed_fixes)
|
||||
else:
|
||||
return None
|
12
apollo/rhwebscraper/example.py
Normal file
12
apollo/rhwebscraper/example.py
Normal file
@ -0,0 +1,12 @@
|
||||
import asyncio
|
||||
|
||||
from __init__ import get_advisory_topic_and_fixes
|
||||
|
||||
|
||||
async def main():
|
||||
advisory = await get_advisory_topic_and_fixes("RHSA-2023:0536")
|
||||
print(advisory)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
35
apollo/rhworker/BUILD.bazel
Normal file
35
apollo/rhworker/BUILD.bazel
Normal file
@ -0,0 +1,35 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_library")
|
||||
|
||||
py_binary(
|
||||
name = "rhworker",
|
||||
srcs = ["__main__.py"],
|
||||
imports = ["../.."],
|
||||
main = "__main__.py",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
":rhworker_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_click//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
],
|
||||
)
|
||||
|
||||
py_library(
|
||||
name = "rhworker_lib",
|
||||
srcs = [
|
||||
"poll_rh_activities.py",
|
||||
"poll_rh_workflow.py",
|
||||
"temporal.py",
|
||||
],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//apollo/db:db_lib",
|
||||
"//apollo/rherrata:rherrata_lib",
|
||||
"//apollo/rhwebscraper:rhwebscraper_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_aiohttp//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
"@pypi_tortoise_orm//:pkg",
|
||||
],
|
||||
)
|
51
apollo/rhworker/__main__.py
Normal file
51
apollo/rhworker/__main__.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
Apollo RH Temporal Worker
|
||||
|
||||
This worker only executes tasks that are related to Red Hat.
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
from temporalio.worker import Worker
|
||||
import click
|
||||
|
||||
from common.database import Database
|
||||
from common.info import Info
|
||||
from common.logger import Logger
|
||||
from common.temporal import Temporal
|
||||
|
||||
from apollo.rhworker.temporal import TASK_QUEUE
|
||||
from apollo.rhworker.poll_rh_workflow import PollRHAdvisoriesWorkflow
|
||||
from apollo.rhworker.poll_rh_activities import get_last_indexed_date, get_rh_advisories
|
||||
|
||||
|
||||
async def run():
|
||||
db = Database(True)
|
||||
await db.init(["apollo.db"])
|
||||
|
||||
temporal = Temporal(True)
|
||||
await temporal.connect()
|
||||
|
||||
worker = Worker(
|
||||
temporal.client,
|
||||
task_queue=TASK_QUEUE,
|
||||
workflows=[
|
||||
PollRHAdvisoriesWorkflow,
|
||||
],
|
||||
activities=[
|
||||
get_last_indexed_date,
|
||||
get_rh_advisories,
|
||||
]
|
||||
)
|
||||
|
||||
await worker.run()
|
||||
|
||||
|
||||
@click.command()
|
||||
def main():
|
||||
Info("apollorhworker", "apollo2")
|
||||
Logger()
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
230
apollo/rhworker/poll_rh_activities.py
Normal file
230
apollo/rhworker/poll_rh_activities.py
Normal file
@ -0,0 +1,230 @@
|
||||
import datetime
|
||||
import re
|
||||
import bz2
|
||||
from typing import Optional
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import aiohttp
|
||||
from temporalio import activity
|
||||
from tortoise.transactions import in_transaction
|
||||
|
||||
from apollo.db import RedHatIndexState, RedHatAdvisory, RedHatAdvisoryPackage
|
||||
from apollo.db import RedHatAdvisoryBugzillaBug, RedHatAdvisoryAffectedProduct, RedHatAdvisoryCVE
|
||||
from apollo.rherrata import API
|
||||
|
||||
from common.logger import Logger
|
||||
|
||||
OVAL_NS = {"": "http://oval.mitre.org/XMLSchema/oval-definitions-5"}
|
||||
bz_re = re.compile(r"BZ#([0-9]+)")
|
||||
|
||||
|
||||
def parse_red_hat_date(rhdate: str) -> datetime.datetime:
|
||||
return datetime.datetime.fromisoformat(rhdate.removesuffix("Z"))
|
||||
|
||||
|
||||
@activity.defn
|
||||
async def get_last_indexed_date() -> Optional[str]:
|
||||
state = await RedHatIndexState.get_or_none()
|
||||
return re.sub(
|
||||
r"\+\d\d:\d\d", "",
|
||||
state.last_indexed_at.isoformat("T") + "Z"
|
||||
) if state else None
|
||||
|
||||
|
||||
async def fetch_mapped_oval() -> dict[str, ET.ElementTree]:
|
||||
# Download the oval_url using aiohttp, decompress using bzip and parse
|
||||
oval_url = "https://access.redhat.com/security/data/oval/com.redhat.rhsa-all.xml.bz2"
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(oval_url) as response:
|
||||
if response.status == 200:
|
||||
data = await response.read()
|
||||
tree = ET.fromstring(bz2.decompress(data))
|
||||
|
||||
# Index by advisory name
|
||||
def_map = {}
|
||||
definitions = tree.findall("definitions/definition", OVAL_NS)
|
||||
for definition in definitions:
|
||||
def_id = definition.attrib["id"]
|
||||
id_split = def_id.split(":")
|
||||
name = f"{id_split[1].split('.')[2].upper()}-{id_split[3][0:4]}:{id_split[3][4:]}"
|
||||
def_map[name] = definition
|
||||
|
||||
return def_map
|
||||
else:
|
||||
raise Exception("Failed to fetch OVAL data")
|
||||
|
||||
|
||||
@activity.defn
|
||||
async def get_rh_advisories(from_timestamp: str = None) -> None:
|
||||
logger = Logger()
|
||||
advisories = await API().search(
|
||||
from_date=from_timestamp, rows=10000, sort_asc=True
|
||||
)
|
||||
oval = await fetch_mapped_oval()
|
||||
|
||||
for advisory in advisories:
|
||||
async with in_transaction():
|
||||
advisory_last_indexed_at = parse_red_hat_date(
|
||||
advisory.portal_publication_date
|
||||
)
|
||||
state = await RedHatIndexState.first()
|
||||
if state:
|
||||
state.last_indexed_at = advisory_last_indexed_at
|
||||
await state.save()
|
||||
else:
|
||||
await RedHatIndexState().create(
|
||||
last_index_at=advisory_last_indexed_at
|
||||
)
|
||||
|
||||
logger.info("Processing advisory %s", advisory.id)
|
||||
|
||||
existing_advisory = await RedHatAdvisory.filter(name=advisory.id
|
||||
).get_or_none()
|
||||
if existing_advisory:
|
||||
logger.info("Advisory %s already exists, skipping", advisory.id)
|
||||
continue
|
||||
|
||||
kind = "Security"
|
||||
if "Enhancement" in advisory.portal_advisory_type:
|
||||
kind = "Enhancement"
|
||||
elif "Bug Fix" in advisory.portal_advisory_type:
|
||||
kind = "Bug Fix"
|
||||
|
||||
issued_at = parse_red_hat_date(advisory.portal_publication_date)
|
||||
severity = advisory.portal_severity
|
||||
if not severity or severity == "":
|
||||
severity = "None"
|
||||
|
||||
ra = await RedHatAdvisory.create(
|
||||
name=advisory.id,
|
||||
red_hat_issued_at=issued_at,
|
||||
synopsis=advisory.portal_synopsis,
|
||||
description=advisory.portal_description,
|
||||
kind=kind,
|
||||
severity=severity,
|
||||
topic="",
|
||||
)
|
||||
|
||||
if advisory.portal_package:
|
||||
await RedHatAdvisoryPackage.bulk_create(
|
||||
[
|
||||
RedHatAdvisoryPackage(
|
||||
**{
|
||||
"red_hat_advisory_id": ra.id,
|
||||
"nevra": nevra
|
||||
}
|
||||
) for nevra in advisory.portal_package
|
||||
],
|
||||
ignore_conflicts=True
|
||||
)
|
||||
|
||||
if advisory.portal_CVE:
|
||||
cves_to_save = []
|
||||
|
||||
definition = oval.get(advisory.id)
|
||||
if not definition:
|
||||
# Fill in CVEs from Errata
|
||||
for advisory_cve in advisory.portal_CVE:
|
||||
cves_to_save.append(
|
||||
RedHatAdvisoryCVE(
|
||||
**{
|
||||
"red_hat_advisory_id": ra.id,
|
||||
"cve": advisory_cve,
|
||||
"cvss3_scoring_vector": "UNKNOWN",
|
||||
"cvss3_base_score": "UNKNOWN",
|
||||
"cwe": "UNKNOWN",
|
||||
}
|
||||
)
|
||||
)
|
||||
else:
|
||||
# Fetch CVEs from the OVAL
|
||||
cves = definition.findall("metadata/advisory/cve", OVAL_NS)
|
||||
for cve in cves:
|
||||
cvss3_scoring_vector = "UNKNOWN"
|
||||
cvss3_base_score = "UNKNOWN"
|
||||
|
||||
cvss3 = cve.attrib.get("cvss3")
|
||||
if cvss3:
|
||||
cvss3_raw = cvss3.split("/", 1)
|
||||
cvss3_scoring_vector = cvss3_raw[
|
||||
1] if cvss3_raw else "UNKNOWN"
|
||||
cvss3_base_score = cvss3_raw[
|
||||
0] if cvss3_raw else "UNKNOWN"
|
||||
|
||||
cwe = cve.attrib.get("cwe")
|
||||
if not cwe:
|
||||
cwe = "UNKNOWN"
|
||||
|
||||
cves_to_save.append(
|
||||
RedHatAdvisoryCVE(
|
||||
**{
|
||||
"red_hat_advisory_id":
|
||||
ra.id,
|
||||
"cve":
|
||||
cve.text,
|
||||
"cvss3_scoring_vector":
|
||||
cvss3_scoring_vector,
|
||||
"cvss3_base_score":
|
||||
cvss3_base_score,
|
||||
"cwe":
|
||||
cwe,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
if not cves_to_save:
|
||||
raise Exception(f"Failed to find CVEs for {advisory.id}")
|
||||
|
||||
await RedHatAdvisoryCVE.bulk_create(
|
||||
cves_to_save,
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
if advisory.portal_BZ:
|
||||
bz_map = {}
|
||||
if advisory.portal_description:
|
||||
for line in advisory.portal_description.splitlines():
|
||||
search = bz_re.search(line)
|
||||
if search:
|
||||
bz_id = search.group(1)
|
||||
bz_line = line.removeprefix("* ")
|
||||
bz_line = line.removeprefix("* ")
|
||||
bz_line = line.removeprefix("- ")
|
||||
bz_line = line.replace(f"(BZ#{bz_id})", "")
|
||||
bz_line = bz_line.strip()
|
||||
bz_map[bz_id] = bz_line
|
||||
|
||||
await RedHatAdvisoryBugzillaBug.bulk_create(
|
||||
[
|
||||
RedHatAdvisoryBugzillaBug(
|
||||
**{
|
||||
"red_hat_advisory_id": ra.id,
|
||||
"bugzilla_bug_id": bugzilla_bug_id,
|
||||
"description": bz_map.get(bugzilla_bug_id, ""),
|
||||
}
|
||||
) for bugzilla_bug_id in advisory.portal_BZ
|
||||
],
|
||||
ignore_conflicts=True
|
||||
)
|
||||
|
||||
affected_products = advisory.get_products()
|
||||
if affected_products:
|
||||
await RedHatAdvisoryAffectedProduct.bulk_create(
|
||||
[
|
||||
RedHatAdvisoryAffectedProduct(
|
||||
**{
|
||||
"red_hat_advisory_id": ra.id,
|
||||
"variant": product.variant,
|
||||
"name": product.name,
|
||||
"major_version": product.major_version,
|
||||
"minor_version": product.minor_version,
|
||||
"arch": product.arch
|
||||
}
|
||||
) for product in affected_products
|
||||
],
|
||||
ignore_conflicts=True
|
||||
)
|
||||
|
||||
logger.info("Processed advisory %s", advisory.id)
|
||||
|
||||
return None
|
24
apollo/rhworker/poll_rh_workflow.py
Normal file
24
apollo/rhworker/poll_rh_workflow.py
Normal file
@ -0,0 +1,24 @@
|
||||
import datetime
|
||||
|
||||
from temporalio import workflow
|
||||
|
||||
|
||||
@workflow.defn
|
||||
class PollRHAdvisoriesWorkflow:
|
||||
"""
|
||||
Polls Red Hat Errata for new advisories.
|
||||
"""
|
||||
@workflow.run
|
||||
async def run(self) -> None:
|
||||
from_timestamp = await workflow.execute_activity(
|
||||
"get_last_indexed_date",
|
||||
start_to_close_timeout=datetime.timedelta(seconds=20),
|
||||
)
|
||||
|
||||
await workflow.execute_activity(
|
||||
"get_rh_advisories",
|
||||
from_timestamp,
|
||||
start_to_close_timeout=datetime.timedelta(hours=2),
|
||||
)
|
||||
|
||||
return None
|
1
apollo/rhworker/temporal.py
Normal file
1
apollo/rhworker/temporal.py
Normal file
@ -0,0 +1 @@
|
||||
TASK_QUEUE = "v2-rhworker"
|
35
apollo/rpmworker/BUILD.bazel
Normal file
35
apollo/rpmworker/BUILD.bazel
Normal file
@ -0,0 +1,35 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_library")
|
||||
|
||||
py_library(
|
||||
name = "rpmworker_lib",
|
||||
srcs = [
|
||||
"repomd.py",
|
||||
"rh_matcher_activities.py",
|
||||
"rh_matcher_workflows.py",
|
||||
"temporal.py",
|
||||
],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//apollo/db:db_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_aiohttp//:pkg",
|
||||
"@pypi_pyyaml//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
"@pypi_tortoise_orm//:pkg",
|
||||
],
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "rpmworker",
|
||||
srcs = ["__main__.py"],
|
||||
imports = ["../.."],
|
||||
main = "__main__.py",
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
":rpmworker_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_click//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
],
|
||||
)
|
51
apollo/rpmworker/__main__.py
Normal file
51
apollo/rpmworker/__main__.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
Apollo RPM Temporal Worker
|
||||
|
||||
This worker only executes tasks that are related to RPMs.
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
from temporalio.worker import Worker
|
||||
import click
|
||||
|
||||
from apollo.rpmworker.rh_matcher_workflows import RhMatcherWorkflow, RhDefunctWorkflow
|
||||
from apollo.rpmworker.rh_matcher_activities import get_supported_products_with_rh_mirrors, match_rh_repos, block_remaining_rh_advisories
|
||||
from apollo.rpmworker.temporal import TASK_QUEUE
|
||||
|
||||
from common.database import Database
|
||||
from common.info import Info
|
||||
from common.temporal import Temporal
|
||||
|
||||
|
||||
async def run():
|
||||
db = Database(True)
|
||||
await db.init(["apollo.db"])
|
||||
|
||||
temporal = Temporal(True)
|
||||
await temporal.connect()
|
||||
|
||||
worker = Worker(
|
||||
temporal.client,
|
||||
task_queue=TASK_QUEUE,
|
||||
workflows=[
|
||||
RhMatcherWorkflow,
|
||||
RhDefunctWorkflow,
|
||||
],
|
||||
activities=[
|
||||
get_supported_products_with_rh_mirrors,
|
||||
match_rh_repos,
|
||||
block_remaining_rh_advisories,
|
||||
]
|
||||
)
|
||||
|
||||
await worker.run()
|
||||
|
||||
|
||||
@click.command()
|
||||
def main():
|
||||
Info("apollorpmworker", "apollo2")
|
||||
asyncio.run(run())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
116
apollo/rpmworker/repomd.py
Normal file
116
apollo/rpmworker/repomd.py
Normal file
@ -0,0 +1,116 @@
|
||||
import gzip
|
||||
import lzma
|
||||
import re
|
||||
from xml.etree import ElementTree as ET
|
||||
from urllib.parse import urlparse
|
||||
from os import path
|
||||
|
||||
import aiohttp
|
||||
import yaml
|
||||
|
||||
from common.logger import Logger
|
||||
|
||||
NVRA_RE = re.compile(
|
||||
r"^(\S+)-([\w~%.+]+)-(\w+(?:\.[\w~%+]+)+?)(?:\.(\w+))?(?:\.rpm)?$"
|
||||
)
|
||||
DIST_RE = re.compile(r"(\.el\d(?:_\d|))")
|
||||
MODULE_DIST_RE = re.compile(r"\.module.+$")
|
||||
|
||||
|
||||
def clean_nvra_pkg(matching_pkg: ET.Element) -> str:
|
||||
name = matching_pkg.find("{http://linux.duke.edu/metadata/common}name").text
|
||||
version = matching_pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}version"
|
||||
).attrib["ver"]
|
||||
release = matching_pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}version"
|
||||
).attrib["rel"]
|
||||
arch = matching_pkg.find("{http://linux.duke.edu/metadata/common}arch").text
|
||||
|
||||
clean_release = MODULE_DIST_RE.sub("", DIST_RE.sub("", release))
|
||||
return f"{name}-{version}-{clean_release}.{arch}"
|
||||
|
||||
|
||||
def clean_nvra(nvra_raw: str) -> str:
|
||||
nvra = NVRA_RE.search(nvra_raw)
|
||||
name = nvra.group(1)
|
||||
version = nvra.group(2)
|
||||
release = nvra.group(3)
|
||||
arch = nvra.group(4)
|
||||
|
||||
clean_release = MODULE_DIST_RE.sub("", DIST_RE.sub("", release))
|
||||
return f"{name}-{version}-{clean_release}.{arch}"
|
||||
|
||||
|
||||
async def download_xml(
|
||||
url: str, gz: bool = False, xz: bool = False
|
||||
) -> ET.Element:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url) as resp:
|
||||
if resp.status != 200:
|
||||
raise Exception(f"Failed to get {url}: {resp.status}")
|
||||
# Do an in memory gzip decompression if gz is set
|
||||
if gz:
|
||||
return ET.fromstring(
|
||||
gzip.decompress(await resp.read()).decode("utf-8")
|
||||
)
|
||||
elif xz:
|
||||
return ET.fromstring(
|
||||
lzma.decompress(await resp.read()).decode("utf-8")
|
||||
)
|
||||
return ET.fromstring(await resp.text())
|
||||
|
||||
|
||||
async def download_yaml(url: str, gz: bool = False, xz: bool = False) -> any:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
async with session.get(url) as resp:
|
||||
if resp.status != 200:
|
||||
raise Exception(f"Failed to get {url}: {resp.status}")
|
||||
# Do an in memory gzip decompression if gz is set
|
||||
if gz:
|
||||
return yaml.full_load_all(
|
||||
gzip.decompress(await resp.read()).decode("utf-8")
|
||||
)
|
||||
elif xz:
|
||||
return yaml.full_load_all(
|
||||
lzma.decompress(await resp.read()).decode("utf-8")
|
||||
)
|
||||
|
||||
return yaml.full_load_all(await resp.text())
|
||||
|
||||
|
||||
async def get_data_from_repomd(
|
||||
url: str,
|
||||
data_type: str,
|
||||
el: ET.Element,
|
||||
is_yaml=False,
|
||||
):
|
||||
# There is a top-most repomd element in repomd
|
||||
# Under there is revision and multiple data elements
|
||||
# We want the data element with type="data_type"
|
||||
# Under that is location with href
|
||||
# That href is the location of the data
|
||||
for data in el.findall("{http://linux.duke.edu/metadata/repo}data"):
|
||||
if data.attrib["type"] == data_type:
|
||||
location = data.find(
|
||||
"{http://linux.duke.edu/metadata/repo}location"
|
||||
)
|
||||
parsed_url = urlparse(url)
|
||||
new_path = path.abspath(
|
||||
path.join(parsed_url.path, "../..", location.attrib["href"])
|
||||
)
|
||||
data_url = parsed_url._replace(path=new_path).geturl()
|
||||
|
||||
if is_yaml:
|
||||
return await download_yaml(
|
||||
data_url,
|
||||
gz=data_url.endswith(".gz"),
|
||||
xz=data_url.endswith(".xz"),
|
||||
)
|
||||
return await download_xml(
|
||||
data_url,
|
||||
gz=data_url.endswith(".gz"),
|
||||
xz=data_url.endswith(".xz"),
|
||||
)
|
||||
|
||||
return None
|
562
apollo/rpmworker/rh_matcher_activities.py
Normal file
562
apollo/rpmworker/rh_matcher_activities.py
Normal file
@ -0,0 +1,562 @@
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
from temporalio import activity
|
||||
from tortoise.transactions import in_transaction
|
||||
|
||||
from apollo.db import SupportedProduct, SupportedProductsRhMirror, SupportedProductsRpmRepomd, SupportedProductsRpmRhOverride, SupportedProductsRhBlock
|
||||
from apollo.db import RedHatAdvisory, Advisory, AdvisoryAffectedProduct, AdvisoryCVE, AdvisoryFix, AdvisoryPackage
|
||||
from apollo.rpmworker import repomd
|
||||
|
||||
from common.logger import Logger
|
||||
|
||||
|
||||
@dataclass
|
||||
class NewPackage:
|
||||
nevra: str
|
||||
checksum: str
|
||||
checksum_type: str
|
||||
module_context: str
|
||||
module_name: str
|
||||
module_stream: str
|
||||
module_version: str
|
||||
repo_name: str
|
||||
package_name: str
|
||||
mirror_id: int
|
||||
supported_product_id: int
|
||||
product_name: str
|
||||
|
||||
|
||||
@activity.defn
|
||||
async def get_supported_products_with_rh_mirrors() -> list[int]:
|
||||
"""
|
||||
Get supported product IDs that has an RH mirror configuration
|
||||
"""
|
||||
rh_mirrors = await SupportedProductsRhMirror.all().prefetch_related(
|
||||
"rpm_repomds",
|
||||
)
|
||||
|
||||
ret = []
|
||||
for rh_mirror in rh_mirrors:
|
||||
if rh_mirror.supported_product_id not in ret and rh_mirror.rpm_repomds:
|
||||
ret.append(rh_mirror.supported_product_id)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
async def get_matching_rh_advisories(
|
||||
mirror: SupportedProductsRhMirror
|
||||
) -> list[RedHatAdvisory]:
|
||||
# First get advisories that matches the mirrored product
|
||||
# And also the overrides
|
||||
# Also exclude blocked advisories and advisories without packages
|
||||
advisories = await RedHatAdvisory.filter(
|
||||
affected_products__variant=mirror.match_variant,
|
||||
affected_products__major_version=mirror.match_major_version,
|
||||
affected_products__minor_version=mirror.match_minor_version,
|
||||
affected_products__arch=mirror.match_arch,
|
||||
).order_by("red_hat_issued_at").prefetch_related(
|
||||
"packages", "cves", "bugzilla_tickets"
|
||||
)
|
||||
|
||||
override_ids = []
|
||||
overrides = await SupportedProductsRpmRhOverride.filter(
|
||||
supported_products_rh_mirror_id=mirror.id
|
||||
).prefetch_related("red_hat_advisory")
|
||||
for override in overrides:
|
||||
override_ids.append(override.red_hat_advisory_id)
|
||||
advisories.append(override.red_hat_advisory)
|
||||
|
||||
blocked = await SupportedProductsRhBlock.filter(
|
||||
supported_products_rh_mirror_id=mirror.id,
|
||||
).all()
|
||||
blocked_ids = []
|
||||
now = datetime.datetime.now(datetime.timezone.utc)
|
||||
for b in blocked:
|
||||
delta = now - b.created_at
|
||||
if delta.days >= 14:
|
||||
blocked_ids.append(b.red_hat_advisory_id)
|
||||
|
||||
# Remove all advisories without packages and blocked advisories
|
||||
final = []
|
||||
for advisory in advisories:
|
||||
if advisory.packages and (
|
||||
advisory.id not in blocked_ids and advisory.id not in override_ids
|
||||
):
|
||||
final.append(advisory)
|
||||
|
||||
return final
|
||||
|
||||
|
||||
async def clone_advisory(
|
||||
product: SupportedProduct,
|
||||
mirrors: list[SupportedProductsRhMirror],
|
||||
advisory: RedHatAdvisory,
|
||||
all_pkgs: list[ET.ElementTree],
|
||||
module_pkgs: dict,
|
||||
published_at: datetime.datetime,
|
||||
):
|
||||
logger = Logger()
|
||||
logger.info("Cloning advisory %s to %s", advisory.name, product.name)
|
||||
|
||||
acceptable_arches = list(set([x.match_arch for x in mirrors]))
|
||||
acceptable_arches.extend(["src", "noarch"])
|
||||
for mirror in mirrors:
|
||||
if mirror.match_arch == "x86_64":
|
||||
acceptable_arches.append("i686")
|
||||
break
|
||||
|
||||
clean_advisory_nvras = {}
|
||||
for advisory_pkg in advisory.packages:
|
||||
nvra = repomd.NVRA_RE.search(advisory_pkg.nevra)
|
||||
if nvra.group(4) not in acceptable_arches:
|
||||
continue
|
||||
cleaned = repomd.clean_nvra(advisory_pkg.nevra)
|
||||
if cleaned not in clean_advisory_nvras:
|
||||
clean_advisory_nvras[cleaned] = True
|
||||
|
||||
if not clean_advisory_nvras:
|
||||
logger.info(
|
||||
"Blocking advisory %s, no packages match arches",
|
||||
advisory.name,
|
||||
)
|
||||
await SupportedProductsRhBlock.bulk_create(
|
||||
[
|
||||
SupportedProductsRhBlock(
|
||||
**{
|
||||
"supported_products_rh_mirror_id": mirror.id,
|
||||
"red_hat_advisory_id": advisory.id,
|
||||
}
|
||||
) for mirror in mirrors
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
overrides = await SupportedProductsRpmRhOverride.filter(
|
||||
supported_products_rh_mirror_id__in=[x.id for x in mirrors],
|
||||
red_hat_advisory_id=advisory.id,
|
||||
).all()
|
||||
if overrides:
|
||||
for override in overrides:
|
||||
await override.delete()
|
||||
return
|
||||
|
||||
pkg_nvras = {}
|
||||
for pkgs in all_pkgs:
|
||||
for pkg in pkgs:
|
||||
cleaned = repomd.clean_nvra_pkg(pkg)
|
||||
if cleaned not in pkg_nvras:
|
||||
pkg_nvras[cleaned] = [pkg]
|
||||
else:
|
||||
pkg_nvras[cleaned].append(pkg)
|
||||
|
||||
async with in_transaction():
|
||||
# Create advisory
|
||||
name = f"{product.code.code}{advisory.name.removeprefix('RH')}"
|
||||
synopsis = advisory.synopsis.replace(
|
||||
"Red Hat Enterprise Linux", product.name
|
||||
)
|
||||
synopsis = synopsis.replace("RHEL", product.name)
|
||||
synopsis = synopsis.replace("Red Hat", product.vendor)
|
||||
synopsis = synopsis.replace(advisory.name, name)
|
||||
description = advisory.description.replace(
|
||||
"Red Hat Enterprise Linux", product.name
|
||||
)
|
||||
description = description.replace("RHEL", product.name)
|
||||
description = description.replace("Red Hat", product.vendor)
|
||||
description = description.replace(advisory.name, name)
|
||||
|
||||
existing_advisory = await Advisory.filter(name=name).get_or_none()
|
||||
if not existing_advisory:
|
||||
new_advisory = await Advisory.create(
|
||||
name=name,
|
||||
synopsis=synopsis,
|
||||
description=description,
|
||||
kind=advisory.kind,
|
||||
severity=advisory.severity,
|
||||
red_hat_advisory_id=advisory.id,
|
||||
published_at=published_at,
|
||||
topic=advisory.topic,
|
||||
)
|
||||
else:
|
||||
new_advisory = existing_advisory
|
||||
|
||||
# Clone packages
|
||||
new_pkgs = []
|
||||
for advisory_nvra, _ in clean_advisory_nvras.items():
|
||||
if advisory_nvra not in pkg_nvras:
|
||||
continue
|
||||
|
||||
pkgs_to_process = pkg_nvras[advisory_nvra]
|
||||
for pkg in pkgs_to_process:
|
||||
pkg_name = pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}name"
|
||||
).text
|
||||
version_tree = pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}version"
|
||||
)
|
||||
version = version_tree.attrib["ver"]
|
||||
release = version_tree.attrib["rel"]
|
||||
epoch = version_tree.attrib["epoch"]
|
||||
arch = pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}arch"
|
||||
).text
|
||||
nevra = f"{pkg_name}-{epoch}:{version}-{release}.{arch}.rpm"
|
||||
|
||||
source_rpm = pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}format"
|
||||
).find("{http://linux.duke.edu/metadata/rpm}sourcerpm")
|
||||
|
||||
# This means we're checking a source RPM
|
||||
if advisory_nvra.endswith(".src.rpm"
|
||||
) or advisory_nvra.endswith(".src"):
|
||||
source_nvra = repomd.NVRA_RE.search(advisory_nvra)
|
||||
package_name = source_nvra.group(1)
|
||||
else:
|
||||
source_nvra = repomd.NVRA_RE.search(source_rpm.text)
|
||||
package_name = source_nvra.group(1)
|
||||
|
||||
checksum_tree = pkg.find(
|
||||
"{http://linux.duke.edu/metadata/common}checksum"
|
||||
)
|
||||
checksum = checksum_tree.text
|
||||
checksum_type = checksum_tree.attrib["type"]
|
||||
|
||||
module_context = None
|
||||
module_name = None
|
||||
module_stream = None
|
||||
module_version = None
|
||||
|
||||
if ".module+" in release:
|
||||
for module_pkg, data in module_pkgs.items():
|
||||
if module_pkg == nevra.removesuffix(".rpm"):
|
||||
module_name = data[0]
|
||||
module_stream = data[1]
|
||||
module_version = data[2]
|
||||
module_context = data[3]
|
||||
|
||||
for mirror in mirrors:
|
||||
if pkg.attrib["mirror_id"] != str(mirror.id):
|
||||
continue
|
||||
|
||||
new_pkgs.append(
|
||||
NewPackage(
|
||||
nevra=nevra,
|
||||
checksum=checksum,
|
||||
checksum_type=checksum_type,
|
||||
module_context=module_context,
|
||||
module_name=module_name,
|
||||
module_stream=module_stream,
|
||||
module_version=module_version,
|
||||
repo_name=pkg.attrib["repo_name"],
|
||||
package_name=package_name,
|
||||
mirror_id=mirror.id,
|
||||
supported_product_id=mirror.supported_product_id,
|
||||
product_name=mirror.name,
|
||||
)
|
||||
)
|
||||
|
||||
if not new_pkgs:
|
||||
logger.info(
|
||||
"Blocking advisory %s, no packages",
|
||||
advisory.name,
|
||||
)
|
||||
if not existing_advisory:
|
||||
await new_advisory.delete()
|
||||
await SupportedProductsRhBlock.bulk_create(
|
||||
[
|
||||
SupportedProductsRhBlock(
|
||||
**{
|
||||
"supported_products_rh_mirror_id": mirror.id,
|
||||
"red_hat_advisory_id": advisory.id,
|
||||
}
|
||||
) for mirror in mirrors
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
overrides = await SupportedProductsRpmRhOverride.filter(
|
||||
supported_products_rh_mirror_id__in=[x.id for x in mirrors],
|
||||
red_hat_advisory_id=advisory.id,
|
||||
).all()
|
||||
if overrides:
|
||||
for override in overrides:
|
||||
await override.delete()
|
||||
return
|
||||
|
||||
await AdvisoryPackage.bulk_create(
|
||||
[
|
||||
AdvisoryPackage(
|
||||
**{
|
||||
"advisory_id": new_advisory.id,
|
||||
"nevra": pkg.nevra,
|
||||
"checksum": pkg.checksum,
|
||||
"checksum_type": pkg.checksum_type,
|
||||
"module_context": pkg.module_context,
|
||||
"module_name": pkg.module_name,
|
||||
"module_stream": pkg.module_stream,
|
||||
"module_version": pkg.module_version,
|
||||
"repo_name": pkg.repo_name,
|
||||
"package_name": pkg.package_name,
|
||||
"supported_products_rh_mirror_id": pkg.mirror_id,
|
||||
"supported_product_id": pkg.supported_product_id,
|
||||
"product_name": pkg.product_name,
|
||||
}
|
||||
) for pkg in new_pkgs
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
# Clone CVEs
|
||||
if advisory.cves:
|
||||
await AdvisoryCVE.bulk_create(
|
||||
[
|
||||
AdvisoryCVE(
|
||||
**{
|
||||
"advisory_id": new_advisory.id,
|
||||
"cve": cve.cve,
|
||||
"cvss3_scoring_vector": cve.cvss3_scoring_vector,
|
||||
"cvss3_base_score": cve.cvss3_base_score,
|
||||
"cwe": cve.cwe,
|
||||
}
|
||||
) for cve in advisory.cves
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
# Clone fixes
|
||||
if advisory.bugzilla_tickets:
|
||||
await AdvisoryFix.bulk_create(
|
||||
[
|
||||
AdvisoryFix(
|
||||
**{
|
||||
"advisory_id":
|
||||
new_advisory.id,
|
||||
"ticket_id":
|
||||
fix.bugzilla_bug_id,
|
||||
"source":
|
||||
f"https://bugzilla.redhat.com/show_bug.cgi?id={fix.bugzilla_bug_id}",
|
||||
"description":
|
||||
fix.description,
|
||||
}
|
||||
) for fix in advisory.bugzilla_tickets
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
# Add affected products
|
||||
await AdvisoryAffectedProduct.bulk_create(
|
||||
[
|
||||
AdvisoryAffectedProduct(
|
||||
**{
|
||||
"advisory_id": new_advisory.id,
|
||||
"variant": product.name,
|
||||
"name": mirror.name,
|
||||
"major_version": mirror.match_major_version,
|
||||
"minor_version": mirror.match_minor_version,
|
||||
"arch": mirror.match_arch,
|
||||
"supported_product_id": mirror.supported_product_id,
|
||||
}
|
||||
) for mirror in mirrors
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
# Check if topic is empty, if so construct it
|
||||
if not new_advisory.topic:
|
||||
package_names = list(set([p.package_name for p in new_pkgs]))
|
||||
affected_products = list(
|
||||
set(
|
||||
[
|
||||
f"{product.name} {mirror.match_major_version}"
|
||||
for mirror in mirrors
|
||||
]
|
||||
)
|
||||
)
|
||||
topic = f"""An update is available for {', '.join(package_names)}.
|
||||
This update affects {', '.join(affected_products)}.
|
||||
A Common Vulnerability Scoring System (CVSS) base score, which gives a detailed severity rating, is available for each vulnerability from the CVE list"""
|
||||
new_advisory.topic = topic
|
||||
|
||||
await new_advisory.save()
|
||||
|
||||
# Block advisory from being attempted to be mirrored again
|
||||
await SupportedProductsRhBlock.bulk_create(
|
||||
[
|
||||
SupportedProductsRhBlock(
|
||||
**{
|
||||
"supported_products_rh_mirror_id": mirror.id,
|
||||
"red_hat_advisory_id": advisory.id,
|
||||
}
|
||||
) for mirror in mirrors
|
||||
],
|
||||
ignore_conflicts=True,
|
||||
)
|
||||
|
||||
|
||||
async def process_repomd(
|
||||
mirror: SupportedProductsRhMirror,
|
||||
rpm_repomd: SupportedProductsRpmRepomd,
|
||||
advisories: list[RedHatAdvisory],
|
||||
):
|
||||
logger = Logger()
|
||||
|
||||
all_pkgs = []
|
||||
urls_to_fetch = [
|
||||
rpm_repomd.url, rpm_repomd.debug_url, rpm_repomd.source_url
|
||||
]
|
||||
module_packages = {}
|
||||
for url in urls_to_fetch:
|
||||
logger.info("Fetching %s", url)
|
||||
repomd_xml = await repomd.download_xml(url)
|
||||
primary_xml = await repomd.get_data_from_repomd(
|
||||
url, "primary", repomd_xml
|
||||
)
|
||||
pkgs = primary_xml.findall(
|
||||
"{http://linux.duke.edu/metadata/common}package"
|
||||
)
|
||||
all_pkgs.extend(pkgs)
|
||||
|
||||
module_yaml_data = await repomd.get_data_from_repomd(
|
||||
url,
|
||||
"modules",
|
||||
repomd_xml,
|
||||
is_yaml=True,
|
||||
)
|
||||
if module_yaml_data:
|
||||
logger.info("Found modules.yaml")
|
||||
for module_data in module_yaml_data:
|
||||
if module_data.get("document") != "modulemd":
|
||||
continue
|
||||
data = module_data.get("data")
|
||||
if not data.get("artifacts"):
|
||||
continue
|
||||
for nevra in data.get("artifacts").get("rpms"):
|
||||
module_packages[nevra] = (
|
||||
data.get("name"),
|
||||
data.get("stream"),
|
||||
data.get("version"),
|
||||
data.get("context"),
|
||||
)
|
||||
|
||||
ret = {}
|
||||
|
||||
pkg_nvras = {}
|
||||
for pkg in all_pkgs:
|
||||
cleaned = repomd.clean_nvra_pkg(pkg)
|
||||
if cleaned not in pkg_nvras:
|
||||
pkg_nvras[cleaned] = pkg
|
||||
|
||||
check_pkgs = []
|
||||
|
||||
# Now check against advisories, and see if we're matching any
|
||||
# If we match, that means we can start creating the supporting
|
||||
# mirror advisories
|
||||
for advisory in advisories:
|
||||
clean_advisory_nvras = {}
|
||||
for advisory_pkg in advisory.packages:
|
||||
cleaned = repomd.clean_nvra(advisory_pkg.nevra)
|
||||
if cleaned not in clean_advisory_nvras:
|
||||
clean_advisory_nvras[cleaned] = True
|
||||
|
||||
if not clean_advisory_nvras:
|
||||
continue
|
||||
|
||||
did_match_any = False
|
||||
|
||||
for nevra, _ in clean_advisory_nvras.items():
|
||||
if nevra in pkg_nvras:
|
||||
pkg = pkg_nvras[nevra]
|
||||
# Set repo name as an attribute to packages
|
||||
pkg.set("repo_name", rpm_repomd.repo_name)
|
||||
pkg.set("mirror_id", str(mirror.id))
|
||||
check_pkgs.append(pkg)
|
||||
did_match_any = True
|
||||
|
||||
if did_match_any:
|
||||
ret.update(
|
||||
{
|
||||
advisory.name:
|
||||
{
|
||||
"advisory": advisory,
|
||||
"packages": [check_pkgs],
|
||||
"module_packages": module_packages,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@activity.defn
|
||||
async def match_rh_repos(supported_product_id: int) -> None:
|
||||
"""
|
||||
Process the repomd files for the supported product
|
||||
"""
|
||||
logger = Logger()
|
||||
|
||||
supported_product = await SupportedProduct.filter(
|
||||
id=supported_product_id
|
||||
).first().prefetch_related("rh_mirrors", "rh_mirrors__rpm_repomds", "code")
|
||||
|
||||
all_advisories = {}
|
||||
|
||||
for mirror in supported_product.rh_mirrors:
|
||||
logger.info("Processing mirror: %s", mirror.name)
|
||||
advisories = await get_matching_rh_advisories(mirror)
|
||||
for rpm_repomd in mirror.rpm_repomds:
|
||||
if rpm_repomd.arch != mirror.match_arch:
|
||||
continue
|
||||
published_at = None
|
||||
if rpm_repomd.production:
|
||||
published_at = datetime.datetime.now()
|
||||
advisory_map = await process_repomd(mirror, rpm_repomd, advisories)
|
||||
if advisory_map:
|
||||
for advisory_name, obj in advisory_map.items():
|
||||
if advisory_name in all_advisories:
|
||||
all_advisories[advisory_name]["packages"].extend(
|
||||
obj["packages"]
|
||||
)
|
||||
all_advisories[advisory_name]["mirrors"].append(mirror)
|
||||
|
||||
for key, val in obj["module_packages"].items():
|
||||
all_advisories[advisory_name]["module_packages"][
|
||||
key] = val
|
||||
else:
|
||||
new_obj = dict(obj)
|
||||
new_obj["published_at"] = published_at
|
||||
new_obj["mirrors"] = [mirror]
|
||||
all_advisories.update({advisory_name: new_obj})
|
||||
|
||||
for advisory_name, obj in all_advisories.items():
|
||||
await clone_advisory(
|
||||
supported_product,
|
||||
list(set(obj["mirrors"])),
|
||||
obj["advisory"],
|
||||
obj["packages"],
|
||||
obj["module_packages"],
|
||||
obj["published_at"],
|
||||
)
|
||||
|
||||
|
||||
@activity.defn
|
||||
async def block_remaining_rh_advisories(supported_product_id: int) -> None:
|
||||
supported_product = await SupportedProduct.filter(
|
||||
id=supported_product_id
|
||||
).first().prefetch_related("rh_mirrors")
|
||||
for mirror in supported_product.rh_mirrors:
|
||||
mirrors = await SupportedProductsRhMirror.filter(
|
||||
supported_product_id=supported_product_id
|
||||
)
|
||||
for mirror in mirrors:
|
||||
advisories = await get_matching_rh_advisories(mirror)
|
||||
await SupportedProductsRhBlock.bulk_create(
|
||||
[
|
||||
SupportedProductsRhBlock(
|
||||
**{
|
||||
"supported_products_rh_mirror_id": mirror.id,
|
||||
"red_hat_advsiory_id": advisory.id,
|
||||
}
|
||||
) for advisory in advisories
|
||||
],
|
||||
ignore_conflicts=True
|
||||
)
|
39
apollo/rpmworker/rh_matcher_workflows.py
Normal file
39
apollo/rpmworker/rh_matcher_workflows.py
Normal file
@ -0,0 +1,39 @@
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
|
||||
from temporalio import workflow
|
||||
|
||||
|
||||
@dataclass
|
||||
class RhDefunctWorkflowInput:
|
||||
supported_product_id: int
|
||||
|
||||
|
||||
@workflow.defn
|
||||
class RhMatcherWorkflow:
|
||||
@workflow.run
|
||||
async def run(self) -> list[int]:
|
||||
supported_product_ids = await workflow.execute_activity(
|
||||
"get_supported_products_with_rh_mirrors",
|
||||
start_to_close_timeout=datetime.timedelta(seconds=20),
|
||||
)
|
||||
|
||||
for supported_product_id in supported_product_ids:
|
||||
await workflow.execute_activity(
|
||||
"match_rh_repos",
|
||||
supported_product_id,
|
||||
start_to_close_timeout=datetime.timedelta(hours=12),
|
||||
)
|
||||
|
||||
return supported_product_ids
|
||||
|
||||
|
||||
@workflow.defn
|
||||
class RhDefunctWorkflow:
|
||||
@workflow.run
|
||||
async def run(self, wf_in: RhDefunctWorkflowInput) -> None:
|
||||
await workflow.execute_activity(
|
||||
"block_remaining_rh_advisories",
|
||||
wf_in.supported_product_id,
|
||||
start_to_close_timeout=datetime.timedelta(hours=12),
|
||||
)
|
49
apollo/rpmworker/rocky_linux.sql
Normal file
49
apollo/rpmworker/rocky_linux.sql
Normal file
@ -0,0 +1,49 @@
|
||||
insert into supported_products_rpm_repomds
|
||||
(supported_products_rh_mirror_id, production, arch, url, debug_url, source_url, repo_name)
|
||||
values
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/NFV/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/NFV/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(2, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/NFV/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/NFV/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(3, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/8/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/NFV/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/CRB/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(4, true, 'x86_64', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/NFV/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/CRB/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(5, true, 'aarch64', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/NFV/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/CRB/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(6, true, 's390x', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/NFV/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/CRB/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(7, true, 'ppc64le', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/pub/rocky/9/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA');
|
75
apollo/rpmworker/rocky_linux_older.sql
Normal file
75
apollo/rpmworker/rocky_linux_older.sql
Normal file
@ -0,0 +1,75 @@
|
||||
insert into supported_products_rpm_repomds
|
||||
(supported_products_rh_mirror_id, production, arch, url, debug_url, source_url, repo_name)
|
||||
values
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(8, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/nfv/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(9, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.4/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(10, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/nfv/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(11, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.5/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(12, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/PowerTools/source/tree/repodata/repomd.xml', 'PowerTools'),
|
||||
(13, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/8.6/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/RT/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/RT/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/RT/source/tree/repodata/repomd.xml', 'RT'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(14, true, 'x86_64', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/x86_64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/x86_64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(15, true, 'aarch64', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/aarch64/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/aarch64/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(16, true, 's390x', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/s390x/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/s390x/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/BaseOS/source/tree/repodata/repomd.xml', 'BaseOS'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/AppStream/source/tree/repodata/repomd.xml', 'AppStream'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/HighAvailability/source/tree/repodata/repomd.xml', 'HighAvailability'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/NFV/source/tree/repodata/repomd.xml', 'NFV'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/CRB/source/tree/repodata/repomd.xml', 'CRB'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/ResilientStorage/source/tree/repodata/repomd.xml', 'ResilientStorage'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAP/source/tree/repodata/repomd.xml', 'SAP'),
|
||||
(17, true, 'ppc64le', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/ppc64le/os/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/ppc64le/debug/tree/repodata/repomd.xml', 'http://dl.rockylinux.org/vault/rocky/9.0/SAPHANA/source/tree/repodata/repomd.xml', 'SAPHANA');
|
1
apollo/rpmworker/temporal.py
Normal file
1
apollo/rpmworker/temporal.py
Normal file
@ -0,0 +1 @@
|
||||
TASK_QUEUE = "v2-rpmworker"
|
591
apollo/schema.sql
Normal file
591
apollo/schema.sql
Normal file
@ -0,0 +1,591 @@
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- Name: codes; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.codes (
|
||||
id text NOT NULL,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone,
|
||||
archived_at timestamp without time zone,
|
||||
description text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_advisories (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone,
|
||||
red_hat_issued_at timestamp with time zone NOT NULL,
|
||||
name text NOT NULL,
|
||||
synopsis text NOT NULL,
|
||||
description text NOT NULL,
|
||||
kind text NOT NULL,
|
||||
severity text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_advisories_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_advisories_id_seq OWNED BY public.red_hat_advisories.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_advisory_affected_products (
|
||||
id bigint NOT NULL,
|
||||
red_hat_advisory_id bigint,
|
||||
variant text NOT NULL,
|
||||
name text NOT NULL,
|
||||
major_version numeric NOT NULL,
|
||||
minor_version numeric,
|
||||
arch text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_advisory_affected_products_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_advisory_affected_products_id_seq OWNED BY public.red_hat_advisory_affected_products.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_advisory_bugzilla_bugs (
|
||||
id bigint NOT NULL,
|
||||
red_hat_advisory_id bigint,
|
||||
bugzilla_bug_id text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_advisory_bugzilla_bugs_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_advisory_bugzilla_bugs_id_seq OWNED BY public.red_hat_advisory_bugzilla_bugs.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_advisory_cves (
|
||||
id bigint NOT NULL,
|
||||
red_hat_advisory_id bigint,
|
||||
cve text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_advisory_cves_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_advisory_cves_id_seq OWNED BY public.red_hat_advisory_cves.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_advisory_packages (
|
||||
id bigint NOT NULL,
|
||||
red_hat_advisory_id bigint,
|
||||
nevra text NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_advisory_packages_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_advisory_packages_id_seq OWNED BY public.red_hat_advisory_packages.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_index_state; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.red_hat_index_state (
|
||||
id bigint NOT NULL,
|
||||
last_indexed_at timestamp with time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_index_state_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.red_hat_index_state_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_index_state_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.red_hat_index_state_id_seq OWNED BY public.red_hat_index_state.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.schema_migrations (
|
||||
version character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.supported_products (
|
||||
id bigint NOT NULL,
|
||||
created_at timestamp with time zone DEFAULT now() NOT NULL,
|
||||
updated_at timestamp with time zone,
|
||||
eol_at timestamp with time zone,
|
||||
name text NOT NULL,
|
||||
rhel_major_version numeric,
|
||||
rhel_minor_version numeric
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.supported_products_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.supported_products_id_seq OWNED BY public.supported_products.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisories ALTER COLUMN id SET DEFAULT nextval('public.red_hat_advisories_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_affected_products ALTER COLUMN id SET DEFAULT nextval('public.red_hat_advisory_affected_products_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_bugzilla_bugs ALTER COLUMN id SET DEFAULT nextval('public.red_hat_advisory_bugzilla_bugs_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_cves ALTER COLUMN id SET DEFAULT nextval('public.red_hat_advisory_cves_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_packages ALTER COLUMN id SET DEFAULT nextval('public.red_hat_advisory_packages_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_index_state id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_index_state ALTER COLUMN id SET DEFAULT nextval('public.red_hat_index_state_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.supported_products ALTER COLUMN id SET DEFAULT nextval('public.supported_products_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: codes codes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.codes
|
||||
ADD CONSTRAINT codes_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories red_hat_advisories_name_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisories
|
||||
ADD CONSTRAINT red_hat_advisories_name_key UNIQUE (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories red_hat_advisories_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisories
|
||||
ADD CONSTRAINT red_hat_advisories_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products red_hat_advisory_affected_pro_red_hat_advisory_id_variant_n_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_affected_products
|
||||
ADD CONSTRAINT red_hat_advisory_affected_pro_red_hat_advisory_id_variant_n_key UNIQUE (red_hat_advisory_id, variant, name, major_version, minor_version, arch);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products red_hat_advisory_affected_products_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_affected_products
|
||||
ADD CONSTRAINT red_hat_advisory_affected_products_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs red_hat_advisory_bugzilla_bug_red_hat_advisory_id_bugzilla__key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_bugzilla_bugs
|
||||
ADD CONSTRAINT red_hat_advisory_bugzilla_bug_red_hat_advisory_id_bugzilla__key UNIQUE (red_hat_advisory_id, bugzilla_bug_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs red_hat_advisory_bugzilla_bugs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_bugzilla_bugs
|
||||
ADD CONSTRAINT red_hat_advisory_bugzilla_bugs_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves red_hat_advisory_cves_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_cves
|
||||
ADD CONSTRAINT red_hat_advisory_cves_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves red_hat_advisory_cves_red_hat_advisory_id_cve_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_cves
|
||||
ADD CONSTRAINT red_hat_advisory_cves_red_hat_advisory_id_cve_key UNIQUE (red_hat_advisory_id, cve);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages red_hat_advisory_packages_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_packages
|
||||
ADD CONSTRAINT red_hat_advisory_packages_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages red_hat_advisory_packages_red_hat_advisory_id_nevra_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_packages
|
||||
ADD CONSTRAINT red_hat_advisory_packages_red_hat_advisory_id_nevra_key UNIQUE (red_hat_advisory_id, nevra);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_index_state red_hat_index_state_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_index_state
|
||||
ADD CONSTRAINT red_hat_index_state_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products supported_products_name_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.supported_products
|
||||
ADD CONSTRAINT supported_products_name_key UNIQUE (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products supported_products_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.supported_products
|
||||
ADD CONSTRAINT supported_products_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_kindx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisories_kindx ON public.red_hat_advisories USING btree (kind);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_namex; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisories_namex ON public.red_hat_advisories USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_red_hat_issued_atx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisories_red_hat_issued_atx ON public.red_hat_advisories USING btree (red_hat_issued_at);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_severityx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisories_severityx ON public.red_hat_advisories USING btree (severity);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisories_synopsisx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisories_synopsisx ON public.red_hat_advisories USING btree (synopsis);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_archx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_affected_products_archx ON public.red_hat_advisory_affected_products USING btree (arch);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_major_versionx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_affected_products_major_versionx ON public.red_hat_advisory_affected_products USING btree (major_version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_minor_versionx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_affected_products_minor_versionx ON public.red_hat_advisory_affected_products USING btree (minor_version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_namex; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_affected_products_namex ON public.red_hat_advisory_affected_products USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products_variantx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_affected_products_variantx ON public.red_hat_advisory_affected_products USING btree (variant);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs_bugzilla_bug_idx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_bugzilla_bugs_bugzilla_bug_idx ON public.red_hat_advisory_bugzilla_bugs USING btree (bugzilla_bug_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cvex; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_cvex ON public.red_hat_advisory_cves USING btree (cve);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages_nevrax; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX red_hat_advisory_packages_nevrax ON public.red_hat_advisory_packages USING btree (nevra);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_eol_atx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX supported_products_eol_atx ON public.supported_products USING btree (eol_at);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_namex; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX supported_products_namex ON public.supported_products USING btree (name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_rhel_major_versionx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX supported_products_rhel_major_versionx ON public.supported_products USING btree (rhel_major_version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: supported_products_rhel_minor_versionx; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX supported_products_rhel_minor_versionx ON public.supported_products USING btree (rhel_minor_version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_affected_products red_hat_advisory_affected_products_red_hat_advisory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_affected_products
|
||||
ADD CONSTRAINT red_hat_advisory_affected_products_red_hat_advisory_id_fkey FOREIGN KEY (red_hat_advisory_id) REFERENCES public.red_hat_advisories(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_bugzilla_bugs red_hat_advisory_bugzilla_bugs_red_hat_advisory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_bugzilla_bugs
|
||||
ADD CONSTRAINT red_hat_advisory_bugzilla_bugs_red_hat_advisory_id_fkey FOREIGN KEY (red_hat_advisory_id) REFERENCES public.red_hat_advisories(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_cves red_hat_advisory_cves_red_hat_advisory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_cves
|
||||
ADD CONSTRAINT red_hat_advisory_cves_red_hat_advisory_id_fkey FOREIGN KEY (red_hat_advisory_id) REFERENCES public.red_hat_advisories(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: red_hat_advisory_packages red_hat_advisory_packages_red_hat_advisory_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.red_hat_advisory_packages
|
||||
ADD CONSTRAINT red_hat_advisory_packages_red_hat_advisory_id_fkey FOREIGN KEY (red_hat_advisory_id) REFERENCES public.red_hat_advisories(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Dbmate schema migrations
|
||||
--
|
||||
|
||||
INSERT INTO public.schema_migrations (version) VALUES
|
||||
('20230128201227');
|
48
apollo/server/BUILD.bazel
Normal file
48
apollo/server/BUILD.bazel
Normal file
@ -0,0 +1,48 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
load("//build/macros:fastapi.bzl", "fastapi_binary")
|
||||
|
||||
py_library(
|
||||
name = "server_lib",
|
||||
srcs = [
|
||||
"roles.py",
|
||||
"routes/admin_index.py",
|
||||
"routes/advisories.py",
|
||||
"routes/api_advisories.py",
|
||||
"routes/api_compat.py",
|
||||
"routes/api_red_hat.py",
|
||||
"routes/login.py",
|
||||
"routes/logout.py",
|
||||
"routes/red_hat_advisories.py",
|
||||
"routes/statistics.py",
|
||||
"server.py",
|
||||
"settings.py",
|
||||
"utils.py",
|
||||
],
|
||||
data = [
|
||||
":assets",
|
||||
":templates",
|
||||
"//apollo/server/static",
|
||||
],
|
||||
imports = ["../.."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"//apollo/db:db_lib",
|
||||
"//apollo/db/serialize:serialize_lib",
|
||||
"//common:common_lib",
|
||||
"@pypi_fastapi//:pkg",
|
||||
"@pypi_fastapi_pagination//:pkg",
|
||||
"@pypi_itsdangerous//:pkg",
|
||||
"@pypi_jinja2//:pkg",
|
||||
"@pypi_passlib//:pkg",
|
||||
"@pypi_python_multipart//:pkg",
|
||||
"@pypi_starlette//:pkg",
|
||||
"@pypi_tortoise_orm//:pkg",
|
||||
],
|
||||
)
|
||||
|
||||
fastapi_binary(
|
||||
name = "server",
|
||||
imports = ["../.."],
|
||||
path = "apollo.server.server",
|
||||
port = "9999",
|
||||
)
|
11
apollo/server/assets/pd-logo-np.svg
Normal file
11
apollo/server/assets/pd-logo-np.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="369" height="322" viewBox="0 0 369 322" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M270.625 0.000793457H97.7074C93.6888 0.000793457 89.9753 2.1446 87.966 5.62505L1.5072 155.376C-0.502076 158.856 -0.502076 163.144 1.5072 166.624L87.966 316.376C89.9753 319.856 93.6888 322 97.7074 322H270.625C274.643 322 278.357 319.856 280.366 316.376L366.825 166.624C368.834 163.144 368.834 158.856 366.825 155.376L280.366 5.62505C278.357 2.1446 274.643 0.000793457 270.625 0.000793457Z" fill="#FFD45D"/>
|
||||
<path d="M368.332 161H294.609L239.387 256.646L276.249 320.492C277.931 319.521 279.362 318.115 280.366 316.375L366.825 166.624C367.83 164.884 368.332 162.942 368.332 161Z" fill="#007362"/>
|
||||
<path d="M239.387 256.646H128.945L92.083 320.492C93.765 321.463 95.698 321.999 97.7073 321.999H270.625C272.634 321.999 274.567 321.463 276.249 320.492L239.387 256.646Z" fill="#00984C"/>
|
||||
<path d="M128.945 256.646L73.7233 161H0C0 162.942 0.50214 164.884 1.50714 166.624L87.9659 316.376C88.9709 318.116 90.4011 319.522 92.083 320.493L128.945 256.646Z" fill="#41A93D"/>
|
||||
<path d="M128.945 65.3538L92.083 1.50714C90.4011 2.47833 88.9702 3.88403 87.9659 5.62426L1.50714 155.376C0.50214 157.116 0 159.058 0 161H73.7233L128.945 65.3538Z" fill="#7DB82F"/>
|
||||
<path d="M128.945 65.3538H239.387L276.249 1.50714C274.567 0.535953 272.634 0 270.625 0H97.7073C95.698 0 93.765 0.535953 92.083 1.50714L128.945 65.3538Z" fill="#41A93D"/>
|
||||
<path d="M239.387 65.3538L294.609 161H368.332C368.332 159.058 367.83 157.116 366.825 155.376L280.366 5.62426C279.362 3.88403 277.931 2.47833 276.249 1.50714L239.387 65.3538Z" fill="#00984C"/>
|
||||
<path d="M239.388 65.3538H128.944L73.7231 161L128.944 256.646H239.388L294.609 161L239.388 65.3538Z" fill="#008658"/>
|
||||
<path d="M130.935 58.6569L137.975 53.3988C139.577 52.2025 141.696 53.9894 140.788 55.7707L136.795 63.5977C136.369 64.4344 136.621 65.4567 137.388 65.9984L144.564 71.0687C146.197 72.2226 145.152 74.7909 143.178 74.4765L134.5 73.0974C133.572 72.9499 132.677 73.506 132.399 74.4031L129.794 82.7949C129.201 84.7042 126.436 84.5042 126.124 82.5294L124.754 73.8506C124.607 72.9233 123.802 72.2442 122.863 72.2564L114.077 72.3722C112.078 72.3989 111.413 69.7069 113.195 68.8004L121.026 64.815C121.863 64.3891 122.26 63.4136 121.958 62.5244L119.132 54.2046C118.489 52.3111 120.844 50.8478 122.258 52.2622L128.467 58.4785C129.132 59.1425 130.182 59.2188 130.935 58.6569Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
2
apollo/server/roles.py
Normal file
2
apollo/server/roles.py
Normal file
@ -0,0 +1,2 @@
|
||||
ADMIN = "admin"
|
||||
ELEVATED = "elevated"
|
15
apollo/server/routes/admin_index.py
Normal file
15
apollo/server/routes/admin_index.py
Normal file
@ -0,0 +1,15 @@
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
from apollo.server.utils import templates
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
async def admin_general(request: Request):
|
||||
return templates.TemplateResponse(
|
||||
"admin_index.jinja", {
|
||||
"request": request,
|
||||
}
|
||||
)
|
127
apollo/server/routes/advisories.py
Normal file
127
apollo/server/routes/advisories.py
Normal file
@ -0,0 +1,127 @@
|
||||
from math import ceil
|
||||
|
||||
from tortoise import connections
|
||||
|
||||
from fastapi import APIRouter, Request, Depends
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.tortoise import paginate, create_page
|
||||
|
||||
from apollo.db import Advisory
|
||||
from apollo.server.utils import templates
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def list_advisories(
|
||||
request: Request,
|
||||
params: Params = Depends(),
|
||||
search: str = None,
|
||||
):
|
||||
params.size = 50
|
||||
if search:
|
||||
a = """
|
||||
with vars (search, size, page_offset) as (
|
||||
values ($1 :: text, $2 :: bigint, $3 :: bigint)
|
||||
)
|
||||
select
|
||||
a.id,
|
||||
a.created_at,
|
||||
a.updated_at,
|
||||
a.published_at,
|
||||
a.name,
|
||||
a.synopsis,
|
||||
a.description,
|
||||
a.kind,
|
||||
a.severity,
|
||||
a.red_hat_advisory_id,
|
||||
count(a.*) over () as total
|
||||
from
|
||||
advisories a
|
||||
left outer join advisory_affected_products ap on ap.advisory_id = a.id
|
||||
left outer join advisory_cves c on c.advisory_id = a.id
|
||||
left outer join advisory_fixes f on f.advisory_id = a.id
|
||||
where
|
||||
(select search from vars) is null or
|
||||
ap.name ilike '%' || (select search from vars) || '%' or
|
||||
a.synopsis ilike '%' || (select search from vars) || '%' or
|
||||
a.description ilike '%' || (select search from vars) || '%' or
|
||||
exists (select cve from advisory_cves where advisory_id = a.id and cve ilike '%' || (select search from vars) || '%') or
|
||||
exists (select ticket_id from advisory_fixes where advisory_id = a.id and ticket_id ilike '%' || (select search from vars) || '%') or
|
||||
a.name ilike '%' || (select search from vars) || '%'
|
||||
group by a.id
|
||||
order by a.published_at desc
|
||||
limit (select size from vars) offset (select page_offset from vars)
|
||||
"""
|
||||
|
||||
connection = connections.get("default")
|
||||
results = await connections.execute_query(
|
||||
a, [search, params.size, params.size * (params.page - 1)]
|
||||
)
|
||||
count = 0
|
||||
if results:
|
||||
if results[1]:
|
||||
count = results[1][0]["total"]
|
||||
|
||||
advisories = create_page(
|
||||
results[1],
|
||||
count,
|
||||
params,
|
||||
)
|
||||
else:
|
||||
advisories = await paginate(
|
||||
Advisory.all().order_by("-published_at"),
|
||||
params=params,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"advisories.jinja", {
|
||||
"request": request,
|
||||
"params": params,
|
||||
"search": search if search else "",
|
||||
"advisories": advisories,
|
||||
"advisories_pages": ceil(advisories.total / advisories.size)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{advisory_name}",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def get_advisory(request: Request, advisory_name: str):
|
||||
advisory = await Advisory.get_or_none(name=advisory_name,
|
||||
).prefetch_related(
|
||||
"red_hat_advisory",
|
||||
"packages",
|
||||
"cves",
|
||||
"fixes",
|
||||
"affected_products",
|
||||
)
|
||||
if advisory is None:
|
||||
return templates.TemplateResponse(
|
||||
"error.jinja", {
|
||||
"request": request,
|
||||
"message": "Requested advisory not found",
|
||||
}
|
||||
)
|
||||
|
||||
package_map = {}
|
||||
for package in advisory.packages:
|
||||
name = f"{package.product_name} - {package.repo_name}"
|
||||
if name not in package_map:
|
||||
package_map[name] = []
|
||||
|
||||
package_map[name].append(package.nevra)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"advisory.jinja", {
|
||||
"request": request,
|
||||
"title": f"Advisory {advisory.id}",
|
||||
"advisory": advisory,
|
||||
"package_map": package_map,
|
||||
}
|
||||
)
|
56
apollo/server/routes/api_advisories.py
Normal file
56
apollo/server/routes/api_advisories.py
Normal file
@ -0,0 +1,56 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi_pagination.links import Page
|
||||
from fastapi_pagination.ext.tortoise import paginate
|
||||
|
||||
from apollo.db import Advisory
|
||||
from apollo.db.serialize import Advisory_Pydantic
|
||||
|
||||
router = APIRouter(tags=["advisories"])
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Pagination(Page[T], Generic[T]):
|
||||
class Config:
|
||||
allow_population_by_field_name = True
|
||||
fields = {"items": {"alias": "advisories"}}
|
||||
|
||||
|
||||
@router.get(
|
||||
"/",
|
||||
response_model=Pagination[Advisory_Pydantic],
|
||||
)
|
||||
async def list_advisories():
|
||||
advisories = await paginate(
|
||||
Advisory.all().prefetch_related(
|
||||
"red_hat_advisory",
|
||||
"packages",
|
||||
"cves",
|
||||
"fixes",
|
||||
"affected_products",
|
||||
).order_by("-published_at"),
|
||||
)
|
||||
|
||||
return advisories
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{advisory_name}",
|
||||
response_model=Advisory_Pydantic,
|
||||
)
|
||||
async def get_advisory(advisory_name: str):
|
||||
advisory = await Advisory.filter(name=advisory_name).prefetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"fixes",
|
||||
"affected_products",
|
||||
"red_hat_advisory",
|
||||
).first()
|
||||
|
||||
if advisory is None:
|
||||
raise HTTPException(404)
|
||||
|
||||
return await Advisory_Pydantic.from_tortoise_orm(advisory)
|
241
apollo/server/routes/api_compat.py
Normal file
241
apollo/server/routes/api_compat.py
Normal file
@ -0,0 +1,241 @@
|
||||
"""
|
||||
This module implements the compatibility API for Apollo V2 advisories
|
||||
"""
|
||||
|
||||
import datetime
|
||||
from typing import TypeVar, Generic, Optional
|
||||
|
||||
from tortoise import connections
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi_pagination.links import Page
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.tortoise import create_page
|
||||
|
||||
from apollo.db import Advisory, RedHatIndexState
|
||||
from apollo.db.serialize import Advisory_Pydantic_V2, Advisory_Pydantic_V2_CVE, Advisory_Pydantic_V2_Fix
|
||||
|
||||
from common.fastapi import RenderErrorTemplateException
|
||||
|
||||
router = APIRouter(tags=["v2_compat"])
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Pagination(Page[T], Generic[T]):
|
||||
lastUpdated: Optional[str] # noqa # pylint: disable=invalid-name
|
||||
|
||||
class Config:
|
||||
allow_population_by_field_name = True
|
||||
fields = {"items": {"alias": "advisories"}}
|
||||
|
||||
|
||||
def v3_advisory_to_v2(
|
||||
advisory: Advisory,
|
||||
include_rpms=True,
|
||||
) -> Advisory_Pydantic_V2:
|
||||
kind = "TYPE_SECURITY"
|
||||
if advisory.kind == "Bug Fix":
|
||||
kind = "TYPE_BUGFIX"
|
||||
elif advisory.kind == "Enhancement":
|
||||
kind = "TYPE_ENHANCEMENT"
|
||||
|
||||
affected_products = list(
|
||||
set(
|
||||
[
|
||||
f"{ap.variant} {ap.major_version}"
|
||||
for ap in advisory.affected_products
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
cves = []
|
||||
for cve in advisory.cves:
|
||||
cves.append(
|
||||
Advisory_Pydantic_V2_CVE(
|
||||
name=cve.cve,
|
||||
cvss3ScoringVector=cve.cvss3_scoring_vector,
|
||||
cvss3BaseScore=cve.cvss3_base_score,
|
||||
cwe=cve.cwe,
|
||||
sourceBy="Red Hat",
|
||||
sourceLink=
|
||||
f"https://access.redhat.com/hydra/rest/securitydata/cve/{cve.cve}.json",
|
||||
)
|
||||
)
|
||||
|
||||
fixes = []
|
||||
for fix in advisory.fixes:
|
||||
fixes.append(
|
||||
Advisory_Pydantic_V2_Fix(
|
||||
ticket=fix.ticket_id,
|
||||
sourceBy="Red Hat",
|
||||
sourceLink=fix.source,
|
||||
description=fix.description,
|
||||
)
|
||||
)
|
||||
|
||||
rpms = {}
|
||||
if include_rpms:
|
||||
for pkg in advisory.packages:
|
||||
name = f"{pkg.supported_product.variant} {pkg.supported_products_rh_mirror.match_major_version}"
|
||||
if name not in rpms:
|
||||
rpms[name] = []
|
||||
rpms[name].append(pkg.nevra)
|
||||
|
||||
return Advisory_Pydantic_V2(
|
||||
id=advisory.id,
|
||||
publishedAt=advisory.published_at,
|
||||
name=advisory.name,
|
||||
synopsis=advisory.synopsis,
|
||||
description=advisory.description,
|
||||
type=kind,
|
||||
severity=f"SEVERITY_{advisory.severity.upper()}",
|
||||
shortCode=advisory.name[0:2],
|
||||
topic=advisory.topic if advisory.topic else "",
|
||||
solution=None,
|
||||
rpms=rpms,
|
||||
affectedProducts=affected_products,
|
||||
references=[],
|
||||
rebootSuggested=False,
|
||||
buildReferences=[],
|
||||
fixes=fixes,
|
||||
cves=cves,
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/",
|
||||
response_model=Pagination[Advisory_Pydantic_V2],
|
||||
)
|
||||
async def list_advisories_compat_v2(
|
||||
params: Params = Depends(),
|
||||
product: str = Query(default=None, alias="filters.product"),
|
||||
before_raw: str = Query(default=None, alias="filters.before"),
|
||||
after_raw: str = Query(default=None, alias="filters.after"),
|
||||
cve: str = Query(default=None, alias="filters.cve"),
|
||||
synopsis: str = Query(default=None, alias="filters.synopsis"),
|
||||
keyword: str = Query(default=None, alias="filters.keyword"),
|
||||
severity: str = Query(default=None, alias="filters.severity"),
|
||||
kind: str = Query(default=None, alias="filters.type"),
|
||||
):
|
||||
before = None
|
||||
after = None
|
||||
|
||||
try:
|
||||
if before_raw:
|
||||
before = datetime.datetime.fromisoformat(
|
||||
before_raw.removesuffix("Z")
|
||||
)
|
||||
except:
|
||||
raise RenderErrorTemplateException("Invalid before date", 400)
|
||||
|
||||
try:
|
||||
if after_raw:
|
||||
after = datetime.datetime.fromisoformat(after_raw.removesuffix("Z"))
|
||||
except:
|
||||
raise RenderErrorTemplateException("Invalid after date", 400)
|
||||
|
||||
state = await RedHatIndexState.first()
|
||||
|
||||
a = """
|
||||
with vars (search, size, page_offset, product, before, after, cve, synopsis, severity, kind) as (
|
||||
values ($1 :: text, $2 :: bigint, $3 :: bigint, $4 :: text, $5 :: timestamp, $6 :: timestamp, $7 :: text, $8 :: text, $9 :: text, $10 :: text)
|
||||
)
|
||||
select
|
||||
a.id,
|
||||
a.created_at,
|
||||
a.updated_at,
|
||||
a.published_at,
|
||||
a.name,
|
||||
a.synopsis,
|
||||
a.description,
|
||||
a.kind,
|
||||
a.severity,
|
||||
a.topic,
|
||||
a.red_hat_advisory_id,
|
||||
count(a.*) over () as total
|
||||
from
|
||||
advisories a
|
||||
left outer join advisory_affected_products ap on ap.advisory_id = a.id
|
||||
left outer join advisory_cves c on c.advisory_id = a.id
|
||||
left outer join advisory_fixes f on f.advisory_id = a.id
|
||||
where
|
||||
((select product from vars) is null or ap.name ilike '%' || (select product from vars) || '%')
|
||||
and ((select before from vars) is null or a.published_at < (select before from vars))
|
||||
and ((select after from vars) is null or a.published_at > (select after from vars))
|
||||
and (a.published_at is not null)
|
||||
and ((select cve from vars) is null or exists (select cve from advisory_cves where advisory_id = a.id and cve ilike '%' || (select cve from vars) || '%'))
|
||||
and ((select synopsis from vars) is null or a.synopsis ilike '%' || (select synopsis from vars) || '%')
|
||||
and ((select severity from vars) is null or a.severity = (select severity from vars))
|
||||
and ((select kind from vars) is null or a.kind = (select kind from vars))
|
||||
and ((select search from vars) is null or
|
||||
ap.name ilike '%' || (select search from vars) || '%' or
|
||||
a.synopsis ilike '%' || (select search from vars) || '%' or
|
||||
a.description ilike '%' || (select search from vars) || '%' or
|
||||
exists (select cve from advisory_cves where advisory_id = a.id and cve ilike '%' || (select search from vars) || '%') or
|
||||
exists (select ticket_id from advisory_fixes where advisory_id = a.id and ticket_id ilike '%' || (select search from vars) || '%') or
|
||||
a.name ilike '%' || (select search from vars) || '%')
|
||||
group by a.id
|
||||
order by a.published_at desc
|
||||
limit (select size from vars) offset (select page_offset from vars)
|
||||
"""
|
||||
|
||||
connection = connections.get("default")
|
||||
results = await connection.execute_query(
|
||||
a, [
|
||||
keyword, params.size, params.size * (params.page - 1), product,
|
||||
before, after, cve, synopsis, severity, kind
|
||||
]
|
||||
)
|
||||
|
||||
count = 0
|
||||
if results:
|
||||
if results[1]:
|
||||
count = results[1][0]["total"]
|
||||
|
||||
advisories = []
|
||||
for adv in results[1]:
|
||||
advisory = Advisory(**adv)
|
||||
await advisory.fetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"fixes",
|
||||
"affected_products",
|
||||
"packages",
|
||||
"packages__supported_product",
|
||||
"packages__supported_products_rh_mirror",
|
||||
)
|
||||
advisories.append(advisory)
|
||||
|
||||
v2_advisories: list[Advisory_Pydantic_V2] = []
|
||||
for advisory in advisories:
|
||||
v2_advisories.append(v3_advisory_to_v2(advisory))
|
||||
|
||||
page = create_page(v2_advisories, count, params)
|
||||
page.lastUpdated = state.last_indexed_at.isoformat("T").replace(
|
||||
"+00:00", ""
|
||||
) + "Z"
|
||||
|
||||
return page
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{advisory_name}",
|
||||
response_model=Advisory_Pydantic_V2,
|
||||
)
|
||||
async def get_advisory_compat_v2(advisory_name: str):
|
||||
advisory = await Advisory.filter(name=advisory_name).prefetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"fixes",
|
||||
"affected_products",
|
||||
"packages",
|
||||
"packages__supported_product",
|
||||
"packages__supported_products_rh_mirror",
|
||||
).get_or_none()
|
||||
|
||||
if not advisory:
|
||||
raise HTTPException(404)
|
||||
|
||||
return Advisory_Pydantic_V2.from_orm(v3_advisory_to_v2(advisory))
|
59
apollo/server/routes/api_red_hat.py
Normal file
59
apollo/server/routes/api_red_hat.py
Normal file
@ -0,0 +1,59 @@
|
||||
from typing import TypeVar, Generic
|
||||
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.exceptions import HTTPException
|
||||
from fastapi_pagination.links import Page
|
||||
from fastapi_pagination.ext.tortoise import paginate
|
||||
|
||||
from apollo.db import RedHatAdvisory
|
||||
from apollo.db.serialize import RedHatAdvisory_Pydantic
|
||||
|
||||
router = APIRouter(tags=["red_hat"])
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class Pagination(Page[T], Generic[T]):
|
||||
class Config:
|
||||
allow_population_by_field_name = True
|
||||
fields = {"items": {"alias": "advisories"}}
|
||||
|
||||
|
||||
@router.get(
|
||||
"/advisories",
|
||||
response_model=Pagination[RedHatAdvisory_Pydantic],
|
||||
)
|
||||
async def list_red_hat_advisories(request: Request):
|
||||
if not request.state.settings.serve_rh_advisories:
|
||||
raise HTTPException(404)
|
||||
|
||||
advisories = await paginate(
|
||||
RedHatAdvisory.all().prefetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"bugzilla_tickets",
|
||||
"affected_products",
|
||||
).order_by("-red_hat_issued_at")
|
||||
)
|
||||
return advisories
|
||||
|
||||
|
||||
@router.get(
|
||||
"/advisories/{advisory_name}",
|
||||
response_model=RedHatAdvisory_Pydantic,
|
||||
)
|
||||
async def get_red_hat_advisory(request: Request, advisory_name: str):
|
||||
if not request.state.settings.serve_rh_advisories:
|
||||
raise HTTPException(404)
|
||||
|
||||
advisory = await RedHatAdvisory.filter(name=advisory_name).prefetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"bugzilla_tickets",
|
||||
"affected_products",
|
||||
).first()
|
||||
|
||||
if advisory is None:
|
||||
raise HTTPException(404)
|
||||
|
||||
return RedHatAdvisory_Pydantic.from_orm(advisory)
|
132
apollo/server/routes/login.py
Normal file
132
apollo/server/routes/login.py
Normal file
@ -0,0 +1,132 @@
|
||||
from fastapi import APIRouter, Request, Form
|
||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||||
from tortoise.expressions import Q
|
||||
|
||||
from apollo.server.utils import templates
|
||||
from apollo.server.roles import ADMIN
|
||||
from apollo.server.utils import pwd_context
|
||||
from apollo.server.settings import OIDC_PROVIDER_NAME, OIDC_PROVIDER, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET
|
||||
from apollo.db import User, Settings
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
async def login_page(request: Request):
|
||||
if request.session.get("user"):
|
||||
return RedirectResponse("/", status_code=302)
|
||||
|
||||
user_count = await User.all().count()
|
||||
should_show_setup = user_count == 0
|
||||
|
||||
ctx = {
|
||||
"request": request,
|
||||
"should_show_setup": should_show_setup,
|
||||
}
|
||||
if not should_show_setup:
|
||||
# Check if we have OIDC_PROVIDER, OIDC_CLIENT_ID and OIDC_CLIENT_SECRET set
|
||||
# If so, show the OIDC login button
|
||||
# If OIDC_PROVIDER_NAME is set, use that as the button text
|
||||
# Otherwise, use "Login with OIDC"
|
||||
settings = await Settings.filter(
|
||||
Q(name=OIDC_PROVIDER_NAME) | Q(name=OIDC_PROVIDER) |
|
||||
Q(name=OIDC_CLIENT_ID) | Q(name=OIDC_CLIENT_SECRET)
|
||||
).all()
|
||||
if len(settings) >= 3:
|
||||
provider_name = "Login with OIDC"
|
||||
# Check if we have OIDC_PROVIDER_NAME set
|
||||
for setting in settings:
|
||||
if setting.name == OIDC_PROVIDER_NAME:
|
||||
provider_name = setting.value
|
||||
break
|
||||
ctx["oidc_provider_name"] = provider_name
|
||||
|
||||
return templates.TemplateResponse("login.jinja", ctx)
|
||||
|
||||
|
||||
@router.post("/", response_class=HTMLResponse)
|
||||
async def do_login(
|
||||
request: Request,
|
||||
email: str = Form(default=None),
|
||||
password: str = Form(default=None)
|
||||
):
|
||||
if request.session.get("user"):
|
||||
return RedirectResponse("/", status_code=302)
|
||||
if not email or not password:
|
||||
return templates.TemplateResponse(
|
||||
"login.jinja", {
|
||||
"request": request,
|
||||
"error": "Email and password are required",
|
||||
}
|
||||
)
|
||||
|
||||
user = await User.get(email=email)
|
||||
if not user:
|
||||
return templates.TemplateResponse(
|
||||
"login.jinja", {
|
||||
"request": request,
|
||||
"error": "Invalid email or password",
|
||||
}
|
||||
)
|
||||
|
||||
if not pwd_context.verify(password, user.password):
|
||||
return templates.TemplateResponse(
|
||||
"login.jinja", {
|
||||
"request": request,
|
||||
"error": "Invalid email or password",
|
||||
}
|
||||
)
|
||||
|
||||
request.session["user"] = user.id
|
||||
request.session["user.name"] = user.name
|
||||
request.session["user.role"] = user.role
|
||||
return RedirectResponse("/", status_code=302)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/setup",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def setup_page(
|
||||
request: Request,
|
||||
name: str = Form(default=None),
|
||||
email: str = Form(default=None),
|
||||
password: str = Form(default=None),
|
||||
confirm_password: str = Form(default=None),
|
||||
):
|
||||
user_count = await User.all().count()
|
||||
if user_count > 0:
|
||||
return RedirectResponse("/")
|
||||
|
||||
error = None
|
||||
if not name:
|
||||
error = "Name is required"
|
||||
elif not email:
|
||||
error = "Email is required"
|
||||
elif "@" not in email:
|
||||
error = "Email is invalid"
|
||||
elif not password:
|
||||
error = "Password is required"
|
||||
elif not confirm_password:
|
||||
error = "Confirm password is required"
|
||||
elif password != confirm_password:
|
||||
error = "Passwords do not match"
|
||||
|
||||
if error:
|
||||
return templates.TemplateResponse(
|
||||
"login.jinja", {
|
||||
"request": request,
|
||||
"should_show_setup": True,
|
||||
"error": error,
|
||||
}
|
||||
)
|
||||
|
||||
await User.create(
|
||||
name=name, email=email, password=pwd_context.hash(password), role=ADMIN
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"login.jinja", {
|
||||
"request": request,
|
||||
"should_show_setup_success": True,
|
||||
}
|
||||
)
|
16
apollo/server/routes/logout.py
Normal file
16
apollo/server/routes/logout.py
Normal file
@ -0,0 +1,16 @@
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get("/")
|
||||
async def logout(request: Request):
|
||||
if request.session.get("user"):
|
||||
request.session.pop("user")
|
||||
if request.session.get("user.name"):
|
||||
request.session.pop("user.name")
|
||||
if request.session.get("user.role"):
|
||||
request.session.pop("user.role")
|
||||
|
||||
return RedirectResponse("/", status_code=302)
|
85
apollo/server/routes/red_hat_advisories.py
Normal file
85
apollo/server/routes/red_hat_advisories.py
Normal file
@ -0,0 +1,85 @@
|
||||
from math import ceil
|
||||
|
||||
from fastapi import APIRouter, Request, Depends, Form
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi_pagination import Params
|
||||
from fastapi_pagination.ext.tortoise import paginate
|
||||
|
||||
from apollo.db import RedHatAdvisory
|
||||
from apollo.server.utils import admin_user_scheme, templates
|
||||
|
||||
from common.fastapi import RenderErrorTemplateException
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get(
|
||||
"/advisories",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def list_red_hat_advisories(request: Request, params: Params = Depends()):
|
||||
if not request.state.settings.serve_rh_advisories:
|
||||
raise RenderErrorTemplateException()
|
||||
|
||||
params.size = 50
|
||||
advisories = await paginate(
|
||||
RedHatAdvisory.all().order_by("-red_hat_issued_at"),
|
||||
params=params,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"red_hat_advisories.jinja", {
|
||||
"request": request,
|
||||
"advisories": advisories,
|
||||
"advisories_pages": ceil(advisories.total / advisories.size),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/advisories/{advisory_name}",
|
||||
response_class=HTMLResponse,
|
||||
)
|
||||
async def get_red_hat_advisory(request: Request, advisory_name: str):
|
||||
if not request.state.settings.serve_rh_advisories:
|
||||
raise RenderErrorTemplateException()
|
||||
|
||||
advisory = await RedHatAdvisory.get_or_none(
|
||||
name=advisory_name,
|
||||
).prefetch_related(
|
||||
"packages",
|
||||
"cves",
|
||||
"bugzilla_tickets",
|
||||
"affected_products",
|
||||
"rpm_rh_overrides",
|
||||
"rpm_rh_overrides__supported_products_rh_mirror",
|
||||
"published_advisories",
|
||||
)
|
||||
if advisory is None:
|
||||
return templates.TemplateResponse(
|
||||
"error.jinja", {
|
||||
"request": request,
|
||||
"message": "Requested advisory not found",
|
||||
}
|
||||
)
|
||||
|
||||
return templates.TemplateResponse(
|
||||
"red_hat_advisory.jinja", {
|
||||
"request": request,
|
||||
"advisory": advisory,
|
||||
"title": f"Red Hat Advisory {advisory.id}",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/advisories/{advisory_name}",
|
||||
response_class=HTMLResponse,
|
||||
dependencies=[Depends(admin_user_scheme)],
|
||||
)
|
||||
async def execute_red_hat_advisory_action(
|
||||
request: Request,
|
||||
advisory_name: str,
|
||||
action: str = Form(),
|
||||
data: str = Form()
|
||||
):
|
||||
pass
|
20
apollo/server/routes/statistics.py
Normal file
20
apollo/server/routes/statistics.py
Normal file
@ -0,0 +1,20 @@
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from apollo.db import RedHatAdvisory, Advisory
|
||||
|
||||
from apollo.server.utils import templates
|
||||
|
||||
router = APIRouter(tags=["non-api"])
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
async def statistics(request: Request):
|
||||
rh_advisory_count = await RedHatAdvisory.all().count()
|
||||
advisory_count = await Advisory.all().count()
|
||||
return templates.TemplateResponse(
|
||||
"index.jinja", {
|
||||
"request": request,
|
||||
"rh_advisory_count": rh_advisory_count,
|
||||
"advisory_count": advisory_count,
|
||||
}
|
||||
)
|
103
apollo/server/server.py
Normal file
103
apollo/server/server.py
Normal file
@ -0,0 +1,103 @@
|
||||
import secrets
|
||||
|
||||
from tortoise import Tortoise
|
||||
|
||||
Tortoise.init_models(["apollo.db"], "models") # noqa # pylint: disable=wrong-import-position
|
||||
|
||||
from fastapi import FastAPI, Request, Depends
|
||||
from fastapi.responses import JSONResponse
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
from fastapi_pagination import add_pagination
|
||||
|
||||
from apollo.server.routes.statistics import router as statistics_router
|
||||
from apollo.server.routes.login import router as login_router
|
||||
from apollo.server.routes.logout import router as logout_router
|
||||
from apollo.server.routes.admin_index import router as admin_index_router
|
||||
from apollo.server.routes.api_advisories import router as api_advisories_router
|
||||
from apollo.server.routes.api_compat import router as api_compat_router
|
||||
from apollo.server.routes.api_red_hat import router as api_red_hat_router
|
||||
from apollo.server.routes.advisories import router as advisories_router
|
||||
from apollo.server.routes.red_hat_advisories import router as red_hat_advisories_router
|
||||
from apollo.server.settings import SECRET_KEY, SettingsMiddleware, get_setting
|
||||
from apollo.server.utils import admin_user_scheme, templates
|
||||
from apollo.db import Settings
|
||||
|
||||
from common.info import Info
|
||||
from common.logger import Logger
|
||||
from common.database import Database
|
||||
from common.fastapi import StaticFilesSym, RenderErrorTemplateException
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
app.mount(
|
||||
"/static", StaticFilesSym(directory="apollo/server/static"), name="static"
|
||||
)
|
||||
app.mount(
|
||||
"/assets", StaticFilesSym(directory="apollo/server/assets"), name="assets"
|
||||
)
|
||||
|
||||
app.add_middleware(SettingsMiddleware)
|
||||
|
||||
app.include_router(advisories_router)
|
||||
app.include_router(statistics_router, prefix="/statistics")
|
||||
app.include_router(login_router, prefix="/login")
|
||||
app.include_router(logout_router, prefix="/logout")
|
||||
app.include_router(
|
||||
admin_index_router,
|
||||
prefix="/admin",
|
||||
dependencies=[Depends(admin_user_scheme)]
|
||||
)
|
||||
app.include_router(red_hat_advisories_router, prefix="/red_hat")
|
||||
app.include_router(api_advisories_router, prefix="/api/v3/advisories")
|
||||
app.include_router(api_compat_router, prefix="/v2/advisories")
|
||||
app.include_router(api_red_hat_router, prefix="/api/v3/red_hat")
|
||||
|
||||
add_pagination(app)
|
||||
|
||||
Info("apollo2")
|
||||
Logger()
|
||||
Database(True, app, ["apollo.db"])
|
||||
|
||||
|
||||
@app.exception_handler(404)
|
||||
async def not_found_handler(request, exc):
|
||||
if request.url.path.startswith("/api"
|
||||
) or request.url.path.startswith("/v2"):
|
||||
return JSONResponse({"error": "Not found"}, status_code=404)
|
||||
return await render_template_exception_handler(request, None)
|
||||
|
||||
|
||||
@app.exception_handler(RenderErrorTemplateException)
|
||||
async def render_template_exception_handler(
|
||||
request: Request, exc: RenderErrorTemplateException
|
||||
):
|
||||
if request.url.path.startswith("/api"
|
||||
) or request.url.path.startswith("/v2"):
|
||||
return JSONResponse(
|
||||
{"error": exc.msg if exc and exc.msg else "Not found"},
|
||||
status_code=exc.status_code if exc and exc.status_code else 404,
|
||||
)
|
||||
return templates.TemplateResponse(
|
||||
"error.jinja", {
|
||||
"request": request,
|
||||
"message": exc.msg if exc and exc.msg else "Page not found",
|
||||
},
|
||||
status_code=exc.status_code if exc and exc.status_code else 404
|
||||
)
|
||||
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup():
|
||||
# Generate secret-key if it does not exist in the database
|
||||
secret_key = await get_setting(SECRET_KEY)
|
||||
if not secret_key:
|
||||
# Generate random secret key
|
||||
secret_key = secrets.token_hex(32)
|
||||
await Settings.create(name=SECRET_KEY, value=secret_key)
|
||||
|
||||
# Mount SessionMiddleware
|
||||
app.add_middleware(
|
||||
SessionMiddleware,
|
||||
secret_key=secret_key,
|
||||
max_age=60 * 60 * 24 * 7, # 1 week
|
||||
)
|
64
apollo/server/settings.py
Normal file
64
apollo/server/settings.py
Normal file
@ -0,0 +1,64 @@
|
||||
from typing import Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Request, Response
|
||||
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
|
||||
|
||||
from apollo.db import Settings
|
||||
from apollo.server.utils import is_admin_user
|
||||
|
||||
SECRET_KEY = "secret-key"
|
||||
OIDC_PROVIDER_NAME = "oidc-provider-name"
|
||||
OIDC_PROVIDER = "oidc-provider"
|
||||
OIDC_CLIENT_ID = "oidc-client-id"
|
||||
OIDC_CLIENT_SECRET = "oidc-client-secret"
|
||||
OIDC_ADMIN_ROLE = "oidc-admin-role"
|
||||
OIDC_ELEVATED_ROLE = "oidc-elevated-role"
|
||||
RH_MATCH_STALE = "rh-match-stale"
|
||||
DISABLE_SERVING_RH_ADVISORIES = "disable-serving-rh-advisories"
|
||||
|
||||
|
||||
async def get_setting(name: str) -> Optional[str]:
|
||||
setting = await Settings.filter(name=name).get_or_none()
|
||||
if setting is None:
|
||||
return None
|
||||
return setting.value
|
||||
|
||||
|
||||
async def get_setting_bool(name: str) -> Optional[bool]:
|
||||
setting = await Settings.filter(name=name).get_or_none()
|
||||
if setting is None:
|
||||
return None
|
||||
return setting.value == "True"
|
||||
|
||||
|
||||
async def should_serve_red_hat_advisories(request: Request) -> bool:
|
||||
setting = await get_setting_bool(DISABLE_SERVING_RH_ADVISORIES)
|
||||
admin_user = await is_admin_user(request)
|
||||
|
||||
if setting and not admin_user:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
@dataclass
|
||||
class SettingsContext:
|
||||
serve_rh_advisories: bool
|
||||
is_admin: bool
|
||||
|
||||
|
||||
class SettingsMiddleware(BaseHTTPMiddleware):
|
||||
async def dispatch(
|
||||
self, request: Request, call_next: RequestResponseEndpoint
|
||||
) -> Response:
|
||||
should_serve_rh_advisories = await should_serve_red_hat_advisories(
|
||||
request
|
||||
)
|
||||
|
||||
request.state.settings = SettingsContext(
|
||||
serve_rh_advisories=should_serve_rh_advisories,
|
||||
is_admin=await is_admin_user(request),
|
||||
)
|
||||
|
||||
return await call_next(request)
|
20
apollo/server/static/BUILD.bazel
Normal file
20
apollo/server/static/BUILD.bazel
Normal file
@ -0,0 +1,20 @@
|
||||
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")
|
||||
|
||||
srcs = glob([
|
||||
"*.ts",
|
||||
"*.scss",
|
||||
])
|
||||
|
||||
esbuild(
|
||||
name = "static",
|
||||
srcs = srcs + [
|
||||
"//:node_modules/@carbon/themes",
|
||||
"//:node_modules/@carbon/web-components",
|
||||
"//:node_modules/carbon-components",
|
||||
"//:node_modules/esbuild-sass-plugin",
|
||||
],
|
||||
config = ":esbuild.config.mjs",
|
||||
entry_point = "index.ts",
|
||||
output_css = "static.css",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
11
apollo/server/static/esbuild.config.mjs
Normal file
11
apollo/server/static/esbuild.config.mjs
Normal file
@ -0,0 +1,11 @@
|
||||
import { sassPlugin } from 'esbuild-sass-plugin';
|
||||
|
||||
export default {
|
||||
keepNames: true,
|
||||
resolveExtensions: ['.ts', '.js', '.tsx', '.jsx'],
|
||||
plugins: [sassPlugin()],
|
||||
define: {
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
'window.process.env.DEBUG': 'undefined',
|
||||
},
|
||||
};
|
94
apollo/server/static/index.ts
Normal file
94
apollo/server/static/index.ts
Normal file
@ -0,0 +1,94 @@
|
||||
import './theme.scss';
|
||||
import '@carbon/web-components/es/components/ui-shell';
|
||||
import '@carbon/web-components/es/components/structured-list';
|
||||
import '@carbon/web-components/es/components/data-table';
|
||||
import '@carbon/web-components/es/components/pagination';
|
||||
import '@carbon/web-components/es/components/form';
|
||||
import '@carbon/web-components/es/components/input';
|
||||
import '@carbon/web-components/es/components/button';
|
||||
import '@carbon/web-components/es/components/notification';
|
||||
import '@carbon/web-components/es/components/tag';
|
||||
import '@carbon/web-components/es/components/list';
|
||||
|
||||
function fixForm() {
|
||||
const buttons = document.querySelectorAll('bx-btn');
|
||||
buttons.forEach((button) => {
|
||||
if (!button.getAttribute('form_id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const form: any = document.querySelector(
|
||||
'form#' + button.getAttribute('form_id')
|
||||
);
|
||||
if (form) {
|
||||
button.addEventListener('click', () => {
|
||||
form.submit();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Also do the same for bx-input and enter key
|
||||
const inputs = document.querySelectorAll('bx-input');
|
||||
inputs.forEach((input) => {
|
||||
input.addEventListener('keydown', (evt: any) => {
|
||||
if (!input.getAttribute('form_id')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (evt.key === 'Enter') {
|
||||
const form: any = document.querySelector(
|
||||
'form#' + input.getAttribute('form_id')
|
||||
);
|
||||
if (form) {
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('bx-pagination').forEach((el) => {
|
||||
el.addEventListener('bx-pagination-changed-current', function (evt: any) {
|
||||
const pageSize = parseInt(el.getAttribute('page-size') || '0');
|
||||
const newPage = Math.ceil(evt.detail.start / pageSize) + 1;
|
||||
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
searchParams.set('page', newPage.toString());
|
||||
window.location.search = searchParams.toString();
|
||||
});
|
||||
});
|
||||
|
||||
// Add "active" if location has prefix, e.g. /admin/ -> /admin
|
||||
// For / only we need to check if the location is exactly /
|
||||
const pathname = window.location.pathname;
|
||||
document.querySelectorAll('bx-side-nav-link').forEach((el) => {
|
||||
const href = el.getAttribute('href');
|
||||
if (href === '/') {
|
||||
if (pathname === '/') {
|
||||
el.setAttribute('active', '');
|
||||
}
|
||||
} else if (pathname.startsWith(href || '')) {
|
||||
el.setAttribute('active', '');
|
||||
}
|
||||
});
|
||||
|
||||
// Change "search" query parameter when the search field encounters Enter
|
||||
const searchToolbar: any = document.querySelector('bx-table-toolbar-search');
|
||||
if (searchToolbar) {
|
||||
const searchBar: any =
|
||||
searchToolbar.shadowRoot.querySelector('.bx--search-input');
|
||||
if (searchBar) {
|
||||
searchBar.addEventListener('keydown', (evt: any) => {
|
||||
if (evt.key === 'Enter') {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
searchParams.set('search', searchBar.value);
|
||||
searchParams.set('page', '1');
|
||||
window.location.search = searchParams.toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fixForm();
|
||||
});
|
19
apollo/server/static/theme.scss
Normal file
19
apollo/server/static/theme.scss
Normal file
@ -0,0 +1,19 @@
|
||||
$feature-flags: (
|
||||
enable-css-custom-properties: true,
|
||||
grid-columns-16: true,
|
||||
);
|
||||
|
||||
@use 'carbon-components/scss/globals/scss/vendor/@carbon/elements/scss/themes/generated/themes';
|
||||
@import 'carbon-components/scss/globals/scss/styles.scss';
|
||||
|
||||
:root {
|
||||
@include carbon--theme($carbon--theme--g90, true);
|
||||
}
|
||||
|
||||
a {
|
||||
color: map-get($carbon--theme--g90, 'link-01');
|
||||
}
|
||||
|
||||
.bx--inline-notification__text-wrapper {
|
||||
width: 100%;
|
||||
}
|
0
apollo/server/templates/BUILD.bazel
Normal file
0
apollo/server/templates/BUILD.bazel
Normal file
5
apollo/server/templates/admin_index.jinja
Normal file
5
apollo/server/templates/admin_index.jinja
Normal file
@ -0,0 +1,5 @@
|
||||
{% extends "admin_layout.jinja" %}
|
||||
|
||||
{% block admin_content %}
|
||||
test
|
||||
{% endblock %}
|
53
apollo/server/templates/admin_layout.jinja
Normal file
53
apollo/server/templates/admin_layout.jinja
Normal file
@ -0,0 +1,53 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block head %}
|
||||
<style>
|
||||
bx-side-nav {
|
||||
margin-top: 3rem;
|
||||
height: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.bx--container {
|
||||
will-change: margin-left;
|
||||
transition: margin-left .11s cubic-bezier(0.2, 0, 1, 0.9)
|
||||
}
|
||||
|
||||
@media(min-width: 66rem) {
|
||||
.bx--container {
|
||||
margin-left: 16rem
|
||||
}
|
||||
}
|
||||
|
||||
.bx--with-rail .bx--container {
|
||||
margin-left: 3rem
|
||||
}
|
||||
|
||||
@media(min-width: 66rem) {
|
||||
.bx--rail-expanded .bx--container {
|
||||
margin-left: 16rem
|
||||
}
|
||||
}
|
||||
|
||||
@media(min-width: 66rem) {
|
||||
.bx--with-side-nav-for-header .bx--container {
|
||||
margin-left: 0
|
||||
}
|
||||
}
|
||||
|
||||
.bx--main {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<bx-side-nav aria-label="Side navigation" expanded>
|
||||
<bx-side-nav-items>
|
||||
<bx-side-nav-link href="/admin">General</bx-side-nav-link>
|
||||
<bx-side-nav-link href="/admin/users">Users</bx-side-nav-link>
|
||||
<bx-side-nav-link href="/admin/oidc">OIDC</bx-side-nav-link>
|
||||
</bx-side-nav-items>
|
||||
</bx-side-nav>
|
||||
|
||||
{% block admin_content %}{% endblock %}
|
||||
{% endblock %}
|
45
apollo/server/templates/advisories.jinja
Normal file
45
apollo/server/templates/advisories.jinja
Normal file
@ -0,0 +1,45 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<h2 style="margin-bottom:1rem;">Advisories</h2>
|
||||
|
||||
<bx-pagination page-size="{{ advisories.size }}" start="{{ (advisories.page-1) * advisories.size }}"
|
||||
total="{{ advisories.total }}">
|
||||
<bx-page-sizes-select slot="page-sizes-select">
|
||||
<option value="50">50</option>
|
||||
</bx-page-sizes-select>
|
||||
<bx-pages-select value="{{ advisories.page - 1 }}" total="{{ advisories_pages }}"></bx-pages-select>
|
||||
</bx-pagination>
|
||||
<bx-data-table>
|
||||
<bx-table-toolbar>
|
||||
<bx-table-toolbar-content>
|
||||
<bx-table-toolbar-search expanded value="{{ search }}">
|
||||
</bx-table-toolbar-search>
|
||||
</bx-table-toolbar-content>
|
||||
</bx-table-toolbar>
|
||||
<bx-table>
|
||||
<bx-table-head>
|
||||
<bx-table-header-row>
|
||||
<bx-table-header-cell>Name</bx-table-header-cell>
|
||||
<bx-table-header-cell>Synopsis</bx-table-header-cell>
|
||||
<bx-table-header-cell>Created at</bx-table-header-cell>
|
||||
<bx-table-header-cell>Issued at</bx-table-header-cell>
|
||||
<bx-table-header-cell>Kind</bx-table-header-cell>
|
||||
<bx-table-header-cell>Severity</bx-table-header-cell>
|
||||
</bx-table-header-row>
|
||||
</bx-table-head>
|
||||
<bx-table-body>
|
||||
{% for advisory in advisories.items -%}
|
||||
<bx-table-row>
|
||||
<bx-table-cell><a href="/{{ advisory.name }}">{{ advisory.name }}</a></bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.synopsis }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.created_at.date() }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.published_at.date() }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.kind }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.severity }}</bx-table-cell>
|
||||
</bx-table-row>
|
||||
{% endfor %}
|
||||
</bx-table-body>
|
||||
</bx-table>
|
||||
</bx-data-table>
|
||||
{% endblock %}
|
103
apollo/server/templates/advisory.jinja
Normal file
103
apollo/server/templates/advisory.jinja
Normal file
@ -0,0 +1,103 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bx--grid bx--grid--full-width">
|
||||
<div style="display:flex;align-items:center;padding-top:0.3rem;">
|
||||
<h1 style="padding-right:0.4rem;">{{ advisory.name }}</h1>
|
||||
{% if advisory.kind == "Security" %}
|
||||
{% set advisory_tag_type = "red" %}
|
||||
{% elif advisory.kind == "Bug Fix" %}
|
||||
{% set advisory_tag_type = "purple" %}
|
||||
{% elif advisory.kind == "Enhancement" %}
|
||||
{% set advisory_tag_type = "teal" %}
|
||||
{% endif %}
|
||||
<bx-tag type="{{ advisory_tag_type }}">{{ advisory.kind }}</bx-tag>
|
||||
{% if advisory.red_hat_advisory_id %}
|
||||
<bx-tag type="blue">
|
||||
Mirrored from
|
||||
{% if request.state.settings.serve_rh_advisories %}
|
||||
<a href="/red_hat/advisories/{{ advisory.red_hat_advisory.name}}"
|
||||
style="color:var(--cds-tag-color-blue);margin-left:0.2rem;">
|
||||
{{advisory.red_hat_advisory.name }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a target="_blank" href="https://access.redhat.com/errata/{{ advisory.red_hat_advisory.name }}"
|
||||
style="color:var(--cds-tag-color-blue);margin-left:0.2rem;">
|
||||
{{ advisory.red_hat_advisory.name }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</bx-tag>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;padding-top:0.3rem;">
|
||||
<h5 style="font-weight:500;margin-right:1rem;">
|
||||
Issued at: <span style="font-weight:400;">{{ advisory.published_at.date() }}</span>
|
||||
</h5>
|
||||
<h5 style="font-weight:500">Updated at: <span style="font-weight:400;">{{ advisory.updated_at.date() }}</span></h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bx--grid bx--grid--full-width" style="margin:3rem 0;">
|
||||
<div class="bx--row">
|
||||
<div class="bx--col-lg-10">
|
||||
<div style="background:var(--cds-ui-02);color:var(--cds-text-01);padding:2rem;">
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Synopsis</h3>
|
||||
<p>{{ advisory.synopsis }}</p>
|
||||
<br /><br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Description</h3>
|
||||
{% set description = advisory.description.split("\n") %}
|
||||
{% for line in description %}
|
||||
<p>{{ line }}</p>
|
||||
{% endfor %}
|
||||
<br /><br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Affected products</h3>
|
||||
<bx-ordered-list>
|
||||
{% for product in advisory.affected_products %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">{{ product.name }}</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
<br /> <br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Fixes</h3>
|
||||
<bx-ordered-list>
|
||||
{% for fix in advisory.fixes %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
<a target="_blank" href="{{ fix.source }}">{{ fix.ticket_id }}</a>
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
<br /> <br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">CVEs</h3>
|
||||
<bx-ordered-list>
|
||||
{% for cve in advisory.cves %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
<a target="_blank" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name={{ cve.cve }}">
|
||||
{{ cve.cve }}
|
||||
</a>
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bx--col-lg-6">
|
||||
<div style="background:var(--cds-ui-02);color:var(--cds-text-01);padding:2rem;">
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);">Affected packages</h3>
|
||||
{% for product_repo_name, nevras in package_map.items() %}
|
||||
<h4 style="padding-bottom:0.3rem;font-weight:400;padding-top:0.3rem;">{{ product_repo_name }}</h4>
|
||||
<bx-ordered-list>
|
||||
{% for nevra in nevras %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
{{ nevra }}
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-list-item>
|
||||
</bx-ordered-list>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
5
apollo/server/templates/error.jinja
Normal file
5
apollo/server/templates/error.jinja
Normal file
@ -0,0 +1,5 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<h1>{{ message }}</h1>
|
||||
{% endblock %}
|
27
apollo/server/templates/index.jinja
Normal file
27
apollo/server/templates/index.jinja
Normal file
@ -0,0 +1,27 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<h2>Statistics</h2>
|
||||
|
||||
<bx-structured-list>
|
||||
<bx-structured-list-head>
|
||||
<bx-structured-list-header-row>
|
||||
<bx-structured-list-header-cell>Service</bx-structured-list-header-cell>
|
||||
<bx-structured-list-header-cell>Resource</bx-structured-list-header-cell>
|
||||
<bx-structured-list-header-cell>Value</bx-structured-list-header-cell>
|
||||
</bx-structured-list-header-row>
|
||||
</bx-structured-list-head>
|
||||
<bx-structured-list-body>
|
||||
<bx-structured-list-row>
|
||||
<bx-structured-list-cell>rpmworker</bx-structured-list-cell>
|
||||
<bx-structured-list-cell>Advisories</bx-structured-list-cell>
|
||||
<bx-structured-list-cell>{{ advisory_count }}</bx-structured-list-cell>
|
||||
</bx-structured-list-row>
|
||||
<bx-structured-list-row>
|
||||
<bx-structured-list-cell>rhworker</bx-structured-list-cell>
|
||||
<bx-structured-list-cell>Red Hat Advisories</bx-structured-list-cell>
|
||||
<bx-structured-list-cell>{{ rh_advisory_count }}</bx-structured-list-cell>
|
||||
</bx-structured-list-row>
|
||||
</bx-structured-list-body>
|
||||
</bx-structured-list>
|
||||
{% endblock %}
|
12
apollo/server/templates/launch_icon.jinja
Normal file
12
apollo/server/templates/launch_icon.jinja
Normal file
@ -0,0 +1,12 @@
|
||||
<svg version="1.1" id="icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
|
||||
y="0px" width="16px" height="16px" viewBox="0 0 16 16" style="enable-background:new 0 0 16 16;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0 {
|
||||
fill: none;
|
||||
}
|
||||
</style>
|
||||
<title>launch</title>
|
||||
<path fill="currentColor" d="M13,14H3c-0.6,0-1-0.4-1-1V3c0-0.6,0.4-1,1-1h5v1H3v10h10V8h1v5C14,13.6,13.6,14,13,14z" />
|
||||
<polygon fill="currentColor" points="10,1 10,2 13.3,2 9,6.3 9.7,7 14,2.7 14,6 15,6 15,1 " />
|
||||
<rect id="_Transparent_Rectangle_" class="st0" width="16" height="16" />
|
||||
</svg>
|
After Width: | Height: | Size: 627 B |
127
apollo/server/templates/layout.jinja
Normal file
127
apollo/server/templates/layout.jinja
Normal file
@ -0,0 +1,127 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>{% block title %}Peridot Apollo{% endblock %}</title>
|
||||
|
||||
<link rel="stylesheet" href="/static/static.css">
|
||||
<script src="/static/static.js"></script>
|
||||
|
||||
<style>
|
||||
.bx--main {
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.apollo-outer {
|
||||
margin-top: 3rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.apollo-outer bx-inline-notification {
|
||||
margin: 0;
|
||||
color: #ffffff;
|
||||
--cds-inverse-01: #ffffff;
|
||||
background: var(--cds-button-separator);
|
||||
}
|
||||
|
||||
.apollo-outer bx-inline-notification:not(.top-notification) {
|
||||
width: 100%;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.apollo-outer bx-inline-notification.top-notification {
|
||||
background: var(--cds-field-01);
|
||||
border-left: 0;
|
||||
border-bottom: 1px solid var(--apollo-notification-border-color, var(--apollo-notification-text-color));
|
||||
max-width: 100%;
|
||||
margin-top: 4rem;
|
||||
color: var(--apollo-notification-text-color);
|
||||
}
|
||||
|
||||
.apollo-outer bx-inline-notification~#apollo-notification-wrapper>bx-inline-notification {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
{% if notification %}
|
||||
{% if notification.get("kind") == "error" %}
|
||||
<style>
|
||||
:root {
|
||||
--apollo-notification-text-color: var(--cds-danger-02);
|
||||
}
|
||||
</style>
|
||||
{% elif notification.get("kind") == "success" %}
|
||||
<style>
|
||||
:root {
|
||||
--apollo-notification-border-color: var(--cds-inverse-support-02);
|
||||
}
|
||||
</style>
|
||||
{% elif notification.get("kind") == "warning" %}
|
||||
<style>
|
||||
:root {
|
||||
--apollo-notification-text-color: var(--cds-inverse-support-03);
|
||||
}
|
||||
</style>
|
||||
{% else %}
|
||||
<style>
|
||||
:root {
|
||||
--apollo-notification-text-color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body class="bx--body">
|
||||
<bx-header aria-label="Apollo">
|
||||
<bx-header-menu-button button-label-active="Close menu" button-label-inactive="Open menu"></bx-header-menu-button>
|
||||
<bx-header-name href="/" prefix="Peridot">[Apollo]</bx-header-name>
|
||||
<bx-header-nav menu-bar-label="Peridot [Apollo]">
|
||||
<bx-header-nav-item href="/">Advisories</bx-header-nav-item>
|
||||
{% if request.state.settings.serve_rh_advisories %}
|
||||
<bx-header-nav-item href="/red_hat/advisories/">Red Hat Advisories</bx-header-nav-item>
|
||||
{% endif %}
|
||||
<bx-header-nav-item href="/statistics/">Statistics</bx-header-nav-item>
|
||||
{% if request.state.settings.is_admin %}
|
||||
<bx-header-nav-item href="/admin/">Admin</bx-header-nav-item>
|
||||
{% endif %}
|
||||
</bx-header-nav>
|
||||
<bx-header-nav style="margin-left:auto;padding-left:0">
|
||||
{% if request.session.get("user.name") %}
|
||||
<bx-header-nav-item>{{ request.session.get("user.name") }}</bx-header-nav-item>
|
||||
<bx-header-nav-item href="/logout/">Logout</bx-header-nav-item>
|
||||
{% else %}
|
||||
<bx-header-nav-item href="/login/">Login</bx-header-nav-item>
|
||||
{% endif %}
|
||||
</bx-header-nav>
|
||||
</bx-header>
|
||||
|
||||
<div class="apollo-outer">
|
||||
{% block outer_content %}{% endblock %}
|
||||
{% if title %}
|
||||
<bx-inline-notification kind="info" title="{{ title }}" hide-close-button>
|
||||
</bx-inline-notification>
|
||||
{% endif %}
|
||||
{% if notification %}
|
||||
<div id="apollo-notification-wrapper" style="margin:0 3.5rem">
|
||||
<bx-inline-notification class="top-notification" kind="{{ notification.get('kind', 'none') }}"
|
||||
title="{{ notification['title'] }}" subtitle="{{ notification['subtitle'] }}"
|
||||
hide-close-button></bx-inline-notification>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<main class="bx--main bx--container">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
89
apollo/server/templates/login.jinja
Normal file
89
apollo/server/templates/login.jinja
Normal file
@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Peridot Apollo</title>
|
||||
|
||||
<link rel="stylesheet" href="/static/static.css">
|
||||
<script src="/static/static.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div style="display:flex;flex-flow:column;justify-content:center;align-items:center;width:100vw;height:100vh">
|
||||
<div style="display:flex;justify-content:center;align-items:center;">
|
||||
<img alt="Peridot logo " height="80px" src="/assets/pd-logo-np.svg" /><br />
|
||||
<h3 style="padding-left:1rem;font-weight:600;">Apollo<br />Errata Management</h3>
|
||||
</div>
|
||||
|
||||
|
||||
{% if error %}
|
||||
<div style="margin-top:3rem;">
|
||||
<h5 style="color:#fa4d56;border-left:0;margin:0;">
|
||||
{{ error }}
|
||||
</h5>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if should_show_setup_success %}
|
||||
<div style="margin-top:3rem;">
|
||||
<h5 style="color:#198038;border-left:0;margin:0;">
|
||||
Admin user created successfully. Please login.
|
||||
</h5>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div style="width:100%;max-width:450px;margin-top:2rem;">
|
||||
{% if should_show_setup %}
|
||||
<form id="signup_form" action="/login/setup" method="POST">
|
||||
<bx-form-item>
|
||||
<bx-input required name="name" form_id="signup_form">
|
||||
<span slot="label-text">Name</span>
|
||||
</bx-input>
|
||||
<bx-input required name="email" type="email" form_id="signup_form">
|
||||
<span slot="label-text">Email</span>
|
||||
</bx-input>
|
||||
<bx-input required name="password" type="password" form_id="signup_form">
|
||||
<span slot="label-text">Password</span>
|
||||
</bx-input>
|
||||
<bx-input required name="confirm_password" type="password" form_id="signup_form">
|
||||
<span slot="label-text">Confirm Password</span>
|
||||
</bx-input>
|
||||
<div
|
||||
style="display:flex;justify-content:space-between;align-items:center;flex-direction:row-reverse;margin-top:25px;width:100%">
|
||||
<bx-btn type="submit" style="margin-left:auto;display:block" form_id="signup_form">Create
|
||||
admin user</bx-btn>
|
||||
</div>
|
||||
</bx-form-item>
|
||||
</form>
|
||||
{% else %}
|
||||
<form id="login_form" action=" /login/" method="POST">
|
||||
<bx-form-item>
|
||||
<bx-input required name="email" type="email" form_id="login_form">
|
||||
<span slot="label-text">Email</span>
|
||||
</bx-input>
|
||||
<bx-input required name="password" type="password" form_id="login_form">
|
||||
<span slot="label-text">Password</span>
|
||||
</bx-input>
|
||||
<div
|
||||
style="display:flex;justify-content:space-between;align-items:center;flex-direction:row-reverse;margin-top:25px;width:100%">
|
||||
<bx-btn type="submit" style="margin-left:auto;display:block" form_id="login_form">Login</bx-btn>
|
||||
{% if oidc_provider_name %}
|
||||
<bx-btn href="/login/oidc" size="sm" kind="ghost" style="display:block;">{{ oidc_provider_name }}</bx-btn>
|
||||
{% endif %}
|
||||
</div>
|
||||
</bx-form-item>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
39
apollo/server/templates/red_hat_advisories.jinja
Normal file
39
apollo/server/templates/red_hat_advisories.jinja
Normal file
@ -0,0 +1,39 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<h2 style="margin-bottom:1rem;">Red Hat Advisories</h2>
|
||||
|
||||
<bx-pagination page-size="{{ advisories.size }}" start="{{ (advisories.page-1) * advisories.size }}"
|
||||
total="{{ advisories.total }}">
|
||||
<bx-page-sizes-select slot="page-sizes-select">
|
||||
<option value="50">50</option>
|
||||
</bx-page-sizes-select>
|
||||
<bx-pages-select value="{{ advisories.page - 1 }}" total="{{ advisories_pages }}"></bx-pages-select>
|
||||
</bx-pagination>
|
||||
<bx-data-table>
|
||||
<bx-table>
|
||||
<bx-table-head>
|
||||
<bx-table-header-row>
|
||||
<bx-table-header-cell>Name</bx-table-header-cell>
|
||||
<bx-table-header-cell>Synopsis</bx-table-header-cell>
|
||||
<bx-table-header-cell>Issued at</bx-table-header-cell>
|
||||
<bx-table-header-cell>Indexed at</bx-table-header-cell>
|
||||
<bx-table-header-cell>Kind</bx-table-header-cell>
|
||||
<bx-table-header-cell>Severity</bx-table-header-cell>
|
||||
</bx-table-header-row>
|
||||
</bx-table-head>
|
||||
<bx-table-body>
|
||||
{% for advisory in advisories.items -%}
|
||||
<bx-table-row>
|
||||
<bx-table-cell><a href="/red_hat/advisories/{{ advisory.name }}">{{ advisory.name }}</a></bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.synopsis }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.red_hat_issued_at.date() }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.created_at.date() }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.kind }}</bx-table-cell>
|
||||
<bx-table-cell>{{ advisory.severity }}</bx-table-cell>
|
||||
</bx-table-row>
|
||||
{% endfor %}
|
||||
</bx-table-body>
|
||||
</bx-table>
|
||||
</bx-data-table>
|
||||
{% endblock %}
|
146
apollo/server/templates/red_hat_advisory.jinja
Normal file
146
apollo/server/templates/red_hat_advisory.jinja
Normal file
@ -0,0 +1,146 @@
|
||||
{% extends "layout.jinja" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="bx--grid bx--grid--full-width" style="margin:0;">
|
||||
<div class="bx--row">
|
||||
<div class="bx--col-lg-15">
|
||||
<div style="display:flex;align-items:center;padding-top:0.3rem;">
|
||||
<h1 style="padding-right:0.4rem;">{{ advisory.name }}</h1>
|
||||
{% if advisory.kind == "Security" %}
|
||||
{% set advisory_tag_type = "red" %}
|
||||
{% elif advisory.kind == "Bug Fix" %}
|
||||
{% set advisory_tag_type = "purple" %}
|
||||
{% elif advisory.kind == "Enhancement" %}
|
||||
{% set advisory_tag_type = "teal" %}
|
||||
{% endif %}
|
||||
<bx-tag type="{{ advisory_tag_type }}">{{ advisory.kind }}</bx-tag>
|
||||
{% for override in advisory.rpm_rh_overrides %}
|
||||
<bx-tag type="blue">
|
||||
Override for {{ override.supported_products_rh_mirror.name }}
|
||||
</bx-tag>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div style="display:flex;align-items:center;padding-top:0.3rem;">
|
||||
<h5 style="font-weight:500;margin-right:1rem;">
|
||||
Issued at: <span style="font-weight:400;">{{advisory.red_hat_issued_at.date() }}</span>
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bx--row" style="margin-top:1rem;">
|
||||
<div class="bx--col">
|
||||
<div style="display:flex;align-items:center">
|
||||
<bx-btn kind="primary" target="_blank" href="https://access.redhat.com/errata/{{ advisory.name }}"
|
||||
style="margin-right:1rem;">
|
||||
{% include "launch_icon.jinja" %}
|
||||
<div style="margin-left:1rem;">
|
||||
Open original
|
||||
</div>
|
||||
</bx-btn>
|
||||
|
||||
<form id="override" action="/red_hat/advisories/{{ advisory.name }}" method="POST">
|
||||
<input type="hidden" name="action" value="override" />
|
||||
<bx-btn kind="primary" form_id="override">Override</bx-button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="bx--row" style="margin-top:1rem;">
|
||||
<div class="bx--col">
|
||||
<div style="display:flex;align-items:center;">
|
||||
{% if advisory.kind == "Security" %}
|
||||
{% set advisory_tag_type = "red" %}
|
||||
{% elif advisory.kind == "Bug Fix" %}
|
||||
{% set advisory_tag_type = "purple" %}
|
||||
{% elif advisory.kind == "Enhancement" %}
|
||||
{% set advisory_tag_type = "teal" %}
|
||||
{% endif %}
|
||||
<bx-tag type="{{ advisory_tag_type }}">{{ advisory.kind }}</bx-tag>
|
||||
{% for override in advisory.rpm_rh_overrides %}
|
||||
<bx-tag type="blue">
|
||||
Override for {{ override.supported_products_rh_mirror.name }}
|
||||
</bx-tag>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
|
||||
<div class="bx--grid bx--grid--full-width" style="margin:3rem 0;">
|
||||
<div class="bx--row">
|
||||
<div class="bx--col-lg-10">
|
||||
<div style="background:var(--cds-ui-02);color:var(--cds-text-01);padding:2rem;">
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Synopsis</h3>
|
||||
<p>{{ advisory.synopsis }}</p>
|
||||
<br /><br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Description</h3>
|
||||
{% set description = advisory.description.split("\n") %}
|
||||
{% for line in description %}
|
||||
<p>{{ line }}</p>
|
||||
{% endfor %}
|
||||
<br /><br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Affected products</h3>
|
||||
<bx-ordered-list>
|
||||
{% for product in advisory.affected_products %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
{{ product.name }} - {{ product.major_version }}{% if product.minor_version %}.{{ product.minor_version }}{%
|
||||
endif %}
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
<br /> <br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Fixes</h3>
|
||||
<bx-ordered-list>
|
||||
{% for ticket in advisory.bugzilla_tickets %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
<a target="_blank" href="https://bugzilla.redhat.com/show_bug.cgi?id={{ ticket.bugzilla_bug_id }}">
|
||||
{{ ticket.bugzilla_bug_id }}
|
||||
</a>
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
<br /> <br />
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">CVEs</h3>
|
||||
<bx-ordered-list>
|
||||
{% for cve in advisory.cves %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
<a target="_blank" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name={{ cve.cve }}">
|
||||
{{ cve.cve }}
|
||||
</a>
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-ordered-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bx--col-lg-6">
|
||||
<div style="background:var(--cds-ui-02);color:var(--cds-text-01);padding:2rem;">
|
||||
{% set pkg_list = {} %}
|
||||
{% for pkg in advisory.packages %}
|
||||
{% if pkg.repo_name in pkg_list %}
|
||||
{% set x=pkg_list.__getitem__(pkg.repo_name).append(pkg) %}
|
||||
{% else %}
|
||||
{% set x=pkg_list.__setitem__(pkg.repo_name, [pkg]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<h3 style="font-weight:600;color:var(--cds-text-04);padding-bottom:0.3rem;">Affected packages</h3>
|
||||
{% for repo_name, pkg in pkg_list.items() %}
|
||||
<h4 style="padding-bottom:0.3rem;font-weight:400;">{{ repo_name }}</h4>
|
||||
<bx-ordered-list>
|
||||
{% for p in pkg %}
|
||||
<bx-list-item style="font-size:var(--cds-body-short-02-font-size)">
|
||||
{{ p.nevra }}
|
||||
</bx-list-item>
|
||||
{% endfor %}
|
||||
</bx-list-item>
|
||||
</bx-ordered-list>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
50
apollo/server/utils.py
Normal file
50
apollo/server/utils.py
Normal file
@ -0,0 +1,50 @@
|
||||
from fastapi import Request
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from passlib.context import CryptContext
|
||||
|
||||
from apollo.db import User
|
||||
from apollo.server.roles import ADMIN
|
||||
|
||||
from common.fastapi import RenderErrorTemplateException
|
||||
|
||||
# Do not remove import (for gazelle)
|
||||
import jinja2 # noqa # pylint: disable=unused-import
|
||||
import multipart # noqa # pylint: disable=unused-import
|
||||
import itsdangerous # noqa # pylint: disable=unused-import
|
||||
|
||||
templates = Jinja2Templates(directory="apollo/server/templates")
|
||||
|
||||
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
||||
|
||||
|
||||
async def admin_user_scheme(request: Request) -> User:
|
||||
user = await user_scheme(request, raise_exc=False)
|
||||
if not user:
|
||||
raise RenderErrorTemplateException(
|
||||
"You need to log in to access this page",
|
||||
status_code=401,
|
||||
)
|
||||
elif user.role != ADMIN:
|
||||
raise RenderErrorTemplateException(
|
||||
"You are not authorized to view this page",
|
||||
status_code=403,
|
||||
)
|
||||
return user
|
||||
|
||||
|
||||
async def user_scheme(request: Request, raise_exc=True) -> User:
|
||||
user_id = request.session.get("user")
|
||||
if not user_id:
|
||||
if raise_exc:
|
||||
raise RenderErrorTemplateException(
|
||||
"You need to log in to access this page",
|
||||
status_code=401,
|
||||
)
|
||||
else:
|
||||
return None
|
||||
return await User.get(id=user_id)
|
||||
|
||||
|
||||
async def is_admin_user(request: Request) -> bool:
|
||||
user = await user_scheme(request, raise_exc=False)
|
||||
return user.role == ADMIN if user else False
|
0
build/BUILD.bazel
Normal file
0
build/BUILD.bazel
Normal file
0
build/macros/BUILD.bazel
Normal file
0
build/macros/BUILD.bazel
Normal file
32
build/macros/fastapi.bzl
Normal file
32
build/macros/fastapi.bzl
Normal file
@ -0,0 +1,32 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_binary")
|
||||
|
||||
def fastapi_binary(name, path, port, deps = [], tags = [], **kwargs):
|
||||
py_binary(
|
||||
name = name,
|
||||
srcs = ["@pypi_hypercorn//:rules_python_wheel_entry_point_hypercorn.py"],
|
||||
args = ["{}:app".format(path), "--reload", "--bind 127.0.0.1:{}".format(port)],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = deps + [
|
||||
":{}_lib".format(name),
|
||||
"@pypi_hypercorn//:pkg",
|
||||
],
|
||||
tags = tags + [
|
||||
"ibazel_notify_changes",
|
||||
],
|
||||
**kwargs
|
||||
)
|
||||
|
||||
py_binary(
|
||||
name = "{}.prod".format(name),
|
||||
srcs = ["@pypi_hypercorn//:rules_python_wheel_entry_point_hypercorn.py"],
|
||||
args = ["{}:app".format(path), "--reload", "--bind 127.0.0.1:{}".format(port)],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = deps + [
|
||||
":{}_lib".format(name),
|
||||
"@pypi_hypercorn//:pkg",
|
||||
],
|
||||
tags = tags + [
|
||||
"ibazel_notify_changes",
|
||||
],
|
||||
**kwargs
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
From e0c49b576595abdfa5167fa7726e604701f79cd8 Mon Sep 17 00:00:00 2001
|
||||
From: Mustafa Gezen <mustafa@ctrliq.com>
|
||||
Date: Sun, 29 Jan 2023 05:54:58 +0100
|
||||
Subject: [PATCH] Fix Quart and Hypercorn failing to install with rules_python
|
||||
|
||||
---
|
||||
.../tools/wheel_installer/wheel_installer.py | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/python/pip_install/tools/wheel_installer/wheel_installer.py b/python/pip_install/tools/wheel_installer/wheel_installer.py
|
||||
index 1f6eaf2..3bbaaaf 100644
|
||||
--- a/python/pip_install/tools/wheel_installer/wheel_installer.py
|
||||
+++ b/python/pip_install/tools/wheel_installer/wheel_installer.py
|
||||
@@ -422,6 +422,21 @@ def main() -> None:
|
||||
extras = {name: extras_for_pkg} if extras_for_pkg and name else dict()
|
||||
|
||||
whl = next(iter(glob.glob("*.whl")))
|
||||
+
|
||||
+ # If wheel starts with "Quart" then rename it to "quart"
|
||||
+ # For some reason the quart package publishes a wheel with a capital Q
|
||||
+ # but internally it is referenced as "quart".
|
||||
+ # This leads to the "installer" package failing to read the WHEEL file
|
||||
+ # Ugly hack, but it is what it is.
|
||||
+ # The same problem is also present with "Hypercorn".
|
||||
+ # This developer is definitely doing something weird but whatever.
|
||||
+ if whl.startswith("Quart"):
|
||||
+ os.rename(whl, whl.replace("Quart", "quart"))
|
||||
+ whl = whl.replace("Quart", "quart")
|
||||
+ if whl.startswith("Hypercorn"):
|
||||
+ os.rename(whl, whl.replace("Hypercorn", "hypercorn"))
|
||||
+ whl = whl.replace("Hypercorn", "hypercorn")
|
||||
+
|
||||
_extract_wheel(
|
||||
wheel_file=whl,
|
||||
extras=extras,
|
||||
--
|
||||
2.32.0 (Apple Git-132)
|
||||
|
1
build/patches/BUILD.bazel
Normal file
1
build/patches/BUILD.bazel
Normal file
@ -0,0 +1 @@
|
||||
exports_files(["0001-Fix-Quart-and-Hypercorn-failing-to-install-with-rule.patch"])
|
20
common/BUILD.bazel
Normal file
20
common/BUILD.bazel
Normal file
@ -0,0 +1,20 @@
|
||||
load("@aspect_rules_py//py:defs.bzl", "py_library")
|
||||
|
||||
py_library(
|
||||
name = "common_lib",
|
||||
srcs = [
|
||||
"database.py",
|
||||
"env.py",
|
||||
"fastapi.py",
|
||||
"info.py",
|
||||
"logger.py",
|
||||
"temporal.py",
|
||||
],
|
||||
imports = [".."],
|
||||
visibility = ["//:__subpackages__"],
|
||||
deps = [
|
||||
"@pypi_fastapi//:pkg",
|
||||
"@pypi_temporalio//:pkg",
|
||||
"@pypi_tortoise_orm//:pkg",
|
||||
],
|
||||
)
|
42
common/database.py
Normal file
42
common/database.py
Normal file
@ -0,0 +1,42 @@
|
||||
"""
|
||||
Database helper methods
|
||||
"""
|
||||
from tortoise import Tortoise
|
||||
from tortoise.contrib.fastapi import register_tortoise
|
||||
|
||||
from common.info import Info
|
||||
|
||||
|
||||
class Database(object):
|
||||
"""
|
||||
Database connection singleton class
|
||||
"""
|
||||
|
||||
initialized = False
|
||||
|
||||
def __init__(self, initialize=False, tortoise_app=None, models=None):
|
||||
if not Database.initialized and not initialize:
|
||||
raise Exception("Database connection not initialized")
|
||||
|
||||
if tortoise_app:
|
||||
register_tortoise(
|
||||
tortoise_app,
|
||||
db_url=self.conn_str(),
|
||||
modules={"models": models},
|
||||
add_exception_handlers=True,
|
||||
)
|
||||
self.initialized = True
|
||||
|
||||
def conn_str(self):
|
||||
info = Info()
|
||||
|
||||
return f"postgres://{info.dbuser()}:{info.dbpassword()}@{info.dbhost()}:{info.dbport()}/{info.dbname()}"
|
||||
|
||||
async def init(self, models):
|
||||
if Database.initialized:
|
||||
return
|
||||
await Tortoise.init(
|
||||
db_url=self.conn_str(), use_tz=True, modules={"models": models}
|
||||
)
|
||||
|
||||
self.initialized = True
|
16
common/env.py
Normal file
16
common/env.py
Normal file
@ -0,0 +1,16 @@
|
||||
"""
|
||||
Environment variables
|
||||
"""
|
||||
import os
|
||||
|
||||
|
||||
def get_env():
|
||||
return os.environ.get("ENV", "development")
|
||||
|
||||
|
||||
def is_prod():
|
||||
return get_env() == "1"
|
||||
|
||||
|
||||
def is_k8s():
|
||||
return os.environ.get("KUBERNETES", "0") == "1"
|
22
common/fastapi.py
Normal file
22
common/fastapi.py
Normal file
@ -0,0 +1,22 @@
|
||||
import os
|
||||
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
|
||||
|
||||
class StaticFilesSym(StaticFiles):
|
||||
"subclass StaticFiles middleware to allow symlinks"
|
||||
def lookup_path(self, path):
|
||||
for directory in self.all_directories:
|
||||
full_path = os.path.realpath(os.path.join(directory, path))
|
||||
try:
|
||||
stat_result = os.stat(full_path)
|
||||
return (full_path, stat_result)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return ("", None)
|
||||
|
||||
|
||||
class RenderErrorTemplateException(Exception):
|
||||
def __init__(self, msg=None, status_code=404):
|
||||
self.msg = msg
|
||||
self.status_code = status_code
|
56
common/info.py
Normal file
56
common/info.py
Normal file
@ -0,0 +1,56 @@
|
||||
"""
|
||||
Application information
|
||||
"""
|
||||
import os
|
||||
|
||||
from common.env import get_env, is_k8s
|
||||
|
||||
|
||||
class Info:
|
||||
"""
|
||||
Application information singleton class
|
||||
"""
|
||||
|
||||
_name = None
|
||||
_dbname = None
|
||||
|
||||
def __init__(self, name=None, dbname=None):
|
||||
if not self._name and not name:
|
||||
raise ValueError("Info.name is not set")
|
||||
if self._name and name:
|
||||
raise ValueError("Info.name is already set")
|
||||
if name:
|
||||
Info._name = name
|
||||
Info._dbname = dbname if dbname else name
|
||||
|
||||
self._name = Info._name
|
||||
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
def dbname(self):
|
||||
return f"{self._dbname}{get_env()}"
|
||||
|
||||
def dbuser(self):
|
||||
return os.environ.get("DB_USER", "postgres")
|
||||
|
||||
def dbpassword(self):
|
||||
return os.environ.get("DB_PASSWORD", "postgres")
|
||||
|
||||
def dbhost(self):
|
||||
return os.environ.get("DB_HOST", "localhost")
|
||||
|
||||
def dbport(self):
|
||||
return os.environ.get("DB_PORT", "5432")
|
||||
|
||||
def dbsslmode(self):
|
||||
return os.environ.get("DB_SSLMODE", "disable")
|
||||
|
||||
def temporal_host(self):
|
||||
if is_k8s():
|
||||
return "workflow-temporal-frontend.workflow.svc.cluster.local:7233"
|
||||
else:
|
||||
return os.environ.get("TEMPORAL_HOSTPORT", "localhost:7233")
|
||||
|
||||
def temporal_namespace(self):
|
||||
return os.environ.get("TEMPORAL_NAMESPACE", "default")
|
52
common/logger.py
Normal file
52
common/logger.py
Normal file
@ -0,0 +1,52 @@
|
||||
"""
|
||||
This module provides a logger class that
|
||||
can be used to log messages to the console.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from common.env import is_prod
|
||||
from common.info import Info
|
||||
|
||||
|
||||
class Logger(object):
|
||||
"""
|
||||
This class provides a logger that can be used to log messages to the console.
|
||||
"""
|
||||
|
||||
logger = None
|
||||
|
||||
def __init__(self):
|
||||
info = Info()
|
||||
|
||||
if Logger.logger is None:
|
||||
level = logging.INFO
|
||||
if not is_prod():
|
||||
level = logging.DEBUG
|
||||
logging.basicConfig(
|
||||
level=level,
|
||||
format="[%(name)s:%(levelname)s:%(asctime)s] %(message)s"
|
||||
)
|
||||
Logger.logger = logging.getLogger(info.name())
|
||||
|
||||
self.logger = Logger.logger
|
||||
|
||||
def warning(self, msg, *args, **kwargs):
|
||||
self.logger.warning(msg, *args, **kwargs)
|
||||
|
||||
def error(self, msg, *args, **kwargs):
|
||||
self.logger.error(msg, *args, **kwargs)
|
||||
|
||||
def info(self, msg, *args, **kwargs):
|
||||
self.logger.info(msg, *args, **kwargs)
|
||||
|
||||
def debug(self, msg, *args, **kwargs):
|
||||
self.logger.debug(msg, *args, **kwargs)
|
||||
|
||||
def exception(self, msg, *args, **kwargs):
|
||||
self.logger.exception(msg, *args, **kwargs)
|
||||
|
||||
def critical(self, msg, *args, **kwargs):
|
||||
self.logger.critical(msg, *args, **kwargs)
|
||||
|
||||
def fatal(self, msg, *args, **kwargs):
|
||||
self.logger.fatal(msg, *args, **kwargs)
|
29
common/temporal.py
Normal file
29
common/temporal.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""
|
||||
Temporal helper methods
|
||||
"""
|
||||
|
||||
from temporalio.client import Client
|
||||
|
||||
from common.info import Info
|
||||
|
||||
|
||||
class Temporal(object):
|
||||
"""
|
||||
Temporal helper singleton class
|
||||
"""
|
||||
|
||||
client = None
|
||||
|
||||
def __init__(self, initialize=False):
|
||||
if Temporal.client is None and not initialize:
|
||||
raise Exception("Temporal client not initialized")
|
||||
|
||||
self.client = Temporal.client
|
||||
|
||||
async def connect(self):
|
||||
info = Info()
|
||||
Temporal.client = await Client.connect(
|
||||
info.temporal_host(),
|
||||
namespace=info.temporal_namespace(),
|
||||
)
|
||||
self.client = Temporal.client
|
1500
gazelle_python.yaml
Normal file
1500
gazelle_python.yaml
Normal file
File diff suppressed because it is too large
Load Diff
20
package.json
Normal file
20
package.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "distro-tools",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@carbon/themes": "^11.16.0",
|
||||
"@carbon/web-components": "^1.23.0",
|
||||
"carbon-components": "^10.58.3",
|
||||
"esbuild-sass-plugin": "^2.4.5",
|
||||
"lit-element": "^3.2.2",
|
||||
"lit-html": "^2.6.1"
|
||||
}
|
||||
}
|
587
pnpm-lock.yaml
generated
Normal file
587
pnpm-lock.yaml
generated
Normal file
@ -0,0 +1,587 @@
|
||||
lockfileVersion: 5.4
|
||||
|
||||
specifiers:
|
||||
'@carbon/themes': ^11.16.0
|
||||
'@carbon/web-components': ^1.23.0
|
||||
carbon-components: ^10.58.3
|
||||
esbuild-sass-plugin: ^2.4.5
|
||||
lit-element: ^3.2.2
|
||||
lit-html: ^2.6.1
|
||||
|
||||
dependencies:
|
||||
'@carbon/themes': 11.16.0
|
||||
'@carbon/web-components': 1.23.0
|
||||
carbon-components: 10.58.3
|
||||
esbuild-sass-plugin: 2.4.5
|
||||
lit-element: 3.2.2
|
||||
lit-html: 2.6.1
|
||||
|
||||
packages:
|
||||
|
||||
/@babel/runtime/7.20.13:
|
||||
resolution: {integrity: sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
regenerator-runtime: 0.13.11
|
||||
dev: false
|
||||
|
||||
/@carbon/colors/11.12.0:
|
||||
resolution: {integrity: sha512-rN/e6EXgS1RM8C/K0qQ/4/zE+En8iMGDE9u6BNLQ9ig2V2KTYncCdhItJW0rAbL7tt8xeP0UrACijS/XCqsm6w==}
|
||||
dev: false
|
||||
|
||||
/@carbon/grid/11.11.0:
|
||||
resolution: {integrity: sha512-07U2cC5lgvy7gWveUtE0wuYUxu6Dndglnajy1FJAeV7BEd2t6cgU/t7AOaL8RhoXPjE7tarN5tnZImw5nmzQYQ==}
|
||||
dependencies:
|
||||
'@carbon/layout': 11.11.0
|
||||
dev: false
|
||||
|
||||
/@carbon/layout/11.11.0:
|
||||
resolution: {integrity: sha512-0AuBxoJ+4HiYDIou0xR/jRtGDjTZ2ew1qeViQd04aM0GdZDGhjPTwU9u9CLCKAZEK4dYcewqWat1FQI4diYaOA==}
|
||||
dev: false
|
||||
|
||||
/@carbon/telemetry/0.1.0:
|
||||
resolution: {integrity: sha512-kNWt0bkgPwGW0i5h7HFuljbKRXPvIhsKbB+1tEURAYLXoJg9iJLF1eGvWN5iVoFCS2zje4GR3OGOsvvKVe7Hlg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/@carbon/themes/11.16.0:
|
||||
resolution: {integrity: sha512-t5323D66p5M6ev9HwMo5tQUE5M1zQP+fa2KExOkHzyJXQfbR3rDSL3y8O/ALrnLgYfBKTftQCGOcUnxhR3LOTQ==}
|
||||
dependencies:
|
||||
'@carbon/colors': 11.12.0
|
||||
'@carbon/layout': 11.11.0
|
||||
'@carbon/type': 11.15.0
|
||||
color: 4.2.3
|
||||
dev: false
|
||||
|
||||
/@carbon/type/11.15.0:
|
||||
resolution: {integrity: sha512-oJm8imiLUF5x7AYaiuExhGfhF/aep8STvV4ckQ9VrPCVFwytJ1haJFmyDU2ssYNiTfgjVN0foy6sNbHMZYM0pg==}
|
||||
dependencies:
|
||||
'@carbon/grid': 11.11.0
|
||||
'@carbon/layout': 11.11.0
|
||||
dev: false
|
||||
|
||||
/@carbon/web-components/1.23.0:
|
||||
resolution: {integrity: sha512-dK28KsVS9pR9YEYCQ5t61imLf1DbcwdykCLcIQX7B1Ak8YZZHYdNEkkcmuiXpbn6Tfd/Rtn1i+5BiJmREN6kKQ==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.20.13
|
||||
carbon-components: 10.58.3
|
||||
flatpickr: 4.6.13
|
||||
lit-element: 2.5.1
|
||||
lit-html: 1.4.1
|
||||
lodash-es: 4.17.21
|
||||
dev: false
|
||||
|
||||
/@esbuild/android-arm/0.15.18:
|
||||
resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@esbuild/linux-loong64/0.15.18:
|
||||
resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/@lit-labs/ssr-dom-shim/1.0.0:
|
||||
resolution: {integrity: sha512-ic93MBXfApIFTrup4a70M/+ddD8xdt2zxxj9sRwHQzhS9ag/syqkD8JPdTXsc1gUy2K8TTirhlCqyTEM/sifNw==}
|
||||
dev: false
|
||||
|
||||
/@lit/reactive-element/1.6.1:
|
||||
resolution: {integrity: sha512-va15kYZr7KZNNPZdxONGQzpUr+4sxVu7V/VG7a8mRfPPXUyhEYj5RzXCQmGrlP3tAh0L3HHm5AjBMFYRqlM9SA==}
|
||||
dependencies:
|
||||
'@lit-labs/ssr-dom-shim': 1.0.0
|
||||
dev: false
|
||||
|
||||
/@types/trusted-types/2.0.2:
|
||||
resolution: {integrity: sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==}
|
||||
dev: false
|
||||
|
||||
/anymatch/3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
normalize-path: 3.0.0
|
||||
picomatch: 2.3.1
|
||||
dev: false
|
||||
|
||||
/binary-extensions/2.2.0:
|
||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/braces/3.0.2:
|
||||
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
fill-range: 7.0.1
|
||||
dev: false
|
||||
|
||||
/carbon-components/10.58.3:
|
||||
resolution: {integrity: sha512-RjTnrWCGStsIZ7nErw97AZI9sQWxQ8oIgo3QMdV0FWFcpTOECA4I9Dy4WPpRRdSMBcQpLetTxqjDGourM4u8Tw==}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@carbon/telemetry': 0.1.0
|
||||
flatpickr: 4.6.1
|
||||
lodash.debounce: 4.0.8
|
||||
warning: 3.0.0
|
||||
dev: false
|
||||
|
||||
/chokidar/3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
dependencies:
|
||||
anymatch: 3.1.3
|
||||
braces: 3.0.2
|
||||
glob-parent: 5.1.2
|
||||
is-binary-path: 2.1.0
|
||||
is-glob: 4.0.3
|
||||
normalize-path: 3.0.0
|
||||
readdirp: 3.6.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
dev: false
|
||||
|
||||
/color-convert/2.0.1:
|
||||
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
|
||||
engines: {node: '>=7.0.0'}
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
dev: false
|
||||
|
||||
/color-name/1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
dev: false
|
||||
|
||||
/color-string/1.9.1:
|
||||
resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
|
||||
dependencies:
|
||||
color-name: 1.1.4
|
||||
simple-swizzle: 0.2.2
|
||||
dev: false
|
||||
|
||||
/color/4.2.3:
|
||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||
engines: {node: '>=12.5.0'}
|
||||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
color-string: 1.9.1
|
||||
dev: false
|
||||
|
||||
/esbuild-android-64/0.15.18:
|
||||
resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-android-arm64/0.15.18:
|
||||
resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-darwin-64/0.15.18:
|
||||
resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-darwin-arm64/0.15.18:
|
||||
resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-freebsd-64/0.15.18:
|
||||
resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-freebsd-arm64/0.15.18:
|
||||
resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-32/0.15.18:
|
||||
resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-64/0.15.18:
|
||||
resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-arm/0.15.18:
|
||||
resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-arm64/0.15.18:
|
||||
resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-mips64le/0.15.18:
|
||||
resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-ppc64le/0.15.18:
|
||||
resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-riscv64/0.15.18:
|
||||
resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-linux-s390x/0.15.18:
|
||||
resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-netbsd-64/0.15.18:
|
||||
resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-openbsd-64/0.15.18:
|
||||
resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-sass-plugin/2.4.5:
|
||||
resolution: {integrity: sha512-di2hLaIwhRXe513uaPPxv+5bjynxAgrS8R+u38lbBfvp1g1xOki4ACXV2aXip2CRPGTbAVDySSxujd9iArFV0w==}
|
||||
dependencies:
|
||||
esbuild: 0.15.18
|
||||
resolve: 1.22.1
|
||||
sass: 1.57.1
|
||||
dev: false
|
||||
|
||||
/esbuild-sunos-64/0.15.18:
|
||||
resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-32/0.15.18:
|
||||
resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-64/0.15.18:
|
||||
resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild-windows-arm64/0.15.18:
|
||||
resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/esbuild/0.15.18:
|
||||
resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@esbuild/android-arm': 0.15.18
|
||||
'@esbuild/linux-loong64': 0.15.18
|
||||
esbuild-android-64: 0.15.18
|
||||
esbuild-android-arm64: 0.15.18
|
||||
esbuild-darwin-64: 0.15.18
|
||||
esbuild-darwin-arm64: 0.15.18
|
||||
esbuild-freebsd-64: 0.15.18
|
||||
esbuild-freebsd-arm64: 0.15.18
|
||||
esbuild-linux-32: 0.15.18
|
||||
esbuild-linux-64: 0.15.18
|
||||
esbuild-linux-arm: 0.15.18
|
||||
esbuild-linux-arm64: 0.15.18
|
||||
esbuild-linux-mips64le: 0.15.18
|
||||
esbuild-linux-ppc64le: 0.15.18
|
||||
esbuild-linux-riscv64: 0.15.18
|
||||
esbuild-linux-s390x: 0.15.18
|
||||
esbuild-netbsd-64: 0.15.18
|
||||
esbuild-openbsd-64: 0.15.18
|
||||
esbuild-sunos-64: 0.15.18
|
||||
esbuild-windows-32: 0.15.18
|
||||
esbuild-windows-64: 0.15.18
|
||||
esbuild-windows-arm64: 0.15.18
|
||||
dev: false
|
||||
|
||||
/fill-range/7.0.1:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
dev: false
|
||||
|
||||
/flatpickr/4.6.1:
|
||||
resolution: {integrity: sha512-3ULSxbXmcMIRzer/2jLNweoqHpwDvsjEawO2FUd9UFR8uPwLM+LruZcPDpuZStcEgbQKhuFOfXo4nYdGladSNw==}
|
||||
dev: false
|
||||
|
||||
/flatpickr/4.6.13:
|
||||
resolution: {integrity: sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==}
|
||||
dev: false
|
||||
|
||||
/fsevents/2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/function-bind/1.1.1:
|
||||
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
|
||||
dev: false
|
||||
|
||||
/glob-parent/5.1.2:
|
||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
dev: false
|
||||
|
||||
/has/1.0.3:
|
||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
function-bind: 1.1.1
|
||||
dev: false
|
||||
|
||||
/immutable/4.2.2:
|
||||
resolution: {integrity: sha512-fTMKDwtbvO5tldky9QZ2fMX7slR0mYpY5nbnFWYp0fOzDhHqhgIw9KoYgxLWsoNTS9ZHGauHj18DTyEw6BK3Og==}
|
||||
dev: false
|
||||
|
||||
/is-arrayish/0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
dev: false
|
||||
|
||||
/is-binary-path/2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
binary-extensions: 2.2.0
|
||||
dev: false
|
||||
|
||||
/is-core-module/2.11.0:
|
||||
resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
|
||||
dependencies:
|
||||
has: 1.0.3
|
||||
dev: false
|
||||
|
||||
/is-extglob/2.1.1:
|
||||
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/is-glob/4.0.3:
|
||||
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
is-extglob: 2.1.1
|
||||
dev: false
|
||||
|
||||
/is-number/7.0.0:
|
||||
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||
engines: {node: '>=0.12.0'}
|
||||
dev: false
|
||||
|
||||
/js-tokens/4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: false
|
||||
|
||||
/lit-element/2.5.1:
|
||||
resolution: {integrity: sha512-ogu7PiJTA33bEK0xGu1dmaX5vhcRjBXCFexPja0e7P7jqLhTpNKYRPmE+GmiCaRVAbiQKGkUgkh/i6+bh++dPQ==}
|
||||
dependencies:
|
||||
lit-html: 1.4.1
|
||||
dev: false
|
||||
|
||||
/lit-element/3.2.2:
|
||||
resolution: {integrity: sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==}
|
||||
dependencies:
|
||||
'@lit/reactive-element': 1.6.1
|
||||
lit-html: 2.6.1
|
||||
dev: false
|
||||
|
||||
/lit-html/1.4.1:
|
||||
resolution: {integrity: sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==}
|
||||
dev: false
|
||||
|
||||
/lit-html/2.6.1:
|
||||
resolution: {integrity: sha512-Z3iw+E+3KKFn9t2YKNjsXNEu/LRLI98mtH/C6lnFg7kvaqPIzPn124Yd4eT/43lyqrejpc5Wb6BHq3fdv4S8Rw==}
|
||||
dependencies:
|
||||
'@types/trusted-types': 2.0.2
|
||||
dev: false
|
||||
|
||||
/lodash-es/4.17.21:
|
||||
resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
|
||||
dev: false
|
||||
|
||||
/lodash.debounce/4.0.8:
|
||||
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
|
||||
dev: false
|
||||
|
||||
/loose-envify/1.4.0:
|
||||
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
js-tokens: 4.0.0
|
||||
dev: false
|
||||
|
||||
/normalize-path/3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/path-parse/1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
dev: false
|
||||
|
||||
/picomatch/2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
dev: false
|
||||
|
||||
/readdirp/3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
dev: false
|
||||
|
||||
/regenerator-runtime/0.13.11:
|
||||
resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
|
||||
dev: false
|
||||
|
||||
/resolve/1.22.1:
|
||||
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
is-core-module: 2.11.0
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: false
|
||||
|
||||
/sass/1.57.1:
|
||||
resolution: {integrity: sha512-O2+LwLS79op7GI0xZ8fqzF7X2m/m8WFfI02dHOdsK5R2ECeS5F62zrwg/relM1rjSLy7Vd/DiMNIvPrQGsA0jw==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
chokidar: 3.5.3
|
||||
immutable: 4.2.2
|
||||
source-map-js: 1.0.2
|
||||
dev: false
|
||||
|
||||
/simple-swizzle/0.2.2:
|
||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||
dependencies:
|
||||
is-arrayish: 0.3.2
|
||||
dev: false
|
||||
|
||||
/source-map-js/1.0.2:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/supports-preserve-symlinks-flag/1.0.0:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
dev: false
|
||||
|
||||
/to-regex-range/5.0.1:
|
||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||
engines: {node: '>=8.0'}
|
||||
dependencies:
|
||||
is-number: 7.0.0
|
||||
dev: false
|
||||
|
||||
/warning/3.0.0:
|
||||
resolution: {integrity: sha512-jMBt6pUrKn5I+OGgtQ4YZLdhIeJmObddh6CsibPxyQ5yPZm1XExSyzC1LCNX7BzhxWgiHmizBWJTHJIjMjTQYQ==}
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
dev: false
|
19
requirements.txt
Normal file
19
requirements.txt
Normal file
@ -0,0 +1,19 @@
|
||||
tortoise-orm[asyncpg]==0.19.2
|
||||
pylint==2.15.10
|
||||
yapf==0.32.0
|
||||
temporalio==1.0.0
|
||||
click==8.1.3
|
||||
aiohttp==3.8.3
|
||||
openapi-python-client==0.13.1
|
||||
dataclass-wizard==0.22.2
|
||||
fastapi==0.89.1
|
||||
fastapi-pagination==0.11.2
|
||||
Jinja2==3.1.2
|
||||
hypercorn==0.14.3
|
||||
setuptools==58.2.0
|
||||
pydantic==1.10.4
|
||||
passlib[bcrypt]==1.7.4
|
||||
python-multipart==0.0.5
|
||||
itsdangerous==2.1.2
|
||||
PyYAML==6.0
|
||||
beautifulsoup4==4.11.2
|
932
requirements_lock.txt
Normal file
932
requirements_lock.txt
Normal file
@ -0,0 +1,932 @@
|
||||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.9
|
||||
# by the following command:
|
||||
#
|
||||
# bazel run //:requirements.update
|
||||
#
|
||||
aiohttp==3.8.3 \
|
||||
--hash=sha256:02f9a2c72fc95d59b881cf38a4b2be9381b9527f9d328771e90f72ac76f31ad8 \
|
||||
--hash=sha256:059a91e88f2c00fe40aed9031b3606c3f311414f86a90d696dd982e7aec48142 \
|
||||
--hash=sha256:05a3c31c6d7cd08c149e50dc7aa2568317f5844acd745621983380597f027a18 \
|
||||
--hash=sha256:08c78317e950e0762c2983f4dd58dc5e6c9ff75c8a0efeae299d363d439c8e34 \
|
||||
--hash=sha256:09e28f572b21642128ef31f4e8372adb6888846f32fecb288c8b0457597ba61a \
|
||||
--hash=sha256:0d2c6d8c6872df4a6ec37d2ede71eff62395b9e337b4e18efd2177de883a5033 \
|
||||
--hash=sha256:16c121ba0b1ec2b44b73e3a8a171c4f999b33929cd2397124a8c7fcfc8cd9e06 \
|
||||
--hash=sha256:1d90043c1882067f1bd26196d5d2db9aa6d268def3293ed5fb317e13c9413ea4 \
|
||||
--hash=sha256:1e56b9cafcd6531bab5d9b2e890bb4937f4165109fe98e2b98ef0dcfcb06ee9d \
|
||||
--hash=sha256:20acae4f268317bb975671e375493dbdbc67cddb5f6c71eebdb85b34444ac46b \
|
||||
--hash=sha256:21b30885a63c3f4ff5b77a5d6caf008b037cb521a5f33eab445dc566f6d092cc \
|
||||
--hash=sha256:21d69797eb951f155026651f7e9362877334508d39c2fc37bd04ff55b2007091 \
|
||||
--hash=sha256:256deb4b29fe5e47893fa32e1de2d73c3afe7407738bd3c63829874661d4822d \
|
||||
--hash=sha256:25892c92bee6d9449ffac82c2fe257f3a6f297792cdb18ad784737d61e7a9a85 \
|
||||
--hash=sha256:2ca9af5f8f5812d475c5259393f52d712f6d5f0d7fdad9acdb1107dd9e3cb7eb \
|
||||
--hash=sha256:2d252771fc85e0cf8da0b823157962d70639e63cb9b578b1dec9868dd1f4f937 \
|
||||
--hash=sha256:2dea10edfa1a54098703cb7acaa665c07b4e7568472a47f4e64e6319d3821ccf \
|
||||
--hash=sha256:2df5f139233060578d8c2c975128fb231a89ca0a462b35d4b5fcf7c501ebdbe1 \
|
||||
--hash=sha256:2feebbb6074cdbd1ac276dbd737b40e890a1361b3cc30b74ac2f5e24aab41f7b \
|
||||
--hash=sha256:309aa21c1d54b8ef0723181d430347d7452daaff93e8e2363db8e75c72c2fb2d \
|
||||
--hash=sha256:3828fb41b7203176b82fe5d699e0d845435f2374750a44b480ea6b930f6be269 \
|
||||
--hash=sha256:398701865e7a9565d49189f6c90868efaca21be65c725fc87fc305906be915da \
|
||||
--hash=sha256:43046a319664a04b146f81b40e1545d4c8ac7b7dd04c47e40bf09f65f2437346 \
|
||||
--hash=sha256:437399385f2abcd634865705bdc180c8314124b98299d54fe1d4c8990f2f9494 \
|
||||
--hash=sha256:45d88b016c849d74ebc6f2b6e8bc17cabf26e7e40c0661ddd8fae4c00f015697 \
|
||||
--hash=sha256:47841407cc89a4b80b0c52276f3cc8138bbbfba4b179ee3acbd7d77ae33f7ac4 \
|
||||
--hash=sha256:4a4fbc769ea9b6bd97f4ad0b430a6807f92f0e5eb020f1e42ece59f3ecfc4585 \
|
||||
--hash=sha256:4ab94426ddb1ecc6a0b601d832d5d9d421820989b8caa929114811369673235c \
|
||||
--hash=sha256:4b0f30372cef3fdc262f33d06e7b411cd59058ce9174ef159ad938c4a34a89da \
|
||||
--hash=sha256:4e3a23ec214e95c9fe85a58470b660efe6534b83e6cbe38b3ed52b053d7cb6ad \
|
||||
--hash=sha256:512bd5ab136b8dc0ffe3fdf2dfb0c4b4f49c8577f6cae55dca862cd37a4564e2 \
|
||||
--hash=sha256:527b3b87b24844ea7865284aabfab08eb0faf599b385b03c2aa91fc6edd6e4b6 \
|
||||
--hash=sha256:54d107c89a3ebcd13228278d68f1436d3f33f2dd2af5415e3feaeb1156e1a62c \
|
||||
--hash=sha256:5835f258ca9f7c455493a57ee707b76d2d9634d84d5d7f62e77be984ea80b849 \
|
||||
--hash=sha256:598adde339d2cf7d67beaccda3f2ce7c57b3b412702f29c946708f69cf8222aa \
|
||||
--hash=sha256:599418aaaf88a6d02a8c515e656f6faf3d10618d3dd95866eb4436520096c84b \
|
||||
--hash=sha256:5bf651afd22d5f0c4be16cf39d0482ea494f5c88f03e75e5fef3a85177fecdeb \
|
||||
--hash=sha256:5c59fcd80b9049b49acd29bd3598cada4afc8d8d69bd4160cd613246912535d7 \
|
||||
--hash=sha256:653acc3880459f82a65e27bd6526e47ddf19e643457d36a2250b85b41a564715 \
|
||||
--hash=sha256:66bd5f950344fb2b3dbdd421aaa4e84f4411a1a13fca3aeb2bcbe667f80c9f76 \
|
||||
--hash=sha256:6f3553510abdbec67c043ca85727396ceed1272eef029b050677046d3387be8d \
|
||||
--hash=sha256:7018ecc5fe97027214556afbc7c502fbd718d0740e87eb1217b17efd05b3d276 \
|
||||
--hash=sha256:713d22cd9643ba9025d33c4af43943c7a1eb8547729228de18d3e02e278472b6 \
|
||||
--hash=sha256:73a4131962e6d91109bca6536416aa067cf6c4efb871975df734f8d2fd821b37 \
|
||||
--hash=sha256:75880ed07be39beff1881d81e4a907cafb802f306efd6d2d15f2b3c69935f6fb \
|
||||
--hash=sha256:75e14eac916f024305db517e00a9252714fce0abcb10ad327fb6dcdc0d060f1d \
|
||||
--hash=sha256:8135fa153a20d82ffb64f70a1b5c2738684afa197839b34cc3e3c72fa88d302c \
|
||||
--hash=sha256:84b14f36e85295fe69c6b9789b51a0903b774046d5f7df538176516c3e422446 \
|
||||
--hash=sha256:86fc24e58ecb32aee09f864cb11bb91bc4c1086615001647dbfc4dc8c32f4008 \
|
||||
--hash=sha256:87f44875f2804bc0511a69ce44a9595d5944837a62caecc8490bbdb0e18b1342 \
|
||||
--hash=sha256:88c70ed9da9963d5496d38320160e8eb7e5f1886f9290475a881db12f351ab5d \
|
||||
--hash=sha256:88e5be56c231981428f4f506c68b6a46fa25c4123a2e86d156c58a8369d31ab7 \
|
||||
--hash=sha256:89d2e02167fa95172c017732ed7725bc8523c598757f08d13c5acca308e1a061 \
|
||||
--hash=sha256:8d6aaa4e7155afaf994d7924eb290abbe81a6905b303d8cb61310a2aba1c68ba \
|
||||
--hash=sha256:92a2964319d359f494f16011e23434f6f8ef0434acd3cf154a6b7bec511e2fb7 \
|
||||
--hash=sha256:96372fc29471646b9b106ee918c8eeb4cca423fcbf9a34daa1b93767a88a2290 \
|
||||
--hash=sha256:978b046ca728073070e9abc074b6299ebf3501e8dee5e26efacb13cec2b2dea0 \
|
||||
--hash=sha256:9c7149272fb5834fc186328e2c1fa01dda3e1fa940ce18fded6d412e8f2cf76d \
|
||||
--hash=sha256:a0239da9fbafd9ff82fd67c16704a7d1bccf0d107a300e790587ad05547681c8 \
|
||||
--hash=sha256:ad5383a67514e8e76906a06741febd9126fc7c7ff0f599d6fcce3e82b80d026f \
|
||||
--hash=sha256:ad61a9639792fd790523ba072c0555cd6be5a0baf03a49a5dd8cfcf20d56df48 \
|
||||
--hash=sha256:b29bfd650ed8e148f9c515474a6ef0ba1090b7a8faeee26b74a8ff3b33617502 \
|
||||
--hash=sha256:b97decbb3372d4b69e4d4c8117f44632551c692bb1361b356a02b97b69e18a62 \
|
||||
--hash=sha256:ba71c9b4dcbb16212f334126cc3d8beb6af377f6703d9dc2d9fb3874fd667ee9 \
|
||||
--hash=sha256:c37c5cce780349d4d51739ae682dec63573847a2a8dcb44381b174c3d9c8d403 \
|
||||
--hash=sha256:c971bf3786b5fad82ce5ad570dc6ee420f5b12527157929e830f51c55dc8af77 \
|
||||
--hash=sha256:d1fde0f44029e02d02d3993ad55ce93ead9bb9b15c6b7ccd580f90bd7e3de476 \
|
||||
--hash=sha256:d24b8bb40d5c61ef2d9b6a8f4528c2f17f1c5d2d31fed62ec860f6006142e83e \
|
||||
--hash=sha256:d5ba88df9aa5e2f806650fcbeedbe4f6e8736e92fc0e73b0400538fd25a4dd96 \
|
||||
--hash=sha256:d6f76310355e9fae637c3162936e9504b4767d5c52ca268331e2756e54fd4ca5 \
|
||||
--hash=sha256:d737fc67b9a970f3234754974531dc9afeea11c70791dcb7db53b0cf81b79784 \
|
||||
--hash=sha256:da22885266bbfb3f78218dc40205fed2671909fbd0720aedba39b4515c038091 \
|
||||
--hash=sha256:da37dcfbf4b7f45d80ee386a5f81122501ec75672f475da34784196690762f4b \
|
||||
--hash=sha256:db19d60d846283ee275d0416e2a23493f4e6b6028825b51290ac05afc87a6f97 \
|
||||
--hash=sha256:db4c979b0b3e0fa7e9e69ecd11b2b3174c6963cebadeecfb7ad24532ffcdd11a \
|
||||
--hash=sha256:e164e0a98e92d06da343d17d4e9c4da4654f4a4588a20d6c73548a29f176abe2 \
|
||||
--hash=sha256:e168a7560b7c61342ae0412997b069753f27ac4862ec7867eff74f0fe4ea2ad9 \
|
||||
--hash=sha256:e381581b37db1db7597b62a2e6b8b57c3deec95d93b6d6407c5b61ddc98aca6d \
|
||||
--hash=sha256:e65bc19919c910127c06759a63747ebe14f386cda573d95bcc62b427ca1afc73 \
|
||||
--hash=sha256:e7b8813be97cab8cb52b1375f41f8e6804f6507fe4660152e8ca5c48f0436017 \
|
||||
--hash=sha256:e8a78079d9a39ca9ca99a8b0ac2fdc0c4d25fc80c8a8a82e5c8211509c523363 \
|
||||
--hash=sha256:ebf909ea0a3fc9596e40d55d8000702a85e27fd578ff41a5500f68f20fd32e6c \
|
||||
--hash=sha256:ec40170327d4a404b0d91855d41bfe1fe4b699222b2b93e3d833a27330a87a6d \
|
||||
--hash=sha256:f178d2aadf0166be4df834c4953da2d7eef24719e8aec9a65289483eeea9d618 \
|
||||
--hash=sha256:f88df3a83cf9df566f171adba39d5bd52814ac0b94778d2448652fc77f9eb491 \
|
||||
--hash=sha256:f973157ffeab5459eefe7b97a804987876dd0a55570b8fa56b4e1954bf11329b \
|
||||
--hash=sha256:ff25f48fc8e623d95eca0670b8cc1469a83783c924a602e0fbd47363bb54aaca
|
||||
# via -r ./requirements.txt
|
||||
aiosignal==1.3.1 \
|
||||
--hash=sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc \
|
||||
--hash=sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17
|
||||
# via aiohttp
|
||||
aiosqlite==0.17.0 \
|
||||
--hash=sha256:6c49dc6d3405929b1d08eeccc72306d3677503cc5e5e43771efc1e00232e8231 \
|
||||
--hash=sha256:f0e6acc24bc4864149267ac82fb46dfb3be4455f99fe21df82609cc6e6baee51
|
||||
# via tortoise-orm
|
||||
anyio==3.6.2 \
|
||||
--hash=sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421 \
|
||||
--hash=sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3
|
||||
# via
|
||||
# httpcore
|
||||
# starlette
|
||||
astroid==2.13.3 \
|
||||
--hash=sha256:14c1603c41cc61aae731cad1884a073c4645e26f126d13ac8346113c95577f3b \
|
||||
--hash=sha256:6afc22718a48a689ca24a97981ad377ba7fb78c133f40335dfd16772f29bcfb1
|
||||
# via pylint
|
||||
async-timeout==4.0.2 \
|
||||
--hash=sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15 \
|
||||
--hash=sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c
|
||||
# via aiohttp
|
||||
asyncpg==0.27.0 \
|
||||
--hash=sha256:16ba8ec2e85d586b4a12bcd03e8d29e3d99e832764d6a1d0b8c27dbbe4a2569d \
|
||||
--hash=sha256:18f77e8e71e826ba2d0c3ba6764930776719ae2b225ca07e014590545928b576 \
|
||||
--hash=sha256:1b6499de06fe035cf2fa932ec5617ed3f37d4ebbf663b655922e105a484a6af9 \
|
||||
--hash=sha256:20b596d8d074f6f695c13ffb8646d0b6bb1ab570ba7b0cfd349b921ff03cfc1e \
|
||||
--hash=sha256:2232ebae9796d4600a7819fc383da78ab51b32a092795f4555575fc934c1c89d \
|
||||
--hash=sha256:4750f5cf49ed48a6e49c6e5aed390eee367694636c2dcfaf4a273ca832c5c43c \
|
||||
--hash=sha256:4bb366ae34af5b5cabc3ac6a5347dfb6013af38c68af8452f27968d49085ecc0 \
|
||||
--hash=sha256:5710cb0937f696ce303f5eed6d272e3f057339bb4139378ccecafa9ee923a71c \
|
||||
--hash=sha256:609054a1f47292a905582a1cfcca51a6f3f30ab9d822448693e66fdddde27920 \
|
||||
--hash=sha256:62932f29cf2433988fcd799770ec64b374a3691e7902ecf85da14d5e0854d1ea \
|
||||
--hash=sha256:69aa1b443a182b13a17ff926ed6627af2d98f62f2fe5890583270cc4073f63bf \
|
||||
--hash=sha256:71cca80a056ebe19ec74b7117b09e650990c3ca535ac1c35234a96f65604192f \
|
||||
--hash=sha256:720986d9a4705dd8a40fdf172036f5ae787225036a7eb46e704c45aa8f62c054 \
|
||||
--hash=sha256:768e0e7c2898d40b16d4ef7a0b44e8150db3dd8995b4652aa1fe2902e92c7df8 \
|
||||
--hash=sha256:7a6206210c869ebd3f4eb9e89bea132aefb56ff3d1b7dd7e26b102b17e27bbb1 \
|
||||
--hash=sha256:7d8585707ecc6661d07367d444bbaa846b4e095d84451340da8df55a3757e152 \
|
||||
--hash=sha256:8113e17cfe236dc2277ec844ba9b3d5312f61bd2fdae6d3ed1c1cdd75f6cf2d8 \
|
||||
--hash=sha256:879c29a75969eb2722f94443752f4720d560d1e748474de54ae8dd230bc4956b \
|
||||
--hash=sha256:88b62164738239f62f4af92567b846a8ef7cf8abf53eddd83650603de4d52163 \
|
||||
--hash=sha256:8934577e1ed13f7d2d9cea3cc016cc6f95c19faedea2c2b56a6f94f257cea672 \
|
||||
--hash=sha256:9654085f2b22f66952124de13a8071b54453ff972c25c59b5ce1173a4283ffd9 \
|
||||
--hash=sha256:975a320baf7020339a67315284a4d3bf7460e664e484672bd3e71dbd881bc692 \
|
||||
--hash=sha256:9a3a4ff43702d39e3c97a8786314123d314e0f0e4dabc8367db5b665c93914de \
|
||||
--hash=sha256:a7a94c03386bb95456b12c66026b3a87d1b965f0f1e5733c36e7229f8f137747 \
|
||||
--hash=sha256:ab0f21c4818d46a60ca789ebc92327d6d874d3b7ccff3963f7af0a21dc6cff52 \
|
||||
--hash=sha256:bb71211414dd1eeb8d31ec529fe77cff04bf53efc783a5f6f0a32d84923f45cf \
|
||||
--hash=sha256:bf21ebf023ec67335258e0f3d3ad7b91bb9507985ba2b2206346de488267cad0 \
|
||||
--hash=sha256:bfc3980b4ba6f97138b04f0d32e8af21d6c9fa1f8e6e140c07d15690a0a99279 \
|
||||
--hash=sha256:c2232d4625c558f2aa001942cac1d7952aa9f0dbfc212f63bc754277769e1ef2 \
|
||||
--hash=sha256:ccddb9419ab4e1c48742457d0c0362dbdaeb9b28e6875115abfe319b29ee225d \
|
||||
--hash=sha256:d20dea7b83651d93b1eb2f353511fe7fd554752844523f17ad30115d8b9c8cd6 \
|
||||
--hash=sha256:e56ac8a8237ad4adec97c0cd4728596885f908053ab725e22900b5902e7f8e69 \
|
||||
--hash=sha256:eb4b2fdf88af4fb1cc569781a8f933d2a73ee82cd720e0cb4edabbaecf2a905b \
|
||||
--hash=sha256:eca01eb112a39d31cc4abb93a5aef2a81514c23f70956729f42fb83b11b3483f \
|
||||
--hash=sha256:fca608d199ffed4903dce1bcd97ad0fe8260f405c1c225bdf0002709132171c2 \
|
||||
--hash=sha256:fddcacf695581a8d856654bc4c8cfb73d5c9df26d5f55201722d3e6a699e9629
|
||||
# via tortoise-orm
|
||||
attrs==22.2.0 \
|
||||
--hash=sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836 \
|
||||
--hash=sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99
|
||||
# via
|
||||
# aiohttp
|
||||
# openapi-python-client
|
||||
autoflake==2.0.0 \
|
||||
--hash=sha256:7185b596e70d8970c6d4106c112ef41921e472bd26abf3613db99eca88cc8c2a \
|
||||
--hash=sha256:d58ed4187c6b4f623a942b9a90c43ff84bf6a266f3682f407b42ca52073c9678
|
||||
# via openapi-python-client
|
||||
bcrypt==4.0.1 \
|
||||
--hash=sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535 \
|
||||
--hash=sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0 \
|
||||
--hash=sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410 \
|
||||
--hash=sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd \
|
||||
--hash=sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665 \
|
||||
--hash=sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab \
|
||||
--hash=sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71 \
|
||||
--hash=sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215 \
|
||||
--hash=sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b \
|
||||
--hash=sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda \
|
||||
--hash=sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9 \
|
||||
--hash=sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a \
|
||||
--hash=sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344 \
|
||||
--hash=sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f \
|
||||
--hash=sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d \
|
||||
--hash=sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c \
|
||||
--hash=sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c \
|
||||
--hash=sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2 \
|
||||
--hash=sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d \
|
||||
--hash=sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e \
|
||||
--hash=sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3
|
||||
# via passlib
|
||||
beautifulsoup4==4.11.2 \
|
||||
--hash=sha256:0e79446b10b3ecb499c1556f7e228a53e64a2bfcebd455f370d8927cb5b59e39 \
|
||||
--hash=sha256:bc4bdda6717de5a2987436fb8d72f45dc90dd856bdfd512a1314ce90349a0106
|
||||
# via -r ./requirements.txt
|
||||
black==22.12.0 \
|
||||
--hash=sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320 \
|
||||
--hash=sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351 \
|
||||
--hash=sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350 \
|
||||
--hash=sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f \
|
||||
--hash=sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf \
|
||||
--hash=sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148 \
|
||||
--hash=sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4 \
|
||||
--hash=sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d \
|
||||
--hash=sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc \
|
||||
--hash=sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d \
|
||||
--hash=sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2 \
|
||||
--hash=sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f
|
||||
# via openapi-python-client
|
||||
certifi==2022.12.7 \
|
||||
--hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \
|
||||
--hash=sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18
|
||||
# via
|
||||
# httpcore
|
||||
# httpx
|
||||
charset-normalizer==2.1.1 \
|
||||
--hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \
|
||||
--hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f
|
||||
# via aiohttp
|
||||
click==8.1.3 \
|
||||
--hash=sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e \
|
||||
--hash=sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48
|
||||
# via
|
||||
# -r ./requirements.txt
|
||||
# black
|
||||
# typer
|
||||
dataclass-wizard==0.22.2 \
|
||||
--hash=sha256:211f842e5e9a8ace50ba891ef428cd78c82579fb98024f80f3e630ca8d1946f6 \
|
||||
--hash=sha256:49be36ecc64bc5a1e9a35a6bad1d71d33b6b9b06877404931a17c6a3a6dfbb10
|
||||
# via -r ./requirements.txt
|
||||
dill==0.3.6 \
|
||||
--hash=sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0 \
|
||||
--hash=sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373
|
||||
# via pylint
|
||||
fastapi==0.89.1 \
|
||||
--hash=sha256:15d9271ee52b572a015ca2ae5c72e1ce4241dd8532a534ad4f7ec70c376a580f \
|
||||
--hash=sha256:f9773ea22290635b2f48b4275b2bf69a8fa721fda2e38228bed47139839dc877
|
||||
# via
|
||||
# -r ./requirements.txt
|
||||
# fastapi-pagination
|
||||
fastapi-pagination==0.11.2 \
|
||||
--hash=sha256:55ecf04131c22c9ee9b9c060d42b1555fba1188aa60fac826a9e475bb9246e83 \
|
||||
--hash=sha256:db4bde1c055a85e3840faa70b2a63d27e45542c0ebd97cba8ca786850bb48c6d
|
||||
# via -r ./requirements.txt
|
||||
frozenlist==1.3.3 \
|
||||
--hash=sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c \
|
||||
--hash=sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f \
|
||||
--hash=sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a \
|
||||
--hash=sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784 \
|
||||
--hash=sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27 \
|
||||
--hash=sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d \
|
||||
--hash=sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3 \
|
||||
--hash=sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678 \
|
||||
--hash=sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a \
|
||||
--hash=sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483 \
|
||||
--hash=sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8 \
|
||||
--hash=sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf \
|
||||
--hash=sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99 \
|
||||
--hash=sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c \
|
||||
--hash=sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48 \
|
||||
--hash=sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5 \
|
||||
--hash=sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56 \
|
||||
--hash=sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e \
|
||||
--hash=sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1 \
|
||||
--hash=sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401 \
|
||||
--hash=sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4 \
|
||||
--hash=sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e \
|
||||
--hash=sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649 \
|
||||
--hash=sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a \
|
||||
--hash=sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d \
|
||||
--hash=sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0 \
|
||||
--hash=sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6 \
|
||||
--hash=sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d \
|
||||
--hash=sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b \
|
||||
--hash=sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6 \
|
||||
--hash=sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf \
|
||||
--hash=sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef \
|
||||
--hash=sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7 \
|
||||
--hash=sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842 \
|
||||
--hash=sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba \
|
||||
--hash=sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420 \
|
||||
--hash=sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b \
|
||||
--hash=sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d \
|
||||
--hash=sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332 \
|
||||
--hash=sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936 \
|
||||
--hash=sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816 \
|
||||
--hash=sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91 \
|
||||
--hash=sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420 \
|
||||
--hash=sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448 \
|
||||
--hash=sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411 \
|
||||
--hash=sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4 \
|
||||
--hash=sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32 \
|
||||
--hash=sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b \
|
||||
--hash=sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0 \
|
||||
--hash=sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530 \
|
||||
--hash=sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669 \
|
||||
--hash=sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7 \
|
||||
--hash=sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1 \
|
||||
--hash=sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5 \
|
||||
--hash=sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce \
|
||||
--hash=sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4 \
|
||||
--hash=sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e \
|
||||
--hash=sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2 \
|
||||
--hash=sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d \
|
||||
--hash=sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9 \
|
||||
--hash=sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642 \
|
||||
--hash=sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0 \
|
||||
--hash=sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703 \
|
||||
--hash=sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb \
|
||||
--hash=sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1 \
|
||||
--hash=sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13 \
|
||||
--hash=sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab \
|
||||
--hash=sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38 \
|
||||
--hash=sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb \
|
||||
--hash=sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb \
|
||||
--hash=sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81 \
|
||||
--hash=sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8 \
|
||||
--hash=sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd \
|
||||
--hash=sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4
|
||||
# via
|
||||
# aiohttp
|
||||
# aiosignal
|
||||
h11==0.14.0 \
|
||||
--hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \
|
||||
--hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761
|
||||
# via
|
||||
# httpcore
|
||||
# hypercorn
|
||||
# wsproto
|
||||
h2==4.1.0 \
|
||||
--hash=sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d \
|
||||
--hash=sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb
|
||||
# via hypercorn
|
||||
hpack==4.0.0 \
|
||||
--hash=sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c \
|
||||
--hash=sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095
|
||||
# via h2
|
||||
httpcore==0.16.3 \
|
||||
--hash=sha256:c5d6f04e2fc530f39e0c077e6a30caa53f1451096120f1f38b954afd0b17c0cb \
|
||||
--hash=sha256:da1fb708784a938aa084bde4feb8317056c55037247c787bd7e19eb2c2949dc0
|
||||
# via httpx
|
||||
httpx==0.23.3 \
|
||||
--hash=sha256:9818458eb565bb54898ccb9b8b251a28785dd4a55afbc23d0eb410754fe7d0f9 \
|
||||
--hash=sha256:a211fcce9b1254ea24f0cd6af9869b3d29aba40154e947d2a07bb499b3e310d6
|
||||
# via openapi-python-client
|
||||
hypercorn==0.14.3 \
|
||||
--hash=sha256:4a87a0b7bbe9dc75fab06dbe4b301b9b90416e9866c23a377df21a969d6ab8dd \
|
||||
--hash=sha256:7c491d5184f28ee960dcdc14ab45d14633ca79d72ddd13cf4fcb4cb854d679ab
|
||||
# via -r ./requirements.txt
|
||||
hyperframe==6.0.1 \
|
||||
--hash=sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15 \
|
||||
--hash=sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914
|
||||
# via h2
|
||||
idna==3.4 \
|
||||
--hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
|
||||
--hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
|
||||
# via
|
||||
# anyio
|
||||
# rfc3986
|
||||
# yarl
|
||||
iso8601==1.1.0 \
|
||||
--hash=sha256:32811e7b81deee2063ea6d2e94f8819a86d1f3811e49d23623a41fa832bef03f \
|
||||
--hash=sha256:8400e90141bf792bce2634df533dc57e3bee19ea120a87bebcd3da89a58ad73f
|
||||
# via tortoise-orm
|
||||
isort==5.11.4 \
|
||||
--hash=sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6 \
|
||||
--hash=sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b
|
||||
# via
|
||||
# openapi-python-client
|
||||
# pylint
|
||||
itsdangerous==2.1.2 \
|
||||
--hash=sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44 \
|
||||
--hash=sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a
|
||||
# via -r ./requirements.txt
|
||||
jinja2==3.1.2 \
|
||||
--hash=sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852 \
|
||||
--hash=sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61
|
||||
# via
|
||||
# -r ./requirements.txt
|
||||
# openapi-python-client
|
||||
lazy-object-proxy==1.9.0 \
|
||||
--hash=sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382 \
|
||||
--hash=sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82 \
|
||||
--hash=sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9 \
|
||||
--hash=sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494 \
|
||||
--hash=sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46 \
|
||||
--hash=sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30 \
|
||||
--hash=sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63 \
|
||||
--hash=sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4 \
|
||||
--hash=sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae \
|
||||
--hash=sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be \
|
||||
--hash=sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701 \
|
||||
--hash=sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd \
|
||||
--hash=sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006 \
|
||||
--hash=sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a \
|
||||
--hash=sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586 \
|
||||
--hash=sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8 \
|
||||
--hash=sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821 \
|
||||
--hash=sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07 \
|
||||
--hash=sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b \
|
||||
--hash=sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171 \
|
||||
--hash=sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b \
|
||||
--hash=sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2 \
|
||||
--hash=sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7 \
|
||||
--hash=sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4 \
|
||||
--hash=sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8 \
|
||||
--hash=sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e \
|
||||
--hash=sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f \
|
||||
--hash=sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda \
|
||||
--hash=sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4 \
|
||||
--hash=sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e \
|
||||
--hash=sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671 \
|
||||
--hash=sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11 \
|
||||
--hash=sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455 \
|
||||
--hash=sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734 \
|
||||
--hash=sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb \
|
||||
--hash=sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59
|
||||
# via astroid
|
||||
markupsafe==2.1.2 \
|
||||
--hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \
|
||||
--hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \
|
||||
--hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \
|
||||
--hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \
|
||||
--hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \
|
||||
--hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \
|
||||
--hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \
|
||||
--hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \
|
||||
--hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \
|
||||
--hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \
|
||||
--hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \
|
||||
--hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \
|
||||
--hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \
|
||||
--hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \
|
||||
--hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \
|
||||
--hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \
|
||||
--hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \
|
||||
--hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \
|
||||
--hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \
|
||||
--hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \
|
||||
--hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \
|
||||
--hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \
|
||||
--hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \
|
||||
--hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \
|
||||
--hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \
|
||||
--hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \
|
||||
--hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \
|
||||
--hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \
|
||||
--hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \
|
||||
--hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \
|
||||
--hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \
|
||||
--hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \
|
||||
--hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \
|
||||
--hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \
|
||||
--hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \
|
||||
--hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \
|
||||
--hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \
|
||||
--hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \
|
||||
--hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \
|
||||
--hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \
|
||||
--hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \
|
||||
--hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \
|
||||
--hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \
|
||||
--hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \
|
||||
--hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \
|
||||
--hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \
|
||||
--hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \
|
||||
--hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \
|
||||
--hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \
|
||||
--hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58
|
||||
# via jinja2
|
||||
mccabe==0.7.0 \
|
||||
--hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \
|
||||
--hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e
|
||||
# via pylint
|
||||
multidict==6.0.4 \
|
||||
--hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \
|
||||
--hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \
|
||||
--hash=sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03 \
|
||||
--hash=sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710 \
|
||||
--hash=sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161 \
|
||||
--hash=sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664 \
|
||||
--hash=sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569 \
|
||||
--hash=sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067 \
|
||||
--hash=sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313 \
|
||||
--hash=sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706 \
|
||||
--hash=sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2 \
|
||||
--hash=sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636 \
|
||||
--hash=sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49 \
|
||||
--hash=sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93 \
|
||||
--hash=sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603 \
|
||||
--hash=sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0 \
|
||||
--hash=sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60 \
|
||||
--hash=sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4 \
|
||||
--hash=sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e \
|
||||
--hash=sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1 \
|
||||
--hash=sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60 \
|
||||
--hash=sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951 \
|
||||
--hash=sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc \
|
||||
--hash=sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe \
|
||||
--hash=sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95 \
|
||||
--hash=sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d \
|
||||
--hash=sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8 \
|
||||
--hash=sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed \
|
||||
--hash=sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2 \
|
||||
--hash=sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775 \
|
||||
--hash=sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87 \
|
||||
--hash=sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c \
|
||||
--hash=sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2 \
|
||||
--hash=sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98 \
|
||||
--hash=sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3 \
|
||||
--hash=sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe \
|
||||
--hash=sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78 \
|
||||
--hash=sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660 \
|
||||
--hash=sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176 \
|
||||
--hash=sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e \
|
||||
--hash=sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988 \
|
||||
--hash=sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c \
|
||||
--hash=sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c \
|
||||
--hash=sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0 \
|
||||
--hash=sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449 \
|
||||
--hash=sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f \
|
||||
--hash=sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde \
|
||||
--hash=sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5 \
|
||||
--hash=sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d \
|
||||
--hash=sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac \
|
||||
--hash=sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a \
|
||||
--hash=sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9 \
|
||||
--hash=sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca \
|
||||
--hash=sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11 \
|
||||
--hash=sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35 \
|
||||
--hash=sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063 \
|
||||
--hash=sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b \
|
||||
--hash=sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982 \
|
||||
--hash=sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258 \
|
||||
--hash=sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1 \
|
||||
--hash=sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52 \
|
||||
--hash=sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480 \
|
||||
--hash=sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7 \
|
||||
--hash=sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461 \
|
||||
--hash=sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d \
|
||||
--hash=sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc \
|
||||
--hash=sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779 \
|
||||
--hash=sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a \
|
||||
--hash=sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547 \
|
||||
--hash=sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0 \
|
||||
--hash=sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171 \
|
||||
--hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \
|
||||
--hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \
|
||||
--hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba
|
||||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
mypy-extensions==0.4.3 \
|
||||
--hash=sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d \
|
||||
--hash=sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8
|
||||
# via black
|
||||
openapi-python-client==0.13.1 \
|
||||
--hash=sha256:43bcd2e43e39dc31decba76ec09cbaeb6faad8709ce4684aec9b0228cd1bf3b5 \
|
||||
--hash=sha256:adb5d886946cae2ff654f26396bd4d3f497234d5a9dafee805ee19587acbfdce
|
||||
# via -r ./requirements.txt
|
||||
passlib[bcrypt]==1.7.4 \
|
||||
--hash=sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1 \
|
||||
--hash=sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04
|
||||
# via -r ./requirements.txt
|
||||
pathspec==0.11.0 \
|
||||
--hash=sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229 \
|
||||
--hash=sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc
|
||||
# via black
|
||||
platformdirs==2.6.2 \
|
||||
--hash=sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490 \
|
||||
--hash=sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2
|
||||
# via
|
||||
# black
|
||||
# pylint
|
||||
priority==2.0.0 \
|
||||
--hash=sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa \
|
||||
--hash=sha256:c965d54f1b8d0d0b19479db3924c7c36cf672dbf2aec92d43fbdaf4492ba18c0
|
||||
# via hypercorn
|
||||
protobuf==4.21.12 \
|
||||
--hash=sha256:1f22ac0ca65bb70a876060d96d914dae09ac98d114294f77584b0d2644fa9c30 \
|
||||
--hash=sha256:237216c3326d46808a9f7c26fd1bd4b20015fb6867dc5d263a493ef9a539293b \
|
||||
--hash=sha256:27f4d15021da6d2b706ddc3860fac0a5ddaba34ab679dc182b60a8bb4e1121cc \
|
||||
--hash=sha256:299ea899484ee6f44604deb71f424234f654606b983cb496ea2a53e3c63ab791 \
|
||||
--hash=sha256:3d164928ff0727d97022957c2b849250ca0e64777ee31efd7d6de2e07c494717 \
|
||||
--hash=sha256:6ab80df09e3208f742c98443b6166bcb70d65f52cfeb67357d52032ea1ae9bec \
|
||||
--hash=sha256:78a28c9fa223998472886c77042e9b9afb6fe4242bd2a2a5aced88e3f4422aa7 \
|
||||
--hash=sha256:7cd532c4566d0e6feafecc1059d04c7915aec8e182d1cf7adee8b24ef1e2e6ab \
|
||||
--hash=sha256:89f9149e4a0169cddfc44c74f230d7743002e3aa0b9472d8c28f0388102fc4c2 \
|
||||
--hash=sha256:a53fd3f03e578553623272dc46ac2f189de23862e68565e83dde203d41b76fc5 \
|
||||
--hash=sha256:b135410244ebe777db80298297a97fbb4c862c881b4403b71bac9d4107d61fd1 \
|
||||
--hash=sha256:b98d0148f84e3a3c569e19f52103ca1feacdac0d2df8d6533cf983d1fda28462 \
|
||||
--hash=sha256:d1736130bce8cf131ac7957fa26880ca19227d4ad68b4888b3be0dea1f95df97 \
|
||||
--hash=sha256:f45460f9ee70a0ec1b6694c6e4e348ad2019275680bd68a1d9314b8c7e01e574
|
||||
# via temporalio
|
||||
pydantic==1.10.4 \
|
||||
--hash=sha256:05a81b006be15655b2a1bae5faa4280cf7c81d0e09fcb49b342ebf826abe5a72 \
|
||||
--hash=sha256:0b53e1d41e97063d51a02821b80538053ee4608b9a181c1005441f1673c55423 \
|
||||
--hash=sha256:2b3ce5f16deb45c472dde1a0ee05619298c864a20cded09c4edd820e1454129f \
|
||||
--hash=sha256:2e82a6d37a95e0b1b42b82ab340ada3963aea1317fd7f888bb6b9dfbf4fff57c \
|
||||
--hash=sha256:301d626a59edbe5dfb48fcae245896379a450d04baeed50ef40d8199f2733b06 \
|
||||
--hash=sha256:39f4a73e5342b25c2959529f07f026ef58147249f9b7431e1ba8414a36761f53 \
|
||||
--hash=sha256:4948f264678c703f3877d1c8877c4e3b2e12e549c57795107f08cf70c6ec7774 \
|
||||
--hash=sha256:4b05697738e7d2040696b0a66d9f0a10bec0efa1883ca75ee9e55baf511909d6 \
|
||||
--hash=sha256:51bdeb10d2db0f288e71d49c9cefa609bca271720ecd0c58009bd7504a0c464c \
|
||||
--hash=sha256:55b1625899acd33229c4352ce0ae54038529b412bd51c4915349b49ca575258f \
|
||||
--hash=sha256:572066051eeac73d23f95ba9a71349c42a3e05999d0ee1572b7860235b850cc6 \
|
||||
--hash=sha256:6a05a9db1ef5be0fe63e988f9617ca2551013f55000289c671f71ec16f4985e3 \
|
||||
--hash=sha256:6dc1cc241440ed7ca9ab59d9929075445da6b7c94ced281b3dd4cfe6c8cff817 \
|
||||
--hash=sha256:6e7124d6855b2780611d9f5e1e145e86667eaa3bd9459192c8dc1a097f5e9903 \
|
||||
--hash=sha256:75d52162fe6b2b55964fbb0af2ee58e99791a3138588c482572bb6087953113a \
|
||||
--hash=sha256:78cec42b95dbb500a1f7120bdf95c401f6abb616bbe8785ef09887306792e66e \
|
||||
--hash=sha256:7feb6a2d401f4d6863050f58325b8d99c1e56f4512d98b11ac64ad1751dc647d \
|
||||
--hash=sha256:8775d4ef5e7299a2f4699501077a0defdaac5b6c4321173bcb0f3c496fbadf85 \
|
||||
--hash=sha256:887ca463c3bc47103c123bc06919c86720e80e1214aab79e9b779cda0ff92a00 \
|
||||
--hash=sha256:9193d4f4ee8feca58bc56c8306bcb820f5c7905fd919e0750acdeeeef0615b28 \
|
||||
--hash=sha256:983e720704431a6573d626b00662eb78a07148c9115129f9b4351091ec95ecc3 \
|
||||
--hash=sha256:990406d226dea0e8f25f643b370224771878142155b879784ce89f633541a024 \
|
||||
--hash=sha256:9cbdc268a62d9a98c56e2452d6c41c0263d64a2009aac69246486f01b4f594c4 \
|
||||
--hash=sha256:a48f1953c4a1d9bd0b5167ac50da9a79f6072c63c4cef4cf2a3736994903583e \
|
||||
--hash=sha256:a9a6747cac06c2beb466064dda999a13176b23535e4c496c9d48e6406f92d42d \
|
||||
--hash=sha256:a9f2de23bec87ff306aef658384b02aa7c32389766af3c5dee9ce33e80222dfa \
|
||||
--hash=sha256:b5635de53e6686fe7a44b5cf25fcc419a0d5e5c1a1efe73d49d48fe7586db854 \
|
||||
--hash=sha256:b6f9d649892a6f54a39ed56b8dfd5e08b5f3be5f893da430bed76975f3735d15 \
|
||||
--hash=sha256:b9a3859f24eb4e097502a3be1fb4b2abb79b6103dd9e2e0edb70613a4459a648 \
|
||||
--hash=sha256:cd8702c5142afda03dc2b1ee6bc358b62b3735b2cce53fc77b31ca9f728e4bc8 \
|
||||
--hash=sha256:d7b5a3821225f5c43496c324b0d6875fde910a1c2933d726a743ce328fbb2a8c \
|
||||
--hash=sha256:d88c4c0e5c5dfd05092a4b271282ef0588e5f4aaf345778056fc5259ba098857 \
|
||||
--hash=sha256:eb992a1ef739cc7b543576337bebfc62c0e6567434e522e97291b251a41dad7f \
|
||||
--hash=sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416 \
|
||||
--hash=sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978 \
|
||||
--hash=sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d
|
||||
# via
|
||||
# -r ./requirements.txt
|
||||
# fastapi
|
||||
# fastapi-pagination
|
||||
# openapi-python-client
|
||||
pyflakes==3.0.1 \
|
||||
--hash=sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf \
|
||||
--hash=sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd
|
||||
# via autoflake
|
||||
pylint==2.15.10 \
|
||||
--hash=sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e \
|
||||
--hash=sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5
|
||||
# via -r ./requirements.txt
|
||||
pypika-tortoise==0.1.6 \
|
||||
--hash=sha256:2d68bbb7e377673743cff42aa1059f3a80228d411fbcae591e4465e173109fd8 \
|
||||
--hash=sha256:d802868f479a708e3263724c7b5719a26ad79399b2a70cea065f4a4cadbebf36
|
||||
# via tortoise-orm
|
||||
python-dateutil==2.8.2 \
|
||||
--hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \
|
||||
--hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9
|
||||
# via
|
||||
# openapi-python-client
|
||||
# temporalio
|
||||
python-multipart==0.0.5 \
|
||||
--hash=sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43
|
||||
# via -r ./requirements.txt
|
||||
pytz==2022.7.1 \
|
||||
--hash=sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0 \
|
||||
--hash=sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a
|
||||
# via tortoise-orm
|
||||
pyyaml==6.0 \
|
||||
--hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \
|
||||
--hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \
|
||||
--hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \
|
||||
--hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \
|
||||
--hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \
|
||||
--hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \
|
||||
--hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \
|
||||
--hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \
|
||||
--hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \
|
||||
--hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \
|
||||
--hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \
|
||||
--hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \
|
||||
--hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \
|
||||
--hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \
|
||||
--hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \
|
||||
--hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \
|
||||
--hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \
|
||||
--hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \
|
||||
--hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \
|
||||
--hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \
|
||||
--hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \
|
||||
--hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \
|
||||
--hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \
|
||||
--hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \
|
||||
--hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \
|
||||
--hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \
|
||||
--hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \
|
||||
--hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \
|
||||
--hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \
|
||||
--hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \
|
||||
--hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \
|
||||
--hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \
|
||||
--hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \
|
||||
--hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \
|
||||
--hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \
|
||||
--hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \
|
||||
--hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \
|
||||
--hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \
|
||||
--hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \
|
||||
--hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5
|
||||
# via
|
||||
# -r ./requirements.txt
|
||||
# openapi-python-client
|
||||
rfc3986[idna2008]==1.5.0 \
|
||||
--hash=sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835 \
|
||||
--hash=sha256:a86d6e1f5b1dc238b218b012df0aa79409667bb209e58da56d0b94704e712a97
|
||||
# via httpx
|
||||
setuptools==58.2.0 \
|
||||
--hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11 \
|
||||
--hash=sha256:2c55bdb85d5bb460bd2e3b12052b677879cffcf46c0c688f2e5bf51d36001145
|
||||
# via -r ./requirements.txt
|
||||
shellingham==1.5.0.post1 \
|
||||
--hash=sha256:368bf8c00754fd4f55afb7bbb86e272df77e4dc76ac29dbcbb81a59e9fc15744 \
|
||||
--hash=sha256:823bc5fb5c34d60f285b624e7264f4dda254bc803a3774a147bf99c0e3004a28
|
||||
# via openapi-python-client
|
||||
six==1.16.0 \
|
||||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||
--hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254
|
||||
# via
|
||||
# python-dateutil
|
||||
# python-multipart
|
||||
sniffio==1.3.0 \
|
||||
--hash=sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101 \
|
||||
--hash=sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384
|
||||
# via
|
||||
# anyio
|
||||
# httpcore
|
||||
# httpx
|
||||
soupsieve==2.3.2.post1 \
|
||||
--hash=sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759 \
|
||||
--hash=sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d
|
||||
# via beautifulsoup4
|
||||
starlette==0.22.0 \
|
||||
--hash=sha256:b092cbc365bea34dd6840b42861bdabb2f507f8671e642e8272d2442e08ea4ff \
|
||||
--hash=sha256:b5eda991ad5f0ee5d8ce4c4540202a573bb6691ecd0c712262d0bc85cf8f2c50
|
||||
# via fastapi
|
||||
temporalio==1.0.0 \
|
||||
--hash=sha256:06126178cbb98d44667914ac57876f24fc3e3532384374cae8b38a6ac59ad8fe \
|
||||
--hash=sha256:4d17e953e93241162133cd6e9581bc8a3804a6e2e3aee8ac3c1d503536d7d8c9 \
|
||||
--hash=sha256:5efbdad3e409b2f2169c34167a5219ca9abd6ebd694fc52ae974f04b2d7c8d79 \
|
||||
--hash=sha256:7c18030d63f178c6c6d958d26c136e77888b7bd1d6db67b129de1bea9a1bd463 \
|
||||
--hash=sha256:7c82a875c3db9ab2c8492ddc01498dbb2636cad34cf8bc985a6f0f17bd627f99 \
|
||||
--hash=sha256:b2454ef6b68335a554adca1e4f14831b5c3ea33ef8adb25742dd91652bd38a82
|
||||
# via -r ./requirements.txt
|
||||
toml==0.10.2 \
|
||||
--hash=sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b \
|
||||
--hash=sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f
|
||||
# via hypercorn
|
||||
tomli==2.0.1 \
|
||||
--hash=sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc \
|
||||
--hash=sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f
|
||||
# via
|
||||
# autoflake
|
||||
# black
|
||||
# pylint
|
||||
tomlkit==0.11.6 \
|
||||
--hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \
|
||||
--hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73
|
||||
# via pylint
|
||||
tortoise-orm[asyncpg]==0.19.2 \
|
||||
--hash=sha256:a99b8c9f42d5cd49493c70471b5c9a5df8ecf49cc624f2f41b9dc75bba993ac5 \
|
||||
--hash=sha256:bff4d79abfca7fb805972bb2438e8e0cd2e6590bc2cfd7593a803518a027bbf0
|
||||
# via -r ./requirements.txt
|
||||
typer==0.7.0 \
|
||||
--hash=sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d \
|
||||
--hash=sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165
|
||||
# via openapi-python-client
|
||||
types-protobuf==3.20.4.6 \
|
||||
--hash=sha256:ab2d315ba82246b83d28f8797c98dc0fe1dd5cfd187909e56faf87239aedaae3 \
|
||||
--hash=sha256:ba27443c592bbec1629dd69494a24c84461c63f0d3b7d648ce258aaae9680965
|
||||
# via temporalio
|
||||
typing-extensions==4.4.0 \
|
||||
--hash=sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa \
|
||||
--hash=sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e
|
||||
# via
|
||||
# aiosqlite
|
||||
# astroid
|
||||
# black
|
||||
# dataclass-wizard
|
||||
# pydantic
|
||||
# pylint
|
||||
# starlette
|
||||
# temporalio
|
||||
wrapt==1.14.1 \
|
||||
--hash=sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3 \
|
||||
--hash=sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b \
|
||||
--hash=sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4 \
|
||||
--hash=sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2 \
|
||||
--hash=sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656 \
|
||||
--hash=sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3 \
|
||||
--hash=sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff \
|
||||
--hash=sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310 \
|
||||
--hash=sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a \
|
||||
--hash=sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57 \
|
||||
--hash=sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069 \
|
||||
--hash=sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383 \
|
||||
--hash=sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe \
|
||||
--hash=sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87 \
|
||||
--hash=sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d \
|
||||
--hash=sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b \
|
||||
--hash=sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907 \
|
||||
--hash=sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f \
|
||||
--hash=sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0 \
|
||||
--hash=sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28 \
|
||||
--hash=sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1 \
|
||||
--hash=sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853 \
|
||||
--hash=sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc \
|
||||
--hash=sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3 \
|
||||
--hash=sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3 \
|
||||
--hash=sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164 \
|
||||
--hash=sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1 \
|
||||
--hash=sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c \
|
||||
--hash=sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1 \
|
||||
--hash=sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7 \
|
||||
--hash=sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1 \
|
||||
--hash=sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320 \
|
||||
--hash=sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed \
|
||||
--hash=sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1 \
|
||||
--hash=sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248 \
|
||||
--hash=sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c \
|
||||
--hash=sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456 \
|
||||
--hash=sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77 \
|
||||
--hash=sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef \
|
||||
--hash=sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1 \
|
||||
--hash=sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7 \
|
||||
--hash=sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86 \
|
||||
--hash=sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4 \
|
||||
--hash=sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d \
|
||||
--hash=sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d \
|
||||
--hash=sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8 \
|
||||
--hash=sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5 \
|
||||
--hash=sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471 \
|
||||
--hash=sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00 \
|
||||
--hash=sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68 \
|
||||
--hash=sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3 \
|
||||
--hash=sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d \
|
||||
--hash=sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735 \
|
||||
--hash=sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d \
|
||||
--hash=sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569 \
|
||||
--hash=sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7 \
|
||||
--hash=sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59 \
|
||||
--hash=sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5 \
|
||||
--hash=sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb \
|
||||
--hash=sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b \
|
||||
--hash=sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f \
|
||||
--hash=sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462 \
|
||||
--hash=sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015 \
|
||||
--hash=sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af
|
||||
# via astroid
|
||||
wsproto==1.2.0 \
|
||||
--hash=sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065 \
|
||||
--hash=sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736
|
||||
# via hypercorn
|
||||
yapf==0.32.0 \
|
||||
--hash=sha256:8fea849025584e486fd06d6ba2bed717f396080fd3cc236ba10cb97c4c51cf32 \
|
||||
--hash=sha256:a3f5085d37ef7e3e004c4ba9f9b3e40c54ff1901cd111f05145ae313a7c67d1b
|
||||
# via -r ./requirements.txt
|
||||
yarl==1.8.2 \
|
||||
--hash=sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87 \
|
||||
--hash=sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89 \
|
||||
--hash=sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a \
|
||||
--hash=sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08 \
|
||||
--hash=sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996 \
|
||||
--hash=sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077 \
|
||||
--hash=sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901 \
|
||||
--hash=sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e \
|
||||
--hash=sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee \
|
||||
--hash=sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574 \
|
||||
--hash=sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165 \
|
||||
--hash=sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634 \
|
||||
--hash=sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229 \
|
||||
--hash=sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b \
|
||||
--hash=sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f \
|
||||
--hash=sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7 \
|
||||
--hash=sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf \
|
||||
--hash=sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89 \
|
||||
--hash=sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0 \
|
||||
--hash=sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1 \
|
||||
--hash=sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe \
|
||||
--hash=sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf \
|
||||
--hash=sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76 \
|
||||
--hash=sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951 \
|
||||
--hash=sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863 \
|
||||
--hash=sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06 \
|
||||
--hash=sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562 \
|
||||
--hash=sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6 \
|
||||
--hash=sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c \
|
||||
--hash=sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e \
|
||||
--hash=sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1 \
|
||||
--hash=sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3 \
|
||||
--hash=sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3 \
|
||||
--hash=sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778 \
|
||||
--hash=sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8 \
|
||||
--hash=sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2 \
|
||||
--hash=sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b \
|
||||
--hash=sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d \
|
||||
--hash=sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f \
|
||||
--hash=sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c \
|
||||
--hash=sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581 \
|
||||
--hash=sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918 \
|
||||
--hash=sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c \
|
||||
--hash=sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e \
|
||||
--hash=sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220 \
|
||||
--hash=sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37 \
|
||||
--hash=sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739 \
|
||||
--hash=sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77 \
|
||||
--hash=sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6 \
|
||||
--hash=sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42 \
|
||||
--hash=sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946 \
|
||||
--hash=sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5 \
|
||||
--hash=sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d \
|
||||
--hash=sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146 \
|
||||
--hash=sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a \
|
||||
--hash=sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83 \
|
||||
--hash=sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef \
|
||||
--hash=sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80 \
|
||||
--hash=sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588 \
|
||||
--hash=sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5 \
|
||||
--hash=sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2 \
|
||||
--hash=sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef \
|
||||
--hash=sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826 \
|
||||
--hash=sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05 \
|
||||
--hash=sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516 \
|
||||
--hash=sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0 \
|
||||
--hash=sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4 \
|
||||
--hash=sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2 \
|
||||
--hash=sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0 \
|
||||
--hash=sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd \
|
||||
--hash=sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8 \
|
||||
--hash=sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b \
|
||||
--hash=sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1 \
|
||||
--hash=sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c
|
||||
# via aiohttp
|
Loading…
Reference in New Issue
Block a user