Return template from call
This commit is contained in:
parent
92db413da6
commit
15c15faf30
5 changed files with 105 additions and 279 deletions
|
@ -1,257 +1,3 @@
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
from Crypto.PublicKey import RSA
|
|
||||||
from flask import Flask, request, Request
|
from flask import Flask, request, Request
|
||||||
from flask_login import LoginManager
|
|
||||||
from flask_mail import Mail
|
|
||||||
from flask_principal import Principal
|
|
||||||
from jwkest.jwk import RSAKey
|
|
||||||
|
|
||||||
import features
|
|
||||||
from _init import CONF_DIR
|
|
||||||
from auth.auth_context import get_authenticated_user
|
|
||||||
from avatars.avatars import Avatar
|
|
||||||
from buildman.manager.buildcanceller import BuildCanceller
|
|
||||||
from data import database
|
|
||||||
from data import model
|
|
||||||
from data.archivedlogs import LogArchive
|
|
||||||
from data.billing import Billing
|
|
||||||
from data.buildlogs import BuildLogs
|
|
||||||
from data.cache import get_model_cache
|
|
||||||
from data.model.user import LoginWrappedDBUser
|
|
||||||
from data.queue import WorkQueue, BuildMetricQueueReporter
|
|
||||||
from data.userevent import UserEventsBuilderModule
|
|
||||||
from data.userfiles import Userfiles
|
|
||||||
from data.users import UserAuthentication
|
|
||||||
from path_converters import RegexConverter, RepositoryPathConverter, APIRepositoryPathConverter
|
|
||||||
from oauth.services.github import GithubOAuthService
|
|
||||||
from oauth.services.gitlab import GitLabOAuthService
|
|
||||||
from oauth.loginmanager import OAuthLoginManager
|
|
||||||
from storage import Storage
|
|
||||||
from util.log import filter_logs
|
|
||||||
from util import get_app_url
|
|
||||||
from util.ipresolver import IPResolver
|
|
||||||
from util.saas.analytics import Analytics
|
|
||||||
from util.saas.useranalytics import UserAnalytics
|
|
||||||
from util.saas.exceptionlog import Sentry
|
|
||||||
from util.names import urn_generator
|
|
||||||
from util.config.configutil import generate_secret_key
|
|
||||||
from util.config.provider import get_config_provider
|
|
||||||
from util.config.superusermanager import SuperUserManager
|
|
||||||
from util.label_validator import LabelValidator
|
|
||||||
from util.metrics.metricqueue import MetricQueue
|
|
||||||
from util.metrics.prometheus import PrometheusPlugin
|
|
||||||
from util.saas.cloudwatch import start_cloudwatch_sender
|
|
||||||
from util.secscan.api import SecurityScannerAPI
|
|
||||||
from util.tufmetadata.api import TUFMetadataAPI
|
|
||||||
from util.security.instancekeys import InstanceKeys
|
|
||||||
from util.security.signing import Signer
|
|
||||||
|
|
||||||
|
|
||||||
OVERRIDE_CONFIG_DIRECTORY = os.path.join(CONF_DIR, 'stack/')
|
|
||||||
OVERRIDE_CONFIG_YAML_FILENAME = os.path.join(CONF_DIR, 'stack/config.yaml')
|
|
||||||
OVERRIDE_CONFIG_PY_FILENAME = os.path.join(CONF_DIR, 'stack/config.py')
|
|
||||||
|
|
||||||
OVERRIDE_CONFIG_KEY = 'QUAY_OVERRIDE_CONFIG'
|
|
||||||
|
|
||||||
DOCKER_V2_SIGNINGKEY_FILENAME = 'docker_v2.pem'
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# Instantiate the configuration.
|
|
||||||
is_testing = 'TEST' in os.environ
|
|
||||||
is_kubernetes = 'KUBERNETES_SERVICE_HOST' in os.environ
|
|
||||||
config_provider = get_config_provider(OVERRIDE_CONFIG_DIRECTORY, 'config.yaml', 'config.py',
|
|
||||||
testing=is_testing, kubernetes=is_kubernetes)
|
|
||||||
|
|
||||||
if is_testing:
|
|
||||||
from test.testconfig import TestConfig
|
|
||||||
logger.debug('Loading test config.')
|
|
||||||
app.config.from_object(TestConfig())
|
|
||||||
else:
|
|
||||||
from config import DefaultConfig
|
|
||||||
logger.debug('Loading default config.')
|
|
||||||
app.config.from_object(DefaultConfig())
|
|
||||||
app.teardown_request(database.close_db_filter)
|
|
||||||
|
|
||||||
# Load the override config via the provider.
|
|
||||||
config_provider.update_app_config(app.config)
|
|
||||||
|
|
||||||
# Update any configuration found in the override environment variable.
|
|
||||||
environ_config = json.loads(os.environ.get(OVERRIDE_CONFIG_KEY, '{}'))
|
|
||||||
app.config.update(environ_config)
|
|
||||||
|
|
||||||
# Allow user to define a custom storage preference for the local instance.
|
|
||||||
_distributed_storage_preference = os.environ.get('QUAY_DISTRIBUTED_STORAGE_PREFERENCE', '').split()
|
|
||||||
if _distributed_storage_preference:
|
|
||||||
app.config['DISTRIBUTED_STORAGE_PREFERENCE'] = _distributed_storage_preference
|
|
||||||
|
|
||||||
# Generate a secret key if none was specified.
|
|
||||||
if app.config['SECRET_KEY'] is None:
|
|
||||||
logger.debug('Generating in-memory secret key')
|
|
||||||
app.config['SECRET_KEY'] = generate_secret_key()
|
|
||||||
|
|
||||||
# If the "preferred" scheme is https, then http is not allowed. Therefore, ensure we have a secure
|
|
||||||
# session cookie.
|
|
||||||
if (app.config['PREFERRED_URL_SCHEME'] == 'https' and
|
|
||||||
not app.config.get('FORCE_NONSECURE_SESSION_COOKIE', False)):
|
|
||||||
app.config['SESSION_COOKIE_SECURE'] = True
|
|
||||||
|
|
||||||
# Load features from config.
|
|
||||||
features.import_features(app.config)
|
|
||||||
|
|
||||||
CONFIG_DIGEST = hashlib.sha256(json.dumps(app.config, default=str)).hexdigest()[0:8]
|
|
||||||
|
|
||||||
logger.debug("Loaded config", extra={"config": app.config})
|
|
||||||
|
|
||||||
|
|
||||||
class RequestWithId(Request):
|
|
||||||
request_gen = staticmethod(urn_generator(['request']))
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(RequestWithId, self).__init__(*args, **kwargs)
|
|
||||||
self.request_id = self.request_gen()
|
|
||||||
|
|
||||||
|
|
||||||
@app.before_request
|
|
||||||
def _request_start():
|
|
||||||
logger.debug('Starting request: %s (%s)', request.request_id, request.path,
|
|
||||||
extra={"request_id": request.request_id})
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_FILTER = lambda x: '[FILTERED]'
|
|
||||||
FILTERED_VALUES = [
|
|
||||||
{'key': ['password'], 'fn': DEFAULT_FILTER},
|
|
||||||
{'key': ['user', 'password'], 'fn': DEFAULT_FILTER},
|
|
||||||
{'key': ['blob'], 'fn': lambda x: x[0:8]}
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
@app.after_request
|
|
||||||
def _request_end(resp):
|
|
||||||
jsonbody = request.get_json(force=True, silent=True)
|
|
||||||
values = request.values.to_dict()
|
|
||||||
|
|
||||||
if jsonbody and not isinstance(jsonbody, dict):
|
|
||||||
jsonbody = {'_parsererror': jsonbody}
|
|
||||||
|
|
||||||
if isinstance(values, dict):
|
|
||||||
filter_logs(values, FILTERED_VALUES)
|
|
||||||
|
|
||||||
extra = {
|
|
||||||
"endpoint": request.endpoint,
|
|
||||||
"request_id" : request.request_id,
|
|
||||||
"remote_addr": request.remote_addr,
|
|
||||||
"http_method": request.method,
|
|
||||||
"original_url": request.url,
|
|
||||||
"path": request.path,
|
|
||||||
"parameters": values,
|
|
||||||
"json_body": jsonbody,
|
|
||||||
"confsha": CONFIG_DIGEST,
|
|
||||||
}
|
|
||||||
|
|
||||||
if request.user_agent is not None:
|
|
||||||
extra["user-agent"] = request.user_agent.string
|
|
||||||
|
|
||||||
logger.debug('Ending request: %s (%s)', request.request_id, request.path, extra=extra)
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
root_logger = logging.getLogger()
|
|
||||||
|
|
||||||
app.request_class = RequestWithId
|
|
||||||
|
|
||||||
# Register custom converters.
|
|
||||||
app.url_map.converters['regex'] = RegexConverter
|
|
||||||
app.url_map.converters['repopath'] = RepositoryPathConverter
|
|
||||||
app.url_map.converters['apirepopath'] = APIRepositoryPathConverter
|
|
||||||
|
|
||||||
Principal(app, use_sessions=False)
|
|
||||||
|
|
||||||
tf = app.config['DB_TRANSACTION_FACTORY']
|
|
||||||
|
|
||||||
model_cache = get_model_cache(app.config)
|
|
||||||
avatar = Avatar(app)
|
|
||||||
login_manager = LoginManager(app)
|
|
||||||
mail = Mail(app)
|
|
||||||
prometheus = PrometheusPlugin(app)
|
|
||||||
metric_queue = MetricQueue(prometheus)
|
|
||||||
chunk_cleanup_queue = WorkQueue(app.config['CHUNK_CLEANUP_QUEUE_NAME'], tf, metric_queue=metric_queue)
|
|
||||||
instance_keys = InstanceKeys(app)
|
|
||||||
ip_resolver = IPResolver(app)
|
|
||||||
storage = Storage(app, metric_queue, chunk_cleanup_queue, instance_keys, config_provider, ip_resolver)
|
|
||||||
userfiles = Userfiles(app, storage)
|
|
||||||
log_archive = LogArchive(app, storage)
|
|
||||||
analytics = Analytics(app)
|
|
||||||
user_analytics = UserAnalytics(app)
|
|
||||||
billing = Billing(app)
|
|
||||||
sentry = Sentry(app)
|
|
||||||
build_logs = BuildLogs(app)
|
|
||||||
authentication = UserAuthentication(app, config_provider, OVERRIDE_CONFIG_DIRECTORY)
|
|
||||||
userevents = UserEventsBuilderModule(app)
|
|
||||||
superusers = SuperUserManager(app)
|
|
||||||
signer = Signer(app, config_provider)
|
|
||||||
instance_keys = InstanceKeys(app)
|
|
||||||
label_validator = LabelValidator(app)
|
|
||||||
build_canceller = BuildCanceller(app)
|
|
||||||
|
|
||||||
start_cloudwatch_sender(metric_queue, app)
|
|
||||||
|
|
||||||
github_trigger = GithubOAuthService(app.config, 'GITHUB_TRIGGER_CONFIG')
|
|
||||||
gitlab_trigger = GitLabOAuthService(app.config, 'GITLAB_TRIGGER_CONFIG')
|
|
||||||
|
|
||||||
oauth_login = OAuthLoginManager(app.config)
|
|
||||||
oauth_apps = [github_trigger, gitlab_trigger]
|
|
||||||
|
|
||||||
image_replication_queue = WorkQueue(app.config['REPLICATION_QUEUE_NAME'], tf,
|
|
||||||
has_namespace=False, metric_queue=metric_queue)
|
|
||||||
dockerfile_build_queue = WorkQueue(app.config['DOCKERFILE_BUILD_QUEUE_NAME'], tf,
|
|
||||||
metric_queue=metric_queue,
|
|
||||||
reporter=BuildMetricQueueReporter(metric_queue),
|
|
||||||
has_namespace=True)
|
|
||||||
notification_queue = WorkQueue(app.config['NOTIFICATION_QUEUE_NAME'], tf, has_namespace=True,
|
|
||||||
metric_queue=metric_queue)
|
|
||||||
secscan_notification_queue = WorkQueue(app.config['SECSCAN_NOTIFICATION_QUEUE_NAME'], tf,
|
|
||||||
has_namespace=False,
|
|
||||||
metric_queue=metric_queue)
|
|
||||||
|
|
||||||
# Note: We set `has_namespace` to `False` here, as we explicitly want this queue to not be emptied
|
|
||||||
# when a namespace is marked for deletion.
|
|
||||||
namespace_gc_queue = WorkQueue(app.config['NAMESPACE_GC_QUEUE_NAME'], tf, has_namespace=False,
|
|
||||||
metric_queue=metric_queue)
|
|
||||||
|
|
||||||
all_queues = [image_replication_queue, dockerfile_build_queue, notification_queue,
|
|
||||||
secscan_notification_queue, chunk_cleanup_queue, namespace_gc_queue]
|
|
||||||
|
|
||||||
secscan_api = SecurityScannerAPI(app, app.config, storage)
|
|
||||||
tuf_metadata_api = TUFMetadataAPI(app, app.config)
|
|
||||||
|
|
||||||
# Check for a key in config. If none found, generate a new signing key for Docker V2 manifests.
|
|
||||||
_v2_key_path = os.path.join(OVERRIDE_CONFIG_DIRECTORY, DOCKER_V2_SIGNINGKEY_FILENAME)
|
|
||||||
if os.path.exists(_v2_key_path):
|
|
||||||
docker_v2_signing_key = RSAKey().load(_v2_key_path)
|
|
||||||
else:
|
|
||||||
docker_v2_signing_key = RSAKey(key=RSA.generate(2048))
|
|
||||||
|
|
||||||
|
|
||||||
database.configure(app.config)
|
|
||||||
model.config.app_config = app.config
|
|
||||||
model.config.store = storage
|
|
||||||
model.config.register_image_cleanup_callback(secscan_api.cleanup_layers)
|
|
||||||
model.config.register_repo_cleanup_callback(tuf_metadata_api.delete_metadata)
|
|
||||||
|
|
||||||
|
|
||||||
@login_manager.user_loader
|
|
||||||
def load_user(user_uuid):
|
|
||||||
logger.debug('User loader loading deferred user with uuid: %s', user_uuid)
|
|
||||||
return LoginWrappedDBUser(user_uuid)
|
|
||||||
|
|
||||||
|
|
||||||
get_app_url = partial(get_app_url, app.config)
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import os
|
# import os
|
||||||
import logging
|
# import logging
|
||||||
import logging.config
|
# import logging.config
|
||||||
|
|
||||||
from util.log import logfile_path
|
# from util.log import logfile_path
|
||||||
from app import app as application
|
from app import app as application
|
||||||
|
|
||||||
|
|
||||||
|
|
78
config_app/config_endpoints/common.py
Normal file
78
config_app/config_endpoints/common.py
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
from flask import make_response, render_template, request, session
|
||||||
|
|
||||||
|
def render_page_template(name, route_data=None, **kwargs):
|
||||||
|
""" Renders the page template with the given name as the response and returns its contents. """
|
||||||
|
# main_scripts = _list_files('build', 'js', js_bundle_name)
|
||||||
|
#
|
||||||
|
# use_cdn = app.config.get('USE_CDN', True)
|
||||||
|
# if request.args.get('use_cdn') is not None:
|
||||||
|
# use_cdn = request.args.get('use_cdn') == 'true'
|
||||||
|
#
|
||||||
|
# external_styles = get_external_css(local=not use_cdn)
|
||||||
|
# external_scripts = get_external_javascript(local=not use_cdn)
|
||||||
|
#
|
||||||
|
# # Add Stripe checkout if billing is enabled.
|
||||||
|
# if features.BILLING:
|
||||||
|
# external_scripts.append('//checkout.stripe.com/checkout.js')
|
||||||
|
#
|
||||||
|
# def get_external_login_config():
|
||||||
|
# login_config = []
|
||||||
|
# for login_service in oauth_login.services:
|
||||||
|
# login_config.append({
|
||||||
|
# 'id': login_service.service_id(),
|
||||||
|
# 'title': login_service.service_name(),
|
||||||
|
# 'config': login_service.get_public_config(),
|
||||||
|
# 'icon': login_service.get_icon(),
|
||||||
|
# })
|
||||||
|
#
|
||||||
|
# return login_config
|
||||||
|
#
|
||||||
|
# def get_oauth_config():
|
||||||
|
# oauth_config = {}
|
||||||
|
# for oauth_app in oauth_apps:
|
||||||
|
# oauth_config[oauth_app.key_name] = oauth_app.get_public_config()
|
||||||
|
#
|
||||||
|
# return oauth_config
|
||||||
|
#
|
||||||
|
# contact_href = None
|
||||||
|
# if len(app.config.get('CONTACT_INFO', [])) == 1:
|
||||||
|
# contact_href = app.config['CONTACT_INFO'][0]
|
||||||
|
#
|
||||||
|
# version_number = ''
|
||||||
|
# if not features.BILLING:
|
||||||
|
# version_number = 'Quay %s' % __version__
|
||||||
|
#
|
||||||
|
# scopes_set = {scope.scope: scope._asdict() for scope in scopes.app_scopes(app.config).values()}
|
||||||
|
|
||||||
|
contents = render_template(name,
|
||||||
|
route_data=route_data,
|
||||||
|
# external_styles=external_styles,
|
||||||
|
# external_scripts=external_scripts,
|
||||||
|
# main_scripts=main_scripts,
|
||||||
|
# feature_set=features.get_features(),
|
||||||
|
# config_set=frontend_visible_config(app.config),
|
||||||
|
# oauth_set=get_oauth_config(),
|
||||||
|
# external_login_set=get_external_login_config(),
|
||||||
|
# scope_set=scopes_set,
|
||||||
|
# vuln_priority_set=PRIORITY_LEVELS,
|
||||||
|
# enterprise_logo=app.config.get('ENTERPRISE_LOGO_URL', ''),
|
||||||
|
# mixpanel_key=app.config.get('MIXPANEL_KEY', ''),
|
||||||
|
# munchkin_key=app.config.get('MARKETO_MUNCHKIN_ID', ''),
|
||||||
|
# recaptcha_key=app.config.get('RECAPTCHA_SITE_KEY', ''),
|
||||||
|
# google_tagmanager_key=app.config.get('GOOGLE_TAGMANAGER_KEY', ''),
|
||||||
|
# google_anaytics_key=app.config.get('GOOGLE_ANALYTICS_KEY', ''),
|
||||||
|
# sentry_public_dsn=app.config.get('SENTRY_PUBLIC_DSN', ''),
|
||||||
|
# is_debug=str(app.config.get('DEBUGGING', False)).lower(),
|
||||||
|
# show_chat=features.SUPPORT_CHAT,
|
||||||
|
# aci_conversion=features.ACI_CONVERSION,
|
||||||
|
# has_billing=features.BILLING,
|
||||||
|
# contact_href=contact_href,
|
||||||
|
# hostname=app.config['SERVER_HOSTNAME'],
|
||||||
|
# preferred_scheme=app.config['PREFERRED_URL_SCHEME'],
|
||||||
|
# version_number=version_number,
|
||||||
|
# current_year=datetime.datetime.now().year,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
resp = make_response(contents)
|
||||||
|
resp.headers['X-FRAME-OPTIONS'] = 'DENY'
|
||||||
|
return resp
|
|
@ -5,25 +5,26 @@ import logging
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
from cachetools import lru_cache
|
from cachetools import lru_cache
|
||||||
from flask import (abort, redirect, request, url_for, make_response, Response, render_template,
|
# from flask import (abort, redirect, request, url_for, make_response, Response, render_template,
|
||||||
Blueprint, jsonify, send_file, session)
|
# Blueprint, jsonify, send_file, session)
|
||||||
from flask_login import current_user
|
from flask import Blueprint
|
||||||
|
# from flask_login import current_user
|
||||||
|
|
||||||
|
|
||||||
from app import (app)
|
from app import (app)
|
||||||
from endpoints.api.discovery import swagger_route_data
|
# from endpoints.api.discovery import swagger_route_data
|
||||||
from endpoints.common import common_login, render_page_template
|
from common import render_page_template
|
||||||
from util.cache import no_cache
|
from util.cache import no_cache
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=1)
|
# @lru_cache(maxsize=1)
|
||||||
def _get_route_data():
|
# def _get_route_data():
|
||||||
return swagger_route_data(include_internal=True, compact=True)
|
# return swagger_route_data(include_internal=True, compact=True)
|
||||||
|
|
||||||
|
|
||||||
def render_page_template_with_routedata(name, *args, **kwargs):
|
def render_page_template_with_routedata(name, *args, **kwargs):
|
||||||
return render_page_template(name, _get_route_data(), *args, **kwargs)
|
return render_page_template(name, *args, **kwargs)
|
||||||
|
|
||||||
# Capture the unverified SSL errors.
|
# Capture the unverified SSL errors.
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -31,7 +32,7 @@ logging.captureWarnings(True)
|
||||||
|
|
||||||
setup_web = Blueprint('setup_web', __name__, template_folder='templates')
|
setup_web = Blueprint('setup_web', __name__, template_folder='templates')
|
||||||
|
|
||||||
STATUS_TAGS = app.config['STATUS_TAGS']
|
# STATUS_TAGS = app.config['STATUS_TAGS']
|
||||||
|
|
||||||
@setup_web.route('/', methods=['GET'], defaults={'path': ''})
|
@setup_web.route('/', methods=['GET'], defaults={'path': ''})
|
||||||
@no_cache
|
@no_cache
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
{% extends "base.html" %}
|
<!DOCTYPE html>
|
||||||
|
<html ng-app="quay">
|
||||||
{% block title %}
|
<head>
|
||||||
<title>Config mode</title>
|
<title>Config app</title>
|
||||||
{% endblock %}
|
</head>
|
||||||
{% block body_content %}
|
<body>
|
||||||
<p>
|
<div>
|
||||||
<div>What is my purpose?</div>
|
<p>What is my purpose</p>
|
||||||
<div>You create tarballs</div>
|
<p>You make tarballs</p>
|
||||||
</p>
|
</div>
|
||||||
{% endblock %}
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Reference in a new issue