Example #1
0
    def construct_yaml(
        self,
        name="test",
        version="0.1",
        summary="Simple test snap",
        description="Something something",
        grade=None,
        architectures=None,
        parts=dedent("""\
                           my-part:
                             plugin: nil
                           """),
        build_packages="[]",
        adopt_info=None,
    ):
        snapcraft_yaml = {
            "name": name,
            "summary": summary,
            "description": description,
            "parts": yaml_utils.load(parts),
            "build-packages": yaml_utils.load(build_packages),
        }

        if version:
            snapcraft_yaml["version"] = version
        if adopt_info:
            snapcraft_yaml["adopt-info"] = adopt_info
        if grade:
            snapcraft_yaml["grade"] = grade
        if architectures:
            snapcraft_yaml["architectures"] = architectures

        with open("snapcraft.yaml", "w") as f:
            yaml_utils.dump(snapcraft_yaml, stream=f)
    def test_prime_without_packages_version(self):
        """Test the recorded manifest for a snap with packages

        This snap declares all the packages that it requires, there are
        no additional dependencies. The packages don't specify their
        version.
        """
        self.run_snapcraft("prime", project_dir="stage-packages-without-dependencies")

        with open(os.path.join("snap", "snapcraft.yaml")) as source_yaml_file:
            source_yaml = yaml_utils.load(source_yaml_file)
        part_name = "part-with-stage-packages"
        expected_packages = [
            "{}={}".format(
                package,
                integration.get_package_version(
                    package, self.distro_series, self.deb_arch
                ),
            )
            for package in source_yaml["parts"][part_name]["stage-packages"]
        ]

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        self.assertThat(
            recorded_yaml["parts"][part_name]["stage-packages"],
            Equals(expected_packages),
        )
    def test_prime_records_packages_version(self):
        """Test the recorded manifest for a snap with packages

        This snap declares all the packages that it requires, there are
        no additional dependencies. The packages specify their version.
        """
        expected_packages = ["haskell-doc", "haskell98-tutorial", "haskell98-report"]
        self.copy_project_to_cwd("stage-packages-without-dependencies")
        part_name = "part-with-stage-packages"
        for package in expected_packages:
            self.set_stage_package_version(
                os.path.join("snap", "snapcraft.yaml"), part_name, package
            )

        self.run_snapcraft("prime")

        with open(os.path.join("snap", "snapcraft.yaml")) as source_yaml_file:
            source_yaml = yaml_utils.load(source_yaml_file)

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        self.assertThat(
            recorded_yaml["parts"][part_name]["stage-packages"],
            Equals(source_yaml["parts"][part_name]["stage-packages"]),
        )
Example #4
0
    def set_package_version(self,
                            type_,
                            snapcraft_yaml_path,
                            part,
                            package,
                            version=None):
        # This doesn't handle complex package syntax.
        with open(snapcraft_yaml_path) as snapcraft_yaml_file:
            snapcraft_yaml = yaml_utils.load(snapcraft_yaml_file)
        if part:
            packages = snapcraft_yaml["parts"][part].get(type_, [])
        else:
            packages = snapcraft_yaml.get(type_, [])
        for index, package_in_yaml in enumerate(packages):
            if package_in_yaml.split("=")[0] == package:
                if version is None:
                    version = get_package_version(package, self.distro_series,
                                                  self.deb_arch)

                packages[index] = "{}={}".format(package, version)
                break
        else:
            self.fail("The part {} doesn't have a package {}".format(
                part, package))

        with open(snapcraft_yaml_path, "w") as snapcraft_yaml_file:
            yaml_utils.dump(snapcraft_yaml, stream=snapcraft_yaml_file)
        return version
Example #5
0
    def generate_meta_yaml(
        self, *, build=False, actual_prime_dir=None, snapcraft_yaml_file_path=None
    ):
        if snapcraft_yaml_file_path is None:
            snapcraft_yaml_file_path = self.snapcraft_yaml_file_path
        os.makedirs("snap", exist_ok=True)
        with open(snapcraft_yaml_file_path, "w") as f:
            f.write(yaml_utils.dump(self.config_data))

        self.project = Project(snapcraft_yaml_file_path=snapcraft_yaml_file_path)
        if actual_prime_dir is not None:
            self.project._prime_dir = actual_prime_dir

        self.meta_dir = os.path.join(self.project.prime_dir, "meta")
        self.hooks_dir = os.path.join(self.meta_dir, "hooks")
        self.snap_yaml = os.path.join(self.meta_dir, "snap.yaml")

        self.config = project_loader.load_config(project=self.project)
        if build:
            for part in self.config.parts.all_parts:
                part.pull()
                part.build()
                part.stage()
                part.prime()

        _snap_packaging.create_snap_packaging(self.config)

        self.assertTrue(os.path.exists(self.snap_yaml), "snap.yaml was not created")

        with open(self.snap_yaml) as f:
            return yaml_utils.load(f)
Example #6
0
    def _load_info(self) -> Dict[str, Any]:
        filepath = os.path.join(self.provider_project_dir, "project-info.yaml")
        if not os.path.exists(filepath):
            return dict()

        with open(filepath) as info_file:
            return yaml_utils.load(info_file)
    def test_prime_with_packages_missing_dependency(self):
        """Test the recorded manifest for a snap with packages

        This snap declares one package that has undeclared dependencies.
        """
        self.copy_project_to_cwd("stage-packages-missing-dependency")
        part_name = "part-with-stage-packages"
        self.set_stage_package_version(
            os.path.join("snap", "snapcraft.yaml"), part_name, package="haskell-doc"
        )
        self.run_snapcraft("prime")

        expected_packages = [
            "{}={}".format(
                package,
                integration.get_package_version(
                    package, self.distro_series, self.deb_arch
                ),
            )
            for package in ["haskell-doc", "haskell98-tutorial", "haskell98-report"]
        ]

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        self.assertThat(
            recorded_yaml["parts"][part_name]["stage-packages"],
            Equals(expected_packages),
        )
    def test_prime_with_build_packages(self):
        """Test the recorded manifest for a snap with build packages

        This snap declares one global build package that has undeclared
        dependencies.

        """
        expected_packages = ["haskell-doc", "haskell98-tutorial", "haskell98-report"]
        self.addCleanup(
            subprocess.call, ["sudo", "apt", "remove", "-y"] + expected_packages
        )

        self.run_snapcraft("prime", self.snap)

        expected_packages_with_version = [
            "{}={}".format(
                package,
                integration.get_package_version(
                    package, self.distro_series, self.deb_arch
                ),
            )
            for package in expected_packages
        ]

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        self.assertThat(
            recorded_yaml["build-packages"], Equals(expected_packages_with_version)
        )
Example #9
0
def _load_yaml(*, yaml_file_path: str) -> OrderedDict:
    with open(yaml_file_path, "rb") as fp:
        bs = fp.read(2)

    if bs == codecs.BOM_UTF16_LE or bs == codecs.BOM_UTF16_BE:
        encoding = "utf-16"
    else:
        encoding = "utf-8"

    try:
        with open(yaml_file_path, encoding=encoding) as fp:  # type: ignore
            yaml_contents = yaml_utils.load(fp)  # type: ignore
    except yaml.MarkedYAMLError as e:
        raise errors.YamlValidationError(
            "{} on line {}, column {}".format(e.problem,
                                              e.problem_mark.line + 1,
                                              e.problem_mark.column + 1),
            yaml_file_path,
        ) from e
    except yaml.reader.ReaderError as e:
        raise errors.YamlValidationError(
            "invalid character {!r} at position {}: {}".format(
                chr(e.character), e.position + 1, e.reason),
            yaml_file_path,
        ) from e
    except yaml.YAMLError as e:
        raise errors.YamlValidationError(str(e), yaml_file_path) from e

    return yaml_contents
    def test_pull_git(self):
        repo_fixture = fixture_setup.GitRepo()
        self.useFixture(repo_fixture)
        project_dir = "asset-tracking-git"

        self.run_snapcraft(["pull", self.part_name], project_dir)

        state_file = os.path.join(self.parts_dir, self.part_name, "state", "pull")
        self.assertThat(state_file, FileExists())
        with open(state_file) as f:
            state = yaml_utils.load(f)

        self.assertIn("source-details", state.assets)

        # fall back to the commit if no other source option is provided
        # snapcraft.source.Git doesn't allow both a tag and a commit
        if self.expected_details:
            self.assertThat(
                state.assets["source-details"][self.expected_details.field],
                Equals(self.expected_details.value),
            )
        else:
            self.assertThat(
                state.assets["source-details"]["source-commit"],
                Equals(repo_fixture.commit),
            )
Example #11
0
    def __init__(self):
        super().__init__()

        if not os.path.exists(self.parts_yaml):
            update()

        with open(self.parts_yaml) as parts_file:
            self._parts = yaml_utils.load(parts_file)
Example #12
0
def get_state(state_dir: str, step: steps.Step):
    state = None
    state_file = get_step_state_file(state_dir, step)
    if os.path.isfile(state_file):
        with open(state_file, "r") as f:
            state = yaml_utils.load(f)

    return state
Example #13
0
 def _load_schema(self):
     schema_file = os.path.abspath(
         os.path.join(common.get_schemadir(), "snapcraft.yaml"))
     try:
         with open(schema_file) as fp:
             self._schema = yaml_utils.load(fp)
     except FileNotFoundError:
         raise errors.YamlValidationError(
             "snapcraft validation file is missing from installation path")
 def test_arch_with_pull(self):
     if self.deb_arch == "armhf":
         self.skipTest("For now, we just support crosscompile from amd64")
     self.run_snapcraft(["--target-arch=i386", "pull", "go-hello"], "go-hello")
     state_file = os.path.join(self.parts_dir, "go-hello", "state", "pull")
     self.assertThat(state_file, FileExists())
     with open(state_file) as f:
         state = yaml_utils.load(f)
     self.assertThat(state.project_options["deb_arch"], Equals("i386"))
Example #15
0
    def test_scriptlet_after_repull(self):
        self.run_command(["prime"])

        with open(os.path.join("prime", "meta", "snap.yaml")) as f:
            y = yaml_utils.load(f)

        self.assertThat(y["grade"], Equals("devel"))
        self.assertThat(y["version"], Equals("v1.0"))

        # modifying source file (src/version.txt) will trigger re-pull
        open(os.path.join("src", "version.txt"), "w").write("v2.0")
        self.run_command(["prime"])

        with open(os.path.join("prime", "meta", "snap.yaml")) as f:
            z = yaml_utils.load(f)

        self.assertThat(z["grade"], Equals("devel"))
        self.assertThat(z["version"], Equals("v2.0"))
    def test_default_architecture(self):
        self.construct_yaml(architectures=[{"build-on": ["other-arch"]}])

        self.run_snapcraft("prime")

        with open(os.path.join("prime", "meta", "snap.yaml")) as f:
            y = yaml_utils.load(f)

        self.assertThat(y["architectures"], Equals([self.deb_arch]))
    def test_simple_architecture(self):
        self.construct_yaml(architectures=[self.deb_arch])

        self.run_snapcraft("prime")

        with open(os.path.join("prime", "meta", "snap.yaml")) as f:
            y = yaml_utils.load(f)

        self.assertThat(y["architectures"], Equals([self.deb_arch]))
Example #18
0
def _snap_data_from_dir(directory):
    with open(os.path.join(directory, "meta", "snap.yaml")) as f:
        snap = yaml_utils.load(f)

    return {
        "name": snap["name"],
        "version": snap["version"],
        "arch": snap.get("architectures", []),
        "type": snap.get("type", ""),
    }
Example #19
0
    def test_update(self):
        result = self.run_command(["update"])

        self.assertThat(result.exit_code, Equals(0))
        self.assertThat(self.parts_yaml, FileExists())
        self.assertThat(self.headers_yaml, FileExists())

        expected_parts = OrderedDict()
        expected_parts["curl"] = p = OrderedDict()
        p["plugin"] = "autotools"
        p["source"] = "http://curl.org"
        p["description"] = "test entry for curl"
        p["maintainer"] = "none"

        expected_parts["part1"] = p = OrderedDict()
        p["plugin"] = "go"
        p["source"] = "http://source.tar.gz"
        p["description"] = "test entry for part1"
        p["maintainer"] = "none"

        expected_parts["long-described-part"] = p = OrderedDict()
        p["plugin"] = "go"
        p["source"] = "http://source.tar.gz"
        p["description"] = "this is a repetitive description " * 3
        p["maintainer"] = "none"

        expected_parts["multiline-part"] = p = OrderedDict()
        p["plugin"] = "go"
        p["source"] = "http://source.tar.gz"
        p["description"] = "this is a multiline description\n" * 3
        p["maintainer"] = "none"

        expected_headers = {
            "If-Modified-Since": "Thu, 07 Jul 2016 10:00:20 GMT"
        }

        with open(self.parts_yaml) as parts_file:
            parts = yaml_utils.load(parts_file)
        with open(self.headers_yaml) as headers_file:
            headers = yaml_utils.load(headers_file)

        self.assertThat(parts, Equals(expected_parts))
        self.assertThat(headers, Equals(expected_headers))
Example #20
0
    def test_merge_tag_yaml(self):
        test_yaml = """
base: &base
    property: value
test:
    <<: *base
"""
        doc = yaml_utils.load(test_yaml)

        self.assertTrue(isinstance(doc, OrderedDict))
        self.assertThat(doc["test"]["property"], Equals("value"))
Example #21
0
    def test_ordereddict_yaml(self):
        from collections import OrderedDict

        data = OrderedDict()

        data["name"] = "test"
        data["description"] = "description"

        output = yaml_utils.dump(data)

        self.assertTrue(isinstance(yaml_utils.load(output), OrderedDict))
Example #22
0
    def test_yaml_conversion(self, init_spy):
        state_string = yaml_utils.dump(self.state)

        # Verify that the dumped tag was correct
        self.assertThat(state_string.splitlines()[0], Equals("!BuildState"))

        # Now verify the conversion
        state_from_yaml = yaml_utils.load(state_string)
        self.assertThat(state_from_yaml, Equals(self.state))

        # Verify that init was not called
        init_spy.assert_not_called()
Example #23
0
def _edit_validation_sets(validation_sets: str) -> Dict[str, Any]:
    """Spawn an editor to modify the validation-sets."""
    editor_cmd = os.getenv("EDITOR", "vi")

    with tempfile.NamedTemporaryFile() as ft:
        ft.close()
        with open(ft.name, "w") as fw:
            print(validation_sets, file=fw)
        subprocess.run([editor_cmd, ft.name], check=True)
        with open(ft.name, "r") as fr:
            edited_validation_sets = yaml_utils.load(fr)

    return edited_validation_sets
    def test_specified_metadata_not_overwritten(self):
        snapcraft_yaml = fixture_setup.SnapcraftYaml(self.path, description=None)
        snapcraft_yaml.data["adopt-info"] = "test-part"
        snapcraft_yaml.update_part(
            "test-part", {"plugin": "dump", "parse-info": ["test.metainfo.xml"]}
        )
        self.useFixture(snapcraft_yaml)

        self.run_snapcraft("prime")
        with open(os.path.join("prime", "meta", "snap.yaml")) as snap_yaml_file:
            snap_yaml = yaml_utils.load(snap_yaml_file)
        self.assertThat(snap_yaml["description"], Equals("test-appstream-description"))
        self.assertThat(snap_yaml["summary"], Equals("test-summary"))
Example #25
0
def add_stage_packages(
    *, part_name: str, stage_packages: List[str], snapcraft_yaml_file=None
):
    if snapcraft_yaml_file is None:
        snapcraft_yaml_file = os.path.join("snap", "snapcraft.yaml")

    with open(snapcraft_yaml_file) as file_read:
        y = yaml_utils.load(file_read)
        if "stage-packages" in y["parts"][part_name]:
            y["parts"][part_name]["stage-packages"].extend(stage_packages)
        else:
            y["parts"][part_name]["stage-packages"] = stage_packages
    with open(snapcraft_yaml_file, "w") as file_write:
        yaml_utils.dump(y, stream=file_write)
    def test_pull_build_package_with_any_architecture(self):
        self.copy_project_to_cwd("build-package")
        self.set_build_package_architecture(
            os.path.join("snap", "snapcraft.yaml"),
            part="hello",
            package="hello",
            architecture="any",
        )
        self.run_snapcraft("pull")

        state_file = os.path.join(self.parts_dir, "hello", "state", "pull")
        with open(state_file) as f:
            state = yaml_utils.load(f)
        self.assertIn("hello", state.assets["build-packages"][0])
    def test_prime_with_architectures(self):
        """Test the recorded manifest for a basic snap

        This snap doesn't have stage or build packages and is declared that it
        works on all architectures.
        """
        self.run_snapcraft(["snap", "--output", "basic.snap"], project_dir="basic")

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        self.assertThat(recorded_yaml["architectures"], Equals(["all"]))
        self.assert_review_passes("basic.snap")
    def test_prime_with_git_source(self):
        self.copy_project_to_cwd("git-head")

        self.init_source_control()
        self.commit('"test-commit"', allow_empty=True)

        self.run_snapcraft(["snap", "--output", "git.snap"])

        recorded_yaml_path = os.path.join(self.prime_dir, "snap", "manifest.yaml")
        with open(recorded_yaml_path) as recorded_yaml_file:
            recorded_yaml = yaml_utils.load(recorded_yaml_file)

        commit = self.get_revno()
        self.assertThat(recorded_yaml["parts"]["git"]["source-commit"], Equals(commit))
        self.assert_review_passes("git.snap")
Example #29
0
def _edit_developers(developers: List[Dict[str, str]]) -> List[Dict[str, str]]:
    """Spawn an editor to modify the snap-developer assertion for a snap."""
    editor_cmd = os.getenv("EDITOR", "vi")

    developer_wrapper = {"developers": developers}

    with tempfile.NamedTemporaryFile() as ft:
        ft.close()
        with open(ft.name, "w") as fw:
            print(_COLLABORATION_HEADER, file=fw)
            yaml_utils.dump(developer_wrapper, stream=fw)
        subprocess.check_call([editor_cmd, ft.name])
        with open(ft.name, "r") as fr:
            developers = yaml_utils.load(fr).get("developers")
    return developers
Example #30
0
def _get_data_from_snap_file(snap_path):
    with tempfile.TemporaryDirectory() as temp_dir:
        unsquashfs_path = get_tool_path("unsquashfs")
        output = subprocess.check_output([
            unsquashfs_path,
            "-d",
            os.path.join(temp_dir, "squashfs-root"),
            snap_path,
            "-e",
            os.path.join("meta", "snap.yaml"),
        ])
        logger.debug(output)
        with open(os.path.join(temp_dir, "squashfs-root", "meta",
                               "snap.yaml")) as yaml_file:
            snap_yaml = yaml_utils.load(yaml_file)
    return snap_yaml