Skip to content

Commit

Permalink
Do not overwrite sources.list.d items when handling sources changes. (#…
Browse files Browse the repository at this point in the history
…136)

This patch introduces a new boolean config variable, `manage-sources-list-d`, that defaults to `True`. When `True`, Landscape manages files in /etc/apt/sources.list.d alongside managing /etc/apt/sources.list when a repository profile is associated with the machine. When `False`, Landscape only manages /etc/apt/sources.list. This is to allow user-added PPAs/sources to remain untouched should the user prefer to have some manual control when using repository profiles.
  • Loading branch information
Perfect5th committed Mar 4, 2023
1 parent abb6416 commit 92121f4
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
6 changes: 6 additions & 0 deletions example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,9 @@ script_users = ALL
# The default is 512kB
# 2MB is allowed in this example
#script_output_limit=2048

# Whether files in /etc/apt/sources.list.d are removed when a repository
# profile is added to this machine.
#
# The default is True
#manage_sources_list_d = True
7 changes: 7 additions & 0 deletions landscape/client/deployment.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ def make_parser(self):
dest="stagger_launch", default=0.1, type=float,
help="Ratio, between 0 and 1, by which to scatter "
"various tasks of landscape.")
parser.add_option(
"--manage-sources-list-d",
action="store_true",
default=True,
help="Repository profiles manage the files in "
"/etc/apt/sources.list.d"
)

# Hidden options, used for load-testing to run in-process clones
parser.add_option("--clones", default=0, type=int, help=SUPPRESS_HELP)
Expand Down
14 changes: 11 additions & 3 deletions landscape/client/manager/aptsources.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ def _handle_repositories(self, message):
return self.call_with_operation_result(message, lambda: deferred)

def _handle_sources(self, ignored, sources):
"""Handle sources repositories."""
"""
Replaces `SOURCES_LIST` with a Landscape-managed version and moves the
original to a ".save" file.
Configurably does the same with files in `SOURCES_LIST_D`.
"""

saved_sources = "{}.save".format(self.SOURCES_LIST)
if sources:
fd, path = tempfile.mkstemp()
Expand All @@ -120,8 +126,10 @@ def _handle_sources(self, ignored, sources):
if os.path.isfile(saved_sources):
shutil.move(saved_sources, self.SOURCES_LIST)

for filename in glob.glob(os.path.join(self.SOURCES_LIST_D, "*.list")):
shutil.move(filename, "%s.save" % filename)
if self.registry.config.manage_sources_list_d:
filenames = glob.glob(os.path.join(self.SOURCES_LIST_D, "*.list"))
for filename in filenames:
shutil.move(filename, f"{filename}.save")

for source in sources:
filename = os.path.join(self.SOURCES_LIST_D,
Expand Down
36 changes: 34 additions & 2 deletions landscape/client/manager/tests/test_aptsources.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ def buggy_source_handler(*args):
"result-text": msg, "status": FAILED,
"operation-id": 1}])

def test_rename_sources_list_d(self):
def test_renames_sources_list_d(self):
"""
The sources files in sources.list.d are renamed to .save when a message
is received.
is received if config says to manage them, which is the default.
"""
with open(os.path.join(self.sourceslist.SOURCES_LIST_D, "file1.list"),
"w") as sources1:
Expand Down Expand Up @@ -241,6 +241,38 @@ def test_rename_sources_list_d(self):
os.path.join(self.sourceslist.SOURCES_LIST_D,
"file2.list.save")))

def test_does_not_rename_sources_list_d(self):
"""
The sources files in sources.list.d are not renamed to .save when a
message is received if config says not to manage them.
"""
with open(os.path.join(self.sourceslist.SOURCES_LIST_D, "file1.list"),
"w") as sources1:
sources1.write("ok\n")

with open(os.path.join(self.sourceslist.SOURCES_LIST_D,
"file2.list.save"), "w") as sources2:
sources2.write("ok\n")

self.manager.config.manage_sources_list_d = False
self.manager.dispatch_message(
{"type": "apt-sources-replace", "sources": [], "gpg-keys": [],
"operation-id": 1})

self.assertTrue(
os.path.exists(
os.path.join(self.sourceslist.SOURCES_LIST_D, "file1.list")))

self.assertFalse(
os.path.exists(
os.path.join(self.sourceslist.SOURCES_LIST_D,
"file1.list.save")))

self.assertTrue(
os.path.exists(
os.path.join(self.sourceslist.SOURCES_LIST_D,
"file2.list.save")))

def test_create_landscape_sources(self):
"""
For every sources listed in the sources field of the message,
Expand Down

0 comments on commit 92121f4

Please sign in to comment.