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