Skip to content
Merged
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
Binary file modified .aptly-bin/aptly
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ __pycache__
/.aptly.conf
/.aptly
/.local
.work
82 changes: 49 additions & 33 deletions pyaptly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,31 @@ def __init__(self):
self.publishes = set()
self.publish_map = {}

def _extract_sources(self, data):
"""
Extract sources from data.

Data needs to be in following format:
Name: test-snap
Description: some description
Sources:
test-snap-base [snapshot]
"""
entered_sources = False
sources = []
for line in data.split("\n"):
# source line need to start with two spaces
if entered_sources and line[0:2] != ' ':
break

if entered_sources:
sources.append(line)

if line == "Sources:":
entered_sources = True

return sources

def read(self):
"""Reads all available system states."""
self.read_gpg()
Expand Down Expand Up @@ -554,45 +579,36 @@ def read_gpg(self):
def read_publish_map(self):
"""Create a publish map. publish -> snapshots"""
self.publish_map = {}
data, _ = call_output([
"aptly", "publish", "list"
])

# match example: main: test-snapshot [snapshot]
re_snap = re.compile(r"\s+[\w\d-]+\:\s([\w\d-]+)\s\[snapshot\]")
for publish in self.publishes:
self.publish_map[publish] = set()
re_snap = re.compile(
r"^\s*\*\s+%s/%s " %
tuple(publish.split(" "))
)
for line in data.split("\n"):
if re_snap.match(line):
for snapshot in self.snapshots:
if re.match(".*\[%s\]" % snapshot, line):
self.publish_map[publish].add(snapshot)

prefix, dist = publish.split(' ')
data, _ = call_output([
"aptly", "publish", "show", dist, prefix
])

sources = self._extract_sources(data)
matches = [re_snap.match(source) for source in sources]
snapshots = [match.group(1) for match in matches if match]
self.publish_map[publish] = set(snapshots)

lg.debug('Joined snapshots and publishes: %s', self.publish_map)

def read_snapshot_map(self):
"""Create a snapshot map. snapshot -> snapshots. This is also called
merge-tree."""
self.snapshot_map = {}
data, _ = call_output([
"aptly", "snapshot", "list"
])

re_snap = re.compile(r"^\s*\*\s+\[([\w\d-]+)\]")

for line in data.split("\n"):
match = re_snap.match(line)
if match:
snapshot_outer = match.group(1)
if snapshot_outer not in self.snapshot_map:
self.snapshot_map[snapshot_outer] = set()

sources_match = re.match(
".*Merged from sources:[\s']*(.*)'", line)
if sources_match:
sources = re.split(r"[ ,']+", sources_match.group(1))
self.snapshot_map[snapshot_outer].update(sources)
# match example: test-snapshot [snapshot]
re_snap = re.compile(r"\s+([\w\d-]+)\s\[snapshot\]")
for snapshot_outer in self.snapshots:
data, _ = call_output([
"aptly", "snapshot", "show", snapshot_outer
])
sources = self._extract_sources(data)
matches = [re_snap.match(source) for source in sources]
snapshots = [match.group(1) for match in matches if match]
self.snapshot_map[snapshot_outer] = set(snapshots)

lg.debug(
'Joined snapshots with self(snapshots): %s',
Expand Down Expand Up @@ -1480,7 +1496,7 @@ def cmd_snapshot_update(cfg, snapshot_name, snapshot_config):
intermediate2.provide('virtual', 'all-snapshots-rebuilt')

create_cmds = []
for snap in affected_snapshots:
for _ in affected_snapshots:

# Well.. there's normally just one, but since we need interface
# consistency, cmd_snapshot_create() returns a list. And since it
Expand Down
72 changes: 59 additions & 13 deletions pyaptly/aptly_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,14 @@ def test_snapshot_update_rotating():
do_snapshot_update_rotating(config)


def test_snapshot_update_twice_rotating():
def test_snapshot_update_threetimes_rotating():
"""Test if rotating snapshot update works."""
with test.clean_and_config(os.path.join(
_test_base,
b"snapshot-current.yml",
)) as (tyml, config):
do_snapshot_update_rotating(config)
with freezegun.freeze_time("2012-11-10 10:10:10"):
with freezegun.freeze_time("2012-10-11 10:10:10"):
args = [
'-c',
config,
Expand All @@ -294,28 +294,74 @@ def test_snapshot_update_twice_rotating():
'fake-current',
'fakerepo01-current-rotated-20121010T1010Z',
'fakerepo02-current-rotated-20121010T1010Z',
'fakerepo01-current-rotated-20121110T1010Z',
'fakerepo02-current-rotated-20121110T1010Z',
'fakerepo01-current-rotated-20121011T1010Z',
'fakerepo02-current-rotated-20121011T1010Z',
]
).issubset(state.snapshots)
expected = {
u'fake-current': set([
u'fakerepo01-current', u'fakerepo02-current'
]),
u'fake-current-rotated-20121010T1010Z': set([
u'fakerepo01-current-rotated-20121010T1010Z',
u'fakerepo02-current-rotated-20121010T1010Z'
]),
u'fake-current-rotated-20121011T1010Z': set([
u'fakerepo01-current-rotated-20121011T1010Z',
u'fakerepo02-current-rotated-20121011T1010Z',
]),
u'fakerepo01-current': set([]),
u'fakerepo01-current-rotated-20121010T1010Z': set([]),
u'fakerepo01-current-rotated-20121011T1010Z': set([]),
u'fakerepo02-current': set([]),
u'fakerepo02-current-rotated-20121010T1010Z': set([]),
u'fakerepo02-current-rotated-20121011T1010Z': set([])
}
assert state.snapshot_map == expected

with freezegun.freeze_time("2012-10-12 10:10:10"):
args = [
'-c',
config,
'snapshot',
'update',
]
main(args)
state = SystemStateReader()
state.read()
assert set(
[
'fake-current',
'fakerepo01-current-rotated-20121011T1010Z',
'fakerepo02-current-rotated-20121011T1010Z',
'fakerepo01-current-rotated-20121012T1010Z',
'fakerepo02-current-rotated-20121012T1010Z',
]
).issubset(state.snapshots)
expected = {
u'fake-current': set([
u'fakerepo01-current', u'fakerepo02-current'
]),
u'fake-current-rotated-20121010T1010Z': set([
u'fakerepo01-current',
u'fakerepo02-current'
u'fakerepo01-current-rotated-20121010T1010Z',
u'fakerepo02-current-rotated-20121010T1010Z'
]),
u'fake-current-rotated-20121011T1010Z': set([
u'fakerepo01-current-rotated-20121011T1010Z',
u'fakerepo02-current-rotated-20121011T1010Z',
]),
u'fake-current-rotated-20121110T1010Z': set([
u'fakerepo01-current',
u'fakerepo02-current'
u'fake-current-rotated-20121012T1010Z': set([
u'fakerepo01-current-rotated-20121012T1010Z',
u'fakerepo02-current-rotated-20121012T1010Z',
]),
u'fakerepo01-current': set([]),
u'fakerepo01-current-rotated-20121010T1010Z': set([]),
u'fakerepo01-current-rotated-20121110T1010Z': set([]),
u'fakerepo01-current-rotated-20121011T1010Z': set([]),
u'fakerepo01-current-rotated-20121012T1010Z': set([]),
u'fakerepo02-current': set([]),
u'fakerepo02-current-rotated-20121010T1010Z': set([]),
u'fakerepo02-current-rotated-20121110T1010Z': set([])
u'fakerepo02-current-rotated-20121011T1010Z': set([]),
u'fakerepo02-current-rotated-20121012T1010Z': set([]),
}
assert state.snapshot_map == expected

Expand Down Expand Up @@ -359,8 +405,8 @@ def do_snapshot_update_rotating(config):
u'fakerepo01-current', u'fakerepo02-current'
]),
u'fake-current-rotated-20121010T1010Z': set([
u'fakerepo01-current',
u'fakerepo02-current'
u'fakerepo01-current-rotated-20121010T1010Z',
u'fakerepo02-current-rotated-20121010T1010Z'
]),
u'fakerepo01-current': set([]),
u'fakerepo01-current-rotated-20121010T1010Z': set([]),
Expand Down