Skip to content

Commit

Permalink
add add_runtime_files function
Browse files Browse the repository at this point in the history
  • Loading branch information
gilesknap committed Jun 24, 2024
1 parent 67ec3ae commit d68f0c8
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 18 deletions.
7 changes: 6 additions & 1 deletion src/ibek/globals.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,14 @@ def IOC_LIBS(self):

@property
def RUNTIME_DEBS(self):
"""ibek-support list of declared libs"""
"""ibek-support list of declared deb packages to install in runtime stage"""
return self.SUPPORT / "configure" / "runtime_debs"

@property
def RUNTIME_FILES(self):
"""ibek-support list of files to copy to the runtime stage"""
return self.SUPPORT / "configure" / "runtime_files_list"


# Folder containing templates for IOC src etc.
TEMPLATES = Path(__file__).parent / "templates"
Expand Down
21 changes: 12 additions & 9 deletions src/ibek/ioc_cmds/assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ def extract_assets(
"""

if GLOBALS.STATIC_BUILD:
# static builds only need database files from support modules
asset_matches = "db"
# static builds only need database and .proto files from support modules
asset_matches = "db|*/protocol"
else:
# dynamically linked builds need binaries
asset_matches = "bin|db|lib"
# dynamically linked builds need binaries and protocol files
asset_matches = "bin|db|lib|*/protocol"

# chdir out of the folders we will move
os.chdir(source)
Expand All @@ -66,18 +66,21 @@ def extract_assets(
Path.readlink(
GLOBALS.IOC_FOLDER
).parent, # get contents of IOC folder and its source (parent)
Path("/venv"), # get the virtualenv
] + list(
source.glob("ibek*")
) # get ibek-support and related folders
GLOBALS.EPICS_ROOT.parent / "venv", # virtualenv is a peer to /epics
]
else:
default_assets = []

# folder names with binary files in them
binary = ["bin", "lib"]

# get the list of additional files supplied by add_runtime_files
if GLOBALS.RUNTIME_FILES.exists():
with GLOBALS.RUNTIME_FILES.open("r") as f:
runtime_files = [Path(line.strip()) for line in f.readlines()]

# move the default assets and extras in their entirety
extra_files = default_assets + extras
extra_files = default_assets + extras + runtime_files
for asset in extra_files:
src = source / asset
if src.exists():
Expand Down
14 changes: 14 additions & 0 deletions src/ibek/support_cmds/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,17 @@ def generate_schema(
typer.echo(Support.get_schema())
else:
output.write_text(Support.get_schema())


@support_cli.command()
def add_runtime_files(
files: List[str] = typer.Argument(
None, help="list of file or folders to add to the runtime image"
),
):
"""
Adds to the list of folders or filesthat are copied over to the runtime
stage of the container build.
"""
files = files or []
add_list_to_file(GLOBALS.RUNTIME_FILES, files)
27 changes: 19 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,26 @@ def entity_factory():
def tmp_epics_root(samples: Path, tmp_path: Path, mocker: MockerFixture):
# create an partially populated epics_root structure in a temporary folder
epics = tmp_path / "epics"
epics_source = samples / "epics"
epics.mkdir()
shutil.copytree(samples / "epics" / "pvi-defs", epics / "pvi-defs")
shutil.copytree(samples / "epics" / "support", epics / "support")
Path.mkdir(epics / "opi")
Path.mkdir(epics / "epics-base")
Path.mkdir(epics / "ioc/config", parents=True)
Path.mkdir(epics / "ibek-defs")
Path.mkdir(epics / "runtime")

# a dummy venv for testing extract_assets
Path.mkdir(tmp_path / "venv")

# create the minimal structure under epics root
files = epics_source.glob("*")
for f in files:
if f.is_dir():
shutil.copytree(f, epics / f.name)
else:
shutil.copy(f, epics / f.name)
Path.mkdir(epics / "opi", exist_ok=True)
Path.mkdir(epics / "epics-base", exist_ok=True)
Path.mkdir(epics / "generic-source" / "ioc" / "config", parents=True)
(epics / "ioc").symlink_to(epics / "generic-source" / "ioc")
Path.mkdir(epics / "ibek-defs", exist_ok=True)
Path.mkdir(epics / "runtime", exist_ok=True)

# patch the global EPICS_ROOT to point to this temporary folder
mocker.patch.object(GLOBALS, "_EPICS_ROOT", epics)

# this should not be needed - what gives?
Expand Down
1 change: 1 addition & 0 deletions tests/samples/epics/runtime_file
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dummy file for testing add_runtime_files
1 change: 1 addition & 0 deletions tests/samples/epics/runtime_folder/text1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dummy file for testing add_runtime_files
1 change: 1 addition & 0 deletions tests/samples/epics/runtime_folder/text2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dummy file for testing add_runtime_files
26 changes: 26 additions & 0 deletions tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,19 @@
"""

import dataclasses
import shutil
from pathlib import Path

import jinja2
import pytest

from ibek.commands import semver_compare
from ibek.ioc import id_to_entity
from ibek.ioc_cmds.assets import extract_assets
from ibek.ioc_factory import IocFactory
from ibek.parameters import IdParam, ObjectParam
from ibek.support import EntityModel, Support
from ibek.support_cmds.commands import add_runtime_files
from ibek.utils import UTILS


Expand Down Expand Up @@ -89,3 +93,25 @@ def test_strict():
my_template = "{{ person.name ~ ' of age ' ~ person.height }}"
with pytest.raises(jinja2.exceptions.UndefinedError):
text = UTILS.render({"person": p}, my_template)


def test_extract_assets(tmp_epics_root: Path, samples: Path):
"""
Test the extract_assets function
"""
runtime_files = [
str(tmp_epics_root / "runtime_file"),
str(tmp_epics_root / "runtime_folder"),
]
add_runtime_files(runtime_files)

dest = Path("/tmp/ibek_test_assests")
shutil.rmtree(dest, ignore_errors=True)
dest.mkdir()

extract_assets(dest, tmp_epics_root, [], True)
new_epics_root = list(dest.glob("tmp/*/*/*/epics"))[0]

assert Path.exists(new_epics_root / "runtime_file")
assert Path.exists(new_epics_root / "runtime_folder/text1.txt")
assert Path.exists(new_epics_root / "runtime_folder/text2.txt")

0 comments on commit d68f0c8

Please sign in to comment.