Esempio n. 1
0
    def load_paths(self):
        """Add all paths to search for buildspecs. We must read configuration file
        and check property ``buildspec_roots`` for list of directories to search.
        We check all directories exist, if any fail we don't add them to path.
        In addition, we add the default buildspec path where we find tutorials
        and general tests.
        """

        buildspec_paths = self.configuration.target_config.get(
            "buildspec_roots") or []

        if buildspec_paths:
            self.roots += buildspec_paths

        # only load default buildspecs if 'load_default_buildspecs' set to True
        if self.configuration.target_config.get("load_default_buildspecs"):
            self.paths += BUILDSPEC_DEFAULT_PATH

        # for every root buildspec defined in configuration or via --root option,
        # we resolve path and if path exist add to self.paths. The path must be a
        # directory. If its file, we ignore it
        if self.roots:

            for root in self.roots:
                path = resolve_path(root, exist=False)
                if not os.path.exists(path):
                    print(f"Path: {path} does not exist!")

                if is_file(path):
                    print(f"Path: {path} must be a directory not a file")

                if is_dir(path):
                    self.paths.append(path)
Esempio n. 2
0
def discover_buildspecs_by_executor_name(executor_name):
    """This method discovers buildspecs by executor name, using ``--executor-name``
    option from ``buildtest build`` command. This method will read BUILDSPEC_CACHE_FILE
    and search for ``executor`` key in buildspec recipe and match with input
    executor name. The return is a list of matching buildspec with executor name
    to process.

    :param executor_name: Input executor name from command line argument ``buildtest build --executor-name <name>``
    :type executor_name: string
    :return: a list of buildspec files that match tag name
    :rtype: list
    """

    if not is_file(BUILDSPEC_CACHE_FILE):
        raise BuildTestError(
            f"Cannot for buildspec cache: {BUILDSPEC_CACHE_FILE}, please run 'buildtest buildspec find' "
        )

    with open(BUILDSPEC_CACHE_FILE, "r") as fd:
        cache = json.loads(fd.read())

    buildspecs = []
    # query all buildspecs from BUILDSPEC_CACHE_FILE for tags keyword and
    # if it matches input_tag we add buildspec to list

    for buildspecfile in cache["buildspecs"].keys():
        for test in cache["buildspecs"][buildspecfile].keys():

            # check if executor in buildspec matches one in argument (buildtest build --executor <EXECUTOR>)
            if executor_name == cache["buildspecs"][buildspecfile][test].get(
                    "executor"):
                buildspecs.append(buildspecfile)

    return buildspecs
Esempio n. 3
0
def discover_buildspecs_by_tags(input_tag):
    """This method discovers buildspecs by tags, using ``--tags`` option
    from ``buildtest build`` command. This method will read BUILDSPEC_CACHE_FILE
    and search for ``tags`` key in buildspec recipe and match with input
    tag. Since ``tags`` field is a list, we check if input tag is in ``list``
    and if so we add the entire buildspec into a list. The return is a list
    of buildspec files to process.

    :param input_tag: Input tags from command line argument ``buildtest build --tags <tags>``
    :type input_tag: str
    :return: a list of buildspec files that match tag name
    :rtype: list
    """
    if not is_file(BUILDSPEC_CACHE_FILE):
        raise BuildTestError(
            f"Cannot for buildspec cache: {BUILDSPEC_CACHE_FILE}, please run 'buildtest buildspec find' "
        )

    with open(BUILDSPEC_CACHE_FILE, "r") as fd:
        cache = json.loads(fd.read())

    buildspecs = []
    # query all buildspecs from BUILDSPEC_CACHE_FILE for tags keyword and
    # if it matches input_tag we add buildspec to list

    for buildspecfile in cache["buildspecs"].keys():
        for test in cache["buildspecs"][buildspecfile].keys():

            # if tags is not declared we set to empty list
            tag = cache["buildspecs"][buildspecfile][test].get("tags") or []

            if input_tag in tag:
                buildspecs.append(buildspecfile)

    return buildspecs
Esempio n. 4
0
def test_read_file(tmp_path):
    # testing invalid type for read_file, expects of type string. Expected return is 'None'
    print("Reading file with invalid type, passing 'None'")
    with pytest.raises(BuildTestError):
        read_file(None)

    file = os.path.join(tmp_path, "hello.txt")
    print(f"Checking {file} is not a file.")
    # ensure file is not valid
    assert not is_file(file)

    print(f"Now reading an invalid file: {file}, expecting read_file to return 'None'")
    # checking invalid file should report an error
    with pytest.raises(BuildTestError):
        read_file(file)

    with tempfile.TemporaryDirectory() as tmpdir:
        fname = os.path.join(tmpdir, "permission-denied.txt")
        msg = "hello world"
        write_file(fname, msg)
        # make permission 000 so its unreadable
        os.chmod(fname, 000)
        with pytest.raises(BuildTestError):
            read_file(fname)

    print("Reading '/etc/shadow' will raise an exception BuildTestError")
    # reading /etc/shadow will raise a Permission error so we catch this exception BuildTestError
    with pytest.raises(BuildTestError):
        read_file("/etc/shadow")
Esempio n. 5
0
def test_resolve_path():
    assert resolve_path("$HOME")
    assert resolve_path("~")

    random_name = "".join(random.choice(string.ascii_letters) for i in range(10))
    # test a directory path that doesn't exist in $HOME with random key, but setting exist=False will return
    # path but doesn't mean file exists
    path = resolve_path(os.path.join("$HOME", random_name), exist=False)

    # checking if path is not file, or directory and not None. This is only valid when exist=False is set
    assert not is_file(path)
    assert not is_dir(path)
    assert path is not None
Esempio n. 6
0
    def build(self):
        """This method will build buildspec cache file. If user requests to
        rebuild cache we remove the file and recreate cache. If cache file
        exists, we simply load from cache
        """

        # implements buildtest buildspec find --rebuild which removes cache file
        # before finding all buildspecs. We only remove file if file exists
        if self.rebuild and is_file(BUILDSPEC_CACHE_FILE):
            try:
                os.remove(BUILDSPEC_CACHE_FILE)
                print(f"Clearing cache file: {BUILDSPEC_CACHE_FILE}")
            except OSError as msg:
                raise BuildTestError(msg)

        # if cache file is not found, then we will build cache by searching
        # all buildspecs paths and traverse directory to find all .yml files

        if not is_file(BUILDSPEC_CACHE_FILE):
            self.build_cache()

        with open(BUILDSPEC_CACHE_FILE, "r") as fd:
            self.cache = json.loads(fd.read())
Esempio n. 7
0
def test_read_file(tmp_path):
    # testing invalid type for read_file, expects of type string. Expected return is 'None'
    print("Reading file with invalid type, passing 'None'")
    with pytest.raises(BuildTestError):
        read_file(None)

    file = os.path.join(tmp_path, "hello.txt")
    print(f"Checking {file} is not a file.")
    # ensure file is not valid
    assert not is_file(file)

    print(
        f"Now reading an invalid file: {file}, expecting read_file to return 'None'"
    )
    # checking invalid file should report an error
    with pytest.raises(BuildTestError):
        read_file(file)

    print("Reading '/etc/shadow' will raise an exception BuildTestError")
    # reading /etc/shadow will raise a Permission error so we catch this exception BuildTestError
    with pytest.raises(BuildTestError):
        read_file("/etc/shadow")
Esempio n. 8
0
    def load(self):
        """This method is responsible for loading report file. If file not found
        or report is empty dictionary we raise an error. The report file
        is loaded using ``json.loads`` and return value is a dictionary containing
        entire report of all tests.
        """

        # raise error if BUILD_REPORT not found
        if not is_file(BUILD_REPORT):
            sys.exit(
                f"Unable to fetch report no such file found: {BUILD_REPORT}")

        report = None
        with open(BUILD_REPORT, "r") as fd:
            report = json.loads(fd.read())

        # if report is None or issue with how json.load returns content of file we
        # raise error
        if not report:
            sys.exit(
                f"Fail to process {BUILD_REPORT} please check if file is valid json"
                f"or remove file")
        return report
Esempio n. 9
0
def update_report(valid_builders):
    """This method will update BUILD_REPORT after every test run performed
    by ``buildtest build``. If BUILD_REPORT is not created, we will create
    file and update json file by extracting contents from builder.metadata

    :param valid_builders: builder object that were successful during build and able to execute test
    :type valid_builders: instance of BuilderBase (subclass)
    """

    if not is_file(os.path.dirname(BUILD_REPORT)):
        create_dir(os.path.dirname(BUILD_REPORT))

    # if file exists, read json file otherwise set report to empty dict
    try:
        with open(BUILD_REPORT, "r") as fd:
            report = json.loads(fd.read())
    except OSError:
        report = {}

    for builder in valid_builders:
        buildspec = builder.metadata["buildspec"]
        name = builder.metadata["name"]
        entry = {}

        report[buildspec] = report.get(buildspec) or {}
        report[buildspec][name] = report.get(buildspec, {}).get(name) or []

        # query over attributes found in builder.metadata, we only assign
        # keys that we care obout for reporting
        for item in [
                "id",
                "full_id",
                "testroot",
                "testpath",
                "command",
                "outfile",
                "errfile",
                "schemafile",
                "executor",
        ]:
            entry[item] = builder.metadata[item]

        entry["tags"] = ""
        # convert tags to string if defined in buildspec
        if builder.metadata["tags"]:
            if isinstance(builder.metadata["tags"], list):
                entry["tags"] = " ".join(builder.metadata["tags"])
            else:
                entry["tags"] = builder.metadata["tags"]

        # query over result attributes, we only assign some keys of interest
        for item in ["starttime", "endtime", "runtime", "state", "returncode"]:
            entry[item] = builder.metadata["result"][item]

        entry["output"] = builder.metadata["output"]
        entry["error"] = builder.metadata["error"]

        entry["job"] = builder.metadata.get("job") or None
        report[buildspec][name].append(entry)

    with open(BUILD_REPORT, "w") as fd:
        json.dump(report, fd, indent=2)
Esempio n. 10
0
def test_checking_file():
    file_name = str(uuid.uuid4())
    assert not is_file(file_name)
    assert is_file("/bin/bash")