Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ A script to create and update mirrors of RPM repositories using `reposync`.

Runs on

* RHEL 8 (and compatible)
* RHEL 9 (and compatible)

- RHEL 8 (and compatible)
- RHEL 9 (and compatible)

## Installation

Expand Down Expand Up @@ -57,7 +56,6 @@ setfacl --recursive --modify user:mirror:rwx "$base_path"
setfacl --default --recursive --modify user:mirror:rwx "$base_path"
```


## How to Provide a RPM-based Repository on your Mirror Server

If you want to provide an RPM-based repository, it must be present in `/etc/yum.repos.d`. However, it does not need to be enabled, so we generally recommend disabling it (to prevent the mirror server itself from accidentally using it).
Expand All @@ -79,10 +77,10 @@ module_hotfixes = 1
In `/etc/mirror.yml`, set the location for the repo to be mirrored. This path should be unique to prevent multiple repos from overwriting each other. The path will then be created by the script.

```yaml
base_path: '/var/www/html/mirror'
base_path: "/var/www/html/mirror"
reposync_repos:
- repoid: 'mirror-rhel8-mariadb-10.6'
relative_target_path: 'MariaDB/mariadb-10.6/yum/rhel/8/x86_64'
- repoid: "mirror-rhel8-mariadb-10.6"
relative_target_path: "MariaDB/mariadb-10.6/yum/rhel/8/x86_64"
```

Determine whether or not it is necessary to run `createrepo`. If the mirrored repo is not identical to the upstream repo (e.g. due to `includepkgs` or `excludepkgs` directives), you need to run `createrepo`. If this is not the case, you should avoid running it, as it will destroy RHEL's module information.
Expand All @@ -107,12 +105,12 @@ restorecon -Fvr $BASE_PATH

`reposync_repos`: Optional, list. List of repositories to mirror using `reposync`.<br>Subkeys:

* `repoid`: Mandatory, string. Repo-ID. Can be found using `dnf repolist`.
* `relative_target_path`: Mandatory, string. Target path where the repo should be placed, relative to `base_path`.
* `createrepo`: Optional, boolean. If `createrepo` should be ran on the repo after mirroring or not. Only use this if the mirrored repo is not idential to the upstream repo (for example due to `includepkgs` or `excludepkgs` directives). Else, you should avoid running it, since it destroys RHEL's module information. Defaults to `false`.

- `repoid`: Mandatory, string. Repo-ID. Can be found using `dnf repolist`.
- `relative_target_path`: Mandatory, string. Target path where the repo should be placed, relative to `base_path`.
- `createrepo`: Optional, boolean. If `createrepo` should be ran on the repo after mirroring or not. Only use this if the mirrored repo is not idential to the upstream repo (for example due to `includepkgs` or `excludepkgs` directives). Else, you should avoid running it, since it destroys RHEL's module information. Defaults to `false`.
- `keep_old_rpms`: Optional, boolean. If set to `true`, the reposync command is executed without the `--delete` flag to keep older packages. Defaults to `false`.

## Exit Codes

* 0: success / config valid
* 1: failed to read config / config invalid
- 0: success / config valid
- 1: failed to read config / config invalid
Binary file added __pycache__/mirror-update_test.cpython-313.pyc
Binary file not shown.
9 changes: 1 addition & 8 deletions example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,4 @@ reposync_repos:
- repoid: 'rocky8-appstream'
relative_target_path: 'rocky/8/AppStream/x86_64/os/'
createrepo: true

github_repos:

- github_user: 'maxbube'
github_repo: 'mydumper'
relative_target_path: 'mydumper/el/8'
rpm_regex: 'mydumper-{latest_version}[-\d]*.el8.x86_64.rpm'
number_of_rpms_to_keep: 3
keep_old_rpms: false
10 changes: 9 additions & 1 deletion mirror-update
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,18 @@ class MirrorUpdate:
if not self.mkdir(target_path):
continue

cmd = "reposync --assumeyes --delete --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}'".format(
cmd_args = "--assumeyes --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}'".format(
REPOID=repo["repoid"],
TARGET_PATH=target_path,
)

if "keep_old_rpms" not in repo or repo["keep_old_rpms"] == False:
cmd_args = cmd_args + " --delete"

cmd = "reposync {CMD_ARGS}".format(
CMD_ARGS=cmd_args,
)

if not self.run_cmd(cmd):
continue

Expand Down
49 changes: 49 additions & 0 deletions mirror-update_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import unittest

class TestCommandBuilder(unittest.TestCase):
def test_add_delete_flag_if_not_explicitly_disabled(self):
target_path = "/test/"
repo = {
"repoid": "test"
}

cmd_args = "--assumeyes --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}'".format(
REPOID=repo["repoid"],
TARGET_PATH=target_path,
)

if "keep_old_rpms" not in repo or repo["keep_old_rpms"] == False:
cmd_args = cmd_args + " --delete"

cmd = "reposync {CMD_ARGS}".format(
CMD_ARGS=cmd_args,
)

self.assertEqual(cmd, "reposync --assumeyes --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}' --delete".format(
REPOID=repo["repoid"],
TARGET_PATH=target_path,
))

def test_ignore_delete_flag_if_disabled(self):
target_path = "/test/"
repo = {
"repoid": "test",
"keep_old_rpms": True
}

cmd_args = "--assumeyes --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}'".format(
REPOID=repo["repoid"],
TARGET_PATH=target_path,
)

if "keep_old_rpms" not in repo or repo["keep_old_rpms"] == False:
cmd_args = cmd_args + " --delete"

cmd = "reposync {CMD_ARGS}".format(
CMD_ARGS=cmd_args,
)

self.assertEqual(cmd, "reposync --assumeyes --download-metadata --download-path='{TARGET_PATH}' --downloadcomps --newest-only --norepopath --repoid='{REPOID}'".format(
REPOID=repo["repoid"],
TARGET_PATH=target_path,
))