Skip to content

Commit

Permalink
Update fact names and operations for 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
Fizzadar committed Nov 17, 2024
1 parent 91ec724 commit a71caf9
Show file tree
Hide file tree
Showing 23 changed files with 58 additions and 78 deletions.
1 change: 1 addition & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[files]
extend-exclude = [
"tests/facts/apt.SimulateOperationWillChange/upgrade.json",
"tests/facts/opkg.Packages/opkg_packages.json",
"tests/words.txt",
]

Expand Down
53 changes: 34 additions & 19 deletions pyinfra/facts/opkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@
see https://openwrt.org/docs/guide-user/additional-software/opkg
"""

import re
from typing import Dict, NamedTuple, Union

from pyinfra import logger
from pyinfra.api import FactBase
from pyinfra.facts.util.packaging import parse_packages

# TODO - change NamedTuple to dataclass but need to figure out how to get json serialization
# TODO - change NamedTuple to dataclass Opkgbut need to figure out how to get json serialization
# to work without changing core code


class PkgUpgradeInfo(NamedTuple):
class OpkgPkgUpgradeInfo(NamedTuple):
installed: str
available: str


class ConfInfo(NamedTuple):
class OpkgConfInfo(NamedTuple):
paths: Dict[str, str] # list of paths, e.g. {'root':'/', 'ram':'/tmp}
list_dir: str # where package lists are stored, e.g. /var/opkg-lists
options: Dict[
Expand All @@ -33,13 +34,13 @@ class ConfInfo(NamedTuple):
arch_cfg: Dict[str, int] # priorities for architectures


class FeedInfo(NamedTuple):
class OpkgFeedInfo(NamedTuple):
url: str # url for the feed
fmt: str # format of the feed, e.g. "src/gz"
kind: str # whether it comes from the 'distribution' or is 'custom'


class Conf(FactBase):
class OpkgConf(FactBase):
"""
Returns a NamedTuple with the current configuration:
Expand Down Expand Up @@ -77,9 +78,13 @@ class Conf(FactBase):
""",
re.X,
)
conf_file = "/etc/opkg.conf"
command = f"cat {conf_file}"
default = lambda x: ConfInfo({}, "", {}, {}) # noqa:

@staticmethod
def default():
return OpkgConfInfo({}, "", {}, {})

def command(self) -> str:
return "cat /etc/opkg.conf"

def process(self, output):
dest, lists_dir, options, arch_cfg = {}, "", {}, {}
Expand All @@ -97,10 +102,10 @@ def process(self, output):
elif match.group("option") is not None:
options[match.group("option")] = match.group("value") or True

return ConfInfo(dest, lists_dir, options, arch_cfg)
return OpkgConfInfo(dest, lists_dir, options, arch_cfg)


class Feeds(FactBase):
class OpkgFeeds(FactBase):
"""
Returns a dictionary containing the information for the distribution-provided and
custom opkg feeds:
Expand All @@ -120,9 +125,11 @@ class Feeds(FactBase):
regex = re.compile(
r"^(CUSTOM)|(?:\s*(?P<fmt>[\w/]+)\s+(?P<name>[\w]+)\s+(?P<url>[\w./:]+))?(?:\s*#.*)?$"
)
command = "cat /etc/opkg/distfeeds.conf; echo CUSTOM; cat /etc/opkg/customfeeds.conf"
default = dict

def command(self) -> str:
return "cat /etc/opkg/distfeeds.conf; echo CUSTOM; cat /etc/opkg/customfeeds.conf"

def process(self, output):
feeds, kind = {}, "distribution"
for line in output:
Expand All @@ -133,12 +140,14 @@ def process(self, output):
elif match.group(0) == "CUSTOM":
kind = "custom"
elif match.group("name") is not None:
feeds[match.group("name")] = FeedInfo(match.group("url"), match.group("fmt"), kind)
feeds[match.group("name")] = OpkgFeedInfo(
match.group("url"), match.group("fmt"), kind
)

return feeds


class InstallableArchitectures(FactBase):
class OpkgInstallableArchitectures(FactBase):
"""
Returns a dictionary containing the currently installable architectures for this system along
with their priority:
Expand All @@ -153,9 +162,11 @@ class InstallableArchitectures(FactBase):
"""

regex = re.compile(r"^(?:\s*arch\s+(?P<arch>[\w]+)\s+(?P<prio>\d+))?(\s*#.*)?$")
command = "/bin/opkg print-architecture"
default = dict

def command(self) -> str:
return "/bin/opkg print-architecture"

def process(self, output):
arch_list = {}
for line in output:
Expand All @@ -169,7 +180,7 @@ def process(self, output):
return arch_list


class Packages(FactBase):
class OpkgPackages(FactBase):
"""
Returns a dict of installed opkg packages:
Expand All @@ -181,15 +192,17 @@ class Packages(FactBase):
}
"""

command = "/bin/opkg list-installed"
regex = r"^([a-zA-Z0-9][\w\-\.]*)\s-\s([\w\-\.]+)"
default = dict

def command(self) -> str:
return "/bin/opkg list-installed"

def process(self, output):
return parse_packages(self.regex, sorted(output))


class UpgradeablePackages(FactBase):
class OpkgUpgradeablePackages(FactBase):
"""
Returns a dict of installed and upgradable opkg packages:
Expand All @@ -201,17 +214,19 @@ class UpgradeablePackages(FactBase):
}
"""

command = "/bin/opkg list-upgradable" # yes, really spelled that way
regex = re.compile(r"^([a-zA-Z0-9][\w\-.]*)\s-\s([\w\-.]+)\s-\s([\w\-.]+)")
default = dict
use_default_on_error = True

def command(self) -> str:
return "/bin/opkg list-upgradable" # yes, really spelled that way

def process(self, output):
result = {}
for line in output:
match = self.regex.match(line)
if match and len(match.groups()) == 3:
result[match.group(1)] = PkgUpgradeInfo(match.group(2), match.group(3))
result[match.group(1)] = OpkgPkgUpgradeInfo(match.group(2), match.group(3))
else:
logger.warning(f"Opkg: could not list-upgradable line '{line}'")

Expand Down
24 changes: 8 additions & 16 deletions pyinfra/operations/opkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,30 @@
see https://openwrt.org/docs/guide-user/additional-software/opkg
OpenWrt recommends against upgrading all packages thus there is no ``opkg.upgrade`` function
"""

from typing import List, Union

from pyinfra import host
from pyinfra.api import StringCommand, operation
from pyinfra.facts.opkg import Packages
from pyinfra.facts.opkg import OpkgPackages
from pyinfra.operations.util.packaging import ensure_packages

EQUALS = "="
UPDATE_ENTRY = "$$updated$$" # use $ as not allowed in package names (TODO - need reference)


@operation(is_idempotent=False)
def update(force: bool = False):
def update():
"""
Update the local opkg information. Unless force is set, will only run
once per host per invocation of pyinfra.
+ force - refresh the package list even if already done
Update the local opkg information.
"""

if force or (UPDATE_ENTRY not in host.get_fact(Packages)):
host.get_fact(Packages).update({UPDATE_ENTRY: [UPDATE_ENTRY]})
yield StringCommand("opkg update > /dev/null 2>&1")
else:
host.noop("opkg packages already updated and not forced")
yield StringCommand("opkg update")


_update = update


@operation
@operation()
def packages(
packages: Union[str, List[str]] = "",
present: bool = True,
Expand Down Expand Up @@ -81,16 +74,15 @@ def packages(
raise ValueError(f"opkg does not support version pinning but found for: '{have_equals}'")

if update:
yield from _update()
yield from _update._inner()

yield from ensure_packages(
host,
pkg_list,
host.get_fact(Packages),
host.get_fact(OpkgPackages),
present,
install_command="opkg install",
upgrade_command="opkg upgrade",
uninstall_command="opkg remove",
latest=latest,
# lower=True, # FIXME - does ensure_packages always do this or ?
)
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion tests/operations/opkg.packages/add_existing_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"update": false
},
"facts": {
"opkg.Packages": {"curl": ["7.66.0-2"]}
"opkg.OpkgPackages": {"curl": ["7.66.0-2"]}
},
"commands": [
],
Expand Down
2 changes: 1 addition & 1 deletion tests/operations/opkg.packages/add_multiple_packages.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"update": false
},
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [
"opkg install curl wget"
Expand Down
2 changes: 1 addition & 1 deletion tests/operations/opkg.packages/add_one_package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"update": false
},
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [
"opkg install curl"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"args": ["curl=7.66.0-2"],
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [ ],
"exception": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"args": ["", "", ""],
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [],
"noop_description": "empty or invalid package list provided to opkg.packages",
Expand Down
2 changes: 1 addition & 1 deletion tests/operations/opkg.packages/null_package_list.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"args": [],
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [],
"noop_description": "empty or invalid package list provided to opkg.packages",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"update": false
},
"facts": {
"opkg.Packages": {"curl": ["7.66.0-2"]}
"opkg.OpkgPackages": {"curl": ["7.66.0-2"]}
},
"commands": [
"opkg remove curl"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"update": true
},
"facts": {
"opkg.Packages": {"curl": ["7.66.0-2"]}
"opkg.OpkgPackages": {"curl": ["7.66.0-2"]}
},
"commands": [
"opkg update > /dev/null 2>&1",
"opkg update",
"opkg remove curl"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"update": false
},
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [
],
Expand Down
4 changes: 2 additions & 2 deletions tests/operations/opkg.packages/update_then_add_one.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"args": ["curl"],
"kwargs": {"update": true},
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [
"opkg update > /dev/null 2>&1",
"opkg update",
"opkg install curl"
]
}
4 changes: 2 additions & 2 deletions tests/operations/opkg.update/first_update.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"args": [],
"facts": {
"opkg.Packages": {}
"opkg.OpkgPackages": {}
},
"commands": [
"opkg update > /dev/null 2>&1"
"opkg update"
]
}
10 changes: 0 additions & 10 deletions tests/operations/opkg.update/opkg_second_update_forced.json

This file was deleted.

9 changes: 0 additions & 9 deletions tests/operations/opkg.update/second_update.json

This file was deleted.

10 changes: 0 additions & 10 deletions tests/operations/opkg.update/second_update_with_force.json

This file was deleted.

1 change: 1 addition & 0 deletions tests/words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -442,3 +442,4 @@ yaml
yarn
zfill
zypper
usign

0 comments on commit a71caf9

Please sign in to comment.