cs-image-system-default-os-plugin 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.basic.builder_base_os import OsBuilderBase
6
+ from .alpine_type import ALPINE_TYPE
7
+
8
+
9
+ class AlpineOsBuilder(OsBuilderBase):
10
+ """Alpine specific OS builder implementation."""
11
+
12
+ @classmethod
13
+ def csis_name(cls) -> str:
14
+ return ALPINE_TYPE
@@ -0,0 +1,38 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+ from cs_image_system.base.models.os_builder_model import OsBuilderModel
9
+
10
+ ALPINE_TYPE: str = "alpine"
11
+
12
+
13
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
14
+ class AlpineOsBuilderModel(OsBuilderModel):
15
+ """Alpine OS/Source configuration data object.
16
+
17
+ Alpine updates via apk against its default repositories. Note: official
18
+ Alpine cloud images ship doas rather than guaranteeing sudo; if a target
19
+ lacks sudo, this command list will need to become config-adjustable —
20
+ sudo is used here for consistency with every other OS type.
21
+ """
22
+ type = ALPINE_TYPE
23
+
24
+ @classmethod
25
+ def csis_name(cls) -> str:
26
+ return ALPINE_TYPE
27
+
28
+ @classmethod
29
+ def get_command_to_update(cls) -> list[str]:
30
+ """Full package-level update for Alpine (single packer shell script).
31
+
32
+ --available upgrades even when packages must be replaced/downgraded to
33
+ match the repositories — the right semantic for "bring fully current".
34
+ """
35
+ return [
36
+ "sudo apk update",
37
+ "sudo apk upgrade --available",
38
+ ]
@@ -0,0 +1,39 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.os_builder_model import OsBuilderModel
6
+ from cs_image_system.base.models.update_policy import (
7
+ POLICY_FULL,
8
+ POLICY_NONE,
9
+ POLICY_PACKAGES,
10
+ POLICY_SECURITY,
11
+ UpdatePolicy,
12
+ )
13
+
14
+
15
+ class AptOsBuilderModel(OsBuilderModel):
16
+ """Base model for apt-managed OS families (debian, ubuntu)."""
17
+
18
+ def commands_for_policy(self, policy: UpdatePolicy) -> list[str]:
19
+ if policy.policy == POLICY_NONE and not policy.pin:
20
+ return []
21
+ cmds = ["sudo apt-get -o DPkg::Lock::Timeout=600 update"]
22
+ for e in policy.exclude:
23
+ cmds.append(f"sudo apt-mark hold '{e}'")
24
+ if policy.policy == POLICY_SECURITY:
25
+ # only upgrades whose candidate comes from a *-security suite
26
+ cmds.append("sudo apt-get -o DPkg::Lock::Timeout=600 -s dist-upgrade | awk '/^Inst/ && /security/ {print $2}' | xargs -r sudo apt-get -o DPkg::Lock::Timeout=600 install -y --only-upgrade")
27
+ if policy.packages:
28
+ cmds.append("sudo apt-get -o DPkg::Lock::Timeout=600 install -y --only-upgrade " + " ".join(policy.packages))
29
+ elif policy.policy == POLICY_PACKAGES:
30
+ if policy.packages:
31
+ cmds.append("sudo apt-get -o DPkg::Lock::Timeout=600 install -y --only-upgrade " + " ".join(policy.packages))
32
+ elif policy.policy == POLICY_FULL:
33
+ cmds += ["sudo apt-get -o DPkg::Lock::Timeout=600 upgrade -y", "sudo apt-get -o DPkg::Lock::Timeout=600 full-upgrade -y",
34
+ "sudo apt-get -o DPkg::Lock::Timeout=600 autoremove -y", "sudo apt-get -o DPkg::Lock::Timeout=600 autoclean -y"]
35
+ for pkg, ver in policy.pin:
36
+ cmds.append(f"sudo apt-get -o DPkg::Lock::Timeout=600 install -y --allow-downgrades '{pkg}={ver}' && sudo apt-mark hold '{pkg}'")
37
+ for e in policy.exclude:
38
+ cmds.append(f"sudo apt-mark unhold '{e}'")
39
+ return cmds
@@ -0,0 +1,19 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+
6
+
7
+ # AWS_EBS_SOURCE_TYPE: str = "amazon-ebs"
8
+ # @dataclass(kw_only=True)
9
+ # class AwsEbsSourceConfig(SourceModel):
10
+ # """AWS EBS Source configuration data object."""
11
+
12
+ # # type: str = "aws-ebs"
13
+ # # region: str. Region comes from the cloud config
14
+ # # root-device-type assumed to be "ebs" and virtualization-type
15
+ # # to be "hvm" for this type
16
+ # instance_type: str = DEFAULT
17
+ # owners: list[str] = field(default_factory=list)
18
+ # filters: dict[str, str] = field(default_factory=dict)
19
+ # most_recent: bool = True
@@ -0,0 +1,23 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import logging
6
+
7
+ log = logging.getLogger(__name__)
8
+
9
+ from typing import TypeVar
10
+
11
+
12
+ from .debian_type import DEBIAN_TYPE, DebianOsBuilderModel
13
+ from cs_image_system.base.basic.builder_base_os import OsBuilderBase
14
+
15
+
16
+ DEBSOS = TypeVar('DEBSOS', bound=DebianOsBuilderModel)
17
+ class DebianOsBuilder(OsBuilderBase[DEBSOS]):
18
+ """Ansible-based modification provider implementation."""
19
+
20
+ @classmethod
21
+ def csis_name(cls) -> str:
22
+ return DEBIAN_TYPE
23
+
@@ -0,0 +1,29 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from __future__ import annotations
6
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
7
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
8
+ import logging
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ from .apt_type import AptOsBuilderModel
13
+
14
+
15
+
16
+ DEBIAN_TYPE: str = "debian"
17
+ UBUNTU_TYPE: str = "ubuntu"
18
+
19
+
20
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
21
+ class DebianOsBuilderModel(AptOsBuilderModel):
22
+ """Some Debian OS/Source configuration data object."""
23
+ type = DEBIAN_TYPE
24
+
25
+ @classmethod
26
+ def csis_name(cls) -> str:
27
+ return DEBIAN_TYPE
28
+
29
+
@@ -0,0 +1,65 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+ from cs_image_system.base.models.os_builder_model import OsBuilderModel
9
+ from cs_image_system.base.models.update_policy import (
10
+ POLICY_FULL,
11
+ POLICY_NONE,
12
+ POLICY_PACKAGES,
13
+ POLICY_SECURITY,
14
+ UpdatePolicy,
15
+ )
16
+
17
+
18
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
19
+ class DnfOsBuilderModel(OsBuilderModel):
20
+ """dnf-managed families. Subclasses supply ``repo_setup_commands`` (e.g.
21
+ subscription-manager on RHEL); the update policy is realized here
22
+ (EXPLORE "More Targeted Updates?")."""
23
+
24
+ def repo_setup_commands(self) -> list[str]:
25
+ return []
26
+
27
+ def commands_for_policy(self, policy: UpdatePolicy) -> list[str]:
28
+ if policy.policy == POLICY_NONE and not policy.pin:
29
+ return []
30
+ cmds = list(self.repo_setup_commands()) + ["sudo dnf clean all"]
31
+ excl = "".join(f" --exclude={e}" for e in policy.exclude)
32
+
33
+ def retried(cmd: str) -> str:
34
+ # RHUI repos flip their cache path mid-run when the point release
35
+ # moves (found live twice: Errno 2 on a downloaded rpm); a clean
36
+ # retry re-resolves against the new cache
37
+ return f"{cmd} || {{ sudo dnf clean all; {cmd}; }}"
38
+
39
+ def targeted(pkgs: str) -> str:
40
+ # dnf5 (EL10; found live on the first Alma 10 bake) exits 1 on
41
+ # `update <pkg>` when the named package has no pending update
42
+ # ("No packages marked for upgrade") where dnf4 exited 0.
43
+ # check-update keeps stable exit semantics on both (100 =
44
+ # updates exist, 0 = none), so the update runs only behind it;
45
+ # the rc dance keeps the line safe under packer's /bin/sh -e.
46
+ check = f"sudo dnf -q check-update{excl} {pkgs}"
47
+ update = retried(f"sudo dnf -y update{excl} {pkgs}")
48
+ return (f'rc=0; {check} || rc=$?; if [ "$rc" -eq 100 ]; then {update}; '
49
+ f'elif [ "$rc" -ne 0 ]; then exit "$rc"; fi')
50
+
51
+ if policy.policy == POLICY_SECURITY:
52
+ cmds.append(retried(f"sudo dnf -y update --security{excl}"))
53
+ if policy.packages:
54
+ cmds.append(targeted(" ".join(policy.packages)))
55
+ elif policy.policy == POLICY_PACKAGES:
56
+ if policy.packages:
57
+ cmds.append(targeted(" ".join(policy.packages)))
58
+ elif policy.policy == POLICY_FULL:
59
+ cmds += [retried(f"sudo dnf -y upgrade{excl}"),
60
+ "sudo dnf -y autoremove", "sudo dnf -y autoclean"]
61
+ if policy.pin:
62
+ cmds.append("sudo dnf -y install python3-dnf-plugin-versionlock || sudo dnf -y install dnf-plugins-core")
63
+ for pkg, ver in policy.pin:
64
+ cmds.append(f"sudo dnf -y install '{pkg}-{ver}' && sudo dnf versionlock add '{pkg}-{ver}'")
65
+ return cmds
@@ -0,0 +1,35 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+ from .os_sources import SourceModel
9
+
10
+ CONTAINER_SOURCE_TYPE: str = "container"
11
+
12
+
13
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
14
+ class ContainerSourceConfig(SourceModel):
15
+ """Container Source configuration data object."""
16
+
17
+ tag: str
18
+ version: str = "latest"
19
+
20
+ @classmethod
21
+ def csis_name(cls) -> str:
22
+ return CONTAINER_SOURCE_TYPE
23
+
24
+
25
+ DOCKER_SOURCE_TYPE: str = "docker"
26
+
27
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
28
+ class DockerSourceModel(ContainerSourceConfig):
29
+ """Docker Source configuration data object."""
30
+
31
+ @classmethod
32
+ def csis_name(cls) -> str:
33
+ return DOCKER_SOURCE_TYPE
34
+
35
+
@@ -0,0 +1,14 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.basic.builder_base_os import OsBuilderBase
6
+ from .fedora_type import FEDORA_TYPE
7
+
8
+
9
+ class FedoraOsBuilder(OsBuilderBase):
10
+ """Fedora specific OS builder implementation."""
11
+
12
+ @classmethod
13
+ def csis_name(cls) -> str:
14
+ return FEDORA_TYPE
@@ -0,0 +1,24 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+ from .dnf_type import DnfOsBuilderModel
9
+
10
+ FEDORA_TYPE: str = "fedora"
11
+
12
+
13
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
14
+ class FedoraOsBuilderModel(DnfOsBuilderModel):
15
+ """Fedora OS/Source configuration data object.
16
+
17
+ Unlike RHEL, Fedora needs no subscription-manager repository enablement —
18
+ a package-level update is a plain dnf upgrade against the default repos.
19
+ """
20
+ type = FEDORA_TYPE
21
+
22
+ @classmethod
23
+ def csis_name(cls) -> str:
24
+ return FEDORA_TYPE
@@ -0,0 +1,9 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import logging
6
+
7
+
8
+ log = logging.getLogger(__name__)
9
+
@@ -0,0 +1,61 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ import logging
6
+ from cs_image_system.base.basic.abstract_plugin_metadata import AbstractPluginMetadata
7
+ from cs_image_system.base.models.os_builder_runtime_config import OSBuilderBaseImageBuilderSubconfig
8
+ from cs_image_system.base.protocols.plugin_metadata import PluginMetadataProtocol
9
+ from cs_image_system.default_os_plugin.os__image_bldr_config_builder import DefaultOSImageBuilderConfigBuilder
10
+ from .alpine_os_builder import AlpineOsBuilder
11
+ from .alpine_type import ALPINE_TYPE, AlpineOsBuilderModel
12
+ from .debian_os_builder import DebianOsBuilder
13
+ from .debian_type import DEBIAN_TYPE, DebianOsBuilderModel
14
+ from .fedora_os_builder import FedoraOsBuilder
15
+ from .fedora_type import FEDORA_TYPE, FedoraOsBuilderModel
16
+ from .rhel_type import RHEL_TYPE, RhelOsBuilderModel
17
+ from .rhel_os_builder import RhelOsBuilder
18
+ from .ubuntu_os_builder import UbuntuOsBuilder
19
+ from .ubuntu_os_type import UBUNTU_TYPE, UbuntuOsBuilderModel
20
+
21
+ log = logging.getLogger(__name__)
22
+
23
+ class DefaultOsTypes(AbstractPluginMetadata, PluginMetadataProtocol):
24
+ def __init__(self) -> None:
25
+ super().__init__( "1", "3.13",
26
+ {RHEL_TYPE: [
27
+ RhelOsBuilderModel,
28
+ RhelOsBuilder
29
+ ],
30
+ UBUNTU_TYPE: [
31
+ UbuntuOsBuilderModel,
32
+ UbuntuOsBuilder
33
+ ],
34
+ DEBIAN_TYPE: [
35
+ DebianOsBuilderModel,
36
+ DebianOsBuilder
37
+ ],
38
+ FEDORA_TYPE: [
39
+ FedoraOsBuilderModel,
40
+ FedoraOsBuilder
41
+ ],
42
+ ALPINE_TYPE: [
43
+ AlpineOsBuilderModel,
44
+ AlpineOsBuilder
45
+ ]
46
+ },
47
+ {
48
+ OSBuilderBaseImageBuilderSubconfig: DefaultOSImageBuilderConfigBuilder,
49
+ DebianOsBuilderModel: DebianOsBuilder,
50
+ RhelOsBuilderModel: RhelOsBuilder,
51
+ UbuntuOsBuilderModel: UbuntuOsBuilder,
52
+ FedoraOsBuilderModel: FedoraOsBuilder,
53
+ AlpineOsBuilderModel: AlpineOsBuilder
54
+ }
55
+ )
56
+
57
+
58
+ def initialize():
59
+ log.debug("Initializing Default OS Provider")
60
+ return DefaultOsTypes()
61
+
@@ -0,0 +1,17 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import TypeVar
6
+
7
+ from cs_image_system.base.basic.builder_base_os import OsRuntimeConfigBuilderBase
8
+ from cs_image_system.base.models.os_builder_runtime_config import OSBuilderBaseImageBuilderSubconfig
9
+
10
+
11
+ DEFAULT_RTCB = TypeVar('DEFAULT_RTCB', bound=OSBuilderBaseImageBuilderSubconfig)
12
+ class DefaultOSImageBuilderConfigBuilder(OsRuntimeConfigBuilderBase[DEFAULT_RTCB]):
13
+ """Default OS runtime config builder implementation."""
14
+
15
+ @classmethod
16
+ def csis_name(cls) -> str:
17
+ return "default_os_runtime_config_builder"
@@ -0,0 +1,26 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from dataclasses import field
6
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
7
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
8
+ from typing import Any
9
+ from cs_image_system.base.constants import VCT
10
+ from cs_image_system.base.helpers.field_helpers import fk_field
11
+ from cs_image_system.base.models.builder_model import NameTyped
12
+ from cs_image_system.base.protocols.plugin_metadata import PluginArtifactProtocol
13
+
14
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
15
+ class SourceModel(NameTyped, PluginArtifactProtocol):
16
+ """Source configuration data object."""
17
+ runtime: str = fk_field(target=VCT.RUNTIME_BUILDER_MODEL, metadata={
18
+ "description": "The runtime-builder this config uses",
19
+ "required": True,
20
+ })
21
+ config: dict[str, Any] = field(default_factory=dict)
22
+ # catchall: CatchAll
23
+
24
+ @classmethod
25
+ def csis_classifier(cls) -> VCT:
26
+ return VCT.SOURCE_MODEL_MODEL
@@ -0,0 +1,15 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.basic.builder_base_os import OsBuilderBase
6
+ from .rhel_type import RHEL_TYPE
7
+
8
+
9
+ # @registry.register_class_to_type_and_key(type_=OS_BUILDER, key=RHEL_TYPE)
10
+ class RhelOsBuilder(OsBuilderBase):
11
+ """RHEL 8 specific Ansible-based modification provider implementation."""
12
+
13
+ @classmethod
14
+ def csis_name(cls) -> str:
15
+ return RHEL_TYPE
@@ -0,0 +1,56 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+
9
+
10
+
11
+
12
+ from .dnf_type import DnfOsBuilderModel
13
+
14
+ RHEL_TYPE:str = "rhel"
15
+
16
+
17
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
18
+ class RhelOsBuilderModel(DnfOsBuilderModel):
19
+ """RHEL 8 OS/Source configuration data object."""
20
+ type = RHEL_TYPE
21
+ subscription_id: str | None = None
22
+
23
+ @classmethod
24
+ def csis_name(cls) -> str:
25
+ return RHEL_TYPE
26
+
27
+ def __post_init__(self) -> None:
28
+ super().__post_init__()
29
+ # stage 63: checked at load, whatever the update policy (it ran only
30
+ # when update commands were generated, so `policy: none` with an
31
+ # unsupported major was never refused)
32
+ v = self.version()
33
+ if not v:
34
+ raise ValueError(f"Could not determine RHEL version from family_version '{self.family_version}' "
35
+ f"in OS builder {self.name}")
36
+ if v.major not in (8, 9, 10):
37
+ raise ValueError(f"Unsupported RHEL version '{v}' in OS builder {self.name} (supported: 8, 9, 10)")
38
+
39
+ def repo_setup_commands(self) -> list[str]:
40
+ """Version-aware repository setup (RHEL 8/9/10 enable different repos).
41
+
42
+ Guarded on registration (found live, TODO stage 1: cloud vendor
43
+ RHEL AMIs are pay-as-you-go/RHUI, "This system is not yet
44
+ registered" -- their RHUI repos already serve baseos/appstream and
45
+ security metadata, so on an unregistered system this is a no-op)."""
46
+ v = self.version()
47
+ assert v is not None, "checked at load (__post_init__)"
48
+ repos = " ".join(f"--enable='rhel-{v.major}-for-x86_64-{r}-rpms'" for r in ("baseos", "appstream")) + f" --enable='codeready-builder-for-rhel-{v.major}-x86_64-rpms'"
49
+ return [
50
+ "# subscription-managed systems get their repos enabled; RHUI/PAYG images skip",
51
+ ("if sudo subscription-manager identity >/dev/null 2>&1; then "
52
+ "sudo subscription-manager refresh; "
53
+ "sudo subscription-manager repos --disable='*'; "
54
+ f"sudo subscription-manager repos {repos}; "
55
+ "else echo 'not subscription-registered (RHUI image): using vendor repos as-is'; fi"),
56
+ ]
@@ -0,0 +1,19 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from typing import TypeVar
6
+
7
+ from cs_image_system.base.basic.builder_base_os import OsBuilderBase
8
+ from .ubuntu_os_type import UbuntuOsBuilderModel, UBUNTU_TYPE
9
+
10
+
11
+
12
+ UBUOS = TypeVar('UBUOS', bound=UbuntuOsBuilderModel)
13
+ # @registry.register_class_to_type_and_key(type_=OS_BUILDER, key=UBUNTU_TYPE)
14
+ class UbuntuOsBuilder(OsBuilderBase[UBUOS]):
15
+ """Ansible-based modification provider implementation."""
16
+
17
+ @classmethod
18
+ def csis_name(cls) -> str:
19
+ return UBUNTU_TYPE
@@ -0,0 +1,22 @@
1
+ # SPDX-FileCopyrightText: 2026 Mykel Alvis <mykelalvis@infrastructurebuilder.org>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ from cs_image_system.base.models.model_config import CSIS_MODEL_CONFIG
6
+ from pydantic.dataclasses import dataclass # stage 23: validation at construction
7
+
8
+ from cs_image_system.default_os_plugin.apt_type import AptOsBuilderModel
9
+
10
+ UBUNTU_TYPE: str = "ubuntu"
11
+
12
+
13
+ @dataclass(kw_only=True, config=CSIS_MODEL_CONFIG)
14
+ # @registry.register_class_to_type_and_key(type_=OS_BUILDER_MODEL, key=UBUNTU_TYPE)
15
+ class UbuntuOsBuilderModel(AptOsBuilderModel):
16
+ """Some Ubuntu OS/Source configuration data object."""
17
+ type = UBUNTU_TYPE
18
+
19
+ @classmethod
20
+ def csis_name(cls) -> str:
21
+ return UBUNTU_TYPE
22
+