aquafire / harbor_paginate.py

Last active 6 months ago

Like 0

aquafire revised this gist 10 months ago · b410cc2

1 file changed, 39 insertions, 23 deletions

harbor_paginate.py
@@ -53,8 +53,8 @@ from itertools import islice
53 53
54 54
55 55 def chunks(lst, n):
56 - iterator = iter(lst)
57 - return list(iter(lambda: list(islice(iterator, n)), []))
56 + for i in range(0, len(lst), n):
57 + yield lst[i : i + n] # Генератор вместо списка
58 58
59 59
60 60 async def get_artifacts(
@@ -80,6 +80,14 @@ async def get_artifacts(
80 80 page_size=10,
81 81 limit=10,
82 82 )
83 +
84 + # нет артефактов
85 + if not artifacts:
86 + # если страница была неполной, то возвращаем результат
87 + if rim_page_number == page_number:
88 + return artifacts_page_buffer.get_filled()
89 + break
90 +
83 91 for artifact in artifacts:
84 92 # массив тэгов
85 93 tags = []
@@ -93,26 +101,28 @@ async def get_artifacts(
93 101 )
94 102 # засовываем в список
95 103 tags.append(artifact_name)
96 - print(f"Tags {tags}")
97 - print(f"Buffer: {artifacts_page_buffer.get_filled()}")
98 - print(f"RIM page number: {rim_page_number}")
99 - # режем на порции
104 + # print(f"Tags {tags}")
105 + # print(f"Buffer: {artifacts_page_buffer.get_filled()}")
106 + # print(
107 + # f"RIM page number: {rim_page_number}, length: {len(artifacts_page_buffer.get_filled())}"
108 + # )
100 109 for portion in chunks(tags, page_size):
101 - # если достигли нужной страницы или получили пустышку от Harbor
102 - if rim_page_number == page_number:
103 - # возвращаем страницы
104 - return artifacts_page_buffer.get_filled()
105 - # буфер страницы заполняется
110 + # загружаем порцию в буфер
106 111 artifacts_page_buffer.load(portion)
107 - # если в накопителе тэгов не исчерпались элементы
108 - if artifacts_page_buffer.filled_size() == page_size:
109 - # увеличиваем счетчик страниц RIM
112 + # Проверяем после каждой порции
113 + if (
114 + artifacts_page_buffer.filled_size() >= page_size
115 + and rim_page_number == page_number
116 + ):
117 + return artifacts_page_buffer.get_filled()
118 + # Считаем полные страницы RIM
119 + if artifacts_page_buffer.filled_size() >= page_size:
120 + # увеличиваем счетчик страниц в RIM
110 121 rim_page_number += 1
111 - # исчерпали все артефакты
112 - if len(artifacts) == 0:
113 - return artifacts_page_buffer.get_filled()
114 122 # увеличиваем счетчик страниц Harbor
115 123 harbor_page_number += 1
124 + # не страниц, или указана несуществующая страница
125 + return []
116 126
117 127
118 128 async def main():
@@ -135,12 +145,18 @@ async def main():
135 145 rbuf.load([1, 2, 3, 4])
136 146 print(rbuf.get_filled())
137 147 # tests
138 - project_name = "sbis-hlha"
139 - repository_name = "charts/sbis-docker-dispatcher"
140 - artifacts = await get_artifacts(client, project_name, repository_name, 1, 21)
141 - print(artifacts)
142 - print(len(artifacts))
148 + # project_name = "sbis-hlha"
149 + # repository_name = "charts/sbis-docker-dispatcher"
150 + project_name = "corp-base"
151 + repository_name = "platform/centos"
152 + artifacts1 = set(await get_artifacts(client, project_name, repository_name, 1, 6))
153 + print(artifacts1)
154 + print(len(artifacts1))
155 + artifacts2 = set(await get_artifacts(client, project_name, repository_name, 2, 6))
156 + print(artifacts2)
157 + print(len(artifacts2))
158 + print(artifacts1 - artifacts2)
143 159
144 160
145 161 if __name__ == "__main__":
146 - asyncio.run(main())
162 + asyncio.run(main())

aquafire revised this gist 10 months ago · 408bdab

1 file changed, 146 insertions

harbor_paginate.py (file created)
@@ -0,0 +1,146 @@
1 + import asyncio
2 + from typing import Any, List
3 +
4 + from harborapi import HarborAsyncClient
5 +
6 +
7 + class AccumulatingBuffer:
8 + def __init__(self, capacity: int):
9 + if capacity <= 0:
10 + raise ValueError("Capacity must be positive")
11 + self.capacity = capacity
12 + self.buf = [None] * capacity
13 + self.count = 0 # Фактически заполненные слоты
14 +
15 + def load(self, elements: List[Any]) -> None:
16 + """Добавляет элементы: в свободное место - в конец, при полном - перезапись с начала"""
17 + L = len(elements)
18 + if L > self.capacity:
19 + raise IndexError(f"Elements ({L}) exceed capacity ({self.capacity})")
20 +
21 + if self.count + L <= self.capacity:
22 + # Есть свободное место - добавляем в конец
23 + for i, elem in enumerate(elements):
24 + self.buf[self.count + i] = elem
25 + self.count += L
26 + # Затираем оставшееся место
27 + for i in range(self.count, self.capacity):
28 + self.buf[i] = None
29 + else:
30 + # Буфер полон - перезаписываем с начала
31 + for i, elem in enumerate(elements):
32 + self.buf[i] = elem
33 + self.count = L
34 + # Затираем остаток
35 + for i in range(L, self.capacity):
36 + self.buf[i] = None
37 +
38 + def get_filled(self) -> List[Any]:
39 + """Возвращает только непустые элементы"""
40 + return [x for x in self.buf[: self.count] if x is not None]
41 +
42 + def size(self) -> int:
43 + return self.count
44 +
45 + def filled_size(self) -> int:
46 + return len(self.get_filled())
47 +
48 + def free_space(self) -> int:
49 + return self.capacity - self.count
50 +
51 +
52 + from itertools import islice
53 +
54 +
55 + def chunks(lst, n):
56 + iterator = iter(lst)
57 + return list(iter(lambda: list(islice(iterator, n)), []))
58 +
59 +
60 + async def get_artifacts(
61 + client: HarborAsyncClient,
62 + project_name: str,
63 + repository_name: str,
64 + page_number: int,
65 + page_size: int,
66 + ):
67 + # номер страницы с артефактами в Harbor
68 + harbor_page_number = 1
69 + # номер страницы с артефактами в RIM
70 + rim_page_number = 1
71 + # выделяем буфер под "страницу" артефактов
72 + artifacts_page_buffer = AccumulatingBuffer(page_size)
73 + # начинаем считываение
74 + while True:
75 + # считываем из Harbor артефакты и загружаем их в буфер
76 + artifacts = await client.get_artifacts(
77 + project_name=project_name,
78 + repository_name=repository_name,
79 + page=harbor_page_number,
80 + page_size=10,
81 + limit=10,
82 + )
83 + for artifact in artifacts:
84 + # массив тэгов
85 + tags = []
86 + # если есть тэги
87 + if artifact.tags:
88 + # перебираем все ссылки на тэги
89 + for tag_reference in artifact.tags:
90 + # формируем имя
91 + artifact_name = (
92 + f"{project_name}/{repository_name}:{tag_reference.name}"
93 + )
94 + # засовываем в список
95 + tags.append(artifact_name)
96 + print(f"Tags {tags}")
97 + print(f"Buffer: {artifacts_page_buffer.get_filled()}")
98 + print(f"RIM page number: {rim_page_number}")
99 + # режем на порции
100 + for portion in chunks(tags, page_size):
101 + # если достигли нужной страницы или получили пустышку от Harbor
102 + if rim_page_number == page_number:
103 + # возвращаем страницы
104 + return artifacts_page_buffer.get_filled()
105 + # буфер страницы заполняется
106 + artifacts_page_buffer.load(portion)
107 + # если в накопителе тэгов не исчерпались элементы
108 + if artifacts_page_buffer.filled_size() == page_size:
109 + # увеличиваем счетчик страниц RIM
110 + rim_page_number += 1
111 + # исчерпали все артефакты
112 + if len(artifacts) == 0:
113 + return artifacts_page_buffer.get_filled()
114 + # увеличиваем счетчик страниц Harbor
115 + harbor_page_number += 1
116 +
117 +
118 + async def main():
119 + registry_url = "-"
120 + registry_login = "-"
121 + registry_password = "-"
122 + client = HarborAsyncClient(
123 + url=registry_url + "/api/v2.0",
124 + username=registry_login,
125 + secret=registry_password,
126 + # ограничение по количеству количества записей о соединениях хранимых клиентом
127 + max_logs=0,
128 + verify=False, # TODO: remove them ?
129 + )
130 + rbuf = AccumulatingBuffer(10)
131 + rbuf.load([])
132 + print(rbuf.get_filled())
133 + rbuf.load([1, 2, 3, 4, 5, 6, 7, 8, 9])
134 + print(rbuf.get_filled())
135 + rbuf.load([1, 2, 3, 4])
136 + print(rbuf.get_filled())
137 + # tests
138 + project_name = "sbis-hlha"
139 + repository_name = "charts/sbis-docker-dispatcher"
140 + artifacts = await get_artifacts(client, project_name, repository_name, 1, 21)
141 + print(artifacts)
142 + print(len(artifacts))
143 +
144 +
145 + if __name__ == "__main__":
146 + asyncio.run(main())