| @@ -107,7 +107,7 @@ def before_request(): | |||||
| def create_app(): | def create_app(): | ||||
| """Set flask APP config, and start the data manager.""" | """Set flask APP config, and start the data manager.""" | ||||
| static_url_path = "/static" | |||||
| static_url_path = settings.URL_PATH_PREFIX + "/static" | |||||
| static_folder_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'ui', 'dist', 'static')) | static_folder_path = os.path.realpath(os.path.join(os.path.dirname(__file__), os.pardir, 'ui', 'dist', 'static')) | ||||
| app = Flask(__name__, static_url_path=static_url_path, static_folder=static_folder_path) | app = Flask(__name__, static_url_path=static_url_path, static_folder=static_folder_path) | ||||
| @@ -20,20 +20,18 @@ from flask import current_app | |||||
| from flask import send_from_directory | from flask import send_from_directory | ||||
| from flask import Blueprint | from flask import Blueprint | ||||
| from mindinsight.conf import settings | |||||
| APP_PATH = os.path.realpath(os.path.dirname(sys.argv[0])) | |||||
| BLUEPRINT = Blueprint("static_resource", __name__) | |||||
| BLUEPRINT = Blueprint("static_resource", __name__, url_prefix=settings.URL_PATH_PREFIX) | |||||
| @BLUEPRINT.route("/", methods=["GET"]) | @BLUEPRINT.route("/", methods=["GET"]) | ||||
| def index(): | def index(): | ||||
| """Interface to return static index.html.""" | """Interface to return static index.html.""" | ||||
| return send_from_directory(get_index_resource_dir(), "index.html") | |||||
| def get_index_resource_dir(): | |||||
| """Interface to return index.html resource directory.""" | |||||
| return os.path.realpath(os.path.join(APP_PATH, current_app.static_folder, os.pardir)) | |||||
| app_path = os.path.realpath(os.path.dirname(sys.argv[0])) | |||||
| index_resource_dir = os.path.realpath(os.path.join(app_path, current_app.static_folder, os.pardir)) | |||||
| return send_from_directory(index_resource_dir, "index.html") | |||||
| def init_module(app): | def init_module(app): | ||||
| @@ -34,7 +34,7 @@ from mindinsight.datavisual.processors.train_task_manager import TrainTaskManage | |||||
| from mindinsight.datavisual.data_transform.data_manager import DATA_MANAGER | from mindinsight.datavisual.data_transform.data_manager import DATA_MANAGER | ||||
| BLUEPRINT = Blueprint("task_manager", __name__, url_prefix=settings.URL_PREFIX) | |||||
| BLUEPRINT = Blueprint("task_manager", __name__, url_prefix=settings.URL_PATH_PREFIX+settings.API_PREFIX) | |||||
| @BLUEPRINT.route("/datavisual/single-job", methods=["GET"]) | @BLUEPRINT.route("/datavisual/single-job", methods=["GET"]) | ||||
| @@ -31,7 +31,7 @@ from mindinsight.datavisual.processors.graph_processor import GraphProcessor | |||||
| from mindinsight.datavisual.data_transform.data_manager import DATA_MANAGER | from mindinsight.datavisual.data_transform.data_manager import DATA_MANAGER | ||||
| BLUEPRINT = Blueprint("train_visual", __name__, url_prefix=settings.URL_PREFIX) | |||||
| BLUEPRINT = Blueprint("train_visual", __name__, url_prefix=settings.URL_PATH_PREFIX+settings.API_PREFIX) | |||||
| @BLUEPRINT.route("/datavisual/image/metadata", methods=["GET"]) | @BLUEPRINT.route("/datavisual/image/metadata", methods=["GET"]) | ||||
| @@ -25,7 +25,7 @@ from mindinsight.lineagemgr.api.model import general_filter_summary_lineage, gen | |||||
| from mindinsight.utils.exceptions import MindInsightException, ParamValueError | from mindinsight.utils.exceptions import MindInsightException, ParamValueError | ||||
| from mindinsight.lineagemgr.cache_item_updater import update_lineage_object | from mindinsight.lineagemgr.cache_item_updater import update_lineage_object | ||||
| BLUEPRINT = Blueprint("lineage", __name__, url_prefix=settings.URL_PREFIX.rstrip("/")) | |||||
| BLUEPRINT = Blueprint("lineage", __name__, url_prefix=settings.URL_PATH_PREFIX+settings.API_PREFIX) | |||||
| @BLUEPRINT.route("/lineagemgr/lineages", methods=["POST"]) | @BLUEPRINT.route("/lineagemgr/lineages", methods=["POST"]) | ||||
| @@ -41,7 +41,7 @@ from mindinsight.profiler.common.validator.validate_path import validate_and_nor | |||||
| from mindinsight.profiler.proposer.compose_proposer import ComposeProposal | from mindinsight.profiler.proposer.compose_proposer import ComposeProposal | ||||
| from mindinsight.utils.exceptions import ParamValueError | from mindinsight.utils.exceptions import ParamValueError | ||||
| BLUEPRINT = Blueprint("profile", __name__, url_prefix=settings.URL_PREFIX) | |||||
| BLUEPRINT = Blueprint("profile", __name__, url_prefix=settings.URL_PATH_PREFIX+settings.API_PREFIX) | |||||
| @BLUEPRINT.route("/profile/ops/search", methods=["POST"]) | @BLUEPRINT.route("/profile/ops/search", methods=["POST"]) | ||||
| @@ -252,7 +252,7 @@ def start(): | |||||
| else: | else: | ||||
| state_result = _check_server_start_stat(errorlog_abspath, log_size) | state_result = _check_server_start_stat(errorlog_abspath, log_size) | ||||
| # print gunicorn start state to stdout | # print gunicorn start state to stdout | ||||
| console.info('Web address: http://%s:%s', settings.HOST, settings.PORT) | |||||
| console.info('Web address: http://%s:%s%s', settings.HOST, settings.PORT, settings.URL_PATH_PREFIX) | |||||
| for line in state_result["prompt_message"]: | for line in state_result["prompt_message"]: | ||||
| console.info(line) | console.info(line) | ||||
| @@ -41,8 +41,8 @@ ENABLE_CORS = False | |||||
| SUPPORT_REQUEST_METHODS = {'POST', 'GET', 'PUT', 'DELETE'} | SUPPORT_REQUEST_METHODS = {'POST', 'GET', 'PUT', 'DELETE'} | ||||
| # url prefix should not end with slash, correct format is /v1/url | |||||
| URL_PREFIX = '/v1/mindinsight' | |||||
| # api prefix should not end with slash, correct format is /v1/url | |||||
| API_PREFIX = '/v1/mindinsight' | |||||
| #################################### | #################################### | ||||
| # Datavisual default settings. | # Datavisual default settings. | ||||
| @@ -24,6 +24,7 @@ WORKSPACE = os.path.join(os.environ['HOME'], 'mindinsight') | |||||
| # Web default settings. | # Web default settings. | ||||
| #################################### | #################################### | ||||
| PORT = 8080 | PORT = 8080 | ||||
| URL_PATH_PREFIX = '' | |||||
| #################################### | #################################### | ||||
| # Datavisual default settings. | # Datavisual default settings. | ||||
| @@ -16,6 +16,7 @@ | |||||
| import os | import os | ||||
| import sys | import sys | ||||
| import re | |||||
| import argparse | import argparse | ||||
| from importlib import import_module | from importlib import import_module | ||||
| @@ -118,6 +119,28 @@ class PortAction(argparse.Action): | |||||
| setattr(namespace, self.dest, port) | setattr(namespace, self.dest, port) | ||||
| class UrlPathPrefixAction(argparse.Action): | |||||
| """Url Path prefix action class definition.""" | |||||
| REGEX = r'^(\/[a-zA-Z0-9-\-\.]+)+$' | |||||
| def __call__(self, parser, namespace, values, option_string=None): | |||||
| """ | |||||
| Inherited __call__ method from argparse.Action. | |||||
| Args: | |||||
| parser (ArgumentParser): Passed-in argument parser. | |||||
| namespace (Namespace): Namespace object to hold arguments. | |||||
| values (object): Argument values with type depending on argument definition. | |||||
| option_string (str): Optional string for specific argument name. Default: None. | |||||
| """ | |||||
| prefix = values | |||||
| if not re.match(self.REGEX, prefix): | |||||
| parser.error(f'{option_string} value is invalid url path prefix') | |||||
| setattr(namespace, self.dest, prefix) | |||||
| class Command(BaseCommand): | class Command(BaseCommand): | ||||
| """ | """ | ||||
| Start mindinsight service. | Start mindinsight service. | ||||
| @@ -158,6 +181,14 @@ class Command(BaseCommand): | |||||
| Custom port ranging from %s to %s. Default value is %s. | Custom port ranging from %s to %s. Default value is %s. | ||||
| """ % (PortAction.MIN_PORT, PortAction.MAX_PORT, settings.PORT)) | """ % (PortAction.MIN_PORT, PortAction.MAX_PORT, settings.PORT)) | ||||
| parser.add_argument( | |||||
| '--url-path-prefix', | |||||
| type=str, | |||||
| action=UrlPathPrefixAction, | |||||
| help=""" | |||||
| Custom path prefix for web page address. Default value is ''. | |||||
| """) | |||||
| for hook in HookUtils.instance().hooks(): | for hook in HookUtils.instance().hooks(): | ||||
| hook.register_startup_arguments(parser) | hook.register_startup_arguments(parser) | ||||
| @@ -20,7 +20,7 @@ import axios from 'axios'; | |||||
| import Vue from 'vue'; | import Vue from 'vue'; | ||||
| export {default} from 'axios'; | export {default} from 'axios'; | ||||
| export const basePath = location.origin; | |||||
| export const basePath = location.origin + location.pathname; | |||||
| axios.defaults.timeout = 30000; | axios.defaults.timeout = 30000; | ||||
| axios.defaults.baseURL = basePath; | axios.defaults.baseURL = basePath; | ||||
| @@ -21,7 +21,7 @@ import pytest | |||||
| from flask import Response | from flask import Response | ||||
| from mindinsight.backend import datavisual | from mindinsight.backend import datavisual | ||||
| from mindinsight.datavisual import utils | |||||
| from mindinsight.datavisual.utils import tools | |||||
| @pytest.fixture | @pytest.fixture | ||||
| @@ -31,12 +31,10 @@ def client(): | |||||
| mock_data_manager.start_load_data = Mock() | mock_data_manager.start_load_data = Mock() | ||||
| datavisual.DATA_MANAGER = mock_data_manager | datavisual.DATA_MANAGER = mock_data_manager | ||||
| packages = ["mindinsight.backend.raw_dataset", | |||||
| "mindinsight.backend.train_dataset", | |||||
| "mindinsight.backend.data_visual"] | |||||
| packages = ["mindinsight.backend.data_visual"] | |||||
| mock_obj = Mock(return_value=packages) | mock_obj = Mock(return_value=packages) | ||||
| utils.find_app_package = mock_obj | |||||
| tools.find_app_package = mock_obj | |||||
| from mindinsight.backend.application import APP | from mindinsight.backend.application import APP | ||||
| APP.response_class = Response | APP.response_class = Response | ||||