blob: cfe76e8b9e3c90f690e96f4943bc77be8e61a3fb [file] [log] [blame]
#!/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)