diff --git a/nuvlaedge-installer/Dockerfile b/nuvlaedge-installer/Dockerfile index b18849c..d3d8a5e 100644 --- a/nuvlaedge-installer/Dockerfile +++ b/nuvlaedge-installer/Dockerfile @@ -20,6 +20,6 @@ ENV PATH="$PATH:${workdir}/common:${workdir}/commands" \ ROOTFS="/rootfs" \ ROOTFS_WORKING_DIR="/rootfs-working-dir" -RUN chmod +x installer +RUN chmod +x installer common/nuvlaedge-printer commands/* ENTRYPOINT ["./installer"] diff --git a/nuvlaedge-installer/commands/nuvlaedge-download-nuvla-configs b/nuvlaedge-installer/commands/nuvlaedge-download-nuvla-configs new file mode 100755 index 0000000..6be26f8 --- /dev/null +++ b/nuvlaedge-installer/commands/nuvlaedge-download-nuvla-configs @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 + +import os +import sys +import inspect + +import requests + +func = inspect.currentframe().f_code + +nuvla_io_endpoint = 'https://nuvla.io' + + +def is_true(s, **kwargs): + """ Check if 's' string represent True else False + + :param s: String to check + :param default: If the check cannot be done return this value or raise ValueError if not provided. + + :returns True if 's' string represent True else False + """ + try: + return s if isinstance(s, bool) \ + else bool(s and s.lower() in ['true', '1', 't', 'y', 'yes']) + except: + message = f'Cannot check if "{s}" is True' + if 'default' not in kwargs: + raise ValueError(message) + else: + return kwargs['default'] + + +def nuvla_login(api_endpoint, api_key, api_secret, insecure=False): + session = requests.Session() + session.verify = not insecure + login_endpoint = api_endpoint + "/session" + payload = { + "template": { + "href": "session-template/api-key", + "key": api_key, + "secret": api_secret + } + } + print("Nuvla login at {}...".format(login_endpoint)) + response = session.post(login_endpoint, json=payload) + response.raise_for_status() + return session + + +def download_compose_files(version, compose_filenames, workdir, keep_files=[], + nuvla_api_endpoint=f'{nuvla_io_endpoint}/api', api=None): + """ Prepares the working environment for installing NuvlaEdge + + :param version: version number of NuvlaEdge to install + :param compose_filenames: list of release assets to download + :param workdir: path where the compose files are to be saved + :param keep_files: list of files that are not supposed to be modified during this preparation + :param nuvla_api_endpoint: Nuvla API endpoint (default: https://nuvla.io/api) + :param api: authenticated requests session. do not use session if not provided + + :returns list of paths to compose files + """ + + if not api: + api = requests.Session() + + params = { + 'filter': "release='{}'".format(version), + 'select': 'compose-files', + 'last': 1 + } + r = api.get('{}/nuvlabox-release'.format(nuvla_api_endpoint), params=params).json()['resources'] + + if not len(r): + raise Exception('Error: NuvlaEdge release "{}" not found on "{}"'.format(version, nuvla_api_endpoint)) + + ne_release = r[0] + compose_files = {r['name']: r['file'] for r in ne_release['compose-files']} + + final_compose_filepaths = [] + for filename in compose_filenames: + filepath = "{}/{}".format(workdir, filename) + + if filename not in compose_files: + raise Exception('Error: compose file "{}" not found in "{}"'.format(filename, compose_files.keys())) + + with open(filepath, 'w') as f: + f.write(compose_files[filename]) + final_compose_filepaths.append(filepath) + + return final_compose_filepaths + + +def main(): + prog = sys.argv[0] if len(sys.argv) >= 1 else __file__ + if len(sys.argv) != 4: + raise Exception(f'Wrong number of arguments. Usage: {prog} compose_filenames_csv dest_dir nuvlaedge_version') + + _, compose_filenames_csv, dest_dir, nuvlaedge_version = sys.argv + + compose_filenames = compose_filenames_csv.split(',') + nuvla_endpoint = os.getenv('NUVLA_ENDPOINT', nuvla_io_endpoint) + nuvla_api_endpoint = nuvla_endpoint.rstrip('/').rstrip('/api') + "/api" + nuvla_api_key = os.getenv('NUVLAEDGE_API_KEY') + nuvla_api_secret = os.getenv('NUVLAEDGE_API_SECRET') + nuvla_api_insecure = is_true(os.getenv('NUVLA_ENDPOINT_INSECURE'), default=False) + + api = None + if nuvla_api_key and nuvla_api_secret: + api = nuvla_login(nuvla_api_endpoint, nuvla_api_key, nuvla_api_secret, nuvla_api_insecure) + + download_compose_files(nuvlaedge_version, compose_filenames, dest_dir, + nuvla_api_endpoint=nuvla_api_endpoint, + api=api) + + +if __name__ == "__main__": + try: + main() + except Exception as e: + # making sure that only the error message is printed and not the whole exception + sys.exit(f'Critical error in {func.co_filename}: {str(e)}') diff --git a/nuvlaedge-installer/commands/nuvlaedge-install b/nuvlaedge-installer/commands/nuvlaedge-install index b06e35b..ab2ebca 100755 --- a/nuvlaedge-installer/commands/nuvlaedge-install +++ b/nuvlaedge-installer/commands/nuvlaedge-install @@ -31,16 +31,27 @@ fi if [[ ! -z ${target_version} ]] && [[ "${target_version}" != "master" ]] && [[ "${target_version}" != "main" ]] then - source_code_url="${github_releases}/download/${target_version}" + # First, try downloading compose files from Nuvla + nuvlaedge-printer "Downloading compose files ${compose_files} from Nuvla for version ${target_version}" "INFO" "no" - nuvlaedge-printer "Downloading config files ${compose_files} from ${source_code_url}" ${quiet} "INFO" "no" - - download=$(nuvlaedge-download-configs "${compose_files}" "${save_dir}" "${source_code_url}" 2>&1) + download=$(nuvlaedge-download-nuvla-configs "${compose_files}" "${save_dir}" "${target_version}" 2>&1) + # If fails, try Github release assets if [[ $? -ne 0 ]] then - nuvlaedge-printer "Install failed! Unable to retrieve files ${compose_files} from ${source_code_url}: ${download}" 0 "ERROR" "no" - exit 1 + nuvlaedge-printer "Failed downloading compose files from Nuvla: ${download}" 0 "WARNING" "no" + + source_code_url="${github_releases}/download/${target_version}" + + nuvlaedge-printer "Downloading compose files ${compose_files} from ${source_code_url}" ${quiet} "INFO" "no" + + download=$(nuvlaedge-download-configs "${compose_files}" "${save_dir}" "${source_code_url}" 2>&1) + + if [[ $? -ne 0 ]] + then + nuvlaedge-printer "Install failed! Unable to retrieve compose files ${compose_files} from ${source_code_url}: ${download}" 0 "ERROR" "no" + exit 1 + fi fi fi diff --git a/nuvlaedge-installer/commands/nuvlaedge-update b/nuvlaedge-installer/commands/nuvlaedge-update index 49532d1..ee877d0 100755 --- a/nuvlaedge-installer/commands/nuvlaedge-update +++ b/nuvlaedge-installer/commands/nuvlaedge-update @@ -38,16 +38,25 @@ then fi fi -source_code_url="${github_releases}/download/${target_version}" - -nuvlaedge-printer "Downloading config files ${compose_files} from ${source_code_url}" ${quiet} "INFO" "no" - -download=$(nuvlaedge-download-configs "${compose_files}" "${working_dir}" "${source_code_url}" 2>&1) +# First, try downloading config files from Nuvla +nuvlaedge-printer "Downloading compose files ${compose_files} from Nuvla for version ${target_version}" "INFO" "no" +download=$(nuvlaedge-download-nuvla-configs "${compose_files}" "${working_dir}" "${target_version}" 2>&1) +# If fails, try Github release assets if [[ $? -ne 0 ]] then - nuvlaedge-printer "Update failed! Unable to retrieve files ${compose_files}: ${download}" 0 "ERROR" "no" - exit 1 + nuvlaedge-printer "Failed downloading compose files from Nuvla: ${download}" 0 "WARNING" "no" + source_code_url="${github_releases}/download/${target_version}" + + nuvlaedge-printer "Downloading compose files ${compose_files} from ${source_code_url}" ${quiet} "INFO" "no" + + download=$(nuvlaedge-download-configs "${compose_files}" "${working_dir}" "${source_code_url}" 2>&1) + + if [[ $? -ne 0 ]] + then + nuvlaedge-printer "Update failed! Unable to retrieve compose files ${compose_files}: ${download}" 0 "ERROR" "no" + exit 1 + fi fi nuvlaedge-printer "Preparing to update NuvlaEdge Engine running as project ${project}" ${quiet} "NONE" "yes" @@ -61,15 +70,20 @@ then then down_dir="/tmp/down" mkdir -p ${down_dir} - source_code_url_current="${github_releases}/download/${current_version}" + download=$(nuvlaedge-download-nuvla-configs "${compose_files}" "${down_dir}" "${current_version}" 2>&1) - nuvlaedge-printer "Downloading current config files ${compose_files} from ${source_code_url} for shutdown" ${quiet} "INFO" "no" + if [[ $? -ne 0 ]] + then + source_code_url_current="${github_releases}/download/${current_version}" + + nuvlaedge-printer "Downloading compose config files ${compose_files} from ${source_code_url_current} for shutdown" ${quiet} "INFO" "no" - download=$(nuvlaedge-download-configs "${compose_files}" "${down_dir}" "${source_code_url_current}" 2>&1) + download=$(nuvlaedge-download-configs "${compose_files}" "${down_dir}" "${source_code_url_current}" 2>&1) + fi if [[ $? -ne 0 ]] then - nuvlaedge-printer "Failed to retrieve current files ${compose_files} for shutdown: ${download}" 0 "ERROR" "no" + nuvlaedge-printer "Failed to retrieve current cmpose files ${compose_files} for shutdown: ${download}" 0 "ERROR" "no" cd ${working_dir} else cd ${down_dir} diff --git a/nuvlaedge-installer/commands/nuvlaedge-update-configs b/nuvlaedge-installer/commands/nuvlaedge-update-configs old mode 100644 new mode 100755 diff --git a/nuvlaedge-installer/installer b/nuvlaedge-installer/installer old mode 100644 new mode 100755