Skip to content

Commit

Permalink
Merge pull request #519 from getwud/feature/#501_multiple_custom_regi…
Browse files Browse the repository at this point in the history
…stries

⭐ [REGISTRY] - Add support for multiple registries of the same type
  • Loading branch information
fmartinou authored Dec 22, 2024
2 parents 505ab4a + 38f0ed6 commit ae6ad01
Show file tree
Hide file tree
Showing 159 changed files with 15,395 additions and 14,385 deletions.
53 changes: 26 additions & 27 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ os: linux

env:
global:
- NODE_VERSION=18
- CC_TEST_REPORTER_ID=46ef31dae5b656e0f4be410a86bd83bdcf73e7d27ab33a704c197e6fe4bf02a0
- DOCKER_PLATFORMS=linux/arm/v7,linux/arm64/v8,linux/amd64
- IMAGE_NAME=wud
- NODE_VERSION=23

before_install:

Expand All @@ -19,6 +21,7 @@ before_install:
- echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
- sudo apt-get update
- sudo apt-get install -y docker-buildx-plugin
- docker version

# Install Nodejs
- nvm install $NODE_VERSION
Expand Down Expand Up @@ -94,7 +97,7 @@ script:

# Pull vaultwarden
- docker pull vaultwarden/server
- docker pull vaultwarden/server:1.32.6-alpine
- docker pull vaultwarden/server:1.32.7-alpine

# Pull youtubedl
- docker pull jeeaaasustest/youtube-dl
Expand Down Expand Up @@ -141,7 +144,7 @@ script:
- docker run -d --name hub_traefik_245 --label 'wud.watch=true' --label 'wud.tag.include=^\d+\.\d+.\d+$' traefik:2.4.5
- docker run -d --name hub_traefik_latest --label 'wud.watch=true' --label 'wud.watch.digest=true' --label 'wud.tag.include=^latest$' traefik

- docker run -d --name hub_vaultwarden_1222 --label 'wud.watch=true' --label 'wud.tag.include=^\d+\.\d+.\d+-alpine$' -e I_REALLY_WANT_VOLATILE_STORAGE=true vaultwarden/server:1.32.6-alpine
- docker run -d --name hub_vaultwarden_1222 --label 'wud.watch=true' --label 'wud.tag.include=^\d+\.\d+.\d+-alpine$' -e I_REALLY_WANT_VOLATILE_STORAGE=true vaultwarden/server:1.32.7-alpine
- docker run -d --name hub_vaultwarden_latest --label 'wud.watch=true' --label 'wud.watch.digest=true' --label 'wud.tag.include=^latest$' -e I_REALLY_WANT_VOLATILE_STORAGE=true vaultwarden/server

- docker run -d --name hub_youtubedb_latest --label 'wud.watch=true' --label 'wud.watch.digest=true' --label 'wud.tag.include=^latest$' jeeaaasustest/youtube-dl
Expand All @@ -160,45 +163,41 @@ script:
--volume /var/run/docker.sock:/var/run/docker.sock
--env WUD_TRIGGER_MOCK_EXAMPLE_MOCK=mock
--env WUD_WATCHER_LOCAL_WATCHBYDEFAULT=false
--env WUD_REGISTRY_ACR_CLIENTID="$ACR_CLIENT_ID"
--env WUD_REGISTRY_ACR_CLIENTSECRET="$ACR_CLIENT_SECRET"
--env WUD_REGISTRY_ECR_ACCESSKEYID="$AWS_ACCESSKEY_ID"
--env WUD_REGISTRY_ECR_SECRETACCESSKEY="$AWS_SECRET_ACCESSKEY"
--env WUD_REGISTRY_ECR_REGION=eu-west-1
--env WUD_REGISTRY_GCR_CLIENTEMAIL="$GCR_CLIENT_EMAIL"
--env WUD_REGISTRY_GCR_PRIVATEKEY="$GCR_PRIVATE_KEY"
--env WUD_REGISTRY_GHCR_USERNAME="$GITHUB_USERNAME"
--env WUD_REGISTRY_GHCR_TOKEN="$GITHUB_TOKEN"
--env WUD_REGISTRY_GITLAB_TOKEN="$GITLAB_TOKEN"
--env WUD_REGISTRY_LSCR_USERNAME="$GITHUB_USERNAME"
--env WUD_REGISTRY_LSCR_TOKEN="$GITHUB_TOKEN"
--env WUD_REGISTRY_ACR_PRIVATE_CLIENTID="$ACR_CLIENT_ID"
--env WUD_REGISTRY_ACR_PRIVATE_CLIENTSECRET="$ACR_CLIENT_SECRET"
--env WUD_REGISTRY_ECR_PRIVATE_ACCESSKEYID="$AWS_ACCESSKEY_ID"
--env WUD_REGISTRY_ECR_PRIVATE_SECRETACCESSKEY="$AWS_SECRET_ACCESSKEY"
--env WUD_REGISTRY_ECR_PRIVATE_REGION=eu-west-1
--env WUD_REGISTRY_GCR_PRIVATE_CLIENTEMAIL="$GCR_CLIENT_EMAIL"
--env WUD_REGISTRY_GCR_PRIVATE_PRIVATEKEY="$GCR_PRIVATE_KEY"
--env WUD_REGISTRY_GHCR_PRIVATE_USERNAME="$GITHUB_USERNAME"
--env WUD_REGISTRY_GHCR_PRIVATE_TOKEN="$GITHUB_TOKEN"
--env WUD_REGISTRY_GITLAB_PRIVATE_TOKEN="$GITLAB_TOKEN"
--env WUD_REGISTRY_LSCR_PRIVATE_USERNAME="$GITHUB_USERNAME"
--env WUD_REGISTRY_LSCR_PRIVATE_TOKEN="$GITHUB_TOKEN"
--env WUD_AUTH_BASIC_JOHN_USER="john"
--env WUD_AUTH_BASIC_JOHN_HASH='$apr1$8zDVtSAY$62WBh9DspNbUKMZXYRsjS/'
wud
# --env WUD_REGISTRY_HUB_LOGIN="$DOCKER_USERNAME"
# --env WUD_REGISTRY_HUB_TOKEN="$DOCKER_PASSWORD"

# Give wud a little time to fetch all available updates
- sleep 20

# Run E2E Tests
- (cd e2e && npm run cucumber)

after_success:

# Report to Code Climate
- (cd app && ./cc-test-reporter after-build -t lcov --debug --exit-code $TRAVIS_TEST_RESULT)

# Override image version with latest if main branch
- if [ "$TRAVIS_BRANCH" == "main" ] ; then export IMAGE_VERSION=latest; fi

# Override image version with tag name if any
- if [ ! -z "$TRAVIS_TAG" ] ; then export IMAGE_VERSION=$TRAVIS_TAG; fi
- export DOCKER_TAGS="-t ${DOCKER_USERNAME}/${IMAGE_NAME}:${IMAGE_VERSION} -t ghcr.io/${GITHUB_USERNAME}/${IMAGE_NAME}:${IMAGE_VERSION}"
- |
if [ ! -z "$TRAVIS_TAG" ]
then
export DOCKER_TAGS="${DOCKER_TAGS} -t ${DOCKER_USERNAME}/${IMAGE_NAME}:latest -t ghcr.io/${GITHUB_USERNAME}/${IMAGE_NAME}:latest"
fi
# Build & push image
- docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD"
- docker login ghcr.io -u "$GITHUB_USERNAME" -p "$GITHUB_TOKEN"
- docker version
- make prepare
- make build IMAGE_NAME=wud IMAGE_VERSION=$IMAGE_VERSION PLATFORMS=linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/amd64 DOCKER_USERNAME=$DOCKER_USERNAME GITHUB_USERNAME=$GITHUB_USERNAME
- docker buildx create --use
- docker buildx build --push --platform ${DOCKER_PLATFORMS} --build-arg WUD_VERSION=${IMAGE_VERSION} ${DOCKER_TAGS} .
2 changes: 1 addition & 1 deletion Docker.entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/sh
#!/usr/bin/env bash
set -e

if [ $1 == "node" ] && [ $2 == "index" ] && [ ${WUD_LOG_FORMAT} != "json" ]; then
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Common Stage
FROM node:18-alpine as base
FROM node:23-slim as base

LABEL maintainer="fmartinou"
EXPOSE 3000
Expand All @@ -15,9 +15,9 @@ WORKDIR /home/node/app
RUN mkdir /store

# Add TZDATA to allow easy local time configuration
RUN apk update \
&& apk add --no-cache tzdata openssl \
&& rm -rf /var/cache/apk/*
RUN apt update \
&& apt install tzdata openssl \
&& rm -rf /var/cache/apt/*

# Dependencies stage
FROM base as dependencies
Expand Down
17 changes: 0 additions & 17 deletions Makefile

This file was deleted.

4 changes: 2 additions & 2 deletions app/.babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"plugins": ["babel-plugin-rewire"]
}
"plugins": ["babel-plugin-rewire"]
}
11 changes: 0 additions & 11 deletions app/.eslintrc

This file was deleted.

4 changes: 4 additions & 0 deletions app/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"tabWidth": 4
}
55 changes: 32 additions & 23 deletions app/api/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,24 @@ function useStrategy(authentication, app) {
passport.use(authentication.getId(), strategy);
STRATEGY_IDS.push(authentication.getId());
} catch (e) {
log.warn(`Unable to apply authentication ${authentication.getId()} (${e.message})`);
log.warn(
`Unable to apply authentication ${authentication.getId()} (${e.message})`,
);
}
}

function getUniqueStrategies() {
const strategies = Object.values(registry.getState().authentication)
.map((authentication) => authentication.getStrategyDescription());
const strategies = Object.values(registry.getState().authentication).map(
(authentication) => authentication.getStrategyDescription(),
);
const uniqueStrategies = [];
strategies.forEach((strategy) => {
if (!(uniqueStrategies
.find(
(item) => item.type === strategy.type
&& item.name === strategy.name,
))) {
if (
!uniqueStrategies.find(
(item) =>
item.type === strategy.type && item.name === strategy.name,
)
) {
uniqueStrategies.push(strategy);
}
});
Expand All @@ -84,7 +88,9 @@ function getStrategies(req, res) {
}

function getLogoutRedirectUrl() {
const strategyWithRedirectUrl = getUniqueStrategies().find((strategy) => strategy.logoutUrl);
const strategyWithRedirectUrl = getUniqueStrategies().find(
(strategy) => strategy.logoutUrl,
);
if (strategyWithRedirectUrl) {
return strategyWithRedirectUrl.logoutUrl;
}
Expand Down Expand Up @@ -128,27 +134,30 @@ function logout(req, res) {
*/
function init(app) {
// Init express session
app.use(session({
store: new LokiStore({
path: `${store.getConfiguration().path}/${store.getConfiguration().file}`,
ttl: 604800, // 7 days
app.use(
session({
store: new LokiStore({
path: `${store.getConfiguration().path}/${store.getConfiguration().file}`,
ttl: 604800, // 7 days
}),
secret: getSessionSecretKey(),
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
maxAge: getCookieMaxAge(7),
},
}),
secret: getSessionSecretKey(),
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
maxAge: getCookieMaxAge(7),
},
}));
);

// Init passport middleware
app.use(passport.initialize());
app.use(passport.session());

// Register all authentications
Object.values(registry.getState().authentication)
.forEach((authentication) => useStrategy(authentication, app));
Object.values(registry.getState().authentication).forEach(
(authentication) => useStrategy(authentication, app),
);

passport.serializeUser((user, done) => {
done(null, JSON.stringify(user));
Expand Down
17 changes: 7 additions & 10 deletions app/api/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@ function mapComponentToItem(key, component) {
function mapComponentsToList(components) {
return Object.keys(components)
.map((key) => mapComponentToItem(key, components[key]))
.sort(byValues([
[(x) => x.type, byString()],
[(x) => x.name, byString()],
]));
.sort(
byValues([
[(x) => x.type, byString()],
[(x) => x.name, byString()],
]),
);
}

/**
Expand All @@ -50,12 +52,7 @@ function getAll(req, res, kind) {
*/
function getById(req, res, kind) {
const { type, name } = req.params;
let id = `${kind}.${type}.${name}`;

// Hack for registries because id and name are equivalent
if (kind === 'registry') {
id = `${name}`;
}
const id = `${type}.${name}`;
const component = registry.getState()[kind][id];
if (component) {
res.status(200).json(mapComponentToItem(id, component));
Expand Down
49 changes: 38 additions & 11 deletions app/api/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ function deleteContainer(req, res) {
*/
async function watchContainers(req, res) {
try {
await Promise.all(Object.values(getWatchers()).map((watcher) => watcher.watch()));
await Promise.all(
Object.values(getWatchers()).map((watcher) => watcher.watch()),
);
getContainers(req, res);
} catch (e) {
res.status(500).json({
Expand All @@ -103,22 +105,45 @@ async function getContainerTriggers(req, res) {
const container = storeContainer.getContainer(id);
if (container) {
const allTriggers = mapComponentsToList(getTriggers());
const includedTriggers = container.triggerInclude ? container.triggerInclude.split(/\s*,\s*/).map((includedTrigger) => Trigger.parseIncludeOrIncludeTriggerString(includedTrigger)) : undefined;
const excludedTriggers = container.triggerExclude ? container.triggerExclude.split(/\s*,\s*/).map((excludedTrigger) => Trigger.parseIncludeOrIncludeTriggerString(excludedTrigger)) : undefined;
const includedTriggers = container.triggerInclude
? container.triggerInclude
.split(/\s*,\s*/)
.map((includedTrigger) =>
Trigger.parseIncludeOrIncludeTriggerString(
includedTrigger,
),
)
: undefined;
const excludedTriggers = container.triggerExclude
? container.triggerExclude
.split(/\s*,\s*/)
.map((excludedTrigger) =>
Trigger.parseIncludeOrIncludeTriggerString(
excludedTrigger,
),
)
: undefined;
const associatedTriggers = [];
allTriggers.forEach((trigger) => {
const triggerToAssociate = { ...trigger };
let associated = true;
if (includedTriggers) {
const includedTrigger = includedTriggers.find((tr) => tr.id === trigger.id);
const includedTrigger = includedTriggers.find(
(tr) => tr.id === trigger.id,
);
if (includedTrigger) {
triggerToAssociate.configuration.threshold = includedTrigger.threshold;
triggerToAssociate.configuration.threshold =
includedTrigger.threshold;
} else {
associated = false;
}
}
if (excludedTriggers && excludedTriggers
.map((excludedTrigger) => excludedTrigger.id).includes(trigger.id)) {
if (
excludedTriggers &&
excludedTriggers
.map((excludedTrigger) => excludedTrigger.id)
.includes(trigger.id)
) {
associated = false;
}
if (associated) {
Expand All @@ -142,7 +167,7 @@ async function watchContainer(req, res) {

const container = storeContainer.getContainer(id);
if (container) {
const watcher = getWatchers()[`watcher.docker.${container.watcher}`];
const watcher = getWatchers()[`docker.${container.watcher}`];
if (!watcher) {
res.status(500).json({
error: `No provider found for container ${id} and provider ${container.watcher}`,
Expand All @@ -152,14 +177,16 @@ async function watchContainer(req, res) {
// Ensure container is still in store
// (for cases where it has been removed before running an new watchAll)
const containers = await watcher.getContainers();
const containerFound = containers
.find((containerInList) => containerInList.id === container.id);
const containerFound = containers.find(
(containerInList) => containerInList.id === container.id,
);

if (!containerFound) {
res.status(404).send();
} else {
// Run watchContainer from the Provider
const containerReport = await watcher.watchContainer(container);
const containerReport =
await watcher.watchContainer(container);
res.status(200).json(containerReport.container);
}
} catch (e) {
Expand Down
Loading

0 comments on commit ae6ad01

Please sign in to comment.