diff --git a/Dockerfile b/Dockerfile index ef4cf3ee1..34d68e93a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -138,4 +138,5 @@ RUN ./scripts/detect-config.sh EXPOSE 443 8443 80 -CMD ./quay-entrypoint.sh +ENTRYPOINT [ "/bin/bash", "./quay-entrypoint.sh"] + diff --git a/config_app/Procfile b/config_app/Procfile index 22dd965c1..16b3fb8a4 100644 --- a/config_app/Procfile +++ b/config_app/Procfile @@ -1,3 +1,3 @@ app: PYTHONPATH="../" gunicorn -c conf/gunicorn_local.py config_application:application -# webpack: npm run watch-config-app +webpack: npm run watch-config-app diff --git a/config_app/_init_config.py b/config_app/_init_config.py index 494edad57..1ab66a338 100644 --- a/config_app/_init_config.py +++ b/config_app/_init_config.py @@ -3,7 +3,8 @@ import re import subprocess -ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) +# Note: this currently points to the directory above, since we're in the quay config_app dir. When extracting, revert +ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) CONF_DIR = os.getenv("QUAYCONF", os.path.join(ROOT_DIR, "conf/")) STATIC_DIR = os.path.join(ROOT_DIR, 'static/') STATIC_LDN_DIR = os.path.join(STATIC_DIR, 'ldn/') @@ -11,9 +12,6 @@ STATIC_FONTS_DIR = os.path.join(STATIC_DIR, 'fonts/') TEMPLATE_DIR = os.path.join(ROOT_DIR, 'templates/') -# TODO(config): Remove this external folder dependency -EXTERNAL_REPO_REQUIRE_PATH = os.path.dirname(ROOT_DIR) - def _get_version_number_changelog(): try: diff --git a/config_app/c_app.py b/config_app/c_app.py index 449563181..6235701da 100644 --- a/config_app/c_app.py +++ b/config_app/c_app.py @@ -1,8 +1,9 @@ import os import logging from flask import Flask -from _init_config import CONF_DIR +from _init_config import ROOT_DIR from config_app.config_util.config import get_config_provider +from util.ipresolver import NoopIPResolver from util.config.superusermanager import SuperUserManager @@ -11,7 +12,8 @@ app = Flask(__name__) logger = logging.getLogger(__name__) -OVERRIDE_CONFIG_DIRECTORY = os.path.join(CONF_DIR, 'stack/') +# OVERRIDE_CONFIG_DIRECTORY = os.path.join(ROOT_DIR, 'stack/') +OVERRIDE_CONFIG_DIRECTORY = os.path.join(ROOT_DIR, 'config_app/conf/stack') is_testing = 'TEST' in os.environ @@ -33,3 +35,4 @@ else: # Load the override config via the provider. config_provider.update_app_config(app.config) superusers = SuperUserManager(app) +ip_resolver = NoopIPResolver() \ No newline at end of file diff --git a/config_app/conf/gunicorn_local.py b/config_app/conf/gunicorn_local.py index 7fcd83a9c..377c1ba0f 100644 --- a/config_app/conf/gunicorn_local.py +++ b/config_app/conf/gunicorn_local.py @@ -10,7 +10,7 @@ from config_app.config_util.workers import get_worker_count logconfig = logfile_path(debug=True) -bind = '127.0.0.1:5000' +bind = '0.0.0.0:5000' workers = get_worker_count('local', 2, minimum=2, maximum=8) worker_class = 'gevent' daemon = False diff --git a/config_app/config_app_config.py b/config_app/config_app_config.py index 2b8204115..cd2d35be4 100644 --- a/config_app/config_app_config.py +++ b/config_app/config_app_config.py @@ -3,7 +3,7 @@ from uuid import uuid4 import os.path import requests -from _init_config import ROOT_DIR, CONF_DIR, EXTERNAL_REPO_REQUIRE_PATH +from _init_config import ROOT_DIR, CONF_DIR def build_requests_session(): @@ -48,7 +48,7 @@ class ImmutableConfig(object): # Status tag config STATUS_TAGS = {} for tag_name in ['building', 'failed', 'none', 'ready', 'cancelled']: - tag_path = os.path.join(EXTERNAL_REPO_REQUIRE_PATH, 'buildstatus', tag_name + '.svg') + tag_path = os.path.join(ROOT_DIR, 'buildstatus', tag_name + '.svg') with open(tag_path) as tag_svg: STATUS_TAGS[tag_name] = tag_svg.read() diff --git a/config_app/config_endpoints/api/suconfig.py b/config_app/config_endpoints/api/suconfig.py index 79e759ec2..03cb895e4 100644 --- a/config_app/config_endpoints/api/suconfig.py +++ b/config_app/config_endpoints/api/suconfig.py @@ -7,7 +7,7 @@ from flask import abort, request from config_app.config_endpoints.api.suconfig_models_pre_oci import pre_oci_model as model from config_app.config_endpoints.api import resource, ApiResource, verify_not_prod, nickname, validate_json_request -from config_app.c_app import app, config_provider, superusers, OVERRIDE_CONFIG_DIRECTORY +from config_app.c_app import app, config_provider, superusers, OVERRIDE_CONFIG_DIRECTORY, ip_resolver from auth.auth_context import get_authenticated_user from data.users import get_federated_service_name, get_users_handler @@ -15,8 +15,7 @@ from data.database import configure from data.runmigration import run_alembic_migration from util.config.configutil import add_enterprise_config_defaults from util.config.database import sync_database_with_config -# TODO(config) re-add this import when we get the app extracted from validators -# from util.config.validator import validate_service_for_config +from util.config.validator import validate_service_for_config, ValidatorContext logger = logging.getLogger(__name__) @@ -64,9 +63,6 @@ class SuperUserConfig(ApiResource): def get(self): """ Returns the currently defined configuration, if any. """ config_object = config_provider.get_config() - logger.debug(config_object) - logger.debug(config_provider) - # Todo: do we even need this endpoint? Since we'll be loading the config in browser return { 'config': config_object } @@ -350,6 +346,10 @@ class SuperUserConfigValidate(ApiResource): # if not config_provider.config_exists() or SuperUserPermission().can(): if not config_provider.config_exists(): config = request.get_json()['config'] - return validate_service_for_config(service, config, request.get_json().get('password', '')) + validator_context = ValidatorContext.from_app(app, config, request.get_json().get('password', ''), + ip_resolver=ip_resolver, + config_provider=config_provider) + return validate_service_for_config(service, validator_context) + abort(403) diff --git a/config_app/config_util/log.py b/config_app/config_util/log.py index 4a934953a..9d91b3d68 100644 --- a/config_app/config_util/log.py +++ b/config_app/config_util/log.py @@ -1,5 +1,5 @@ import os -from _init_config import CONF_DIR +from config_app._init_config import CONF_DIR def logfile_path(jsonfmt=False, debug=False): diff --git a/config_app/init/service/gunicorn_web/run b/config_app/init/service/gunicorn_web/run new file mode 100755 index 000000000..e7564a2c9 --- /dev/null +++ b/config_app/init/service/gunicorn_web/run @@ -0,0 +1,11 @@ +#! /bin/bash + +echo 'Starting gunicon' + +QUAYPATH=${QUAYPATH:-"."} +QUAYCONF=${QUAYCONF:-"$QUAYPATH/conf"} + +cd ${QUAYDIR:-"/"} +PYTHONPATH=$QUAYPATH venv/bin/gunicorn -c $QUAYDIR/config_app/conf/gunicorn_local.py config_application:application + +echo 'Gunicorn exited' \ No newline at end of file diff --git a/config_app/js/services/api-service.js b/config_app/js/services/api-service.js index ace9cce64..09b88bcfa 100644 --- a/config_app/js/services/api-service.js +++ b/config_app/js/services/api-service.js @@ -324,8 +324,5 @@ angular.module('quay-config').factory('ApiService', ['Restangular', '$q', 'UtilS }; }; - // todo: remove hacks - apiService.scRegistryStatus = () => new Promise(() => { hello: true }); - return apiService; }]); diff --git a/config_app/js/setup/setup.component.js b/config_app/js/setup/setup.component.js index 3e828214c..d8d4f2b6e 100644 --- a/config_app/js/setup/setup.component.js +++ b/config_app/js/setup/setup.component.js @@ -196,6 +196,7 @@ const templateUrl = require('./setup.html'); }; $scope.isStep = function(step) { + console.log('current step is', step); for (var i = 1; i < arguments.length; ++i) { if (arguments[i] == step) { return true; diff --git a/quay-entrypoint.sh b/quay-entrypoint.sh index a67c2c5eb..9e9a60fe5 100755 --- a/quay-entrypoint.sh +++ b/quay-entrypoint.sh @@ -3,8 +3,8 @@ MODE="$1" display_usage() { - echo "This script takes one arguments." - echo -e "\nUsage: ${0} \n" + echo "This script takes one argument." + echo -e "\nUsage: ${0} \n" } if [[ "${MODE}" = "help" ]] @@ -32,6 +32,10 @@ EOF venv/bin/python -m displayversion case "$MODE" in + "config") + echo "Entering config mode, only copying config-app entrypoints" + cp -r ${QUAYDIR}/config_app/init/service/* /etc/service + ;; "interactive") echo "Copying $MODE files" cp -r ${QUAYCONF}/init/service/interactive/* /etc/service diff --git a/util/config/validators/validate_secscan.py b/util/config/validators/validate_secscan.py index 9f7c2d67f..c690e68d4 100644 --- a/util/config/validators/validate_secscan.py +++ b/util/config/validators/validate_secscan.py @@ -1,6 +1,6 @@ import time -from boot import setup_jwt_proxy +# from boot import setup_jwt_proxy from util.secscan.api import SecurityScannerAPI from util.config.validators import BaseValidator, ConfigValidationException @@ -23,9 +23,9 @@ class SecurityScannerValidator(BaseValidator): api = SecurityScannerAPI(config, None, server_hostname, client=client, skip_validation=True, uri_creator=uri_creator) - if not is_testing: + # if not is_testing: # Generate a temporary Quay key to use for signing the outgoing requests. - setup_jwt_proxy() + # setup_jwt_proxy() # We have to wait for JWT proxy to restart with the newly generated key. max_tries = 5 diff --git a/util/config/validators/validate_torrent.py b/util/config/validators/validate_torrent.py index d8137e12c..dce091efa 100644 --- a/util/config/validators/validate_torrent.py +++ b/util/config/validators/validate_torrent.py @@ -3,7 +3,7 @@ import logging from hashlib import sha1 from util.config.validators import BaseValidator, ConfigValidationException -from util.registry.torrent import jwt_from_infohash +# from util.registry.torrent import jwt_from_infohash logger = logging.getLogger(__name__) @@ -31,8 +31,8 @@ class BittorrentValidator(BaseValidator): 'port': 80, } - encoded_jwt = jwt_from_infohash(params['info_hash']) - params['jwt'] = encoded_jwt + # encoded_jwt = jwt_from_infohash(params['info_hash']) + # params['jwt'] = encoded_jwt resp = client.get(announce_url, timeout=5, params=params) logger.debug('Got tracker response: %s: %s', resp.status_code, resp.text)