up
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ops/offline-kit/__pycache__/mirror_debug_store.cpython-312.pyc
Normal file
BIN
ops/offline-kit/__pycache__/mirror_debug_store.cpython-312.pyc
Normal file
Binary file not shown.
@@ -184,6 +184,45 @@ def copy_plugins_and_assets(staging_dir: Path) -> None:
|
||||
copy_if_exists(REPO_ROOT / "docs" / "24_OFFLINE_KIT.md", docs_dir / "24_OFFLINE_KIT.md")
|
||||
copy_if_exists(REPO_ROOT / "docs" / "ops" / "telemetry-collector.md", docs_dir / "telemetry-collector.md")
|
||||
copy_if_exists(REPO_ROOT / "docs" / "ops" / "telemetry-storage.md", docs_dir / "telemetry-storage.md")
|
||||
copy_if_exists(REPO_ROOT / "docs" / "airgap" / "mirror-bundles.md", docs_dir / "mirror-bundles.md")
|
||||
|
||||
|
||||
def copy_cli_and_taskrunner_assets(release_dir: Path, staging_dir: Path) -> None:
|
||||
"""Bundle CLI binaries, task pack docs, and Task Runner samples when available."""
|
||||
cli_src = release_dir / "cli"
|
||||
if cli_src.exists():
|
||||
copy_if_exists(cli_src, staging_dir / "cli")
|
||||
|
||||
taskrunner_bootstrap = staging_dir / "bootstrap" / "task-runner"
|
||||
taskrunner_bootstrap.mkdir(parents=True, exist_ok=True)
|
||||
copy_if_exists(REPO_ROOT / "etc" / "task-runner.yaml.sample", taskrunner_bootstrap / "task-runner.yaml.sample")
|
||||
|
||||
docs_dir = staging_dir / "docs"
|
||||
copy_if_exists(REPO_ROOT / "docs" / "task-packs", docs_dir / "task-packs")
|
||||
copy_if_exists(REPO_ROOT / "docs" / "modules" / "taskrunner", docs_dir / "modules" / "taskrunner")
|
||||
|
||||
|
||||
def copy_orchestrator_assets(release_dir: Path, staging_dir: Path) -> None:
|
||||
"""Copy orchestrator service, worker SDK, postgres snapshot, and dashboards when present."""
|
||||
mapping = {
|
||||
release_dir / "orchestrator" / "service": staging_dir / "orchestrator" / "service",
|
||||
release_dir / "orchestrator" / "worker-sdk": staging_dir / "orchestrator" / "worker-sdk",
|
||||
release_dir / "orchestrator" / "postgres": staging_dir / "orchestrator" / "postgres",
|
||||
release_dir / "orchestrator" / "dashboards": staging_dir / "orchestrator" / "dashboards",
|
||||
}
|
||||
for src, dest in mapping.items():
|
||||
copy_if_exists(src, dest)
|
||||
|
||||
|
||||
def copy_export_and_notifier_assets(release_dir: Path, staging_dir: Path) -> None:
|
||||
"""Copy Export Center and Notifier offline bundles and tooling when present."""
|
||||
copy_if_exists(release_dir / "export-center", staging_dir / "export-center")
|
||||
copy_if_exists(release_dir / "notifier", staging_dir / "notifier")
|
||||
|
||||
|
||||
def copy_surface_secrets(release_dir: Path, staging_dir: Path) -> None:
|
||||
"""Include Surface.Secrets bundles and manifests if present."""
|
||||
copy_if_exists(release_dir / "surface-secrets", staging_dir / "surface-secrets")
|
||||
|
||||
|
||||
def copy_bootstrap_configs(staging_dir: Path) -> None:
|
||||
@@ -267,7 +306,21 @@ def scan_files(staging_dir: Path, exclude: Optional[set[str]] = None) -> list[Or
|
||||
)
|
||||
)
|
||||
)
|
||||
return entries
|
||||
return entries
|
||||
|
||||
|
||||
def copy_container_bundles(release_dir: Path, staging_dir: Path) -> None:
|
||||
"""Copy container air-gap bundles if present in the release directory."""
|
||||
candidates = [release_dir / "containers", release_dir / "images"]
|
||||
target_dir = staging_dir / "containers"
|
||||
for root in candidates:
|
||||
if not root.exists():
|
||||
continue
|
||||
for bundle in sorted(root.glob("**/*")):
|
||||
if bundle.is_file() and bundle.suffix in {".gz", ".tar", ".tgz"}:
|
||||
target_path = target_dir / bundle.relative_to(root)
|
||||
target_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(bundle, target_path)
|
||||
|
||||
|
||||
def write_offline_manifest(
|
||||
@@ -372,11 +425,16 @@ def build_offline_kit(args: argparse.Namespace) -> MutableMapping[str, Any]:
|
||||
if isinstance(checksums, Mapping):
|
||||
release_manifest_sha = checksums.get("sha256")
|
||||
|
||||
copy_release_manifests(release_dir, staging_dir)
|
||||
copy_release_manifests(release_dir, staging_dir)
|
||||
copy_component_artifacts(manifest_data, release_dir, staging_dir)
|
||||
copy_collections(manifest_data, release_dir, staging_dir)
|
||||
copy_plugins_and_assets(staging_dir)
|
||||
copy_bootstrap_configs(staging_dir)
|
||||
copy_cli_and_taskrunner_assets(release_dir, staging_dir)
|
||||
copy_container_bundles(release_dir, staging_dir)
|
||||
copy_orchestrator_assets(release_dir, staging_dir)
|
||||
copy_export_and_notifier_assets(release_dir, staging_dir)
|
||||
copy_surface_secrets(release_dir, staging_dir)
|
||||
copy_third_party_licenses(staging_dir)
|
||||
package_telemetry_bundle(staging_dir)
|
||||
|
||||
|
||||
@@ -40,8 +40,42 @@ class OfflineKitBuilderTests(unittest.TestCase):
|
||||
json.dump(payload, handle, indent=2)
|
||||
handle.write("\n")
|
||||
|
||||
def _create_sample_release(self) -> None:
|
||||
self.release_dir.mkdir(parents=True, exist_ok=True)
|
||||
def _create_sample_release(self) -> None:
|
||||
self.release_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
cli_archive = self.release_dir / "cli" / "stellaops-cli-linux-x64.tar.gz"
|
||||
cli_archive.parent.mkdir(parents=True, exist_ok=True)
|
||||
cli_archive.write_bytes(b"cli-bytes")
|
||||
compute_sha256(cli_archive)
|
||||
|
||||
container_bundle = self.release_dir / "containers" / "stellaops-containers.tar.gz"
|
||||
container_bundle.parent.mkdir(parents=True, exist_ok=True)
|
||||
container_bundle.write_bytes(b"container-bundle")
|
||||
compute_sha256(container_bundle)
|
||||
|
||||
orchestrator_service = self.release_dir / "orchestrator" / "service" / "orchestrator-service.tar.gz"
|
||||
orchestrator_service.parent.mkdir(parents=True, exist_ok=True)
|
||||
orchestrator_service.write_bytes(b"orch-service")
|
||||
compute_sha256(orchestrator_service)
|
||||
|
||||
orchestrator_dash = self.release_dir / "orchestrator" / "dashboards" / "dash.json"
|
||||
orchestrator_dash.parent.mkdir(parents=True, exist_ok=True)
|
||||
orchestrator_dash.write_text("{}\n", encoding="utf-8")
|
||||
|
||||
export_bundle = self.release_dir / "export-center" / "export-offline-bundle.tar.gz"
|
||||
export_bundle.parent.mkdir(parents=True, exist_ok=True)
|
||||
export_bundle.write_bytes(b"export")
|
||||
compute_sha256(export_bundle)
|
||||
|
||||
notifier_pack = self.release_dir / "notifier" / "notifier-offline-pack.tar.gz"
|
||||
notifier_pack.parent.mkdir(parents=True, exist_ok=True)
|
||||
notifier_pack.write_bytes(b"notifier")
|
||||
compute_sha256(notifier_pack)
|
||||
|
||||
secrets_bundle = self.release_dir / "surface-secrets" / "secrets-bundle.tar.gz"
|
||||
secrets_bundle.parent.mkdir(parents=True, exist_ok=True)
|
||||
secrets_bundle.write_bytes(b"secrets")
|
||||
compute_sha256(secrets_bundle)
|
||||
|
||||
sbom_path = self.release_dir / "artifacts/sboms/sample.cyclonedx.json"
|
||||
sbom_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
@@ -114,10 +148,10 @@ class OfflineKitBuilderTests(unittest.TestCase):
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
manifest = OrderedDict(
|
||||
(
|
||||
(
|
||||
"release",
|
||||
manifest = OrderedDict(
|
||||
(
|
||||
(
|
||||
"release",
|
||||
OrderedDict(
|
||||
(
|
||||
("version", "1.0.0"),
|
||||
@@ -216,9 +250,9 @@ class OfflineKitBuilderTests(unittest.TestCase):
|
||||
),
|
||||
)
|
||||
)
|
||||
write_manifest(manifest, self.release_dir)
|
||||
|
||||
def test_build_offline_kit(self) -> None:
|
||||
write_manifest(manifest, self.release_dir)
|
||||
|
||||
def test_build_offline_kit(self) -> None:
|
||||
args = argparse.Namespace(
|
||||
version="2025.10.0",
|
||||
channel="edge",
|
||||
@@ -242,10 +276,34 @@ class OfflineKitBuilderTests(unittest.TestCase):
|
||||
self.assertTrue((bootstrap_notify / "notify.yaml").exists())
|
||||
self.assertTrue((bootstrap_notify / "notify-web.secret.example").exists())
|
||||
|
||||
taskrunner_bootstrap = self.staging_dir / "bootstrap" / "task-runner"
|
||||
self.assertTrue((taskrunner_bootstrap / "task-runner.yaml.sample").exists())
|
||||
|
||||
docs_taskpacks = self.staging_dir / "docs" / "task-packs"
|
||||
self.assertTrue(docs_taskpacks.exists())
|
||||
self.assertTrue((self.staging_dir / "docs" / "mirror-bundles.md").exists())
|
||||
|
||||
containers_dir = self.staging_dir / "containers"
|
||||
self.assertTrue((containers_dir / "stellaops-containers.tar.gz").exists())
|
||||
|
||||
orchestrator_dir = self.staging_dir / "orchestrator"
|
||||
self.assertTrue((orchestrator_dir / "service" / "orchestrator-service.tar.gz").exists())
|
||||
self.assertTrue((orchestrator_dir / "dashboards" / "dash.json").exists())
|
||||
|
||||
export_dir = self.staging_dir / "export-center"
|
||||
self.assertTrue((export_dir / "export-offline-bundle.tar.gz").exists())
|
||||
|
||||
notifier_dir = self.staging_dir / "notifier"
|
||||
self.assertTrue((notifier_dir / "notifier-offline-pack.tar.gz").exists())
|
||||
|
||||
secrets_dir = self.staging_dir / "surface-secrets"
|
||||
self.assertTrue((secrets_dir / "secrets-bundle.tar.gz").exists())
|
||||
|
||||
with offline_manifest.open("r", encoding="utf-8") as handle:
|
||||
manifest_data = json.load(handle)
|
||||
artifacts = manifest_data["artifacts"]
|
||||
self.assertTrue(any(item["name"].startswith("sboms/") for item in artifacts))
|
||||
self.assertTrue(any(item["name"].startswith("cli/") for item in artifacts))
|
||||
|
||||
metadata_path = Path(result["metadataPath"])
|
||||
data = json.loads(metadata_path.read_text(encoding="utf-8"))
|
||||
@@ -258,6 +316,11 @@ class OfflineKitBuilderTests(unittest.TestCase):
|
||||
self.assertTrue(any(name.startswith("sboms/sample-") for name in members))
|
||||
self.assertIn("bootstrap/notify/notify.yaml", members)
|
||||
self.assertIn("bootstrap/notify/notify-web.secret.example", members)
|
||||
self.assertIn("containers/stellaops-containers.tar.gz", members)
|
||||
self.assertIn("orchestrator/service/orchestrator-service.tar.gz", members)
|
||||
self.assertIn("export-center/export-offline-bundle.tar.gz", members)
|
||||
self.assertIn("notifier/notifier-offline-pack.tar.gz", members)
|
||||
self.assertIn("surface-secrets/secrets-bundle.tar.gz", members)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user