assemblyline-core 4.5.1.dev202__tar.gz → 4.5.1.dev204__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of assemblyline-core might be problematic. Click here for more details.
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/PKG-INFO +1 -1
- assemblyline-core-4.5.1.dev204/assemblyline_core/VERSION +1 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/scaler_server.py +8 -1
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/updater/helper.py +114 -72
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core.egg-info/PKG-INFO +1 -1
- assemblyline-core-4.5.1.dev202/assemblyline_core/VERSION +0 -1
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/LICENCE.md +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/README.md +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/alerter/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/alerter/processing.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/alerter/run_alerter.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/archiver/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/archiver/run_archiver.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/badlist_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/__main__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/dispatcher.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/schedules.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/dispatching/timeout.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/expiry/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/expiry/run_expiry.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/ingester/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/ingester/__main__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/ingester/constants.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/ingester/ingester.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/es_metrics.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/heartbeat_formatter.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/helper.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/metrics_server.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/run_heartbeat_manager.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/run_metrics_aggregator.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/metrics/run_statistics_aggregator.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/plumber/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/plumber/run_plumber.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/creator/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/creator/run.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/creator/run_worker.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/loader/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/loader/run.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/loader/run_worker.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/replay.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/safelist_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/collection.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/controllers/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/controllers/docker_ctl.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/controllers/interface.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/controllers/kubernetes_ctl.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/scaler/run_scaler.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/server_base.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/signature_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/submission_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/tasking_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/updater/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/updater/run_updater.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/crawler.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/department_map.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/safelist.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/stream_map.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/worker.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/workflow/__init__.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/workflow/run_workflow.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core.egg-info/SOURCES.txt +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core.egg-info/dependency_links.txt +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core.egg-info/requires.txt +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core.egg-info/top_level.txt +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/setup.cfg +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/setup.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_alerter.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_badlist_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_dispatcher.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_expiry.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_plumber.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_replay.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_safelist_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_scaler.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_scheduler.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_signature_client.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_simulation.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_vacuum.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_worker_ingest.py +0 -0
- {assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_worker_submit.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.5.1.dev204
|
|
@@ -37,6 +37,7 @@ from assemblyline.common.forge import get_classification, get_service_queue, get
|
|
|
37
37
|
from assemblyline.common.constants import SCALER_TIMEOUT_QUEUE, SERVICE_STATE_HASH, ServiceStatus
|
|
38
38
|
from assemblyline.common.version import FRAMEWORK_VERSION, SYSTEM_VERSION
|
|
39
39
|
from assemblyline.common.isotime import now_as_iso
|
|
40
|
+
from assemblyline_core.updater.helper import get_registry_config
|
|
40
41
|
from assemblyline_core.scaler.controllers import KubernetesController
|
|
41
42
|
from assemblyline_core.scaler.controllers.interface import ContainerEvent, ServiceControlError
|
|
42
43
|
from assemblyline_core.server_base import ServiceStage, ThreadedCoreBase
|
|
@@ -518,6 +519,12 @@ class ScalerServer(ThreadedCoreBase):
|
|
|
518
519
|
for var in default_settings.environment:
|
|
519
520
|
if var.name not in set_keys:
|
|
520
521
|
docker_config.environment.append(var)
|
|
522
|
+
|
|
523
|
+
# Set authentication to registry to pull the image
|
|
524
|
+
auth_config = get_registry_config(docker_config, self.config)
|
|
525
|
+
docker_config.registry_username = auth_config['username']
|
|
526
|
+
docker_config.registry_password = auth_config['password']
|
|
527
|
+
|
|
521
528
|
return docker_config
|
|
522
529
|
|
|
523
530
|
# noinspection PyBroadException
|
|
@@ -537,7 +544,7 @@ class ScalerServer(ThreadedCoreBase):
|
|
|
537
544
|
if not service.version.startswith(system_spec):
|
|
538
545
|
# If FW and SYS version don't prefix in the service version, we can't guarantee the
|
|
539
546
|
# service is compatible. Disable and treat it as incompatible due to service version.
|
|
540
|
-
self.log.warning("Disabling service with incompatible version. "
|
|
547
|
+
self.log.warning(f"Disabling {service.name} with incompatible version. "
|
|
541
548
|
f"[{service.version} != '{system_spec}.X.{service.update_channel}Y'].")
|
|
542
549
|
disable_incompatible_service()
|
|
543
550
|
elif service.update_config and service.update_config.wait_for_update and not service.update_config.sources:
|
|
@@ -5,13 +5,15 @@ import string
|
|
|
5
5
|
import time
|
|
6
6
|
|
|
7
7
|
from assemblyline.common.version import FRAMEWORK_VERSION, SYSTEM_VERSION
|
|
8
|
-
from assemblyline.odm.models.config import Config as SystemConfig
|
|
9
|
-
from assemblyline.odm.models.service import Service as ServiceConfig
|
|
8
|
+
from assemblyline.odm.models.config import Config as SystemConfig, ServiceRegistry
|
|
9
|
+
from assemblyline.odm.models.service import Service as ServiceConfig, DockerConfig
|
|
10
10
|
|
|
11
11
|
from base64 import b64encode
|
|
12
12
|
from collections import defaultdict
|
|
13
13
|
from logging import Logger
|
|
14
|
+
from typing import Dict, List
|
|
14
15
|
from packaging.version import parse, Version
|
|
16
|
+
from urllib.parse import urlencode
|
|
15
17
|
|
|
16
18
|
DEFAULT_DOCKER_REGISTRY = "hub.docker.com"
|
|
17
19
|
|
|
@@ -129,9 +131,36 @@ REGISTRY_TYPE_MAPPING = {
|
|
|
129
131
|
'harbor': HarborRegistry()
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
def get_registry_config(docker_config: DockerConfig, system_config: SystemConfig) -> Dict[str, str]:
|
|
135
|
+
server = docker_config.image.split("/", 1)[0]
|
|
136
|
+
|
|
137
|
+
# Prioritize authentication given as a system configuration
|
|
138
|
+
registries: List[ServiceRegistry] = system_config.services.registries or []
|
|
139
|
+
for registry in registries:
|
|
140
|
+
if server.startswith(registry.name):
|
|
141
|
+
# Return authentication credentials and the type of registry
|
|
142
|
+
return dict(username=registry.username, password=registry.password, type=registry.type)
|
|
143
|
+
|
|
144
|
+
# Otherwise return what's configured for the service
|
|
145
|
+
return dict(username=docker_config.registry_username, password=docker_config.registry_password,
|
|
146
|
+
type=docker_config.registry_type)
|
|
147
|
+
|
|
148
|
+
def get_latest_tag_for_service(service_config: ServiceConfig, system_config: SystemConfig, logger: Logger,
|
|
149
|
+
prefix: str = ""):
|
|
150
|
+
"""
|
|
151
|
+
Retrieves the latest compatible tag for a given service from its respective Docker registry.
|
|
152
|
+
This function processes the image name to determine the correct server, authenticates
|
|
153
|
+
with the registry, and then fetches the latest tag that matches the service's framework
|
|
154
|
+
and system version constraints. It handles different registry configurations including
|
|
155
|
+
private and public ones.
|
|
156
|
+
Args:
|
|
157
|
+
service_config (ServiceConfig): The configuration object for the service which includes Docker configuration.
|
|
158
|
+
system_config (SystemConfig): System-wide configuration which includes service updates and registry configurations.
|
|
159
|
+
logger (Logger): Logger object for logging messages.
|
|
160
|
+
prefix (str, optional): A prefix string to prepend to log messages for clarity in logs.
|
|
161
|
+
Returns:
|
|
162
|
+
tuple: Returns a tuple of the final image name, the latest tag, and authentication config used for the Docker registry.
|
|
163
|
+
"""
|
|
135
164
|
def process_image(image):
|
|
136
165
|
# Find which server to search in
|
|
137
166
|
server = image.split("/")[0]
|
|
@@ -151,10 +180,9 @@ def get_latest_tag_for_service(
|
|
|
151
180
|
|
|
152
181
|
# Split repo name without the tag
|
|
153
182
|
image_name = image_name.rsplit(":", 1)[0]
|
|
154
|
-
|
|
155
183
|
return server, image_name
|
|
156
184
|
|
|
157
|
-
# Extract
|
|
185
|
+
# Extract and process service information
|
|
158
186
|
service_name = service_config.name
|
|
159
187
|
image = service_config.docker_config.image
|
|
160
188
|
update_channel = service_config.update_channel
|
|
@@ -167,36 +195,23 @@ def get_latest_tag_for_service(
|
|
|
167
195
|
|
|
168
196
|
# Get authentication
|
|
169
197
|
auth = None
|
|
170
|
-
auth_config = None
|
|
171
198
|
server, image_name = process_image(searchable_image)
|
|
172
199
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
service_config.docker_config.registry_username = registry['username']
|
|
179
|
-
service_config.docker_config.registry_password = registry['password']
|
|
180
|
-
service_config.docker_config.registry_type = registry['type']
|
|
181
|
-
break
|
|
182
|
-
|
|
183
|
-
if service_config.docker_config.registry_username and service_config.docker_config.registry_password:
|
|
184
|
-
# We're authenticating using Basic Auth
|
|
185
|
-
auth_config = {
|
|
186
|
-
'username': service_config.docker_config.registry_username,
|
|
187
|
-
'password': service_config.docker_config.registry_password
|
|
188
|
-
}
|
|
189
|
-
upass = f"{service_config.docker_config.registry_username}:{service_config.docker_config.registry_password}"
|
|
200
|
+
# Generate 'Authenication' header value for pulling tag list from registry
|
|
201
|
+
auth_config = get_registry_config(service_config.docker_config, system_config)
|
|
202
|
+
registry_type = auth_config.pop('type')
|
|
203
|
+
if auth_config['username'] and auth_config['password']:
|
|
204
|
+
upass = f"{auth_config['username']}:{auth_config['password']}"
|
|
190
205
|
auth = f"Basic {b64encode(upass.encode()).decode()}"
|
|
191
|
-
elif
|
|
206
|
+
elif auth_config['password']:
|
|
192
207
|
# We're assuming that if only a password is given, then this is a token
|
|
193
|
-
auth = f"Bearer {
|
|
208
|
+
auth = f"Bearer {auth_config['password']}"
|
|
194
209
|
|
|
195
210
|
if server.endswith(".azurecr.io"):
|
|
196
211
|
# This is an Azure Container Registry based on the server name
|
|
197
212
|
registry = AzureContainerRegistry()
|
|
198
213
|
else:
|
|
199
|
-
registry = REGISTRY_TYPE_MAPPING[
|
|
214
|
+
registry = REGISTRY_TYPE_MAPPING[registry_type]
|
|
200
215
|
token_server = None
|
|
201
216
|
proxies = None
|
|
202
217
|
for reg_conf in system_config.core.updater.registry_configs:
|
|
@@ -206,31 +221,28 @@ def get_latest_tag_for_service(
|
|
|
206
221
|
break
|
|
207
222
|
|
|
208
223
|
if server == DEFAULT_DOCKER_REGISTRY:
|
|
209
|
-
tags = _get_dockerhub_tags(image_name, update_channel, proxies)
|
|
224
|
+
tags = _get_dockerhub_tags(image_name, update_channel, prefix, proxies, logger=logger)
|
|
210
225
|
else:
|
|
211
226
|
tags = registry._get_proprietary_registry_tags(server, image_name, auth,
|
|
212
227
|
not system_config.services.allow_insecure_registry,
|
|
213
228
|
proxies, token_server)
|
|
214
|
-
tag_name = None
|
|
215
229
|
|
|
216
230
|
# Pre-filter tags to only consider 'compatible' tags relative to the running system
|
|
217
|
-
tags = [
|
|
218
|
-
if re.match(f"({FRAMEWORK_VERSION})\.({SYSTEM_VERSION})\.\\d+\.({update_channel})\\d+",
|
|
219
|
-
|
|
231
|
+
tags = [tag for tag in tags
|
|
232
|
+
if re.match(f"({FRAMEWORK_VERSION})\.({SYSTEM_VERSION})\.\\d+\.({update_channel})\\d+", tag)]
|
|
220
233
|
if not tags:
|
|
221
|
-
logger.warning(f"{prefix}Cannot fetch latest tag for service {service_name} - {image_name}"
|
|
234
|
+
logger.warning(f"{prefix} Cannot fetch latest tag for service {service_name} - {image_name}" \
|
|
222
235
|
f" => [server: {server}, repo_name: {image_name}, channel: {update_channel}]")
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
logger.info(f"{prefix}Latest {service_name} tag on {update_channel.upper()} channel is: {tag_name}")
|
|
236
|
+
tag_name = None
|
|
237
|
+
for tag in tags:
|
|
238
|
+
t_version = Version(tag.replace(update_channel, ""))
|
|
239
|
+
# Tag name gets assigned to the first viable option then relies on comparison to get the latest
|
|
240
|
+
if not tag_name:
|
|
241
|
+
tag_name = tag
|
|
242
|
+
elif t_version.major == FRAMEWORK_VERSION and t_version.minor == SYSTEM_VERSION and \
|
|
243
|
+
t_version > parse(tag_name.replace(update_channel, "")):
|
|
244
|
+
tag_name = tag
|
|
245
|
+
logger.info(f"{prefix}Latest {service_name} tag on {update_channel.upper()} channel is: {tag_name}")
|
|
234
246
|
|
|
235
247
|
# Fix service image for use in Kubernetes
|
|
236
248
|
image_variables = defaultdict(str)
|
|
@@ -244,43 +256,73 @@ def get_latest_tag_for_service(
|
|
|
244
256
|
|
|
245
257
|
return image_name, tag_name, auth_config
|
|
246
258
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
259
|
+
def _get_dockerhub_tags(image_name, update_channel, prefix, proxies=None, docker_registry=DEFAULT_DOCKER_REGISTRY,
|
|
260
|
+
logger: Logger=None):
|
|
261
|
+
"""
|
|
262
|
+
Retrieve DockerHub tags for a specific image and update channel.
|
|
263
|
+
Args:
|
|
264
|
+
image_name (str): Full name of the image (including namespace).
|
|
265
|
+
update_channel (str): Specific channel to filter tags (e.g., stable, beta).
|
|
266
|
+
proxies (dict, optional): Proxy configuration.
|
|
267
|
+
docker_registry (str, optional): Docker registry URL. Defaults to DEFAULT_DOCKER_REGISTRY.
|
|
268
|
+
Returns:
|
|
269
|
+
list: A list of tag names that match the given criteria, or None if an error occurs.
|
|
270
|
+
"""
|
|
252
271
|
namespace, repository = image_name.split('/', 1)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
272
|
+
base_url = f"https://{docker_registry}/v2/namespaces/{namespace}/repositories/{repository}/tags"
|
|
273
|
+
query_params = {
|
|
274
|
+
'page_size': 50,
|
|
275
|
+
'page': 1,
|
|
276
|
+
'name': update_channel,
|
|
277
|
+
'ordering': 'last_updated'
|
|
278
|
+
}
|
|
279
|
+
url = f"{base_url}?{urlencode(query_params)}"
|
|
256
280
|
while True:
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
281
|
+
try:
|
|
282
|
+
response = requests.get(url, proxies=proxies)
|
|
283
|
+
response.raise_for_status() # Raises an HTTPError for bad responses
|
|
284
|
+
response_data = response.json()
|
|
285
|
+
tags = []
|
|
260
286
|
if namespace == "cccs":
|
|
261
287
|
# The tags are coming from a repository managed by the Assemblyline team
|
|
262
|
-
for
|
|
263
|
-
tag_name =
|
|
264
|
-
if tag_name == f"{FRAMEWORK_VERSION}.{SYSTEM_VERSION}.{update_channel}":
|
|
288
|
+
for tag_info in response_data['results']:
|
|
289
|
+
tag_name = tag_info.get('name')
|
|
290
|
+
if tag_name and tag_name == f"{FRAMEWORK_VERSION}.{SYSTEM_VERSION}.{update_channel}":
|
|
265
291
|
# Ignore tag aliases containing the update_channel
|
|
266
292
|
continue
|
|
267
|
-
|
|
268
|
-
if tag_name.startswith(f"{FRAMEWORK_VERSION}.{SYSTEM_VERSION}"):
|
|
293
|
+
if tag_name and tag_name.startswith(f"{FRAMEWORK_VERSION}.{SYSTEM_VERSION}"):
|
|
269
294
|
# Because the order of paging is based on `last_updated`,
|
|
270
295
|
# we can return the first valid candidate
|
|
296
|
+
logger.info(f"{prefix}Valid tag found for {repository}: {tag_name}")
|
|
271
297
|
return [tag_name]
|
|
272
298
|
else:
|
|
273
299
|
# The tags are coming from another repository, so we're don't know the ordering of tags
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
300
|
+
tags.extend(tag_info.get('name') for tag_info in response_data['results'] if tag_info.get('name'))
|
|
301
|
+
url = response_data.get('next')
|
|
302
|
+
if not url:
|
|
303
|
+
logger.info(f"{prefix}No more pages left to fetch.")
|
|
278
304
|
break
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
305
|
+
except requests.exceptions.HTTPError as e:
|
|
306
|
+
if response.status_code == 429:
|
|
307
|
+
# Based on https://docs.docker.com/docker-hub/api/latest/#tag/rate-limiting
|
|
308
|
+
# We've hit the rate limit so we have to wait and try again later
|
|
309
|
+
logger.warning(f"{prefix}Rate limit reached for DockerHub. Retrying after sleep..")
|
|
310
|
+
time.sleep(int(response.headers['retry-after']) - int(time.time()))
|
|
311
|
+
else:
|
|
312
|
+
logger.error(f"{prefix}HTTP error occurred: {e}")
|
|
284
313
|
break
|
|
285
|
-
|
|
286
|
-
|
|
314
|
+
except requests.exceptions.ConnectionError as e:
|
|
315
|
+
logger.error(f"{prefix}Connection error occurred: {e}")
|
|
316
|
+
break
|
|
317
|
+
except requests.exceptions.Timeout as e:
|
|
318
|
+
logger.error(f"{prefix}Request timed out.")
|
|
319
|
+
break
|
|
320
|
+
except requests.exceptions.RequestException as e:
|
|
321
|
+
logger.error(f"{prefix}An error occurred during requests: {e}")
|
|
322
|
+
break
|
|
323
|
+
except ValueError as e:
|
|
324
|
+
logger.error(f"{prefix}JSON decode error: {e}")
|
|
325
|
+
break
|
|
326
|
+
if tags:
|
|
327
|
+
logger.info(f"{prefix}Tags retrieved successfully: {tags}")
|
|
328
|
+
return tags
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
4.5.1.dev202
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/replay/replay.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/server_base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/assemblyline_core/vacuum/worker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_badlist_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_safelist_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_signature_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_worker_ingest.py
RENAMED
|
File without changes
|
{assemblyline-core-4.5.1.dev202 → assemblyline-core-4.5.1.dev204}/test/test_worker_submit.py
RENAMED
|
File without changes
|