Skip to content

Commit

Permalink
[antlir2][rpms] add remove feature
Browse files Browse the repository at this point in the history
Summary:
To prevent endlessly growing lists of "remove this rpm if it happens to be
installed" lists, create a `feature.rpms_remove` variant that fails if the rpm
to be removed is not actually installed.

Test Plan:
```
❯ hg diff
 diff --git a/fbcode/antlir/antlir2/test_images/rpms/TARGETS b/fbcode/antlir/antlir2/test_images/rpms/TARGETS
 --- a/fbcode/antlir/antlir2/test_images/rpms/TARGETS
+++ b/fbcode/antlir/antlir2/test_images/rpms/TARGETS
@@ -385,3 +385,13 @@
     ],
     flavor = "//antlir/antlir2/test_images:test-image-flavor",
 )
+
+test_rpms(
+    name = "remove-will-fail",
+    expected = expected_t(),
+    features = [
+        feature.rpms_remove(rpms = [
+            "foo",
+        ]),
+    ],
+)

[email protected] in fbsource
❯ buck test fbcode//antlir/antlir2/test_images/rpms:remove-will-fail
❯ buck2 test fbcode//antlir/antlir2/test_images/rpms:remove-will-fail
File changed: fbcode//antlir/antlir2/bzl/feature/defs.bzl
Buck UI: https://www.internalfb.com/buck2/72d72d6b-b94d-4d2d-ae15-c45bf7da2807
Test UI: https://www.internalfb.com/intern/testinfra/testrun/4222124857434732
Network: Up: 0B  Down: 0B  (reSessionID-d6083da1-7614-41a5-b1f7-fe3b325809fa)
...
2023-11-01T20:08:45.422851Z TRACE plan:rpms[plan]: rpm: dnf-driver: PackageNotInstalled("foo")
2023-11-01T20:08:45.422964Z TRACE plan:rpms[plan]: rpm: dnf-driver: TransactionResolved { install: {}, remove: {} }
2023-11-01T20:08:45.450023Z ERROR plan:rpms[plan]: rpm: error=there were one or more transaction errors: ["Package to be removed 'foo' was not installed"]
2023-11-01T20:08:46.815411Z ERROR map: antlir2::cmd::map: error="isolated command failed: exit status: 255"
stderr:
Uncategorized(
    "isolated command failed: exit status: 255",
)
"isolated command failed: exit status: 255"
Buck UI: https://www.internalfb.com/buck2/5614de3f-3d06-4569-ba81-09fae9ec91c0
Test UI: https://www.internalfb.com/intern/testinfra/testrun/12103424007408552
Network: Up: 24MiB  Down: 793KiB  (reSessionID-4286c14b-d4cf-4d6d-acf8-ce0127e98feb)
Jobs completed: 80796. Time elapsed: 48.5s.
Cache hits: 78%. Commands: 379 (cached: 294, remote: 0, local: 85). Fallback: 6/85
for action key `(target: `fbcode//antlir/antlir2/test_images/rpms:remove-will-fail--layer (ovr_config//platform/linux:x86_64-fbcode-platform010-clang15-CUDA-projects-cuda-12-cuda-12#e4818cc9359b9595)`, id: `6`)`

Caused by:
    Failed to build 'fbcode//antlir/antlir2/test_images/rpms:remove-will-fail--layer (ovr_config//platform/linux:x86_64-fbcode-platform010-clang15-CUDA-projects-cuda-12-cuda-12#e4818cc9359b9595)'
1 BUILDS FAILED
Tests finished: Pass 0. Fail 0. Fatal 0. Skip 0. Build failure 1
NO TESTS RAN
```

Reviewed By: sergeyfd

Differential Revision: D50898640

fbshipit-source-id: 739b644757d9152ba274fb8ff47c295b242df464
  • Loading branch information
vmagro authored and facebook-github-bot committed Nov 2, 2023
1 parent e76228a commit 461d370
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
3 changes: 2 additions & 1 deletion antlir/antlir2/bzl/feature/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ load("//antlir/antlir2/bzl/feature:metakv.bzl", "metakv_remove", "metakv_store")
load("//antlir/antlir2/bzl/feature:mount.bzl", "host_mount", "layer_mount")
load("//antlir/antlir2/bzl/feature:remove.bzl", "remove")
load("//antlir/antlir2/bzl/feature:requires.bzl", "requires")
load("//antlir/antlir2/bzl/feature:rpms.bzl", "rpms_install", "rpms_remove_if_exists", "rpms_upgrade")
load("//antlir/antlir2/bzl/feature:rpms.bzl", "rpms_install", "rpms_remove", "rpms_remove_if_exists", "rpms_upgrade")
load("//antlir/antlir2/bzl/feature:symlink.bzl", "ensure_dir_symlink", "ensure_file_symlink")
load("//antlir/antlir2/bzl/feature:tarball.bzl", "tarball")
load("//antlir/antlir2/bzl/feature:usergroup.bzl", "group_add", "standard_user", "user_add", "usermod")
Expand All @@ -38,6 +38,7 @@ feature = struct(
remove = remove,
requires = requires,
rpms_install = rpms_install,
rpms_remove = rpms_remove,
rpms_remove_if_exists = rpms_remove_if_exists,
rpms_upgrade = rpms_upgrade,
ensure_file_symlink = ensure_file_symlink,
Expand Down
30 changes: 29 additions & 1 deletion antlir/antlir2/bzl/feature/rpms.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,35 @@ def rpms_remove_if_exists(*, rpms: list[str | Select] | Select) -> ParseTimeFeat
],
)

action_enum = enum("install", "remove_if_exists", "upgrade")
def rpms_remove(*, rpms: list[str | Select] | Select) -> ParseTimeFeature:
"""
Remove RPMs if they are installed, fail if they are not
Elements in `rpms` can be any rpm specifier (name, NEVR, etc). If the rpm is
not installed, this feature will fail.
Note that dependencies of these rpms can also be removed, but only if no
explicitly-installed RPM depends on them (in this case, the goal cannot be
solved and the image build will fail unless you remove those rpms as well).
"""
return ParseTimeFeature(
feature_type = "rpm",
plugin = antlir2_dep("features:rpm"),
kwargs = {
"action": "remove",
"subjects": rpms,
},
analyze_uses_context = True,
compatible_with = [
"//antlir/antlir2/os/package_manager:dnf",
],
)

action_enum = enum(
"install",
"remove",
"remove_if_exists",
"upgrade",
)

rpm_source_record = record(
subject = field([str, None], default = None),
Expand Down
7 changes: 7 additions & 0 deletions antlir/antlir2/dnf/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,13 @@ def resolve(out, spec, base, local_rpms, explicitly_installed_package_names):
except dnf.exceptions.PackageNotFoundError as e:
with out as o:
json.dump({"package_not_found": e.pkg_spec}, o)
elif action == "remove":
# cannot remove by file path, so let's do this to be extra safe
try:
base.remove(rpm["subject"])
except dnf.exceptions.PackagesNotInstalledError:
with out as o:
json.dump({"package_not_installed": rpm["subject"]}, o)
elif action == "remove_if_exists":
# cannot remove by file path, so let's do this to be extra safe
try:
Expand Down
5 changes: 5 additions & 0 deletions antlir/antlir2/features/rpm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ pub type Feature = Rpm;
pub enum Action {
Install,
Upgrade,
Remove,
RemoveIfExists,
}

Expand Down Expand Up @@ -287,6 +288,7 @@ enum DriverEvent {
},
ScriptletOutput(String),
PackageNotFound(String),
PackageNotInstalled(String),
}

fn run_dnf_driver(
Expand Down Expand Up @@ -373,6 +375,9 @@ fn run_dnf_driver(
DriverEvent::PackageNotFound(package) => {
Some(Cow::Owned(format!("No such package found '{package}'")))
}
DriverEvent::PackageNotInstalled(package) => Some(Cow::Owned(format!(
"Package to be removed '{package}' was not installed"
))),
_ => None,
})
.collect();
Expand Down

0 comments on commit 461d370

Please sign in to comment.