diff --git a/app/model/container.js b/app/model/container.js index eb9f4679..a6190455 100644 --- a/app/model/container.js +++ b/app/model/container.js @@ -26,6 +26,7 @@ const schema = joi.object({ .object({ name: joi.string().min(1).required(), url: joi.string().min(1).required(), + lookupImage: joi.string(), }) .required(), name: joi.string().min(1).required(), diff --git a/app/prometheus/container.js b/app/prometheus/container.js index 1badf12e..20c6ee29 100644 --- a/app/prometheus/container.js +++ b/app/prometheus/container.js @@ -55,6 +55,7 @@ function init() { 'image_id', 'image_name', 'image_os', + 'image_registry_lookup_image', 'image_registry_name', 'image_registry_url', 'image_tag_semver', diff --git a/app/watchers/providers/docker/Docker.js b/app/watchers/providers/docker/Docker.js index 4c154d05..43cef2c2 100644 --- a/app/watchers/providers/docker/Docker.js +++ b/app/watchers/providers/docker/Docker.js @@ -21,6 +21,7 @@ const { wudDisplayIcon, wudTriggerInclude, wudTriggerExclude, + wudRegistryLookupImage, } = require('./label'); const storeContainer = require('../../../store/container'); const log = require('../../../log'); @@ -112,15 +113,31 @@ function getTagCandidates(container, tags, logContainer) { function normalizeContainer(container) { const containerWithNormalizedImage = container; - const registryProvider = Object.values(getRegistries()).find((provider) => - provider.match(container.image), + // Create a temporary image with parsed lookupImage if present for registry matching + let imageForMatching = container.image; + if (container.image.registry.lookupImage) { + const parsedLookupImage = parse(container.image.registry.lookupImage); + // If no domain specified, default to Docker Hub registry + const registryUrl = parsedLookupImage.domain || 'registry-1.docker.io'; + imageForMatching = { + ...container.image, + registry: { + ...container.image.registry, + url: registryUrl, + }, + name: parsedLookupImage.path, + }; + } + const registries = getRegistries(); + const registryProvider = Object.values(registries).find((provider) => + provider.match(imageForMatching), ); if (!registryProvider) { log.warn(`${fullName(container)} - No Registry Provider found`); containerWithNormalizedImage.image.registry.name = 'unknown'; } else { containerWithNormalizedImage.image = registryProvider.normalizeImage( - container.image, + imageForMatching, ); containerWithNormalizedImage.image.registry.name = registryProvider.getId(); @@ -545,6 +562,7 @@ class Docker extends Component { container.Labels[wudDisplayIcon], container.Labels[wudTriggerInclude], container.Labels[wudTriggerExclude], + container.Labels[wudRegistryLookupImage], ), ); const containersWithImage = await Promise.all(containerPromises); @@ -670,6 +688,7 @@ class Docker extends Component { displayIcon, triggerInclude, triggerExclude, + wudRegistryLookupImageValue, ) { const containerId = container.Id; @@ -738,6 +757,7 @@ class Docker extends Component { id: imageId, registry: { url: parsedImage.domain, + lookupImage: wudRegistryLookupImageValue, }, name: parsedImage.path, tag: { diff --git a/app/watchers/providers/docker/label.js b/app/watchers/providers/docker/label.js index 77745450..5d91683e 100644 --- a/app/watchers/providers/docker/label.js +++ b/app/watchers/providers/docker/label.js @@ -51,4 +51,9 @@ module.exports = { * Optional list of triggers to exclude */ wudTriggerExclude: 'wud.trigger.exclude', + + /** + * Optional Lookup image (can be useful when pulling containers from a registry cache) + */ + wudRegistryLookupImage: 'wud.registry.lookup.image', }; diff --git a/docs/changelog/README.md b/docs/changelog/README.md index fd0a6ba1..d824c64e 100644 --- a/docs/changelog/README.md +++ b/docs/changelog/README.md @@ -1,7 +1,13 @@ # Changelog +<<<<<<< HEAD ## 8.1.1 - :fire: [TELEGRAM] - Fix markdown character escape +======= +# 6.7.0 (wip) +- :star: [UI] - Add support for [Selfh.st](https://selfh.st/icons/) icons +- :star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache) +>>>>>>> ab7cf7c (:star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache)) ## 8.1.0 - :star: Add 60s default jitter in docker watcher to avoid load spike on Docker Hub diff --git a/docs/configuration/watchers/README.md b/docs/configuration/watchers/README.md index 237b20c5..d3bd28ee 100644 --- a/docs/configuration/watchers/README.md +++ b/docs/configuration/watchers/README.md @@ -183,8 +183,9 @@ To fine-tune the behaviour of WUD _per container_, you can add labels on them. |-----------------------|:--------------:|----------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------| | `wud.display.icon` | :white_circle: | Custom display icon for the container | Valid [Material Design Icon](https://materialdesignicons.com/), [Fontawesome Icon](https://fontawesome.com/) or [Simple icon](https://simpleicons.org/) (see details below) | `mdi:docker` | | `wud.display.name` | :white_circle: | Custom display name for the container | Valid String | Container name | -| `wud.link.template` | :white_circle: | Browsable link associated to the container version | JS string template with vars `${container}`, `${original}`, `${transformed}`, `${major}`, `${minor}`, `${patch}`, `${prerelease}` | | -| `wud.tag.exclude` | :white_circle: | Regex to exclude specific tags | Valid JavaScript Regex | | +| `wud.link.template` | :white_circle: | Browsable link associated to the container version | JS string template with vars `${container}`, `${original}`, `${transformed}`, `${major}`, `${minor}`, `${patch}`, `${prerelease}` | | +| `wud.registry.lookup.image` | :white_circle: | Alternative image to use for update lookups | Full image path (e.g., `namespace/image` or `registry.example.com/namespace/image`) | | +| `wud.tag.exclude` | :white_circle: | Regex to exclude specific tags | Valid JavaScript Regex | | | `wud.tag.include` | :white_circle: | Regex to include specific tags only | Valid JavaScript Regex | | | `wud.tag.transform` | :white_circle: | Transform function to apply to the tag | `$valid_regex => $valid_string_with_placeholders` (see below) | | | `wud.trigger.exclude` | :white_circle: | Optional list of triggers to exclude | `$trigger_1_id,$trigger_2_id:$threshold` | | @@ -437,3 +438,30 @@ docker run -d --name my_important_service --label 'wud.trigger.include=smtp.gmai ?> Threshold `minor` means that the trigger will run only if this is a `minor` or `patch` semver change ?> Threshold `patch` means that the trigger will run only if this is a `patch` semver change + +### Use an alternative image for update lookups +When using a Docker Registry cache (Harbor, Nexus, etc.), you need to specify the upstream image that WUD should check for updates. + + +#### **Docker Compose** +```yaml +version: '3' + +services: + + traefik: + image: harbor.example.com/ghcr-proxy/traefik/traefik:v3.5.3 + labels: + - wud.watch=true + - wud.registry.lookup.image=ghcr.io/traefik/traefik +``` + +#### **Docker** +```bash +docker run -d \ + --name traefik \ + --label 'wud.watch=true' \ + --label 'wud.registry.lookup.image=ghcr.io/traefik/traefik' \ + harbor.example.com/ghcr-proxy/traefik/traefik:v3.5.3 +``` + diff --git a/e2e/features/api-container.feature b/e2e/features/api-container.feature index ae932f0b..2e3a7b67 100644 --- a/e2e/features/api-container.feature +++ b/e2e/features/api-container.feature @@ -86,6 +86,8 @@ Feature: WUD Container API Exposure And response body should be valid json And response body path $.link should be https://github.com/home-assistant/core/releases/tag/2021.6.1 And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2025.7.1 + And response body path $.result.link should be https://github.com/home-assistant/core/releases/tag/2024.10.2 +>>>>>>> ab7cf7c (:star: [WATCHER] - Add support for alternative lookup registry url (useful when pulling from registry cache)) Scenario: WUD must allow to trigger a watch on a container Given I GET /api/containers diff --git a/ui/src/components/ContainerImage.vue b/ui/src/components/ContainerImage.vue index 36c5efb5..b5473e25 100644 --- a/ui/src/components/ContainerImage.vue +++ b/ui/src/components/ContainerImage.vue @@ -39,9 +39,14 @@ {{ registryIcon }} - Registry + Registry name {{ image.registry.name }} + + Registry url + {{ image.registry.url }} + {{ image.registry.lookupImage }} (lookup) +