Publish curated Unraid-AppOps-Gateway source from f4a918d9dba3663faa1f675dcc335c9ec951f30c
This commit is contained in:
1 parent
f50d6e8c2c
commit
4f9c5a1106
4 files changed
+100
-6
No files matched your search
@@ -0,0 +1,25 @@
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def test_source_preflight_handles_recursive_yaml_lists_without_host_packages():
|
||||
source = ROOT / 'scripts/prepare_controller_hub_release_volume.py'
|
||||
program = """
|
||||
import importlib.util, sys
|
||||
spec = importlib.util.spec_from_file_location('controller', sys.argv[1])
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
module._preflight_source_compose(b'services: {deploy-control: {image: fixed}}\\nx-loop: &a [*a]\\n')
|
||||
try:
|
||||
module._preflight_source_compose(b'services: {deploy-control: {image: fixed}}\\nx-loop: &a [*a, {env_file: /tmp/secret}]\\n')
|
||||
except module.VolumeTransitionError as error:
|
||||
assert str(error) == 'controller_volume_external_source_invalid'
|
||||
else:
|
||||
raise AssertionError('external source inside alias accepted')
|
||||
"""
|
||||
result = subprocess.run([sys.executable, '-I', '-S', '-c', program, str(source)],
|
||||
capture_output=True, text=True, timeout=15, check=False)
|
||||
assert result.returncode == 0, result.stderr
|
||||
@@ -1,9 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import importlib.util
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tarfile
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
||||
@@ -668,6 +672,37 @@ def test_capture_program_is_fixed_descriptor_based_and_compiles():
|
||||
assert "open(path,'rb')" not in legacy
|
||||
|
||||
|
||||
@pytest.mark.parametrize("legacy_config", [True, False])
|
||||
def test_capture_archive_roundtrips_through_a_nonseekable_pipe(legacy_config):
|
||||
source = module._controller_capture_source(config_root_in_code=legacy_config)
|
||||
statements = ast.parse(source).body
|
||||
start = next(i for i, node in enumerate(statements)
|
||||
if isinstance(node, ast.Assign)
|
||||
and any(isinstance(target, ast.Name) and target.id == "stream"
|
||||
for target in node.targets))
|
||||
end = next(i for i, node in enumerate(statements[start:], start)
|
||||
if isinstance(node, ast.Expr) and isinstance(node.value, ast.Call)
|
||||
and isinstance(node.value.func, ast.Attribute)
|
||||
and isinstance(node.value.func.value, ast.Name)
|
||||
and node.value.func.value.id == "stream" and node.value.func.attr == "close")
|
||||
archive_program = ast.unparse(ast.Module(body=statements[start:end + 1], type_ignores=[]))
|
||||
fixture = (
|
||||
"import io,sys,tarfile\n"
|
||||
"records={'deploy.py':(b'fixture source',0o644),'secrets/key':(b'fixture secret',0o600)}\n"
|
||||
"dirs={'secrets':0o700}\n"
|
||||
)
|
||||
result = subprocess.run([sys.executable, "-c", fixture + archive_program],
|
||||
capture_output=True, timeout=10, check=False)
|
||||
assert result.returncode == 0, result.stderr.decode("utf-8", "replace")
|
||||
with tarfile.open(fileobj=io.BytesIO(result.stdout), mode="r:") as archive:
|
||||
assert archive.getnames() == ["secrets", "deploy.py", "secrets/key"]
|
||||
assert archive.getmember("secrets").mode == 0o700
|
||||
assert archive.getmember("secrets/key").mode == 0o600
|
||||
assert archive.extractfile("deploy.py").read() == b"fixture source"
|
||||
assert archive.extractfile("secrets/key").read() == b"fixture secret"
|
||||
assert all(member.uid == member.gid == 0 for member in archive.getmembers())
|
||||
|
||||
|
||||
def test_prior_release_capture_must_match_protected_git_tree(monkeypatch):
|
||||
files = module.LEGACY_RELEASE_FILES_2_1_5
|
||||
entries = {name: (f"source:{name}".encode(), 0o644) for name in files}
|
||||
@@ -692,12 +727,41 @@ def test_prior_release_capture_must_match_protected_git_tree(monkeypatch):
|
||||
for name in files if name != "run_repopulse_adoption.py"
|
||||
})
|
||||
outputs["scripts/run_repopulse_adoption.py"] = entries["run_repopulse_adoption.py"][0]
|
||||
controller_id = "c" * 64
|
||||
|
||||
def run(arguments, **_kwargs):
|
||||
assert arguments[:5] == ["docker", "exec", controller_id, "git",
|
||||
f"--git-dir={module.SOURCE_GIT_DIR}"]
|
||||
return outputs[arguments[-1].split(":", 1)[-1]] if arguments[-2] == "show" else outputs["rev-parse"]
|
||||
|
||||
monkeypatch.setattr(module, "_run", run)
|
||||
module._verify_git_source_identity(entries, identity)
|
||||
module._verify_git_source_identity(entries, identity, controller_id=controller_id)
|
||||
outputs["ops/gitea-deploy-broker/deploy.py"] = b"replaced source"
|
||||
with pytest.raises(module.VolumeTransitionError, match="source_mismatch"):
|
||||
module._verify_git_source_identity(entries, identity)
|
||||
module._verify_git_source_identity(entries, identity, controller_id=controller_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("controller_id", ["gitea-deploy-control", "", "a" * 63, "a" * 65])
|
||||
def test_prior_release_source_verification_requires_pinned_container_id(controller_id, monkeypatch):
|
||||
monkeypatch.setattr(module, "_run", lambda *_args, **_kwargs: pytest.fail("Docker must not run"))
|
||||
with pytest.raises(module.VolumeTransitionError, match="container_invalid"):
|
||||
module._verify_git_source_identity({}, {}, controller_id=controller_id)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("name", "revision", "version", "captured", "source", "accepted"),
|
||||
[
|
||||
("run_repopulse_adoption.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.12", b"one\r\ntwo\r\n", b"one\ntwo\n", True),
|
||||
("deploy.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.12", b"one\r\ntwo\r\n", b"one\ntwo\n", False),
|
||||
("run_repopulse_adoption.py", "a" * 40, "2.1.12", b"one\r\ntwo\r\n", b"one\ntwo\n", False),
|
||||
("run_repopulse_adoption.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.13", b"one\r\ntwo\r\n", b"one\ntwo\n", False),
|
||||
("run_repopulse_adoption.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.12", b"one\r\ntwo\n", b"one\ntwo\n", False),
|
||||
("run_repopulse_adoption.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.12", b"one\r\nchanged\r\n", b"one\ntwo\n", False),
|
||||
("run_repopulse_adoption.py", "034c9f844d2455850ba37b31379b7edaa786583e", "2.1.12", b"one\r\r\n", b"one\r\n", False),
|
||||
],
|
||||
)
|
||||
def test_legacy_crlf_compatibility_is_limited_to_one_attested_handoff(
|
||||
name, revision, version, captured, source, accepted,
|
||||
):
|
||||
identity = {"sourceRevision": revision, "controllerVersion": version}
|
||||
assert module._matches_legacy_crlf_source(name, captured, source, identity) is accepted
|
||||
Reference in new issue
Block a user