diff --git a/deploy/ansible/roles/legion_core_chart/templates/legion-core-values.yaml.j2 b/deploy/ansible/roles/legion_core_chart/templates/legion-core-values.yaml.j2 index 638747b92..a7ccf5d87 100644 --- a/deploy/ansible/roles/legion_core_chart/templates/legion-core-values.yaml.j2 +++ b/deploy/ansible/roles/legion_core_chart/templates/legion-core-values.yaml.j2 @@ -5,6 +5,14 @@ localDomain: "cluster.local" addLocalDomain: true s3BucketName: "{{ legion_data_s3_bucket }}" +{% if dex.enabled == true %} +auth: + enabled: true + annotations: + nginx.ingress.kubernetes.io/auth-signin: https://auth.{{ cluster_name }}/oauth2/start?rd=https://$host$request_uri$is_args$args + nginx.ingress.kubernetes.io/auth-url: http://oauth2-proxy.kube-system.svc.cluster.local:4180/oauth2/auth +{% endif %} + package: version: "{{ legion_version }}" repository: "{{ pypi_repo }}" @@ -21,7 +29,7 @@ jenkins: enabled: true persistence: storageClass: {% if persistent_jenkins_volume %}"jenkins-volume"{% else %}""{% endif %} - + size: {{ jenkins_volume_size | default('20') }}Gi dags_volume_pvc: "{{ airflow_dags_pvc }}" diff --git a/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 b/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 index 84c7f1c8b..bd5afc7e8 100644 --- a/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 +++ b/deploy/ansible/roles/legion_enclave/templates/legion-values.yaml.j2 @@ -5,6 +5,14 @@ namespace: default log_level: {{ log_level }} +{% if dex.enabled == true %} +auth: + enabled: true + annotations: + nginx.ingress.kubernetes.io/auth-signin: https://auth.{{ cluster_name }}/oauth2/start?rd=https://$host$request_uri$is_args$args + nginx.ingress.kubernetes.io/auth-url: http://oauth2-proxy.kube-system.svc.cluster.local:4180/oauth2/auth +{% endif %} + package: version: "{{ legion_version }}" repository: "{{ pypi_repo }}" @@ -33,12 +41,6 @@ grafana: ingress: tls: enabled: {% if use_https == "yes" %}true{% else %}false{% endif %} -{% if dex.enabled == true %} - - annotations: - nginx.ingress.kubernetes.io/auth-signin: https://auth.{{ cluster_name }}/oauth2/start?rd=https://$host$request_uri$is_args$args - nginx.ingress.kubernetes.io/auth-url: http://oauth2-proxy.kube-system.svc.cluster.local:4180/oauth2/auth -{% endif %} edge: enabled: true diff --git a/deploy/helms/legion-core/templates/_helpers.tpl b/deploy/helms/legion-core/templates/_helpers.tpl index cf95a7eb2..abcb85a00 100644 --- a/deploy/helms/legion-core/templates/_helpers.tpl +++ b/deploy/helms/legion-core/templates/_helpers.tpl @@ -29,4 +29,15 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this {{- define "fullname" -}} {{- $name := default .Chart.Name .Values.nameOverride -}} {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} \ No newline at end of file +{{- end -}} + +{{/* +Create dex Ingress auth annotations +*/}} +{{- define "dex-ingress-annotations" }} + {{- if .Values.auth.enabled -}} + {{- range $key, $value := .Values.auth.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deploy/helms/legion-core/templates/jenkins/jenkins-server.yaml b/deploy/helms/legion-core/templates/jenkins/jenkins-server.yaml index 4fdfe6933..6f80c1614 100644 --- a/deploy/helms/legion-core/templates/jenkins/jenkins-server.yaml +++ b/deploy/helms/legion-core/templates/jenkins/jenkins-server.yaml @@ -74,12 +74,6 @@ spec: - name: LEGION_BASE_IMAGE_REPOSITORY value: "{{ .Values.package.baseImage.repository }}" # EDI credentials - - name: EDI_USER - value: "" - - name: EDI_PASSOWRD - value: "" - - name: EDI_TOKEN - value: "" # External resource (saving and loading model files) - name: EXTERNAL_RESOURCE_PROTOCOL value: "http" diff --git a/deploy/helms/legion-core/templates/metrics/grafana.yaml b/deploy/helms/legion-core/templates/metrics/grafana.yaml index 635053ed6..797cecc7b 100644 --- a/deploy/helms/legion-core/templates/metrics/grafana.yaml +++ b/deploy/helms/legion-core/templates/metrics/grafana.yaml @@ -82,6 +82,7 @@ metadata: {{- range $key, $value := .Values.grafana.ingress.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} + {{- template "dex-ingress-annotations" . }} labels: heritage: {{ .Release.Service | quote }} release: {{ .Release.Name | quote }} diff --git a/deploy/helms/legion-core/templates/nexus/nexus-ingress.yaml b/deploy/helms/legion-core/templates/nexus/nexus-ingress.yaml index e8d711673..cbdaa3e27 100644 --- a/deploy/helms/legion-core/templates/nexus/nexus-ingress.yaml +++ b/deploy/helms/legion-core/templates/nexus/nexus-ingress.yaml @@ -10,9 +10,10 @@ metadata: release: {{ .Release.Name | quote }} chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" annotations: - {{- range $key, $value := .Values.nexus.ingress.annotations }} - {{ $key }}: {{ $value | quote }} - {{- end }} + {{- range $key, $value := .Values.nexus.ingress.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- template "dex-ingress-annotations" . }} spec: rules: - host: "{{ .Values.nexus.ingress.domain.partial }}.{{ .Values.rootDomain }}" diff --git a/deploy/helms/legion-core/values.yaml b/deploy/helms/legion-core/values.yaml index 0885158b7..c2e0d9c73 100644 --- a/deploy/helms/legion-core/values.yaml +++ b/deploy/helms/legion-core/values.yaml @@ -4,6 +4,10 @@ enclaveDeploymentPrefix: "legion-" domainDelimiter: "." s3BucketName: "" +auth: + enabled: false + annotations: {} + secrets: nexus: admin: "jonny" @@ -16,7 +20,7 @@ jenkins: pullPolicy: "Always" rbac: true - + ingress: enabled: true annotations: {} diff --git a/deploy/helms/legion/templates/_helpers.tpl b/deploy/helms/legion/templates/_helpers.tpl new file mode 100644 index 000000000..3aa0241e3 --- /dev/null +++ b/deploy/helms/legion/templates/_helpers.tpl @@ -0,0 +1,12 @@ +{{/* vim: set filetype=mustache: */}} + +{{/* +Create dex Ingress auth annotations +*/}} +{{- define "dex-ingress-annotations" }} + {{- if .Values.auth.enabled -}} + {{- range $key, $value := .Values.auth.annotations }} + {{ $key }}: {{ $value | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deploy/helms/legion/templates/edi/edi-server.yaml b/deploy/helms/legion/templates/edi/edi-server.yaml index f1e778392..76a6a38e4 100644 --- a/deploy/helms/legion/templates/edi/edi-server.yaml +++ b/deploy/helms/legion/templates/edi/edi-server.yaml @@ -115,6 +115,7 @@ metadata: {{- range $key, $value := .Values.edi.ingress.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} + {{- template "dex-ingress-annotations" . }} labels: heritage: {{ .Release.Service | quote }} release: {{ .Release.Name | quote }} diff --git a/deploy/helms/legion/templates/metrics/grafana.yaml b/deploy/helms/legion/templates/metrics/grafana.yaml index 14052a3b5..5a82f7da5 100644 --- a/deploy/helms/legion/templates/metrics/grafana.yaml +++ b/deploy/helms/legion/templates/metrics/grafana.yaml @@ -84,6 +84,7 @@ metadata: {{- range $key, $value := .Values.grafana.ingress.annotations }} {{ $key }}: {{ $value | quote }} {{- end }} + {{- template "dex-ingress-annotations" . }} labels: heritage: {{ .Release.Service | quote }} release: {{ .Release.Name | quote }} diff --git a/deploy/helms/legion/values.yaml b/deploy/helms/legion/values.yaml index 3b0681ab1..a4ebf1417 100644 --- a/deploy/helms/legion/values.yaml +++ b/deploy/helms/legion/values.yaml @@ -8,15 +8,19 @@ clusterName: "" log_level: info +auth: + enabled: false + annotations: {} + feedback: replicas: 1 ingress: - annotations: {} - domain: - partial: feedback - tls: - enabled: true - autoSecretNameDeduction: true + annotations: {} + domain: + partial: feedback + tls: + enabled: true + autoSecretNameDeduction: true image: repository: "legion/k8s-fluentd" diff --git a/k8s/jenkins/legion-jenkins-plugin/src/main/resources/legion.groovy b/k8s/jenkins/legion-jenkins-plugin/src/main/resources/legion.groovy index ac97ca9af..31c5003ae 100644 --- a/k8s/jenkins/legion-jenkins-plugin/src/main/resources/legion.groovy +++ b/k8s/jenkins/legion-jenkins-plugin/src/main/resources/legion.groovy @@ -77,7 +77,6 @@ def pod(Map podParams=null, Closure body) { envToPass = [ "LEGION_PACKAGE_VERSION", "LEGION_PACKAGE_REPOSITORY", "LEGION_BASE_IMAGE_TAG", "LEGION_BASE_IMAGE_REPOSITORY", - "EDI_USER", "EDI_PASSOWRD", "EDI_TOKEN", "EXTERNAL_RESOURCE_PROTOCOL", "EXTERNAL_RESOURCE_HOST", "EXTERNAL_RESOURCE_USER", "EXTERNAL_RESOURCE_PASSWORD", "MODEL_IMAGES_REGISTRY", "MODEL_IMAGES_REGISTRY_HOST", "DOCKER_REGISTRY_USER", "DOCKER_REGISTRY_PASSWORD", "GRAPHITE_HOST", "STATSD_HOST", "STATSD_PORT", diff --git a/legion/bin/legionctl b/legion/bin/legionctl index 01eb700eb..e7bcbb1d5 100755 --- a/legion/bin/legionctl +++ b/legion/bin/legionctl @@ -20,8 +20,9 @@ import argparse import logging import legion.docker_bootup +from legion.edi.security import login, add_edi_arguments from legion.serving.pyserve import serve_model -from legion.external.edi import add_edi_arguments, add_arguments_for_wait_operation +from legion.external.edi import add_arguments_for_wait_operation from legion.edi.deploy import \ build_model, \ deploy_kubernetes, undeploy_kubernetes, scale_kubernetes, inspect_kubernetes, \ @@ -54,6 +55,11 @@ if __name__ == '__main__': action='store_true') subparsers = parser.add_subparsers() + # --------- LOGIN SECTION ----------- + login_parser = subparsers.add_parser('login', description='Save edi credentials to the config') + add_edi_arguments(login_parser, required=True) + login_parser.set_defaults(func=login) + # --------- LOCAL DOCKER SECTION ----------- build_parser = subparsers.add_parser('build', description='build model into new docker image (should be run ' 'in the docker container)') diff --git a/legion/docs/source/conf.py b/legion/docs/source/conf.py index af3e5aefc..91939c6f7 100644 --- a/legion/docs/source/conf.py +++ b/legion/docs/source/conf.py @@ -19,6 +19,9 @@ # import os import sys + +from legion.version import __version__ as legion_version + sys.path.insert(0, os.path.abspath('../..')) from recommonmark.parser import CommonMarkParser @@ -63,9 +66,9 @@ # built documents. # # The short X.Y version. -version = '1.0' +version = legion_version[:legion_version.rfind('.')] # The full version, including alpha/beta/rc tags. -release = '1.0' +release = legion_version # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/legion/docs/source/index.rst b/legion/docs/source/index.rst index 66fcd8210..7bba9c639 100644 --- a/legion/docs/source/index.rst +++ b/legion/docs/source/index.rst @@ -9,6 +9,7 @@ Welcome to legion's documentation! usage system_architecture model_rest_api + legionctl .. toctree:: diff --git a/legion/docs/source/legionctl.md b/legion/docs/source/legionctl.md new file mode 100644 index 000000000..9a484b19b --- /dev/null +++ b/legion/docs/source/legionctl.md @@ -0,0 +1,35 @@ +# Legionctl + +`legionctl` is a command line tool that allows you to manage an edi service. + +## Basic + +To read legionctl help you should use the following command: + +```bash +legionctl --help +``` + +for a specific command, for example, inspect: + +```bash +legionctl inspect --help +``` + +## Security + +You should open edi url in a browser to get a token. + +Then you can use it in a legionctl command, for example: + +```bash +legionctl inspect --edi --token +``` + +Another option save the token in config file. Further you can use legionctl commands without `edi` and +`token` parameters. For example: + +```bash +legionctl login --edi --token +legionctl inspect +``` \ No newline at end of file diff --git a/legion/docs/source/testing.md b/legion/docs/source/testing.md index 860819272..7e39aa599 100644 --- a/legion/docs/source/testing.md +++ b/legion/docs/source/testing.md @@ -72,12 +72,12 @@ dex: - email: tests-user@legion.com password: ~ ``` -* Export the following environment variables: +* Go to the `tests\robot` directory. Export the following environment variables: ```bash export PROFILE="legion-test.epm.kharlamov.biz" export LEGION_VERSION="0.10.0-20181213084714.1329.6ba06cc" export PATH_TO_COOKIES="credentials.secret" -export CLUSTER_NAME="legion-test.epm.kharlamov.biz" +export CLUSTER_NAME="${PROFILE}" export CREDENTIAL_SECRETS=".secrets.yaml" export ROBOT_OPTIONS="-v PATH_TO_PROFILES_DIR:../../deploy/profiles" ``` diff --git a/legion/legion/config.py b/legion/legion/config.py index 43a4dff3b..4a4dd654e 100644 --- a/legion/legion/config.py +++ b/legion/legion/config.py @@ -50,11 +50,11 @@ GRAFANA_USER = 'GRAFANA_USER', 'admin' GRAFANA_PASSWORD = 'GRAFANA_PASSWORD', 'admin' -EDI_URL = 'EDI_URL', 'http://localhost:5001/' -EDI_USER = 'EDI_USER', '' -EDI_PASSWORD = 'EDI_PASSWORD', '' +EDI_URL = 'EDI_URL', '' EDI_TOKEN = 'EDI_TOKEN', '' +LEGION_CONFIG = 'LEGION_CONFIG', '' + LOCAL_DEFAULT_RESOURCE_PREFIX = 'LOCAL_DEFAULT_RESOURCE_PREFIX', '' EXTERNAL_RESOURCE_USE_BY_DEFAULT = 'EXTERNAL_RESOURCE_USE_BY_DEFAULT', 'true' EXTERNAL_RESOURCE_PROTOCOL = 'EXTERNAL_RESOURCE_PROTOCOL', 'https' diff --git a/legion/legion/edi/security.py b/legion/legion/edi/security.py new file mode 100644 index 000000000..50bd9007e --- /dev/null +++ b/legion/legion/edi/security.py @@ -0,0 +1,136 @@ +# +# Copyright 2018 EPAM Systems +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Security logic for legion +""" + +import configparser +import logging +import os +from pathlib import Path + +from legion import config +from legion.external import edi + +_DEFAULT_CONFIG_PATH = Path.home().joinpath('.legion/config') +LOG = logging.getLogger(__name__) + + +def add_edi_arguments(parser, required=False): + """ + Add EDI arguments parser + + :param parser: add arguments to it + :type parser: argparse.ArgumentParser + :param required: (Optional) mark edi arguments as required if it equals True + :type required: bool + :return: None + """ + parser.add_argument('--edi', + type=str, help='EDI server host', required=required) + parser.add_argument('--token', + type=str, help='EDI server token', required=required) + + +def _get_config_location(): + """ + Return the config path. + LEGION_CONFIG can override path value + + :return: Path -- config path + """ + config_path_from_env = os.getenv(*config.LEGION_CONFIG) + + return Path(config_path_from_env) if config_path_from_env else _DEFAULT_CONFIG_PATH + + +def _check_credentials(args): + """ + Make a request to the server to make sure that credentials are correct + + :param args: command arguments with .namespace + :type args: argparse.Namespace + :return None + """ + # url and token must presents in args + edi_clint = edi.build_client(args) + + edi_clint.info() + + +def _save_credentials(edi, token): + """ + Save credentials to the config file. + If file or dir doesn't exist then it will be created. + While we store only security parameters, func can override existed parameters + + :param edi: edi url + :type edi: str + :param token: dex token + :type token: str + :return None + """ + config_path = _get_config_location() + + config_path.parent.mkdir(mode=0o775, parents=True, exist_ok=True) + config_path.touch(mode=0o600, exist_ok=True) + + config = configparser.ConfigParser() + config['security'] = { + 'host': edi, + 'token': token + } + + with config_path.open("w") as config_file: + config.write(config_file) + + LOG.debug('Save config {} to the file {}'.format(config, config_path)) + + +def login(args): + """ + Check that credentials is correct and save to the config + + :param args: command arguments + :type args: argparse.Namespace + :return: None + """ + _check_credentials(args) + _save_credentials(args.edi, args.token) + + LOG.info('Success! Credentials were saved.') + + +def get_security_params_from_config(): + """ + Return dict with edi url and token from config. + If an exception occurs during parsing of config or config file doesn't exist then + return empty dict + + :return: dict[str, str] -- config + """ + config_path = _get_config_location() + + if config_path.exists(): + try: + config = configparser.ConfigParser() + config.read(str(config_path)) + + return dict(config['security']) + except Exception as e: + LOG.debug('Exception during parsing of legion config {}'.format(e), exc_info=True) + + return {} diff --git a/legion/legion/edi/server.py b/legion/legion/edi/server.py index b5203877f..e57f9ae5d 100644 --- a/legion/legion/edi/server.py +++ b/legion/legion/edi/server.py @@ -24,16 +24,22 @@ import legion.external.grafana import legion.http import legion.model -from flask import Flask, Blueprint +from flask import Flask, Blueprint, render_template, request from flask import current_app as app +import os import jwt from datetime import datetime, timedelta LOGGER = logging.getLogger(__name__) blueprint = Blueprint('apiserver', __name__) +TEMPLATES_FOLDER = os.path.abspath(os.path.join( + os.path.dirname(__file__), os.pardir, 'templates', 'edi') +) +AUTH_COOKIE_NAME = '_oauth2_proxy' EDI_VERSION = '1.0' EDI_ROOT = '/' +EDI_API_ROOT = '/api/' EDI_DEPLOY = '/api/{version}/deploy' EDI_UNDEPLOY = '/api/{version}/undeploy' EDI_SCALE = '/api/{version}/scale' @@ -91,9 +97,21 @@ def return_model_deployments(model_deployments): @blueprint.route(build_blueprint_url(EDI_ROOT), methods=['GET']) +def root(): + """ + Root endpoint for authorisation + + :return: dict -- root information + """ + token = request.cookies.get(AUTH_COOKIE_NAME, 'INVALID COOKIE') + return render_template('index.html', + token=token) + + +@blueprint.route(build_blueprint_url(EDI_API_ROOT), methods=['GET']) @legion.http.provide_json_response @legion.http.authenticate(authenticate) -def root(): +def api_root(): """ Root API endpoint @@ -190,7 +208,7 @@ def undeploy(model, version=None, grace_period=0, ignore_not_found=False): :param model: model id - :type model: str + :type model: strset jinja folder :param version: (Optional) specific model version :type version: str or None :param grace_period: grace period for removing @@ -351,13 +369,16 @@ def generate_token(model_id, model_version): def create_application(): """ - Create Flask application and register blueprints + Create Flask application, register blueprints and templates folder :return: :py:class:`Flask.app` -- Flask application instance """ - application = Flask(__name__, static_url_path='') + application = Flask(__name__, + static_url_path='', + template_folder=TEMPLATES_FOLDER) application.register_blueprint(blueprint) + application.create_jinja_environment() return application diff --git a/legion/legion/external/edi.py b/legion/legion/external/edi.py index 218ac3fca..16e9bf560 100644 --- a/legion/legion/external/edi.py +++ b/legion/legion/external/edi.py @@ -20,12 +20,14 @@ import json import logging import os +from urllib.parse import urlparse import legion.k8s import legion.edi.server import legion.config import requests import requests.exceptions +from legion.edi import security LOGGER = logging.getLogger(__name__) @@ -51,22 +53,23 @@ def __init__(self, base, token=None, retries=3): self._version = legion.edi.server.EDI_VERSION self._retries = retries - def _request(self, action, url, data=None, headers=None): + def _request(self, action, url, data=None, headers=None, cookies=None): """ Make HTTP request - :param action: request action, e.g. get / post / delete :type action: str :param url: target URL :type url: str :param data: (Optional) data to be placed in body of request - :param data: dict[str, str] or None + :type data: dict[str, str] or None :param headers: (Optional) additional HTTP headers - :param headers: dict[str, str] or None + :type headers: dict[str, str] or None + :param cookies: (Optional) HTTP cookies + :type cookies: dict[str, str] or None :return: :py:class:`requests.Response` -- response """ request_data = {'params' if action == 'GET' else 'data': data} - return requests.request(action.lower(), url, headers=headers, **request_data) + return requests.request(action.lower(), url, headers=headers, cookies=cookies, **request_data) def _query(self, url_template, payload=None, action='GET'): """ @@ -82,15 +85,15 @@ def _query(self, url_template, payload=None, action='GET'): """ sub_url = url_template.format(version=self._version) target_url = self._base.strip('/') + sub_url + cookies = {'_oauth2_proxy': self._token} if self._token else {} left_retries = self._retries if self._retries > 0 else 1 raised_exception = None - while left_retries > 0: try: LOGGER.debug('Requesting {}'.format(target_url)) - # TODO: Add sending token (LEGION #313) - response = self._request(action, target_url, payload) + + response = self._request(action, target_url, payload, cookies=cookies) except requests.exceptions.ConnectionError as exception: LOGGER.error('Failed to connect to {}: {}. Retrying'.format(self._base, exception)) raised_exception = exception @@ -104,6 +107,18 @@ def _query(self, url_template, payload=None, action='GET'): self._base, raised_exception )) + # We assume if there were redirects then credentials are out of date + if response.history: + LOGGER.debug('Status code: "{}", Response: "{}"'.format(response.status_code, response.text)) + + parse_result = urlparse(target_url) + + raise Exception( + 'Credentials are not correct. You should open {}://{} url in a browser to get fresh token'.format( + parse_result.scheme, parse_result.netloc + ) + ) + try: answer = json.loads(response.text) LOGGER.debug('Got answer: {!r} with code {} for URL {!r}' @@ -245,9 +260,7 @@ def get_token(self, model_id, model_version): :type model_version: str :return: str -- return API Token """ - payload = {} - payload['model_id'] = model_id - payload['model_version'] = model_version + payload = {'model_id': model_id, 'model_version': model_version} response = self._query(legion.edi.server.EDI_GENERATE_TOKEN, action='POST', payload=payload) if response and 'token' in response: @@ -264,24 +277,6 @@ def __repr__(self): __str__ = __repr__ -def add_edi_arguments(parser): - """ - Add EDI arguments parser - - :param parser: add arguments to it - :type parser: argparse.ArgumentParser - :return: None - """ - parser.add_argument('--edi', - type=str, help='EDI server host') - parser.add_argument('--user', - type=str, help='EDI server user') - parser.add_argument('--password', - type=str, help='EDI server password') - parser.add_argument('--token', - type=str, help='EDI server token') - - def add_arguments_for_wait_operation(parser): """ Add arguments of wait operation in the parser @@ -311,17 +306,18 @@ def build_client(args=None): if args.edi: host = args.edi - if args.user: - user = args.user - - if args.password: - password = args.password - if args.token: token = args.token - if not host: - host = os.environ.get(*legion.config.EDI_URL) + if not host or not token: + host = host or os.environ.get(*legion.config.EDI_URL) + token = token or os.environ.get(*legion.config.EDI_TOKEN) + + if not host and not token: + config = security.get_security_params_from_config() + + host = config.get('host') + token = config.get('token') if not host: try: @@ -329,14 +325,5 @@ def build_client(args=None): except Exception: LOGGER.warning('Cannot get EDI URL from K8S API') - if not user or not password: - user = os.environ.get(*legion.config.EDI_USER) - password = os.environ.get(*legion.config.EDI_PASSWORD) - - # TODO: Password and user now are ignored. Add auth mechanism (LEGION #313) - - if not token: - token = os.environ.get(*legion.config.EDI_TOKEN) - client = EdiClient(host, token) return client diff --git a/legion/legion/templates/edi/index.html b/legion/legion/templates/edi/index.html new file mode 100644 index 000000000..09f70fc8b --- /dev/null +++ b/legion/legion/templates/edi/index.html @@ -0,0 +1,72 @@ + + + + + + + + Legion EDI web console + + + +
+

Legion EDI

+

Your personal authorisation token is:

+
+
{{ token }}
+
+
+ + + + + \ No newline at end of file diff --git a/legion/legion/utils.py b/legion/legion/utils.py index 84ce97a1e..d019e9c91 100644 --- a/legion/legion/utils.py +++ b/legion/legion/utils.py @@ -49,6 +49,7 @@ def render_template(template_name, values=None): """ Render template with parameters + :param template_name: name of template without path (all templates should be placed in legion.templates directory) :param values: dict template variables or None :return: str rendered template diff --git a/legion/tests/legion_test_utils.py b/legion/tests/legion_test_utils.py index a097c3ffe..be930db06 100644 --- a/legion/tests/legion_test_utils.py +++ b/legion/tests/legion_test_utils.py @@ -693,11 +693,18 @@ def build_requests_mock_function(test_client): :type test_client: :py:class:`flask.test.FlaskClient` :return: Callable[[str, str, dict[str, str], dict[str, str]], requests.Response] """ - def func(action, url, data=None, headers=None): + + def func(action, url, data=None, headers=None, cookies=None): request_data = {'query_string' if action == 'GET' else 'data': data} + server_name = "localhost" + + for k, v in cookies.items(): + test_client.set_cookie(server_name, k, v) + test_response = test_client.open(url, method=action, headers=headers, **request_data) return build_requests_reponse_from_flask_client_response(test_response, url) + return func diff --git a/legion/tests/test_legionctl.py b/legion/tests/test_legionctl.py index 510d4f26d..35942d616 100644 --- a/legion/tests/test_legionctl.py +++ b/legion/tests/test_legionctl.py @@ -1,9 +1,15 @@ import argparse +import configparser import logging +import os import unittest +from pathlib import Path +from unittest import mock +from unittest.mock import patch import urllib3 -from build.lib.legion.edi.deploy import build_model +from legion.edi import security +from legion.edi.deploy import build_model class TestBuildModel(unittest.TestCase): @@ -25,5 +31,91 @@ def test_download_model_file_by_wrong_url(self): build_model(build_model_args) +TEST_DEFAULT_CONFIG_PATH = Path.cwd().joinpath('.legion/config') + + +@patch.object(security, '_DEFAULT_CONFIG_PATH', TEST_DEFAULT_CONFIG_PATH) +class TestLogin(unittest.TestCase): + + def setUp(self): + logging.basicConfig(level=logging.DEBUG) + + self._remove_config() + + def tearDown(self): + self._remove_config() + + def _get_config(self): + config = configparser.ConfigParser() + config.read(TEST_DEFAULT_CONFIG_PATH) + + return dict(config['security']) + + def _remove_config(self): + if TEST_DEFAULT_CONFIG_PATH.parent.exists(): + if TEST_DEFAULT_CONFIG_PATH.exists(): + TEST_DEFAULT_CONFIG_PATH.unlink() + + TEST_DEFAULT_CONFIG_PATH.parent.rmdir() + + def test_default_config_path(self): + self.assertEqual(security._get_config_location(), TEST_DEFAULT_CONFIG_PATH) + + def test_override_default_config_path(self): + new_config_path = Path('some/path') + + with patch.dict(os.environ, {'LEGION_CONFIG': str(new_config_path)}): + self.assertEqual(security._get_config_location(), new_config_path) + + @patch.object(security, '_check_credentials', mock.MagicMock()) + def test_config_creation(self): + build_model_args = argparse.Namespace(token='test-token', edi='http://test.edi/url') + + security.login(build_model_args) + + self.assertTrue(TEST_DEFAULT_CONFIG_PATH.exists(), 'Config file was not created') + + @patch.object(security, '_check_credentials', mock.MagicMock()) + def test_config_options(self): + token = 'test-token' + edi = 'http://test.edi/url' + build_model_args = argparse.Namespace(token=token, edi=edi) + + security.login(build_model_args) + + self.assertDictEqual(self._get_config(), {'host': edi, 'token': token}, + 'Options does not equal') + + @patch.object(security, '_check_credentials', mock.MagicMock()) + def test_get_security_options(self): + token = 'test-token' + edi = 'http://test.edi/url' + build_model_args = argparse.Namespace(token=token, edi=edi) + + security.login(build_model_args) + security_options = security.get_security_params_from_config() + + self.assertDictEqual(security_options, {'host': edi, 'token': token}, + 'Options does not equal') + + @patch.object(security, '_check_credentials', mock.MagicMock()) + def test_get_security_options_config_not_exist(self): + security_options = security.get_security_params_from_config() + + self.assertDictEqual(security_options, {}, 'Options does not equal') + + @patch.object(security, '_check_credentials', mock.MagicMock()) + def test_get_security_options_broken_config(self): + TEST_DEFAULT_CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) + TEST_DEFAULT_CONFIG_PATH.touch(exist_ok=True) + + with TEST_DEFAULT_CONFIG_PATH.open('w') as f: + f.write('some garbage') + + security_options = security.get_security_params_from_config() + + self.assertDictEqual(security_options, {}, 'Options does not equal') + + if __name__ == '__main__': unittest.main() diff --git a/legion_test/legion_test/profiler_loader.py b/legion_test/legion_test/profiler_loader.py index fc3d7355d..d36a34cb4 100644 --- a/legion_test/legion_test/profiler_loader.py +++ b/legion_test/legion_test/profiler_loader.py @@ -20,6 +20,7 @@ import os import yaml +from legion_test.robot import dex_client from legion_test.robot.dex_client import init_session_id, init_session_id_from_data PROFILE_ENVIRON_KEY = 'PROFILE' @@ -112,6 +113,9 @@ def get_variables(arg=None): init_session_id_from_data(cookies_data) variables['STATIC_USER_EMAIL'] = static_user['email'] variables['STATIC_USER_PASS'] = static_user['password'] + + variables['DEX_TOKEN'] = dex_client.get_token() + variables['DEX_COOKIES'] = dex_client.get_session_cookies() else: variables['STATIC_USER_EMAIL'] = '' variables['STATIC_USER_PASS'] = '' diff --git a/legion_test/legion_test/robot/dex_client.py b/legion_test/legion_test/robot/dex_client.py index 0e2821aee..451f088c0 100644 --- a/legion_test/legion_test/robot/dex_client.py +++ b/legion_test/legion_test/robot/dex_client.py @@ -67,7 +67,7 @@ def init_session_id(login: str, password: str, cluster_host: str) -> None: if response.status_code != 200: raise IOError('Authentication endpoint is unavailable, got {} http code' .format(response.status_code)) - if response.url.startswith(AUTHENTICATION_HOSTNAME.format(cluster_host)): # if auth form is opened + if response.url.startswith(AUTHENTICATION_HOSTNAME.format(cluster_host)): # if auth form is opened match = re.search(REQUEST_ID_REGEXP, response.text) if match: request_id = match.group(1) @@ -105,6 +105,15 @@ def get_session_cookies(): return _session_cookies +def get_token(): + """ + Get token from session cookies that can be used inside Request. + + :return: str -- jwt + """ + return _session_cookies['_oauth2_proxy'] + + def get_jenkins_credentials(): """ Get credentials (username and API Token) for Jenkins API, if they are found. diff --git a/legion_test/legion_test/robot/utils.py b/legion_test/legion_test/robot/utils.py index a60f92fd6..ca1e2288a 100644 --- a/legion_test/legion_test/robot/utils.py +++ b/legion_test/legion_test/robot/utils.py @@ -177,7 +177,7 @@ def check_valid_http_response(url, token=None): raise Exception('Unexpected case happen!') @staticmethod - def execute_post_request(url, data=None, json=None): + def execute_post_request(url, data=None, json=None, cookies=None): """ Execute post request @@ -187,14 +187,12 @@ def execute_post_request(url, data=None, json=None): :type data: dict :param json: json data to send in request :type json: dict + :param cookies: cookies to send in request + :type cookies: dict :return: str -- response text """ - if data: - response = requests.post(url, data=data) - elif json: - response = requests.post(url, json=json) - else: - response = requests.post(url) + response = requests.post(url, json=json, data=data, cookies=cookies) + return {"text": response.text, "code": response.status_code} @staticmethod diff --git a/tests/python/test_k8s_introspection.py b/tests/python/test_k8s_introspection.py index f21d29426..dcdde43b2 100644 --- a/tests/python/test_k8s_introspection.py +++ b/tests/python/test_k8s_introspection.py @@ -116,7 +116,7 @@ def test_check_edi_client(self): url = enclave.edi_service.public_url self.assertIsNotNone(url) - client = legion.external.EdiClient(url) + client = legion.external.EdiClient(url, token=VARIABLES['DEX_TOKEN']) info = client.info() self.assertIsInstance(info, dict) diff --git a/tests/robot/resources/browser.robot b/tests/robot/resources/browser.robot index 18792815c..59a373487 100644 --- a/tests/robot/resources/browser.robot +++ b/tests/robot/resources/browser.robot @@ -8,16 +8,32 @@ ${BROWSER} Firefox ${SELENIUM_TIMEOUT} 60 seconds #time to explicite wait for keywords run ${SELENIUM_IMPLICIT_WAIT} 5 seconds #time to wait for a DOM load on page ${NEXUS_COMPONENTS_TABLE} //table[contains(.,'docker')] +${NEXUS_HOST} ${HOST_PROTOCOL}://nexus.${HOST_BASE_DOMAIN} + + # LOCATORS + ## DEX AUTH PAGE + ${DEX_AUTH_dex_email_login_button} //button[contains(@class, 'dex-btn theme-btn-provider')] + ${DEX_AUTH_login_input} //*[@id="login"] + ${DEX_AUTH_password_input} //*[@id="password"] + ${DEX_AUTH_login_button} //*[@id="submit-login"] *** Keywords *** -Open Nexus - [Arguments] ${suburl} - Open Browser ${HOST_PROTOCOL}://nexus.${HOST_BASE_DOMAIN}${suburl} ${BROWSER} +Start browser + [Arguments] ${url} + Open Browser ${url} ${BROWSER} Set Selenium Timeout ${SELENIUM_TIMEOUT} Set Selenium Implicit Wait ${SELENIUM_IMPLICIT_WAIT} Maximize Browser Window +Login with dex + Wait Until Element Is Visible xpath: ${DEX_AUTH_dex_email_login_button} + Click Button xpath: ${DEX_AUTH_dex_email_login_button} + Wait Until Element Is Visible xpath: ${DEX_AUTH_login_input} + Input Text xpath: ${DEX_AUTH_login_input} ${STATIC_USER_EMAIL} + Input Text xpath: ${DEX_AUTH_password_input} ${STATIC_USER_PASS} + Click Button xpath: ${DEX_AUTH_login_button} + Wait Nexus componens in menu Wait Until Element Is Visible xpath: //span[contains(@class, 'x-tree-node-text') and contains(text(), "Components")] diff --git a/tests/robot/resources/keywords.robot b/tests/robot/resources/keywords.robot index ac868fa83..3eaac01ec 100644 --- a/tests/robot/resources/keywords.robot +++ b/tests/robot/resources/keywords.robot @@ -39,7 +39,7 @@ Shell Run EDI inspect enclave and check result [Documentation] run legionctl 'inspect command', logs result and return dict with return code and output [Arguments] ${enclave} ${expected_rc} ${expected_output} - ${result}= Run Process without PIPE legionctl --verbose inspect --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose inspect --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} Should Be Equal As Integers ${result.rc} ${expected_rc} @@ -48,7 +48,7 @@ Run EDI inspect enclave and check result Run EDI inspect [Documentation] run legionctl 'inspect command', logs result and return dict with return code and output [Arguments] ${enclave} - ${result}= Run Process without PIPE legionctl --verbose inspect --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose inspect --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -56,7 +56,7 @@ Run EDI inspect Run EDI inspect by model id [Documentation] run legionctl 'inspect command', logs result and return dict with return code and output [Arguments] ${enclave} ${model_id} - ${result}= Run Process without PIPE legionctl --verbose inspect --model-id ${model_id} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose inspect --model-id ${model_id} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -64,7 +64,7 @@ Run EDI inspect by model id Run EDI inspect by model version [Documentation] run legionctl 'inspect command', logs result and return dict with return code and output [Arguments] ${enclave} ${model_ver} - ${result}= Run Process without PIPE legionctl --verbose inspect --model-version ${model_ver} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose inspect --model-version ${model_ver} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -72,7 +72,7 @@ Run EDI inspect by model version Run EDI inspect by model id and model version [Documentation] run legionctl 'inspect command', logs result and return dict with return code and output [Arguments] ${enclave} ${model_id} ${model_ver} - ${result}= Run Process without PIPE legionctl --verbose inspect --model-id ${model_id} --model-version ${model_ver} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose inspect --model-id ${model_id} --model-version ${model_ver} --format column --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -97,7 +97,7 @@ Run EDI inspect with parse by model id Run EDI deploy [Documentation] run legionctl 'deploy command', logs result and return dict with return code and output(for exceptions) [Arguments] ${enclave} ${image} - ${result}= Run Process without PIPE legionctl --verbose deploy ${image} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose deploy ${image} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -105,13 +105,14 @@ Run EDI deploy Run EDI deploy with scale [Documentation] run legionctl 'deploy command with scale option', logs result and return dict with return code and output(for exceptions) [Arguments] ${enclave} ${image} ${scale_count} - ${result}= Run Process without PIPE legionctl --verbose deploy ${image} --scale ${scale_count} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose deploy ${image} --scale ${scale_count} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} Run EDI deploy and check model started [Arguments] ${enclave} ${image} ${model_id} ${model_ver} + Log ${DEX_TOKEN} ${edi_state}= Run EDI deploy ${enclave} ${image} Should Be Equal As Integers ${edi_state.rc} 0 ${response}= Check model started ${enclave} ${model_id} ${model_ver} @@ -138,7 +139,7 @@ Run EDI undeploy model without version and check Run EDI undeploy with version [Arguments] ${enclave} ${model_id} ${model_version} - ${result}= Run Process without PIPE legionctl --verbose undeploy ${model_id} --model-version ${model_version} --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose undeploy ${model_id} --model-version ${model_version} --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -146,7 +147,7 @@ Run EDI undeploy with version Run EDI undeploy without version [Documentation] run legionctl 'undeploy command', logs result and return dict with return code and output(for exceptions) [Arguments] ${enclave} ${model_id} - ${result}= Run Process without PIPE legionctl --verbose undeploy ${model_id} --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose undeploy ${model_id} --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -155,7 +156,7 @@ Run EDI undeploy without version Run EDI scale [Documentation] run legionctl 'scale command', logs result and return dict with return code and output(for exceptions) [Arguments] ${enclave} ${model_id} ${new_scale} - ${result}= Run Process without PIPE legionctl --verbose scale ${model_id} ${new_scale} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose scale ${model_id} ${new_scale} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -163,7 +164,7 @@ Run EDI scale Run EDI scale with version [Documentation] run legionctl 'scale command', logs result and return dict with return code and output(for exceptions) [Arguments] ${enclave} ${model_id} ${new_scale} ${model_ver} - ${result}= Run Process without PIPE legionctl --verbose scale ${model_id} ${new_scale} --model-version ${model_ver} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} shell=True + ${result}= Run Process without PIPE legionctl --verbose scale ${model_id} ${new_scale} --model-version ${model_ver} --edi ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" shell=True Log stdout = ${result.stdout} Log stderr = ${result.stderr} [Return] ${result} @@ -178,7 +179,7 @@ Get token from EDI [Documentation] get token from EDI for the EDGE session [Arguments] ${enclave} ${model_id} ${model_version} &{data} = Create Dictionary model_id=${model_id} model_version=${model_version} - &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} + &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${enclave}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} cookies=${DEX_COOKIES} Log ${resp["text"]} Should not be empty ${resp} &{token} = Evaluate json.loads('''${resp["text"]}''') json @@ -343,7 +344,7 @@ Test model pipeline result Dashboard should exists ${model_id} Sleep 15s Metric should be presented ${model_id} ${model_version} - ${edi_state}= Run legionctl inspect --model-id ${model_id} --format column --edi ${HOST_PROTOCOL}://edi.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${edi_state}= Run legionctl inspect --model-id ${model_id} --format column --edi ${HOST_PROTOCOL}://edi.${HOST_BASE_DOMAIN} Log State of ${model_id} is ${edi_state} [Return] ${model_id} ${model_version} diff --git a/tests/robot/tests/1_common/1.0_check_components_auth.robot b/tests/robot/tests/1_common/1.0_check_components_auth.robot index 753de72aa..5ede04f2c 100644 --- a/tests/robot/tests/1_common/1.0_check_components_auth.robot +++ b/tests/robot/tests/1_common/1.0_check_components_auth.robot @@ -19,16 +19,15 @@ Check if Jenkins domain has been secured [Template] Check if component domain has been secured component=jenkins enclave=${EMPTY} -# TODO uncomment when would be secured -#Check if Nexus domain has been secured -# [Tags] core security auth -# [Template] Check if component domain has been secured -# component=nexus enclave=${EMPTY} -# -#Check if Grafana domain has been secured -# [Tags] core security auth -# [Template] Check if component domain has been secured -# component=grafana enclave=${EMPTY} +Check if Nexus domain has been secured + [Tags] core security auth + [Template] Check if component domain has been secured + component=nexus enclave=${EMPTY} + +Check if Grafana domain has been secured + [Tags] core security auth + [Template] Check if component domain has been secured + component=grafana enclave=${EMPTY} Check if Grafana enclave domain has been secured [Tags] core security auth apps @@ -55,16 +54,15 @@ Check if Jenkins domain does not auth with invalid creds [Template] Secured component domain should not be accessible by invalid credentials component=jenkins enclave=${EMPTY} -# TODO uncomment when would be secured -#Check if Nexus domain does not auth with invalid creds -# [Tags] core security auth apps -# [Template] Secured component domain should not be accessible by invalid credentials -# component=nexus enclave=${EMPTY} -# -#Check if Grafana domain does not auth with invalid creds -# [Tags] core security auth apps -# [Template] Secured component domain should not be accessible by invalid credentials -# component=grafana enclave=${EMPTY} +Check if Nexus domain does not auth with invalid creds + [Tags] core security auth apps + [Template] Secured component domain should not be accessible by invalid credentials + component=nexus enclave=${EMPTY} + +Check if Grafana domain does not auth with invalid creds + [Tags] core security auth apps + [Template] Secured component domain should not be accessible by invalid credentials + component=grafana enclave=${EMPTY} Check if Grafana enclave does not auth with invalid creds [Tags] core security auth apps @@ -106,16 +104,15 @@ Check if K8S dashboard domain can auth with valid creds [Template] Secured component domain should be accessible by valid credentials component=Dashboard enclave=${EMPTY} -# TODO uncomment when would be secured -#Check if Nexus domain can auth with valid creds -# [Tags] core security auth apps -# [Template] Secured component domain should be accessible by valid credentials -# component=nexus enclave=${EMPTY} -# -#Check if Grafana domain can auth with valid creds -# [Tags] core security auth apps -# [Template] Secured component domain should be accessible by valid credentials -# component=grafana enclave=${EMPTY} +Check if Nexus domain can auth with valid creds + [Tags] core security auth apps + [Template] Secured component domain should be accessible by valid credentials + component=nexus enclave=${EMPTY} + +Check if Grafana domain can auth with valid creds + [Tags] core security auth apps + [Template] Secured component domain should be accessible by valid credentials + component=grafana enclave=${EMPTY} Check if EDGE has been secured by token [Tags] core security auth apps diff --git a/tests/robot/tests/1_common/1.1_check_clusterwide.robot b/tests/robot/tests/1_common/1.1_check_clusterwide.robot index af480484f..f25c0bb63 100644 --- a/tests/robot/tests/1_common/1.1_check_clusterwide.robot +++ b/tests/robot/tests/1_common/1.1_check_clusterwide.robot @@ -38,14 +38,18 @@ Checking if all replica sets, stateful sets, replication controllers are up and Check Nexus availability [Documentation] Check Nexus UI availability [Tags] nexus ui apps - Open Nexus / + Start browser ${NEXUS_HOST} + Login with dex + Go To ${NEXUS_HOST}/ Wait Nexus componens in menu Check Nexus Components available [Documentation] Check that Nexus storages (components) are ready [Tags] nexus ui apps + Start browser ${NEXUS_HOST} + Login with dex + Go To ${NEXUS_HOST}/#browse/browse/components @{expectedComponentsNames} = Create List docker-hosted raw - Open Nexus /#browse/browse/components Check components presence in Nexus table ${expectedComponentsNames} Check enclave Grafana availability diff --git a/tests/robot/tests/3_edi_one_model/3.0_check_edi_one_model.robot b/tests/robot/tests/3_edi_one_model/3.0_check_edi_one_model.robot index 36fc24301..7500fca6d 100644 --- a/tests/robot/tests/3_edi_one_model/3.0_check_edi_one_model.robot +++ b/tests/robot/tests/3_edi_one_model/3.0_check_edi_one_model.robot @@ -25,7 +25,7 @@ Get token from EDI with valid parameters [Setup] NONE [Tags] edi cli enclave edi_token &{data} = Create Dictionary model_id=${TEST_EDI_MODEL_ID} model_version=${TEST_MODEL_3_VERSION} - &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} + &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} cookies=${DEX_COOKIES} Log ${resp} Should not be empty ${resp} Should be equal as integers ${resp["code"]} 200 @@ -39,7 +39,7 @@ Get token from EDI without version parameter [Setup] NONE [Tags] edi cli enclave edi_token &{data} = Create Dictionary model_id=${TEST_EDI_MODEL_ID} - &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} + &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} cookies=${DEX_COOKIES} Log ${resp} Should not be empty ${resp} Should be equal as integers ${resp["code"]} 500 @@ -53,7 +53,7 @@ Get token from EDI without model_id parameter [Setup] NONE [Tags] edi cli enclave edi_token &{data} = Create Dictionary model_version=${TEST_MODEL_3_VERSION} - &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} + &{resp} = Execute post request ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN}/api/1.0/generate_token data=${data} cookies=${DEX_COOKIES} Log ${resp} Should not be empty ${resp} Should be equal as integers ${resp["code"]} 500 diff --git a/tests/robot/tests/6_incorrect_legionctl_commands/6.1_check_incorrect_legionctl_commands.robot b/tests/robot/tests/6_legionctl_commands/6.1_check_legionctl_commands.robot similarity index 57% rename from tests/robot/tests/6_incorrect_legionctl_commands/6.1_check_incorrect_legionctl_commands.robot rename to tests/robot/tests/6_legionctl_commands/6.1_check_legionctl_commands.robot index 4627c8a18..a7a1b8964 100644 --- a/tests/robot/tests/6_incorrect_legionctl_commands/6.1_check_incorrect_legionctl_commands.robot +++ b/tests/robot/tests/6_legionctl_commands/6.1_check_legionctl_commands.robot @@ -9,128 +9,68 @@ Library Collections Suite Setup Run keywords Choose cluster context ${CLUSTER_NAME} AND ... Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} Suite Teardown Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - +*** Variables *** +${LOCAL_CONFIG} legion/config *** Test Cases *** Scale. Nonexistent model service [Documentation] The scale command must fail if a model cannot be found by id [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale this-model-does-not-exsit 1 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale this-model-does-not-exsit 1 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} No one model can be found Scale. Nonexistent version of model service [Documentation] The scale command must fail if a model cannot be found by version [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --model-version this-version-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --model-version this-version-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} No one model can be found Scale. Scale to zero replicas [Documentation] The scale command must fail if number of replicas is zero [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} should contain ${res.stderr} Invalid scale parameter: should be greater then 0 Scale. Scale to negative number of replicas [Documentation] The scale command must fail if number of replicas is negative [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be greater then 0 Scale. Zero timeout parameter [Documentation] The scale command must fail if timeout parameter is zero [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer Scale. Negative timeout parameter [Documentation] The scale command must fail if it contains negative timeout parameter [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer Scale. Negative timeout with no-wait parameter [Documentation] Ignore negative timeout parameter due to using no-wait parameter [Tags] edi cli enclave - ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose scale ${TEST_COMMAND_MODEL_ID} 1 --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should be equal ${res.rc} ${0} Scale. Missed the host parameter [Documentation] The scale command must fail if it does not contain an edi host [Tags] edi cli enclave - ${res}= Shell legionctl scale ${TEST_COMMAND_MODEL_ID} 2 --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl scale ${TEST_COMMAND_MODEL_ID} 2 --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} Failed to connect -# TODO: uncomment after resolving of the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Scale. Missed the user parameter -# [Documentation] The scale command must fail if it does not contain an user -# [Tags] edi cli enclave -# ${res}= Shell legionctl scale ${TEST_COMMAND_MODEL_ID} 1 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --password ${SERVICE_PASSWORD} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Scale. Missed the password parameter -# [Documentation] The scale command must fail if it does not contain a password -# [Tags] edi cli enclave -# ${res}= Shell legionctl scale ${TEST_COMMAND_MODEL_ID} 1 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Scale. Wrong token -# [Documentation] The scale command must fail if it does not contain a token -# [Tags] edi cli enclave -# ${res}= Shell legionctl scale ${TEST_COMMAND_MODEL_ID} 1 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect - -Inspect. Missed the host parameter - [Documentation] The inspect command must fail if it does not contain an edi host - [Tags] edi cli enclave - ${res}= Shell legionctl inspect --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} - Should not be equal ${res.rc} ${0} - Should contain ${res.stderr} Failed to connect - -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Inspect. Missed the user parameter -# [Documentation] The inspect command must fail if it does not contain an user -# [Tags] edi cli enclave -# ${res}= Shell legionctl inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --password ${SERVICE_PASSWORD} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Inspect. Missed the password parameter -# [Documentation] The inspect command must fail if it does not contain a password -# [Tags] edi cli enclave -# ${res}= Shell legionctl inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Inspect. Wrong token -# [Documentation] The inspect command must fail if it does not contain a token -# [Tags] edi cli enclave -# ${res}= Shell legionctl inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect - Undeploy. Nonexistent model service [Documentation] The undeploy command must fail if a model cannot be found by id [Tags] edi cli enclave - ${res}= Shell legionctl --verbose undeploy this-model-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy this-model-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} No one model can be found @@ -139,14 +79,14 @@ Undeploy. Nonexistent version of model service [Setup] Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} [Teardown] Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} [Tags] edi cli enclave - ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --model-version this-version-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --model-version this-version-does-not-exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} No one model can be found Undeploy. Nonexistent model service with ignore-not-found parameter [Documentation] The undeploy command must finish successfully if a model does not exists but we there is --ignore-not-found parameter [Tags] edi cli enclave - ${res}= Shell legionctl --verbose undeploy this-model-does-not-exsit --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy this-model-does-not-exsit --ignore-not-found --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should be equal ${res.rc} ${0} Undeploy. Negative grace period parameter @@ -154,7 +94,7 @@ Undeploy. Negative grace period parameter [Tags] edi cli enclave [Setup] Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} [Teardown] Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --grace-period=-5 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --grace-period=-5 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should be equal ${res.rc} ${0} Undeploy. Zero timeout parameter @@ -162,7 +102,7 @@ Undeploy. Zero timeout parameter [Tags] edi cli enclave [Setup] Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} [Teardown] Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer @@ -171,7 +111,7 @@ Undeploy. Negative timeout parameter [Tags] edi cli enclave [Setup] Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} [Teardown] Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer @@ -180,47 +120,13 @@ Undeploy. Negative timeout with no-wait parameter [Setup] Run EDI deploy and check model started ${MODEL_TEST_ENCLAVE} ${TEST_MODEL_IMAGE_5} ${TEST_COMMAND_MODEL_ID} ${TEST_MODEL_5_VERSION} [Teardown] Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} [Tags] edi cli enclave - ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose undeploy ${TEST_COMMAND_MODEL_ID} --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should be equal ${res.rc} ${0} -Undeploy. Missed the host parameter - [Documentation] The undeploy command must fail if it does not contain an edi host - [Tags] edi cli enclave - ${res}= Shell legionctl undeploy ${TEST_COMMAND_MODEL_ID} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} - Should not be equal ${res.rc} ${0} - Should contain ${res.stderr} Failed to connect - -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Undeploy. Missed the user parameter -# [Documentation] The undeploy command must fail if it does not contain an user -# [Tags] edi cli enclave -# ${res}= Shell legionctl undeploy ${TEST_COMMAND_MODEL_ID} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --password ${SERVICE_PASSWORD} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Undeploy. Missed the password parameter -# [Documentation] The undeploy command must fail if it does not contain a password -# [Tags] edi cli enclave -# ${res}= Shell legionctl undeploy ${TEST_COMMAND_MODEL_ID} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Undeploy. Wrong token -# [Documentation] The undeploy command must fail if it does not contain a token -# [Tags] edi cli enclave -# ${res}= Shell legionctl undeploy ${TEST_COMMAND_MODEL_ID} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect - Deploy. Nonexistent image [Documentation] The deploy command must fail if image does not exist [Tags] edi cli enclave - ${res}= Shell legionctl --verbose deploy nexus-local.cc.epm.kharlamov.biz:443/legion/this-image-does-not:exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy nexus-local.cc.epm.kharlamov.biz:443/legion/this-image-does-not:exsit --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} Can't get image @@ -228,7 +134,7 @@ Deploy. Negative liveness timeout [Documentation] The deploy command must fail if liveness timeout is negative [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --livenesstimeout -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --livenesstimeout -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} should contain ${res.stderr} must be greater than or equal to 0 @@ -236,7 +142,7 @@ Deploy. Negative readiness timeout [Documentation] The deploy command must fail if readiness timeout is negative [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --readinesstimeout -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --readinesstimeout -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} should contain ${res.stderr} must be greater than or equal to 0 @@ -244,7 +150,7 @@ Deploy. Zero replicas [Documentation] The deploy command must fail if number of replicas is zero [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --scale 0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --scale 0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be greater then 0 @@ -252,7 +158,7 @@ Deploy. Negative number of replicas [Documentation] The deploy command must fail if number of replicas is negative [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --scale -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --scale -3 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be greater then 0 @@ -260,7 +166,7 @@ Deploy. Zero timeout parameter [Documentation] The deploy command must fail if timeout parameter is zero [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --timeout=0 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer @@ -268,7 +174,7 @@ Deploy. Negative timeout parameter [Documentation] The deploy command must fail if it contains negative timeout parameter [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} should be positive integer @@ -276,39 +182,57 @@ Deploy. Negative timeout with no-wait parameter [Documentation] Ignore negative timeout parameter due to using no-wait parameter [Tags] edi cli enclave [Setup] Run Keyword And Ignore Error Run EDI undeploy without version ${MODEL_TEST_ENCLAVE} ${TEST_COMMAND_MODEL_ID} - ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose deploy ${TEST_MODEL_IMAGE_5} --no-wait --timeout=-500 --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" Should be equal ${res.rc} ${0} -Deploy. Missed the host parameter - [Documentation] The deploy command must fail if it does not contain an edi host +Missed the host parameter + [Documentation] The inspect command must fail if it does not contain an edi host [Tags] edi cli enclave - ${res}= Shell legionctl deploy ${TEST_MODEL_IMAGE_5} --user ${SERVICE_ACCOUNT} --password ${SERVICE_PASSWORD} + ${res}= Shell legionctl --verbose inspect --token "${DEX_TOKEN}" Should not be equal ${res.rc} ${0} Should contain ${res.stderr} Failed to connect -# TODO: uncomment after resolving of the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Deploy. Missed the user parameter -# [Documentation] The deploy command must fail if it does not contain an user -# [Tags] edi cli enclave -# ${res}= Shell legionctl deploy ${TEST_MODEL_IMAGE_5} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --password ${SERVICE_PASSWORD} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Deploy. Missed the password parameter -# [Documentation] The deploy command must fail if it does not contain a password -# [Tags] edi cli enclave -# ${res}= Shell legionctl deploy ${TEST_MODEL_IMAGE_5} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --user ${SERVICE_ACCOUNT} -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect -# -# TODO: uncomment after the issue https://github.com/legion-platform/legion/issues/313 will be completed -#Deploy. Wrong token -# [Documentation] The deploy command must fail if it does not contain a token -# [Tags] edi cli enclave -# ${res}= Shell legionctl deploy ${TEST_MODEL_IMAGE_5} --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token -# -# Should not be equal ${res.rc} ${0} -# Should contain ${res.stderr} Failed to connect \ No newline at end of file +Wrong token + [Documentation] The inspect command must fail if it does not contain a token + [Tags] edi cli enclave + ${res}= Shell legionctl --verbose inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token + + Should not be equal ${res.rc} ${0} + Should contain ${res.stderr} Credentials are not correct + +Without token + [Documentation] The inspect command must fail if token is wrong + [Tags] edi cli enclave + ${res}= Shell legionctl --verbose inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} + + Should not be equal ${res.rc} ${0} + Should contain ${res.stderr} Credentials are not correct + +Login. Basic usage + [Documentation] Check the login command and inspect command + [Tags] edi cli enclave + [Teardown] Remove File ${LOCAL_CONFIG} + ${res}= Shell LEGION_CONFIG=${LOCAL_CONFIG} legionctl --verbose login --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" + Should be equal ${res.rc} ${0} + + ${res}= Shell LEGION_CONFIG=${LOCAL_CONFIG} legionctl --verbose inspect + Should be equal ${res.rc} ${0} + +Login. Wrong token + [Documentation] The login command must fail if token is wrong + [Tags] edi cli enclave + [Teardown] Remove File ${LOCAL_CONFIG} + ${res}= Shell LEGION_CONFIG=${LOCAL_CONFIG} legionctl --verbose inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token + Should not be equal ${res.rc} ${0} + Should contain ${res.stderr} Credentials are not correct + +Login. Override login values + [Documentation] Command line parameters must be overrided by config parameters + [Tags] edi cli enclave + [Teardown] Remove File ${LOCAL_CONFIG} + ${res}= Shell LEGION_CONFIG=${LOCAL_CONFIG} legionctl --verbose login --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token "${DEX_TOKEN}" + Should be equal ${res.rc} ${0} + + ${res}= Shell LEGION_CONFIG=${LOCAL_CONFIG} legionctl --verbose inspect --edi ${HOST_PROTOCOL}://edi-${MODEL_TEST_ENCLAVE}.${HOST_BASE_DOMAIN} --token wrong-token + Should not be equal ${res.rc} ${0} + Should contain ${res.stderr} Credentials are not correct \ No newline at end of file