Ejemplo n.º 1
0
def get(pattern, cache_filename, no_cache, update_cache):
    cache_path = Path(cache_filename)
    data = {}
    fetch_from_scc = False
    if cache_path.exists() and cache_path.is_file() and not no_cache:
        data = cache.load(cache_filename)
        try:
            data["product"]
        except KeyError as err:
            fetch_from_scc = True
    else:
        fetch_from_scc = True
    if fetch_from_scc:
        response = request.fetch("https://scc.suse.com/api/package_search/products")
        try:
            data["product"] = response["data"]
        except KeyError as err:
            print_err(f"Error: No data key found in scc api response, {err}")
            sys.exit(1)

    ret = []
    if not pattern:
        ret = data["product"]
    else:
        for product in data["product"]:
            for k in product.keys():
                if pattern in str(product[k]):
                    ret.append(product)
                    break

    if update_cache:
        cache.save("product", cache_filename, ret)
    return ret
Ejemplo n.º 2
0
def load(filename) -> Dict:
    """Load cache from filename

    The cache file is a json file and retruns a dictionary

    Parameters
    ----------
    filename: str
        path to the json file

    Returns
    -------
    dict
        the content of the cache json file as dict

    Raises
    ------
    SystemExit
        If PermissionError raises
        if unable to decode cache file as JSON
    """

    data = {}
    try:
        with open(filename, "r") as f:
            data = json.load(f)
    except PermissionError as err:
        print_err({err})
        sys.exit(13)
    except json.decoder.JSONDecodeError as err:
        print_err(f"unable to parse {filename} as JSON, {err}")
        sys.exit(1)
    except FileNotFoundError:
        pass
    return data
Ejemplo n.º 3
0
def lookup_product(identifier, filename):
    """Lookup a product in the cache

    Lookup a product in cache based on identifier and return the id

    Parameters
    ----------
    identifier: str
        product identifier to search for
    filename: str
        path to cache file to use

    Returns
    -------
    int
        the product id

    Raises
    ------
    SystemExit
        if no product matches the identifier
    """

    data = load(filename)
    for product in data["product"]:
        if product["identifier"] == identifier:
            return product["id"]
    print_err(f"Couldn't find id for '{identifier}'")
    sys.exit(1)
Ejemplo n.º 4
0
def get(product, pattern, cache_filename):
    """Get the packages information from SUSE Customer Center
    for a particular product

    Parameters
    ----------
    product: str
        product id or identifier
    pattern: str
        search pattern in package name, if blank all packages will be
        returned
    cache_filename: str
        path to the cache file name to be used to lookup product id
        if product identifier is specified instead of product it

    Returns
    -------
    list
        a list of packages that matches the search result
        each package is a dict

    Raises
    ------
    SystemExit
        if the response from SUSE Customer Center is not parsable
    """

    try:
        product_id = int(product)
    except ValueError:
        product_id = cache.lookup_product(product, cache_filename)

    url = f"https://scc.suse.com/api/package_search/packages?product_id={product_id}&query={pattern}"
    response = request.fetch(url)
    try:
        response["data"]
    except KeyError as err:
        print_err(f"Error: No data key found, {err}")
        sys.exit(1)
    return response["data"]
Ejemplo n.º 5
0
def save(key, filename, data):
    """Saves cache to filename

    The cache is a json file and is loaded as dictionary.

    Parameters
    ---------
    key: str
        the dictionary key that the data should be accociated with.
    filename: str
        the path to filename to save the cache to
    data: list
        data to be saved in cache

    Returns
    -------
    None

    Raises
    ------
    SystemExit
        if key is not known
        if data is not of type list
        if PermissionError is raised when saving to filename
    """

    cache_data = {}
    if not key in ["product", "patchproducts"]:
        print_err(f"trying to save cache with unknown key '{key}'")
        sys.exit(1)
    if not isinstance(data, list):
        print_err("Must have list as data source to save cache")
        sys.exit(1)

    if Path(filename).is_file():
        cache_data = load(filename)

    cache_data[key] = data
    try:
        cache_data["age"][key] = datetime.now().strftime("%Y-%m-%d")
    except KeyError:
        cache_data["age"] = {}
        cache_data["age"][key] = datetime.now().strftime("%Y-%m-%d")

    try:
        with open(filename, "w") as f:
            json.dump(cache_data, f)
    except PermissionError as err:
        print_err({err})
        sys.exit(13)
Ejemplo n.º 6
0
def fetch(url, type="json"):
    try:
        response = requests.get(url, headers)
    except requests.exceptions.RequestException as err:
        print_err({err})
        sys.exit(1)
    if response.status_code != 200:
        print_err(f"Got status code '{response.status_code}' from {url}", )
        sys.exit(1)
    if type == "json":
        try:
            return response.json()
        except json.decoder.JSONDecodeError as err:
            print_err(f"Couldn't parse json response {err}")
            sys.exit(1)
    elif type == "html":
        return response.text
Ejemplo n.º 7
0
def get(pattern, cachefile, no_cache, update_cache) -> List:
    """Fetch the products used by SCC Patches

    Parameters
    ----------
    pattern: str
        Only return products where 'pattern' matches product name
    cachefile: str
        Patch to cache file
    no_cache: bool
        If true the cache file will not be used
    update_cache: bool
        if true the cache file will be updated

    Returns:
    List
        A list of Dict representing the products

    Raises:
    SystemExit
        if response from SUSE Customer Center is not parsable
    """

    data = {}
    if not update_cache and (
        Path(cachefile).exists() and Path(cachefile).is_file() and not no_cache
    ):
        data = cache.load(cachefile)
        try:
            data["patchproducts"]
        except KeyError as err:
            print_err("no patch product key found in cachefile")
            sys.exit(1)
    else:
        response = request.fetch("https://scc.suse.com/patches", "html")
        matches = re.findall(".*productsData=(.*)[^ \t\n\r\f\v]+.*", response)
        if len(matches) != 1:
            if len(matches) > 1:
                print_err("to many matches in response from SCC")
            else:
                print_err("no matches in response from SCC")
            exit(1)
        try:
            data["patchproducts"] = json.loads(matches[0])
        except json.decoder.JSONDecodeError as err:
            print_err(f"Couldn't parse json response {err}")
            sys.exit(1)

    ret = []
    if not pattern:
        ret = data["patchproducts"]
    else:
        for product in data["patchproducts"]:
            for k in product.keys():
                if pattern in str(product[k]):
                    ret.append(product)
                    break

    if update_cache:
        cache.save("patchproducts", cachefile, data["patchproducts"])
    return ret
Ejemplo n.º 8
0
def get(cachefile, shell=None):
    """Generates a shell completion script

    Parameters
    ----------
    cachefile: str
        Path to cache file
    shell: str, optional
        Name of the shell to generate completion script for
        if not provided the function will try to use the
        SHELL environment varable

    Raises
    ------
    SystemExit
        if an unknown shell is provided
        if shell is not provided and SHELL environ is not set
        if completion generation file is not readable
    """

    if shell == None:
        try:
            os.environ["SHELL"]
        except KeyError:
            print_err(
                "Couldn't determin shell, you need to specify shell or set $SHELL environment variable",
            )
            sys.exit(1)
        shell = os.path.basename(os.environ.get("SHELL"))
    if shell == "bash":
        filename = f"{os.path.dirname(os.path.realpath(__file__))}/completion.sh"
    else:
        print_err(f"Unsupported shell specified '{shell}'")
        sys.exit(1)

    try:
        with open(filename, "r") as f:  # pragma: no cover
            fc = f.read()
    except FileNotFoundError as err:
        print_err({err})
        sys.exit(2)

    data = cache.load(cachefile)
    sps_patch_product_complete = ""
    sps_patch_version_complete = ""
    sps_patch_arch_complete = ""
    try:
        sps_patch_product_complete = " ".join(
            patchproducts.short(data["patchproducts"], "name"))
        sps_patch_version_complete = " ".join(
            patchproducts.short(data["patchproducts"], "version"))
        sps_patch_arch_complete = " ".join(
            patchproducts.short(data["patchproducts"], "architecture"))
    except KeyError:
        print_warn(
            "Patch product information not found in cache file\nTo enable completion for patch products run: sps patchproduct --update-cache"
        )
    products = []
    try:
        for product in data["product"]:
            products.append(product["identifier"])
    except KeyError:
        print_warn(
            "Product information not found in cache file\nTo enable completion for products run: sps product --update-cache"
        )
    sps_package_product_complete = " ".join(products)

    fc = fc.replace("{sps_patch_product_complete}", sps_patch_product_complete)
    fc = fc.replace("{sps_patch_version_complete}", sps_patch_version_complete)
    fc = fc.replace("{sps_patch_arch_complete}", sps_patch_arch_complete)
    fc = fc.replace("{sps_package_product_complete}",
                    sps_package_product_complete)
    return fc