From 915796fb453c4fbf76794de34139df0418cacb35 Mon Sep 17 00:00:00 2001 From: Jiri Petrlik Date: Fri, 5 Jan 2024 10:34:19 +0100 Subject: [PATCH 01/31] Keywords for management of components (#1085) --- .../RHODS_OLM/install/oc_install.robot | 26 +++++++++++++++++++ .../test-run-codeflare-tests.robot | 25 ++++-------------- .../test-run-dw-tests.robot | 25 ++++-------------- 3 files changed, 36 insertions(+), 40 deletions(-) diff --git a/ods_ci/tasks/Resources/RHODS_OLM/install/oc_install.robot b/ods_ci/tasks/Resources/RHODS_OLM/install/oc_install.robot index 39ce0183f..0c47f8e4b 100644 --- a/ods_ci/tasks/Resources/RHODS_OLM/install/oc_install.robot +++ b/ods_ci/tasks/Resources/RHODS_OLM/install/oc_install.robot @@ -329,3 +329,29 @@ Install Kserve Dependencies ELSE Log To Console message=Serverless Operator is already installed END + +Set Component State + [Documentation] Set component state in Data Science Cluster (state should be Managed or Removed) + [Arguments] ${component} ${state} + ${result} = Run Process oc get datascienceclusters.datasciencecluster.opendatahub.io -o name + ... shell=true stderr=STDOUT + IF $result.stdout == "" + FAIL Can not find datasciencecluster + END + ${cluster_name} = Set Variable ${result.stdout} + ${result} = Run Process oc patch ${cluster_name} --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/${component}/managementState" ,"value" : "${state}"}]' + ... shell=true stderr=STDOUT + IF $result.rc != 0 + FAIL Can not enable ${component}: ${result.stdout} + END + Log To Console Component ${component} state was set to ${state} + +Enable Component + [Documentation] Enables a component in Data Science Cluster + [Arguments] ${component} + Set Component State ${component} Managed + +Disable Component + [Documentation] Disable a component in Data Science Cluster + [Arguments] ${component} + Set Component State ${component} Removed diff --git a/ods_ci/tests/Tests/650__distributed_workloads/test-run-codeflare-tests.robot b/ods_ci/tests/Tests/650__distributed_workloads/test-run-codeflare-tests.robot index 2b010a8aa..0b56e5682 100644 --- a/ods_ci/tests/Tests/650__distributed_workloads/test-run-codeflare-tests.robot +++ b/ods_ci/tests/Tests/650__distributed_workloads/test-run-codeflare-tests.robot @@ -4,6 +4,7 @@ Suite Setup Prepare Codeflare E2E Test Suite Suite Teardown Teardown Codeflare E2E Test Suite Library OperatingSystem Library Process +Resource ../../../tasks/Resources/RHODS_OLM/install/oc_install.robot *** Variables *** @@ -66,30 +67,14 @@ Prepare Codeflare E2E Test Suite FAIL Unable to clone Codeflare repo ${CODEFLARE_REPO_URL}:${CODEFLARE_REPO_BRANCH} END - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/ray/managementState" ,"value" : "Managed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not enable ray - END - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/codeflare/managementState" ,"value" : "Managed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not enable codeflare - END + Enable Component ray + Enable Component codeflare Create Directory %{WORKSPACE}/codeflare-e2e-logs Create Directory %{WORKSPACE}/codeflare-odh-logs Teardown Codeflare E2E Test Suite - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/codeflare/managementState" ,"value" : "Removed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not disable codeflare - END - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/ray/managementState" ,"value" : "Removed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not disable ray - END + Disable Component codeflare + Disable Component ray Run Codeflare E2E Test [Arguments] ${TEST_NAME} diff --git a/ods_ci/tests/Tests/650__distributed_workloads/test-run-dw-tests.robot b/ods_ci/tests/Tests/650__distributed_workloads/test-run-dw-tests.robot index 06064bfbd..fc9dc61ec 100644 --- a/ods_ci/tests/Tests/650__distributed_workloads/test-run-dw-tests.robot +++ b/ods_ci/tests/Tests/650__distributed_workloads/test-run-dw-tests.robot @@ -2,6 +2,7 @@ Documentation Distributed workloads tests Resource ../../../tasks/Resources/RHODS_OLM/install/codeflare_install.resource +Resource ../../../tasks/Resources/RHODS_OLM/install/oc_install.robot Resource ../../Resources/Page/DistributedWorkloads/DistributedWorkloads.resource Suite Setup Prepare Distributed Workloads E2E Test Suite @@ -33,25 +34,9 @@ Run distributed workloads sanity tests *** Keywords *** Prepare Distributed Workloads E2E Test Suite - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/ray/managementState" ,"value" : "Managed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not enable ray - END - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/codeflare/managementState" ,"value" : "Managed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not enable codeflare - END + Enable Component ray + Enable Component codeflare Teardown Distributed Workloads E2E Test Suite - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/codeflare/managementState" ,"value" : "Removed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not disable codeflare - END - ${result} = Run Process oc patch datascienceclusters.datasciencecluster.opendatahub.io default-dsc --type 'json' -p '[{"op" : "replace" ,"path" : "/spec/components/ray/managementState" ,"value" : "Removed"}]' - ... shell=true stderr=STDOUT - IF ${result.rc} != 0 - FAIL Can not disable ray - END + Disable Component codeflare + Disable Component ray From f8faae811f204f2ea05e2146dcd79a049a2bfa6c Mon Sep 17 00:00:00 2001 From: Jakub Stejskal Date: Wed, 30 Aug 2023 17:07:39 +0200 Subject: [PATCH 02/31] Add `__init__.py` files in `utils/` to mark directories as Python packages in PyCharm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakub Stejskal Signed-off-by: Jiri Daněk --- ods_ci/__init__.py | 0 ods_ci/utils/__init__.py | 0 ods_ci/utils/scripts/Sender/__init__.py | 0 ods_ci/utils/scripts/__init__.py | 0 ods_ci/utils/scripts/ocm/__init__.py | 0 ods_ci/utils/scripts/openshift/__init__.py | 0 ods_ci/utils/scripts/polarion/__init__.py | 0 ods_ci/utils/scripts/reportportal/__init__.py | 0 ods_ci/utils/scripts/terraform/__init__.py | 0 ods_ci/utils/scripts/terraform/openstack/__init__.py | 0 ods_ci/utils/scripts/testconfig/__init__.py | 0 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 ods_ci/__init__.py create mode 100644 ods_ci/utils/__init__.py create mode 100644 ods_ci/utils/scripts/Sender/__init__.py create mode 100644 ods_ci/utils/scripts/__init__.py create mode 100644 ods_ci/utils/scripts/ocm/__init__.py create mode 100644 ods_ci/utils/scripts/openshift/__init__.py create mode 100644 ods_ci/utils/scripts/polarion/__init__.py create mode 100644 ods_ci/utils/scripts/reportportal/__init__.py create mode 100644 ods_ci/utils/scripts/terraform/__init__.py create mode 100644 ods_ci/utils/scripts/terraform/openstack/__init__.py create mode 100644 ods_ci/utils/scripts/testconfig/__init__.py diff --git a/ods_ci/__init__.py b/ods_ci/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/__init__.py b/ods_ci/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/Sender/__init__.py b/ods_ci/utils/scripts/Sender/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/__init__.py b/ods_ci/utils/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/ocm/__init__.py b/ods_ci/utils/scripts/ocm/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/openshift/__init__.py b/ods_ci/utils/scripts/openshift/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/polarion/__init__.py b/ods_ci/utils/scripts/polarion/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/reportportal/__init__.py b/ods_ci/utils/scripts/reportportal/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/terraform/__init__.py b/ods_ci/utils/scripts/terraform/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/terraform/openstack/__init__.py b/ods_ci/utils/scripts/terraform/openstack/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/ods_ci/utils/scripts/testconfig/__init__.py b/ods_ci/utils/scripts/testconfig/__init__.py new file mode 100644 index 000000000..e69de29bb From 25824580d2d7d0342f7699064b11c1bdb56ee625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Fri, 5 Jan 2024 17:39:23 +0100 Subject: [PATCH 03/31] Add ruff Python linter and suppress reported issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Ruff: a fast Python linter](https://lwn.net/Articles/930487/) * [Ruff: The First 200 Releases](https://notes.crmarsh.com/ruff-the-first-200-releases) Even though ruff is not as good a linter as Pylint, it is still quite good and is _much_ faster: ``` $ time pylint ods_ci real 0m10.980s, user 0m10.745s, sys 0m0.179s $ time ruff ods_ci real 0m0.023s, user 0m0.040s, sys 0m0.017s ``` Signed-off-by: Jiri Daněk --- .github/workflows/code_quality.yaml | 15 ++ poetry.lock | 308 +++++----------------------- pyproject.toml | 122 +++++++++++ 3 files changed, 184 insertions(+), 261 deletions(-) diff --git a/.github/workflows/code_quality.yaml b/.github/workflows/code_quality.yaml index 0346e3d53..91c5ffcb4 100644 --- a/.github/workflows/code_quality.yaml +++ b/.github/workflows/code_quality.yaml @@ -81,3 +81,18 @@ jobs: isort $file --check --diff fi done + ruff: + name: ruff + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install ruff + run: | + pip install poetry + poetry install --only dev + + - name: Run ruff check + run: poetry run ruff check ods_ci/ diff --git a/poetry.lock b/poetry.lock index fcbb70441..8b1f0fcc9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,10 +1,9 @@ -# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "absl-py" version = "1.4.0" description = "Abseil Python Common Libraries, see https://github.com/abseil/abseil-py." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -16,7 +15,6 @@ files = [ name = "aenum" version = "3.1.15" description = "Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants" -category = "main" optional = false python-versions = "*" files = [ @@ -29,7 +27,6 @@ files = [ name = "appdirs" version = "1.4.4" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" optional = false python-versions = "*" files = [ @@ -41,7 +38,6 @@ files = [ name = "appnope" version = "0.1.3" description = "Disable App Nap on macOS >= 10.9" -category = "main" optional = false python-versions = "*" files = [ @@ -53,7 +49,6 @@ files = [ name = "asttokens" version = "2.4.0" description = "Annotate AST trees with source code positions" -category = "main" optional = false python-versions = "*" files = [ @@ -71,7 +66,6 @@ test = ["astroid", "pytest"] name = "attrs" version = "23.1.0" description = "Classes Without Boilerplate" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -90,7 +84,6 @@ tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pyte name = "autopage" version = "0.5.1" description = "A library to provide automatic paging for console output" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -102,7 +95,6 @@ files = [ name = "awscli" version = "1.29.54" description = "Universal Command Line Environment for AWS." -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -122,7 +114,6 @@ s3transfer = ">=0.6.0,<0.7.0" name = "backcall" version = "0.2.0" description = "Specifications for callback functions passed in to an API" -category = "main" optional = false python-versions = "*" files = [ @@ -134,7 +125,6 @@ files = [ name = "backports-zoneinfo" version = "0.2.1" description = "Backport of the standard library zoneinfo module" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -163,7 +153,6 @@ tzdata = ["tzdata"] name = "beautifulsoup4" version = "4.12.2" description = "Screen-scraping library" -category = "main" optional = false python-versions = ">=3.6.0" files = [ @@ -182,7 +171,6 @@ lxml = ["lxml"] name = "black" version = "23.9.1" description = "The uncompromising code formatter." -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -229,7 +217,6 @@ uvloop = ["uvloop (>=0.15.2)"] name = "botocore" version = "1.31.54" description = "Low-level, data-driven core of boto 3." -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -249,7 +236,6 @@ crt = ["awscrt (==0.16.26)"] name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." -category = "main" optional = false python-versions = "*" files = [ @@ -261,7 +247,6 @@ files = [ name = "cachetools" version = "5.3.1" description = "Extensible memoizing collections and decorators" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -273,7 +258,6 @@ files = [ name = "certifi" version = "2023.7.22" description = "Python package for providing Mozilla's CA Bundle." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -285,7 +269,6 @@ files = [ name = "cffi" version = "1.15.1" description = "Foreign Function Interface for Python calling C code." -category = "main" optional = false python-versions = "*" files = [ @@ -362,7 +345,6 @@ pycparser = "*" name = "cfgv" version = "3.4.0" description = "Validate configuration and produce human readable error messages." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -374,7 +356,6 @@ files = [ name = "chardet" version = "3.0.4" description = "Universal encoding detector for Python 2 and 3" -category = "main" optional = false python-versions = "*" files = [ @@ -386,7 +367,6 @@ files = [ name = "charset-normalizer" version = "3.2.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -471,7 +451,6 @@ files = [ name = "click" version = "8.1.7" description = "Composable command line interface toolkit" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -486,7 +465,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} name = "cliff" version = "4.3.0" description = "Command Line Interface Formulation Framework" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -506,7 +484,6 @@ stevedore = ">=2.0.1" name = "cloudpickle" version = "2.2.1" description = "Extended pickling support for Python objects" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -518,7 +495,6 @@ files = [ name = "cmd2" version = "2.4.3" description = "cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -541,7 +517,6 @@ validate = ["flake8", "mypy", "types-pkg-resources"] name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -553,7 +528,6 @@ files = [ name = "comtypes" version = "1.2.0" description = "Pure Python COM package" -category = "main" optional = false python-versions = "*" files = [ @@ -565,7 +539,6 @@ files = [ name = "convertdate" version = "2.4.0" description = "Converts between Gregorian dates and other calendar systems" -category = "main" optional = false python-versions = "<4,>=3.7" files = [ @@ -585,7 +558,6 @@ tests = ["coverage"] name = "cryptography" version = "41.0.4" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -631,7 +603,6 @@ test-randomorder = ["pytest-randomly"] name = "debtcollector" version = "2.5.0" description = "A collection of Python deprecation patterns and strategies that help you collect your technical debt in a non-destructive manner." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -646,7 +617,6 @@ wrapt = ">=1.7.0" name = "decorator" version = "5.1.1" description = "Decorators for Humans" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -658,7 +628,6 @@ files = [ name = "defusedxml" version = "0.7.1" description = "XML bomb protection for Python stdlib modules" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -670,7 +639,6 @@ files = [ name = "deprecated" version = "1.2.14" description = "Python @deprecated decorator to deprecate old python classes, functions or methods." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -688,7 +656,6 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] name = "distlib" version = "0.3.7" description = "Distribution utilities" -category = "main" optional = false python-versions = "*" files = [ @@ -700,7 +667,6 @@ files = [ name = "dnspython" version = "2.4.2" description = "DNS toolkit" -category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -720,7 +686,6 @@ wmi = ["wmi (>=1.5.1,<2.0.0)"] name = "docstring-parser" version = "0.15" description = "Parse Python docstrings in reST, Google and Numpydoc format" -category = "main" optional = false python-versions = ">=3.6,<4.0" files = [ @@ -732,7 +697,6 @@ files = [ name = "docutils" version = "0.16" description = "Docutils -- Python Documentation Utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -744,7 +708,6 @@ files = [ name = "dogpile-cache" version = "1.2.2" description = "A caching front-end based on the Dogpile lock." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -761,7 +724,6 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} name = "escapism" version = "1.0.1" description = "Simple, generic API for escaping strings." -category = "main" optional = false python-versions = "*" files = [ @@ -773,7 +735,6 @@ files = [ name = "et-xmlfile" version = "1.1.0" description = "An implementation of lxml.xmlfile for the standard library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -785,7 +746,6 @@ files = [ name = "exceptiongroup" version = "1.1.3" description = "Backport of PEP 654 (exception groups)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -800,7 +760,6 @@ test = ["pytest (>=6)"] name = "exchangelib" version = "4.9.0" description = "Client for Microsoft Exchange Web Services (EWS)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -832,7 +791,6 @@ sspi = ["requests-negotiate-sspi"] name = "executing" version = "1.2.0" description = "Get the currently executing AST node of a frame, and other information" -category = "main" optional = false python-versions = "*" files = [ @@ -847,7 +805,6 @@ tests = ["asttokens", "littleutils", "pytest", "rich"] name = "filelock" version = "3.12.4" description = "A platform independent file lock." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -864,7 +821,6 @@ typing = ["typing-extensions (>=4.7.1)"] name = "fire" version = "0.4.0" description = "A library for automatically generating command line interfaces." -category = "main" optional = false python-versions = "*" files = [ @@ -879,7 +835,6 @@ termcolor = "*" name = "flake8" version = "6.1.0" description = "the modular source code checker: pep8 pyflakes and co" -category = "main" optional = false python-versions = ">=3.8.1" files = [ @@ -896,7 +851,6 @@ pyflakes = ">=3.1.0,<3.2.0" name = "fonttools" version = "4.42.1" description = "Tools to manipulate font files" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -954,7 +908,6 @@ woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] name = "fpdf2" version = "2.7.5" description = "Simple & fast PDF generation for Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -965,13 +918,12 @@ files = [ [package.dependencies] defusedxml = "*" fonttools = ">=4.34.0" -Pillow = ">=6.2.2,<9.2.0 || >=9.3.0" +Pillow = ">=6.2.2,<9.2.dev0 || >=9.3.dev0" [[package]] name = "furl" version = "2.1.3" description = "URL manipulation made simple." -category = "main" optional = false python-versions = "*" files = [ @@ -987,7 +939,6 @@ six = ">=1.8.0" name = "future" version = "0.18.3" description = "Clean single-source support for Python 3 and 2" -category = "main" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -998,7 +949,6 @@ files = [ name = "google-api-core" version = "2.12.0" description = "Google API client core library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1021,7 +971,6 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] name = "google-api-python-client" version = "1.12.11" description = "Google API Client Library for Python" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" files = [ @@ -1041,7 +990,6 @@ uritemplate = ">=3.0.0,<4dev" name = "google-auth" version = "2.23.0" description = "Google Authentication Library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1066,7 +1014,6 @@ requests = ["requests (>=2.20.0,<3.0.0.dev0)"] name = "google-auth-httplib2" version = "0.1.1" description = "Google Authentication Library: httplib2 transport" -category = "main" optional = false python-versions = "*" files = [ @@ -1082,7 +1029,6 @@ httplib2 = ">=0.19.0" name = "google-cloud-core" version = "2.3.3" description = "Google Cloud API client core library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1091,7 +1037,7 @@ files = [ ] [package.dependencies] -google-api-core = ">=1.31.6,<2.0.0 || >2.3.0,<3.0.0dev" +google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" google-auth = ">=1.25.0,<3.0dev" [package.extras] @@ -1101,7 +1047,6 @@ grpc = ["grpcio (>=1.38.0,<2.0dev)"] name = "google-cloud-storage" version = "2.11.0" description = "Google Cloud Storage API client library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1110,7 +1055,7 @@ files = [ ] [package.dependencies] -google-api-core = ">=1.31.5,<2.0.0 || >2.3.0,<3.0.0dev" +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev" google-auth = ">=1.25.0,<3.0dev" google-cloud-core = ">=2.3.0,<3.0dev" google-resumable-media = ">=2.6.0" @@ -1123,7 +1068,6 @@ protobuf = ["protobuf (<5.0.0dev)"] name = "google-crc32c" version = "1.5.0" description = "A python wrapper of the C library 'Google CRC32C'" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1204,7 +1148,6 @@ testing = ["pytest"] name = "google-resumable-media" version = "2.6.0" description = "Utilities for Google Media Downloads and Resumable Uploads" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -1223,7 +1166,6 @@ requests = ["requests (>=2.18.0,<3.0.0dev)"] name = "googleapis-common-protos" version = "1.60.0" description = "Common protobufs used in Google APIs" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1241,7 +1183,6 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] name = "graphviz" version = "0.13.2" description = "Simple Python interface for Graphviz" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" files = [ @@ -1258,7 +1199,6 @@ test = ["mock (>=2)", "pytest (>=3.4,!=3.10.0)", "pytest-cov", "pytest-mock (>=1 name = "h11" version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1270,7 +1210,6 @@ files = [ name = "hijri-converter" version = "2.3.1" description = "Accurate Hijri-Gregorian dates converter based on the Umm al-Qura calendar" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1282,7 +1221,6 @@ files = [ name = "holidays" version = "0.21.13" description = "Generate and work with holidays in Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1303,7 +1241,6 @@ tzdata = {version = "*", markers = "os_name == \"nt\""} name = "htmldocx" version = "0.0.6" description = "Convert html to docx" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1319,7 +1256,6 @@ python-docx = ">=0.8.10" name = "httplib2" version = "0.22.0" description = "A comprehensive HTTP client library." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -1334,7 +1270,6 @@ pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0 name = "hubspot-api-client" version = "4.0.6" description = "HubSpot API client" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1355,7 +1290,6 @@ dev = ["black", "pytest"] name = "identify" version = "2.5.29" description = "File identification library for Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1370,7 +1304,6 @@ license = ["ukkonen"] name = "idna" version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -1382,7 +1315,6 @@ files = [ name = "importlib-metadata" version = "4.13.0" description = "Read metadata from Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1402,7 +1334,6 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag name = "importlib-resources" version = "6.1.0" description = "Read resources from Python packages" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1421,7 +1352,6 @@ testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", name = "iniconfig" version = "2.0.0" description = "brain-dead simple config-ini parsing" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1433,7 +1363,6 @@ files = [ name = "ipython" version = "8.4.0" description = "IPython: Productive Interactive Computing" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1473,7 +1402,6 @@ test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.19)", "pa name = "iso8601" version = "2.0.0" description = "Simple module to parse ISO 8601 dates" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -1485,7 +1413,6 @@ files = [ name = "isodate" version = "0.6.1" description = "An ISO 8601 date/time/duration parser and formatter" -category = "main" optional = false python-versions = "*" files = [ @@ -1500,7 +1427,6 @@ six = "*" name = "java-access-bridge-wrapper" version = "1.0.0" description = "Python wrapper for the Windows Java Access Bridge" -category = "main" optional = false python-versions = ">=3.8.1,<4.0.0" files = [ @@ -1515,7 +1441,6 @@ pywin32 = {version = ">=300,<307", markers = "python_full_version != \"3.8.1\" a name = "jedi" version = "0.19.0" description = "An autocompletion tool for Python that can be used for text editors." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -1535,7 +1460,6 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] name = "jinja2" version = "3.1.2" description = "A very fast and expressive template engine." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1553,7 +1477,6 @@ i18n = ["Babel (>=2.7)"] name = "jmespath" version = "1.0.1" description = "JSON Matching Expressions" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1565,7 +1488,6 @@ files = [ name = "jsonpatch" version = "1.33" description = "Apply JSON-Patches (RFC 6902)" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -1580,7 +1502,6 @@ jsonpointer = ">=1.9" name = "jsonpath-ng" version = "1.6.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." -category = "main" optional = false python-versions = "*" files = [ @@ -1595,7 +1516,6 @@ ply = "*" name = "jsonpointer" version = "2.4" description = "Identify specific nodes in a JSON document (RFC 6901)" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" files = [ @@ -1607,7 +1527,6 @@ files = [ name = "jsonschema" version = "4.19.1" description = "An implementation of JSON Schema validation for Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1631,7 +1550,6 @@ format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339- name = "jsonschema-specifications" version = "2023.7.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1647,7 +1565,6 @@ referencing = ">=0.28.0" name = "keystoneauth1" version = "5.3.0" description = "Authentication Library for OpenStack Identity" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -1673,7 +1590,6 @@ test = ["PyYAML (>=3.12)", "bandit (>=1.1.0,<1.6.0)", "betamax (>=0.7.0)", "cove name = "kfp" version = "1.8.22" description = "KubeFlow Pipelines SDK" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -1687,7 +1603,7 @@ cloudpickle = ">=2.0.0,<3" Deprecated = ">=1.2.7,<2" docstring-parser = ">=0.7.3,<1" fire = ">=0.3.1,<1" -google-api-core = ">=1.31.5,<2.0.0 || >2.3.0,<3.0.0dev" +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev" google-api-python-client = ">=1.7.8,<2" google-auth = ">=1.6.1,<3" google-cloud-storage = ">=1.20.0,<3" @@ -1713,7 +1629,6 @@ all = ["docker"] name = "kfp-pipeline-spec" version = "0.1.16" description = "Kubeflow Pipelines pipeline spec" -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -1727,7 +1642,6 @@ protobuf = ">=3.13.0,<4" name = "kfp-server-api" version = "1.8.5" description = "Kubeflow Pipelines API" -category = "main" optional = false python-versions = "*" files = [ @@ -1744,7 +1658,6 @@ urllib3 = ">=1.15" name = "kfp-tekton" version = "1.5.9" description = "Tekton Compiler for Kubeflow Pipelines" -category = "main" optional = false python-versions = ">=3.6.1" files = [ @@ -1759,7 +1672,6 @@ PyYAML = ">=6,<7" name = "korean-lunar-calendar" version = "0.3.1" description = "Korean Lunar Calendar" -category = "main" optional = false python-versions = "*" files = [ @@ -1771,7 +1683,6 @@ files = [ name = "kubernetes" version = "12.0.1" description = "Kubernetes python client" -category = "main" optional = false python-versions = "*" files = [ @@ -1789,7 +1700,7 @@ requests-oauthlib = "*" setuptools = ">=21.0.0" six = ">=1.9.0" urllib3 = ">=1.24.2" -websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.0 || >=0.43.0" +websocket-client = ">=0.32.0,<0.40.0 || >0.40.0,<0.41.dev0 || >=0.43.dev0" [package.extras] adal = ["adal (>=1.0.2)"] @@ -1798,7 +1709,6 @@ adal = ["adal (>=1.0.2)"] name = "lxml" version = "4.9.3" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" files = [ @@ -1906,7 +1816,6 @@ source = ["Cython (>=0.29.35)"] name = "markdown-it-py" version = "3.0.0" description = "Python port of markdown-it. Markdown parsing, done right!" -category = "dev" optional = false python-versions = ">=3.8" files = [ @@ -1931,7 +1840,6 @@ testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] name = "markupsafe" version = "2.1.3" description = "Safely add untrusted strings to HTML/XML markup." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -1955,6 +1863,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1991,7 +1909,6 @@ files = [ name = "matplotlib-inline" version = "0.1.6" description = "Inline Matplotlib backend for Jupyter" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2006,7 +1923,6 @@ traitlets = "*" name = "mccabe" version = "0.7.0" description = "McCabe checker, plugin for flake8" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2018,7 +1934,6 @@ files = [ name = "mdurl" version = "0.1.2" description = "Markdown URL utilities" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2030,7 +1945,6 @@ files = [ name = "more-itertools" version = "10.1.0" description = "More routines for operating on iterables, beyond itertools" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2042,7 +1956,6 @@ files = [ name = "msgpack" version = "1.0.6" description = "MessagePack serializer" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2108,7 +2021,6 @@ files = [ name = "mss" version = "6.1.0" description = "An ultra fast cross-platform multiple screenshots module in pure python using ctypes." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2120,7 +2032,6 @@ files = [ name = "mypy" version = "1.5.1" description = "Optional static typing for Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2167,7 +2078,6 @@ reports = ["lxml"] name = "mypy-extensions" version = "1.0.0" description = "Type system extensions for programs checked with the mypy type checker." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -2179,7 +2089,6 @@ files = [ name = "netaddr" version = "0.9.0" description = "A network address manipulation library for Python" -category = "main" optional = false python-versions = "*" files = [ @@ -2191,7 +2100,6 @@ files = [ name = "netifaces" version = "0.11.0" description = "Portable network interface information." -category = "main" optional = false python-versions = "*" files = [ @@ -2231,7 +2139,6 @@ files = [ name = "netsuitesdk" version = "1.24.0" description = "Python SDK for accessing the NetSuite SOAP webservice" -category = "main" optional = false python-versions = "*" files = [ @@ -2246,7 +2153,6 @@ zeep = "*" name = "nodeenv" version = "1.8.0" description = "Node.js virtual environment builder" -category = "main" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" files = [ @@ -2261,7 +2167,6 @@ setuptools = "*" name = "notifiers" version = "1.3.3" description = "The easy way to send notifications" -category = "main" optional = false python-versions = ">=3.7,<4.0" files = [ @@ -2278,7 +2183,6 @@ requests = ">=2.27.1,<3.0.0" name = "o365" version = "2.0.26" description = "Microsoft Graph and Office 365 API made easy" -category = "main" optional = false python-versions = ">=3.4" files = [ @@ -2299,7 +2203,6 @@ tzlocal = ">=4.0" name = "oauthlib" version = "3.2.2" description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2316,7 +2219,6 @@ signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] name = "openpyxl" version = "3.1.2" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2331,7 +2233,6 @@ et-xmlfile = "*" name = "openshift" version = "0.12.1" description = "OpenShift python client" -category = "main" optional = false python-versions = "*" files = [ @@ -2349,7 +2250,6 @@ six = "*" name = "openstacksdk" version = "1.5.0" description = "An SDK for building applications to work with OpenStack" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2376,7 +2276,6 @@ requestsexceptions = ">=1.2.0" name = "orderedmultidict" version = "1.0.1" description = "Ordered Multivalue Dictionary" -category = "main" optional = false python-versions = "*" files = [ @@ -2391,7 +2290,6 @@ six = ">=1.8.0" name = "os-service-types" version = "1.7.0" description = "Python library for consuming OpenStack sevice-types-authority data" -category = "main" optional = false python-versions = "*" files = [ @@ -2406,7 +2304,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "osc-lib" version = "2.8.1" description = "OpenStackClient Library" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2428,7 +2325,6 @@ stevedore = ">=1.20.0" name = "oslo-config" version = "9.2.0" description = "Oslo Configuration API" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2453,7 +2349,6 @@ test = ["bandit (>=1.7.0,<1.8.0)", "coverage (>=4.0,!=4.4)", "fixtures (>=3.0.0) name = "oslo-i18n" version = "6.1.0" description = "Oslo i18n library" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2468,7 +2363,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "oslo-serialization" version = "5.2.0" description = "Oslo Serialization library" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2487,7 +2381,6 @@ tzdata = ">=2022.4" name = "oslo-utils" version = "6.2.1" description = "Oslo Utility library" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2510,7 +2403,6 @@ tzdata = ">=2022.4" name = "outcome" version = "1.2.0" description = "Capture the outcome of Python function calls." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2525,7 +2417,6 @@ attrs = ">=19.2.0" name = "packaging" version = "23.1" description = "Core utilities for Python packages" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2537,7 +2428,6 @@ files = [ name = "parso" version = "0.8.3" description = "A Python Parser" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2553,7 +2443,6 @@ testing = ["docopt", "pytest (<6.0.0)"] name = "pathspec" version = "0.11.2" description = "Utility library for gitignore style pattern matching of file paths." -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -2565,7 +2454,6 @@ files = [ name = "pbr" version = "5.11.1" description = "Python Build Reasonableness" -category = "main" optional = false python-versions = ">=2.6" files = [ @@ -2577,7 +2465,6 @@ files = [ name = "pdfminer-six" version = "20221105" description = "PDF parser and analyzer" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2598,7 +2485,6 @@ image = ["Pillow"] name = "pendulum" version = "2.1.2" description = "Python datetimes made easy" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -2633,7 +2519,6 @@ pytzdata = ">=2020.1" name = "pexpect" version = "4.8.0" description = "Pexpect allows easy control of interactive console applications." -category = "main" optional = false python-versions = "*" files = [ @@ -2648,7 +2533,6 @@ ptyprocess = ">=0.5" name = "pickleshare" version = "0.7.5" description = "Tiny 'shelve'-like database with concurrency support" -category = "main" optional = false python-versions = "*" files = [ @@ -2660,7 +2544,6 @@ files = [ name = "pillow" version = "9.5.0" description = "Python Imaging Library (Fork)" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2740,7 +2623,6 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa name = "pkgutil-resolve-name" version = "1.3.10" description = "Resolve a name to an object." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -2752,7 +2634,6 @@ files = [ name = "platformdirs" version = "3.8.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2768,7 +2649,6 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest- name = "pluggy" version = "1.3.0" description = "plugin and hook calling mechanisms for python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2784,7 +2664,6 @@ testing = ["pytest", "pytest-benchmark"] name = "ply" version = "3.11" description = "Python Lex & Yacc" -category = "main" optional = false python-versions = "*" files = [ @@ -2796,7 +2675,6 @@ files = [ name = "pre-commit" version = "3.4.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2815,7 +2693,6 @@ virtualenv = ">=20.10.0" name = "prettytable" version = "3.9.0" description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2833,9 +2710,8 @@ tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"] name = "prompt-toolkit" version = "2.0.10" description = "Library for building powerful interactive command lines in Python" -category = "main" optional = false -python-versions = ">=2.6,<3.0.0 || >=3.3.0" +python-versions = ">=2.6,<3.0.dev0 || >=3.3.dev0" files = [ {file = "prompt_toolkit-2.0.10-py2-none-any.whl", hash = "sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31"}, {file = "prompt_toolkit-2.0.10-py3-none-any.whl", hash = "sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4"}, @@ -2850,7 +2726,6 @@ wcwidth = "*" name = "protobuf" version = "3.20.3" description = "Protocol Buffers" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -2882,7 +2757,6 @@ files = [ name = "psutil" version = "5.9.5" description = "Cross-platform lib for process and system monitoring in Python." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2909,7 +2783,6 @@ test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] name = "ptyprocess" version = "0.7.0" description = "Run a subprocess in a pseudo terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -2921,7 +2794,6 @@ files = [ name = "pure-eval" version = "0.2.2" description = "Safely evaluate AST nodes without side effects" -category = "main" optional = false python-versions = "*" files = [ @@ -2936,7 +2808,6 @@ tests = ["pytest"] name = "pyasn1" version = "0.5.0" description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2948,7 +2819,6 @@ files = [ name = "pyasn1-modules" version = "0.3.0" description = "A collection of ASN.1-based protocols modules" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -2963,7 +2833,6 @@ pyasn1 = ">=0.4.6,<0.6.0" name = "pycodestyle" version = "2.11.0" description = "Python style guide checker" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -2975,7 +2844,6 @@ files = [ name = "pycparser" version = "2.21" description = "C parser in Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -2987,7 +2855,6 @@ files = [ name = "pydantic" version = "1.10.12" description = "Data validation and settings management using python type hints" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3040,7 +2907,6 @@ email = ["email-validator (>=1.0.3)"] name = "pyflakes" version = "3.1.0" description = "passive checker of Python programs" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3052,7 +2918,6 @@ files = [ name = "pygments" version = "2.16.1" description = "Pygments is a syntax highlighting package written in Python." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3067,7 +2932,6 @@ plugins = ["importlib-metadata"] name = "pyjwt" version = "2.8.0" description = "JSON Web Token implementation in Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3085,7 +2949,6 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"] name = "pymeeus" version = "0.5.12" description = "Python implementation of Jean Meeus astronomical routines" -category = "main" optional = false python-versions = "*" files = [ @@ -3096,7 +2959,6 @@ files = [ name = "pynput-robocorp-fork" version = "5.0.0" description = "Monitor and control user input devices" -category = "main" optional = false python-versions = "*" files = [ @@ -3115,7 +2977,6 @@ six = "*" name = "pyobjc-core" version = "9.2" description = "Python<->ObjC Interoperability Module" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3133,7 +2994,6 @@ files = [ name = "pyobjc-framework-applicationservices" version = "9.2" description = "Wrappers for the framework ApplicationServices on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3156,7 +3016,6 @@ pyobjc-framework-Quartz = ">=9.2" name = "pyobjc-framework-cocoa" version = "9.2" description = "Wrappers for the Cocoa frameworks on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3177,7 +3036,6 @@ pyobjc-core = ">=9.2" name = "pyobjc-framework-quartz" version = "9.2" description = "Wrappers for the Quartz frameworks on macOS" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3199,7 +3057,6 @@ pyobjc-framework-Cocoa = ">=9.2" name = "pyotp" version = "2.9.0" description = "Python One Time Password Library" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3214,7 +3071,6 @@ test = ["coverage", "mypy", "ruff", "wheel"] name = "pyparsing" version = "3.1.1" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" optional = false python-versions = ">=3.6.8" files = [ @@ -3229,7 +3085,6 @@ diagrams = ["jinja2", "railroad-diagrams"] name = "pypdf" version = "3.16.2" description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3251,7 +3106,6 @@ image = ["Pillow (>=8.0.0)"] name = "pyperclip" version = "1.8.2" description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" -category = "main" optional = false python-versions = "*" files = [ @@ -3262,7 +3116,6 @@ files = [ name = "pyreadline3" version = "3.4.1" description = "A python implementation of GNU readline." -category = "main" optional = false python-versions = "*" files = [ @@ -3274,7 +3127,6 @@ files = [ name = "pysocks" version = "1.7.1" description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3287,7 +3139,6 @@ files = [ name = "pyspnego" version = "0.9.2" description = "Windows Negotiate Authentication Client and Server" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3318,7 +3169,6 @@ yaml = ["ruamel.yaml"] name = "pytest" version = "7.4.2" description = "pytest: simple powerful testing with Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3341,7 +3191,6 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no name = "pytest-logger" version = "0.5.1" description = "Plugin configuring handlers for loggers from Python logging module." -category = "main" optional = false python-versions = "*" files = [ @@ -3357,7 +3206,6 @@ pytest = ">=3.2" name = "python-cinderclient" version = "9.4.0" description = "OpenStack Block Storage API Client Library" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3378,7 +3226,6 @@ stevedore = ">=3.3.0" name = "python-dateutil" version = "2.8.2" description = "Extensions to the standard Python datetime module" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ @@ -3393,7 +3240,6 @@ six = ">=1.5" name = "python-docx" version = "0.8.11" description = "Create and update Microsoft Word .docx files." -category = "main" optional = false python-versions = "*" files = [ @@ -3407,7 +3253,6 @@ lxml = ">=2.3.2" name = "python-dotenv" version = "1.0.0" description = "Read key-value pairs from a .env file and set them as environment variables" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3422,7 +3267,6 @@ cli = ["click (>=5.0)"] name = "python-keystoneclient" version = "5.2.0" description = "Client Library for OpenStack Identity" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3447,7 +3291,6 @@ stevedore = ">=1.20.0" name = "python-novaclient" version = "18.4.0" description = "Client library for OpenStack Compute API" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3469,7 +3312,6 @@ stevedore = ">=2.0.1" name = "python-openstackclient" version = "6.3.0" description = "OpenStack Command-line Client" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3495,7 +3337,6 @@ stevedore = ">=2.0.1" name = "python-string-utils" version = "1.0.0" description = "Utility functions for strings validation and manipulation." -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -3507,7 +3348,6 @@ files = [ name = "python-xlib" version = "0.33" description = "Python X Library" -category = "main" optional = false python-versions = "*" files = [ @@ -3522,7 +3362,6 @@ six = ">=1.10.0" name = "pytz" version = "2023.3.post1" description = "World timezone definitions, modern and historical" -category = "main" optional = false python-versions = "*" files = [ @@ -3534,7 +3373,6 @@ files = [ name = "pytz-deprecation-shim" version = "0.1.0.post0" description = "Shims to make deprecation of pytz easier" -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ @@ -3550,7 +3388,6 @@ tzdata = {version = "*", markers = "python_version >= \"3.6\""} name = "pytzdata" version = "2020.1" description = "The Olson timezone database for Python." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3562,7 +3399,6 @@ files = [ name = "pywin32" version = "303" description = "Python for Window Extensions" -category = "main" optional = false python-versions = "*" files = [ @@ -3584,7 +3420,6 @@ files = [ name = "pywinauto" version = "0.6.8" description = "A set of Python modules to automate the Microsoft Windows GUI" -category = "main" optional = false python-versions = "*" files = [ @@ -3601,7 +3436,6 @@ six = "*" name = "pyyaml" version = "6.0.1" description = "YAML parser and emitter for Python" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3661,7 +3495,6 @@ files = [ name = "referencing" version = "0.30.2" description = "JSON Referencing + Python" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -3677,7 +3510,6 @@ rpds-py = ">=0.7.0" name = "reportportal-client" version = "5.4.1" description = "Python client for ReportPortal v5." -category = "main" optional = false python-versions = "*" files = [ @@ -3694,7 +3526,6 @@ six = ">=1.16.0" name = "requests" version = "2.31.0" description = "Python HTTP for Humans." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3717,7 +3548,6 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-file" version = "1.5.1" description = "File transport adapter for Requests" -category = "main" optional = false python-versions = "*" files = [ @@ -3733,7 +3563,6 @@ six = "*" name = "requests-ntlm" version = "1.2.0" description = "This package allows for HTTP NTLM authentication using the requests library." -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3750,7 +3579,6 @@ requests = ">=2.0.0" name = "requests-oauthlib" version = "1.3.1" description = "OAuthlib authentication support for Requests." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3769,7 +3597,6 @@ rsa = ["oauthlib[signedtoken] (>=3.0.0)"] name = "requests-toolbelt" version = "0.10.1" description = "A utility belt for advanced users of python-requests" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -3784,7 +3611,6 @@ requests = ">=2.0.1,<3.0.0" name = "requestsexceptions" version = "1.4.0" description = "Import exceptions from potentially bundled packages in requests." -category = "main" optional = false python-versions = "*" files = [ @@ -3796,7 +3622,6 @@ files = [ name = "rfc3986" version = "2.0.0" description = "Validating URI References per RFC 3986" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -3811,7 +3636,6 @@ idna2008 = ["idna"] name = "rich" version = "13.5.3" description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" -category = "dev" optional = false python-versions = ">=3.7.0" files = [ @@ -3831,7 +3655,6 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] name = "rich-click" version = "1.6.1" description = "Format click help output nicely with rich" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3850,7 +3673,6 @@ dev = ["pre-commit"] name = "robocorp-storage" version = "1.0.0" description = "Robocorp Asset Storage library" -category = "main" optional = false python-versions = ">=3.7.2,<4.0.0" files = [ @@ -3866,7 +3688,6 @@ tenacity = ">=8.0.1,<9.0.0" name = "robotframework" version = "6.1.1" description = "Generic automation framework for acceptance testing and robotic process automation (RPA)" -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -3878,7 +3699,6 @@ files = [ name = "robotframework-debuglibrary" version = "2.3.0" description = "RobotFramework debug library and an interactive shell" -category = "main" optional = false python-versions = "*" files = [ @@ -3894,7 +3714,6 @@ robotframework = ">=3.0" name = "robotframework-jupyterlibrary" version = "0.4.2" description = "A Robot Framework library for automating (testing of) Jupyter end-user applications and extensions" -category = "main" optional = false python-versions = "*" files = [ @@ -3910,7 +3729,6 @@ robotframework-seleniumlibrary = ">=4.5" name = "robotframework-lsp" version = "1.11.0" description = "Language Server Protocol implementation for Robot Framework" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -3929,7 +3747,6 @@ test = ["mock", "pytest", "pytest-regressions (==1.0.6)", "pytest-timeout", "pyt name = "robotframework-openshift" version = "1.0.0" description = "" -category = "main" optional = false python-versions = "*" files = [] @@ -3965,7 +3782,6 @@ resolved_reference = "129734755d5c7ccea1788d4fb5ae1772a19132dd" name = "robotframework-pythonlibcore" version = "4.2.0" description = "Tools to ease creating larger test libraries for Robot Framework using Python." -category = "main" optional = false python-versions = ">=3.7, <4" files = [ @@ -3977,7 +3793,6 @@ files = [ name = "robotframework-requests" version = "0.9.5" description = "Robot Framework keyword library wrapper around requests" -category = "main" optional = false python-versions = "*" files = [ @@ -3996,7 +3811,6 @@ test = ["coverage", "flake8", "flask", "pytest", "robotframework (>=3.2.1)", "si name = "robotframework-robocop" version = "4.1.1" description = "Static code analysis tool (linter) for Robot Framework" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4021,7 +3835,6 @@ doc = ["furo", "pygments", "sphinx", "sphinx-copybutton", "sphinx-design", "sphi name = "robotframework-sapguilibrary" version = "1.1" description = "A Robot Framework Library for automating the SAP GUI desktop client" -category = "main" optional = false python-versions = "*" files = [ @@ -4037,7 +3850,6 @@ robotframework = ">=2.9" name = "robotframework-seleniumlibrary" version = "6.1.2" description = "Web testing library for Robot Framework" -category = "main" optional = false python-versions = ">=3.6, <4" files = [ @@ -4054,7 +3866,6 @@ selenium = ">=4.3.0" name = "robotframework-seleniumtestability" version = "2.1.0" description = "SeleniumTestability library that helps speed up tests withasyncronous evens" -category = "main" optional = false python-versions = "*" files = [ @@ -4071,7 +3882,6 @@ wrapt = "*" name = "robotframework-tidy" version = "4.5.0" description = "Code autoformatter for Robot Framework" -category = "dev" optional = false python-versions = ">=3.7" files = [ @@ -4080,13 +3890,13 @@ files = [ ] [package.dependencies] -click = ">=8.1.0,<8.2.0" +click = "==8.1.*" colorama = ">=0.4.3,<0.4.7" jinja2 = ">=3.0,<4.0" pathspec = ">=0.9.0,<0.11.3" rich-click = ">=1.4,<1.6.2" robotframework = ">=4.0" -tomli = ">=2.0.0,<2.1.0" +tomli = "==2.0.*" [package.extras] dev = ["coverage", "invoke", "jinja2", "packaging (>=21.0)", "pre-commit", "pyflakes (>=2.4,<3.2)", "pylama", "pytest"] @@ -4096,7 +3906,6 @@ doc = ["furo", "sphinx", "sphinx-copybutton (==0.5.2)", "sphinx-design"] name = "rpaframework" version = "27.2.0" description = "A collection of tools and libraries for RPA" -category = "main" optional = false python-versions = ">=3.8.1,<4.0.0" files = [ @@ -4163,7 +3972,6 @@ xlwt = ">=1.3.0,<2.0.0" name = "rpaframework-core" version = "11.2.0" description = "Core utilities used by RPA Framework" -category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -4184,7 +3992,6 @@ webdriver-manager = "4.0.0" name = "rpaframework-pdf" version = "7.2.0" description = "PDF library of RPA Framework" -category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -4204,7 +4011,6 @@ rpaframework-core = ">=11.0.0,<12.0.0" name = "rpaframework-windows" version = "7.4.0" description = "Windows library for RPA Framework" -category = "main" optional = false python-versions = ">=3.8,<4.0" files = [ @@ -4227,7 +4033,6 @@ uiautomation = ">=2.0.15,<3.0.0" name = "rpds-py" version = "0.10.3" description = "Python bindings to Rust's persistent data structures (rpds)" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4334,7 +4139,6 @@ files = [ name = "rsa" version = "4.7.2" description = "Pure-Python RSA implementation" -category = "main" optional = false python-versions = ">=3.5, <4" files = [ @@ -4349,7 +4153,6 @@ pyasn1 = ">=0.1.3" name = "ruamel-yaml" version = "0.17.32" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -category = "main" optional = false python-versions = ">=3" files = [ @@ -4368,7 +4171,6 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] name = "ruamel-yaml-clib" version = "0.2.7" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -category = "main" optional = false python-versions = ">=3.5" files = [ @@ -4411,11 +4213,36 @@ files = [ {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, ] +[[package]] +name = "ruff" +version = "0.1.11" +description = "An extremely fast Python linter and code formatter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.11-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a7f772696b4cdc0a3b2e527fc3c7ccc41cdcb98f5c80fdd4f2b8c50eb1458196"}, + {file = "ruff-0.1.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:934832f6ed9b34a7d5feea58972635c2039c7a3b434fe5ba2ce015064cb6e955"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea0d3e950e394c4b332bcdd112aa566010a9f9c95814844a7468325290aabfd9"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bd4025b9c5b429a48280785a2b71d479798a69f5c2919e7d274c5f4b32c3607"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1ad00662305dcb1e987f5ec214d31f7d6a062cae3e74c1cbccef15afd96611d"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4b077ce83f47dd6bea1991af08b140e8b8339f0ba8cb9b7a484c30ebab18a23f"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4a88efecec23c37b11076fe676e15c6cdb1271a38f2b415e381e87fe4517f18"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b25093dad3b055667730a9b491129c42d45e11cdb7043b702e97125bcec48a1"}, + {file = "ruff-0.1.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:231d8fb11b2cc7c0366a326a66dafc6ad449d7fcdbc268497ee47e1334f66f77"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:09c415716884950080921dd6237767e52e227e397e2008e2bed410117679975b"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0f58948c6d212a6b8d41cd59e349751018797ce1727f961c2fa755ad6208ba45"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:190a566c8f766c37074d99640cd9ca3da11d8deae2deae7c9505e68a4a30f740"}, + {file = "ruff-0.1.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6464289bd67b2344d2a5d9158d5eb81025258f169e69a46b741b396ffb0cda95"}, + {file = "ruff-0.1.11-py3-none-win32.whl", hash = "sha256:9b8f397902f92bc2e70fb6bebfa2139008dc72ae5177e66c383fa5426cb0bf2c"}, + {file = "ruff-0.1.11-py3-none-win_amd64.whl", hash = "sha256:eb85ee287b11f901037a6683b2374bb0ec82928c5cbc984f575d0437979c521a"}, + {file = "ruff-0.1.11-py3-none-win_arm64.whl", hash = "sha256:97ce4d752f964ba559c7023a86e5f8e97f026d511e48013987623915431c7ea9"}, + {file = "ruff-0.1.11.tar.gz", hash = "sha256:f9d4d88cb6eeb4dfe20f9f0519bd2eaba8119bde87c3d5065c541dbae2b5a2cb"}, +] + [[package]] name = "s3transfer" version = "0.6.2" description = "An Amazon S3 Transfer Manager" -category = "main" optional = false python-versions = ">= 3.7" files = [ @@ -4433,7 +4260,6 @@ crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] name = "selenium" version = "4.13.0" description = "" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4451,7 +4277,6 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]} name = "semver" version = "2.13.0" description = "Python helper for Semantic Versioning (http://semver.org/)" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -4463,7 +4288,6 @@ files = [ name = "setuptools" version = "68.2.2" description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4480,7 +4304,6 @@ testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jar name = "simple-salesforce" version = "1.12.5" description = "A basic Salesforce.com REST API client." -category = "main" optional = false python-versions = "*" files = [ @@ -4500,7 +4323,6 @@ zeep = "*" name = "simplejson" version = "3.19.1" description = "Simple, fast, extensible JSON encoder/decoder for Python" -category = "main" optional = false python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -4595,7 +4417,6 @@ files = [ name = "six" version = "1.16.0" description = "Python 2 and 3 compatibility utilities" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ @@ -4607,7 +4428,6 @@ files = [ name = "smartsheet-python-sdk" version = "3.0.2" description = "Library that uses Python to connect to Smartsheet services (using API 2.0)." -category = "main" optional = false python-versions = "*" files = [ @@ -4630,7 +4450,6 @@ test = ["coverage", "coveralls", "pytest"] name = "sniffio" version = "1.3.0" description = "Sniff out which async library your code is running under" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4642,7 +4461,6 @@ files = [ name = "sortedcontainers" version = "2.4.0" description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -category = "main" optional = false python-versions = "*" files = [ @@ -4654,7 +4472,6 @@ files = [ name = "soupsieve" version = "2.5" description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4666,7 +4483,6 @@ files = [ name = "stack-data" version = "0.6.2" description = "Extract data from python stack frames and tracebacks for informative displays" -category = "main" optional = false python-versions = "*" files = [ @@ -4686,7 +4502,6 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] name = "stevedore" version = "5.1.0" description = "Manage dynamic plugins for Python applications" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4701,7 +4516,6 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0" name = "stringcase" version = "1.2.0" description = "String case converter." -category = "main" optional = false python-versions = "*" files = [ @@ -4712,7 +4526,6 @@ files = [ name = "strip-hints" version = "0.1.10" description = "Function and command-line program to strip Python type hints." -category = "main" optional = false python-versions = "*" files = [ @@ -4726,7 +4539,6 @@ wheel = "*" name = "tabulate" version = "0.9.0" description = "Pretty-print tabular data" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4741,7 +4553,6 @@ widechars = ["wcwidth"] name = "tenacity" version = "8.2.3" description = "Retry code until it succeeds" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4756,7 +4567,6 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] name = "termcolor" version = "2.3.0" description = "ANSI color formatting for output in terminal" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4771,7 +4581,6 @@ tests = ["pytest", "pytest-cov"] name = "tomli" version = "2.0.1" description = "A lil' TOML parser" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4783,7 +4592,6 @@ files = [ name = "traitlets" version = "5.10.1" description = "Traitlets Python configuration system" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4799,7 +4607,6 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.5.1)", "pre-commit", "pytest (>=7.0, name = "trio" version = "0.22.2" description = "A friendly Python library for async concurrency and I/O" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4820,7 +4627,6 @@ sortedcontainers = "*" name = "trio-websocket" version = "0.10.4" description = "WebSocket library for Trio" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4837,7 +4643,6 @@ wsproto = ">=0.14" name = "tweepy" version = "3.10.0" description = "Twitter library for Python" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ @@ -4858,7 +4663,6 @@ test = ["mock (>=1.0.1)", "nose (>=1.3.3)", "vcrpy (>=1.10.3)"] name = "typer" version = "0.9.0" description = "Typer, build great CLIs. Easy to code. Based on Python type hints." -category = "main" optional = false python-versions = ">=3.6" files = [ @@ -4880,7 +4684,6 @@ test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6. name = "typing-extensions" version = "4.8.0" description = "Backported and Experimental Type Hints for Python 3.8+" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -4892,7 +4695,6 @@ files = [ name = "tzdata" version = "2023.3" description = "Provider of IANA time zone data" -category = "main" optional = false python-versions = ">=2" files = [ @@ -4904,7 +4706,6 @@ files = [ name = "tzlocal" version = "4.3.1" description = "tzinfo object for the local timezone" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -4924,11 +4725,11 @@ devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pyte name = "uiautomation" version = "2.0.18" description = "Python UIAutomation for Windows" -category = "main" optional = false python-versions = "*" files = [ {file = "uiautomation-2.0.18-py3-none-any.whl", hash = "sha256:19b2e03d7f94acf89c2f4dedf29d88e0befb2cb3ce9862039f7c548cb0a4de43"}, + {file = "uiautomation-2.0.18.tar.gz", hash = "sha256:1e891d7a1d3e913e25b3cfed9d03f0a4f91ed2e80b827d9ea85141a679ef9ada"}, ] [package.dependencies] @@ -4938,7 +4739,6 @@ comtypes = ">=1.1.10" name = "uritemplate" version = "3.0.1" description = "URI templates" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" files = [ @@ -4950,7 +4750,6 @@ files = [ name = "urllib3" version = "1.26.16" description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -4970,7 +4769,6 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] name = "validators" version = "0.20.0" description = "Python Data Validation for Humans™." -category = "main" optional = false python-versions = ">=3.4" files = [ @@ -4987,7 +4785,6 @@ test = ["flake8 (>=2.4.0)", "isort (>=4.2.2)", "pytest (>=2.2.3)"] name = "virtualenv" version = "20.24.1" description = "Virtual Python Environment builder" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5008,7 +4805,6 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess name = "wcwidth" version = "0.2.6" description = "Measures the displayed width of unicode strings in a terminal" -category = "main" optional = false python-versions = "*" files = [ @@ -5020,7 +4816,6 @@ files = [ name = "webdriver-manager" version = "4.0.0" description = "Library provides the way to automatically manage drivers for different browsers" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5037,7 +4832,6 @@ requests = "*" name = "websocket-client" version = "1.6.3" description = "WebSocket client for Python with low level API options" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -5054,7 +4848,6 @@ test = ["websockets"] name = "wheel" version = "0.41.2" description = "A built-package format for Python" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5069,7 +4862,6 @@ test = ["pytest (>=6.0.0)", "setuptools (>=65)"] name = "wrapt" version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." -category = "main" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ @@ -5154,7 +4946,6 @@ files = [ name = "wsproto" version = "1.2.0" description = "WebSockets state-machine based protocol implementation" -category = "main" optional = false python-versions = ">=3.7.0" files = [ @@ -5169,7 +4960,6 @@ h11 = ">=0.9.0,<1" name = "xlrd" version = "2.0.1" description = "Library for developers to extract data from Microsoft Excel (tm) .xls spreadsheet files" -category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ @@ -5186,7 +4976,6 @@ test = ["pytest", "pytest-cov"] name = "xlutils" version = "2.0.0" description = "Utilities for working with Excel files that require both xlrd and xlwt" -category = "main" optional = false python-versions = "*" files = [ @@ -5206,7 +4995,6 @@ test = ["coveralls", "errorhandler", "manuel", "mock", "nose", "nose-cov", "nose name = "xlwt" version = "1.3.0" description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+" -category = "main" optional = false python-versions = "*" files = [ @@ -5218,7 +5006,6 @@ files = [ name = "zeep" version = "4.2.1" description = "A Python SOAP client" -category = "main" optional = false python-versions = ">=3.7" files = [ @@ -5246,7 +5033,6 @@ xmlsec = ["xmlsec (>=0.6.1)"] name = "zipp" version = "3.17.0" description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" optional = false python-versions = ">=3.8" files = [ @@ -5261,4 +5047,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.8.1" -content-hash = "c02246c966ef5dd35eeea923e456a07c07c656f3b0bdbb0d2c090696e1c3fc87" +content-hash = "137a7000354cc3d046532c81896fecb73820acd4b55a82f0f48c6980eece8111" diff --git a/pyproject.toml b/pyproject.toml index cf7ce1976..c6b249440 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,129 @@ robotframework-lsp = ">=1.11.0" robotframework-robocop = "^4.1.0" robotframework-tidy = "^4.5.0" black = ">20.0.0" +ruff = "0.1.11" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" + +[tool.ruff] +target-version = "py38" + +# https://docs.astral.sh/ruff/rules +[tool.ruff.lint] +preview = true +select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "COM", # flake8-commas + "E", "W", # pycodestyle errors/warnings + "F", # Pyflakes + "FA", # flake8-future-annotations + "FLY", # flynt + "G", # flake8-logging-format + "I", # isort + "INP", # flake8-no-pep420 + "INT", # flake8-gettext + "ISC", # flake8-implicit-str-concat + "ISC", # implicit string concatenation + "N", # pep8-naming + "NPY002", # numpy-legacy-random + "PERF", # Perflint + "PGH", # pygrep-hooks + "PIE", # misc lints + "PL", # pylint + "PL", # pylint + "PYI", # flake8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RUF", # Ruff-specific + "S102", # flake8-bandit: exec-builtin + "T10", # flake8-debugger + "TCH", # type-checking imports + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "YTT", # flake8-2020 +] +ignore = [ + # intentionally disabled + "E203", # space before : (needed for how black formats slicing) + # various limits and unimportant warnings + "E501", # Line too long + "E741", # Ambiguous variable name: `l` + "PLR0904", # Too many public methods (56 > 20) + "PLR0912", # Too many branches + "PLR0913", # Too many arguments in function definition (6 > 5) + "PLR0915", # Too many statements + "PLR0917", # Too many positional arguments (10/5) + "PLR0917", # Too many positional arguments (7/5) + "PLR2004", # Magic value used in comparison + # "W503", # not yet implemented; line break before binary operator + # "W504", # not yet implemented; line break after binary operator + # TODO + "B006", # Do not use mutable data structures for argument defaults + "B007", # Loop control variable `retry` not used within loop body + "COM812", # Trailing comma missing + "F841", # Local variable `response` is assigned to but never used + "FA100", # Missing `from __future__ import annotations`, but uses `typing.Optional` + "I001", # Import block is un-sorted or un-formatted + "INP001", # File `ods_ci/tests/Resources/Page/ODH/JupyterHub/jupyter-helper.py` is part of an implicit namespace package. Add an `__init__.py`. + "ISC001", # Implicitly concatenated string literals on one line + "N806", # Variable `outputText` in function should be lowercase + "N813", # Camelcase `ElementTree` imported as lowercase `et` + "N816", # Variable `rotatingHandler` in global scope should not be mixedCase + "N999", # Invalid module name: 'createPolarionTestRun' + "PERF401", # Use a list comprehension to create a transformed list + "PLC0415", # `import` should be at the top-level of a file + "PLC1901", # `filter_value != ""` can be simplified to `filter_value` as an empty string is falsey + "PLR5501", # Use `elif` instead of `else` then `if`, to reduce indentation + "PLR6201", # Use a `set` literal when testing for membership + "PLR6301", # Method `_render_template` could be a function, class method, or static method + "PLW1514", # `codecs.open` in text mode without explicit `encoding` argument + "PLW2901", # `for` loop variable `tag_it` overwritten by assignment target + "Q000", # Single quotes found but double quotes preferred + "RET501", # Do not explicitly `return None` in function if it is the only possible return value + "RET503", # Missing explicit `return` at the end of function able to return non-`None` value + "RET504", # Unnecessary assignment to `names` before `return` statement + "RET505", # Unnecessary `else` after `return` statement + "UP015", # Unnecessary open mode parameters + "UP031", # format specifiers instead of percent format + "UP032", # Use f-string instead of `format` call + "UP034", # Avoid extraneous parentheses + "W605", # Invalid escape sequence: `\d` + # TODO(jdanek) + "C416", # Unnecessary `list` comprehension (rewrite using `list()`) + "E117", # Over-indented + "E231", # Missing whitespace after ',' + "E401", # Multiple imports on one line + "E402", # Module level import not at top of file + "E711", # Comparison to `None` should be `cond is not None` + "E712", # Comparison to `True` should be `cond is True` or `if cond:` + "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks + "E722", # Do not use bare `except` + "F401", # `re` imported but unused + "F403", # `from python_terraform import *` used; unable to detect undefined names + "F405", # `IsNotFlagged` may be undefined, or defined from star imports + "F541", # f-string without any placeholders + "F811", # Redefinition of unused `hide_values_in_op_json` from line 565 + "F821", # Undefined name `os` + "PIE790", # Unnecessary `pass` statement + "PLR1714", # Consider merging multiple comparisons. Use a `set` if the elements are hashable. + "Q004", # Unnecessary escape on inner quote character + "RET507", # Unnecessary `else` after `continue` statement + "RET508", # Unnecessary `elif` after `break` statement + "W292", # No newline at end of file + "W293", # Blank line contains whitespace +] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.format] +line-ending = "lf" +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false + +docstring-code-format = true +docstring-code-line-length = "dynamic" From 5c46a88a3a190aa53b6fcee72cdc8eb3d42fa4ee Mon Sep 17 00:00:00 2001 From: tarukumar <93319437+tarukumar@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:39:15 +0530 Subject: [PATCH 04/31] Add support to validate gpu Operator pod (#1090) Signed-off-by: Tarun Kumar --- .../Resources/Provisioning/GPU/gpu_deploy.sh | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh index 655d5db14..7c213a33e 100755 --- a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh +++ b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh @@ -11,26 +11,35 @@ sed -i -e "0,/v1.11/s//$CHANNEL/g" -e "s/gpu-operator-certified.v1.11.0/$CSVNAME oc apply -f ${GPU_INSTALL_DIR}/gpu_install.yaml -function wait_until_gpu_pods_are_running() { +function wait_until_pod_ready_status() { local timeout_seconds=1200 local sleep_time=90 + local pod_label=$1 + local namespace=nvidia-gpu-operator echo "Waiting until gpu pods are in running state..." SECONDS=0 while [ "$SECONDS" -le "$timeout_seconds" ]; do - pod_status=$(oc get pods -n "nvidia-gpu-operator" | grep gpu-operator | awk 'NR == 1 { print $3 }') - if [ "$pod_status" == "Running" ]; then - break + pod_status=$(oc get pods -lapp=$pod_label -n $namespace -ojsonpath='{range .items[*]}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' 2>/dev/null || echo "terminated") + if [ "$pod_status" == "True" ]; then + pod_terminating_status=$(oc get pods -lapp=$pod_label -n $namespace -o jsonpath='{.items[0].metadata.deletionGracePeriodSeconds}' 2>/dev/null || echo "terminated") + if [ "${pod_terminating_status}" != "" ]; then + echo "pod $pod_label is in terminating state..." + else + echo "Pod $pod_label is ready" + break; + fi else ((remaining_seconds = timeout_seconds - SECONDS)) echo "GPU installation seems to be still running (timeout in $remaining_seconds seconds)..." + oc get pods -n $namespace sleep $sleep_time fi done - if [ "$pod_status" == "Running" ]; then + if [ "$pod_status" == "True" ] ; then printf "GPU operator is up and running\n" return 0 else @@ -63,10 +72,15 @@ function rerun_accelerator_migration() { } -wait_until_gpu_pods_are_running +wait_until_pod_ready_status "gpu-operator" oc apply -f ${GPU_INSTALL_DIR}/nfd_deploy.yaml oc get csv -n nvidia-gpu-operator $CSVNAME -ojsonpath={.metadata.annotations.alm-examples} | jq .[0] > clusterpolicy.json oc apply -f clusterpolicy.json +wait_until_pod_ready_status "nvidia-device-plugin-daemonset" +wait_until_pod_ready_status "nvidia-container-toolkit-daemonset" +wait_until_pod_ready_status "nvidia-dcgm-exporter" +wait_until_pod_ready_status "gpu-feature-discovery" +wait_until_pod_ready_status "nvidia-operator-validator" rerun_accelerator_migration From 577993a4b5cd1f5e21887c234cc6fe59b746416b Mon Sep 17 00:00:00 2001 From: tarukumar <93319437+tarukumar@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:32:41 +0530 Subject: [PATCH 05/31] Add missing taint for gpu node (#1091) --- .../tasks/Resources/Provisioning/Hive/AWS/provision-gpu.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/provision-gpu.sh b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/provision-gpu.sh index ca898fbca..8455ff405 100755 --- a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/provision-gpu.sh +++ b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/provision-gpu.sh @@ -21,17 +21,18 @@ oc get -o json -n openshift-machine-api $SOURCE_MACHINESET | jq -r > /tmp/sourc OLD_MACHINESET_NAME=$(jq '.metadata.name' -r /tmp/source-machineset.json ) NEW_MACHINESET_NAME=${OLD_MACHINESET_NAME/worker/gpu} + # Change instanceType and delete some stuff -jq -r ".spec.template.spec.providerSpec.value.instanceType = \"$INSTANCE_TYPE\" +jq -r --arg INSTANCE_TYPE "$INSTANCE_TYPE" '.spec.template.spec.providerSpec.value.instanceType=$INSTANCE_TYPE | del(.metadata.selfLink) | del(.metadata.uid) | del(.metadata.creationTimestamp) | del(.metadata.resourceVersion) - " /tmp/source-machineset.json > /tmp/gpu-machineset.json + | .spec.template.spec.taints += [{"effect": "NoSchedule" , "key": "nvidia.com/gpu" , "value": "None"}] +' /tmp/source-machineset.json > /tmp/gpu-machineset.json # Change machineset name sed -i "s/$OLD_MACHINESET_NAME/$NEW_MACHINESET_NAME/g" /tmp/gpu-machineset.json - # Create new machineset oc apply -f /tmp/gpu-machineset.json rm /tmp/source-machineset.json From ebfe0c8999c0bf1e1ada462f8d48f98204078aa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Wed, 3 Jan 2024 11:34:25 +0100 Subject: [PATCH 06/31] RHOAIENG-1179 Verify user can create a workbench with an existing data connection --- .../Workbenches.resource | 25 +++++++++++++++++++ .../415__ods_dashboard_projects.robot | 22 ++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource index 05ea69a73..e37d9055f 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource @@ -24,6 +24,8 @@ ${WORKBENCH_SIZE_ITEM_BTN_XP}= xpath=//ul[@data-id="container-size-sel ${WORKBENCH_GPU_MENU_BTN_XP}= xpath=//section[@id="deployment-size"]//button[contains(@aria-labelledby,"gpu-numbers")] # robocop: disable ${WORKBENCH_GPU_ITEM_BTN_XP}= xpath=//ul[@data-id="gpu-select"]/li/button ${WORKBENCH_ADD_VAR_BTN_XP}= xpath=//button[text()="Add variable"] +${WORKBENCH_USE_CONNECTION_CHK_XP}= xpath=//input[@name="enable-data-connection-checkbox"] +${WORKBENCH_EXISTING_CONNECTION_RAD_XP}= xpath=//input[@name="existing-data-connection-type-radio"] ${WORKBENCH_STATUS_STOPPED}= Stopped ${WORKBENCH_STATUS_RUNNING}= Running ${WORKBENCH_STATUS_STARTING}= Starting... @@ -36,6 +38,7 @@ ${WORKBENCH_IMAGE_VER_DROPDOWN}= ${WORKBENCH_IMAGE_VER_BUTTON}/../ul[@id="wo ${KEYVALUE_TYPE}= Key / value ${UPLOAD_TYPE}= Upload ${ENV_VARIABLES_SECTION_XP}= xpath=//section[@aria-label="Environment variables"] +${ENV_DATA_CONNECTION_SECTION_XP}= xpath=//section[@aria-label="Data connections"] ${ERROR_ICON_XP}= span[contains(@class,'pf-m-danger')] @@ -47,6 +50,7 @@ Create Workbench [Arguments] ${workbench_title} ${workbench_description} ${prj_title} ${image_name} ${deployment_size} ... ${storage} ${pv_existent} ${pv_name} ${pv_description} ${pv_size} ${gpus}=${NONE} ... ${press_cancel}=${FALSE} ${version}=default ${envs}=${NONE} + ... ${data_connection}=${NONE} Click Element ${WORKBENCH_CREATE_BTN_XP} Wait Until Page Contains Element ${WORKBENCH_NAME_INPUT_XP} Run Keyword And Continue On Failure Element Should Be Disabled ${WORKBENCH_CREATE_BTN_2_XP} @@ -60,6 +64,9 @@ Create Workbench ${envs_copy}= Copy List ${envs} deepcopy=${TRUE} Add Environment Variables In Workbench env_variables=${envs_copy} END + IF "${data_connection} != ${NONE}" + Add Existing Data Connection In Workbench data_connection=${data_connection} + END ${version_check}= Is RHODS Version Greater Or Equal Than 1.20.0 IF ${version_check}==True Run Keyword And Continue On Failure Page Should Not Contain Element @@ -139,6 +146,24 @@ Add Environment Variables In Workbench END END +Add Existing Data Connection In Workbench + [Documentation] Adds the data connection through the workbench creation page + [Arguments] ${data_connection} + # Use the `Jump to section` links in the page to scroll the section into view + Click Element //a[@href="#data-connections"] + Click Element ${WORKBENCH_USE_CONNECTION_CHK_XP} + # Use the `Jump to section` again to move the expanded form into view + Click Element //a[@href="#data-connections"] + Click Element ${WORKBENCH_EXISTING_CONNECTION_RAD_XP} + Select Existing Data Connection data_connection=${data_connection} + +Select Existing Data Connection + [Documentation] Selects the existing data connection in the workbench creation page from a dropdown list + [Arguments] ${data_connection} + Click Element ${ENV_DATA_CONNECTION_SECTION_XP}//div[contains(@class,"pf-c-select")]/button + Wait Until Page Contains Element xpath=//ul[@role="listbox"]/li/button[text()="${data_connection}"] + Click Element xpath=//ul[@role="listbox"]/li/button[text()="${data_connection}"] + Select Environment Variable Types [Documentation] Selects the type of environment variable in the workbench creation page: Secret vs Config Map [Arguments] ${k8s_type} ${input_type} ${variable_index} diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot index 39b66ce92..549a52e26 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot @@ -253,6 +253,28 @@ Verify User Can Delete A Data Connection Data Connection Should Not Be Listed name=${DC_3_S3_NAME} Check Data Connection Secret Is Deleted dc_name=${DC_3_S3_NAME} namespace=${ns_name} +Verify user can create a workbench with an existing data connection + [Tags] Tier1 ODS-2176 + [Documentation] Verifies users can create a workbench with an existing data connection + + Open Data Science Project Details Page project_title=${PRJ_TITLE} + Create S3 Data Connection project_title=${PRJ_TITLE} + ... dc_name=${DC_S3_NAME} + ... aws_access_key=dummy-key + ... aws_secret_access=dummy-secret + ... aws_s3_endpoint=${DC_S3_ENDPOINT} + ... aws_region=${DC_S3_REGION} + Create Workbench workbench_title=${WORKBENCH_TITLE} workbench_description=${WORKBENCH_DESCRIPTION} + ... prj_title=${PRJ_TITLE} image_name=${NB_IMAGE} deployment_size=Small + ... storage=Persistent pv_existent=${NONE} pv_name=${NONE} pv_description=${NONE} pv_size=${NONE} + ... data_connection=${DC_S3_NAME} + + # The Workbench and the Data connection appear on the project details page. + Workbench Should Be Listed workbench_title=${WORKBENCH_TITLE} + # The data connection has the workbench name in the "Connected workbenches" column + ${workbenches}= Create Dictionary ${WORKBENCH_TITLE}=mount-data + Data Connection Should Be Listed name=${DC_S3_NAME} type=${DC_S3_TYPE} connected_workbench=${workbenches} + Verify User Can Create A Workbench With Environment Variables [Tags] Sanity Tier1 ODS-1864 [Documentation] Verifies users can create a workbench and inject environment variables during creation From 811dd91196bc79c54f3389e247e64f8404c4543e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Thu, 4 Jan 2024 10:26:32 +0100 Subject: [PATCH 07/31] fixup review comment if condition --- .../ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource index e37d9055f..bd148b9a8 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource @@ -64,7 +64,7 @@ Create Workbench ${envs_copy}= Copy List ${envs} deepcopy=${TRUE} Add Environment Variables In Workbench env_variables=${envs_copy} END - IF "${data_connection} != ${NONE}" + IF "${data_connection}" != "${NONE}" Add Existing Data Connection In Workbench data_connection=${data_connection} END ${version_check}= Is RHODS Version Greater Or Equal Than 1.20.0 From 72b1f143c210a9e8c58fd7dd42f0dfaf98fa594b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Thu, 4 Jan 2024 10:30:09 +0100 Subject: [PATCH 08/31] fixup review comment rename data connection --- .../415__ods_dashboard_projects.robot | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot index 549a52e26..b695aea5f 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot @@ -257,9 +257,11 @@ Verify user can create a workbench with an existing data connection [Tags] Tier1 ODS-2176 [Documentation] Verifies users can create a workbench with an existing data connection + ${data_connection_name}= Set Variable aDataConnection + Open Data Science Project Details Page project_title=${PRJ_TITLE} Create S3 Data Connection project_title=${PRJ_TITLE} - ... dc_name=${DC_S3_NAME} + ... dc_name=${data_connection_name} ... aws_access_key=dummy-key ... aws_secret_access=dummy-secret ... aws_s3_endpoint=${DC_S3_ENDPOINT} @@ -267,13 +269,14 @@ Verify user can create a workbench with an existing data connection Create Workbench workbench_title=${WORKBENCH_TITLE} workbench_description=${WORKBENCH_DESCRIPTION} ... prj_title=${PRJ_TITLE} image_name=${NB_IMAGE} deployment_size=Small ... storage=Persistent pv_existent=${NONE} pv_name=${NONE} pv_description=${NONE} pv_size=${NONE} - ... data_connection=${DC_S3_NAME} + ... data_connection=${data_connection_name} # The Workbench and the Data connection appear on the project details page. Workbench Should Be Listed workbench_title=${WORKBENCH_TITLE} # The data connection has the workbench name in the "Connected workbenches" column ${workbenches}= Create Dictionary ${WORKBENCH_TITLE}=mount-data - Data Connection Should Be Listed name=${DC_S3_NAME} type=${DC_S3_TYPE} connected_workbench=${workbenches} + Data Connection Should Be Listed name=${data_connection_name} type=${DC_S3_TYPE} + ... connected_workbench=${workbenches} Verify User Can Create A Workbench With Environment Variables [Tags] Sanity Tier1 ODS-1864 From 8297c4a98145e66dc0a44772abf7cca293cab597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Thu, 4 Jan 2024 12:31:37 +0100 Subject: [PATCH 09/31] fixup review comment add teardown --- .../415__ods_dashboard_projects.robot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot index b695aea5f..477741fc6 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot @@ -278,6 +278,9 @@ Verify user can create a workbench with an existing data connection Data Connection Should Be Listed name=${data_connection_name} type=${DC_S3_TYPE} ... connected_workbench=${workbenches} + [Teardown] Clean Project From Workbench Resources workbench_title=${WORKBENCH_TITLE} + ... project_title=${PRJ_TITLE} + Verify User Can Create A Workbench With Environment Variables [Tags] Sanity Tier1 ODS-1864 [Documentation] Verifies users can create a workbench and inject environment variables during creation From 8c47be393c023a4a07c629a511b302a674700b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Sat, 6 Jan 2024 17:24:09 +0100 Subject: [PATCH 10/31] Fix various Python lint warnings using ruff auto-fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` poetry run ruff ods_ci/ --unsafe-fixes --fix poetry run black $(git diff --name-only | grep '.py$') poetry run isort $(git diff --name-only | grep '.py$') ``` Besides running ruff, it is necessary to placate black and isort in the affected files using the commands above. Config for isort had to be added, so it converges with the black's ideas about formatting import blocks. Signed-off-by: Jiri Daněk --- ods_ci/libs/DataSciencePipelinesAPI.py | 38 ++++--- ods_ci/libs/DataSciencePipelinesKfpTekton.py | 40 +++---- ods_ci/libs/Helpers.py | 13 ++- .../Files/pipeline-samples/flip_coin.py | 1 + .../Files/pipeline-samples/ray_integration.py | 56 +++++----- .../Files/pipeline-samples/upload_download.py | 44 +++++--- ods_ci/utils/scripts/SplitSuite.py | 4 +- ods_ci/utils/scripts/awsOps.py | 5 +- ods_ci/utils/scripts/ocm/ocm.py | 105 +++++++++++------- .../scripts/polarion/xunit_add_properties.py | 5 +- .../utils/scripts/reportportal/rp_uploader.py | 2 +- ods_ci/utils/scripts/rosa/rosa.py | 8 +- ods_ci/utils/scripts/rosa/rosaOps.py | 15 ++- .../testconfig/generateTestConfigFile.py | 22 ++-- ods_ci/utils/scripts/util.py | 42 ++++--- pyproject.toml | 21 +--- 16 files changed, 232 insertions(+), 189 deletions(-) diff --git a/ods_ci/libs/DataSciencePipelinesAPI.py b/ods_ci/libs/DataSciencePipelinesAPI.py index 75f9aa6b0..c42031ca3 100644 --- a/ods_ci/libs/DataSciencePipelinesAPI.py +++ b/ods_ci/libs/DataSciencePipelinesAPI.py @@ -25,7 +25,7 @@ def wait_until_openshift_pipelines_operator_is_deployed(self): while deployment_count != 1 and count < 30: deployments = [] response, _ = self.run_oc( - f"oc get deployment -n openshift-operators openshift-pipelines-operator -o json" + "oc get deployment -n openshift-operators openshift-pipelines-operator -o json" ) try: response = json.loads(response) @@ -45,12 +45,14 @@ def wait_until_openshift_pipelines_operator_is_deployed(self): while pipeline_run_crd_count < 1 and count < 60: # https://github.com/opendatahub-io/odh-dashboard/issues/1673 # It is possible to start the Pipeline Server without pipelineruns.tekton.dev CRD - pipeline_run_crd_count = self.count_pods("oc get crd pipelineruns.tekton.dev", 1) + pipeline_run_crd_count = self.count_pods( + "oc get crd pipelineruns.tekton.dev", 1 + ) time.sleep(1) count += 1 assert pipeline_run_crd_count == 1 return self.count_running_pods( - f"oc get pods -n openshift-operators -l name=openshift-pipelines-operator -o json", + "oc get pods -n openshift-operators -l name=openshift-pipelines-operator -o json", "openshift-pipelines-operator", "Running", 1, @@ -92,7 +94,9 @@ def login_and_wait_dsp_route( count += 1 assert self.route != "", "Route must not be empty" - print(f"Waiting for Data Science Pipeline route to be ready to avoid firing false alerts: {self.route}") + print( + f"Waiting for Data Science Pipeline route to be ready to avoid firing false alerts: {self.route}" + ) time.sleep(45) status = -1 count = 0 @@ -195,12 +199,11 @@ def check_run_status(self, run_id, timeout=160): run_status = run_json["run"]["status"] except JSONDecodeError: print(response, status) - pass print(f"Checking run status: {run_status}") - if run_status == 'Failed': + if run_status == "Failed": break # https://github.com/tektoncd/pipeline/blob/main/docs/pipelineruns.md#monitoring-execution-status - if run_status == "Completed" or run_status == "Succeeded": + if run_status in ("Completed", "Succeeded"): run_finished_ok = True break time.sleep(1) @@ -255,13 +258,13 @@ def do_http_request(self, url): return response.url def count_pods(self, oc_command, pod_criteria, timeout=30): - oc_command = f'{oc_command} --no-headers' + oc_command = f"{oc_command} --no-headers" pod_count = 0 count = 0 while pod_count != pod_criteria and count < timeout: bash_str, _ = self.run_oc(oc_command) # | wc -l is returning an empty string - pod_count = sum(1 for line in bash_str.split('\n') if line.strip()) + pod_count = sum(1 for line in bash_str.split("\n") if line.strip()) if pod_count >= pod_criteria: break time.sleep(1) @@ -304,17 +307,22 @@ def retrieve_auth_url(self): def get_default_storage(self): result, _ = self.run_oc("oc get storageclass -A -o json") result = json.loads(result) - for storage_class in result['items']: - if 'annotations' in storage_class['metadata']: - if storage_class['metadata']['annotations']['storageclass.kubernetes.io/is-default-class'] == 'true': + for storage_class in result["items"]: + if "annotations" in storage_class["metadata"]: + if ( + storage_class["metadata"]["annotations"][ + "storageclass.kubernetes.io/is-default-class" + ] + == "true" + ): break - return storage_class['metadata']['name'] + return storage_class["metadata"]["name"] def get_openshift_server(self): - return self.run_oc('oc whoami --show-server=true')[0].replace('\n', '') + return self.run_oc("oc whoami --show-server=true")[0].replace("\n", "") def get_openshift_token(self): - return self.run_oc('oc whoami --show-token=true')[0].replace('\n', '') + return self.run_oc("oc whoami --show-token=true")[0].replace("\n", "") def run_oc(self, command): process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) diff --git a/ods_ci/libs/DataSciencePipelinesKfpTekton.py b/ods_ci/libs/DataSciencePipelinesKfpTekton.py index 2c68db9f3..70d469c03 100644 --- a/ods_ci/libs/DataSciencePipelinesKfpTekton.py +++ b/ods_ci/libs/DataSciencePipelinesKfpTekton.py @@ -3,14 +3,14 @@ import json import os import sys + from DataSciencePipelinesAPI import DataSciencePipelinesAPI from robotlibcore import keyword from urllib3.exceptions import MaxRetryError, SSLError class DataSciencePipelinesKfpTekton: - - base_image = 'registry.redhat.io/ubi8/python-39@sha256:3523b184212e1f2243e76d8094ab52b01ea3015471471290d011625e1763af61' + base_image = "registry.redhat.io/ubi8/python-39@sha256:3523b184212e1f2243e76d8094ab52b01ea3015471471290d011625e1763af61" # init should not have a call to external system, otherwise dry-run will fail def __init__(self): @@ -30,7 +30,7 @@ def get_client(self, user, pwd, project, route_name): os.environ["TEKTON_COPY_RESULTS_STEP_IMAGE"] = default_image os.environ["CONDITION_IMAGE_NAME"] = default_image # https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes - os.environ["DEFAULT_ACCESSMODES"] = 'ReadWriteOnce' + os.environ["DEFAULT_ACCESSMODES"] = "ReadWriteOnce" import kfp_tekton # the following fallback it is to simplify the test development @@ -53,7 +53,7 @@ def get_client(self, user, pwd, project, route_name): return self.client, self.api def get_cert(self, api): - cert_json = self.get_secret(api, 'openshift-ingress-operator', 'router-ca') + cert_json = self.get_secret(api, "openshift-ingress-operator", "router-ca") cert = cert_json["data"]["tls.crt"] decoded_cert = base64.b64decode(cert).decode("utf-8") @@ -64,20 +64,18 @@ def get_cert(self, api): return file_name def get_secret(self, api, project, name): - secret_json, _ = api.run_oc( - f"oc get secret -n {project} {name} -o json" - ) + secret_json, _ = api.run_oc(f"oc get secret -n {project} {name} -o json") return json.loads(secret_json) def get_bucket_name(self, api, project): bucket_name, _ = api.run_oc( f"oc get dspa -n {project} pipelines-definition -o json" ) - objectStorage = json.loads(bucket_name)['spec']['objectStorage'] - if 'minio' in objectStorage: - return objectStorage['minio']['bucket'] + objectStorage = json.loads(bucket_name)["spec"]["objectStorage"] + if "minio" in objectStorage: + return objectStorage["minio"]["bucket"] else: - return objectStorage['externalStorage']['bucket'] + return objectStorage["externalStorage"]["bucket"] def import_souce_code(self, path): module_name = os.path.basename(path).replace("-", "_") @@ -94,7 +92,9 @@ def kfp_tekton_create_run_from_pipeline_func( self, user, pwd, project, route_name, source_code, fn, current_path=None ): client, api = self.get_client(user, pwd, project, route_name) - mlpipeline_minio_artifact_secret = self.get_secret(api, project, 'mlpipeline-minio-artifact') + mlpipeline_minio_artifact_secret = self.get_secret( + api, project, "mlpipeline-minio-artifact" + ) bucket_name = self.get_bucket_name(api, project) # the current path is from where you are running the script # sh ods_ci/run_robot_test.sh @@ -109,12 +109,15 @@ def kfp_tekton_create_run_from_pipeline_func( # create_run_from_pipeline_func will compile the code # if you need to see the yaml, for debugging purpose, call: TektonCompiler().compile(pipeline, f'{fn}.yaml') result = client.create_run_from_pipeline_func( - pipeline_func=pipeline, arguments={ - 'mlpipeline_minio_artifact_secret': mlpipeline_minio_artifact_secret["data"], - 'bucket_name': bucket_name, - 'openshift_server': self.api.get_openshift_server(), - 'openshift_token': self.api.get_openshift_token() - } + pipeline_func=pipeline, + arguments={ + "mlpipeline_minio_artifact_secret": mlpipeline_minio_artifact_secret[ + "data" + ], + "bucket_name": bucket_name, + "openshift_server": self.api.get_openshift_server(), + "openshift_token": self.api.get_openshift_token(), + }, ) # easy to debug and double check failures print(result) @@ -128,4 +131,3 @@ def kfp_tekton_wait_for_run_completion( ): _, api = self.get_client(user, pwd, project, route_name) return api.check_run_status(run_result.run_id, timeout=timeout) - diff --git a/ods_ci/libs/Helpers.py b/ods_ci/libs/Helpers.py index 3dc78a654..004a94f1e 100644 --- a/ods_ci/libs/Helpers.py +++ b/ods_ci/libs/Helpers.py @@ -1,9 +1,9 @@ from robot.api import logger from robot.libraries.BuiltIn import BuiltIn +from robotlibcore import keyword from semver import VersionInfo from ods_ci.utils.scripts.ocm.ocm import OpenshiftClusterManager -from robotlibcore import keyword class Helpers: @@ -136,7 +136,7 @@ def parse_file_for_tolerations(self, filename): elif line.startswith("Events:"): break else: - if saving == True: + if saving is True: tolerations.append(line.strip()) print(line) print(tolerations) @@ -213,7 +213,7 @@ def _inference_object_comparison(expected, received, threshold): # if element is model name, don't care about ID result_ex = model_name.match(expected) result_rec = model_name.match(received) - if result_ex != None and result_rec != None: + if result_ex is not None and result_rec is not None: if expected.split("__")[0] != received.split("__")[0]: failures.append([expected, received]) # else compare values are equal @@ -245,9 +245,10 @@ def send_random_inference_request( ): import os import random - import requests from pathlib import Path + import requests + for _ in range(no_requests): data_img = [ random.randrange(value_range[0], value_range[1]) @@ -304,11 +305,11 @@ def process_resource_list(self, filename_in, filename_out=None): resource_name = line.split()[1] resource_name = regex.sub(repl="", string=resource_name) out.append(line.split()[0] + " " * spaces + resource_name + "\n") - if filename_out == None: + if filename_out is None: filename_out = filename_in.split(".")[0] + "_processed.txt" with open(filename_out, "w") as outfile: outfile.write("".join(str(l) for l in out)) @keyword def escape_forward_slashes(self, string_to_escape): - return string_to_escape.replace('/','\/') \ No newline at end of file + return string_to_escape.replace("/", "\/") diff --git a/ods_ci/tests/Resources/Files/pipeline-samples/flip_coin.py b/ods_ci/tests/Resources/Files/pipeline-samples/flip_coin.py index 7017b7a01..9729ece7e 100644 --- a/ods_ci/tests/Resources/Files/pipeline-samples/flip_coin.py +++ b/ods_ci/tests/Resources/Files/pipeline-samples/flip_coin.py @@ -14,6 +14,7 @@ # source https://github.com/kubeflow/kfp-tekton/blob/master/samples/flip-coin/condition.py from kfp import components, dsl + from ods_ci.libs.DataSciencePipelinesKfpTekton import DataSciencePipelinesKfpTekton diff --git a/ods_ci/tests/Resources/Files/pipeline-samples/ray_integration.py b/ods_ci/tests/Resources/Files/pipeline-samples/ray_integration.py index 3122e4b83..113cd6fd1 100644 --- a/ods_ci/tests/Resources/Files/pipeline-samples/ray_integration.py +++ b/ods_ci/tests/Resources/Files/pipeline-samples/ray_integration.py @@ -1,44 +1,47 @@ from kfp import components, dsl + from ods_ci.libs.DataSciencePipelinesKfpTekton import DataSciencePipelinesKfpTekton -def ray_fn(openshift_server:str, openshift_token:str) -> int: - from codeflare_sdk.cluster.cluster import Cluster, ClusterConfiguration - from codeflare_sdk.cluster.auth import TokenAuthentication +def ray_fn(openshift_server: str, openshift_token: str) -> int: import ray + from codeflare_sdk.cluster.auth import TokenAuthentication + from codeflare_sdk.cluster.cluster import Cluster, ClusterConfiguration - print('before login') + print("before login") auth = TokenAuthentication( - token=openshift_token, - server=openshift_server, - skip_tls=True + token=openshift_token, server=openshift_server, skip_tls=True ) auth_return = auth.login() print(f'auth_return: "{auth_return}"') - print('after login') - cluster = Cluster(ClusterConfiguration( - name='raytest', - # namespace must exist, and it is the same from 432__data-science-pipelines-tekton.robot - namespace='pipelineskfptekton1', - num_workers=1, - head_cpus='500m', - min_memory=1, - max_memory=1, - num_gpus=0, - image="quay.io/project-codeflare/ray:latest-py39-cu118", - instascale=False - )) + print("after login") + cluster = Cluster( + ClusterConfiguration( + name="raytest", + # namespace must exist, and it is the same from 432__data-science-pipelines-tekton.robot + namespace="pipelineskfptekton1", + num_workers=1, + head_cpus="500m", + min_memory=1, + max_memory=1, + num_gpus=0, + image="quay.io/project-codeflare/ray:latest-py39-cu118", + instascale=False, + ) + ) # workaround for https://github.com/project-codeflare/codeflare-sdk/pull/412 - cluster_file_name = '/opt/app-root/src/.codeflare/appwrapper/raytest.yaml' + cluster_file_name = "/opt/app-root/src/.codeflare/appwrapper/raytest.yaml" # Read in the file - with open(cluster_file_name, 'r') as file: + with open(cluster_file_name, "r") as file: filedata = file.read() # Replace the target string - filedata = filedata.replace('busybox:1.28', 'quay.io/project-codeflare/busybox:latest') + filedata = filedata.replace( + "busybox:1.28", "quay.io/project-codeflare/busybox:latest" + ) # Write the file out again - with open(cluster_file_name, 'w') as file: + with open(cluster_file_name, "w") as file: file.write(filedata) # end workaround @@ -82,7 +85,8 @@ def train_fn(): ) def ray_integration(openshift_server, openshift_token): ray_op = components.create_component_from_func( - ray_fn, base_image=DataSciencePipelinesKfpTekton.base_image, - packages_to_install=['codeflare-sdk'] + ray_fn, + base_image=DataSciencePipelinesKfpTekton.base_image, + packages_to_install=["codeflare-sdk"], ) ray_op(openshift_server, openshift_token) diff --git a/ods_ci/tests/Resources/Files/pipeline-samples/upload_download.py b/ods_ci/tests/Resources/Files/pipeline-samples/upload_download.py index f293b6401..fca7fe171 100644 --- a/ods_ci/tests/Resources/Files/pipeline-samples/upload_download.py +++ b/ods_ci/tests/Resources/Files/pipeline-samples/upload_download.py @@ -1,7 +1,7 @@ """Test pipeline to exercise various data flow mechanisms.""" import kfp -from ods_ci.libs.DataSciencePipelinesKfpTekton import DataSciencePipelinesKfpTekton +from ods_ci.libs.DataSciencePipelinesKfpTekton import DataSciencePipelinesKfpTekton """Producer""" @@ -14,11 +14,13 @@ def send_file( import zipfile def create_large_file(file_path, size_in_bytes): - with open(file_path, 'wb') as f: + with open(file_path, "wb") as f: f.write(os.urandom(size_in_bytes)) def zip_file(input_file_path, output_zip_path): - with zipfile.ZipFile(output_zip_path, 'w', compression=zipfile.ZIP_DEFLATED) as zipf: + with zipfile.ZipFile( + output_zip_path, "w", compression=zipfile.ZIP_DEFLATED + ) as zipf: zipf.write(input_file_path, os.path.basename(input_file_path)) print("starting creating the file...") @@ -49,14 +51,20 @@ def receive_file( shutil.copyfile(incomingfile, saveartifact) -def test_uploaded_artifact(previous_step: kfp.components.InputPath(), file_size_bytes: int, mlpipeline_minio_artifact_secret: str, bucket_name: str): - from minio import Minio +def test_uploaded_artifact( + previous_step: kfp.components.InputPath(), + file_size_bytes: int, + mlpipeline_minio_artifact_secret: str, + bucket_name: str, +): import base64 import json + from minio import Minio + print(previous_step) - name_data = previous_step.split('/') - object_name = 'artifacts/' + name_data[4] + '/receive-file/saveartifact.tgz' + name_data = previous_step.split("/") + object_name = "artifacts/" + name_data[4] + "/receive-file/saveartifact.tgz" mlpipeline_minio_artifact_secret = json.loads(mlpipeline_minio_artifact_secret) @@ -68,16 +76,13 @@ def inner_decode(my_str): access_key = inner_decode(mlpipeline_minio_artifact_secret["accesskey"]) secret_key = inner_decode(mlpipeline_minio_artifact_secret["secretkey"]) secure = inner_decode(mlpipeline_minio_artifact_secret["secure"]) - secure = secure.lower() == 'true' + secure = secure.lower() == "true" client = Minio( - f'{host}:{port}', - access_key=access_key, - secret_key=secret_key, - secure=secure + f"{host}:{port}", access_key=access_key, secret_key=secret_key, secure=secure ) data = client.get_object(bucket_name, object_name) - with open('my-testfile', 'wb') as file_data: + with open("my-testfile", "wb") as file_data: for d in data.stream(32 * 1024): file_data.write(d) bytes_written = file_data.tell() @@ -104,7 +109,7 @@ def inner_decode(my_str): test_uploaded_artifact_op = kfp.components.create_component_from_func( test_uploaded_artifact, base_image=DataSciencePipelinesKfpTekton.base_image, - packages_to_install=['minio'] + packages_to_install=["minio"], ) """Wire up the pipeline""" @@ -123,8 +128,11 @@ def wire_up_pipeline(mlpipeline_minio_artifact_secret, bucket_name): receive_file_task = receive_file_op( send_file_task.output, - ).add_pod_annotation(name='artifact_outputs', value=json.dumps(['saveartifact'])) - - test_uploaded_artifact_op(receive_file_task.output, file_size_bytes, mlpipeline_minio_artifact_secret, bucket_name) - + ).add_pod_annotation(name="artifact_outputs", value=json.dumps(["saveartifact"])) + test_uploaded_artifact_op( + receive_file_task.output, + file_size_bytes, + mlpipeline_minio_artifact_secret, + bucket_name, + ) diff --git a/ods_ci/utils/scripts/SplitSuite.py b/ods_ci/utils/scripts/SplitSuite.py index 456c8f92e..b6347d804 100644 --- a/ods_ci/utils/scripts/SplitSuite.py +++ b/ods_ci/utils/scripts/SplitSuite.py @@ -18,7 +18,7 @@ def chunked(lst, nchunk): def fetch_subsuites(parent): - children = [child for child in parent.suites] + children = list(parent.suites) return children @@ -70,7 +70,7 @@ def visit_suite(self, suite): print("Suites names in the suite: ", suite_names) num_suite = math.ceil(len(sub_suites_list) / self.parts) print("Number of suites per split:", num_suite) - chunked_suites = [i for i in chunked(sub_suites_list, num_suite)] + chunked_suites = list(chunked(sub_suites_list, num_suite)) print("Number of chunked suites: ", len(chunked_suites)) print("Chunked suites: ", chunked_suites) suite_to_execute = chunked_suites[self.which_part - 1] diff --git a/ods_ci/utils/scripts/awsOps.py b/ods_ci/utils/scripts/awsOps.py index f87276e3a..af81862f6 100644 --- a/ods_ci/utils/scripts/awsOps.py +++ b/ods_ci/utils/scripts/awsOps.py @@ -1,9 +1,8 @@ -from util import ( - execute_command, -) from logging import log from time import sleep +from util import execute_command + def aws_configure(aws_access_key_id, aws_secret_access_key, aws_region): """ diff --git a/ods_ci/utils/scripts/ocm/ocm.py b/ods_ci/utils/scripts/ocm/ocm.py index 192f3fcb2..91177af55 100644 --- a/ods_ci/utils/scripts/ocm/ocm.py +++ b/ods_ci/utils/scripts/ocm/ocm.py @@ -18,9 +18,16 @@ dir_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(dir_path + "/../") from logger import log + # fmt: off -from util import (clone_config_repo, compare_dicts, execute_command, - read_data_from_json, read_yaml, write_data_in_json) +from util import ( + clone_config_repo, + compare_dicts, + execute_command, + read_data_from_json, + read_yaml, + write_data_in_json, +) # fmt: on @@ -54,7 +61,7 @@ def __init__(self, args={}): self.region = args.get("region") self.compute_machine_type = args.get("compute_machine_type") self.ocm_cli_binary_url = args.get("ocm_cli_binary_url") - self.ocm_verbose_level = args.get("ocm_verbose_level","0") + self.ocm_verbose_level = args.get("ocm_verbose_level", "0") self.num_users_to_create_per_group = args.get("num_users_to_create_per_group") self.htpasswd_cluster_admin = args.get("htpasswd_cluster_admin") self.htpasswd_cluster_password = args.get("htpasswd_cluster_password") @@ -122,7 +129,7 @@ def ocm_describe(self, filter=""): cmd += " " + filter ret = execute_command(cmd) if ret is None or "Error: Can't retrieve cluster for key" in ret: - log.info("ocm describe for cluster " "{} failed".format(self.cluster_name)) + log.info("ocm describe for cluster {} failed".format(self.cluster_name)) return None return ret @@ -130,9 +137,7 @@ def is_osd_cluster_exists(self): """Checks if cluster exists""" ret = self.ocm_describe() if ret is None: - log.info( - "ocm cluster with name " "{} not exists!".format(self.cluster_name) - ) + log.info("ocm cluster with name {} not exists!".format(self.cluster_name)) return False log.info("ocm cluster with name {} exists!".format(self.cluster_name)) return True @@ -173,7 +178,7 @@ def osd_cluster_create(self): channel_grp = "" if self.channel_group != "": - if (self.channel_group == "stable") or (self.channel_group == "candidate"): + if self.channel_group in ("stable", "candidate"): if version == "": log.error( ( @@ -236,7 +241,9 @@ def osd_cluster_create(self): def get_osd_cluster_id(self): """Gets osd cluster ID""" - cmd = "ocm list clusters -p search=\"name = '{}' or id = '{}'\" --columns id --no-headers".format(self.cluster_name, self.cluster_name) + cmd = "ocm list clusters -p search=\"name = '{}' or id = '{}'\" --columns id --no-headers".format( + self.cluster_name, self.cluster_name + ) ret = execute_command(cmd) if ret is None: log.info( @@ -343,7 +350,7 @@ def wait_for_osd_cluster_to_be_ready(self, timeout=7200): break elif cluster_state == "error": log.info( - "{} is in error state. Hence " "exiting!!".format(self.cluster_name) + "{} is in error state. Hence exiting!!".format(self.cluster_name) ) sys.exit(1) @@ -416,7 +423,7 @@ def check_if_machine_pool_exists(self): """Checks if given machine pool name already exists in cluster""" - cmd = "/bin/ocm list machinepools --cluster {} " "| grep -w {}".format( + cmd = "/bin/ocm list machinepools --cluster {} | grep -w {}".format( self.cluster_name, self.pool_name ) ret = execute_command(cmd) @@ -526,8 +533,10 @@ def uninstall_addon(self, addon_name="managed-odh", exit_on_failure=True): addon_state = self.get_addon_state(addon_name) if addon_state != "not installed": cluster_id = self.get_osd_cluster_id() - cmd = "ocm --v={} delete /api/clusters_mgmt/v1/clusters/{}/addons/" "{}".format( - self.ocm_verbose_level, cluster_id, addon_name + cmd = ( + "ocm --v={} delete /api/clusters_mgmt/v1/clusters/{}/addons/{}".format( + self.ocm_verbose_level, cluster_id, addon_name + ) ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) @@ -604,8 +613,10 @@ def install_addon( output_file = output_filename self._render_template(template_file, output_file, replace_vars) cluster_id = self.get_osd_cluster_id() - cmd = "ocm --v={} post /api/clusters_mgmt/v1/clusters/{}/addons " "--body={}".format( - self.ocm_verbose_level, cluster_id, output_file + cmd = ( + "ocm --v={} post /api/clusters_mgmt/v1/clusters/{}/addons --body={}".format( + self.ocm_verbose_level, cluster_id, output_file + ) ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) @@ -724,9 +735,7 @@ def install_rhoam_addon(self, exit_on_failure=True): log.info("redhat-rhoam-smpt secret found!") else: failure_flags.append(True) - log.info( - "redhat-rhoam-smpt secret " "was not created during installation" - ) + log.info("redhat-rhoam-smpt secret was not created during installation") if exit_on_failure: sys.exit(1) @@ -901,12 +910,14 @@ def create_idp(self): def delete_idp(self): """Deletes Identity Provider""" - cmd = "ocm --v={} delete idp -c {} {}".format(self.ocm_verbose_level, self.cluster_name, self.idp_name) + cmd = "ocm --v={} delete idp -c {} {}".format( + self.ocm_verbose_level, self.cluster_name, self.idp_name + ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) if ret is None: log.info( - "Failed to delete identity provider of " "type {}".format(self.idp_name) + "Failed to delete identity provider of type {}".format(self.idp_name) ) def add_user_to_group(self, user="", group="cluster-admins"): @@ -915,33 +926,29 @@ def add_user_to_group(self, user="", group="cluster-admins"): if user == "": user = self.htpasswd_cluster_admin - if ( - (group == "rhods-admins") - or (group == "rhods-users") - or (group == "rhods-noaccess") - ): + if group in ("rhods-admins", "rhods-users", "rhods-noaccess"): cmd = "oc adm groups add-users {} {}".format(group, user) else: - cmd = "ocm --v={} create user {} --cluster {} " "--group={}".format( + cmd = "ocm --v={} create user {} --cluster {} --group={}".format( self.ocm_verbose_level, user, self.cluster_name, group ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) if ret is None: - log.info("Failed to add user {} to group " "{}".format(user, group)) + log.info("Failed to add user {} to group {}".format(user, group)) def delete_user(self, user="", group="cluster-admins"): """Deletes user""" if user == "": user = self.htpasswd_cluster_admin - cmd = "ocm --v={} delete user {} --cluster {} " "--group={}".format( + cmd = "ocm --v={} delete user {} --cluster {} --group={}".format( self.ocm_verbose_level, user, self.cluster_name, group ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) if ret is None: - log.info("Failed to delete user {} of group " "{}".format(user, group)) + log.info("Failed to delete user {} of group {}".format(user, group)) def create_group(self, group_name): """Creates new group""" @@ -950,7 +957,7 @@ def create_group(self, group_name): log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) if ret is None: - log.info("Failed to add group " "{}".format(group_name)) + log.info("Failed to add group {}".format(group_name)) def add_users_to_rhods_group(self): """Add users to rhods group""" @@ -1024,8 +1031,12 @@ def install_rhods_addon(self): # Install dependency operators for rhoai deployment dependency_operators = ["servicemesh", "serverless"] for dependency_operator in dependency_operators: - self.install_openshift_isv(dependency_operator, "stable", "redhat-operators") - self.wait_for_isv_installation_to_complete(dependency_operator, namespace="openshift-operators") + self.install_openshift_isv( + dependency_operator, "stable", "redhat-operators" + ) + self.wait_for_isv_installation_to_complete( + dependency_operator, namespace="openshift-operators" + ) # Deploy rhoai self.install_rhods() @@ -1102,7 +1113,9 @@ def hibernate_cluster(self): """Hibernate OSD Cluster""" cluster_id = self.get_osd_cluster_id() - cmd = "ocm --v={} hibernate cluster {}".format(self.ocm_verbose_level, cluster_id) + cmd = "ocm --v={} hibernate cluster {}".format( + self.ocm_verbose_level, cluster_id + ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) if ret is None: @@ -1179,7 +1192,9 @@ def update_notification_email_address( cluster_id = self.get_osd_cluster_id() cmd = ( "ocm --v={} patch /api/clusters_mgmt/v1/clusters/{}/addons/{} " - "--body={}".format(self.ocm_verbose_level, cluster_id, addon_name, output_file) + "--body={}".format( + self.ocm_verbose_level, cluster_id, addon_name, output_file + ) ) log.info("CMD: {}".format(cmd)) ret = execute_command(cmd) @@ -1195,7 +1210,6 @@ def update_notification_email_address( else: return ret - def install_openshift_isv( self, operator_name, channel, source, exit_on_failure=True ): @@ -1216,26 +1230,31 @@ def install_openshift_isv( yaml.dump(newdct, f) if operator_name == "serverless": - replace_vars = { "ISV_NAME": "serverless-operators", - "NAMESPACE": "openshift-serverless" + "NAMESPACE": "openshift-serverless", } template_file = "resource.jinja" file_path1 = "resource.yaml" self._render_template(template_file, file_path1, replace_vars) def yaml_loader(filepath): - with open(filepath,'rb')as file_descriptor: + with open(filepath, "rb") as file_descriptor: data = yaml.load(file_descriptor, Loader=yaml.SafeLoader) return data data1 = yaml_loader(file_path1) data2 = yaml_loader(output_file) data1.update(data2) - - with open(output_file, 'w') as yaml_output: - yaml.dump(data1, yaml_output, default_flow_style=False, explicit_start=True, allow_unicode=True) + + with open(output_file, "w") as yaml_output: + yaml.dump( + data1, + yaml_output, + default_flow_style=False, + explicit_start=True, + allow_unicode=True, + ) cmd = "oc apply -f {} ".format(os.path.abspath(output_file)) ret = execute_command(cmd) @@ -1373,7 +1392,9 @@ def change_cluster_channel_group(self): cluster_id = self.get_osd_cluster_id() run_change_channel_cmd = ( "ocm --v={} patch /api/clusters_mgmt/v1/clusters/{}" - " --body {}".format(self.ocm_verbose_level, cluster_id, self.update_ocm_channel_json) + " --body {}".format( + self.ocm_verbose_level, cluster_id, self.update_ocm_channel_json + ) ) log.info(run_change_channel_cmd) ret = execute_command(run_change_channel_cmd) diff --git a/ods_ci/utils/scripts/polarion/xunit_add_properties.py b/ods_ci/utils/scripts/polarion/xunit_add_properties.py index 94b1dcab1..796ab17b0 100644 --- a/ods_ci/utils/scripts/polarion/xunit_add_properties.py +++ b/ods_ci/utils/scripts/polarion/xunit_add_properties.py @@ -1,12 +1,13 @@ """Inserts properties from a config file into a xunit format XML file""" import argparse import codecs +import os import xml.etree.ElementTree as et from copy import deepcopy from xml.dom import minidom -import os -from junitparser import JUnitXml, TestCase, TestSuite, Failure, Error, Skipped + import yaml +from junitparser import Error, Failure, JUnitXml, Skipped, TestCase, TestSuite def parse_args(): diff --git a/ods_ci/utils/scripts/reportportal/rp_uploader.py b/ods_ci/utils/scripts/reportportal/rp_uploader.py index ea92926ca..a1cd3e5cd 100644 --- a/ods_ci/utils/scripts/reportportal/rp_uploader.py +++ b/ods_ci/utils/scripts/reportportal/rp_uploader.py @@ -43,7 +43,7 @@ def write_output_file(self, file_content): def upload_result(self): """Uploads test results to report portal""" - cmd = "rp_preproc -c {} -d {} " "--service {} -l {}".format( + cmd = "rp_preproc -c {} -d {} --service {} -l {}".format( self.config_file, self.payload_dir, self.service_url, self.log_path ) log.info("CMD: {}".format(cmd)) diff --git a/ods_ci/utils/scripts/rosa/rosa.py b/ods_ci/utils/scripts/rosa/rosa.py index d7ee2025b..e64d9bcfb 100644 --- a/ods_ci/utils/scripts/rosa/rosa.py +++ b/ods_ci/utils/scripts/rosa/rosa.py @@ -1,12 +1,14 @@ -import argparse, sys, os +import argparse +import os +import sys dir_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(dir_path + "/../") -from logger import log from awsOps import aws_configure +from logger import log from rosaOps import ( - rosa_create_cluster, create_account_roles, + rosa_create_cluster, wait_for_osd_cluster_to_be_ready, ) diff --git a/ods_ci/utils/scripts/rosa/rosaOps.py b/ods_ci/utils/scripts/rosa/rosaOps.py index f63d6b6d7..16e3210a2 100644 --- a/ods_ci/utils/scripts/rosa/rosaOps.py +++ b/ods_ci/utils/scripts/rosa/rosaOps.py @@ -1,7 +1,8 @@ -from util import execute_command +import sys from logging import log from time import sleep -import sys + +from util import execute_command def create_account_roles(): @@ -29,7 +30,7 @@ def rosa_create_cluster( rosa_version, sts=True, ): - if sts == True: + if sts is True: cmd_rosa_create_cluster = [ "rosa", "create", @@ -126,7 +127,7 @@ def rosa_describe(cluster_name, filter=""): cmd += " " + filter ret = execute_command(cmd) if ret is None: - print("rosa describe for cluster " "{} failed".format(cluster_name)) + print("rosa describe for cluster {} failed".format(cluster_name)) return None return ret @@ -159,13 +160,11 @@ def wait_for_osd_cluster_to_be_ready(cluster_name, timeout=7200): check_flag = True break elif cluster_state == "error": - print("{} is in error state. Hence " "exiting!!".format(cluster_name)) + print("{} is in error state. Hence exiting!!".format(cluster_name)) sys.exit(1) sleep(60) count += 60 if not check_flag: - print( - "{} not in ready state even after 2 hours." " EXITING".format(cluster_name) - ) + print("{} not in ready state even after 2 hours. EXITING".format(cluster_name)) sys.exit(1) diff --git a/ods_ci/utils/scripts/testconfig/generateTestConfigFile.py b/ods_ci/utils/scripts/testconfig/generateTestConfigFile.py index ff9dc8f01..e7cedf0ea 100644 --- a/ods_ci/utils/scripts/testconfig/generateTestConfigFile.py +++ b/ods_ci/utils/scripts/testconfig/generateTestConfigFile.py @@ -107,6 +107,7 @@ def parse_args(): return parser.parse_args() + def change_component_state(components): # Parse and convert the component states argument into a dictionary component_states = {} @@ -150,12 +151,16 @@ def get_dashboard_url(): cmd = "oc get route -A -o json | jq '.items[].spec.host' | grep 'dashboard'" dashboard_url = execute_command(cmd) - return "https://" + dashboard_url.strip('\"').strip("\n") + return "https://" + dashboard_url.strip('"').strip("\n") def generate_test_config_file( - config_template, config_data, test_cluster, set_prometheus_config, - set_dashboard_url, components=None + config_template, + config_data, + test_cluster, + set_prometheus_config, + set_dashboard_url, + components=None, ): """ Generates test config file dynamically by @@ -271,7 +276,7 @@ def generate_test_config_file( if bool(set_dashboard_url): # Get Dashboard url for open data science dashboard_url = get_dashboard_url() - data["ODH_DASHBOARD_URL"] = dashboard_url.replace('"', '') + data["ODH_DASHBOARD_URL"] = dashboard_url.replace('"', "") with open(config_file, "w") as yaml_file: yaml_file.write(yaml.dump(data, default_flow_style=False, sort_keys=False)) @@ -300,9 +305,12 @@ def main(): # Generate test config file generate_test_config_file( - args.config_template, config_data, args.test_cluster, args.set_prometheus_config, - args.set_dashboard_url, components=args.components, - + args.config_template, + config_data, + args.test_cluster, + args.set_prometheus_config, + args.set_dashboard_url, + components=args.components, ) print("Done generating config file") diff --git a/ods_ci/utils/scripts/util.py b/ods_ci/utils/scripts/util.py index 1cb50c854..6adbeaa9b 100644 --- a/ods_ci/utils/scripts/util.py +++ b/ods_ci/utils/scripts/util.py @@ -54,32 +54,32 @@ def read_yaml(filename): return yaml.safe_load(fh) except OSError as error: return None - + def execute_command(cmd): """ Executes command in the local node, and print real-time output """ - output = '' + output = "" try: with subprocess.Popen( - cmd, - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=True, - encoding='utf-8', - errors='replace' - ) as p: - while True: - line = p.stdout.readline() - if line != '': - output += (line + "\n") - print(line) - elif p.poll() != None: - break - sys.stdout.flush() - return output + cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + universal_newlines=True, + encoding="utf-8", + errors="replace", + ) as p: + while True: + line = p.stdout.readline() + if line != "": + output += line + "\n" + print(line) + elif p.poll() is not None: + break + sys.stdout.flush() + return output except: return None @@ -119,9 +119,7 @@ def render_template(search_path, template_file, output_file, replace_vars): with open(output_file, "w") as fh: fh.write(outputText) except: - print( - "Failed to render template and create json " "file {}".format(output_file) - ) + print("Failed to render template and create json file {}".format(output_file)) sys.exit(1) diff --git a/pyproject.toml b/pyproject.toml index c6b249440..1364bce41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,8 +41,14 @@ ruff = "0.1.11" requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" +[tool.isort] +# https://pycqa.github.io/isort/docs/configuration/black_compatibility.html +profile = "black" +line_length = 88 # align with black's default + [tool.ruff] target-version = "py38" +line-length = 88 # align with black's default # https://docs.astral.sh/ruff/rules [tool.ruff.lint] @@ -100,9 +106,7 @@ ignore = [ "COM812", # Trailing comma missing "F841", # Local variable `response` is assigned to but never used "FA100", # Missing `from __future__ import annotations`, but uses `typing.Optional` - "I001", # Import block is un-sorted or un-formatted "INP001", # File `ods_ci/tests/Resources/Page/ODH/JupyterHub/jupyter-helper.py` is part of an implicit namespace package. Add an `__init__.py`. - "ISC001", # Implicitly concatenated string literals on one line "N806", # Variable `outputText` in function should be lowercase "N813", # Camelcase `ElementTree` imported as lowercase `et` "N816", # Variable `rotatingHandler` in global scope should not be mixedCase @@ -115,7 +119,6 @@ ignore = [ "PLR6301", # Method `_render_template` could be a function, class method, or static method "PLW1514", # `codecs.open` in text mode without explicit `encoding` argument "PLW2901", # `for` loop variable `tag_it` overwritten by assignment target - "Q000", # Single quotes found but double quotes preferred "RET501", # Do not explicitly `return None` in function if it is the only possible return value "RET503", # Missing explicit `return` at the end of function able to return non-`None` value "RET504", # Unnecessary assignment to `names` before `return` statement @@ -126,28 +129,16 @@ ignore = [ "UP034", # Avoid extraneous parentheses "W605", # Invalid escape sequence: `\d` # TODO(jdanek) - "C416", # Unnecessary `list` comprehension (rewrite using `list()`) - "E117", # Over-indented - "E231", # Missing whitespace after ',' - "E401", # Multiple imports on one line "E402", # Module level import not at top of file - "E711", # Comparison to `None` should be `cond is not None` - "E712", # Comparison to `True` should be `cond is True` or `if cond:` "E721", # Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks "E722", # Do not use bare `except` "F401", # `re` imported but unused "F403", # `from python_terraform import *` used; unable to detect undefined names "F405", # `IsNotFlagged` may be undefined, or defined from star imports - "F541", # f-string without any placeholders "F811", # Redefinition of unused `hide_values_in_op_json` from line 565 "F821", # Undefined name `os` - "PIE790", # Unnecessary `pass` statement - "PLR1714", # Consider merging multiple comparisons. Use a `set` if the elements are hashable. - "Q004", # Unnecessary escape on inner quote character "RET507", # Unnecessary `else` after `continue` statement "RET508", # Unnecessary `elif` after `break` statement - "W292", # No newline at end of file - "W293", # Blank line contains whitespace ] # Allow unused variables when underscore-prefixed. From daf5733dc92c70384fbced17726d62da687f889c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Mon, 8 Jan 2024 13:19:28 +0100 Subject: [PATCH 11/31] fixup #fmt: on comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jiri Daněk --- ods_ci/utils/scripts/ocm/ocm.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ods_ci/utils/scripts/ocm/ocm.py b/ods_ci/utils/scripts/ocm/ocm.py index 91177af55..e78ce4705 100644 --- a/ods_ci/utils/scripts/ocm/ocm.py +++ b/ods_ci/utils/scripts/ocm/ocm.py @@ -18,8 +18,6 @@ dir_path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(dir_path + "/../") from logger import log - -# fmt: off from util import ( clone_config_repo, compare_dicts, @@ -29,8 +27,6 @@ write_data_in_json, ) -# fmt: on - """ Class for Openshift Cluster Manager """ @@ -1423,10 +1419,12 @@ def update_ocm_policy(self): latest_upgrade_version = ast.literal_eval(latest_upgrade_version)[-1] data["version"] = latest_upgrade_version write_data_in_json(self.update_policies_json, data) - # fmt: off + schedule_cluster_upgrade = ( "ocm --v={} post /api/clusters_mgmt/v1/clusters/{}/upgrade_policies" - " --body {}".format(self.ocm_verbose_level, cluster_id, self.update_policies_json) + " --body {}".format( + self.ocm_verbose_level, cluster_id, self.update_policies_json + ) ) ret = execute_command(schedule_cluster_upgrade) if ret is None: From 266e0cac73e259c1c6175cf638976eeda370f0c7 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Tue, 19 Dec 2023 09:28:20 +0000 Subject: [PATCH 12/31] New Test: Verify Project Sharing Does Not Override Dashboard Permissions Signed-off-by: manosnoam --- .../Permissions.resource | 42 ++++++++++++++++++ .../400__ods_dashboard.robot | 43 +------------------ ..._dashboard_projects_permissions_mgmt.robot | 18 ++++++++ 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index af0bf260d..b910d343f 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -102,3 +102,45 @@ Is ${username} In The Permissions Table ${present}= Run Keyword And Return Status ... Page Should Contain Element xpath=//tr[td[@data-label="Username"]//*[text()="${username}"]] RETURN ${present} + +Set RHODS Admins Group Empty Group + [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + ... to the given empty group (i.e., with no users) + Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} + ... users_group=${STANDARD_USERS_GROUP} + +Set RHODS Admins Group To system:authenticated # robocop:disable + [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + ... to the given empty group (i.e., with no users) + Set Access Groups Settings admins_group=system:authenticated + ... users_group=${STANDARD_USERS_GROUP} + +Set RHODS Users Group Empty Group + [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + ... to the given empty group (i.e., with no users) + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${CUSTOM_EMPTY_GROUP} + +Set RHODS Admins Group To Inexistent Group + [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + ... to the given inexistent group + Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} + ... users_group=${STANDARD_USERS_GROUP} + +Set RHODS Users Group To Inexistent Group + [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + ... to the given inexistent group + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${CUSTOM_INEXISTENT_GROUP} + +Set Default Groups And Check Logs Do Not Change + [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "rhods-groups-config" + ... ConfigMap and checks if no new lines are generated in the logs after that. + [Arguments] ${delete_group}=${FALSE} + ${lengths_dict}= Get Lengths Of Dashboard Pods Logs + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${STANDARD_USERS_GROUP} + Logs Of Dashboard Pods Should Not Contain New Lines lengths_dict=${lengths_dict} + IF "${delete_group}" == "${TRUE}" + Delete Group group_name=${CUSTOM_EMPTY_GROUP} + END diff --git a/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot b/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot index d691d7f7f..cab8d854d 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot @@ -5,6 +5,7 @@ Resource ../../Resources/RHOSi.resource Resource ../../Resources/ODS.robot Resource ../../Resources/Page/ODH/ODHDashboard/ODHDashboard.resource Resource ../../Resources/Page/ODH/ODHDashboard/ODHDashboardResources.resource +Resource ../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource Resource ../../Resources/Page/ODH/AiApps/Anaconda.resource Resource ../../Resources/Page/LoginPage.robot Resource ../../Resources/Page/OCPLogin/OCPLogin.robot @@ -388,48 +389,6 @@ Wait Until New Log Lines Are Generated In A Dashboard Pod END RETURN ${pod_logs_lines}[${prev_length}:] ${n_lines} -Set RHODS Admins Group Empty Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given empty group (i.e., with no users) - Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} - ... users_group=${STANDARD_USERS_GROUP} - -Set RHODS Admins Group To system:authenticated # robocop:disable - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given empty group (i.e., with no users) - Set Access Groups Settings admins_group=system:authenticated - ... users_group=${STANDARD_USERS_GROUP} - -Set RHODS Users Group Empty Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given empty group (i.e., with no users) - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_EMPTY_GROUP} - -Set RHODS Admins Group To Inexistent Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given inexistent group - Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} - ... users_group=${STANDARD_USERS_GROUP} - -Set RHODS Users Group To Inexistent Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given inexistent group - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_INEXISTENT_GROUP} - -Set Default Groups And Check Logs Do Not Change - [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "rhods-groups-config" - ... ConfigMap and checks if no new lines are generated in the logs after that. - [Arguments] ${delete_group}=${FALSE} - ${lengths_dict}= Get Lengths Of Dashboard Pods Logs - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_USERS_GROUP} - Logs Of Dashboard Pods Should Not Contain New Lines lengths_dict=${lengths_dict} - IF "${delete_group}" == "${TRUE}" - Delete Group group_name=${CUSTOM_EMPTY_GROUP} - END - Logs Of Dashboard Pods Should Not Contain New Lines [Documentation] Checks if no new lines are generated in the logs after that. [Arguments] ${lengths_dict} diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index bce3ac36e..d3067a66f 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -76,6 +76,24 @@ Verify User Can Assign Access Permissions To User Groups Sleep 5s ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} +Verify Project Sharing Does Not Override Dashboard Permissions + [Tags] Tier1 Sanity + ... ODS-2223 + # [Setup] Run Keywords Restore Permissions Of The Project + # ... AND Set RHODS Admins Group Empty Group + [Setup] Set RHODS Admins Group Empty Group + Launch Data Science Project Main Page username=${TEST_USER_4.USERNAME} + Move To Tab Permissions + Remove User From Group username=${USER_B} + ... group_name=rhods-users + Remove User From Group username=${USER_C} + ... group_name=rhods-users + Assign Admin Permissions To User ${USER_B} + Assign Edit Permissions To User ${USER_C} + ${USER_B} Should Not Have Access To ${PRJ_USER_B_TITLE} + ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} + [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated + ... AND Set User Groups For Testing *** Keywords *** Project Permissions Mgmt Suite Setup # robocop: disable From e71ec240208edf60f460fbd5693a60f199c7651c Mon Sep 17 00:00:00 2001 From: manosnoam Date: Wed, 3 Jan 2024 08:41:00 +0000 Subject: [PATCH 13/31] Fix 'Create Group' KW to apply new group only if it doesn't exist Signed-off-by: manosnoam --- .../Resources/Page/OCPDashboard/UserManagement/Groups.robot | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot index 125188ebb..021bfa51f 100644 --- a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot +++ b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot @@ -14,9 +14,10 @@ Go To ${group_name} Group Page Wait Until Page Contains Element xpath://h2/span[text()='Users'] Create Group - [Documentation] Creates a user group in OCP + [Documentation] Creates a user group in OCP if it doesn't exist [Arguments] ${group_name} - ${res} ${output}= Run And Return Rc And Output oc adm groups new ${group_name} + ${res} ${output}= Run And Return Rc And Output + ... oc adm groups new ${group_name} --dry-run=client -o yaml | kubectl apply --validate=false -f - # Oc Create kind=Group src={"metadata": {"name": "${group_name}"}, "users": null} Should Be Equal As Integers ${res} 0 From fd118098a7729324c0f72e0f0ef7b4ae19604e57 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Wed, 3 Jan 2024 10:54:56 +0000 Subject: [PATCH 14/31] Add Resource ODS.robot to Permissions.resource and set Groups Variables Signed-off-by: manosnoam --- .../ODHDashboard/ODHDataScienceProject/Permissions.resource | 2 ++ .../415__ods_dashboard_projects_permissions_mgmt.robot | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index b910d343f..9d15d37ea 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -1,12 +1,14 @@ *** Settings *** Documentation Collection of keywords to interact with Storages Resource ./Projects.resource +Resource ../../../../../Resources/ODS.robot *** Variables *** ${SAVE_BUTTON}= xpath://button[@data-id="save-rolebinding-button"] ${PERMISSIONS_DROPDOWN}= xpath://td[@data-label="Permission"]//button[@aria-label="Options menu"] ${IS_CLUSTER_ADMIN}= ${FALSE} +${CUSTOM_EMPTY_GROUP}= empty-group *** Keywords *** diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index d3067a66f..f16ec29a2 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -80,7 +80,7 @@ Verify Project Sharing Does Not Override Dashboard Permissions [Tags] Tier1 Sanity ... ODS-2223 # [Setup] Run Keywords Restore Permissions Of The Project - # ... AND Set RHODS Admins Group Empty Group + # ... AND Set RHODS Admins Group Empty Group [Setup] Set RHODS Admins Group Empty Group Launch Data Science Project Main Page username=${TEST_USER_4.USERNAME} Move To Tab Permissions @@ -101,6 +101,8 @@ Project Permissions Mgmt Suite Setup # robocop: disable ... It creates some test variables and runs RHOSi setup Set Library Search Order SeleniumLibrary RHOSi Setup + Set Standard RHODS Groups Variables + Set Default Access Groups Settings ${to_delete}= Create List Set Suite Variable ${PROJECTS_TO_DELETE} ${to_delete} Launch RHODS Dashboard Session With User A From d468a6db02f22aeff7b360e19f977c2019f3e3c5 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Wed, 3 Jan 2024 15:11:42 +0000 Subject: [PATCH 15/31] Use elevated user to Setup the test Signed-off-by: manosnoam --- .../415__ods_dashboard_projects_permissions_mgmt.robot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index f16ec29a2..349a6acfb 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -82,7 +82,7 @@ Verify Project Sharing Does Not Override Dashboard Permissions # [Setup] Run Keywords Restore Permissions Of The Project # ... AND Set RHODS Admins Group Empty Group [Setup] Set RHODS Admins Group Empty Group - Launch Data Science Project Main Page username=${TEST_USER_4.USERNAME} + Launch Data Science Project Main Page username=${TEST_USER.USERNAME} Move To Tab Permissions Remove User From Group username=${USER_B} ... group_name=rhods-users From a253481e47e8916e552f8661853bdd5e6eaad84c Mon Sep 17 00:00:00 2001 From: manosnoam Date: Wed, 3 Jan 2024 17:26:31 +0000 Subject: [PATCH 16/31] New Keyword: Set RHODS Users Group To rhods-users Signed-off-by: manosnoam --- ods_ci/tests/Resources/ODS.robot | 1 + .../OCPDashboard/UserManagement/Groups.robot | 2 +- .../Permissions.resource | 26 ++++++++++++------- ..._dashboard_projects_permissions_mgmt.robot | 10 +++---- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/ods_ci/tests/Resources/ODS.robot b/ods_ci/tests/Resources/ODS.robot index 2c24c4fd8..e9941bfbe 100644 --- a/ods_ci/tests/Resources/ODS.robot +++ b/ods_ci/tests/Resources/ODS.robot @@ -89,6 +89,7 @@ Set Standard RHODS Groups Variables Set Suite Variable ${STANDARD_ADMINS_GROUP} rhods-admins END Set Suite Variable ${STANDARD_USERS_GROUP} system:authenticated + Set Suite Variable ${STANDARD_USERS_GROUP} rhods-users Apply Access Groups Settings diff --git a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot index 021bfa51f..ce7de33c0 100644 --- a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot +++ b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot @@ -32,7 +32,7 @@ Add User To Group Run oc adm groups add-users ${group_name} ${username} Remove User From Group - [Documentation] Add a user to a given OCP user group + [Documentation] Remove a user from a given OCP user group [Arguments] ${username} ${group_name} Run oc adm groups remove-users ${group_name} ${username} diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index 9d15d37ea..e54178f85 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -106,37 +106,43 @@ Is ${username} In The Permissions Table RETURN ${present} Set RHODS Admins Group Empty Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap ... to the given empty group (i.e., with no users) Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} ... users_group=${STANDARD_USERS_GROUP} Set RHODS Admins Group To system:authenticated # robocop:disable - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given empty group (i.e., with no users) + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the system:authenticated group Set Access Groups Settings admins_group=system:authenticated ... users_group=${STANDARD_USERS_GROUP} +Set RHODS Admins Group To Inexistent Group + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the given inexistent group + Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} + ... users_group=${STANDARD_USERS_GROUP} + Set RHODS Users Group Empty Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap ... to the given empty group (i.e., with no users) Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} ... users_group=${CUSTOM_EMPTY_GROUP} -Set RHODS Admins Group To Inexistent Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap - ... to the given inexistent group - Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} +Set RHODS Users Group To rhods-users # robocop:disable + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the rhods-users group + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} ... users_group=${STANDARD_USERS_GROUP} Set RHODS Users Group To Inexistent Group - [Documentation] Sets the "admins_groups" field in "rhods-groups-config" ConfigMap + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap ... to the given inexistent group Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} ... users_group=${CUSTOM_INEXISTENT_GROUP} Set Default Groups And Check Logs Do Not Change - [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "rhods-groups-config" + [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "odh-dashboard-config" ... ConfigMap and checks if no new lines are generated in the logs after that. [Arguments] ${delete_group}=${FALSE} ${lengths_dict}= Get Lengths Of Dashboard Pods Logs diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index 349a6acfb..2fc109596 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -79,9 +79,9 @@ Verify User Can Assign Access Permissions To User Groups Verify Project Sharing Does Not Override Dashboard Permissions [Tags] Tier1 Sanity ... ODS-2223 - # [Setup] Run Keywords Restore Permissions Of The Project - # ... AND Set RHODS Admins Group Empty Group - [Setup] Set RHODS Admins Group Empty Group + [Setup] Run Keywords Restore Permissions Of The Project + ... AND Set RHODS Users Group To rhods-users + # [Setup] Set RHODS Users Group To rhods-users Launch Data Science Project Main Page username=${TEST_USER.USERNAME} Move To Tab Permissions Remove User From Group username=${USER_B} @@ -101,8 +101,8 @@ Project Permissions Mgmt Suite Setup # robocop: disable ... It creates some test variables and runs RHOSi setup Set Library Search Order SeleniumLibrary RHOSi Setup - Set Standard RHODS Groups Variables - Set Default Access Groups Settings + # Set Standard RHODS Groups Variables + # Set Default Access Groups Settings ${to_delete}= Create List Set Suite Variable ${PROJECTS_TO_DELETE} ${to_delete} Launch RHODS Dashboard Session With User A From 21a6029e2ec14dccb3065fb5922b2f54fd4f87a2 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Thu, 4 Jan 2024 18:32:20 +0000 Subject: [PATCH 17/31] Fix 'Delete Group' KW to to handle unexcited group Signed-off-by: manosnoam --- ods_ci/tests/Resources/ODS.robot | 12 +++--- .../OCPDashboard/UserManagement/Groups.robot | 5 ++- .../Permissions.resource | 40 +++++++++---------- ..._dashboard_projects_permissions_mgmt.robot | 2 +- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/ods_ci/tests/Resources/ODS.robot b/ods_ci/tests/Resources/ODS.robot index e9941bfbe..1924c622d 100644 --- a/ods_ci/tests/Resources/ODS.robot +++ b/ods_ci/tests/Resources/ODS.robot @@ -84,12 +84,12 @@ Set Standard RHODS Groups Variables [Documentation] Sets the RHODS groups name based on RHODS version ${is_self_managed}= Is RHODS Self-Managed IF ${is_self_managed} == False - Set Suite Variable ${STANDARD_ADMINS_GROUP} dedicated-admins + Set Suite Variable ${STANDARD_ADMINS_GROUP} dedicated-admins ELSE - Set Suite Variable ${STANDARD_ADMINS_GROUP} rhods-admins + Set Suite Variable ${STANDARD_ADMINS_GROUP} rhods-admins END - Set Suite Variable ${STANDARD_USERS_GROUP} system:authenticated - Set Suite Variable ${STANDARD_USERS_GROUP} rhods-users + Set Suite Variable ${STANDARD_SYSTEM_GROUP} system:authenticated + Set Suite Variable ${STANDARD_USERS_GROUP} rhods-users Apply Access Groups Settings @@ -108,7 +108,7 @@ Set Access Groups Settings Set Default Access Groups Settings [Documentation] Restores the default rhods-groups config map Apply Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} Uninstall RHODS From OSD Cluster [Documentation] Selects the cluster type and triggers the RHODS uninstallation @@ -242,7 +242,7 @@ Verify RHODS Dashboard CR Contains Expected Values Verify Default Access Groups Settings [Documentation] Verifies that ODS contains the expected default groups settings &{exp_values}= Create Dictionary spec.groupsConfig.adminGroups=${STANDARD_ADMINS_GROUP} - ... spec.groupsConfig.allowedGroups=${STANDARD_USERS_GROUP} + ... spec.groupsConfig.allowedGroups=${STANDARD_SYSTEM_GROUP} Verify RHODS Dashboard CR Contains Expected Values &{exp_values} Enable Access To Grafana Using OpenShift Port Forwarding diff --git a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot index ce7de33c0..9d3d351c0 100644 --- a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot +++ b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot @@ -24,7 +24,10 @@ Create Group Delete Group [Documentation] Deletes a user group in OCP [Arguments] ${group_name} - Oc Delete kind=Group name=${group_name} + ${res} ${output}= Run And Return Rc And Output + ... oc adm groups delete ${group_name} --dry-run=client -o yaml | kubectl apply --validate=false -f - + # Oc Delete kind=Group name=${group_name} + Should Be Equal As Integers ${res} 0 Add User To Group [Documentation] Add a user to a given OCP user group diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index e54178f85..152590b03 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -109,45 +109,45 @@ Set RHODS Admins Group Empty Group [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap ... to the given empty group (i.e., with no users) Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} Set RHODS Admins Group To system:authenticated # robocop:disable - [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap - ... to the system:authenticated group + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the system:authenticated group Set Access Groups Settings admins_group=system:authenticated - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} Set RHODS Admins Group To Inexistent Group - [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap - ... to the given inexistent group + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the given inexistent group Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} Set RHODS Users Group Empty Group - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the given empty group (i.e., with no users) + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the given empty group (i.e., with no users) Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_EMPTY_GROUP} + ... users_group=${CUSTOM_EMPTY_GROUP} Set RHODS Users Group To rhods-users # robocop:disable - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the rhods-users group + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the rhods-users group Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_USERS_GROUP} Set RHODS Users Group To Inexistent Group - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the given inexistent group + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the given inexistent group Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_INEXISTENT_GROUP} + ... users_group=${CUSTOM_INEXISTENT_GROUP} Set Default Groups And Check Logs Do Not Change - [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "odh-dashboard-config" - ... ConfigMap and checks if no new lines are generated in the logs after that. - [Arguments] ${delete_group}=${FALSE} + [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "odh-dashboard-config" + ... ConfigMap and checks if no new lines are generated in the logs after that. + [Arguments] ${delete_group}=${FALSE} ${lengths_dict}= Get Lengths Of Dashboard Pods Logs Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_USERS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} Logs Of Dashboard Pods Should Not Contain New Lines lengths_dict=${lengths_dict} IF "${delete_group}" == "${TRUE}" Delete Group group_name=${CUSTOM_EMPTY_GROUP} diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index 2fc109596..edc70ad47 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -101,7 +101,7 @@ Project Permissions Mgmt Suite Setup # robocop: disable ... It creates some test variables and runs RHOSi setup Set Library Search Order SeleniumLibrary RHOSi Setup - # Set Standard RHODS Groups Variables + Set Standard RHODS Groups Variables # Set Default Access Groups Settings ${to_delete}= Create List Set Suite Variable ${PROJECTS_TO_DELETE} ${to_delete} From 4cce8a7faa62d6c3ea7f0a6f1911454fa40b029d Mon Sep 17 00:00:00 2001 From: manosnoam Date: Thu, 4 Jan 2024 18:54:39 +0000 Subject: [PATCH 18/31] Add Users names to Suite Variables Signed-off-by: manosnoam --- ..._dashboard_projects_permissions_mgmt.robot | 149 +++++++++--------- 1 file changed, 75 insertions(+), 74 deletions(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index edc70ad47..52650b710 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -1,34 +1,40 @@ *** Settings *** -Documentation Suite to test additional scenarios for Data Science Projects (a.k.a DSG) feature -Resource ../../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource -Suite Setup Project Permissions Mgmt Suite Setup -Suite Teardown Project Permissions Mgmt Suite Teardown +Documentation Suite to test additional scenarios for Data Science Projects (a.k.a DSG) feature + +Resource ../../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource + +Suite Setup Project Permissions Mgmt Suite Setup +Suite Teardown Project Permissions Mgmt Suite Teardown *** Variables *** -${PRJ_BASE_TITLE}= ODS-CI DS Project -${PRJ_DESCRIPTION}= ${PRJ_BASE_TITLE} is a test project for validating DS Project Sharing feature -${WORKBENCH_DESCRIPTION}= a test workbench to check project sharing -${NB_IMAGE}= Minimal Python -${PV_NAME}= ods-ci-project-sharing -${PV_DESCRIPTION}= it is a PV created to test DS Projects Sharing feature -${PV_SIZE}= 1 -${USER_GROUP_1}= ds-group-1 -${USER_GROUP_2}= ds-group-2 +${PRJ_BASE_TITLE}= ODS-CI DS Project +${PRJ_DESCRIPTION}= ${PRJ_BASE_TITLE} is a test project for validating DS Project Sharing feature +${WORKBENCH_DESCRIPTION}= a test workbench to check project sharing +${NB_IMAGE}= Minimal Python +${PV_NAME}= ods-ci-project-sharing +${PV_DESCRIPTION}= it is a PV created to test DS Projects Sharing feature +${PV_SIZE}= 1 +${USER_GROUP_1}= ds-group-1 +${USER_GROUP_2}= ds-group-2 +${USER_A}= ${TEST_USER_2.USERNAME} +${USER_B}= ${TEST_USER_3.USERNAME} +${PRJ_USER_B_TITLE}= ${PRJ_BASE_TITLE}-${TEST_USER_3.USERNAME} +${USER_C}= ${TEST_USER_4.USERNAME} +${PRJ_USER_C_TITLE}= ${PRJ_BASE_TITLE}-${TEST_USER_4.USERNAME} + *** Test Cases *** Verify User Can Access Permission Tab In Their Owned DS Project [Documentation] Verify user has access to "Permissions" tab in their DS Projects - [Tags] Tier1 Smoke OpenDataHub - ... ODS-2194 - Pass Execution The Test is executed as part of Suite Setup + [Tags] Tier1 Smoke OpenDataHub ODS-2194 + Pass Execution The Test is executed as part of Suite Setup Verify User Can Make Their Owned DS Project Accessible To Other Users # robocop: disable [Documentation] Verify user can give access permissions for their DS Projects to other users - [Tags] Tier1 Sanity - ... ODS-2201 - Switch To User ${USER_B} - Move To Tab Permissions + [Tags] Tier1 Sanity ODS-2201 + Switch To User ${USER_B} + Move To Tab Permissions Assign Edit Permissions To User ${USER_C} Assign Admin Permissions To User ${USER_A} ${USER_C} Should Have Edit Access To ${PRJ_USER_B_TITLE} @@ -36,69 +42,67 @@ Verify User Can Make Their Owned DS Project Accessible To Other Users # roboc Verify User Can Modify And Revoke Access To DS Projects From Other Users # robocop: disable [Documentation] Verify user can modify/remove access permissions for their DS Projects to other users - [Tags] Tier1 Sanity - ... ODS-2202 - Switch To User ${USER_B} - Move To Tab Permissions + [Tags] Tier1 Sanity ODS-2202 + Switch To User ${USER_B} + Move To Tab Permissions Change ${USER_C} Permissions To Admin Change ${USER_A} Permissions To Edit Refresh Pages ${USER_C} Should Have Admin Access To ${PRJ_USER_B_TITLE} ${USER_A} Should Have Edit Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} - Move To Tab Permissions + Switch To User ${USER_B} + Move To Tab Permissions Remove ${USER_C} Permissions ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} Verify User Can Assign Access Permissions To User Groups - [Tags] Tier1 Sanity - ... ODS-2208 - [Setup] Restore Permissions Of The Project - Switch To User ${USER_B} + [Tags] Tier1 Sanity ODS-2208 + [Setup] Restore Permissions Of The Project + Switch To User ${USER_B} Assign Edit Permissions To Group ${USER_GROUP_1} Assign Admin Permissions To Group ${USER_GROUP_2} - RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} - ... subject_name=${USER_GROUP_1} + RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} + ... subject_name=${USER_GROUP_1} - RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} - ... subject_name=${USER_GROUP_2} - Sleep 5s + RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} + ... subject_name=${USER_GROUP_2} + Sleep 5s ${USER_A} Should Have Edit Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Have Admin Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} + Switch To User ${USER_B} Change ${USER_GROUP_1} Permissions To Admin Change ${USER_GROUP_2} Permissions To Edit - Sleep 5s + Sleep 5s ${USER_A} Should Have Admin Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Have Edit Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} + Switch To User ${USER_B} Remove ${USER_GROUP_2} Permissions - Sleep 5s + Sleep 5s ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} Verify Project Sharing Does Not Override Dashboard Permissions - [Tags] Tier1 Sanity - ... ODS-2223 - [Setup] Run Keywords Restore Permissions Of The Project - ... AND Set RHODS Users Group To rhods-users - # [Setup] Set RHODS Users Group To rhods-users - Launch Data Science Project Main Page username=${TEST_USER.USERNAME} - Move To Tab Permissions - Remove User From Group username=${USER_B} - ... group_name=rhods-users - Remove User From Group username=${USER_C} - ... group_name=rhods-users + [Tags] Tier1 Sanity ODS-2223 + [Setup] Run Keywords Restore Permissions Of The Project + ... AND Set RHODS Users Group To rhods-users + # [Setup] Set RHODS Users Group To rhods-users + Launch Data Science Project Main Page username=${TEST_USER.USERNAME} + Move To Tab Permissions + Remove User From Group username=${USER_B} + ... group_name=rhods-users + Remove User From Group username=${USER_C} + ... group_name=rhods-users Assign Admin Permissions To User ${USER_B} Assign Edit Permissions To User ${USER_C} ${USER_B} Should Not Have Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} - [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated - ... AND Set User Groups For Testing + [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated + ... AND Set User Groups For Testing + *** Keywords *** Project Permissions Mgmt Suite Setup # robocop: disable [Documentation] Suite setup steps for testing DS Projects. - ... It creates some test variables and runs RHOSi setup + ... It creates some test variables and runs RHOSi setup Set Library Search Order SeleniumLibrary RHOSi Setup Set Standard RHODS Groups Variables @@ -113,9 +117,9 @@ Project Permissions Mgmt Suite Setup # robocop: disable Project Permissions Mgmt Suite Teardown [Documentation] Suite teardown steps after testing DSG. It Deletes - ... all the DS projects created by the tests and run RHOSi teardown + ... all the DS projects created by the tests and run RHOSi teardown Close All Browsers - Delete Data Science Projects From CLI ocp_projects=${PROJECTS_TO_DELETE} + Delete Data Science Projects From CLI ocp_projects=${PROJECTS_TO_DELETE} RHOSi Teardown Remove User From Group username=${USER_A} ... group_name=rhods-users @@ -140,14 +144,12 @@ Switch To User Set Suite Variable ${IS_CLUSTER_ADMIN} ${is_cluster_admin} Launch RHODS Dashboard Session With User A - Launch Dashboard ocp_user_name=${TEST_USER_2.USERNAME} ocp_user_pw=${TEST_USER_2.PASSWORD} + Launch Dashboard ocp_user_name=${TEST_USER_2.USERNAME} ocp_user_pw=${TEST_USER_2.PASSWORD} ... ocp_user_auth_type=${TEST_USER_2.AUTH_TYPE} dashboard_url=${ODH_DASHBOARD_URL} - ... browser=${BROWSER.NAME} browser_options=${BROWSER.OPTIONS} + ... browser=${BROWSER.NAME} browser_options=${BROWSER.OPTIONS} ... browser_alias=${TEST_USER_2.USERNAME}-session - Set Suite Variable ${USER_A} ${TEST_USER_2.USERNAME} Launch RHODS Dashboard Session And Create A DS Project With User B - ${PRJ_USER_B_TITLE}= Set Variable ${PRJ_BASE_TITLE}-${TEST_USER_3.USERNAME} Append To List ${PROJECTS_TO_DELETE} ${PRJ_USER_B_TITLE} Launch Data Science Project Main Page username=${TEST_USER_3.USERNAME} ... password=${TEST_USER_3.PASSWORD} @@ -157,11 +159,8 @@ Launch RHODS Dashboard Session And Create A DS Project With User B ... description=${PRJ_DESCRIPTION} Permissions Tab Should Be Accessible Components Tab Should Be Accessible - Set Suite Variable ${USER_B} ${TEST_USER_3.USERNAME} - Set Suite Variable ${PRJ_USER_B_TITLE} ${PRJ_USER_B_TITLE} Launch RHODS Dashboard Session With User C - ${PRJ_USER_C_TITLE}= Set Variable ${PRJ_BASE_TITLE}-${TEST_USER_4.USERNAME} Append To List ${PROJECTS_TO_DELETE} ${PRJ_USER_C_TITLE} Launch Data Science Project Main Page username=${TEST_USER_4.USERNAME} ... password=${TEST_USER_4.PASSWORD} @@ -171,8 +170,6 @@ Launch RHODS Dashboard Session With User C ... description=${PRJ_DESCRIPTION} Permissions Tab Should Be Accessible Components Tab Should Be Accessible - Set Suite Variable ${USER_C} ${TEST_USER_4.USERNAME} - Set Suite Variable ${PRJ_USER_C_TITLE} ${PRJ_USER_C_TITLE} Set User Groups For Testing Create Group ${USER_GROUP_1} @@ -196,13 +193,9 @@ Restore Permissions Of The Project Switch To User ${USER_B} Move To Tab Permissions ${present_a}= Is ${USER_A} In The Permissions Table - IF ${present_a} == ${TRUE} - Remove ${USER_A} Permissions - END + IF ${present_a} == ${TRUE} Remove ${USER_A} Permissions ${present_c}= Is ${USER_C} In The Permissions Table - IF ${present_c} == ${TRUE} - Remove ${USER_C} Permissions - END + IF ${present_c} == ${TRUE} Remove ${USER_C} Permissions ${USER_A} Should Not Have Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} @@ -226,14 +219,18 @@ Reload Page If Project ${project_title} Is Not Listed ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${FALSE} - Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! # robocop:disable + # robocop:disable + Log + ... message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${FALSE} - Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! (2) # robocop:disable + # robocop:disable + Log + ... message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! (2) ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} @@ -244,14 +241,18 @@ Reload Page If Project ${project_title} Is Listed ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${TRUE} - Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! # robocop:disable + # robocop:disable + Log + ... message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${TRUE} - Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! (2) # robocop:disable + # robocop:disable + Log + ... message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! (2) ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} From d3e1bcf4187adc30dfb70b8508a526cd814ce957 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Thu, 4 Jan 2024 19:40:13 +0000 Subject: [PATCH 19/31] Delete a user group in OCP only if it already exists Signed-off-by: manosnoam --- .../Page/OCPDashboard/UserManagement/Groups.robot | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot index 9d3d351c0..64024acdb 100644 --- a/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot +++ b/ods_ci/tests/Resources/Page/OCPDashboard/UserManagement/Groups.robot @@ -14,20 +14,18 @@ Go To ${group_name} Group Page Wait Until Page Contains Element xpath://h2/span[text()='Users'] Create Group - [Documentation] Creates a user group in OCP if it doesn't exist + [Documentation] Creates a user group in OCP (if it doesn't exist) [Arguments] ${group_name} ${res} ${output}= Run And Return Rc And Output ... oc adm groups new ${group_name} --dry-run=client -o yaml | kubectl apply --validate=false -f - - # Oc Create kind=Group src={"metadata": {"name": "${group_name}"}, "users": null} - Should Be Equal As Integers ${res} 0 + Should Be Equal As Integers ${res} 0 ${output} Delete Group - [Documentation] Deletes a user group in OCP + [Documentation] Deletes a user group in OCP (if it exists) [Arguments] ${group_name} ${res} ${output}= Run And Return Rc And Output - ... oc adm groups delete ${group_name} --dry-run=client -o yaml | kubectl apply --validate=false -f - - # Oc Delete kind=Group name=${group_name} - Should Be Equal As Integers ${res} 0 + ... oc delete group ${group_name} --ignore-not-found + Should Be Equal As Integers ${res} 0 ${output} Add User To Group [Documentation] Add a user to a given OCP user group From 4643cd69f99a13d5193f8086b989388fcdc01f5c Mon Sep 17 00:00:00 2001 From: manosnoam Date: Fri, 5 Jan 2024 00:37:23 +0000 Subject: [PATCH 20/31] New Keyword: Assign Permissions To User in Project Signed-off-by: manosnoam --- ..._dashboard_projects_permissions_mgmt.robot | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index 52650b710..bbbab1e5f 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -82,19 +82,24 @@ Verify User Can Assign Access Permissions To User Groups Verify Project Sharing Does Not Override Dashboard Permissions [Tags] Tier1 Sanity ODS-2223 - [Setup] Run Keywords Restore Permissions Of The Project - ... AND Set RHODS Users Group To rhods-users - # [Setup] Set RHODS Users Group To rhods-users - Launch Data Science Project Main Page username=${TEST_USER.USERNAME} - Move To Tab Permissions - Remove User From Group username=${USER_B} - ... group_name=rhods-users - Remove User From Group username=${USER_C} - ... group_name=rhods-users - Assign Admin Permissions To User ${USER_B} - Assign Edit Permissions To User ${USER_C} - ${USER_B} Should Not Have Access To ${PRJ_USER_B_TITLE} - ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} + # [Setup] Run Keywords Restore Permissions Of The Project + # ... AND Set RHODS Users Group To rhods-users + [Setup] Set RHODS Users Group To rhods-users + # Launch Data Science Project Main Page username=${TEST_USER.USERNAME} + Launch Data Science Project Main Page username=${OCP_ADMIN_USER.USERNAME} password=${OCP_ADMIN_USER.PASSWORD} + ... ocp_user_auth_type=${OCP_ADMIN_USER.AUTH_TYPE} + # Switch To User ${USER_A} + # Open Data Science Projects Home Page + Assign Admin Permissions To User ${USER_B} in Project ${PRJ_USER_B_TITLE} + Assign Edit Permissions To User ${USER_C} in Project ${PRJ_USER_C_TITLE} + Remove User From Group username=${USER_B} group_name=rhods-users + Remove User From Group username=${USER_C} group_name=rhods-users + Switch To User ${USER_B} + Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} + Page Should Contain Access permissions needed + Switch To User ${USER_C} + Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} + Page Should Contain Access permissions needed [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated ... AND Set User Groups For Testing @@ -106,7 +111,7 @@ Project Permissions Mgmt Suite Setup # robocop: disable Set Library Search Order SeleniumLibrary RHOSi Setup Set Standard RHODS Groups Variables - # Set Default Access Groups Settings + Set Default Access Groups Settings ${to_delete}= Create List Set Suite Variable ${PROJECTS_TO_DELETE} ${to_delete} Launch RHODS Dashboard Session With User A @@ -284,3 +289,10 @@ ${username} Should Not Have Access To ${project_title} Project Should Not Be Listed project_title=${project_title} RoleBinding Should Not Exist project_title=${project_title} ... subject_name=${username} + +Assign ${permission_type} Permissions To User ${username} in Project ${project_title} + Open Data Science Projects Home Page + Wait Until Project Is Listed project_title=${project_title} + Open Data Science Project Details Page ${project_title} + Move To Tab Permissions + Assign ${permission_type} Permissions To User ${username} \ No newline at end of file From 36943b99709286d38358b2298571e369b01793ae Mon Sep 17 00:00:00 2001 From: manosnoam Date: Fri, 5 Jan 2024 00:57:57 +0000 Subject: [PATCH 21/31] New Keyword: Verify No Permissions For User Signed-off-by: manosnoam --- ...ds_dashboard_projects_permissions_mgmt.robot | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index bbbab1e5f..6c58bd77b 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -85,21 +85,15 @@ Verify Project Sharing Does Not Override Dashboard Permissions # [Setup] Run Keywords Restore Permissions Of The Project # ... AND Set RHODS Users Group To rhods-users [Setup] Set RHODS Users Group To rhods-users - # Launch Data Science Project Main Page username=${TEST_USER.USERNAME} Launch Data Science Project Main Page username=${OCP_ADMIN_USER.USERNAME} password=${OCP_ADMIN_USER.PASSWORD} ... ocp_user_auth_type=${OCP_ADMIN_USER.AUTH_TYPE} - # Switch To User ${USER_A} - # Open Data Science Projects Home Page Assign Admin Permissions To User ${USER_B} in Project ${PRJ_USER_B_TITLE} Assign Edit Permissions To User ${USER_C} in Project ${PRJ_USER_C_TITLE} Remove User From Group username=${USER_B} group_name=rhods-users Remove User From Group username=${USER_C} group_name=rhods-users + Verify No Permissions For User ${USER_B} + Verify No Permissions For User ${USER_C} Switch To User ${USER_B} - Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} - Page Should Contain Access permissions needed - Switch To User ${USER_C} - Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} - Page Should Contain Access permissions needed [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated ... AND Set User Groups For Testing @@ -295,4 +289,9 @@ Assign ${permission_type} Permissions To User ${username} in Project ${project_t Wait Until Project Is Listed project_title=${project_title} Open Data Science Project Details Page ${project_title} Move To Tab Permissions - Assign ${permission_type} Permissions To User ${username} \ No newline at end of file + Assign ${permission_type} Permissions To User ${username} + +Verify No Permissions For User ${username} + Switch To User ${username} + Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} + Page Should Contain Access permissions needed \ No newline at end of file From bdff16b4910d4efbe54f5397b0e6f936d7d0b238 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Fri, 5 Jan 2024 08:56:39 +0000 Subject: [PATCH 22/31] Rebase Signed-off-by: manosnoam --- ..._dashboard_projects_permissions_mgmt.robot | 84 +++++++++---------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index 6c58bd77b..a298b5010 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -1,10 +1,8 @@ *** Settings *** -Documentation Suite to test additional scenarios for Data Science Projects (a.k.a DSG) feature - -Resource ../../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource - -Suite Setup Project Permissions Mgmt Suite Setup -Suite Teardown Project Permissions Mgmt Suite Teardown +Documentation Suite to test additional scenarios for Data Science Projects (a.k.a DSG) feature +Resource ../../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +Suite Setup Project Permissions Mgmt Suite Setup +Suite Teardown Project Permissions Mgmt Suite Teardown *** Variables *** @@ -27,14 +25,16 @@ ${PRJ_USER_C_TITLE}= ${PRJ_BASE_TITLE}-${TEST_USER_4.USERNAME} *** Test Cases *** Verify User Can Access Permission Tab In Their Owned DS Project [Documentation] Verify user has access to "Permissions" tab in their DS Projects - [Tags] Tier1 Smoke OpenDataHub ODS-2194 - Pass Execution The Test is executed as part of Suite Setup + [Tags] Tier1 Smoke OpenDataHub + ... ODS-2194 + Pass Execution The Test is executed as part of Suite Setup Verify User Can Make Their Owned DS Project Accessible To Other Users # robocop: disable [Documentation] Verify user can give access permissions for their DS Projects to other users - [Tags] Tier1 Sanity ODS-2201 - Switch To User ${USER_B} - Move To Tab Permissions + [Tags] Tier1 Sanity + ... ODS-2201 + Switch To User ${USER_B} + Move To Tab Permissions Assign Edit Permissions To User ${USER_C} Assign Admin Permissions To User ${USER_A} ${USER_C} Should Have Edit Access To ${PRJ_USER_B_TITLE} @@ -42,42 +42,44 @@ Verify User Can Make Their Owned DS Project Accessible To Other Users # roboc Verify User Can Modify And Revoke Access To DS Projects From Other Users # robocop: disable [Documentation] Verify user can modify/remove access permissions for their DS Projects to other users - [Tags] Tier1 Sanity ODS-2202 - Switch To User ${USER_B} - Move To Tab Permissions + [Tags] Tier1 Sanity + ... ODS-2202 + Switch To User ${USER_B} + Move To Tab Permissions Change ${USER_C} Permissions To Admin Change ${USER_A} Permissions To Edit Refresh Pages ${USER_C} Should Have Admin Access To ${PRJ_USER_B_TITLE} ${USER_A} Should Have Edit Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} - Move To Tab Permissions + Switch To User ${USER_B} + Move To Tab Permissions Remove ${USER_C} Permissions ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} Verify User Can Assign Access Permissions To User Groups - [Tags] Tier1 Sanity ODS-2208 - [Setup] Restore Permissions Of The Project - Switch To User ${USER_B} + [Tags] Tier1 Sanity + ... ODS-2208 + [Setup] Restore Permissions Of The Project + Switch To User ${USER_B} Assign Edit Permissions To Group ${USER_GROUP_1} Assign Admin Permissions To Group ${USER_GROUP_2} - RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} - ... subject_name=${USER_GROUP_1} + RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} + ... subject_name=${USER_GROUP_1} - RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} - ... subject_name=${USER_GROUP_2} - Sleep 5s + RoleBinding Should Exist project_title=${PRJ_USER_B_TITLE} + ... subject_name=${USER_GROUP_2} + Sleep 5s ${USER_A} Should Have Edit Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Have Admin Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} + Switch To User ${USER_B} Change ${USER_GROUP_1} Permissions To Admin Change ${USER_GROUP_2} Permissions To Edit - Sleep 5s + Sleep 5s ${USER_A} Should Have Admin Access To ${PRJ_USER_B_TITLE} ${USER_C} Should Have Edit Access To ${PRJ_USER_B_TITLE} - Switch To User ${USER_B} + Switch To User ${USER_B} Remove ${USER_GROUP_2} Permissions - Sleep 5s + Sleep 5s ${USER_C} Should Not Have Access To ${PRJ_USER_B_TITLE} Verify Project Sharing Does Not Override Dashboard Permissions @@ -101,7 +103,7 @@ Verify Project Sharing Does Not Override Dashboard Permissions *** Keywords *** Project Permissions Mgmt Suite Setup # robocop: disable [Documentation] Suite setup steps for testing DS Projects. - ... It creates some test variables and runs RHOSi setup + ... It creates some test variables and runs RHOSi setup Set Library Search Order SeleniumLibrary RHOSi Setup Set Standard RHODS Groups Variables @@ -116,9 +118,9 @@ Project Permissions Mgmt Suite Setup # robocop: disable Project Permissions Mgmt Suite Teardown [Documentation] Suite teardown steps after testing DSG. It Deletes - ... all the DS projects created by the tests and run RHOSi teardown + ... all the DS projects created by the tests and run RHOSi teardown Close All Browsers - Delete Data Science Projects From CLI ocp_projects=${PROJECTS_TO_DELETE} + Delete Data Science Projects From CLI ocp_projects=${PROJECTS_TO_DELETE} RHOSi Teardown Remove User From Group username=${USER_A} ... group_name=rhods-users @@ -143,9 +145,9 @@ Switch To User Set Suite Variable ${IS_CLUSTER_ADMIN} ${is_cluster_admin} Launch RHODS Dashboard Session With User A - Launch Dashboard ocp_user_name=${TEST_USER_2.USERNAME} ocp_user_pw=${TEST_USER_2.PASSWORD} + Launch Dashboard ocp_user_name=${TEST_USER_2.USERNAME} ocp_user_pw=${TEST_USER_2.PASSWORD} ... ocp_user_auth_type=${TEST_USER_2.AUTH_TYPE} dashboard_url=${ODH_DASHBOARD_URL} - ... browser=${BROWSER.NAME} browser_options=${BROWSER.OPTIONS} + ... browser=${BROWSER.NAME} browser_options=${BROWSER.OPTIONS} ... browser_alias=${TEST_USER_2.USERNAME}-session Launch RHODS Dashboard Session And Create A DS Project With User B @@ -218,18 +220,14 @@ Reload Page If Project ${project_title} Is Not Listed ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${FALSE} - # robocop:disable - Log - ... message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! + Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! # robocop:disable ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${FALSE} - # robocop:disable - Log - ... message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! (2) + Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! (2) # robocop:disable ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} @@ -240,18 +238,14 @@ Reload Page If Project ${project_title} Is Listed ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${TRUE} - # robocop:disable - Log - ... message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! + Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! # robocop:disable ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${TRUE} - # robocop:disable - Log - ... message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! (2) + Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! (2) # robocop:disable ... level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} From 5becb29fd15fec13c4031f7632bff031196bdfc0 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Sun, 7 Jan 2024 16:54:14 +0000 Subject: [PATCH 23/31] 'Reload Page If Project Is/Not Listed' Keyword with WHILE and Timeout Signed-off-by: manosnoam --- .../Permissions.resource | 2 +- ..._dashboard_projects_permissions_mgmt.robot | 36 ++++++++----------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index 152590b03..691dce3c2 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -31,7 +31,7 @@ Change ${username} Permissions To ${permission_type} Save Permission Remove ${username} Permissions - [Documentation] Remove the the access to the given user ${username} + [Documentation] Remove the access to the given user ${username} ... from the currently open DS Project in UI Permissions.Click Action From Actions Menu username=${username} ... action=Delete diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index a298b5010..74d50bc05 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -92,10 +92,11 @@ Verify Project Sharing Does Not Override Dashboard Permissions Assign Admin Permissions To User ${USER_B} in Project ${PRJ_USER_B_TITLE} Assign Edit Permissions To User ${USER_C} in Project ${PRJ_USER_C_TITLE} Remove User From Group username=${USER_B} group_name=rhods-users + Remove User From Group username=${USER_B} group_name=rhods-admins Remove User From Group username=${USER_C} group_name=rhods-users + Remove User From Group username=${USER_C} group_name=rhods-admins Verify No Permissions For User ${USER_B} Verify No Permissions For User ${USER_C} - Switch To User ${USER_B} [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated ... AND Set User Groups For Testing @@ -217,38 +218,28 @@ Refresh Pages ... wait_for_cards=${FALSE} Reload Page If Project ${project_title} Is Not Listed - ${is_listed}= Run Keyword And Return Status - ... Project Should Be Listed project_title=${project_title} - IF ${is_listed} == ${FALSE} - Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! # robocop:disable - ... level=WARN - Reload RHODS Dashboard Page expected_page=Data Science Projects - ... wait_for_cards=${FALSE} + ${is_listed} = Set Variable ${FALSE} + WHILE not ${is_listed} limit=3m on_limit_message=Timeout exceeded waiting for project ${project_title} to be listed # robotcode: ignore ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${FALSE} - Log message=Project ${project_title} is not listed as expected: reloading DS Project page to refresh project list! (2) # robocop:disable - ... level=WARN + Log message=Project ${project_title} is not listed but expected: Reloading DS Project page to refresh project list! level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} + Sleep 5s END END Reload Page If Project ${project_title} Is Listed - ${is_listed}= Run Keyword And Return Status - ... Project Should Be Listed project_title=${project_title} - IF ${is_listed} == ${TRUE} - Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! # robocop:disable - ... level=WARN - Reload RHODS Dashboard Page expected_page=Data Science Projects - ... wait_for_cards=${FALSE} + ${is_listed} = Set Variable ${TRUE} + WHILE ${is_listed} limit=3m on_limit_message=Timeout exceeded waiting for project ${project_title} NOT expected to be listed # robotcode: ignore ${is_listed}= Run Keyword And Return Status ... Project Should Be Listed project_title=${project_title} IF ${is_listed} == ${TRUE} - Log message=Project ${project_title} is still listed as NOT expected: reloading DS Project page to refresh project list! (2) # robocop:disable - ... level=WARN + Log message=Project ${project_title} is still listed but NOT expected: Reloading DS Project page to refresh project list! level=WARN Reload RHODS Dashboard Page expected_page=Data Science Projects ... wait_for_cards=${FALSE} + Sleep 5s END END @@ -287,5 +278,8 @@ Assign ${permission_type} Permissions To User ${username} in Project ${project_t Verify No Permissions For User ${username} Switch To User ${username} - Wait for RHODS Dashboard to Load expected_page=${NONE} wait_for_cards=${FALSE} - Page Should Contain Access permissions needed \ No newline at end of file + ${permissions_set} = Set Variable ${FALSE} + WHILE not ${permissions_set} limit=3m on_limit_message=Timeout exceeded waiting for user ${username} permissions to be updated # robotcode: ignore + ${permissions_set}= Run Keyword And Return Status Wait Until Page Contains Access permissions needed timeout=15 + IF ${permissions_set} == ${FALSE} Reload Page + END From d938fc7cbf3872e6a426402cc59285def47fdcda Mon Sep 17 00:00:00 2001 From: Andrej Podhradsky Date: Wed, 3 Jan 2024 16:20:44 +0100 Subject: [PATCH 24/31] RHODS-13159: Use the new parameter 'base_domain' in ods-ci Signed-off-by: Andrej Podhradsky --- .../infrastructure_configuration_variables.md | 2 +- .../Provisioning/Hive/AWS/aws-cluster.yaml | 4 ++-- .../Provisioning/Hive/GCP/gcp-cluster.yaml | 4 ++-- .../Provisioning/Hive/OSP/create_fips.sh | 22 +++++++++---------- .../Hive/OSP/hive_osp_cluster_template.yaml | 4 ++-- .../Provisioning/Hive/provision.robot | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ods_ci/docs/infrastructure_configuration_variables.md b/ods_ci/docs/infrastructure_configuration_variables.md index 725f228e9..11d0442a8 100644 --- a/ods_ci/docs/infrastructure_configuration_variables.md +++ b/ods_ci/docs/infrastructure_configuration_variables.md @@ -9,7 +9,7 @@ The infrastructure configuration variables are used to configure the infrastruct | `hive_claim_name` | The name of the claim. | `rhods{provider}claim` | `all` | | `hive_claim_ns` | The namespace of the claim. | `rhods` | `all` | | `image_set` | The image set name to use for the cluster. | `rhods-openshift` | `all` | -| `aws_domain` | The AWS domain to use for the cluster. | `rhods.ccitredhat.com` | `aws` | +| `base_domain` | The base domain to use for the cluster. | `""` | `aws` | | `worker_node_instance_type` | The instance type to use for the worker nodes. | `m5.xlarge` | `all` | | `worker_node_replicas` | The number of worker nodes to create. | `2` | `all` | | `master_node_instance_type` | The AWS instance type to use for the master nodes. | `m5.xlarge` | `all` | diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml index c94adae44..569afc94f 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml @@ -7,7 +7,7 @@ items: name: {{ hive_cluster_name|default("rhodsaws") }}-pool namespace: rhods spec: - baseDomain: rhods.ccitredhat.com + baseDomain: {{ base_domain }} imageSetRef: name: {{ image_set|default("rhods-openshift") }} platform: @@ -28,7 +28,7 @@ items: stringData: install-config.yaml: | apiVersion: v1 - baseDomain: rhods.ccitredhat.com + baseDomain: {{ base_domain }} compute: - name: worker platform: diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml index 3fc8a0a68..3dcf24c2e 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml @@ -7,7 +7,7 @@ items: name: {{ hive_cluster_name|default("rhodsgcp") }}-pool namespace: rhods spec: - baseDomain: gcp.rhods.ccitredhat.com + baseDomain: {{ base_domain }} imageSetRef: name: {{ image_set|default("rhods-openshift") }} platform: @@ -28,7 +28,7 @@ items: stringData: install-config.yaml: | apiVersion: v1 - baseDomain: rhods.ccitredhat.com + baseDomain: {{ base_domain }} compute: - name: worker platform: diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/OSP/create_fips.sh b/ods_ci/tasks/Resources/Provisioning/Hive/OSP/create_fips.sh index d10bb9b19..71e546077 100755 --- a/ods_ci/tasks/Resources/Provisioning/Hive/OSP/create_fips.sh +++ b/ods_ci/tasks/Resources/Provisioning/Hive/OSP/create_fips.sh @@ -4,7 +4,7 @@ # Global vars export CLUSTER_NAME=${1:-$CLUSTER_NAME} -export AWS_DOMAIN=${2:-$AWS_DOMAIN} +export BASE_DOMAIN=${2:-$BASE_DOMAIN} export OSP_NETWORK=${3:-$OSP_NETWORK} export OSP_CLOUD=${4:-openstack} export OUTPUT_DIR=${5:-.${CLUSTER_NAME}_conf} @@ -12,15 +12,15 @@ export OUTPUT_DIR=${5:-.${CLUSTER_NAME}_conf} # Cluster name should be converted to lowercase export CLUSTER_NAME=${CLUSTER_NAME,,} -if [[ -z $CLUSTER_NAME || -z $AWS_DOMAIN || -z $OSP_NETWORK ]] ; then +if [[ -z $CLUSTER_NAME || -z $BASE_DOMAIN || -z $OSP_NETWORK ]] ; then echo -e "Some global variables are missing, for example: # export CLUSTER_NAME=${CLUSTER_NAME:-"rhods-qe-007"} # To set the cluster Subdomain (A Record) in AWS. - # export AWS_DOMAIN=${AWS_DOMAIN:-"rhods.ccitredhat.com"} # To set the cluster Domain in AWS. + # export BASE_DOMAIN=${BASE_DOMAIN:-"rhods.ccitredhat.com"} # To set the cluster Domain in AWS. # export OSP_NETWORK=${OSP_NETWORK:-"shared_net_5"} # The external network for the new Floating IPs on OSP. " exit 1 else - echo "Creating Floating IPs on OSP external network '$OSP_NETWORK' and A records in AWS domain: $CLUSTER_NAME.$AWS_DOMAIN" + echo "Creating Floating IPs on OSP external network '$OSP_NETWORK' and A records in AWS domain: $CLUSTER_NAME.$BASE_DOMAIN" fi export OS_CLOUD=${OSP_CLOUD} @@ -69,10 +69,10 @@ echo "" echo "" echo "FLOATING IP'S" echo "========================================================================" -echo "cluster's apiFloatingIP api.$CLUSTER_NAME.$AWS_DOMAIN -> $FIP_API" +echo "cluster's apiFloatingIP api.$CLUSTER_NAME.$BASE_DOMAIN -> $FIP_API" echo "" echo "" -echo "cluster's ingressFloatingIP *.apps.$CLUSTER_NAME.$AWS_DOMAIN -> $FIP_APPS" +echo "cluster's ingressFloatingIP *.apps.$CLUSTER_NAME.$BASE_DOMAIN -> $FIP_APPS" echo "" echo "" echo "========================================================================" @@ -80,16 +80,16 @@ echo "========================================================================" echo "Getting zone ID in Route53" ZONES=$(aws route53 list-hosted-zones --output json) -ZONE_ID=$(echo "$ZONES" | jq -r ".HostedZones[] | select(.Name==\"$AWS_DOMAIN.\") | .Id") +ZONE_ID=$(echo "$ZONES" | jq -r ".HostedZones[] | select(.Name==\"$BASE_DOMAIN.\") | .Id") if [[ -z "$ZONE_ID" ]] ; then - echo "Domain $AWS_DOMAIN not found in Route53" + echo "Domain $BASE_DOMAIN not found in Route53" exit 20 fi echo "Updating DNS records (cluster api's) in AWS Route53" RESPONSE=$(aws route53 change-resource-record-sets --hosted-zone-id "$ZONE_ID" --change-batch \ '{ "Comment": "Update A record for cluster API", "Changes": -[ { "Action": "UPSERT", "ResourceRecordSet": { "Name": "api.'"$CLUSTER_NAME"'.'"$AWS_DOMAIN"'", +[ { "Action": "UPSERT", "ResourceRecordSet": { "Name": "api.'"$CLUSTER_NAME"'.'"$BASE_DOMAIN"'", "Type": "A", "TTL": 172800, "ResourceRecords": [ { "Value": "'"$FIP_API"'" } ] } } ] }' --output json) || rc=$? if [[ -n "$rc" ]] ; then echo -e "Failed to update DNS A record in AWS for cluster API. @@ -104,7 +104,7 @@ aws route53 wait resource-record-sets-changed --id "$(echo "$RESPONSE" | jq -r ' echo "Updating DNS records (cluster ingress) in AWS Route53" RESPONSE=$(aws route53 change-resource-record-sets --hosted-zone-id "$ZONE_ID" --change-batch \ '{ "Comment": "Update A record for cluster APPS", "Changes": -[ { "Action": "UPSERT", "ResourceRecordSet": { "Name": "*.apps.'"$CLUSTER_NAME"'.'"$AWS_DOMAIN"'", +[ { "Action": "UPSERT", "ResourceRecordSet": { "Name": "*.apps.'"$CLUSTER_NAME"'.'"$BASE_DOMAIN"'", "Type": "A", "TTL": 172800, "ResourceRecords": [ { "Value": "'"$FIP_APPS"'" } ] } } ] }' --output json) || rc=$? if [[ -n "$rc" ]] ; then @@ -118,7 +118,7 @@ echo "Waiting for DNS change to propagate" aws route53 wait resource-record-sets-changed --id "$(echo "$RESPONSE" | jq -r '.ChangeInfo.Id')" mkdir -p "$OUTPUT_DIR" -export CLUSTER_FIPS="$OUTPUT_DIR/$CLUSTER_NAME.$AWS_DOMAIN.fips" +export CLUSTER_FIPS="$OUTPUT_DIR/$CLUSTER_NAME.$BASE_DOMAIN.fips" echo "Exporting Floating IPs of API '$FIP_API' and *APPS '$FIP_APPS', and saving into: $CLUSTER_FIPS" : > "$CLUSTER_FIPS" diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/OSP/hive_osp_cluster_template.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/OSP/hive_osp_cluster_template.yaml index 8d911fb9c..109cc393c 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/OSP/hive_osp_cluster_template.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/OSP/hive_osp_cluster_template.yaml @@ -7,7 +7,7 @@ items: name: ${infrastructure_configurations}[hive_cluster_name]-pool namespace: ${infrastructure_configurations}[hive_claim_ns] spec: - baseDomain: ${infrastructure_configurations}[aws_domain] + baseDomain: ${infrastructure_configurations}[base_domain] imageSetRef: name: ${infrastructure_configurations}[image_set] # see line 100 inventory: @@ -33,7 +33,7 @@ items: stringData: install-config.yaml: | apiVersion: v1 - baseDomain: ${infrastructure_configurations}[aws_domain] + baseDomain: ${infrastructure_configurations}[base_domain] compute: - name: worker platform: diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot b/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot index 1b9ade54c..e986c0761 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot +++ b/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot @@ -101,11 +101,11 @@ Create Floating IPs Create File ${osp_clouds_yaml} ${result.stdout} File Should Not Be Empty ${osp_clouds_yaml} ${shell_script} = Catenate - ... ${CURDIR}/OSP/create_fips.sh ${cluster_name} ${infrastructure_configurations}[aws_domain] + ... ${CURDIR}/OSP/create_fips.sh ${cluster_name} ${infrastructure_configurations}[base_domain] ... ${infrastructure_configurations}[osp_network] ${infrastructure_configurations}[osp_cloud_name] ${artifacts_dir}/ ${return_code} = Run and Watch Command ${shell_script} output_should_contain=Exporting Floating IPs Should Be Equal As Integers ${return_code} 0 msg=Error creating floating IPs for cluster '${cluster_name}' - ${fips_file_to_export} = Set Variable ${artifacts_dir}/${cluster_name}.${infrastructure_configurations}[aws_domain].fips + ${fips_file_to_export} = Set Variable ${artifacts_dir}/${cluster_name}.${infrastructure_configurations}[base_domain].fips Export Variables From File ${fips_file_to_export} Watch Hive Install Log From 6b14f797124d0ebee3ce9ee1f88c998c1afc1d51 Mon Sep 17 00:00:00 2001 From: Andrej Podhradsky Date: Thu, 4 Jan 2024 15:17:56 +0100 Subject: [PATCH 25/31] Reduce the line length Co-authored-by: Jan Stourac --- ods_ci/tasks/Resources/Provisioning/Hive/provision.robot | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot b/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot index e986c0761..6f07c0bf9 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot +++ b/ods_ci/tasks/Resources/Provisioning/Hive/provision.robot @@ -105,7 +105,8 @@ Create Floating IPs ... ${infrastructure_configurations}[osp_network] ${infrastructure_configurations}[osp_cloud_name] ${artifacts_dir}/ ${return_code} = Run and Watch Command ${shell_script} output_should_contain=Exporting Floating IPs Should Be Equal As Integers ${return_code} 0 msg=Error creating floating IPs for cluster '${cluster_name}' - ${fips_file_to_export} = Set Variable ${artifacts_dir}/${cluster_name}.${infrastructure_configurations}[base_domain].fips + ${fips_file_to_export} = Set Variable + ... ${artifacts_dir}/${cluster_name}.${infrastructure_configurations}[base_domain].fips Export Variables From File ${fips_file_to_export} Watch Hive Install Log From 9c486a39686cb0fded20c187fa307f1316bc2be9 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Mon, 8 Jan 2024 14:42:45 +0000 Subject: [PATCH 26/31] Capture screenshot at Teardown of Keyword 'User Should Not Be Allowed' Signed-off-by: manosnoam --- ods_ci/tests/Resources/ODS.robot | 1 - .../ODHDashboardSettings.resource | 39 ++++++++++++- .../Permissions.resource | 57 +++---------------- .../400__ods_dashboard.robot | 13 ++++- ..._dashboard_projects_permissions_mgmt.robot | 20 +++---- 5 files changed, 64 insertions(+), 66 deletions(-) diff --git a/ods_ci/tests/Resources/ODS.robot b/ods_ci/tests/Resources/ODS.robot index 1924c622d..14122fedf 100644 --- a/ods_ci/tests/Resources/ODS.robot +++ b/ods_ci/tests/Resources/ODS.robot @@ -91,7 +91,6 @@ Set Standard RHODS Groups Variables Set Suite Variable ${STANDARD_SYSTEM_GROUP} system:authenticated Set Suite Variable ${STANDARD_USERS_GROUP} rhods-users - Apply Access Groups Settings [Documentation] Changes the rhods-groups config map to set the new access configuration ... and rolls out JH to make the changes effecting in Jupyter diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDashboardSettings.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDashboardSettings.resource index d14038c88..75b37cc23 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDashboardSettings.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDashboardSettings.resource @@ -2,6 +2,7 @@ Library OpenShiftLibrary Resource ../../LoginPage.robot Resource ../../ODH/JupyterHub/LoginJupyterHub.robot +Resource ../../../ODS.robot *** Variables *** @@ -9,7 +10,7 @@ ${TOLERATION_CHECKBOX}= //input[@id="tolerations-enabled-checkbox"] ${GROUP_BTN_XP}= (//*[@class="pf-c-chip-group"])//*[@class="pf-c-chip__text" ]//following-sibling::button[1] ${SINGLE_MODE_SERVING_CHECK_BOX}= //input[@id="single-model-serving-platform-enabled-checkbox"] ${MULTI_MODE_SERVING_CHECK_BOX}= //input[@id="multi-model-serving-platform-enabled-checkbox"] - +${CUSTOM_EMPTY_GROUP}= empty-group *** Keywords *** Add OpenShift Groups To Data Science Administrators @@ -306,3 +307,39 @@ Check IF Multi Model Serving IS Enabled From DSC And Cluster Setting ${status}= Get Checkbox State Of Multi Model Serving Platforms Should Be Equal ${status} True Element Should Be Enabled ${MULTI_MODEL_SERVING_CHECK_BOX} + +Set RHODS Admins Group Empty Group + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the given empty group (i.e., with no users) + Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} + +Set RHODS Admins Group To system:authenticated # robocop:disable + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the system:authenticated group + Set Access Groups Settings admins_group=system:authenticated + ... users_group=${STANDARD_SYSTEM_GROUP} + +Set RHODS Admins Group To Inexistent Group + [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap + ... to the given inexistent group + Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} + +Set RHODS Users Group Empty Group + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the given empty group (i.e., with no users) + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${CUSTOM_EMPTY_GROUP} + +Set RHODS Users Group To rhods-users # robocop:disable + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the rhods-users group + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${STANDARD_USERS_GROUP} + +Set RHODS Users Group To Inexistent Group + [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap + ... to the given inexistent group + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${CUSTOM_INEXISTENT_GROUP} diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource index 691dce3c2..cda7ed9a1 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource @@ -1,14 +1,12 @@ *** Settings *** Documentation Collection of keywords to interact with Storages Resource ./Projects.resource -Resource ../../../../../Resources/ODS.robot *** Variables *** ${SAVE_BUTTON}= xpath://button[@data-id="save-rolebinding-button"] ${PERMISSIONS_DROPDOWN}= xpath://td[@data-label="Permission"]//button[@aria-label="Options menu"] ${IS_CLUSTER_ADMIN}= ${FALSE} -${CUSTOM_EMPTY_GROUP}= empty-group *** Keywords *** @@ -22,6 +20,13 @@ Assign ${permission_type} Permissions To User ${username} Select Permission Type permission_type=${permission_type} Save Permission +Assign ${permission_type} Permissions To User ${username} in Project ${project_title} + Open Data Science Projects Home Page + Wait Until Project Is Listed project_title=${project_title} + Open Data Science Project Details Page ${project_title} + Move To Tab Permissions + Assign ${permission_type} Permissions To User ${username} + Change ${username} Permissions To ${permission_type} [Documentation] Change the level of permission ${permission_type} for the given user ${username} ... in the currently open DS Project in UI @@ -104,51 +109,3 @@ Is ${username} In The Permissions Table ${present}= Run Keyword And Return Status ... Page Should Contain Element xpath=//tr[td[@data-label="Username"]//*[text()="${username}"]] RETURN ${present} - -Set RHODS Admins Group Empty Group - [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap - ... to the given empty group (i.e., with no users) - Set Access Groups Settings admins_group=${CUSTOM_EMPTY_GROUP} - ... users_group=${STANDARD_SYSTEM_GROUP} - -Set RHODS Admins Group To system:authenticated # robocop:disable - [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap - ... to the system:authenticated group - Set Access Groups Settings admins_group=system:authenticated - ... users_group=${STANDARD_SYSTEM_GROUP} - -Set RHODS Admins Group To Inexistent Group - [Documentation] Sets the "adminGroups" field in "odh-dashboard-config" ConfigMap - ... to the given inexistent group - Set Access Groups Settings admins_group=${CUSTOM_INEXISTENT_GROUP} - ... users_group=${STANDARD_SYSTEM_GROUP} - -Set RHODS Users Group Empty Group - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the given empty group (i.e., with no users) - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_EMPTY_GROUP} - -Set RHODS Users Group To rhods-users # robocop:disable - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the rhods-users group - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_USERS_GROUP} - -Set RHODS Users Group To Inexistent Group - [Documentation] Sets the "allowedGroups" field in "odh-dashboard-config" ConfigMap - ... to the given inexistent group - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${CUSTOM_INEXISTENT_GROUP} - -Set Default Groups And Check Logs Do Not Change - [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "odh-dashboard-config" - ... ConfigMap and checks if no new lines are generated in the logs after that. - [Arguments] ${delete_group}=${FALSE} - ${lengths_dict}= Get Lengths Of Dashboard Pods Logs - Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} - ... users_group=${STANDARD_SYSTEM_GROUP} - Logs Of Dashboard Pods Should Not Contain New Lines lengths_dict=${lengths_dict} - IF "${delete_group}" == "${TRUE}" - Delete Group group_name=${CUSTOM_EMPTY_GROUP} - END diff --git a/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot b/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot index cab8d854d..d935e650e 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/400__ods_dashboard.robot @@ -5,7 +5,6 @@ Resource ../../Resources/RHOSi.resource Resource ../../Resources/ODS.robot Resource ../../Resources/Page/ODH/ODHDashboard/ODHDashboard.resource Resource ../../Resources/Page/ODH/ODHDashboard/ODHDashboardResources.resource -Resource ../../Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Permissions.resource Resource ../../Resources/Page/ODH/AiApps/Anaconda.resource Resource ../../Resources/Page/LoginPage.robot Resource ../../Resources/Page/OCPLogin/OCPLogin.robot @@ -399,6 +398,18 @@ Logs Of Dashboard Pods Should Not Contain New Lines Run Keyword And Continue On Failure Should Be Equal ${new_lines_flag} ${FALSE} END +Set Default Groups And Check Logs Do Not Change + [Documentation] Teardown for ODS-1408 and ODS-1494. It sets the default configuration of "odh-dashboard-config" + ... ConfigMap and checks if no new lines are generated in the logs after that. + [Arguments] ${delete_group}=${FALSE} + ${lengths_dict}= Get Lengths Of Dashboard Pods Logs + Set Access Groups Settings admins_group=${STANDARD_ADMINS_GROUP} + ... users_group=${STANDARD_SYSTEM_GROUP} + Logs Of Dashboard Pods Should Not Contain New Lines lengths_dict=${lengths_dict} + IF "${delete_group}" == "${TRUE}" + Delete Group group_name=${CUSTOM_EMPTY_GROUP} + END + Favorite Items Should Be Listed First [Documentation] Compares the ids and checks that favorite Items ... are listed first diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot index 74d50bc05..c12219c0c 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects_permissions_mgmt.robot @@ -84,8 +84,6 @@ Verify User Can Assign Access Permissions To User Groups Verify Project Sharing Does Not Override Dashboard Permissions [Tags] Tier1 Sanity ODS-2223 - # [Setup] Run Keywords Restore Permissions Of The Project - # ... AND Set RHODS Users Group To rhods-users [Setup] Set RHODS Users Group To rhods-users Launch Data Science Project Main Page username=${OCP_ADMIN_USER.USERNAME} password=${OCP_ADMIN_USER.PASSWORD} ... ocp_user_auth_type=${OCP_ADMIN_USER.AUTH_TYPE} @@ -95,9 +93,9 @@ Verify Project Sharing Does Not Override Dashboard Permissions Remove User From Group username=${USER_B} group_name=rhods-admins Remove User From Group username=${USER_C} group_name=rhods-users Remove User From Group username=${USER_C} group_name=rhods-admins - Verify No Permissions For User ${USER_B} - Verify No Permissions For User ${USER_C} - [Teardown] Run Keywords Set RHODS Admins Group To system:authenticated + User ${USER_B} Should Not Be Allowed To Dashboard + User ${USER_C} Should Not Be Allowed To Dashboard + [Teardown] Run Keywords Set Default Access Groups Settings ... AND Set User Groups For Testing @@ -229,6 +227,7 @@ Reload Page If Project ${project_title} Is Not Listed Sleep 5s END END + [Teardown] Capture Page Screenshot Reload Page If Project ${project_title} Is Listed ${is_listed} = Set Variable ${TRUE} @@ -242,6 +241,7 @@ Reload Page If Project ${project_title} Is Listed Sleep 5s END END + [Teardown] Capture Page Screenshot ${username} Should Have Edit Access To ${project_title} Switch To User ${username} @@ -269,17 +269,11 @@ ${username} Should Not Have Access To ${project_title} RoleBinding Should Not Exist project_title=${project_title} ... subject_name=${username} -Assign ${permission_type} Permissions To User ${username} in Project ${project_title} - Open Data Science Projects Home Page - Wait Until Project Is Listed project_title=${project_title} - Open Data Science Project Details Page ${project_title} - Move To Tab Permissions - Assign ${permission_type} Permissions To User ${username} - -Verify No Permissions For User ${username} +User ${username} Should Not Be Allowed To Dashboard Switch To User ${username} ${permissions_set} = Set Variable ${FALSE} WHILE not ${permissions_set} limit=3m on_limit_message=Timeout exceeded waiting for user ${username} permissions to be updated # robotcode: ignore ${permissions_set}= Run Keyword And Return Status Wait Until Page Contains Access permissions needed timeout=15 IF ${permissions_set} == ${FALSE} Reload Page END + [Teardown] Capture Page Screenshot From 7afdb10f5fb194ee444f37cc68ec057ca2b610df Mon Sep 17 00:00:00 2001 From: manosnoam Date: Tue, 9 Jan 2024 16:05:54 +0000 Subject: [PATCH 27/31] Verify GPU AcceleratorProfile is created after restarting Dashboard Add to gpu_deploy.sh script two verification steps after restarting rhods-dashboard deployment: - Wait for up to 3 minutes until the deployment is rolled out - Verify that an AcceleratorProfiles resource is created Signed-off-by: manosnoam --- ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh index 7c213a33e..18eae29dd 100755 --- a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh +++ b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh @@ -70,6 +70,12 @@ function rerun_accelerator_migration() { return 1 fi + echo "Waiting for up to 3 minutes until rhods-dashboard deployment is rolled out" + oc rollout status deployment.apps/rhods-dashboard -n redhat-ods-applications --watch --timeout 3m + + echo "Verifying that an AcceleratorProfiles resource was created in redhat-ods-applications" + oc describe AcceleratorProfiles -n redhat-ods-applications + } wait_until_pod_ready_status "gpu-operator" From 6bb4f8e813046ccd2bbc651ec3efdd7bc003f454 Mon Sep 17 00:00:00 2001 From: manosnoam Date: Tue, 9 Jan 2024 19:52:40 +0000 Subject: [PATCH 28/31] Simplified the function wait_until_pod_ready_status() The previous implementation of the function did not handle completed pods, so the script hanged for ~45 minutes waiting for completed pods (e.g. nvidia-cuda-validator pods) to become running: ``` 19:24:53 GPU installation seems to be still running ... 20:13:48 nvidia-cuda-validator-2jnxd 0/1 Completed 0 5h50m 20:13:48 nvidia-cuda-validator-nsf98 0/1 Completed 0 5h51m ... 21:11:34 ERROR: Timeout reached while waiting for gpu operator ``` A simple call to `oc wait --for=condition=ready pod -l app=$pod_label` within the function should resolve it. Signed-off-by: manosnoam --- .../Resources/Provisioning/GPU/gpu_deploy.sh | 50 ++++--------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh index 18eae29dd..f1a28336d 100755 --- a/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh +++ b/ods_ci/tasks/Resources/Provisioning/GPU/gpu_deploy.sh @@ -1,4 +1,6 @@ #!/bin/bash +set -e + # Make changes to gpu install file GPU_INSTALL_DIR="$(dirname "$0")" @@ -12,61 +14,32 @@ sed -i -e "0,/v1.11/s//$CHANNEL/g" -e "s/gpu-operator-certified.v1.11.0/$CSVNAME oc apply -f ${GPU_INSTALL_DIR}/gpu_install.yaml function wait_until_pod_ready_status() { - local timeout_seconds=1200 - local sleep_time=90 local pod_label=$1 local namespace=nvidia-gpu-operator - echo "Waiting until gpu pods are in running state..." - - SECONDS=0 - while [ "$SECONDS" -le "$timeout_seconds" ]; do - pod_status=$(oc get pods -lapp=$pod_label -n $namespace -ojsonpath='{range .items[*]}{.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' 2>/dev/null || echo "terminated") - if [ "$pod_status" == "True" ]; then - pod_terminating_status=$(oc get pods -lapp=$pod_label -n $namespace -o jsonpath='{.items[0].metadata.deletionGracePeriodSeconds}' 2>/dev/null || echo "terminated") - if [ "${pod_terminating_status}" != "" ]; then - echo "pod $pod_label is in terminating state..." - else - echo "Pod $pod_label is ready" - break; - fi - else - ((remaining_seconds = timeout_seconds - SECONDS)) - echo "GPU installation seems to be still running (timeout in $remaining_seconds seconds)..." - oc get pods -n $namespace - sleep $sleep_time - fi - done - - if [ "$pod_status" == "True" ] ; then - printf "GPU operator is up and running\n" - return 0 - else - printf "ERROR: Timeout reached while waiting for gpu operator to be in running state\n" - return 1 - fi - + echo "Waiting until GPU pods of '$pod_label' in namespace '$namespace' are in running state..." + oc wait --timeout=${timeout_seconds}s --for=condition=ready pod -n $namespace -l app="$pod_label" } function rerun_accelerator_migration() { -# As we are adding the GPUs after installing the RHODS operator, those GPUs are not discovered automatically. -# In order to rerun the migration we need to -# 1. Delete the migration configmap -# 2. Rollout restart dashboard deployment, so the configmap is created again and the migration run again -# Context: https://github.com/opendatahub-io/odh-dashboard/issues/1938 + # As we are adding the GPUs after installing the RHODS operator, those GPUs are not discovered automatically. + # In order to rerun the migration we need to + # 1. Delete the migration configmap + # 2. Rollout restart dashboard deployment, so the configmap is created again and the migration run again + # Context: https://github.com/opendatahub-io/odh-dashboard/issues/1938 echo "Deleting configmap migration-gpu-status" if ! oc delete configmap migration-gpu-status -n redhat-ods-applications; then - printf "ERROR: When trying to delete the migration-gpu-status configmap\n" + echo "ERROR: When trying to delete the migration-gpu-status configmap" return 1 fi echo "Rollout restart rhods-dashboard deployment" if ! oc rollout restart deployment.apps/rhods-dashboard -n redhat-ods-applications; then - printf "ERROR: When trying to rollout restart rhods-dashboard deployment\n" + echo "ERROR: When trying to rollout restart rhods-dashboard deployment" return 1 fi @@ -75,7 +48,6 @@ function rerun_accelerator_migration() { echo "Verifying that an AcceleratorProfiles resource was created in redhat-ods-applications" oc describe AcceleratorProfiles -n redhat-ods-applications - } wait_until_pod_ready_status "gpu-operator" From dea022c3b29a3c333a20ff1e633a8ad99d9b7306 Mon Sep 17 00:00:00 2001 From: Andrej Podhradsky Date: Mon, 18 Dec 2023 18:11:53 +0100 Subject: [PATCH 29/31] RHODS-12892: Parameterize the hive namespace The parameter hive_claim_ns is already used in hive_osp_cluster_template.yaml Signed-off-by: Andrej Podhradsky --- .../Resources/Provisioning/Hive/AWS/aws-cluster.yaml | 8 ++++---- .../Resources/Provisioning/Hive/GCP/gcp-cluster.yaml | 8 ++++---- ods_ci/tasks/Resources/Provisioning/Hive/claim.yaml | 2 +- .../tasks/Resources/Provisioning/Hive/deprovision.robot | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml index 569afc94f..6e84fd967 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/AWS/aws-cluster.yaml @@ -5,7 +5,7 @@ items: kind: ClusterPool metadata: name: {{ hive_cluster_name|default("rhodsaws") }}-pool - namespace: rhods + namespace: {{ hive_claim_ns }} spec: baseDomain: {{ base_domain }} imageSetRef: @@ -23,7 +23,7 @@ items: kind: Secret metadata: name: aws-sno-install-config - namespace: rhods + namespace: {{ hive_claim_ns }} type: Opaque stringData: install-config.yaml: | @@ -62,7 +62,7 @@ items: kind: Secret metadata: name: aws-creds - namespace: rhods + namespace: {{ hive_claim_ns }} type: Opaque stringData: aws_access_key_id: {{ AWS_ACCESS_KEY_ID }} @@ -71,6 +71,6 @@ items: kind: ClusterImageSet metadata: name: {{ image_set|default("rhods-openshift") }} - namespace: rhods + namespace: {{ hive_claim_ns }} spec: releaseImage: {{ openshift_image|default("quay.io/openshift-release-dev/ocp-release:4.10.42-x86_64") }} diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml index 3dcf24c2e..964c28e78 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/GCP/gcp-cluster.yaml @@ -5,7 +5,7 @@ items: kind: ClusterPool metadata: name: {{ hive_cluster_name|default("rhodsgcp") }}-pool - namespace: rhods + namespace: {{ hive_claim_ns }} spec: baseDomain: {{ base_domain }} imageSetRef: @@ -23,7 +23,7 @@ items: kind: Secret metadata: name: gcp-sno-install-config - namespace: rhods + namespace: {{ hive_claim_ns }} type: Opaque stringData: install-config.yaml: | @@ -63,7 +63,7 @@ items: kind: Secret metadata: name: gcp-creds - namespace: rhods + namespace: {{ hive_claim_ns }} type: Opaque stringData: osServiceAccount.json: | @@ -83,6 +83,6 @@ items: kind: ClusterImageSet metadata: name: {{ image_set|default("rhods-openshift") }} - namespace: rhods + namespace: {{ hive_claim_ns }} spec: releaseImage: {{ release_image|default("quay.io/openshift-release-dev/ocp-release:4.10.18-x86_64") }} diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/claim.yaml b/ods_ci/tasks/Resources/Provisioning/Hive/claim.yaml index 0cf86ce73..8cad400d9 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/claim.yaml +++ b/ods_ci/tasks/Resources/Provisioning/Hive/claim.yaml @@ -2,6 +2,6 @@ apiVersion: hive.openshift.io/v1 kind: ClusterClaim metadata: name: {{ hive_cluster_name }}-claim - namespace: rhods + namespace: {{ hive_claim_ns }} spec: clusterPoolName: {{ hive_cluster_name }}-pool \ No newline at end of file diff --git a/ods_ci/tasks/Resources/Provisioning/Hive/deprovision.robot b/ods_ci/tasks/Resources/Provisioning/Hive/deprovision.robot index 2d36e06e1..040bfdda0 100644 --- a/ods_ci/tasks/Resources/Provisioning/Hive/deprovision.robot +++ b/ods_ci/tasks/Resources/Provisioning/Hive/deprovision.robot @@ -8,7 +8,7 @@ Set Hive Default Variables Set Suite Variable ${claim_name} ${conf_name} = Get Variable Value ${conf_name} ${cluster_name}-conf Set Suite Variable ${conf_name} - ${hive_namespace} = Get Variable Value ${hive_namespace} rhods + ${hive_namespace} = Get Variable Value ${hive_namespace} %{HIVE_NAMESPACE} Set Suite Variable ${hive_namespace} Delete Cluster Configuration From 5efe44903ba9d40094e4c4c66a50fd323c80509f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Dan=C4=9Bk?= Date: Wed, 10 Jan 2024 16:12:16 +0100 Subject: [PATCH 30/31] ODS-1975 - Verify user can cancel workbench start from event log [AUTOMATION] (#1104) --- .../Workbenches.resource | 5 ++++ .../415__ods_dashboard_projects.robot | 28 ++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource index bd148b9a8..de391806f 100644 --- a/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource +++ b/ods_ci/tests/Resources/Page/ODH/ODHDashboard/ODHDataScienceProject/Workbenches.resource @@ -449,6 +449,11 @@ Event Log Should Report The Failure Page Should Contain Event Log expected_progress_text=${exp_progress_text} ... expected_result_text=${exp_result_text} +Cancel Workbench Startup From Event Log + [Documentation] Clicks the Cancel button in Workbench statup event log + Click Element ${KFNBC_MODAL_CANCEL_XPATH} + Wait Until Generic Modal Disappears + Close Event Log [Documentation] Closes the event log which was previously opened by the robot ${cancel_present}= Run Keyword And Return Status diff --git a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot index 477741fc6..f2a6e274a 100644 --- a/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot +++ b/ods_ci/tests/Tests/400__ods_dashboard/415__ods_dashboard_projects/415__ods_dashboard_projects.robot @@ -221,7 +221,7 @@ Verify User Can Create A S3 Data Connection And Connect It To Workbenches ... status=${WORKBENCH_STATUS_STARTING} Run Keyword And Continue On Failure Wait Until Workbench Is Started workbench_title=${WORKBENCH_TITLE} Workbench Status Should Be workbench_title=${WORKBENCH_2_TITLE} status=${WORKBENCH_STATUS_STOPPED} - [Teardown] Run Keywords + [Teardown] Run Keywords ... Clean Project From Workbench Resources workbench_title=${WORKBENCH_2_TITLE} project_title=${PRJ_TITLE} ... AND ... Clean Project From Workbench Resources workbench_title=${WORKBENCH_TITLE} project_title=${PRJ_TITLE} @@ -400,6 +400,32 @@ Verify Event Log Is Accessible While Starting A Workbench [Teardown] Clean Project From Workbench Resources workbench_title=${WORKBENCH_6_TITLE} ... project_title=${PRJ_TITLE} +Verify User Can Cancel Workbench Start From Event Log + [Tags] Sanity Tier1 ODS-1975 + [Documentation] Verify user can cancel workbench start from event log + + Open Data Science Project Details Page project_title=${PRJ_TITLE} + Create Workbench workbench_title=${WORKBENCH_TITLE} workbench_description=${WORKBENCH_DESCRIPTION} + ... prj_title=${PRJ_TITLE} image_name=${NB_IMAGE} deployment_size=Small + ... storage=Persistent pv_name=${NONE} pv_existent=${NONE} + ... pv_description=${NONE} pv_size=${NONE} + ... press_cancel=${FALSE} envs=${NONE} + + Workbench Status Should Be workbench_title=${WORKBENCH_TITLE} status=${WORKBENCH_STATUS_STARTING} + + Open Notebook Event Log workbench_title=${WORKBENCH_TITLE} + Page Should Contain Event Log + Cancel Workbench Startup From Event Log + Wait Until Workbench Is Stopped workbench_title=${WORKBENCH_TITLE} + + Workbench Status Should Be workbench_title=${WORKBENCH_TITLE} status=${WORKBENCH_STATUS_STOPPED} + + Wait Until Keyword Succeeds 5 min 5s + ... Run Keyword And Expect Error EQUALS:ResourceOperationFailed: Get failed\nReason: Not Found + ... Get Workbench Pod project_title=${PRJ_TITLE} workbench_title=${WORKBENCH_TITLE} + + [Teardown] Clean Project From Workbench Resources workbench_title=${WORKBENCH_TITLE} project_title=${PRJ_TITLE} + Verify Error Is Reported When Workbench Fails To Start # robocop: disable [Tags] Tier1 Sanity ... ODS-1973 From 08fc8d0bd12d3f5d4f3ec3fdceb2b4f8399ca24f Mon Sep 17 00:00:00 2001 From: Jiri Petrlik Date: Thu, 11 Jan 2024 10:38:56 +0100 Subject: [PATCH 31/31] [RHOAIENG-125] ODS CI tests which run Kuberay E2E (#1046) --- .../test-run-kuberay-e2e.robot | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 ods_ci/tests/Tests/650__distributed_workloads/test-run-kuberay-e2e.robot diff --git a/ods_ci/tests/Tests/650__distributed_workloads/test-run-kuberay-e2e.robot b/ods_ci/tests/Tests/650__distributed_workloads/test-run-kuberay-e2e.robot new file mode 100644 index 000000000..a7a24b5d0 --- /dev/null +++ b/ods_ci/tests/Tests/650__distributed_workloads/test-run-kuberay-e2e.robot @@ -0,0 +1,65 @@ +*** Settings *** +Documentation Kuberay E2E tests - https://github.com/ray-project/kuberay.git +Suite Setup Prepare Kuberay E2E Test Suite +Suite Teardown Teardown Kuberay E2E Test Suite +Library OperatingSystem +Library Process +Resource ../../../tasks/Resources/RHODS_OLM/install/oc_install.robot + +*** Variables *** +${KUBERAY_DIR} kuberay +${KUBERAY_REPO_URL} %{KUBERAY_REPO_URL=https://github.com/ray-project/kuberay.git} +${KUBERAY_REPO_BRANCH} %{KUBERAY_REPO_BRANCH=master} + +*** Test Cases *** +Run TestRayJob test + [Documentation] Run Go E2E test: TestRayJob + [Tags] Sanity + ... Tier1 + ... DistributedWorkloads + ... Kuberay + Skip "Requires Kuberay 1.0" + Run Kuberay E2E Test "^TestRayJob$" + +Run TestRayJobWithClusterSelector test + [Documentation] Run Go E2E test: TestRayJobWithClusterSelector + [Tags] Sanity + ... Tier1 + ... DistributedWorkloads + ... Kuberay + Skip "Requires Kuberay 1.0" + Run Kuberay E2E Test TestRayJobWithClusterSelector + +Run TestRayJobSuspend test + [Documentation] Run Go E2E test: TestRayJobSuspend + [Tags] Sanity + ... Tier1 + ... DistributedWorkloads + ... Kuberay + Run Kuberay E2E Test TestRayJobSuspend + + +*** Keywords *** +Prepare Kuberay E2E Test Suite + [Documentation] Prepare Kuberay E2E Test Suite + ${result} = Run Process git clone -b %{KUBERAY_REPO_BRANCH=master} ${KUBERAY_REPO_URL} ${KUBERAY_DIR} + ... shell=true stderr=STDOUT + Log To Console ${result.stdout} + IF ${result.rc} != 0 + FAIL Unable to clone Kuberay repo ${DW_REPO_URL}:${DW_REPO_BRANCH}:${DW_DIR} + END + Enable Component ray + +Teardown Kuberay E2E Test Suite + Disable Component ray + +Run Kuberay E2E Test + [Documentation] Run Kuberay E2E Test + [Arguments] ${test_name} + Log To Console Running Kuberay E2E test: ${test_name} + ${result} = Run Process go test -timeout 30m -parallel 1 -v ./test/e2e -run ${test_name} + ... shell=true stderr=STDOUT cwd=${KUBERAY_DIR}/ray-operator timeout=20m stdout=${TEMPDIR}/output.txt + Log To Console ${result.stdout} + IF ${result.rc} != 0 + FAIL ${test_name} failed + END