| #!/usr/bin/python |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| |
| from __future__ import print_function |
| |
| MINIFI_SUBFOLDER = '/nifi/nifi-minifi-cpp/' |
| APACHE_CLOSER_REPO_JSON_URL = 'https://www.apache.org/dyn/closer.cgi?as_json=1&path=/nifi/nifi-minifi-cpp' |
| APACHE_MIRROR_LIST = "http://www.apache.org/mirrors/" |
| |
| import argparse |
| import sys |
| |
| if sys.version_info[0] < 3: |
| from urllib2 import urlopen |
| input = raw_input |
| else: |
| from urllib.request import urlopen |
| |
| import json |
| import os.path |
| import platform |
| import tarfile |
| |
| |
| from distutils.util import strtobool |
| from ftplib import FTP |
| |
| def install_package(package_name): |
| try: |
| import pip |
| if hasattr(pip, 'main'): |
| pipcode = pip.main(['install', package]) |
| else: |
| pipcode = pip._internal.main(['install', package]) |
| return pipcode == 0 |
| except: |
| return False |
| |
| |
| distro_available = False |
| |
| try: |
| import distro |
| |
| distro_available = True |
| except: |
| distro_available = install_package("distro") |
| |
| |
| def get_distro(): |
| if is_mac(): |
| return ["osx", "", "darwin"] |
| try: |
| if distro_available: |
| return distro.linux_distribution(full_distribution_name=False) |
| else: |
| return platform.linux_distribution() |
| except: |
| return ["N/A", "N/A", "N/A"] |
| |
| |
| def is_mac(): |
| return platform.system() == "Darwin" |
| |
| |
| def mapped_distro(): |
| distro_info = get_distro() |
| distro = distro_info[0].lower() |
| release = distro_info[2].lower() |
| if any(d in distro for d in ["rhel", "red hat", "centos"]): |
| return "rhel", release |
| else: |
| return distro, release |
| |
| |
| def find_closest_mirror(): |
| try: |
| url = urlopen(APACHE_CLOSER_REPO_JSON_URL) |
| data = json.loads(url.read().decode()) |
| |
| return data['ftp'][0] |
| |
| except Exception as e: |
| print ("Failed to find closest mirror, please specify one!") |
| return "" |
| |
| |
| def get_release_and_binaries_from_ftp(host, apache_dir, version = None): |
| ftp = FTP(host) |
| ftp.login() |
| ftp.cwd(apache_dir + MINIFI_SUBFOLDER) |
| # list files with ftplib |
| file_list = list(filter(lambda x: any(char.isdigit() for char in x), |
| ftp.nlst(""))) # to filter "." and ".." - relese names contain number |
| file_list.sort(reverse=True) |
| if not version: |
| latest_release = file_list[0] |
| else: |
| if version not in file_list: |
| print("The specified version (" + version + ") doesn't exist. Please use one of the following: " + ", ".join(file_list)) |
| exit(-1) |
| latest_release = version |
| |
| ftp.cwd("./" + latest_release) |
| binaries = list(filter(lambda x: any(char.isdigit() for char in x), ftp.nlst(""))) |
| |
| ftp.quit() |
| |
| return latest_release, binaries |
| |
| |
| def download_binary_from_ftp(host, apache_dir, release, binary): |
| successful_download = False |
| |
| try: |
| ftp = FTP(host) |
| ftp.login() |
| ftp.cwd(apache_dir + MINIFI_SUBFOLDER + release) |
| |
| print ("Downloading: ftp://" + host + "/" + MINIFI_SUBFOLDER + release + "/" + binary) |
| |
| with open(os.path.join(os.getcwd(), binary), "wb") as targetfile: |
| ftp.retrbinary("RETR " + binary, targetfile.write) |
| successful_download = True |
| except: |
| print("Failed to download binary") |
| finally: |
| ftp.quit() |
| |
| return successful_download |
| |
| |
| def main(args): |
| print(get_distro()) |
| binaries = [] |
| |
| try: |
| local_repo = args.mirror if args.mirror else find_closest_mirror() |
| |
| print(local_repo) |
| |
| host, dir = local_repo.replace('ftp://', '').split('/', 1) |
| latest_release, binaries = get_release_and_binaries_from_ftp(host, dir, args.version if args.version else None) |
| |
| except: |
| print("Failed to get binaries from Apache mirror") |
| return -1 |
| |
| matching_binaries = [] |
| |
| for binary in binaries: |
| distro, release = mapped_distro() |
| if release and release in binary: |
| matching_binaries.append(binary) |
| elif distro and distro in binary: |
| matching_binaries.append(binary) |
| |
| if not matching_binaries: |
| print("No compatible binary found, MiNiFi needs to be compiled locally") |
| return 1 |
| |
| invalid_input = True |
| download = None |
| selected_binary = None |
| |
| if len(matching_binaries) == 1: |
| print("A binary in Apache repo seems to match your system: " + matching_binaries[0]) |
| while invalid_input: |
| try: |
| download = strtobool(input("Would you like to download? [y/n]")) |
| invalid_input = False |
| if download: |
| selected_binary = matching_binaries[0] |
| except: |
| pass |
| |
| else: |
| print("The following binaries in Apache repo seem to match your system: ") |
| for i, item in enumerate(matching_binaries): |
| print(str(i + 1) + " - " + item) |
| print() |
| while invalid_input: |
| try: |
| user_input = input("Please select one to download (1 to " + str( |
| len(matching_binaries)) + ") or \"s\" to skip and compile locally\n") |
| user_input.lower() |
| if user_input == "s": |
| invalid_input = False |
| download = False |
| break |
| idx = int(user_input) - 1 |
| if (idx < 0): |
| continue |
| selected_binary = matching_binaries[idx] |
| download = True |
| invalid_input = False |
| except: |
| pass |
| |
| if not download: |
| return 1 |
| |
| if not download_binary_from_ftp(host, dir, latest_release, selected_binary): |
| return -1 |
| |
| try: |
| with tarfile.open(os.path.join(os.getcwd(), selected_binary), "r:gz") as tar: |
| tar.extractall() |
| except: |
| print("Failed to extract tar file") |
| return -1 |
| |
| print("Successfully downloaded and extracted MiNiFi") |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| parser = argparse.ArgumentParser(description="Download latest MiNiFi release") |
| parser.add_argument("-m", "--mirror", dest="mirror", help="user-specified apache mirror") |
| parser.add_argument("-v", "--version", dest="version", help="user-specified version to be downloaded") |
| args = parser.parse_args() |
| main(args) |