|
1 | | -import time, json, sys, subprocess |
| 1 | +import time |
| 2 | +import json |
| 3 | +import sys |
| 4 | +import subprocess |
| 5 | +import re |
2 | 6 |
|
3 | 7 | def catch_error_and_exit(errmsg, logger): |
4 | 8 | logger.error(errmsg) |
@@ -81,6 +85,17 @@ def run_stackql_command(command, stackql, logger, ignore_errors=False, retries=0 |
81 | 85 | while attempt <= retries: |
82 | 86 | try: |
83 | 87 | logger.debug(f"(utils.run_stackql_command) executing stackql command (attempt {attempt + 1}):\n\n{command}\n") |
| 88 | + # If qyery is start with 'REGISTRY PULL', check version |
| 89 | + if command.startswith("REGISTRY PULL"): |
| 90 | + match = re.match(r'(REGISTRY PULL \w+)(::v[\d\.]+)?', command) |
| 91 | + if match: |
| 92 | + service_provider = match.group(1) |
| 93 | + version = match.group(2) |
| 94 | + if version: |
| 95 | + command = f"{service_provider} {version[2:]}" |
| 96 | + else: |
| 97 | + raise ValueError("REGISTRY PULL command must be in the format 'REGISTRY PULL <service_provider>::v<version>' or 'REGISTRY PULL <service_provider>'") |
| 98 | + |
84 | 99 | result = stackql.executeStmt(command) |
85 | 100 | logger.debug(f"(utils.run_stackql_command) stackql command result:\n\n{result}, type: {type(result)}\n") |
86 | 101 |
|
@@ -115,17 +130,89 @@ def run_stackql_command(command, stackql, logger, ignore_errors=False, retries=0 |
115 | 130 | def pull_providers(providers, stackql, logger): |
116 | 131 | logger.debug(f"(utils.pull_providers) stackql run time info:\n\n{json.dumps(stackql.properties(), indent=2)}\n") |
117 | 132 | installed_providers = run_stackql_query("SHOW PROVIDERS", stackql, False, logger) # not expecting an error here |
118 | | - if len(installed_providers) == 0: |
119 | | - installed_names = set() |
120 | | - else: |
121 | | - installed_names = {provider["name"] for provider in installed_providers} |
| 133 | + # check if the provider is already installed |
122 | 134 | for provider in providers: |
123 | | - if provider not in installed_names: |
124 | | - logger.info(f"pulling provider '{provider}'...") |
125 | | - msg = run_stackql_command(f"REGISTRY PULL {provider}", stackql, logger) |
126 | | - logger.info(msg) |
| 135 | + # check if the provider is a specific version |
| 136 | + if "::" in provider: |
| 137 | + name, version = provider.split("::") |
| 138 | + check_provider_version_available(name, version, stackql, logger) |
| 139 | + found = False |
| 140 | + # provider is a version which will be installed |
| 141 | + # installed is a version which is already installed |
| 142 | + for installed in installed_providers: |
| 143 | + # if name and version are the same, it's already installed |
| 144 | + if installed["name"] == name and installed["version"] == version: |
| 145 | + logger.info(f"provider '{provider}' is already installed.") |
| 146 | + found = True |
| 147 | + break |
| 148 | + # if name is the same but the installed version is higher, |
| 149 | + # it's already installed(latest version) |
| 150 | + elif installed["name"] == name and is_installed_version_higher(installed["version"], version): |
| 151 | + logger.warning(f"provider '{name}' version '{version}' is not available in the registry, but a higher version '{installed['version']}' is already installed.") |
| 152 | + logger.warning("If you want to install the lower version, you must delete the higher version folder from the stackql providers directory.") |
| 153 | + logger.info(f"provider {name}::{version} is already installed.") |
| 154 | + found = True |
| 155 | + break |
| 156 | + # if not found, pull the provider |
| 157 | + if not found: |
| 158 | + logger.info(f"pulling provider '{provider}'...") |
| 159 | + msg = run_stackql_command(f"REGISTRY PULL {provider}", stackql, logger) |
| 160 | + logger.info(msg) |
| 161 | + else: |
| 162 | + found = False |
| 163 | + # provider is a name which will be installed |
| 164 | + # installed is a list of providers which are already installed |
| 165 | + for installed in installed_providers: |
| 166 | + if installed["name"] == provider: |
| 167 | + logger.info(f"provider '{provider}' is already installed.") |
| 168 | + found = True |
| 169 | + break |
| 170 | + # if not found, pull the provider |
| 171 | + if not found: |
| 172 | + logger.info(f"pulling provider '{provider}'...") |
| 173 | + msg = run_stackql_command(f"REGISTRY PULL {provider}", stackql, logger) |
| 174 | + logger.info(msg) |
| 175 | + |
| 176 | +def check_provider_version_available(provider_name, version, stackql, logger): |
| 177 | + """Check if the provider version is available in the registry. |
| 178 | +
|
| 179 | + Args: |
| 180 | + provider_name (str): The name of the provider. |
| 181 | + version (str): The version of the provider. |
| 182 | + stackql (StackQL): The StackQL object. |
| 183 | + logger (Logger): The logger object. |
| 184 | + """ |
| 185 | + query = f"REGISTRY LIST {provider_name}" |
| 186 | + try: |
| 187 | + result = run_stackql_query(query, stackql, True, logger) |
| 188 | + # result[0]['versions'] is a string, not a list |
| 189 | + # so we need to split it into a list |
| 190 | + versions = result[0]['versions'].split(", ") |
| 191 | + if version not in versions: |
| 192 | + catch_error_and_exit(f"(utils.check_provider_version_available) version '{version}' not found for provider '{provider_name}', available versions: {versions}", logger) |
| 193 | + except Exception: |
| 194 | + catch_error_and_exit(f"(utils.check_provider_version_available) provider '{provider_name}' not found in registry", logger) |
| 195 | + |
| 196 | +def is_installed_version_higher(installed_version, requested_version): |
| 197 | + """Check if the installed version is higher than the requested version. |
| 198 | +
|
| 199 | + Args: |
| 200 | + installed_version (str): v24.09.00251 |
| 201 | + requested_version (str): v23.01.00104 |
| 202 | +
|
| 203 | + Returns: |
| 204 | + bool: True if installed version is higher than requested version, False otherwise |
| 205 | + """ |
| 206 | + |
| 207 | + try: |
| 208 | + int_installed = int(installed_version.replace("v", "").replace(".", "")) |
| 209 | + int_requested = int(requested_version.replace("v", "").replace(".", "")) |
| 210 | + if int_installed > int_requested: |
| 211 | + return True |
127 | 212 | else: |
128 | | - logger.info(f"provider '{provider}' is already installed.") |
| 213 | + return False |
| 214 | + except Exception: |
| 215 | + catch_error_and_exit(f"(utils.is_installed_version_higher) version comparison failed: installed version '{installed_version}', requested version '{requested_version}'", logger) |
129 | 216 |
|
130 | 217 | def run_test(resource, rendered_test_iql, stackql, logger, delete_test=False): |
131 | 218 | try: |
|
0 commit comments