Compare commits

..

1 Commits

Author SHA1 Message Date
Michael Barz
1cb980c307 fix: make dev docker builds possible with reva replace 2025-09-26 15:35:43 +02:00
2034 changed files with 90072 additions and 136199 deletions

View File

@@ -1,6 +0,0 @@
{
"repoOwner": "opencloud-eu",
"repoName": "opencloud",
"targetBranchChoices": ["main", "stable-2.0", "stable-4.0"],
"fork": false
}

View File

@@ -16,7 +16,7 @@ exclude_paths:
- 'tests/acceptance/expected-failures-*.md'
- 'tests/acceptance/bootstrap/**'
- 'tests/acceptance/TestHelpers/**'
- 'tests/acceptance/scripts/run.sh'
- 'tests/acceptance/run.sh'
- 'vendor/**/*'
- 'tests/ocwrapper/vendor/**'
...

View File

@@ -1,4 +1 @@
_extends: gh-labels

1
.gitignore vendored
View File

@@ -38,7 +38,6 @@ vendor-php
# API acceptance tests - auto-generated files
.php-cs-fixer.cache
suite-logs
tests/acceptance/filesForUpload/filesWithVirus/
# QA activity reports
tests/qa-activity-report/reports/

View File

@@ -36,18 +36,8 @@ ifndef DATE
DATE := $(shell date -u '+%Y%m%d')
endif
LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -s -w \
-X "$(OC_REPO)/pkg/version.Edition=$(EDITION)" \
-X "$(OC_REPO)/pkg/version.String=$(STRING)" \
-X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" \
-X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DEBUG_LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn \
-X "$(OC_REPO)/pkg/version.Edition=$(EDITION)" \
-X "$(OC_REPO)/pkg/version.String=$(STRING)" \
-X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" \
-X "$(OC_REPO)/pkg/version.Date=$(DATE)"
LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -s -w -X "$(OC_REPO)/pkg/version.String=$(STRING)" -X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" -X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DEBUG_LDFLAGS += -X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn -X "$(OC_REPO)/pkg/version.String=$(STRING)" -X "$(OC_REPO)/pkg/version.Tag=$(VERSION)" -X "$(OC_REPO)/pkg/version.Date=$(DATE)"
DOCKER_LDFLAGS += -X "$(OC_REPO)/pkg/config/defaults.BaseDataPathType=path" -X "$(OC_REPO)/pkg/config/defaults.BaseDataPathValue=/var/lib/opencloud"
DOCKER_LDFLAGS += -X "$(OC_REPO)/pkg/config/defaults.BaseConfigPathType=path" -X "$(OC_REPO)/pkg/config/defaults.BaseConfigPathValue=/etc/opencloud"

29
.vscode/launch.json vendored
View File

@@ -53,7 +53,7 @@
"OC_MACHINE_AUTH_API_KEY": "some-opencloud-machine-auth-api-key",
"OC_TRANSFER_SECRET": "some-opencloud-transfer-secret",
// collaboration
"COLLABORATION_WOPI_SECRET": "some-wopi-secret",
"COLLABORATION_WOPIAPP_SECRET": "some-wopi-secret",
// idm ldap
"IDM_SVC_PASSWORD": "some-ldap-idm-password",
"GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password",
@@ -193,21 +193,20 @@
"OC_LOG_COLOR": "true",
"PROXY_ENABLE_BASIC_AUTH": "true",
"IDM_CREATE_DEMO_USERS": "true",
"OC_ADMIN_USER_ID": "fed-admin-user-id-0000-000000000000",
"OC_ADMIN_USER_ID": "some-admin-user-id-0000-000000000000",
"IDM_ADMIN_PASSWORD": "admin",
"OC_SYSTEM_USER_ID": "fed-system-user-id-000-000000000000",
"OC_SYSTEM_USER_API_KEY": "fed-system-user-machine-auth-api-key",
"OC_JWT_SECRET": "fed-opencloud-jwt-secret",
"OC_MACHINE_AUTH_API_KEY": "fed-opencloud-machine-auth-api-key",
"OC_TRANSFER_SECRET": "fed-opencloud-transfer-secret",
"COLLABORATION_WOPI_SECRET": "fed-wopi-secret",
"IDM_SVC_PASSWORD": "fed-ldap-idm-password",
"GRAPH_LDAP_BIND_PASSWORD": "fed-ldap-idm-password",
"IDM_REVASVC_PASSWORD": "fed-ldap-reva-password",
"GROUPS_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
"USERS_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
"AUTH_BASIC_LDAP_BIND_PASSWORD": "fed-ldap-reva-password",
"IDM_IDPSVC_PASSWORD": "fed-ldap-idp-password",
"OC_SYSTEM_USER_ID": "some-system-user-id-000-000000000000",
"OC_SYSTEM_USER_API_KEY": "some-system-user-machine-auth-api-key",
"OC_JWT_SECRET": "some-opencloud-jwt-secret",
"OC_MACHINE_AUTH_API_KEY": "some-opencloud-machine-auth-api-key",
"OC_TRANSFER_SECRET": "some-opencloud-transfer-secret",
"IDM_SVC_PASSWORD": "some-ldap-idm-password",
"GRAPH_LDAP_BIND_PASSWORD": "some-ldap-idm-password",
"IDM_REVASVC_PASSWORD": "some-ldap-reva-password",
"GROUPS_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
"USERS_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
"AUTH_BASIC_LDAP_BIND_PASSWORD": "some-ldap-reva-password",
"IDM_IDPSVC_PASSWORD": "some-ldap-idp-password",
"IDP_LDAP_BIND_PASSWORD": "some-ldap-idp-password",
"GRAPH_APPLICATION_ID": "application-1"
}

View File

@@ -1,4 +1,4 @@
# The test runner source for UI tests
WEB_COMMITID=3120ea384c7a9d1f1ea0c328965951fc06d66900
WEB_COMMITID=1abc9f6c9bf8b5fe6c8e9cb8418dab7911edaec7
WEB_BRANCH=main

View File

@@ -3,12 +3,12 @@
# Repository
repo_slug = "${CI_REPO}"
repo_slug = "opencloud-eu/opencloud"
docker_repo_slug = "opencloudeu/opencloud"
# images
ALPINE_GIT = "alpine/git:latest"
APACHE_TIKA = "apache/tika:3.2.3.0-full"
APACHE_TIKA = "apache/tika:2.8.0.0"
CHKO_DOCKER_PUSHRM = "chko/docker-pushrm:1"
COLLABORA_CODE = "collabora/code:24.04.5.1.1"
OPEN_SEARCH = "opensearchproject/opensearch:2"
@@ -18,7 +18,7 @@ OC_CI_ALPINE = "owncloudci/alpine:latest"
OC_CI_BAZEL_BUILDIFIER = "owncloudci/bazel-buildifier:latest"
OC_CI_CLAMAVD = "owncloudci/clamavd"
OC_CI_DRONE_ANSIBLE = "owncloudci/drone-ansible:latest"
OC_CI_GOLANG = "registry.heinlein.group/opencloud/golang-ci:1.25"
OC_CI_GOLANG = "docker.io/golang:1.24"
OC_CI_NODEJS = "owncloudci/nodejs:%s"
OC_CI_PHP = "owncloudci/php:%s"
OC_CI_WAIT_FOR = "owncloudci/wait-for:latest"
@@ -27,7 +27,6 @@ OC_LITMUS = "owncloudci/litmus:latest"
OC_UBUNTU = "owncloud/ubuntu:20.04"
ONLYOFFICE_DOCUMENT_SERVER = "onlyoffice/documentserver:7.5.1"
PLUGINS_DOCKER_BUILDX = "woodpeckerci/plugin-docker-buildx:latest"
PLUGINS_NOTATION = "registry.heinlein.group/opencloud/notation-wp-plugin:latest"
PLUGINS_GITHUB_RELEASE = "woodpeckerci/plugin-release"
PLUGINS_GIT_ACTION = "quay.io/thegeeklab/wp-git-action"
PLUGINS_S3 = "plugins/s3:1"
@@ -41,21 +40,22 @@ DEFAULT_PHP_VERSION = "8.2"
DEFAULT_NODEJS_VERSION = "20"
CACHE_S3_SERVER = "https://s3.ci.opencloud.eu"
INSTALL_LIBVIPS_COMMAND = "apt-get update; apt-get install libvips42 -y"
dirs = {
"base": "/woodpecker/src/github.com/%s" % repo_slug,
"web": "/woodpecker/src/github.com/%s/webTestRunner" % repo_slug,
"zip": "/woodpecker/src/github.com/%s/zip" % repo_slug,
"webZip": "/woodpecker/src/github.com/%s/zip/web.tar.gz" % repo_slug,
"webPnpmZip": "/woodpecker/src/github.com/%s/zip/web-pnpm.tar.gz" % repo_slug,
"playwrightBrowsersArchive": "/woodpecker/src/github.com/%s/zip/playwright-browsers.tar.gz" % repo_slug,
"baseGo": "/go/src/github.com/%s" % repo_slug,
"base": "/woodpecker/src/github.com/opencloud-eu/opencloud",
"web": "/woodpecker/src/github.com/opencloud-eu/opencloud/webTestRunner",
"zip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip",
"webZip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/web.tar.gz",
"webPnpmZip": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/web-pnpm.tar.gz",
"playwrightBrowsersArchive": "/woodpecker/src/github.com/opencloud-eu/opencloud/zip/playwright-browsers.tar.gz",
"baseGo": "/go/src/github.com/opencloud-eu/opencloud",
"gobinTar": "go-bin.tar.gz",
"gobinTarPath": "/go/src/github.com/%s/go-bin.tar.gz" % repo_slug,
"gobinTarPath": "/go/src/github.com/opencloud-eu/opencloud/go-bin.tar.gz",
"opencloudConfig": "tests/config/woodpecker/opencloud-config.json",
"opencloudRevaDataRoot": "/woodpecker/src/github.com/%s/srv/app/tmp/ocis/owncloud/data" % repo_slug,
"multiServiceOcBaseDataPath": "/woodpecker/src/github.com/%s/multiServiceData" % repo_slug,
"ocWrapper": "/woodpecker/src/github.com/%s/tests/ocwrapper" % repo_slug,
"opencloudRevaDataRoot": "/woodpecker/src/github.com/opencloud-eu/opencloud/srv/app/tmp/ocis/owncloud/data",
"multiServiceOcBaseDataPath": "/woodpecker/src/github.com/opencloud-eu/opencloud/multiServiceData",
"ocWrapper": "/woodpecker/src/github.com/opencloud-eu/opencloud/tests/ocwrapper",
"bannedPasswordList": "tests/config/woodpecker/banned-password-list.txt",
"ocmProviders": "tests/config/woodpecker/providers.json",
"opencloudBinPath": "opencloud/bin",
@@ -137,8 +137,7 @@ config = {
"suites": [
"apiGraph",
"apiServiceAvailability",
# skip tests for collaborativePosix. see https://github.com/opencloud-eu/opencloud/issues/2036
#"collaborativePosix",
"collaborativePosix",
],
"skip": False,
"withRemotePhp": [True],
@@ -234,7 +233,6 @@ config = {
],
"skip": False,
"antivirusNeeded": True,
"generateVirusFiles": True,
"extraServerEnvironment": {
"ANTIVIRUS_SCANNER_TYPE": "clamav",
"ANTIVIRUS_CLAMAV_SOCKET": "tcp://clamav:3310",
@@ -301,7 +299,6 @@ config = {
"skip": False,
"withRemotePhp": [True],
"antivirusNeeded": True,
"generateVirusFiles": True,
"extraServerEnvironment": {
"ANTIVIRUS_SCANNER_TYPE": "clamav",
"ANTIVIRUS_CLAMAV_SOCKET": "tcp://clamav:3310",
@@ -321,7 +318,6 @@ config = {
"USE_PREPARED_LDAP_USERS": True,
},
"extraServerEnvironment": {
"OC_MULTI_TENANT_ENABLED": True,
"OC_LDAP_USER_SCHEMA_TENANT_ID": "departmentNumber",
"OC_LDAP_URI": "ldaps://ldap-server:1636",
"OC_LDAP_INSECURE": True,
@@ -337,11 +333,9 @@ config = {
"GRAPH_LDAP_SERVER_UUID": True,
"GRAPH_LDAP_GROUP_CREATE_BASE_DN": "ou=custom,ou=groups,dc=opencloud,dc=eu",
"GRAPH_LDAP_REFINT_ENABLED": True,
"GROUPS_DRIVER": "null",
"FRONTEND_READONLY_USER_ATTRIBUTES": "user.onPremisesSamAccountName,user.displayName,user.mail,user.passwordProfile,user.accountEnabled,user.appRoleAssignments",
"OC_LDAP_SERVER_WRITE_ENABLED": False,
"OC_EXCLUDE_RUN_SERVICES": "idm",
"OC_LDAP_USER_ENABLED_ATTRIBUTE": "",
},
},
},
@@ -354,7 +348,7 @@ config = {
"part": {
"skip": False,
"totalParts": 4, # divide and run all suites in parts (divide pipelines)
"xsuites": ["search", "app-provider", "app-provider-onlyOffice", "app-store", "keycloak", "oidc", "ocm", "a11y", "mobile-view", "navigation"], # suites to skip
"xsuites": ["search", "app-provider", "app-provider-onlyOffice", "app-store", "keycloak", "oidc", "ocm", "a11y", "mobile-view"], # suites to skip
},
"search": {
"skip": False,
@@ -388,9 +382,7 @@ config = {
"architectures": ["arm64", "amd64"],
"production": {
# NOTE: need to be updated if new production releases are determined
"tags": ["2.0", "4.0"],
# NOTE: need to be set to true if patch releases are made from stable-X-branches
"skip_rolling": "false",
"tags": ["2.0"],
"repo": docker_repo_slug,
"build_type": "production",
},
@@ -414,7 +406,7 @@ GRAPH_AVAILABLE_ROLES = "b1e2218d-eef8-4d4c-b82d-0f1a1b48f3b5,a8d5fe5e-96e3-418d
workspace = \
{
"base": "/go",
"path": "src/github.com/%s/" % repo_slug,
"path": "src/github.com/opencloud-eu/opencloud/",
}
# minio mc environment variables
@@ -482,10 +474,6 @@ def main(ctx):
if ctx.build.event == "cron" and ctx.build.sender == "translation-sync":
return translation_sync(ctx)
is_release_pr = (ctx.build.event == "pull_request" and ctx.build.sender == "openclouders" and "🎉 release" in ctx.build.title.lower())
if is_release_pr:
return [licenseCheck(ctx)]
build_release_helpers = \
readyReleaseGo()
@@ -556,6 +544,7 @@ def main(ctx):
def cachePipeline(ctx, name, steps):
return {
"name": "build-%s-cache" % name,
"skip_clone": True,
"steps": steps,
"when": [
{
@@ -614,7 +603,7 @@ def testPipelines(ctx):
pipelines += apiTests(ctx)
enable_watch_fs = [False]
if ctx.build.event == "cron":
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
enable_watch_fs.append(True)
for run_with_watch_fs_enabled in enable_watch_fs:
@@ -711,7 +700,7 @@ def restoreGoBinCache():
"name": "extract-go-bin-cache",
"image": OC_UBUNTU,
"commands": [
"tar -xvmf %s -C /" % dirs["gobinTarPath"],
"tar -xmf %s -C /" % dirs["gobinTarPath"],
],
},
]
@@ -1000,7 +989,7 @@ def localApiTestPipeline(ctx):
with_remote_php = [True]
enable_watch_fs = [False]
if ctx.build.event == "cron":
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
with_remote_php.append(False)
enable_watch_fs.append(True)
@@ -1024,7 +1013,6 @@ def localApiTestPipeline(ctx):
"withRemotePhp": with_remote_php,
"enableWatchFs": enable_watch_fs,
"ldapNeeded": False,
"generateVirusFiles": False,
}
if "localApiTests" in config:
@@ -1049,7 +1037,7 @@ def localApiTestPipeline(ctx):
(opencloudServer(storage, params["accounts_hash_difficulty"], deploy_type = "federation", extra_server_environment = params["extraServerEnvironment"], watch_fs_enabled = run_with_watch_fs_enabled) if params["federationServer"] else []) +
((wopiCollaborationService("fakeoffice") + wopiCollaborationService("collabora") + wopiCollaborationService("onlyoffice")) if params["collaborationServiceNeeded"] else []) +
(openCloudHealthCheck("wopi", ["wopi-collabora:9304", "wopi-onlyoffice:9304", "wopi-fakeoffice:9304"]) if params["collaborationServiceNeeded"] else []) +
localApiTests(name, params["suites"], storage, params["extraTestEnvironment"], run_with_remote_php, params["generateVirusFiles"]) +
localApiTests(name, params["suites"], storage, params["extraTestEnvironment"], run_with_remote_php) +
logRequests(),
"services": (emailService() if params["emailNeeded"] else []) +
(clamavService() if params["antivirusNeeded"] else []) +
@@ -1069,7 +1057,7 @@ def localApiTestPipeline(ctx):
pipelines.append(pipeline)
return pipelines
def localApiTests(name, suites, storage = "decomposed", extra_environment = {}, with_remote_php = False, generate_virus_files = False):
def localApiTests(name, suites, storage = "decomposed", extra_environment = {}, with_remote_php = False):
test_dir = "%s/tests/acceptance" % dirs["base"]
expected_failures_file = "%s/expected-failures-localAPI-on-%s-storage.md" % (test_dir, storage)
@@ -1086,31 +1074,20 @@ def localApiTests(name, suites, storage = "decomposed", extra_environment = {},
"WITH_REMOTE_PHP": with_remote_php,
"COLLABORATION_SERVICE_URL": "http://wopi-fakeoffice:9300",
"OC_STORAGE_PATH": "$HOME/.opencloud/storage/users",
"USE_BEARER_TOKEN": True,
}
for item in extra_environment:
environment[item] = extra_environment[item]
commands = []
# Generate EICAR virus test files if needed
if generate_virus_files:
commands.append("chmod +x %s/tests/acceptance/scripts/generate-virus-files.sh" % dirs["base"])
commands.append("bash %s/tests/acceptance/scripts/generate-virus-files.sh" % dirs["base"])
# Merge expected failures
if not with_remote_php:
commands.append("cat %s/expected-failures-without-remotephp.md >> %s" % (test_dir, expected_failures_file))
# Run tests
commands.append("make -C %s test-acceptance-api" % (dirs["base"]))
return [{
"name": "localApiTests-%s" % name,
"image": OC_CI_PHP % DEFAULT_PHP_VERSION,
"environment": environment,
"commands": commands,
"commands": [
# merge the expected failures
"" if with_remote_php else "cat %s/expected-failures-without-remotephp.md >> %s" % (test_dir, expected_failures_file),
"make -C %s test-acceptance-api" % (dirs["base"]),
],
}]
def cs3ApiTests(ctx, storage, accounts_hash_difficulty = 4):
@@ -1231,7 +1208,7 @@ def wopiValidatorTests(ctx, storage, wopiServerType, accounts_hash_difficulty =
"commands": [
"curl -v -X PUT '%s/remote.php/webdav/test.wopitest' -k --fail --retry-connrefused --retry 7 --retry-all-errors -u admin:admin -D headers.txt" % OC_URL,
"cat headers.txt",
"export FILE_ID=$(cat headers.txt | sed -n -e 's/^.*oc-fileid: //Ip')",
"export FILE_ID=$(cat headers.txt | sed -n -e 's/^.*Oc-Fileid: //p')",
"export URL=\"%s/app/open?app_name=FakeOffice&file_id=$FILE_ID\"" % OC_URL,
"export URL=$(echo $URL | tr -d '[:cntrl:]')",
"curl -v -X POST \"$URL\" -k --fail --retry-connrefused --retry 7 --retry-all-errors -u admin:admin > open.json",
@@ -1316,7 +1293,7 @@ def apiTests(ctx):
with_remote_php = [True]
enable_watch_fs = [False]
if ctx.build.event == "cron":
if ctx.build.event == "cron" or "full-ci" in ctx.build.title.lower():
with_remote_php.append(False)
enable_watch_fs.append(True)
@@ -1500,7 +1477,7 @@ def multiServiceE2ePipeline(ctx, watch_fs_enabled = False):
}
if watch_fs_enabled:
extra_server_environment["STORAGE_USERS_POSIX_WATCH_FS"] = True
extra_server_environment["STORAGE_USES_POSIX_WATCH_FS"] = True
storage_users_environment = {
"OC_CORS_ALLOW_ORIGINS": "%s,https://%s:9201" % (OC_URL, OC_SERVER_NAME),
@@ -1614,40 +1591,31 @@ def uploadTracingResult(ctx):
def dockerReleases(ctx):
pipelines = []
docker_releases = []
docker_repos = []
build_type = ""
# only make realeases on tag events
if ctx.build.event == "tag":
tag = ctx.build.ref.replace("refs/tags/v", "").lower()
# iterate over production tags to see if this is a production release
is_production = False
skip_rolling = False
for prod_tag in config["dockerReleases"]["production"]["tags"]:
if tag.startswith(prod_tag):
is_production = True
skip_rolling = config["dockerReleases"]["production"]["skip_rolling"]
break
if is_production:
docker_releases.append("production")
# a new production realease is also a rolling release
# unless skip_rolling is set in the config, i.e. for patch-releases on stable-branch
if not skip_rolling:
docker_releases.append("rolling")
docker_repos.append(config["dockerReleases"]["production"]["repo"])
build_type = config["dockerReleases"]["production"]["build_type"]
else:
docker_releases.append("rolling")
docker_repos.append(config["dockerReleases"]["rolling"]["repo"])
build_type = config["dockerReleases"]["rolling"]["build_type"]
# on non tag events, do daily build
else:
docker_releases.append("daily")
docker_repos.append(config["dockerReleases"]["daily"]["repo"])
build_type = config["dockerReleases"]["daily"]["build_type"]
for releaseConfigName in docker_releases:
repo = config["dockerReleases"][releaseConfigName]["repo"]
build_type = config["dockerReleases"][releaseConfigName]["build_type"]
for repo in docker_repos:
repo_pipelines = []
repo_pipelines.append(dockerRelease(ctx, repo, build_type))
@@ -1667,19 +1635,8 @@ def dockerRelease(ctx, repo, build_type):
build_args = {
"REVISION": "%s" % ctx.build.commit,
"VERSION": "%s" % (ctx.build.ref.replace("refs/tags/", "") if ctx.build.event == "tag" else "daily"),
"EDITION": "stable" if build_type == "production" else "rolling",
}
# if no additional tag is given, the build-plugin adds latest
hard_tag = "daily"
if ctx.build.event == "tag":
tag_version = ctx.build.ref.replace("refs/tags/v", "")
tag_parts = tag_version.split("-")
# if a tag has something appended with "-" i.e. alpha, beta, rc1...
# set the entire string as tag, else tag with latest (same as empty with current plugin)
hard_tag = tag_version if len(tag_parts) > 1 else "latest"
depends_on = getPipelineNames(getGoBinForTesting(ctx))
if ctx.build.event == "tag":
@@ -1693,12 +1650,11 @@ def dockerRelease(ctx, repo, build_type):
"name": "dryrun",
"image": PLUGINS_DOCKER_BUILDX,
"settings": {
"context": "..",
"dry_run": True,
"platforms": "linux/amd64", # do dry run only on the native platform
"repo": "%s,quay.io/%s,registry.heinlein.group/%s" % (repo, repo, repo),
"repo": "%s,quay.io/%s" % (repo, repo),
"auto_tag": False if build_type == "daily" else True,
"tag": hard_tag,
"tag": "daily" if build_type == "daily" else "",
"default_tag": "daily",
"dockerfile": "opencloud/docker/Dockerfile.multiarch",
"build_args": build_args,
@@ -1716,11 +1672,10 @@ def dockerRelease(ctx, repo, build_type):
"name": "build-and-push",
"image": PLUGINS_DOCKER_BUILDX,
"settings": {
"context": "..",
"repo": "%s,quay.io/%s,registry.heinlein.group/%s" % (repo, repo, repo),
"repo": "%s,quay.io/%s" % (repo, repo),
"platforms": "linux/amd64,linux/arm64", # we can add remote builders
"auto_tag": False if build_type == "daily" else True,
"tag": hard_tag,
"tag": "daily" if build_type == "daily" else "",
"default_tag": "daily",
"dockerfile": "opencloud/docker/Dockerfile.multiarch",
"build_args": build_args,
@@ -1750,45 +1705,6 @@ def dockerRelease(ctx, repo, build_type):
"from_secret": "quay_password",
},
},
{
"registry": "https://registry.heinlein.group",
"username": {
"from_secret": "harbor_opencloudeu_user",
},
"password": {
"from_secret": "harbor_opencloudeu_password",
},
},
],
},
"when": [
event["cron"],
event["base"],
event["tag"],
],
},
{
"name": "notation-signing",
"image": PLUGINS_NOTATION,
"settings": {
"key": {
"from_secret": "notation_key",
},
"crt": {
"from_secret": "notation_cert",
},
"target": "registry.heinlein.group/%s:%s" % (repo, hard_tag),
"pull_image": True,
"logins": [
{
"registry": "https://registry.heinlein.group",
"username": {
"from_secret": "harbor_opencloudeu_user",
},
"password": {
"from_secret": "harbor_opencloudeu_password",
},
},
],
},
"when": [
@@ -1831,7 +1747,6 @@ def binaryRelease(ctx, arch, depends_on = []):
"image": OC_CI_GOLANG,
"environment": {
"VERSION": (ctx.build.ref.replace("refs/tags/", "") if ctx.build.event == "tag" else "daily"),
"EDITION": "rolling",
"HTTP_PROXY": {
"from_secret": "ci_http_proxy",
},
@@ -2077,9 +1992,7 @@ def notifyMatrix(ctx):
},
"QA_REPO": "https://github.com/opencloud-eu/qa.git",
"QA_REPO_BRANCH": "main",
"CI_WOODPECKER_URL": {
"from_secret": "oc_ci_url",
},
"CI_WOODPECKER_URL": "https://ci.opencloud.eu/",
"CI_REPO_ID": "3",
"CI_WOODPECKER_TOKEN": "no-auth-needed-on-this-repo",
},
@@ -2156,7 +2069,6 @@ def opencloudServer(storage = "decomposed", accounts_hash_difficulty = 4, depend
"WEB_DEBUG_ADDR": "0.0.0.0:9104",
"WEBDAV_DEBUG_ADDR": "0.0.0.0:9119",
"WEBFINGER_DEBUG_ADDR": "0.0.0.0:9279",
"STORAGE_USERS_POSIX_SCAN_DEBOUNCE_DELAY": 0,
}
if storage == "posix":
@@ -2194,7 +2106,7 @@ def opencloudServer(storage = "decomposed", accounts_hash_difficulty = 4, depend
environment["SEARCH_EXTRACTOR_CS3SOURCE_INSECURE"] = True
if watch_fs_enabled:
environment["STORAGE_USERS_POSIX_WATCH_FS"] = True
environment["STORAGE_USES_POSIX_WATCH_FS"] = True
# Pass in "default" accounts_hash_difficulty to not set this environment variable.
# That will allow OpenCloud to use whatever its built-in default is.
@@ -2241,6 +2153,9 @@ def opencloudServer(storage = "decomposed", accounts_hash_difficulty = 4, depend
},
},
"commands": [
"apt-get update",
"apt-get install -y inotify-tools xattr",
INSTALL_LIBVIPS_COMMAND,
"%s init --insecure true" % dirs["opencloudBin"],
"cat $OC_CONFIG_DIR/opencloud.yaml",
"cp tests/config/woodpecker/app-registry.yaml $OC_CONFIG_DIR/app-registry.yaml",
@@ -2284,6 +2199,7 @@ def startOpenCloudService(service = None, name = None, environment = {}):
"detach": True,
"environment": environment,
"commands": [
INSTALL_LIBVIPS_COMMAND,
"%s %s server" % (dirs["opencloudBin"], service),
],
},
@@ -2309,6 +2225,7 @@ def build():
"name": "build",
"image": OC_CI_GOLANG,
"commands": [
"apt-get update; apt-get install libvips-dev -y",
"for i in $(seq 3); do make -C opencloud build ENABLE_VIPS=1 && break || sleep 1; done",
],
"environment": CI_HTTP_PROXY_ENV,
@@ -2357,12 +2274,11 @@ def translation_sync(ctx):
"image": OC_CI_GOLANG,
"commands": [
"make l10n-read",
"mkdir tx && cd tx",
"curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash",
"export PATH=$PATH:$(pwd) && cd ..",
". ~/.profile",
"make l10n-push",
"make l10n-pull",
"rm -rf tx",
"rm tx",
"make l10n-clean",
],
"environment": {
@@ -2499,7 +2415,7 @@ def genericBuildArtifactCache(ctx, name, action, path):
return genericCache(name, action, [path], cache_path)
if action == "purge":
return purgeCache("purge_opencloud_build_artifact_cache", "cache/%s" % repo_slug, 1)
return purgeCache("purge_opencloud_build_artifact_cache", "cache/opencloud-eu/opencloud", 1)
return []
def restoreBuildArtifactCache(ctx, name, path):
@@ -2705,13 +2621,15 @@ def setupForLitmus():
}]
def getWoodpeckerEnvAndCheckScript(ctx):
path_to_woodpecker_env = "%s/.woodpecker.env" % dirs["base"]
path_to_check_script = "%s/tests/config/woodpecker/check_web_cache.sh" % dirs["base"]
opencloud_git_base_url = "https://raw.githubusercontent.com/opencloud-eu/opencloud"
path_to_woodpecker_env = "%s/%s/.woodpecker.env" % (opencloud_git_base_url, ctx.build.commit)
path_to_check_script = "%s/%s/tests/config/woodpecker/check_web_cache.sh" % (opencloud_git_base_url, ctx.build.commit)
return {
"name": "get-woodpecker-env-and-check-script",
"image": OC_UBUNTU,
"commands": [
"cp %s check_web_cache.sh" % path_to_check_script,
"curl -s -o .woodpecker.env %s" % path_to_woodpecker_env,
"curl -s -o check_web_cache.sh %s" % path_to_check_script,
],
}
@@ -2784,7 +2702,6 @@ def generateWebPnpmCache(ctx):
def cacheBrowsers(ctx):
e2e_trigger = [
event["base"],
event["cron"],
{
"event": "pull_request",
"path": {
@@ -2810,10 +2727,8 @@ def cacheBrowsers(ctx):
}]
webPnpmCacheSteps = restoreWebPnpmCache(extra_commands = [
"cd %s" % dirs["web"],
". ./.woodpecker.env",
"if $BROWSER_CACHE_FOUND; then exit 0; fi",
"cd %s" % dirs["base"],
])
browser_cache_steps = [
@@ -2824,9 +2739,9 @@ def cacheBrowsers(ctx):
"PLAYWRIGHT_BROWSERS_PATH": ".playwright",
},
"commands": [
"cd %s" % dirs["web"],
". ./.woodpecker.env",
"if $BROWSER_CACHE_FOUND; then exit 0; fi",
"cd %s" % dirs["web"],
"pnpm exec playwright install --with-deps",
"pnpm exec playwright install --list",
"tar -czf %s .playwright" % dirs["playwrightBrowsersArchive"],
@@ -2837,9 +2752,9 @@ def cacheBrowsers(ctx):
"image": MINIO_MC,
"environment": MINIO_MC_ENV,
"commands": [
"cd %s" % dirs["web"],
". ./.woodpecker.env",
"if $BROWSER_CACHE_FOUND; then exit 0; fi",
"cd %s" % dirs["web"],
"playwright_version=$(bash tests/woodpecker/script.sh get_playwright_version)",
"mc alias set s3 $MC_HOST $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY",
"mc cp -r -a %s s3/$CACHE_BUCKET/web/browsers-cache/$playwright_version/" % dirs["playwrightBrowsersArchive"],
@@ -2945,7 +2860,7 @@ def restoreBrowsersCache():
"name": "unzip-browsers-cache",
"image": OC_UBUNTU,
"commands": [
"tar -xf /woodpecker/src/github.com/%s/webTestRunner/playwright-browsers.tar.gz -C ." % repo_slug,
"tar -xf /woodpecker/src/github.com/opencloud-eu/opencloud/webTestRunner/playwright-browsers.tar.gz -C .",
],
},
]
@@ -3058,13 +2973,11 @@ def wopiCollaborationService(name):
environment["COLLABORATION_APP_ADDR"] = "https://collabora:9980"
environment["COLLABORATION_APP_ICON"] = "https://collabora:9980/favicon.ico"
elif name == "onlyoffice":
environment["COLLABORATION_SERVICE_NAME"] = "collboration-onlyoffice"
environment["COLLABORATION_APP_NAME"] = "OnlyOffice"
environment["COLLABORATION_APP_PRODUCT"] = "OnlyOffice"
environment["COLLABORATION_APP_ADDR"] = "https://onlyoffice"
environment["COLLABORATION_APP_ICON"] = "https://onlyoffice/web-apps/apps/documenteditor/main/resources/img/favicon.ico"
elif name == "fakeoffice":
environment["COLLABORATION_SERVICE_NAME"] = "collboration-fakeoficce"
environment["COLLABORATION_APP_NAME"] = "FakeOffice"
environment["COLLABORATION_APP_PRODUCT"] = "Microsoft"
environment["COLLABORATION_APP_ADDR"] = "http://fakeoffice:8080"
@@ -3133,7 +3046,7 @@ def k6LoadTests(ctx):
if "skip" in config["k6LoadTests"] and config["k6LoadTests"]["skip"]:
return []
opencloud_git_base_url = "https://raw.githubusercontent.com/%s" % repo_slug
opencloud_git_base_url = "https://raw.githubusercontent.com/opencloud-eu/opencloud"
script_link = "%s/%s/tests/config/woodpecker/run_k6_tests.sh" % (opencloud_git_base_url, ctx.build.commit)
event_array = ["cron"]

View File

@@ -1,244 +1,5 @@
# Changelog
## [4.2.0](https://github.com/opencloud-eu/opencloud/releases/tag/v4.2.0) - 2025-12-24
### ❤️ Thanks to all contributors! ❤️
@ScharfViktor, @butonic, @dragonchaser, @fschade, @rhafer, @saw-jan
### 🐛 Bug Fixes
- Remove sub-service binary entrypoints and fix antivirus only server cmd [[#2043](https://github.com/opencloud-eu/opencloud/pull/2043)]
- fix(thumbnailer): respect image boundaries and text wrappings [[#2062](https://github.com/opencloud-eu/opencloud/pull/2062)]
- fix: cobra viper flags and env [[#2047](https://github.com/opencloud-eu/opencloud/pull/2047)]
- fix service name in suture logs [[#2052](https://github.com/opencloud-eu/opencloud/pull/2052)]
### ✅ Tests
- [full-ci] use graph api in the enforcePasswordPublicLink.feature [[#2050](https://github.com/opencloud-eu/opencloud/pull/2050)]
- [full-ci][tests-only] test: check last email content with retries as emails can be delayed [[#2038](https://github.com/opencloud-eu/opencloud/pull/2038)]
- skip collaborativePosix tests in CI [[#2039](https://github.com/opencloud-eu/opencloud/pull/2039)]
### 📈 Enhancement
- allow http2 connections to proxy [[#2040](https://github.com/opencloud-eu/opencloud/pull/2040)]
- migrate from urfave/cli to spf13/cobra [[#1954](https://github.com/opencloud-eu/opencloud/pull/1954)]
### 📦️ Dependencies
- build(deps): bump github.com/testcontainers/testcontainers-go/modules/opensearch from 0.39.0 to 0.40.0 [[#1967](https://github.com/opencloud-eu/opencloud/pull/1967)]
- build(deps): bump golang.org/x/net from 0.47.0 to 0.48.0 [[#2061](https://github.com/opencloud-eu/opencloud/pull/2061)]
- build(deps): bump github.com/open-policy-agent/opa from 1.10.1 to 1.11.0 [[#1930](https://github.com/opencloud-eu/opencloud/pull/1930)]
## [4.1.0](https://github.com/opencloud-eu/opencloud/releases/tag/v4.1.0) - 2025-12-15
### ❤️ Thanks to all contributors! ❤️
@JammingBen, @ScharfViktor, @Svanvith, @butonic, @flimmy, @fschade, @individual-it, @kulmann, @micbar, @prashant-gurung899, @saw-jan
### 📚 Documentation
- fix typo [[#2024](https://github.com/opencloud-eu/opencloud/pull/2024)]
- [docs] update policies link [[#1996](https://github.com/opencloud-eu/opencloud/pull/1996)]
- fix the link in quickstart script for itself [[#1956](https://github.com/opencloud-eu/opencloud/pull/1956)]
### ✅ Tests
- [full-ci][tests-only] test: fix some test flakiness [[#2003](https://github.com/opencloud-eu/opencloud/pull/2003)]
- [tests-only] Skip test related pipelines for ready-release-go PRs [[#2011](https://github.com/opencloud-eu/opencloud/pull/2011)]
- [full-ci][tests-only] test: add test to check mismatch offset during TUS upload [[#1993](https://github.com/opencloud-eu/opencloud/pull/1993)]
- [full-ci][tests-only] test: proper resource existence check [[#1990](https://github.com/opencloud-eu/opencloud/pull/1990)]
- check propfing after renaming data in file system [[#1809](https://github.com/opencloud-eu/opencloud/pull/1809)]
- fix-get-attribute-test [[#1974](https://github.com/opencloud-eu/opencloud/pull/1974)]
### 📈 Enhancement
- Show edition in opencloud version command [[#2019](https://github.com/opencloud-eu/opencloud/pull/2019)]
### 🐛 Bug Fixes
- fix: enforce trailing slash for server url [[#1995](https://github.com/opencloud-eu/opencloud/pull/1995)]
- fix: enhance resource creation with detailed process information [[#1978](https://github.com/opencloud-eu/opencloud/pull/1978)]
### 📦️ Dependencies
- chore: bump web to v4.3.0 [[#2030](https://github.com/opencloud-eu/opencloud/pull/2030)]
- reva-bump-2.41.0 [[#2032](https://github.com/opencloud-eu/opencloud/pull/2032)]
- build(deps): bump github.com/testcontainers/testcontainers-go from 0.39.0 to 0.40.0 [[#1931](https://github.com/opencloud-eu/opencloud/pull/1931)]
## [4.0.0](https://github.com/opencloud-eu/opencloud/releases/tag/v4.0.0) - 2025-12-01
### ❤️ Thanks to all contributors! ❤️
@AlexAndBear, @MahdiBaghbani, @ScharfViktor, @butonic, @dragonchaser, @flimmy, @fschade, @individual-it, @jnweiger, @kulmann, @micbar, @mikelolasagasti, @pbleser-oc, @rhafer, @schweigisito
### 💥 Breaking changes
- collaboration: Enable `InsertRemoteImage` option [[#1692](https://github.com/opencloud-eu/opencloud/pull/1692)]
### 📚 Documentation
- Fix typos in antivirus README documentation [[#1940](https://github.com/opencloud-eu/opencloud/pull/1940)]
- fix: add missing service README.md files with basic description [[#1859](https://github.com/opencloud-eu/opencloud/pull/1859)]
- Fix README.md files which contain broken or missing links [[#1854](https://github.com/opencloud-eu/opencloud/pull/1854)]
### 🐛 Bug Fixes
- introduce OC_EVENTS_TLS_INSECURE [[#1936](https://github.com/opencloud-eu/opencloud/pull/1936)]
- kill unused env vars [[#1888](https://github.com/opencloud-eu/opencloud/pull/1888)]
- rc-handling was only active for the dryrun, not the real build-and-push [[#1919](https://github.com/opencloud-eu/opencloud/pull/1919)]
- handle objectguid endianess [[#1901](https://github.com/opencloud-eu/opencloud/pull/1901)]
- fix: add update server to default csp rules [[#1875](https://github.com/opencloud-eu/opencloud/pull/1875)]
- fix: add missing capability flag support-radicale [[#1891](https://github.com/opencloud-eu/opencloud/pull/1891)]
- fix opensearch client certificate [[#1890](https://github.com/opencloud-eu/opencloud/pull/1890)]
- Bump reva [[#1882](https://github.com/opencloud-eu/opencloud/pull/1882)]
- load two yaml configs [[#1617](https://github.com/opencloud-eu/opencloud/pull/1617)]
- make user cache tenant aware [[#1732](https://github.com/opencloud-eu/opencloud/pull/1732)]
- fix: sanitise markdow code to make docusaurus happy [[#1851](https://github.com/opencloud-eu/opencloud/pull/1851)]
- update launch.json [[#1843](https://github.com/opencloud-eu/opencloud/pull/1843)]
- docs: Fix auth-app examples in README [[#1844](https://github.com/opencloud-eu/opencloud/pull/1844)]
- fix: fix typo in treesize logging [[#1826](https://github.com/opencloud-eu/opencloud/pull/1826)]
- fix: set global signing secret fallback correctly [[#1781](https://github.com/opencloud-eu/opencloud/pull/1781)]
### 📈 Enhancement
- feat(ocm): add WAYF configuration for reva OCM service [[#1714](https://github.com/opencloud-eu/opencloud/pull/1714)]
- log missing name or id attributes [[#1914](https://github.com/opencloud-eu/opencloud/pull/1914)]
- collabora: Set IsAdminUser and IsAnonymousUser in CheckFileInfo [[#1745](https://github.com/opencloud-eu/opencloud/pull/1745)]
### ✅ Tests
- [full-ci] disable running ci with watch fs when full-ci [[#1902](https://github.com/opencloud-eu/opencloud/pull/1902)]
- api-tests: delete spaces before users [[#1877](https://github.com/opencloud-eu/opencloud/pull/1877)]
- update tika version [[#1872](https://github.com/opencloud-eu/opencloud/pull/1872)]
- add share sync to collaborativePosix suite [[#1806](https://github.com/opencloud-eu/opencloud/pull/1806)]
- removed test virus files from repo [[#1812](https://github.com/opencloud-eu/opencloud/pull/1812)]
- increase timeouts waiting for notification & search [[#1802](https://github.com/opencloud-eu/opencloud/pull/1802)]
- Sync share before action [[#1795](https://github.com/opencloud-eu/opencloud/pull/1795)]
- correct STORAGE_USERS_POSIX_WATCH_FS env typo in CI [[#1746](https://github.com/opencloud-eu/opencloud/pull/1746)]
### 📦️ Dependencies
- [full-ci] revaBump-v2.40.1 [[#1927](https://github.com/opencloud-eu/opencloud/pull/1927)]
- [full-ci] chore: bump web to v4.2.1 [[#1938](https://github.com/opencloud-eu/opencloud/pull/1938)]
- build(deps): bump google.golang.org/grpc from 1.76.0 to 1.77.0 [[#1923](https://github.com/opencloud-eu/opencloud/pull/1923)]
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.12.1 to 2.12.2 [[#1922](https://github.com/opencloud-eu/opencloud/pull/1922)]
- build(deps): bump github.com/kovidgoyal/imaging from 1.7.2 to 1.8.17 [[#1912](https://github.com/opencloud-eu/opencloud/pull/1912)]
- build(deps): bump golang.org/x/crypto from 0.44.0 to 0.45.0 [[#1911](https://github.com/opencloud-eu/opencloud/pull/1911)]
- [decomposed]Update version 4.0.0 rc.2 [[#1917](https://github.com/opencloud-eu/opencloud/pull/1917)]
- chore: bump web to v4.2.1-rc.1 [[#1900](https://github.com/opencloud-eu/opencloud/pull/1900)]
- revaBump-getting#428 [[#1887](https://github.com/opencloud-eu/opencloud/pull/1887)]
- build(deps): bump github.com/blevesearch/bleve/v2 from 2.5.4 to 2.5.5 [[#1884](https://github.com/opencloud-eu/opencloud/pull/1884)]
- build(deps): bump github.com/olekukonko/tablewriter from 1.1.0 to 1.1.1 [[#1869](https://github.com/opencloud-eu/opencloud/pull/1869)]
- build(deps): bump golang.org/x/term from 0.36.0 to 0.37.0 [[#1845](https://github.com/opencloud-eu/opencloud/pull/1845)]
- reva-bump-2.39.2. update opencloud 4.0.0-rc.1 [[#1849](https://github.com/opencloud-eu/opencloud/pull/1849)]
- build(deps): bump golang.org/x/sync from 0.17.0 to 0.18.0 [[#1836](https://github.com/opencloud-eu/opencloud/pull/1836)]
- build(deps): bump golang.org/x/oauth2 from 0.32.0 to 0.33.0 [[#1828](https://github.com/opencloud-eu/opencloud/pull/1828)]
- build(deps): bump github.com/KimMachineGun/automemlimit from 0.7.4 to 0.7.5 [[#1787](https://github.com/opencloud-eu/opencloud/pull/1787)]
- build(deps): bump github.com/open-policy-agent/opa from 1.9.0 to 1.10.1 [[#1788](https://github.com/opencloud-eu/opencloud/pull/1788)]
- Bump reva [[#1786](https://github.com/opencloud-eu/opencloud/pull/1786)]
- build(deps): bump github.com/gabriel-vasile/mimetype from 1.4.10 to 1.4.11 [[#1775](https://github.com/opencloud-eu/opencloud/pull/1775)]
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.12.0 to 2.12.1 [[#1706](https://github.com/opencloud-eu/opencloud/pull/1706)]
- build(deps): bump github.com/onsi/ginkgo/v2 from 2.27.1 to 2.27.2 [[#1754](https://github.com/opencloud-eu/opencloud/pull/1754)]
## [3.7.0](https://github.com/opencloud-eu/opencloud/releases/tag/v3.7.0) - 2025-11-03
### ❤️ Thanks to all contributors! ❤️
@ScharfViktor, @individual-it, @kulmann, @rhafer, @schweigisito, @sdwilsh
### ✅ Tests
- check status of postprocessing before accesing the file [[#1762](https://github.com/opencloud-eu/opencloud/pull/1762)]
### 📈 Enhancement
- multi-tenancy: Optional attributes on provision API [[#1663](https://github.com/opencloud-eu/opencloud/pull/1663)]
- fix: fix #1698 - Notification email doesn't contain Message-Id header [[#1708](https://github.com/opencloud-eu/opencloud/pull/1708)]
### 🐛 Bug Fixes
- fix: only search LDAP group by name [[#1724](https://github.com/opencloud-eu/opencloud/pull/1724)]
### 📦️ Dependencies
- [full-ci] bump web 4.2.0 and opencloud 3.7.0 version [[#1765](https://github.com/opencloud-eu/opencloud/pull/1765)]
## [3.6.0](https://github.com/opencloud-eu/opencloud/releases/tag/v3.6.0) - 2025-10-27
### ❤️ Thanks to all contributors! ❤️
@AlexAndBear, @ScharfViktor, @butonic, @dragonchaser, @fschade, @micbar, @prashant-gurung899, @rhafer, @schweigisito, @tammi-23
### 📈 Enhancement
- allow specifying a shutdown order [[#1622](https://github.com/opencloud-eu/opencloud/pull/1622)]
- change: use 404 as status when thumbnail can not be fetched [[#1582](https://github.com/opencloud-eu/opencloud/pull/1582)]
- feat: add dedicated logo (web) for mobile view to theme [[#1579](https://github.com/opencloud-eu/opencloud/pull/1579)]
- feat: make it possible to start the collaboration service in the single process [[#1569](https://github.com/opencloud-eu/opencloud/pull/1569)]
- introduce AppURLs helper for atomic backgroud updates [[#1542](https://github.com/opencloud-eu/opencloud/pull/1542)]
- chore: add config for capability CheckForUpdates [[#1556](https://github.com/opencloud-eu/opencloud/pull/1556)]
### ✅ Tests
- [full-ci] feat: implement OIDC authentication option [[#1676](https://github.com/opencloud-eu/opencloud/pull/1676)]
- apiTest-coverage for #1523 [[#1660](https://github.com/opencloud-eu/opencloud/pull/1660)]
- [full-ci] deleted unused step definitions [[#1639](https://github.com/opencloud-eu/opencloud/pull/1639)]
- check thumbnails in the share with me response [[#1605](https://github.com/opencloud-eu/opencloud/pull/1605)]
- [full-ci][tests-only] fix restore browsers cache workflow [[#1615](https://github.com/opencloud-eu/opencloud/pull/1615)]
- [full-ci] Enhance getSpaceByName: check local cache before Graph API calls [[#1574](https://github.com/opencloud-eu/opencloud/pull/1574)]
- [full-ci] getting personal space by userId instead of userName [[#1553](https://github.com/opencloud-eu/opencloud/pull/1553)]
- apiTest-flaky: sync share before checking [[#1550](https://github.com/opencloud-eu/opencloud/pull/1550)]
- [decomposed] use Alpine for opencloud starting [[#1547](https://github.com/opencloud-eu/opencloud/pull/1547)]
### 🐛 Bug Fixes
- fix: apply changes from other fixes in compose repo [[#1707](https://github.com/opencloud-eu/opencloud/pull/1707)]
- fix(settings): env var precedence [[#1625](https://github.com/opencloud-eu/opencloud/pull/1625)]
- fix(antivirus): update icap-client library which fixes tcp socket reuse [[#1589](https://github.com/opencloud-eu/opencloud/pull/1589)]
- fix: use valid autocomplete values (axe autocomplete-valid) [[#1588](https://github.com/opencloud-eu/opencloud/pull/1588)]
- Fix collaboration service name [[#1577](https://github.com/opencloud-eu/opencloud/pull/1577)]
- let the runtime always create a cancel context [[#1565](https://github.com/opencloud-eu/opencloud/pull/1565)]
- Bump reva and cs3apis [[#1538](https://github.com/opencloud-eu/opencloud/pull/1538)]
- use correct endpoint in nats check [[#1533](https://github.com/opencloud-eu/opencloud/pull/1533)]
### 📚 Documentation
- adr: use eduation api for multi-tenancy provisioning [[#1548](https://github.com/opencloud-eu/opencloud/pull/1548)]
- fix: remove deprecated web ui feature "OpenAppsInTab" [[#1575](https://github.com/opencloud-eu/opencloud/pull/1575)]
### 📦️ Dependencies
- build(deps): bump github.com/onsi/ginkgo/v2 from 2.26.0 to 2.27.1 [[#1705](https://github.com/opencloud-eu/opencloud/pull/1705)]
- [decomposed] bump-version-v3.6.0 [[#1719](https://github.com/opencloud-eu/opencloud/pull/1719)]
- revaBump-2.39.1 [[#1718](https://github.com/opencloud-eu/opencloud/pull/1718)]
- chore: bump reva [[#1701](https://github.com/opencloud-eu/opencloud/pull/1701)]
- build(deps): bump github.com/kovidgoyal/imaging from 1.6.4 to 1.7.2 [[#1696](https://github.com/opencloud-eu/opencloud/pull/1696)]
- build(deps): bump github.com/blevesearch/bleve/v2 from 2.5.3 to 2.5.4 [[#1697](https://github.com/opencloud-eu/opencloud/pull/1697)]
- build(deps): bump golang.org/x/oauth2 from 0.31.0 to 0.32.0 [[#1634](https://github.com/opencloud-eu/opencloud/pull/1634)]
- build(deps): bump golang.org/x/net from 0.44.0 to 0.46.0 [[#1638](https://github.com/opencloud-eu/opencloud/pull/1638)]
- revaBumb: add groupware capabilities [[#1689](https://github.com/opencloud-eu/opencloud/pull/1689)]
- revaUpdate: adding groupware capabilities [[#1659](https://github.com/opencloud-eu/opencloud/pull/1659)]
- chore/bump-web-4.1.0 [[#1652](https://github.com/opencloud-eu/opencloud/pull/1652)]
- build(deps): bump google.golang.org/grpc from 1.75.1 to 1.76.0 [[#1628](https://github.com/opencloud-eu/opencloud/pull/1628)]
- build(deps): bump github.com/coreos/go-oidc/v3 from 3.15.0 to 3.16.0 [[#1627](https://github.com/opencloud-eu/opencloud/pull/1627)]
- build(deps): bump github.com/grpc-ecosystem/grpc-gateway/v2 from 2.27.2 to 2.27.3 [[#1608](https://github.com/opencloud-eu/opencloud/pull/1608)]
- build(deps): bump github.com/go-ldap/ldap/v3 from 3.4.11 to 3.4.12 [[#1609](https://github.com/opencloud-eu/opencloud/pull/1609)]
- build(deps): bump google.golang.org/protobuf from 1.36.9 to 1.36.10 [[#1604](https://github.com/opencloud-eu/opencloud/pull/1604)]
- build(deps): bump github.com/onsi/ginkgo/v2 from 2.25.3 to 2.26.0 [[#1603](https://github.com/opencloud-eu/opencloud/pull/1603)]
- build(deps): bump github.com/nats-io/nats.go from 1.46.0 to 1.46.1 [[#1590](https://github.com/opencloud-eu/opencloud/pull/1590)]
- build(deps): bump github.com/olekukonko/tablewriter from 1.0.9 to 1.1.0 [[#1584](https://github.com/opencloud-eu/opencloud/pull/1584)]
- build(deps): bump github.com/open-policy-agent/opa from 1.8.0 to 1.9.0 [[#1576](https://github.com/opencloud-eu/opencloud/pull/1576)]
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.11.9 to 2.12.0 [[#1568](https://github.com/opencloud-eu/opencloud/pull/1568)]
- build(deps): bump golang.org/x/net from 0.43.0 to 0.44.0 [[#1567](https://github.com/opencloud-eu/opencloud/pull/1567)]
- reva bump. getting #327 [[#1555](https://github.com/opencloud-eu/opencloud/pull/1555)]
- build(deps): bump golang.org/x/image from 0.30.0 to 0.31.0 [[#1552](https://github.com/opencloud-eu/opencloud/pull/1552)]
- build(deps): bump github.com/nats-io/nats.go from 1.45.0 to 1.46.0 [[#1551](https://github.com/opencloud-eu/opencloud/pull/1551)]
- build(deps): bump golang.org/x/crypto from 0.41.0 to 0.42.0 [[#1545](https://github.com/opencloud-eu/opencloud/pull/1545)]
- build(deps): bump github.com/testcontainers/testcontainers-go/modules/opensearch from 0.38.0 to 0.39.0 [[#1544](https://github.com/opencloud-eu/opencloud/pull/1544)]
- build(deps): bump github.com/open-policy-agent/opa from 1.6.0 to 1.8.0 [[#1510](https://github.com/opencloud-eu/opencloud/pull/1510)]
- build(deps): bump google.golang.org/grpc from 1.75.0 to 1.75.1 [[#1534](https://github.com/opencloud-eu/opencloud/pull/1534)]
## [3.5.0](https://github.com/opencloud-eu/opencloud/releases/tag/v3.5.0) - 2025-09-22
### ❤️ Thanks to all contributors! ❤️

View File

@@ -124,7 +124,7 @@ BEHAT_BIN=vendor-bin/behat/vendor/bin/behat
.PHONY: test-acceptance-api
test-acceptance-api: vendor-bin/behat/vendor
BEHAT_BIN=$(BEHAT_BIN) tests/acceptance/scripts/run.sh
BEHAT_BIN=$(BEHAT_BIN) tests/acceptance/run.sh
vendor/bamarni/composer-bin-plugin: composer.lock
composer install
@@ -198,10 +198,6 @@ go-mod-tidy:
test:
@go test -v -tags '$(TAGS)' -coverprofile coverage.out ./...
.PHONY: test-with-race
test-with-race:
@go test -race -v -tags '$(TAGS)' -coverprofile coverage.out ./...
.PHONY: go-coverage
go-coverage:
@if [ ! -f coverage.out ]; then $(MAKE) test &>/dev/null; fi;

View File

@@ -1,7 +0,0 @@
Enhancement: Add WAYF configuration for reva OCM service
Add WAYF configuration support for the Reva OCM service,
enabling federation discovery functionality for Open Cloud Mesh.
This includes configuration for federations file storage and invite accept dialog URL.
https://github.com/opencloud-eu/opencloud/pull/1714

View File

@@ -11,7 +11,7 @@ set -euo pipefail
# OC_VERSION: Version to download, e.g. OC_VERSION="1.2.0"
# Call this script directly from opencloud:
# curl -L https://opencloud.eu/install | /bin/bash
# curl -L https://opencloud.eu/quickinstall.sh | /bin/bash
# This function is borrowed from openSUSEs /usr/bin/old, thanks.
function backup_file () {

View File

@@ -663,7 +663,6 @@
"profile",
"roles",
"groups",
"OpenCloudUnique_ID",
"basic",
"email"
],
@@ -2309,7 +2308,7 @@
"always"
],
"usePasswordModifyExtendedOp": [
"true"
"false"
],
"trustEmail": [
"false"

View File

@@ -19,11 +19,6 @@ services:
- "--entryPoints.http.http.redirections.entryPoint.to=https"
- "--entryPoints.http.http.redirections.entryPoint.scheme=https"
- "--entryPoints.https.address=:443"
# http2 optimizations
- "--entryPoints.https.http2.maxConcurrentStreams=512"
- "--serversTransport.maxIdleConnsPerHost=100"
# allow self signed certificate from OpenCloud
- "--serversTransport.insecureSkipVerify=true"
# change default timeouts for long-running requests
# this is needed for webdav clients that do not support the TUS protocol
- "--entryPoints.https.transport.respondingTimeouts.readTimeout=12h"

View File

@@ -25,7 +25,7 @@ services:
OC_LOG_COLOR: "${LOG_PRETTY:-false}"
OC_LOG_PRETTY: "${LOG_PRETTY:-false}"
# do not use SSL between Traefik and OpenCloud
PROXY_TLS: "true"
PROXY_TLS: "false"
# make the REVA gateway accessible to the app drivers
GATEWAY_GRPC_ADDR: 0.0.0.0:9142
# INSECURE: needed if OpenCloud / Traefik is using self generated certificates
@@ -72,7 +72,6 @@ services:
- "traefik.http.routers.opencloud.tls.certresolver=http"
- "traefik.http.routers.opencloud.service=opencloud"
- "traefik.http.services.opencloud.loadbalancer.server.port=9200"
- "traefik.http.services.opencloud.loadbalancer.server.scheme=https"
logging:
driver: ${LOG_DRIVER:-local}
restart: always

View File

@@ -1,79 +0,0 @@
---
title: "Use the graph education API for multi-tenant user provisioning"
---
* Status: approved
* Deciders: [@micbar, @butonic, @rhafer]
* Date: 2025-09-23
Reference: https://github.com/opencloud-eu/opencloud/issues/877
## Context and Problem Statement
With the current multi-tenancy implementation, the user-management is mostly external
to the OpenCloud instance. Up to [now](../0001-simple-multi-tenancy-using-a-single-opencloud-instance.md)
we relied on some external LDAP server providing the users including their tenant assignment.
We'd like multi-tenancy to also work in environments where no such LDAP server is available.
## Decision Drivers
* Multi-tenancy must work without some existing external (as in not managed by us) LDAP server
* keep the implementation effort low
* allow integration with existing (de)provisioning systems
## Considered Options
### Use the auto-provisioning feature of OpenCloud
We already have basic auto-provsioning features implemented in OpenCloud.
Currently this is not tenant-aware, but it could be extended to support that.
This would require some changes in the way that the users are managed by the
auto-proviosioning code.
The auto-provisioning code does currently use the "normal" graph API to create
users. That API is not tenant-aware and would need to be significantly changed
to support multi-tenancy. However currently there is no real need to put
tenant-awareness into that API (and it would drive us even further a away from
compatibility with the MS Graph API). We could also switch away from the Graph API
for auto-provisioning and use some direct calls to the underlying LDAP server.
Also, using the auto-provisioning feature means that users are only created
when they first login. This means it is not possible to share files with users that
have not yet logged in. This is a significant limitation.
Also we don't currently have any de-provisioning features implemented.
### Use the existing Eudcation API of the Graph Service
We already implemented the Graph Education API in OpenCloud (based on the MS Graph Education API).
This, apart from the somewhat different naming, does already bring most of what is needed
for provisioning users in a multi-tenant environment.
The customer would just need to hookup their existing (de)provisioning system to call the
Education API to create/delete users and assign them to tenants (schools/classes).
The main drawback of this approach is that the customer needs to create some code to
hookup their existing system to the Education API.
The main advantage is that it would give the customer much more control over the users' lifecycle.
## Decision Outcome
Use the existing Education API of the Graph Service.
* Allows integration with existing (de)provisioning systems
* hopefully keeps the implementation effort low
Note: For now this means that the auto-provisioning feature will not be available for
multi-tenant setups. We might want to revisit this in the future.
### Implementation Steps
* re-vive the existing Education API implementation and run it as a separate service
* (maybe) allow to create tenants with a customer specified ID. The tenant id might also be
part of the user's claims (provided by the customer's identity provider). It would be better
if the tenant ids in our system match the tenant ids in the customer's identity provider.
* For de-provisioning to work we need to implement a way to lookup users by an external ID as
that is only unique identfier the customer's system knows for a user. While the MS Graph API
already provides an `externalId` Attribute we don't currently support that on our APIs.

177
go.mod
View File

@@ -5,25 +5,26 @@ go 1.24.6
require (
dario.cat/mergo v1.0.2
github.com/CiscoM31/godata v1.0.11
github.com/KimMachineGun/automemlimit v0.7.5
github.com/KimMachineGun/automemlimit v0.7.4
github.com/Masterminds/semver v1.5.0
github.com/MicahParks/keyfunc/v2 v2.1.0
github.com/Nerzal/gocloak/v13 v13.9.0
github.com/bbalet/stopwords v1.0.0
github.com/beevik/etree v1.6.0
github.com/blevesearch/bleve/v2 v2.5.5
github.com/blevesearch/bleve/v2 v2.5.3
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/coreos/go-oidc/v3 v3.17.0
github.com/coreos/go-oidc/v3 v3.15.0
github.com/cs3org/go-cs3apis v0.0.0-20250908152307-4ca807afe54e
github.com/davidbyttow/govips/v2 v2.16.0
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
github.com/gabriel-vasile/mimetype v1.4.11
github.com/egirna/icap-client v0.1.1
github.com/gabriel-vasile/mimetype v1.4.10
github.com/ggwhite/go-masker v1.1.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/render v1.0.3
github.com/go-jose/go-jose/v3 v3.0.4
github.com/go-ldap/ldap/v3 v3.4.12
github.com/go-ldap/ldap/v3 v3.4.11
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3
github.com/go-micro/plugins/v4/client/grpc v1.2.1
github.com/go-micro/plugins/v4/logger/zerolog v1.2.0
@@ -33,7 +34,8 @@ require (
github.com/go-micro/plugins/v4/store/nats-js-kv v0.0.0-20240726082623-6831adfdcdc4
github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus v1.2.0
github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0
github.com/go-playground/validator/v10 v10.28.0
github.com/go-playground/validator/v10 v10.27.0
github.com/gofrs/uuid v4.4.0+incompatible
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/golang/protobuf v1.5.4
github.com/google/go-cmp v0.7.0
@@ -41,30 +43,29 @@ require (
github.com/google/uuid v1.6.0
github.com/gookit/config/v2 v2.2.7
github.com/gorilla/mux v1.8.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2
github.com/invopop/validation v0.8.0
github.com/jellydator/ttlcache/v2 v2.11.1
github.com/jellydator/ttlcache/v3 v3.4.0
github.com/jinzhu/now v1.1.5
github.com/justinas/alice v1.2.0
github.com/kovidgoyal/imaging v1.8.17
github.com/kovidgoyal/imaging v1.6.4
github.com/leonelquinteros/gotext v1.7.2
github.com/libregraph/idm v0.5.0
github.com/libregraph/lico v0.66.0
github.com/mitchellh/mapstructure v1.5.0
github.com/mna/pigeon v1.3.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/nats-io/nats-server/v2 v2.12.2
github.com/nats-io/nats.go v1.47.0
github.com/nats-io/nats-server/v2 v2.11.9
github.com/nats-io/nats.go v1.46.0
github.com/oklog/run v1.2.0
github.com/olekukonko/tablewriter v1.1.1
github.com/olekukonko/tablewriter v1.0.9
github.com/onsi/ginkgo v1.16.5
github.com/onsi/ginkgo/v2 v2.27.2
github.com/onsi/ginkgo/v2 v2.25.3
github.com/onsi/gomega v1.38.2
github.com/open-policy-agent/opa v1.11.1
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89
github.com/open-policy-agent/opa v1.8.0
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76
github.com/opencloud-eu/reva/v2 v2.41.0
github.com/opencloud-eu/reva/v2 v2.38.1-0.20250924125540-eaa2437c36b2
github.com/opensearch-project/opensearch-go/v4 v4.5.0
github.com/orcaman/concurrent-map v1.0.0
github.com/pkg/errors v0.9.1
@@ -75,21 +76,20 @@ require (
github.com/rogpeppe/go-internal v1.14.1
github.com/rs/cors v1.11.1
github.com/rs/zerolog v1.34.0
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af
github.com/sirupsen/logrus v1.9.3
github.com/spf13/afero v1.15.0
github.com/spf13/cobra v1.10.1
github.com/spf13/pflag v1.0.10
github.com/spf13/viper v1.21.0
github.com/stretchr/testify v1.11.1
github.com/test-go/testify v1.1.4
github.com/testcontainers/testcontainers-go v0.40.0
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0
github.com/testcontainers/testcontainers-go v0.39.0
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0
github.com/theckman/yacspin v0.13.12
github.com/thejerf/suture/v4 v4.0.6
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
github.com/tus/tusd/v2 v2.8.0
github.com/unrolled/secure v1.16.0
github.com/urfave/cli/v2 v2.27.7
github.com/vmihailenco/msgpack/v5 v5.4.1
github.com/xhit/go-simple-mail/v2 v2.16.0
go-micro.dev/v4 v4.11.0
@@ -98,23 +98,22 @@ require (
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0
go.opentelemetry.io/contrib/zpages v0.63.0
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/exporters/jaeger v1.17.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0
go.opentelemetry.io/otel/sdk v1.38.0
go.opentelemetry.io/otel/trace v1.38.0
golang.org/x/crypto v0.46.0
golang.org/x/crypto v0.42.0
golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac
golang.org/x/image v0.33.0
golang.org/x/net v0.48.0
golang.org/x/oauth2 v0.33.0
golang.org/x/sync v0.19.0
golang.org/x/term v0.38.0
golang.org/x/text v0.32.0
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.10
golang.org/x/image v0.31.0
golang.org/x/net v0.44.0
golang.org/x/oauth2 v0.31.0
golang.org/x/sync v0.17.0
golang.org/x/term v0.35.0
golang.org/x/text v0.29.0
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5
google.golang.org/grpc v1.75.1
google.golang.org/protobuf v1.36.9
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.2
stash.kopano.io/kgol/rndm v1.1.2
)
@@ -141,13 +140,13 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/bitly/go-simplejson v0.5.0 // indirect
github.com/bits-and-blooms/bitset v1.22.0 // indirect
github.com/blevesearch/bleve_index_api v1.2.11 // indirect
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
github.com/blevesearch/geo v0.2.4 // indirect
github.com/blevesearch/go-faiss v1.0.26 // indirect
github.com/blevesearch/go-faiss v1.0.25 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/gtreap v0.1.1 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
@@ -157,24 +156,21 @@ require (
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
github.com/blevesearch/zapx/v16 v16.2.7 // indirect
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
github.com/bluele/gcache v0.0.2 // indirect
github.com/bombsimon/logrusr/v3 v3.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
github.com/ceph/go-ceph v0.36.0 // indirect
github.com/ceph/go-ceph v0.35.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cevaris/ordered_map v0.0.0-20190319150403-3adeae072e73 // indirect
github.com/clipperhouse/displaywidth v0.3.1 // indirect
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v1.0.0-rc.2 // indirect
github.com/containerd/platforms v1.0.0-rc.1 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.6.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cornelk/hashmap v1.0.8 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
@@ -190,7 +186,7 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/docker/docker v28.5.1+incompatible // indirect
github.com/docker/docker v28.3.3+incompatible // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
@@ -209,7 +205,7 @@ require (
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-git/go-git/v5 v5.13.2 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.4.3 // indirect
@@ -232,18 +228,17 @@ require (
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.2.1 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/goccy/go-yaml v1.18.0 // indirect
github.com/gofrs/flock v0.13.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/goccy/go-yaml v1.12.0 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gomodule/redigo v1.9.3 // indirect
github.com/gomodule/redigo v1.9.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/go-tpm v0.9.6 // indirect
github.com/google/go-tpm v0.9.5 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/renameio/v2 v2.0.1 // indirect
github.com/google/renameio/v2 v2.0.0 // indirect
github.com/gookit/goutil v0.7.1 // indirect
github.com/gorilla/handlers v1.5.1 // indirect
github.com/gorilla/schema v1.4.1 // indirect
@@ -260,18 +255,13 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/juliangruber/go-intersect v1.1.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/klauspost/compress v1.18.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.11 // indirect
github.com/klauspost/crc32 v1.3.0 // indirect
github.com/kovidgoyal/go-parallel v1.1.1 // indirect
github.com/kovidgoyal/go-shm v1.0.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
github.com/lestrrat-go/dsig v1.0.0 // indirect
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.1 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.12 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.0 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.10 // indirect
github.com/lestrrat-go/option v1.0.1 // indirect
github.com/lestrrat-go/option/v2 v2.0.0 // indirect
github.com/libregraph/oidc-go v1.1.0 // indirect
@@ -282,16 +272,16 @@ require (
github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-sqlite3 v1.14.32 // indirect
github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b // indirect
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 // indirect
github.com/miekg/dns v1.1.57 // indirect
github.com/mileusna/useragent v1.3.5 // indirect
github.com/minio/crc64nvme v1.1.0 // indirect
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect
github.com/minio/crc64nvme v1.0.2 // indirect
github.com/minio/highwayhash v1.0.3 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/minio-go/v7 v7.0.97 // indirect
github.com/minio/minio-go/v7 v7.0.95 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
@@ -302,17 +292,16 @@ require (
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nats-io/jwt/v2 v2.8.0 // indirect
github.com/nats-io/jwt/v2 v2.7.4 // indirect
github.com/nats-io/nkeys v0.4.11 // indirect
github.com/nats-io/nuid v1.0.1 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect
github.com/olekukonko/errors v1.1.0 // indirect
github.com/olekukonko/ll v0.1.2 // indirect
github.com/olekukonko/ll v0.0.9 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
@@ -320,45 +309,38 @@ require (
github.com/pablodz/inotifywaitgo v0.0.9 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pquerna/cachecontrol v0.2.0 // indirect
github.com/prometheus/alertmanager v0.29.0 // indirect
github.com/prometheus/alertmanager v0.28.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.67.1 // indirect
github.com/prometheus/procfs v0.17.0 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/prometheus/statsd_exporter v0.22.8 // indirect
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/russellhaering/goxmldsig v1.5.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect
github.com/sagikazarmark/locafero v0.11.0 // indirect
github.com/samber/lo v1.51.0 // indirect
github.com/samber/slog-common v0.19.0 // indirect
github.com/samber/slog-zerolog/v2 v2.9.0 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/segmentio/kafka-go v0.4.49 // indirect
github.com/segmentio/ksuid v1.0.4 // indirect
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
github.com/sergi/go-diff v1.4.0 // indirect
github.com/sethvargo/go-diceware v0.5.0 // indirect
github.com/sethvargo/go-password v0.3.1 // indirect
github.com/shamaton/msgpack/v2 v2.4.0 // indirect
github.com/shamaton/msgpack/v2 v2.3.1 // indirect
github.com/shirou/gopsutil/v4 v4.25.6 // indirect
github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect
github.com/shurcooL/vfsgen v0.0.0-20230704071429-0000e147ea92 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 // indirect
github.com/spf13/cast v1.10.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/studio-b12/gowebdav v0.9.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
@@ -367,9 +349,8 @@ require (
github.com/tklauser/numcpus v0.8.0 // indirect
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
github.com/trustelem/zxcvbn v1.0.1 // indirect
github.com/urfave/cli/v2 v2.27.7 // indirect
github.com/valyala/fastjson v1.6.4 // indirect
github.com/vektah/gqlparser/v2 v2.5.31 // indirect
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/wk8/go-ordered-map v1.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
@@ -378,32 +359,37 @@ require (
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/yashtewari/glob-intersection v0.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/etcd/api/v3 v3.6.6 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.6 // indirect
go.etcd.io/etcd/client/v3 v3.6.6 // indirect
go.etcd.io/etcd/api/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.4 // indirect
go.etcd.io/etcd/client/v3 v3.6.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
go.yaml.in/yaml/v2 v2.4.3 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/mod v0.30.0 // indirect
golang.org/x/sys v0.39.0 // indirect
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.39.0 // indirect
golang.org/x/mod v0.27.0 // indirect
golang.org/x/sys v0.36.0 // indirect
golang.org/x/time v0.13.0 // indirect
golang.org/x/tools v0.36.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
)
replace github.com/studio-b12/gowebdav => github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202
replace github.com/egirna/icap-client => github.com/fschade/icap-client v0.0.0-20240802074440-aade4a234387
replace github.com/unrolled/secure => github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c
replace go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3
@@ -413,6 +399,3 @@ replace go-micro.dev/v4 => github.com/butonic/go-micro/v4 v4.11.1-0.202411151126
exclude github.com/mattn/go-sqlite3 v2.0.3+incompatible
replace github.com/go-micro/plugins/v4/store/nats-js-kv => github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a
// to get the logger injection (https://github.com/pablodz/inotifywaitgo/pull/11)
replace github.com/pablodz/inotifywaitgo v0.0.9 => github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9

363
go.sum
View File

@@ -72,8 +72,8 @@ github.com/CiscoM31/godata v1.0.11 h1:w7y8twuW02LdH6mak3/GJ5i0GrCv2IoZUJVqa/g5Ye
github.com/CiscoM31/godata v1.0.11/go.mod h1:ZMiT6JuD3Rm83HEtiTx4JEChsd25YCrxchKGag/sdTc=
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c h1:ocsNvQ2tNHme4v/lTs17HROamc7mFzZfzWcg4m+UXN0=
github.com/DeepDiver1975/secure v0.0.0-20240611112133-abc838fb797c/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
github.com/KimMachineGun/automemlimit v0.7.5 h1:RkbaC0MwhjL1ZuBKunGDjE/ggwAX43DwZrJqVwyveTk=
github.com/KimMachineGun/automemlimit v0.7.5/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
github.com/KimMachineGun/automemlimit v0.7.4 h1:UY7QYOIfrr3wjjOAqahFmC3IaQCLWvur9nmfIn6LnWk=
github.com/KimMachineGun/automemlimit v0.7.4/go.mod h1:QZxpHaGOQoYvFhv/r4u3U0JTC2ZcOwbSr11UZF46UBM=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
@@ -108,8 +108,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI=
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHcQQP0w=
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.976/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA=
@@ -151,22 +151,22 @@ github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/blevesearch/bleve/v2 v2.5.5 h1:lzC89QUCco+y1qBnJxGqm4AbtsdsnlUvq0kXok8n3C8=
github.com/blevesearch/bleve/v2 v2.5.5/go.mod h1:t5WoESS5TDteTdnjhhvpA1BpLYErOBX2IQViTMLK7wo=
github.com/blevesearch/bleve_index_api v1.2.11 h1:bXQ54kVuwP8hdrXUSOnvTQfgK0KI1+f9A0ITJT8tX1s=
github.com/blevesearch/bleve_index_api v1.2.11/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/bleve/v2 v2.5.3 h1:9l1xtKaETv64SZc1jc4Sy0N804laSa/LeMbYddq1YEM=
github.com/blevesearch/bleve/v2 v2.5.3/go.mod h1:Z/e8aWjiq8HeX+nW8qROSxiE0830yQA071dwR3yoMzw=
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
github.com/blevesearch/go-faiss v1.0.26 h1:4dRLolFgjPyjkaXwff4NfbZFdE/dfywbzDqporeQvXI=
github.com/blevesearch/go-faiss v1.0.26/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
github.com/blevesearch/scorch_segment_api/v2 v2.3.13 h1:ZPjv/4VwWvHJZKeMSgScCapOy8+DdmsmRyLmSB88UoY=
github.com/blevesearch/scorch_segment_api/v2 v2.3.13/go.mod h1:ENk2LClTehOuMS8XzN3UxBEErYmtwkE7MAArFTXs9Vc=
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 h1:Yqk0XD1mE0fDZAJXTjawJ8If/85JxnLd8v5vG/jWE/s=
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
@@ -185,8 +185,8 @@ github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.2.7 h1:xcgFRa7f/tQXOwApVq7JWgPYSlzyUMmkuYa54tMDuR0=
github.com/blevesearch/zapx/v16 v16.2.7/go.mod h1:murSoCJPCk25MqURrcJaBQ1RekuqSCSfMjXH4rHyA14=
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
@@ -198,8 +198,8 @@ github.com/bufbuild/protocompile v0.14.1 h1:iA73zAf/fyljNjQKwYzUHD6AD4R8KMasmwa/
github.com/bufbuild/protocompile v0.14.1/go.mod h1:ppVdAIhbr2H8asPk6k4pY7t9zB1OU5DoEw9xY/FUi1c=
github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3 h1:h8Z0hBv5tg/uZMKu8V47+DKWYVQg0lYP8lXDQq7uRpE=
github.com/butonic/go-micro/v4 v4.11.1-0.20241115112658-b5d4de5ed9b3/go.mod h1:eE/tD53n3KbVrzrWxKLxdkGw45Fg1qaNLWjpJMvIUF4=
github.com/bytecodealliance/wasmtime-go/v39 v39.0.1 h1:RibaT47yiyCRxMOj/l2cvL8cWiWBSqDXHyqsa9sGcCE=
github.com/bytecodealliance/wasmtime-go/v39 v39.0.1/go.mod h1:miR4NYIEBXeDNamZIzpskhJ0z/p8al+lwMWylQ/ZJb4=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA=
github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q=
github.com/c-bata/go-prompt v0.2.5/go.mod h1:vFnjEGDIIA/Lib7giyE4E9c50Lvl8j0S+7FVlAwDAVw=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
@@ -210,8 +210,8 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/ceph/go-ceph v0.36.0 h1:IDE4vEF+4fmjve+CPjD1WStgfQ+Lh6vD+9PMUI712KI=
github.com/ceph/go-ceph v0.36.0/go.mod h1:fGCbndVDLuHW7q2954d6y+tgPFOBnRLqJRe2YXyngw4=
github.com/ceph/go-ceph v0.35.0 h1:wcDUbsjeNJ7OfbWCE7I5prqUL794uXchopw3IvrGQkk=
github.com/ceph/go-ceph v0.35.0/go.mod h1:ILF8WKhQQ2p2YuX1oWigkmsfT39U8T/HS2NrqxExq2s=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@@ -223,12 +223,6 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/clipperhouse/displaywidth v0.3.1 h1:k07iN9gD32177o1y4O1jQMzbLdCrsGJh+blirVYybsk=
github.com/clipperhouse/displaywidth v0.3.1/go.mod h1:tgLJKKyaDOCadywag3agw4snxS5kYEuYR6Y9+qWDDYM=
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY=
github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
@@ -239,19 +233,18 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
github.com/containerd/platforms v1.0.0-rc.2 h1:0SPgaNZPVWGEi4grZdV8VRYQn78y+nm6acgLGv/QzE4=
github.com/containerd/platforms v1.0.0-rc.2/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/containerd/platforms v1.0.0-rc.1 h1:83KIq4yy1erSRgOVHNk1HYdPvzdJ5CnsWaRoJX4C41E=
github.com/containerd/platforms v1.0.0-rc.1/go.mod h1:J71L7B+aiM5SdIEqmd9wp6THLVRzJGXfNuWCZCllLA4=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/coreos/go-oidc/v3 v3.15.0 h1:R6Oz8Z4bqWR7VFQ+sPSvZPQv4x8M+sJkDO5ojgwlyAg=
github.com/coreos/go-oidc/v3 v3.15.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4=
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cornelk/hashmap v1.0.8 h1:nv0AWgw02n+iDcawr5It4CjQIAcdMMKRrs10HOJYlrc=
github.com/cornelk/hashmap v1.0.8/go.mod h1:RfZb7JO3RviW/rT6emczVuC/oxpdz4UsSB2LJSclR1k=
@@ -310,8 +303,8 @@ github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
github.com/dnsimple/dnsimple-go v0.63.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
github.com/docker/docker v28.5.1+incompatible h1:Bm8DchhSD2J6PsFzxC35TZo4TLGR2PdW/E69rU45NhM=
github.com/docker/docker v28.5.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
@@ -352,26 +345,20 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fschade/icap-client v0.0.0-20240802074440-aade4a234387 h1:Y3wZgTr29sLxWSMz4KF91o0x87EaJF6FIPNJFepRIiw=
github.com/fschade/icap-client v0.0.0-20240802074440-aade4a234387/go.mod h1:HpntrRsQA6RKNXy2Nbr4kVj+NO3OYWpAQUVxeya+3sU=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0=
github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
github.com/gdexlab/go-render v1.0.1 h1:rxqB3vo5s4n1kF0ySmoNeSPRYkEsyHgln4jFIQY7v0U=
github.com/gdexlab/go-render v1.0.1/go.mod h1:wRi5nW2qfjiGj4mPukH4UV0IknS1cHD4VgFTmJX5JzM=
github.com/getkin/kin-openapi v0.13.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
github.com/ggwhite/go-masker v1.1.0 h1:kN/KIvktu2U+hd3KWrSlLj7xBGD1iBfc9/xdbVgFbRc=
github.com/ggwhite/go-masker v1.1.0/go.mod h1:xnTRHwrIU9FtBADwEjUC5Dy/BVedvoTxyOE7/d3CNwY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gkampitakis/ciinfo v0.3.2 h1:JcuOPk8ZU7nZQjdUhctuhQofk7BGHuIy0c9Ez8BNhXs=
github.com/gkampitakis/ciinfo v0.3.2/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
github.com/gkampitakis/go-snaps v0.5.15 h1:amyJrvM1D33cPHwVrjo9jQxX8g/7E2wYdZ+01KS3zGE=
github.com/gkampitakis/go-snaps v0.5.15/go.mod h1:HNpx/9GoKisdhw9AFOBT1N7DBs9DiHo/hGheFGBZ+mc=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-acme/lego/v4 v4.4.0 h1:uHhU5LpOYQOdp3aDU+XY2bajseu8fuExphTL1Ss6/Fc=
@@ -403,8 +390,8 @@ github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v3 v3.0.4 h1:Wp5HA7bLQcKnf6YYao/4kpRpVMp/yf6+pJKV8WFSaNY=
github.com/go-jose/go-jose/v3 v3.0.4/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI=
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
@@ -412,8 +399,8 @@ github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
github.com/go-ldap/ldap/v3 v3.4.12 h1:1b81mv7MagXZ7+1r7cLTWmyuTqVqdwbtJSjC0DAp9s4=
github.com/go-ldap/ldap/v3 v3.4.12/go.mod h1:+SPAGcTtOfmGsCb3h1RFiq4xpp4N636G75OEace8lNo=
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3 h1:sfz1YppV05y4sYaW7kXZtrocU/+vimnIWt4cxAYh7+o=
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3/go.mod h1:ZXFhGda43Z2TVbfGZefXyMJzsDHhCh0go3bZUcwTx7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@@ -456,8 +443,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4=
github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
@@ -486,11 +473,11 @@ github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM=
github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw=
github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
@@ -511,9 +498,8 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -546,8 +532,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/gomodule/redigo v1.9.3 h1:dNPSXeXv6HCq2jdyWfjgmhBdqnR6PRO3m/G05nvpPC8=
github.com/gomodule/redigo v1.9.3/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s=
github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
@@ -575,8 +561,8 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/go-tika v0.3.1 h1:l+jr10hDhZjcgxFRfcQChRLo1bPXQeLFluMyvDhXTTA=
github.com/google/go-tika v0.3.1/go.mod h1:DJh5N8qxXIl85QkqmXknd+PeeRkUOTbvwyYf7ieDz6c=
github.com/google/go-tpm v0.9.6 h1:Ku42PT4LmjDu1H5C5ISWLlpI1mj+Zq7sPGKoRw2XROA=
github.com/google/go-tpm v0.9.6/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/go-tpm v0.9.5 h1:ocUmnDebX54dnW+MQWGQRbdaAcJELsa6PqZhJ48KwVU=
github.com/google/go-tpm v0.9.5/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -590,8 +576,8 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.1 h1:HyOM6qd9gF9sf15AvhbptGHUnaLTpEI9akAFFU3VyW0=
github.com/google/renameio/v2 v2.0.1/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -624,8 +610,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vb
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -703,8 +689,6 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
github.com/jonboulle/clockwork v0.5.0/go.mod h1:3mZlmanh0g2NDKO5TWZVJAfofYk64M7XN3SzBPjZF60=
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
github.com/joshdk/go-junit v1.0.0/go.mod h1:TiiV0PqkaNfFXjEiyjWM3XXrhVyCa1K4Zfga6W52ung=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -728,25 +712,19 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4OxRzU=
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202 h1:A1xJ2NKgiYFiaHiLl9B5yw/gUBACSs9crDykTS3GuQI=
github.com/kobergj/gowebdav v0.0.0-20250102091030-aa65266db202/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXHetKXuInt4S7omeXUu62/A845kiycsSQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kovidgoyal/go-parallel v1.1.1 h1:1OzpNjtrUkBPq3UaqrnvOoB2F9RttSt811uiUXyI7ok=
github.com/kovidgoyal/go-parallel v1.1.1/go.mod h1:BJNIbe6+hxyFWv7n6oEDPj3PA5qSw5OCtf0hcVxWJiw=
github.com/kovidgoyal/go-shm v1.0.0 h1:HJEel9D1F9YhULvClEHJLawoRSj/1u/EDV7MJbBPgQo=
github.com/kovidgoyal/go-shm v1.0.0/go.mod h1:Yzb80Xf9L3kaoB2RGok9hHwMIt7Oif61kT6t3+VnZds=
github.com/kovidgoyal/imaging v1.8.17 h1:IDc7lbN2Qrn8s50y7Zt355HhOc+jUpvsScYAaGCW8vs=
github.com/kovidgoyal/imaging v1.8.17/go.mod h1:uD4XKN42lLV9du0TsPkwi53yw23vz/qDmfpiDWCSUCE=
github.com/kovidgoyal/imaging v1.6.4 h1:K0idhRPXnRrJBKnBYcTfI1HTWSNDeAn7hYDvf9I0dCk=
github.com/kovidgoyal/imaging v1.6.4/go.mod h1:bEIgsaZmXlvFfkv/CUxr9rJook6AQkJnpB5EPosRfRY=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -769,16 +747,12 @@ github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA=
github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
github.com/lestrrat-go/dsig v1.0.0 h1:OE09s2r9Z81kxzJYRn07TFM9XA4akrUdoMwr0L8xj38=
github.com/lestrrat-go/dsig v1.0.0/go.mod h1:dEgoOYYEJvW6XGbLasr8TFcAxoWrKlbQvmJgCR0qkDo=
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7gcrVVMFPOzY=
github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU=
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
github.com/lestrrat-go/httprc/v3 v3.0.1 h1:3n7Es68YYGZb2Jf+k//llA4FTZMl3yCwIjFIk4ubevI=
github.com/lestrrat-go/httprc/v3 v3.0.1/go.mod h1:2uAvmbXE4Xq8kAUjVrZOq1tZVYYYs5iP62Cmtru00xk=
github.com/lestrrat-go/jwx/v3 v3.0.12 h1:p25r68Y4KrbBdYjIsQweYxq794CtGCzcrc5dGzJIRjg=
github.com/lestrrat-go/jwx/v3 v3.0.12/go.mod h1:HiUSaNmMLXgZ08OmGBaPVvoZQgJVOQphSrGr5zMamS8=
github.com/lestrrat-go/httprc/v3 v3.0.0 h1:nZUx/zFg5uc2rhlu1L1DidGr5Sj02JbXvGSpnY4LMrc=
github.com/lestrrat-go/httprc/v3 v3.0.0/go.mod h1:k2U1QIiyVqAKtkffbg+cUmsyiPGQsb9aAfNQiNFuQ9Q=
github.com/lestrrat-go/jwx/v3 v3.0.10 h1:XuoCBhZBncRIjMQ32HdEc76rH0xK/Qv2wq5TBouYJDw=
github.com/lestrrat-go/jwx/v3 v3.0.10/go.mod h1:kNMedLgTpHvPJkK5EMVa1JFz+UVyY2dMmZKu3qjl/Pk=
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss=
@@ -804,8 +778,6 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
@@ -832,8 +804,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs=
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
@@ -843,22 +815,20 @@ github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b h1:Q53idHrTuQD
github.com/maxymania/go-system v0.0.0-20170110133659-647cc364bf0b/go.mod h1:KirJrATYGbTyUwVR26xIkaipRqRcMRXBf8N5dacvGus=
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103 h1:Z/i1e+gTZrmcGeZyWckaLfucYG6KYOXLWo4co8pZYNY=
github.com/mendsley/gojwk v0.0.0-20141217222730-4d5ec6e58103/go.mod h1:o9YPB5aGP8ob35Vy6+vyq3P3bWe7NQWzf+JLiXCiMaE=
github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE=
github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
github.com/mileusna/useragent v1.3.5 h1:SJM5NzBmh/hO+4LGeATKpaEX9+b4vcGg2qXGLiNGDws=
github.com/mileusna/useragent v1.3.5/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
github.com/minio/crc64nvme v1.1.0 h1:e/tAguZ+4cw32D+IO/8GSf5UVr9y+3eJcxZI2WOO/7Q=
github.com/minio/crc64nvme v1.1.0/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk=
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
github.com/minio/crc64nvme v1.0.2 h1:6uO1UxGAD+kwqWWp7mBFsi5gAse66C4NXO8cmcVculg=
github.com/minio/crc64nvme v1.0.2/go.mod h1:eVfm2fAzLlxMdUGc0EEBGSMmPwmXD5XiNRpnu9J3bvg=
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.97 h1:lqhREPyfgHTB/ciX8k2r8k0D93WaFqxbJX36UZq5occ=
github.com/minio/minio-go/v7 v7.0.97/go.mod h1:re5VXuo0pwEtoNLsNuSr0RrLfT/MBtohwdaSmPPSRSk=
github.com/minio/minio-go/v7 v7.0.95 h1:ywOUPg+PebTMTzn9VDsoFJy32ZuARN9zhB+K3IYEvYU=
github.com/minio/minio-go/v7 v7.0.95/go.mod h1:wOOX3uxS334vImCNRVyIDdXX9OsXDm89ToynKgqUKlo=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
@@ -898,9 +868,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8=
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@@ -912,12 +881,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g=
github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
github.com/nats-io/nats-server/v2 v2.12.2 h1:4TEQd0Y4zvcW0IsVxjlXnRso1hBkQl3TS0BI+SxgPhE=
github.com/nats-io/nats-server/v2 v2.12.2/go.mod h1:j1AAttYeu7WnvD8HLJ+WWKNMSyxsqmZ160pNtCQRMyE=
github.com/nats-io/nats.go v1.47.0 h1:YQdADw6J/UfGUd2Oy6tn4Hq6YHxCaJrVKayxxFqYrgM=
github.com/nats-io/nats.go v1.47.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/jwt/v2 v2.7.4 h1:jXFuDDxs/GQjGDZGhNgH4tXzSUK6WQi2rsj4xmsNOtI=
github.com/nats-io/jwt/v2 v2.7.4/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
github.com/nats-io/nats-server/v2 v2.11.9 h1:k7nzHZjUf51W1b08xiQih63Rdxh0yr5O4K892Mx5gQA=
github.com/nats-io/nats-server/v2 v2.11.9/go.mod h1:1MQgsAQX1tVjpf3Yzrk3x2pzdsZiNL/TVP3Amhp3CR8=
github.com/nats-io/nats.go v1.46.0 h1:iUcX+MLT0HHXskGkz+Sg20sXrPtJLsOojMDTDzOHSb8=
github.com/nats-io/nats.go v1.46.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g=
github.com/nats-io/nkeys v0.4.11 h1:q44qGV008kYd9W1b1nEBkNzvnWxtRSQ7A8BoqRrcfa0=
github.com/nats-io/nkeys v0.4.11/go.mod h1:szDimtgmfOi9n25JpfIdGw12tZFYXqhGxjhVxsatHVE=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
@@ -936,39 +905,33 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
github.com/oklog/run v1.2.0 h1:O8x3yXwah4A73hJdlrwo/2X6J62gE5qTMusH0dvz60E=
github.com/oklog/run v1.2.0/go.mod h1:mgDbKRSwPhJfesJ4PntqFUbKQRZ50NgmZTSPlFA0YFk=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc=
github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0=
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.1.2 h1:lkg/k/9mlsy0SxO5aC+WEpbdT5K83ddnNhAepz7TQc0=
github.com/olekukonko/ll v0.1.2/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew=
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/olekukonko/tablewriter v1.1.1 h1:b3reP6GCfrHwmKkYwNRFh2rxidGHcT6cgxj/sHiDDx0=
github.com/olekukonko/tablewriter v1.1.1/go.mod h1:De/bIcTF+gpBDB3Alv3fEsZA+9unTsSzAg/ZGADCtn4=
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw=
github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A=
github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k=
github.com/open-policy-agent/opa v1.11.1 h1:4bMlG6DjRZTRAswRyF+KUCgxHu1Gsk0h9EbZ4W9REvM=
github.com/open-policy-agent/opa v1.11.1/go.mod h1:QimuJO4T3KYxWzrmAymqlFvsIanCjKrGjmmC8GgAdgE=
github.com/open-policy-agent/opa v1.8.0 h1:4JdYuZcANeUF1v/87NGpirocpaZzJA0PcuL7xfmsMNM=
github.com/open-policy-agent/opa v1.8.0/go.mod h1:vOVZuIJQISnaYcZtQ58yTDkVCp1FmGPwK43pO9qPDqM=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a h1:Sakl76blJAaM6NxylVkgSzktjo2dS504iDotEFJsh3M=
github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY=
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+lP5lUUIzjRGDg93WrQfZJZCaV1ZP3KeyXi8bzY=
github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI=
github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9 h1:dIftlX03Bzfbujhp9B54FbgER0VBDWJi/w8RBxJlzxU=
github.com/opencloud-eu/inotifywaitgo v0.0.0-20251111171128-a390bae3c5e9/go.mod h1:JWyDC6H+5oZRdUJUgKuaye+8Ph5hEs6HVzVoPKzWSGI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76 h1:vD/EdfDUrv4omSFjrinT8Mvf+8D7f9g4vgQ2oiDrVUI=
github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20250724122329-41ba6b191e76/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q=
github.com/opencloud-eu/reva/v2 v2.41.0 h1:oie8+sxcA+drREXRTqm0LmfUdy/mmaa6pA6wkdF6tF4=
github.com/opencloud-eu/reva/v2 v2.41.0/go.mod h1:DGH08n2mvtsQLkt8o15FV6m51FwSJJGhjR8Ty+iIJww=
github.com/opencloud-eu/reva/v2 v2.38.1-0.20250924125540-eaa2437c36b2 h1:e3B6KbWMjloKpqoTwTwvBLoCETRyyCDkQsqwRQMUdxc=
github.com/opencloud-eu/reva/v2 v2.38.1-0.20250924125540-eaa2437c36b2/go.mod h1:8mGCM9tLIPsC5aEKS022Z5u89u6jKuOl0znK0gNFReM=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
@@ -985,6 +948,8 @@ github.com/orcaman/concurrent-map v1.0.0/go.mod h1:Lu3tH6HLW3feq74c2GC+jIMS/K2CF
github.com/ovh/go-ovh v1.1.0/go.mod h1:AxitLZ5HBRPyUd+Zl60Ajaag+rNTdVXWIkzfrVuTXWA=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pablodz/inotifywaitgo v0.0.9 h1:njquRbBU7fuwIe5rEvtaniVBjwWzcpdUVptSgzFqZsw=
github.com/pablodz/inotifywaitgo v0.0.9/go.mod h1:hAfx2oN+WKg8miwUKPs52trySpPignlRBRxWcXVHku0=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
@@ -992,8 +957,6 @@ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2D
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
@@ -1020,8 +983,10 @@ github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:Om
github.com/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k=
github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
github.com/pquerna/otp v1.3.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/alertmanager v0.29.0 h1:/ET4NmAGx2Dv9kStrXIBqBgHyiSgIk4OetY+hoZRfgc=
github.com/prometheus/alertmanager v0.29.0/go.mod h1:SjI2vhrfdWg10UaRUxTz27rgdJVG3HXrhI5WFjCdBgs=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/alertmanager v0.28.1 h1:BK5pCoAtaKg01BYRUJhEDV1tqJMEtYBGzPw8QdvnnvA=
github.com/prometheus/alertmanager v0.28.1/go.mod h1:0StpPUDDHi1VXeM7p2yYfeZgLVi/PPlt39vo9LQUHxM=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
@@ -1054,8 +1019,8 @@ github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.67.1 h1:OTSON1P4DNxzTg4hmKCc37o4ZAZDv0cfXLkOt0oEowI=
github.com/prometheus/common v0.67.1/go.mod h1:RpmT9v35q2Y+lsieQsdOh5sXZ6ajUGC8NjZAmr8vb0Q=
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
github.com/prometheus/procfs v0.0.0-20170703101242-e645f4e5aaa8/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@@ -1066,8 +1031,8 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI=
github.com/prometheus/statsd_exporter v0.22.8 h1:Qo2D9ZzaQG+id9i5NYNGmbf1aa/KxKbB9aKfMS+Yib0=
github.com/prometheus/statsd_exporter v0.22.8/go.mod h1:/DzwbTEaFTE0Ojz5PqcSk6+PFHOPWGxdXVr6yC8eFOM=
@@ -1076,10 +1041,13 @@ github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I=
github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 h1:bsUq1dX0N8AOIL7EB/X911+m4EHsnWEHeJ0c+3TTBrg=
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/riandyrn/otelchi v0.12.2 h1:6QhGv0LVw/dwjtPd12mnNrl0oEQF4ZAlmHcnlTYbeAg=
github.com/riandyrn/otelchi v0.12.2/go.mod h1:weZZeUJURvtCcbWsdb7Y6F8KFZGedJlSrgUjq9VirV8=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
@@ -1095,22 +1063,12 @@ github.com/russellhaering/goxmldsig v1.5.0/go.mod h1:x98CjQNFJcWfMxeOrMnMKg70lvD
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sacloud/libsacloud v1.36.2/go.mod h1:P7YAOVmnIn3DKHqCZcUKYUXmSwGBm3yS7IBEjKVSrjg=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
github.com/samber/lo v1.51.0 h1:kysRYLbHy/MB7kQZf5DSN50JHmMsNEdeY24VzJFu7wI=
github.com/samber/lo v1.51.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
github.com/samber/slog-common v0.19.0 h1:fNcZb8B2uOLooeYwFpAlKjkQTUafdjfqKcwcC89G9YI=
github.com/samber/slog-common v0.19.0/go.mod h1:dTz+YOU76aH007YUU0DffsXNsGFQRQllPQh9XyNoA3M=
github.com/samber/slog-zerolog/v2 v2.9.0 h1:6LkOabJmZdNLaUWkTC3IVVA+dq7b/V0FM6lz6/7+THI=
github.com/samber/slog-zerolog/v2 v2.9.0/go.mod h1:gnQW9VnCfM34v2pRMUIGMsZOVbYLqY/v0Wxu6atSVGc=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.7.0.20210127161313-bd30bebeac4f/go.mod h1:CJJ5VAbozOl0yEw7nHB9+7BXTJbIn6h7W+f6Gau5IP8=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/segmentio/kafka-go v0.4.49 h1:GJiNX1d/g+kG6ljyJEoi9++PUMdXGAxb7JGPiDCuNmk=
github.com/segmentio/kafka-go v0.4.49/go.mod h1:Y1gn60kzLEEaW28YshXyk2+VCUKbJ3Qr6DrnT3i4+9E=
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
@@ -1123,8 +1081,8 @@ github.com/sethvargo/go-diceware v0.5.0 h1:exrQ7GpaBo00GqRVM1N8ChXSsi3oS7tjQiIeh
github.com/sethvargo/go-diceware v0.5.0/go.mod h1:Lg1SyPS7yQO6BBgTN5r4f2MUDkqGfLWsOjHPY0kA8iw=
github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU=
github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs=
github.com/shamaton/msgpack/v2 v2.4.0 h1:O5Z08MRmbo0lA9o2xnQ4TXx6teJbPqEurqcCOQ8Oi/4=
github.com/shamaton/msgpack/v2 v2.4.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/shamaton/msgpack/v2 v2.3.1 h1:R3QNLIGA/tbdczNMZ5PCRxrXvy+fnzsIaHG4kKMgWYo=
github.com/shamaton/msgpack/v2 v2.3.1/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
@@ -1138,8 +1096,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0=
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/skratchdot/open-golang v0.0.0-20160302144031-75fb7ed4208c/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
@@ -1150,8 +1108,6 @@ github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:s
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/gunit v1.0.4/go.mod h1:EH5qMBab2UclzXUcpR8b93eHsIlp9u+pDQIRp5DZNzQ=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784 h1:0jjO3HdJfOn6gYHD/ZNZh0LLMxEAqkYX7xoDPQReEgs=
github.com/spacewander/go-suffix-tree v0.0.0-20191010040751-0865e368c784/go.mod h1:ff/5myEGgtsAwf26goQCO905GrEm5ugEZSd6OWTsrhM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
@@ -1161,8 +1117,6 @@ github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s=
github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0=
@@ -1170,13 +1124,10 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
@@ -1198,16 +1149,14 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/tchap/go-patricia/v2 v2.3.3 h1:xfNEsODumaEcCcY3gI0hYPZ/PcpVv5ju6RMAhgwZDDc=
github.com/tchap/go-patricia/v2 v2.3.3/go.mod h1:VZRHKAb53DLaG+nA9EaYYiaEx6YztwDlLElMsnSHD4k=
github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE=
github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU=
github.com/testcontainers/testcontainers-go v0.40.0 h1:pSdJYLOVgLE8YdUY2FHQ1Fxu+aMnb6JfVz1mxk7OeMU=
github.com/testcontainers/testcontainers-go v0.40.0/go.mod h1:FSXV5KQtX2HAMlm7U3APNyLkkap35zNLxukw9oBi/MY=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0 h1:3TIrGk0zXyO9CG2N6APo7auwWIwAvhkwE1reISif8LM=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.40.0/go.mod h1:VA0UCTPu+Gcs7MzdzBnSl0qDnxquuphv3ngSGdX97Xs=
github.com/testcontainers/testcontainers-go v0.39.0 h1:uCUJ5tA+fcxbFAB0uP3pIK3EJ2IjjDUHFSZ1H1UxAts=
github.com/testcontainers/testcontainers-go v0.39.0/go.mod h1:qmHpkG7H5uPf/EvOORKvS6EuDkBUPE3zpVGaH9NL7f8=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0 h1:IkJUhR8AigQxv7qHZho/OtTU6JtiSdBGVh76o175JGo=
github.com/testcontainers/testcontainers-go/modules/opensearch v0.39.0/go.mod h1:B7AhrDmQ4QbpzA0BeWvqzaJ8vbwcdEQDzybr35sBRfw=
github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o=
github.com/thanhpk/randstr v1.0.6/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
github.com/theckman/yacspin v0.13.12 h1:CdZ57+n0U6JMuh2xqjnjRq5Haj6v1ner2djtLQRzJr4=
@@ -1248,8 +1197,8 @@ github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXV
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.1.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/vektah/gqlparser/v2 v2.5.31 h1:YhWGA1mfTjID7qJhd1+Vxhpk5HTgydrGU9IgkWBTJ7k=
github.com/vektah/gqlparser/v2 v2.5.31/go.mod h1:c1I28gSOVNzlfc4WuDlqU7voQnsqI6OG2amkBAFmgts=
github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE=
github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
github.com/vinyldns/go-vinyldns v0.0.0-20200917153823-148a5f6b8f14/go.mod h1:RWc47jtnVuQv6+lY3c768WtXCas/Xi+U5UFc5xULmYg=
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
@@ -1291,12 +1240,12 @@ github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.etcd.io/etcd/api/v3 v3.6.6 h1:mcaMp3+7JawWv69p6QShYWS8cIWUOl32bFLb6qf8pOQ=
go.etcd.io/etcd/api/v3 v3.6.6/go.mod h1:f/om26iXl2wSkcTA1zGQv8reJRSLVdoEBsi4JdfMrx4=
go.etcd.io/etcd/client/pkg/v3 v3.6.6 h1:uoqgzSOv2H9KlIF5O1Lsd8sW+eMLuV6wzE3q5GJGQNs=
go.etcd.io/etcd/client/pkg/v3 v3.6.6/go.mod h1:YngfUVmvsvOJ2rRgStIyHsKtOt9SZI2aBJrZiWJhCbI=
go.etcd.io/etcd/client/v3 v3.6.6 h1:G5z1wMf5B9SNexoxOHUGBaULurOZPIgGPsW6CN492ec=
go.etcd.io/etcd/client/v3 v3.6.6/go.mod h1:36Qv6baQ07znPR3+n7t+Rk5VHEzVYPvFfGmfF4wBHV8=
go.etcd.io/etcd/api/v3 v3.6.4 h1:7F6N7toCKcV72QmoUKa23yYLiiljMrT4xCeBL9BmXdo=
go.etcd.io/etcd/api/v3 v3.6.4/go.mod h1:eFhhvfR8Px1P6SEuLT600v+vrhdDTdcfMzmnxVXXSbk=
go.etcd.io/etcd/client/pkg/v3 v3.6.4 h1:9HBYrjppeOfFjBjaMTRxT3R7xT0GLK8EJMVC4xg6ok0=
go.etcd.io/etcd/client/pkg/v3 v3.6.4/go.mod h1:sbdzr2cl3HzVmxNw//PH7aLGVtY4QySjQFuaCgcRFAI=
go.etcd.io/etcd/client/v3 v3.6.4 h1:YOMrCfMhRzY8NgtzUsHl8hC2EBSnuqbR3dh84Uryl7A=
go.etcd.io/etcd/client/v3 v3.6.4/go.mod h1:jaNNHCyg2FdALyKWnd7hxZXZxZANb0+KGY+YQaEMISo=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -1307,8 +1256,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
@@ -1317,14 +1266,14 @@ go.opentelemetry.io/contrib/zpages v0.63.0 h1:TppOKuZGbqXMgsfjqq3i09N5Vbo1JLtLIm
go.opentelemetry.io/contrib/zpages v0.63.0/go.mod h1:5F8uugz75ay/MMhRRhxAXY33FuaI8dl7jTxefrIy5qk=
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0 h1:kJxSDN4SgWWTjG/hPp3O7LCGLcHXFlvS2/FFOrwL+SE=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0/go.mod h1:mgIOzS7iZeKJdeB8/NYHrJ48fdGc71Llo5bJ1J4DWUE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA=
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
@@ -1338,6 +1287,8 @@ go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzK
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
@@ -1350,8 +1301,8 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.0.0-20180621125126-a49355c7e3f8/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -1375,8 +1326,8 @@ golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -1392,8 +1343,8 @@ golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScy
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/image v0.33.0 h1:LXRZRnv1+zGd5XBUVRFmYEphyyKJjQjCRiOuAP3sZfQ=
golang.org/x/image v0.33.0/go.mod h1:DD3OsTYT9chzuzTQt+zMcOlBHgfoKQb1gry8p76Y1sc=
golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA=
golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -1418,8 +1369,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk=
golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1473,8 +1424,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1482,8 +1433,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo=
golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1501,8 +1452,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1586,8 +1537,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1599,8 +1550,8 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -1615,16 +1566,16 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1679,14 +1630,14 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ=
golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ=
golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk=
golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
@@ -1744,10 +1695,10 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4=
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1763,8 +1714,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e h1:m7aQHHqd0q89mRwhwS9Bx2rjyl/hsFAeta+uGrHsQaU=
google.golang.org/grpc/examples v0.0.0-20211102180624-670c133e568e/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -1781,8 +1732,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=

View File

@@ -17,7 +17,7 @@ include ../.make/docs.mk
.PHONY: dev-docker
dev-docker:
docker build -f docker/Dockerfile.multiarch -t opencloudeu/opencloud:dev ../..
docker build -f docker/Dockerfile.multiarch -t opencloudeu/opencloud:dev ..
.PHONY: dev-docker-multiarch
dev-docker-multiarch:

View File

@@ -1,20 +1,19 @@
FROM golang:alpine3.22 AS build
FROM golang:alpine3.21 AS build
ARG TARGETOS
ARG TARGETARCH
ARG VERSION
ARG STRING
ARG EDITION="dev"
RUN apk add bash make git curl gcc musl-dev libc-dev binutils-gold inotify-tools vips-dev
WORKDIR /build
RUN --mount=type=bind,target=/build,rw \
WORKDIR /opencloud
RUN --mount=type=bind,target=/opencloud,rw\
--mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache \
GOOS="${TARGETOS:-linux}" GOARCH="${TARGETARCH:-amd64}" ; \
make -C opencloud/opencloud release-linux-docker-${TARGETARCH} ENABLE_VIPS=true DIST=/dist
cd opencloud && make -C opencloud release-linux-docker-${TARGETARCH} ENABLE_VIPS=true DIST=/dist
FROM alpine:3.22
FROM alpine:3.21
ARG VERSION
ARG REVISION
ARG TARGETOS

View File

@@ -4,8 +4,6 @@ import (
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/opencloud-eu/opencloud/opencloud/pkg/backup"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
@@ -13,34 +11,62 @@ import (
"github.com/opencloud-eu/opencloud/pkg/config/parser"
decomposedbs "github.com/opencloud-eu/reva/v2/pkg/storage/fs/decomposed/blobstore"
decomposeds3bs "github.com/opencloud-eu/reva/v2/pkg/storage/fs/decomposeds3/blobstore"
"github.com/urfave/cli/v2"
)
// BackupCommand is the entrypoint for the backup command
func BackupCommand(cfg *config.Config) *cobra.Command {
bckCmd := &cobra.Command{
Use: "backup",
Short: "OpenCloud backup functionality",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
func BackupCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "backup",
Usage: "OpenCloud backup functionality",
Subcommands: []*cli.Command{
ConsistencyCommand(cfg),
},
Before: func(c *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg, true))
},
Action: func(_ *cli.Context) error {
fmt.Println("Read the docs")
return nil
},
}
bckCmd.AddCommand(ConsistencyCommand(cfg))
return bckCmd
}
// ConsistencyCommand is the entrypoint for the consistency Command
func ConsistencyCommand(cfg *config.Config) *cobra.Command {
consCmd := &cobra.Command{
Use: "consistency",
Short: "check backup consistency",
RunE: func(cmd *cobra.Command, args []string) error {
func ConsistencyCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "consistency",
Usage: "check backup consistency",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "basepath",
Aliases: []string{"p"},
Usage: "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/users)",
Required: true,
},
&cli.StringFlag{
Name: "blobstore",
Aliases: []string{"b"},
Usage: "the blobstore type. Can be (none, decomposed, decomposeds3). Default decomposed",
Value: "decomposed",
},
&cli.BoolFlag{
Name: "fail",
Usage: "exit with non-zero status if consistency check fails",
},
},
Action: func(c *cli.Context) error {
basePath := c.String("basepath")
if basePath == "" {
fmt.Println("basepath is required")
return cli.ShowCommandHelp(c, "consistency")
}
var (
bs backup.ListBlobstore
err error
)
basePath, _ := cmd.Flags().GetString("basepath")
blobstoreFlag, _ := cmd.Flags().GetString("blobstore")
switch blobstoreFlag {
switch c.String("blobstore") {
case "decomposeds3":
bs, err = decomposeds3bs.New(
cfg.StorageUsers.Drivers.DecomposedS3.Endpoint,
@@ -61,8 +87,7 @@ func ConsistencyCommand(cfg *config.Config) *cobra.Command {
fmt.Println(err)
return err
}
fail, _ := cmd.Flags().GetBool("fail")
if err := backup.CheckProviderConsistency(basePath, bs, fail); err != nil {
if err := backup.CheckProviderConsistency(basePath, bs, c.Bool("fail")); err != nil {
fmt.Println(err)
return err
}
@@ -70,11 +95,6 @@ func ConsistencyCommand(cfg *config.Config) *cobra.Command {
return nil
},
}
consCmd.Flags().StringP("basepath", "p", "", "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/users)")
_ = consCmd.MarkFlagRequired("basepath")
consCmd.Flags().StringP("blobstore", "b", "decomposed", "the blobstore type. Can be (none, decomposed, decomposeds3). Default decomposed")
consCmd.Flags().Bool("fail", false, "exit with non-zero status if consistency check fails")
return consCmd
}
func init() {

View File

@@ -21,47 +21,105 @@ import (
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/pkg/xattr"
"github.com/rogpeppe/go-internal/lockedfile"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// BenchmarkCommand is the entrypoint for the benchmark commands.
func BenchmarkCommand(cfg *config.Config) *cobra.Command {
benchCmd := &cobra.Command{
Use: "benchmark",
Short: "cli tools to test low and high level performance",
func BenchmarkCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "benchmark",
Usage: "cli tools to test low and high level performance",
Category: "benchmark",
Subcommands: []*cli.Command{BenchmarkClientCommand(cfg), BenchmarkSyscallsCommand(cfg)},
}
benchCmd.AddCommand(BenchmarkClientCommand(cfg), BenchmarkSyscallsCommand(cfg))
return benchCmd
}
// BenchmarkClientCommand is the entrypoint for the benchmark client command.
func BenchmarkClientCommand(cfg *config.Config) *cobra.Command {
benchClientCmd := &cobra.Command{
Use: "client",
Short: "Start a client that continuously makes web requests and prints stats. The options mimic curl, but URL must be at the end.",
RunE: func(cmd *cobra.Command, args []string) error {
jobs, err := cmd.Flags().GetInt("jobs")
if err != nil {
return err
}
insecure, _ := cmd.Flags().GetBool("insecure")
func BenchmarkClientCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "client",
Usage: "Start a client that continuously makes web requests and prints stats. The options mimic curl, but URL must be at the end.",
Flags: []cli.Flag{
// TODO with v3 'flag.Persistent: true' can be set to make the order of flags no longer relevant \o/
// flags mimicing curl
&cli.StringFlag{
Name: "request",
Aliases: []string{"X"},
Value: "PROPFIND",
Usage: "Specifies a custom request method to use when communicating with the HTTP server.",
},
&cli.StringFlag{
Name: "user",
Aliases: []string{"u"},
Value: "admin:admin",
Usage: "Specify the user name and password to use for server authentication.",
},
&cli.BoolFlag{
Name: "insecure",
Aliases: []string{"k"},
Usage: "Skip the TLS verification step and proceed without checking.",
},
&cli.StringFlag{
Name: "data",
Aliases: []string{"d"},
Usage: "Sends the specified data in a request to the HTTP server.",
// TODE support multiple data flags, support data-binary, data-raw
},
&cli.StringSliceFlag{
Name: "header",
Aliases: []string{"H"},
Usage: "Extra header to include in information sent.",
},
&cli.StringFlag{
Name: "rate",
Usage: `Specify the maximum transfer frequency you allow a client to use - in number of transfer starts per time unit (sometimes called request rate).
The request rate is provided as "N/U" where N is an integer number and U is a time unit. Supported units are 's' (second), 'm' (minute), 'h' (hour) and 'd' /(day, as in a 24 hour unit). The default time unit, if no "/U" is provided, is number of transfers per hour.`,
},
/*
&cli.StringFlag{
Name: "oauth2-bearer",
Usage: "Specify the Bearer Token for OAUTH 2.0 server authentication.",
},
&cli.StringFlag{
Name: "user-agent",
Aliases: []string{"A"},
Value: "admin:admin",
Usage: "Specify the User-Agent string to send to the HTTP server.",
},
*/
// other flags
&cli.StringFlag{
Name: "bearer-token-command",
Usage: "Command to execute for a bearer token, e.g. 'oidc-token opencloud'. When set, disables basic auth.",
},
&cli.IntFlag{
Name: "every",
Usage: "Aggregate stats every time this amount of seconds has passed.",
},
&cli.IntFlag{
Name: "jobs",
Aliases: []string{"j"},
Value: 1,
Usage: "Number of parallel clients to start.",
},
},
Category: "benchmark",
Action: func(c *cli.Context) error {
opt := clientOptions{
request: cmd.Flag("request").Value.String(),
url: args[0],
insecure: insecure,
jobs: jobs,
request: c.String("request"),
url: c.Args().First(),
insecure: c.Bool("insecure"),
jobs: c.Int("jobs"),
headers: make(map[string]string),
data: []byte(cmd.Flag("data").Value.String()),
data: []byte(c.String("data")),
}
if opt.url == "" {
log.Fatal(errors.New("no URL specified"))
}
headersSlice, err := cmd.Flags().GetStringSlice("headers")
if err != nil {
return err
}
for _, h := range headersSlice {
for _, h := range c.StringSlice("headers") {
parts := strings.SplitN(h, ":", 2)
if len(parts) != 2 {
log.Fatal(errors.New("invalid header '" + h + "'"))
@@ -69,7 +127,7 @@ func BenchmarkClientCommand(cfg *config.Config) *cobra.Command {
opt.headers[parts[0]] = strings.TrimSpace(parts[1])
}
rate, _ := cmd.Flags().GetString("rate")
rate := c.String("rate")
if rate != "" {
parts := strings.SplitN(rate, "/", 2)
num, err := strconv.Atoi(parts[0])
@@ -92,12 +150,12 @@ func BenchmarkClientCommand(cfg *config.Config) *cobra.Command {
opt.rateDelay = unit / time.Duration(num)
}
user, _ := cmd.Flags().GetString("user")
user := c.String("user")
opt.auth = func() string {
return "Basic " + base64.StdEncoding.EncodeToString([]byte(user))
}
btc, _ := cmd.Flags().GetString("bearer-token-command")
btc := c.String("bearer-token-command")
if btc != "" {
parts := strings.SplitN(btc, " ", 2)
var cmd *exec.Cmd
@@ -115,10 +173,7 @@ func BenchmarkClientCommand(cfg *config.Config) *cobra.Command {
}
}
every, err := cmd.Flags().GetInt("every")
if err != nil {
return err
}
every := c.Int("every")
if every != 0 {
opt.ticker = time.NewTicker(time.Second * time.Duration(every))
defer opt.ticker.Stop()
@@ -128,22 +183,6 @@ func BenchmarkClientCommand(cfg *config.Config) *cobra.Command {
},
}
// TODO with v3 'flag.Persistent: true' can be set to make the order of flags no longer relevant \o/
// flags mimicing curl
benchClientCmd.Flags().StringP("request", "X", "PROPFIND", "Specifies a custom request method to use when communicating with the HTTP server.")
benchClientCmd.Flags().StringP("user", "u", "admin:admin", "Specify the user name and password to use for server authentication.")
benchClientCmd.Flags().BoolP("insecure", "k", false, "Skip the TLS verification step and proceed without checking.")
benchClientCmd.Flags().StringP("data", "d", "", "Sends the specified data in a request to the HTTP server.")
benchClientCmd.Flags().StringSliceP("headers", "H", []string{}, "Extra header to include in information sent.")
benchClientCmd.Flags().String("rate", "", "Specify the maximum transfer frequency you allow a client to use - in number of transfer starts per time unit (sometimes called request rate). The request rate is provided as \"N/U\" where N is an integer number and U is a time unit. Supported units are 's' (second), 'm' (minute), 'h' (hour) and 'd' /(day, as in a 24 hour unit). The default time unit, if no \"/U\" is provided, is number of transfers per hour.")
// other flags
benchClientCmd.Flags().IntP("jobs", "j", 1, "Number of parallel clients to start. Defaults to 1.")
benchClientCmd.Flags().Int("every", 0, "Aggregate stats every time this amount of seconds has passed.")
benchClientCmd.Flags().String("bearer-token-command", "", "Command to execute for a bearer token, e.g. 'oidc-token opencloud'. When set, disables basic auth.")
return benchClientCmd
}
type clientOptions struct {
@@ -241,13 +280,25 @@ func client(o clientOptions) error {
}
// BenchmarkSyscallsCommand is the entrypoint for the benchmark syscalls command.
func BenchmarkSyscallsCommand(cfg *config.Config) *cobra.Command {
benchSysCallCmd := &cobra.Command{
Use: "syscalls",
Short: "test the performance of syscalls",
RunE: func(cmd *cobra.Command, args []string) error {
func BenchmarkSyscallsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "syscalls",
Usage: "test the performance of syscalls",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "path",
Usage: "Path to test",
},
&cli.StringFlag{
Name: "iterations",
Value: "100",
Usage: "Number of iterations to execute",
},
},
Category: "benchmark",
Action: func(c *cli.Context) error {
path, _ := cmd.Flags().GetString("path")
path := c.String("path")
if path == "" {
f, err := os.CreateTemp("", "opencloud-bench-temp-")
if err != nil {
@@ -258,16 +309,11 @@ func BenchmarkSyscallsCommand(cfg *config.Config) *cobra.Command {
defer os.Remove(path)
}
iterations, err := cmd.Flags().GetInt("iterations")
if err != nil {
return err
}
iterations := c.Int("iterations")
return benchmark(iterations, path)
},
}
benchSysCallCmd.Flags().String("path", "", "Path to test")
benchSysCallCmd.Flags().Int("iterations", 100, "Number of iterations to execute")
return benchSysCallCmd
}
func benchmark(iterations int, path string) error {

View File

@@ -1,7 +0,0 @@
package command
const (
CommandGroupServer = "Server"
CommandGroupServices = "Service"
CommandGroupStorage = "Storage"
)

View File

@@ -9,6 +9,8 @@ import (
"sort"
"strings"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
@@ -23,57 +25,69 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/storage/pkg/decomposedfs/tree"
"github.com/opencloud-eu/reva/v2/pkg/storagespace"
"github.com/opencloud-eu/reva/v2/pkg/store"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// DecomposedfsCommand is the entrypoint for the groups command.
func DecomposedfsCommand(cfg *config.Config) *cobra.Command {
decomposedCmd := &cobra.Command{
Use: "decomposedfs",
Short: `cli tools to inspect and manipulate a decomposedfs storage.`,
GroupID: CommandGroupStorage,
func DecomposedfsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "decomposedfs",
Usage: `cli tools to inspect and manipulate a decomposedfs storage.`,
Category: "maintenance",
Subcommands: []*cli.Command{
metadataCmd(cfg),
checkCmd(cfg),
},
}
decomposedCmd.AddCommand(metadataCmd(cfg), checkCmd(cfg))
return decomposedCmd
}
func init() {
register.AddCommand(DecomposedfsCommand)
}
func checkCmd(_ *config.Config) *cobra.Command {
cCmd := &cobra.Command{
Use: "check-treesize",
Short: `cli tool to check the treesize metadata of a Space`,
RunE: check,
func checkCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "check-treesize",
Usage: `cli tool to check the treesize metadata of a Space`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "root",
Aliases: []string{"r"},
Required: true,
Usage: "Path to the root directory of the decomposedfs",
},
&cli.StringFlag{
Name: "node",
Required: true,
Aliases: []string{"n"},
Usage: "Space ID of the Space to inspect",
},
&cli.BoolFlag{
Name: "repair",
Usage: "Try to repair nodes with incorrect treesize metadata. IMPORTANT: Only use this while OpenCloud is not running.",
},
&cli.BoolFlag{
Name: "force",
Usage: "Do not prompt for confirmation when running in repair mode.",
},
},
Action: check,
}
cCmd.Flags().StringP("root", "r", "", "Path to the root directory of the decomposedfs")
_ = cCmd.MarkFlagRequired("root")
cCmd.Flags().StringP("node", "n", "", "Space ID of the Space to inspect")
_ = cCmd.MarkFlagRequired("node")
cCmd.Flags().Bool("repair", false, "Try to repair nodes with incorrect treesize metadata. IMPORTANT: Only use this while OpenCloud is not running.")
cCmd.Flags().Bool("force", false, "Do not prompt for confirmation when running in repair mode.")
return cCmd
}
func check(cmd *cobra.Command, args []string) error {
rootFlag, _ := cmd.Flags().GetString("root")
repairFlag, _ := cmd.Flags().GetBool("repair")
forceFlag, _ := cmd.Flags().GetBool("force")
func check(c *cli.Context) error {
rootFlag := c.String("root")
repairFlag := c.Bool("repair")
if repairFlag && !forceFlag {
if repairFlag && !c.Bool("force") {
answer := strings.ToLower(stringPrompt("IMPORTANT: Only use '--repair' when OpenCloud is not running. Do you want to continue? [yes | no = default]"))
if answer != "yes" && answer != "y" {
return nil
}
}
lu, backend := getBackend(cmd)
lu, backend := getBackend(c)
o := &options.Options{
MetadataBackend: backend.Name(),
MaxConcurrency: 100,
@@ -86,7 +100,7 @@ func check(cmd *cobra.Command, args []string) error {
tree := tree.New(lu, bs, o, permissions.Permissions{}, store.Create(), &zerolog.Logger{})
nId, _ := cmd.Flags().GetString("node")
nId := c.String("node")
n, err := lu.NodeFromSpaceID(context.Background(), nId)
if err != nil || !n.Exists {
fmt.Println("Can not find node '" + nId + "'")
@@ -102,10 +116,7 @@ func check(cmd *cobra.Command, args []string) error {
})
treeSize, err := walkTree(ctx, tree, lu, n, repairFlag)
if err != nil {
fmt.Printf("failed to walk tree of node %s: %s\n", n.ID, err)
}
treesizeFromMetadata, err := n.GetTreeSize(cmd.Context())
treesizeFromMetadata, err := n.GetTreeSize(c.Context)
if err != nil {
fmt.Printf("failed to read treesize of node: %s: %s\n", n.ID, err)
}
@@ -115,7 +126,7 @@ func check(cmd *cobra.Command, args []string) error {
if repairFlag {
fmt.Printf("Fixing tree size for node: %s. Calculated treesize: %d\n",
n.ID, treeSize)
n.SetTreeSize(cmd.Context(), treeSize)
n.SetTreeSize(c.Context, treeSize)
}
}
return nil
@@ -174,79 +185,105 @@ func walkTree(ctx context.Context, tree *tree.Tree, lu *lookup.Lookup, root *nod
return treesize, nil
}
func metadataCmd(cfg *config.Config) *cobra.Command {
metaCmd := &cobra.Command{
Use: "metadata",
Short: `cli tools to inspect and manipulate node metadata`,
func metadataCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "metadata",
Usage: `cli tools to inspect and manipulate node metadata`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "root",
Aliases: []string{"r"},
Required: true,
Usage: "Path to the decomposedfs",
},
&cli.StringFlag{
Name: "node",
Required: true,
Aliases: []string{"n"},
Usage: "Path to or ID of the node to inspect",
},
},
Subcommands: []*cli.Command{dumpCmd(cfg), getCmd(cfg), setCmd(cfg)},
}
metaCmd.AddCommand(dumpCmd(cfg), getCmd(cfg), setCmd(cfg))
metaCmd.Flags().StringP("root", "r", "", "Path to the root directory of the decomposedfs")
_ = metaCmd.MarkFlagRequired("root")
metaCmd.Flags().StringP("node", "n", "", "Path to or ID of the node to inspect")
_ = metaCmd.MarkFlagRequired("node")
return metaCmd
}
func dumpCmd(_ *config.Config) *cobra.Command {
return &cobra.Command{
Use: "dump",
Short: `print the metadata of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.`,
RunE: func(cmd *cobra.Command, args []string) error {
lu, backend := getBackend(cmd)
path, err := getNode(cmd, lu)
func dumpCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "dump",
Usage: `print the metadata of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.`,
Action: func(c *cli.Context) error {
lu, backend := getBackend(c)
path, err := getNode(c, lu)
if err != nil {
return err
}
attribs, err := backend.All(cmd.Context(), path)
attribs, err := backend.All(c.Context, path)
if err != nil {
fmt.Println("Error reading attributes")
return err
}
attributeFlag, _ := cmd.Flags().GetString("attribute")
printAttribs(attribs, attributeFlag)
printAttribs(attribs, c.String("attribute"))
return nil
},
}
}
func getCmd(_ *config.Config) *cobra.Command {
gCmd := &cobra.Command{
Use: "get",
Short: `print a specific attribute of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.`,
RunE: func(cmd *cobra.Command, args []string) error {
lu, backend := getBackend(cmd)
path, err := getNode(cmd, lu)
func getCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "get",
Usage: `print a specific attribute of the given node. String attributes will be enclosed in quotes. Binary attributes will be returned encoded as base64 with their value being prefixed with '0s'.`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "attribute",
Aliases: []string{"a"},
Usage: "attribute to inspect",
},
},
Action: func(c *cli.Context) error {
lu, backend := getBackend(c)
path, err := getNode(c, lu)
if err != nil {
return err
}
attribs, err := backend.All(cmd.Context(), path)
attribs, err := backend.All(c.Context, path)
if err != nil {
fmt.Println("Error reading attributes")
return err
}
attributeFlag, _ := cmd.Flags().GetString("attribute")
printAttribs(attribs, attributeFlag)
printAttribs(attribs, c.String("attribute"))
return nil
},
}
gCmd.Flags().StringP("attribute", "a", "", "attribute to inspect, can be a glob pattern (e.g. 'user.*' will match all attributes starting with 'user.').")
return gCmd
}
func setCmd(_ *config.Config) *cobra.Command {
sCmd := &cobra.Command{
Use: "set",
Short: `manipulate metadata of the given node. Binary attributes can be given hex encoded (prefix by '0x') or base64 encoded (prefix by '0s').`,
RunE: func(cmd *cobra.Command, args []string) error {
lu, backend := getBackend(cmd)
n, err := getNode(cmd, lu)
func setCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "set",
Usage: `manipulate metadata of the given node. Binary attributes can be given hex encoded (prefix by '0x') or base64 encoded (prefix by '0s').`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "attribute",
Required: true,
Aliases: []string{"a"},
Usage: "attribute to inspect",
},
&cli.StringFlag{
Name: "value",
Required: true,
Aliases: []string{"v"},
Usage: "value to set",
},
},
Action: func(c *cli.Context) error {
lu, backend := getBackend(c)
n, err := getNode(c, lu)
if err != nil {
return err
}
v, _ := cmd.Flags().GetString("value")
v := c.String("value")
if strings.HasPrefix(v, "0s") {
b64, err := base64.StdEncoding.DecodeString(v[2:])
if err == nil {
@@ -263,8 +300,7 @@ func setCmd(_ *config.Config) *cobra.Command {
}
}
attributeFlag, _ := cmd.Flags().GetString("attribute")
err = backend.Set(cmd.Context(), n, attributeFlag, []byte(v))
err = backend.Set(c.Context, n, c.String("attribute"), []byte(v))
if err != nil {
fmt.Println("Error setting attribute")
return err
@@ -272,16 +308,9 @@ func setCmd(_ *config.Config) *cobra.Command {
return nil
},
}
sCmd.Flags().StringP("attribute", "a", "", "attribute to inspect, can be a glob pattern (e.g. 'user.*' will match all attributes starting with 'user.').")
_ = sCmd.MarkFlagRequired("attribute")
sCmd.Flags().StringP("value", "v", "", "value to set")
_ = sCmd.MarkFlagRequired("value")
return sCmd
}
func backend(backend string) metadata.Backend {
func backend(root, backend string) metadata.Backend {
switch backend {
case "xattrs":
return metadata.NewXattrsBackend(cache.Config{})
@@ -291,11 +320,11 @@ func backend(backend string) metadata.Backend {
return metadata.NullBackend{}
}
func getBackend(cmd *cobra.Command) (*lookup.Lookup, metadata.Backend) {
rootFlag, _ := cmd.Flags().GetString("root")
func getBackend(c *cli.Context) (*lookup.Lookup, metadata.Backend) {
rootFlag := c.String("root")
bod := lookup.DetectBackendOnDisk(rootFlag)
backend := backend(bod)
backend := backend(rootFlag, bod)
lu := lookup.New(backend, &options.Options{
Root: rootFlag,
MetadataBackend: bod,
@@ -303,8 +332,8 @@ func getBackend(cmd *cobra.Command) (*lookup.Lookup, metadata.Backend) {
return lu, backend
}
func getNode(cmd *cobra.Command, lu *lookup.Lookup) (*node.Node, error) {
nodeFlag, _ := cmd.Flags().GetString("node")
func getNode(c *cli.Context, lu *lookup.Lookup) (*node.Node, error) {
nodeFlag := c.String("node")
id, err := storagespace.ParseID(nodeFlag)
if err != nil {

View File

@@ -0,0 +1,9 @@
package helper
import (
"fmt"
)
func SubcommandDescription(serviceName string) string {
return fmt.Sprintf("%s service commands", serviceName)
}

View File

@@ -11,19 +11,49 @@ import (
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/defaults"
"github.com/spf13/cobra"
"github.com/spf13/viper"
cli "github.com/urfave/cli/v2"
)
// InitCommand is the entrypoint for the init command
func InitCommand(_ *config.Config) *cobra.Command {
initCmd := &cobra.Command{
Use: "init",
Short: "initialise an OpenCloud config",
GroupID: CommandGroupServer,
RunE: func(cmd *cobra.Command, args []string) error {
insecureFlag := viper.GetString("insecure")
func InitCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "init",
Usage: "initialise an OpenCloud config",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "insecure",
EnvVars: []string{"OC_INSECURE"},
Value: "ask",
Usage: "Allow insecure OpenCloud config",
},
&cli.BoolFlag{
Name: "diff",
Aliases: []string{"d"},
Usage: "Show the difference between the current config and the new one",
Value: false,
},
&cli.BoolFlag{
Name: "force-overwrite",
Aliases: []string{"f"},
EnvVars: []string{"OC_FORCE_CONFIG_OVERWRITE"},
Value: false,
Usage: "Force overwrite existing config file",
},
&cli.StringFlag{
Name: "config-path",
Value: defaults.BaseConfigPath(),
Usage: "Config path for the OpenCloud runtime",
EnvVars: []string{"OC_CONFIG_DIR", "OC_BASE_DATA_PATH"},
},
&cli.StringFlag{
Name: "admin-password",
Aliases: []string{"ap"},
EnvVars: []string{"ADMIN_PASSWORD", "IDM_ADMIN_PASSWORD"},
Usage: "Set admin password instead of using a random generated one",
},
},
Action: func(c *cli.Context) error {
insecureFlag := c.String("insecure")
insecure := false
if insecureFlag == "ask" {
answer := strings.ToLower(stringPrompt("Do you want to configure OpenCloud with certificate checking disabled?\n This is not recommended for public instances! [yes | no = default]"))
@@ -33,37 +63,13 @@ func InitCommand(_ *config.Config) *cobra.Command {
} else if insecureFlag == strings.ToLower("true") || insecureFlag == strings.ToLower("yes") || insecureFlag == strings.ToLower("y") {
insecure = true
}
forceOverwriteFlag := viper.GetBool("force-overwrite")
diffFlag, _ := cmd.Flags().GetBool("diff")
configPathFlag := viper.GetString("config-path")
adminPasswordFlag := viper.GetString("admin-password")
err := ocinit.CreateConfig(insecure, forceOverwriteFlag, diffFlag, configPathFlag, adminPasswordFlag)
err := ocinit.CreateConfig(insecure, c.Bool("force-overwrite"), c.Bool("diff"), c.String("config-path"), c.String("admin-password"))
if err != nil {
log.Fatalf("Could not create config: %s", err)
}
return nil
},
}
initCmd.Flags().String("insecure", "ask", "Allow insecure OpenCloud config")
_ = viper.BindEnv("insecure", "OC_INSECURE")
_ = viper.BindPFlag("insecure", initCmd.Flags().Lookup("insecure"))
initCmd.Flags().BoolP("diff", "d", false, "Show the difference between the current config and the new one")
initCmd.Flags().BoolP("force-overwrite", "f", false, "Force overwrite existing config file")
_ = viper.BindEnv("force-overwrite", "OC_FORCE_CONFIG_OVERWRITE")
_ = viper.BindPFlag("force-overwrite", initCmd.Flags().Lookup("force-overwrite"))
initCmd.Flags().String("config-path", defaults.BaseConfigPath(), "Config path for the OpenCloud runtime")
_ = viper.BindEnv("config-path", "OC_CONFIG_DIR")
_ = viper.BindEnv("config-path", "OC_BASE_DATA_PATH")
_ = viper.BindPFlag("config-path", initCmd.Flags().Lookup("config-path"))
initCmd.Flags().String("admin-password", "", "Set admin password instead of using a random generated one")
_ = viper.BindEnv("admin-password", "ADMIN_PASSWORD")
_ = viper.BindEnv("admin-password", "IDM_ADMIN_PASSWORD")
_ = viper.BindPFlag("admin-password", initCmd.Flags().Lookup("admin-password"))
return initCmd
}
func init() {
@@ -74,7 +80,7 @@ func stringPrompt(label string) string {
input := ""
reader := bufio.NewReader(os.Stdin)
for {
_, _ = fmt.Fprint(os.Stderr, label+" ")
fmt.Fprint(os.Stderr, label+" ")
input, _ = reader.ReadString('\n')
if input != "" {
break

View File

@@ -8,26 +8,31 @@ import (
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/config/parser"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/urfave/cli/v2"
)
// ListCommand is the entrypoint for the list command.
func ListCommand(cfg *config.Config) *cobra.Command {
listCmd := &cobra.Command{
Use: "list",
Short: "list OpenCloud services running in the runtime (supervised mode)",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return configlog.ReturnError(parser.ParseConfig(cfg, true))
func ListCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "list",
Usage: "list OpenCloud services running in the runtime (supervised mode)",
Category: "runtime",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "hostname",
Value: "localhost",
EnvVars: []string{"OC_RUNTIME_HOST"},
Destination: &cfg.Runtime.Host,
},
&cli.StringFlag{
Name: "port",
Value: "9250",
EnvVars: []string{"OC_RUNTIME_PORT"},
Destination: &cfg.Runtime.Port,
},
},
RunE: func(cmd *cobra.Command, args []string) error {
host := viper.GetString("hostname")
port := viper.GetString("port")
client, err := rpc.DialHTTP("tcp", net.JoinHostPort(host, port))
Action: func(c *cli.Context) error {
client, err := rpc.DialHTTP("tcp", net.JoinHostPort(cfg.Runtime.Host, cfg.Runtime.Port))
if err != nil {
log.Fatalf("Failed to connect to the runtime. Has the runtime been started and did you configure the right runtime address (\"%s\")", cfg.Runtime.Host+":"+cfg.Runtime.Port)
}
@@ -43,15 +48,6 @@ func ListCommand(cfg *config.Config) *cobra.Command {
return nil
},
}
listCmd.Flags().String("hostname", "localhost", "hostname of the runtime")
_ = viper.BindEnv("hostname", "OC_RUNTIME_HOST")
_ = viper.BindPFlag("hostname", listCmd.Flags().Lookup("hostname"))
listCmd.Flags().String("port", "9250", "port of the runtime")
_ = viper.BindEnv("port", "OC_RUNTIME_PORT")
_ = viper.BindPFlag("port", listCmd.Flags().Lookup("port"))
return listCmd
}
func init() {

View File

@@ -10,10 +10,9 @@ import (
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/pkg/xattr"
"github.com/spf13/cobra"
"github.com/theckman/yacspin"
"github.com/urfave/cli/v2"
"github.com/vmihailenco/msgpack/v5"
)
@@ -38,16 +37,15 @@ type EntryInfo struct {
}
// PosixfsCommand is the entrypoint for the posixfs command.
func PosixfsCommand(cfg *config.Config) *cobra.Command {
posixCmd := &cobra.Command{
Use: "posixfs",
Short: `cli tools to inspect and manipulate a posixfs storage.`,
GroupID: CommandGroupStorage,
func PosixfsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "posixfs",
Usage: `cli tools to inspect and manipulate a posixfs storage.`,
Category: "maintenance",
Subcommands: []*cli.Command{
consistencyCmd(cfg),
},
}
posixCmd.AddCommand(consistencyCmd(cfg))
return posixCmd
}
func init() {
@@ -55,23 +53,27 @@ func init() {
}
// consistencyCmd returns a command to check the consistency of the posixfs storage.
func consistencyCmd(cfg *config.Config) *cobra.Command {
consCmd := &cobra.Command{
Use: "consistency",
Short: "check the consistency of the posixfs storage",
RunE: func(cmd *cobra.Command, args []string) error {
return checkPosixfsConsistency(cmd, cfg)
func consistencyCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "consistency",
Usage: "check the consistency of the posixfs storage",
Action: func(c *cli.Context) error {
return checkPosixfsConsistency(c, cfg)
},
Flags: []cli.Flag{
&cli.StringFlag{
Name: "root",
Aliases: []string{"r"},
Required: true,
Usage: "Path to the root directory of the posixfs storage",
},
},
}
consCmd.Flags().StringP("root", "r", "", "Path to the root directory of the posixfs storage")
_ = consCmd.MarkFlagRequired("root")
return consCmd
}
// checkPosixfsConsistency checks the consistency of the posixfs storage.
func checkPosixfsConsistency(cmd *cobra.Command, cfg *config.Config) error {
rootPath, _ := cmd.Flags().GetString("root")
func checkPosixfsConsistency(c *cli.Context, cfg *config.Config) error {
rootPath := c.String("root")
indexesPath := filepath.Join(rootPath, "indexes")
_, err := os.Stat(indexesPath)

View File

@@ -6,7 +6,6 @@ import (
"path/filepath"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/opencloud/pkg/revisions"
"github.com/opencloud-eu/opencloud/pkg/config"
@@ -16,8 +15,7 @@ import (
decomposeds3bs "github.com/opencloud-eu/reva/v2/pkg/storage/fs/decomposeds3/blobstore"
"github.com/opencloud-eu/reva/v2/pkg/storage/fs/posix/lookup"
"github.com/opencloud-eu/reva/v2/pkg/storagespace"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
var (
@@ -26,33 +24,75 @@ var (
)
// RevisionsCommand is the entrypoint for the revisions command.
func RevisionsCommand(cfg *config.Config) *cobra.Command {
revCmd := &cobra.Command{
Use: "revisions",
Short: "OpenCloud revisions functionality",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
func RevisionsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "revisions",
Usage: "OpenCloud revisions functionality",
Subcommands: []*cli.Command{
PurgeRevisionsCommand(cfg),
},
Before: func(_ *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg, true))
},
Action: func(_ *cli.Context) error {
fmt.Println("Read the docs")
return nil
},
}
revCmd.AddCommand(PurgeRevisionsCommand(cfg))
return revCmd
}
// PurgeRevisionsCommand allows removing all revisions from a storage provider.
func PurgeRevisionsCommand(cfg *config.Config) *cobra.Command {
revCmd := &cobra.Command{
Use: "purge",
Short: "purge revisions",
RunE: func(cmd *cobra.Command, args []string) error {
basePath, _ := cmd.Flags().GetString("basepath")
func PurgeRevisionsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "purge",
Usage: "purge revisions",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "basepath",
Aliases: []string{"p"},
Usage: "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/metadata)",
Required: true,
},
&cli.StringFlag{
Name: "blobstore",
Aliases: []string{"b"},
Usage: "the blobstore type. Can be (none, decomposed, decomposeds3). Default decomposed. Note: When using decomposeds3 this needs same configuration as the storage-users service",
Value: "decomposed",
},
&cli.BoolFlag{
Name: "dry-run",
Usage: "do not delete anything, just print what would be deleted",
Value: true,
},
&cli.BoolFlag{
Name: "verbose",
Aliases: []string{"v"},
Usage: "print verbose output",
Value: false,
},
&cli.StringFlag{
Name: "resource-id",
Aliases: []string{"r"},
Usage: "purge all revisions of this file/space. If not set, all revisions will be purged",
},
&cli.StringFlag{
Name: "glob-mechanism",
Usage: "the glob mechanism to find all nodes. Can be 'glob', 'list' or 'workers'. 'glob' uses globbing with a single worker. 'workers' spawns multiple go routines, accelatering the command drastically but causing high cpu and ram usage. 'list' looks for references by listing directories with multiple workers. Default is 'glob'",
Value: "glob",
},
},
Action: func(c *cli.Context) error {
basePath := c.String("basepath")
if basePath == "" {
fmt.Println("basepath is required")
return cli.ShowCommandHelp(c, "revisions")
}
var (
bs revisions.DelBlobstore
err error
)
blobstoreFlag, _ := cmd.Flags().GetString("blobstore")
switch blobstoreFlag {
switch c.String("blobstore") {
case "decomposeds3":
bs, err = decomposeds3bs.New(
cfg.StorageUsers.Drivers.DecomposedS3.Endpoint,
@@ -75,13 +115,12 @@ func PurgeRevisionsCommand(cfg *config.Config) *cobra.Command {
}
var rid *provider.ResourceId
resourceIDFlag, _ := cmd.Flags().GetString("resource-id")
resid, err := storagespace.ParseID(resourceIDFlag)
resid, err := storagespace.ParseID(c.String("resource-id"))
if err == nil {
rid = &resid
}
mechanism, _ := cmd.Flags().GetString("glob-mechanism")
mechanism := c.String("glob-mechanism")
if rid.GetOpaqueId() != "" {
mechanism = "glob"
}
@@ -107,30 +146,11 @@ func PurgeRevisionsCommand(cfg *config.Config) *cobra.Command {
ch = revisions.List(p, 10)
}
flagDryRun, err := cmd.Flags().GetBool("dry-run")
if err != nil {
return err
}
flagVerbose, err := cmd.Flags().GetBool("verbose")
if err != nil {
return err
}
files, blobs, revisionResults := revisions.PurgeRevisions(ch, bs, flagDryRun, flagVerbose)
printResults(files, blobs, revisionResults, flagDryRun)
files, blobs, revisions := revisions.PurgeRevisions(ch, bs, c.Bool("dry-run"), c.Bool("verbose"))
printResults(files, blobs, revisions, c.Bool("dry-run"))
return nil
},
}
revCmd.Flags().StringP("basepath", "p", "", "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/metadata)")
_ = revCmd.MarkFlagRequired("basepath")
revCmd.Flags().StringP("blobstore", "b", "decomposed", "the blobstore type. Can be (none, decomposed, decomposeds3). Default decomposed")
revCmd.Flags().Bool("dry-run", true, "do not delete anything, just print what would be deleted")
revCmd.Flags().BoolP("verbose", "v", false, "print verbose output")
revCmd.Flags().StringP("resource-id", "r", "", "purge all revisions of this file/space. If not set, all revisions will be purged")
revCmd.Flags().String("glob-mechanism", "glob", "the glob mechanism to find all nodes. Can be 'glob', 'list' or 'workers'. 'glob' uses globbing with a single worker. 'workers' spawns multiple go routines, accelatering the command drastically but causing high cpu and ram usage. 'list' looks for references by listing directories with multiple workers. Default is 'glob'")
return revCmd
}
func printResults(countFiles, countBlobs, countRevisions int, dryRun bool) {

View File

@@ -9,32 +9,25 @@ import (
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/clihelper"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// Execute is the entry point for the opencloud command.
func Execute() error {
cfg := config.DefaultConfig()
app := clihelper.DefaultApp(&cobra.Command{
Use: "opencloud",
Short: "opencloud",
app := clihelper.DefaultApp(&cli.App{
Name: "opencloud",
Usage: "opencloud",
})
for _, commandFactory := range register.Commands {
command := commandFactory(cfg)
if command.GroupID != "" && !app.ContainsGroup(command.GroupID) {
app.AddGroup(&cobra.Group{
ID: command.GroupID,
Title: command.GroupID,
})
}
app.AddCommand(command)
for _, fn := range register.Commands {
app.Commands = append(
app.Commands,
fn(cfg),
)
}
app.SetArgs(os.Args[1:])
ctx, _ := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
return app.ExecuteContext(ctx)
return app.RunContext(ctx, os.Args)
}

View File

@@ -6,23 +6,22 @@ import (
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/config/parser"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// Server is the entrypoint for the server command.
func Server(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "server",
Short: "start a fullstack server (runtime and all services in supervised mode)",
PreRunE: func(cmd *cobra.Command, args []string) error {
func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "server",
Usage: "start a fullstack server (runtime and all services in supervised mode)",
Category: "fullstack",
Before: func(c *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg, false))
},
GroupID: CommandGroupServer,
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
// Prefer the in-memory registry as the default when running in single-binary mode
r := runtime.New(cfg)
return r.Start(cmd.Context())
return r.Start(c.Context)
},
}
}

View File

@@ -1,8 +1,9 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
"github.com/opencloud-eu/opencloud/opencloud/pkg/command/helper"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
@@ -49,243 +50,238 @@ import (
web "github.com/opencloud-eu/opencloud/services/web/pkg/command"
webdav "github.com/opencloud-eu/opencloud/services/webdav/pkg/command"
webfinger "github.com/opencloud-eu/opencloud/services/webfinger/pkg/command"
"github.com/spf13/cobra"
)
var serviceCommands = []register.Command{
func(cfg *config.Config) *cobra.Command {
var svccmds = []register.Command{
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Activitylog.Service.Name, activitylog.GetCommands(cfg.Activitylog), func(c *config.Config) {
cfg.Activitylog.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Antivirus.Service.Name, antivirus.GetCommands(cfg.Antivirus), func(c *config.Config) {
cfg.Antivirus.Commons = cfg.Commons
// cfg.Antivirus.Commons = cfg.Commons // antivirus needs no commons atm
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AppProvider.Service.Name, appprovider.GetCommands(cfg.AppProvider), func(c *config.Config) {
cfg.AppProvider.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AppRegistry.Service.Name, appregistry.GetCommands(cfg.AppRegistry), func(c *config.Config) {
cfg.AppRegistry.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Audit.Service.Name, audit.GetCommands(cfg.Audit), func(c *config.Config) {
cfg.Audit.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AuthApp.Service.Name, authapp.GetCommands(cfg.AuthApp), func(_ *config.Config) {
cfg.AuthApp.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AuthBasic.Service.Name, authbasic.GetCommands(cfg.AuthBasic), func(c *config.Config) {
cfg.AuthBasic.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AuthBearer.Service.Name, authbearer.GetCommands(cfg.AuthBearer), func(c *config.Config) {
cfg.AuthBearer.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AuthMachine.Service.Name, authmachine.GetCommands(cfg.AuthMachine), func(c *config.Config) {
cfg.AuthMachine.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.AuthService.Service.Name, authservice.GetCommands(cfg.AuthService), func(c *config.Config) {
cfg.AuthService.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Clientlog.Service.Name, clientlog.GetCommands(cfg.Clientlog), func(c *config.Config) {
cfg.Clientlog.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Collaboration.Service.Name, collaboration.GetCommands(cfg.Collaboration), func(c *config.Config) {
cfg.Collaboration.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.EventHistory.Service.Name, eventhistory.GetCommands(cfg.EventHistory), func(c *config.Config) {
cfg.EventHistory.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Frontend.Service.Name, frontend.GetCommands(cfg.Frontend), func(c *config.Config) {
cfg.Frontend.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Gateway.Service.Name, gateway.GetCommands(cfg.Gateway), func(c *config.Config) {
cfg.Gateway.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Graph.Service.Name, graph.GetCommands(cfg.Graph), func(c *config.Config) {
cfg.Graph.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Groups.Service.Name, groups.GetCommands(cfg.Groups), func(c *config.Config) {
cfg.Groups.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.IDM.Service.Name, idm.GetCommands(cfg.IDM), func(c *config.Config) {
cfg.IDM.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.IDP.Service.Name, idp.GetCommands(cfg.IDP), func(c *config.Config) {
cfg.IDP.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Invitations.Service.Name, invitations.GetCommands(cfg.Invitations), func(c *config.Config) {
cfg.Invitations.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Nats.Service.Name, nats.GetCommands(cfg.Nats), func(c *config.Config) {
cfg.Nats.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Notifications.Service.Name, notifications.GetCommands(cfg.Notifications), func(c *config.Config) {
cfg.Notifications.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.OCDav.Service.Name, ocdav.GetCommands(cfg.OCDav), func(c *config.Config) {
cfg.OCDav.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.OCM.Service.Name, ocm.GetCommands(cfg.OCM), func(c *config.Config) {
cfg.OCM.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.OCS.Service.Name, ocs.GetCommands(cfg.OCS), func(c *config.Config) {
cfg.OCS.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Policies.Service.Name, policies.GetCommands(cfg.Policies), func(c *config.Config) {
cfg.Policies.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Postprocessing.Service.Name, postprocessing.GetCommands(cfg.Postprocessing), func(c *config.Config) {
cfg.Postprocessing.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Proxy.Service.Name, proxy.GetCommands(cfg.Proxy), func(c *config.Config) {
cfg.Proxy.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Search.Service.Name, search.GetCommands(cfg.Search), func(c *config.Config) {
cfg.Search.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Settings.Service.Name, settings.GetCommands(cfg.Settings), func(c *config.Config) {
cfg.Settings.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Sharing.Service.Name, sharing.GetCommands(cfg.Sharing), func(c *config.Config) {
cfg.Sharing.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.SSE.Service.Name, sse.GetCommands(cfg.SSE), func(c *config.Config) {
cfg.SSE.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.StoragePublicLink.Service.Name, storagepubliclink.GetCommands(cfg.StoragePublicLink), func(c *config.Config) {
cfg.StoragePublicLink.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.StorageShares.Service.Name, storageshares.GetCommands(cfg.StorageShares), func(c *config.Config) {
cfg.StorageShares.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.StorageSystem.Service.Name, storagesystem.GetCommands(cfg.StorageSystem), func(c *config.Config) {
cfg.StorageSystem.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.StorageUsers.Service.Name, storageusers.GetCommands(cfg.StorageUsers), func(c *config.Config) {
cfg.StorageUsers.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Thumbnails.Service.Name, thumbnails.GetCommands(cfg.Thumbnails), func(c *config.Config) {
cfg.Thumbnails.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Userlog.Service.Name, userlog.GetCommands(cfg.Userlog), func(c *config.Config) {
cfg.Userlog.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Users.Service.Name, users.GetCommands(cfg.Users), func(c *config.Config) {
cfg.Users.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Web.Service.Name, web.GetCommands(cfg.Web), func(c *config.Config) {
cfg.Web.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.WebDAV.Service.Name, webdav.GetCommands(cfg.WebDAV), func(c *config.Config) {
cfg.WebDAV.Commons = cfg.Commons
})
},
func(cfg *config.Config) *cobra.Command {
func(cfg *config.Config) *cli.Command {
return ServiceCommand(cfg, cfg.Webfinger.Service.Name, webfinger.GetCommands(cfg.Webfinger), func(c *config.Config) {
cfg.Webfinger.Commons = cfg.Commons
})
},
}
// ServiceCommand composes a cobra command from the given inputs.
func ServiceCommand(cfg *config.Config, serviceName string, subCommands []*cobra.Command, f func(*config.Config)) *cobra.Command {
command := &cobra.Command{
Use: serviceName,
Short: fmt.Sprintf("%s service commands", serviceName),
GroupID: CommandGroupServices,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// ServiceCommand is the entry point for the all service commands.
func ServiceCommand(cfg *config.Config, serviceName string, subcommands []*cli.Command, f func(*config.Config)) *cli.Command {
return &cli.Command{
Name: serviceName,
Usage: helper.SubcommandDescription(serviceName),
Category: "services",
Before: func(c *cli.Context) error {
configlog.Error(parser.ParseConfig(cfg, true))
f(cfg)
return nil
},
Subcommands: subcommands,
}
command.AddCommand(subCommands...)
return command
}
func init() {
for _, c := range serviceCommands {
for _, c := range svccmds {
register.AddCommand(c)
}
}

View File

@@ -3,7 +3,13 @@ package command
import (
"errors"
"github.com/spf13/viper"
"github.com/rs/zerolog"
"github.com/urfave/cli/v2"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3"
"github.com/opencloud-eu/reva/v2/pkg/share/manager/registry"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
@@ -13,21 +19,15 @@ import (
mregistry "github.com/opencloud-eu/opencloud/pkg/registry"
sharing "github.com/opencloud-eu/opencloud/services/sharing/pkg/config"
sharingparser "github.com/opencloud-eu/opencloud/services/sharing/pkg/config/parser"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/share/manager/jsoncs3"
"github.com/opencloud-eu/reva/v2/pkg/share/manager/registry"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
)
// SharesCommand is the entrypoint for the groups command.
func SharesCommand(cfg *config.Config) *cobra.Command {
sharesCmd := &cobra.Command{
Use: "shares",
Short: `cli tools to manage entries in the share manager.`,
PreRunE: func(cmd *cobra.Command, args []string) error {
func SharesCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "shares",
Usage: `cli tools to manage entries in the share manager.`,
Category: "maintenance",
Before: func(c *cli.Context) error {
// Parse base config
if err := parser.ParseConfig(cfg, true); err != nil {
return configlog.ReturnError(err)
@@ -37,21 +37,37 @@ func SharesCommand(cfg *config.Config) *cobra.Command {
cfg.Sharing.Commons = cfg.Commons
return configlog.ReturnError(sharingparser.ParseConfig(cfg.Sharing))
},
Subcommands: []*cli.Command{
cleanupCmd(cfg),
},
}
sharesCmd.AddCommand(cleanupCmd(cfg))
return sharesCmd
}
func init() {
register.AddCommand(SharesCommand)
}
func cleanupCmd(cfg *config.Config) *cobra.Command {
cleanCmd := &cobra.Command{
Use: "cleanup",
Short: `clean up stale entries in the share manager.`,
PreRunE: func(cmd *cobra.Command, args []string) error {
func cleanupCmd(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "cleanup",
Usage: `clean up stale entries in the share manager.`,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "service-account-id",
Value: "",
Usage: "Name of the service account to use for the cleanup",
EnvVars: []string{"OC_SERVICE_ACCOUNT_ID"},
Required: true,
},
&cli.StringFlag{
Name: "service-account-secret",
Value: "",
Usage: "Secret for the service account",
EnvVars: []string{"OC_SERVICE_ACCOUNT_SECRET"},
Required: true,
},
},
Before: func(c *cli.Context) error {
// Parse base config
if err := parser.ParseConfig(cfg, true); err != nil {
return configlog.ReturnError(err)
@@ -61,24 +77,13 @@ func cleanupCmd(cfg *config.Config) *cobra.Command {
cfg.Sharing.Commons = cfg.Commons
return configlog.ReturnError(sharingparser.ParseConfig(cfg.Sharing))
},
RunE: func(cmd *cobra.Command, args []string) error {
return cleanup(cmd, cfg)
Action: func(c *cli.Context) error {
return cleanup(c, cfg)
},
}
cleanCmd.Flags().String("service-account-id", "", "Name of the service account to use for the cleanup")
_ = cleanCmd.MarkFlagRequired("service-account-id")
_ = viper.BindEnv("service-account-id", "OC_SERVICE_ACCOUNT_ID")
_ = viper.BindPFlag("service-account-id", cleanCmd.Flags().Lookup("service-account-id"))
cleanCmd.Flags().String("service-account-secret", "", "Secret for the service account")
_ = cleanCmd.MarkFlagRequired("service-account-secret")
_ = viper.BindEnv("service-account-secret", "OC_SERVICE_ACCOUNT_SECRET")
_ = viper.BindPFlag("service-account-secret", cleanCmd.Flags().Lookup("service-account-secret"))
return cleanCmd
}
func cleanup(_ *cobra.Command, cfg *config.Config) error {
func cleanup(c *cli.Context, cfg *config.Config) error {
driver := cfg.Sharing.UserSharingDriver
// cleanup is only implemented for the jsoncs3 share manager
if driver != "jsoncs3" {
@@ -109,9 +114,7 @@ func cleanup(_ *cobra.Command, cfg *config.Config) error {
return configlog.ReturnError(err)
}
serviceAccountIDFlag := viper.GetString("service-account-id")
serviceAccountSecretFlag := viper.GetString("service-account-secret")
serviceUserCtx, err := utils.GetServiceUserContext(serviceAccountIDFlag, client, serviceAccountSecretFlag)
serviceUserCtx, err := utils.GetServiceUserContext(c.String("service-account-id"), client, c.String("service-account-secret"))
if err != nil {
return configlog.ReturnError(err)
}
@@ -168,6 +171,39 @@ func revaShareConfig(cfg *sharing.Config) map[string]interface{} {
}
}
func revaPublicShareConfig(cfg *sharing.Config) map[string]interface{} {
return map[string]interface{}{
"json": map[string]interface{}{
"file": cfg.PublicSharingDrivers.JSON.File,
"gateway_addr": cfg.Reva.Address,
},
"jsoncs3": map[string]interface{}{
"gateway_addr": cfg.Reva.Address,
"provider_addr": cfg.PublicSharingDrivers.JSONCS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.JSONCS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.JSONCS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.JSONCS3.SystemUserAPIKey,
},
"sql": map[string]interface{}{
"db_username": cfg.PublicSharingDrivers.SQL.DBUsername,
"db_password": cfg.PublicSharingDrivers.SQL.DBPassword,
"db_host": cfg.PublicSharingDrivers.SQL.DBHost,
"db_port": cfg.PublicSharingDrivers.SQL.DBPort,
"db_name": cfg.PublicSharingDrivers.SQL.DBName,
"password_hash_cost": cfg.PublicSharingDrivers.SQL.PasswordHashCost,
"enable_expired_shares_cleanup": cfg.PublicSharingDrivers.SQL.EnableExpiredSharesCleanup,
"janitor_run_interval": cfg.PublicSharingDrivers.SQL.JanitorRunInterval,
},
"cs3": map[string]interface{}{
"gateway_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr,
"provider_addr": cfg.PublicSharingDrivers.CS3.ProviderAddr,
"service_user_id": cfg.PublicSharingDrivers.CS3.SystemUserID,
"service_user_idp": cfg.PublicSharingDrivers.CS3.SystemUserIDP,
"machine_auth_apikey": cfg.PublicSharingDrivers.CS3.SystemUserAPIKey,
},
}
}
func logger() *zerolog.Logger {
log := oclog.NewLogger(
oclog.Name("migrate"),

View File

@@ -3,40 +3,57 @@ package command
import (
"fmt"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/opencloud/pkg/trash"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/config/parser"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
func TrashCommand(cfg *config.Config) *cobra.Command {
trashCmd := &cobra.Command{
Use: "trash",
Short: "OpenCloud trash functionality",
PreRunE: func(cmd *cobra.Command, args []string) error {
func TrashCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "trash",
Usage: "OpenCloud trash functionality",
Subcommands: []*cli.Command{
TrashPurgeEmptyDirsCommand(cfg),
},
Before: func(c *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg, true))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(_ *cli.Context) error {
fmt.Println("Read the docs")
return nil
},
}
trashCmd.AddCommand(TrashPurgeEmptyDirsCommand(cfg))
return trashCmd
}
func TrashPurgeEmptyDirsCommand(cfg *config.Config) *cobra.Command {
trashPurgeCmd := &cobra.Command{
Use: "purge-empty-dirs",
Short: "purge empty directories",
RunE: func(cmd *cobra.Command, args []string) error {
basePath, _ := cmd.Flags().GetString("basepath")
dryRun, _ := cmd.Flags().GetBool("dry-run")
if err := trash.PurgeTrashEmptyPaths(basePath, dryRun); err != nil {
func TrashPurgeEmptyDirsCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "purge-empty-dirs",
Usage: "purge empty directories",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "basepath",
Aliases: []string{"p"},
Usage: "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/users)",
Required: true,
},
&cli.BoolFlag{
Name: "dry-run",
Usage: "do not delete anything, just print what would be deleted",
Value: true,
},
},
Action: func(c *cli.Context) error {
basePath := c.String("basepath")
if basePath == "" {
fmt.Println("basepath is required")
return cli.ShowCommandHelp(c, "trash")
}
if err := trash.PurgeTrashEmptyPaths(basePath, c.Bool("dry-run")); err != nil {
fmt.Println(err)
return err
}
@@ -44,12 +61,6 @@ func TrashPurgeEmptyDirsCommand(cfg *config.Config) *cobra.Command {
return nil
},
}
trashPurgeCmd.Flags().StringP("basepath", "p", "", "the basepath of the decomposedfs (e.g. /var/tmp/opencloud/storage/users)")
_ = trashPurgeCmd.MarkFlagRequired("basepath")
trashPurgeCmd.Flags().Bool("dry-run", true, "do not delete anything, just print what would be deleted")
return trashPurgeCmd
}
func init() {

View File

@@ -4,16 +4,15 @@ import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
"github.com/urfave/cli/v2"
mreg "go-micro.dev/v4/registry"
"github.com/opencloud-eu/opencloud/opencloud/pkg/register"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/opencloud-eu/opencloud/pkg/registry"
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
mreg "go-micro.dev/v4/registry"
)
const (
@@ -21,18 +20,22 @@ const (
)
// VersionCommand is the entrypoint for the version command.
func VersionCommand(cfg *config.Config) *cobra.Command {
versionCmd := &cobra.Command{
Use: "version",
Short: "print the version of this binary and all running service instances",
GroupID: CommandGroupServer,
RunE: func(cmd *cobra.Command, args []string) error {
func VersionCommand(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "version",
Usage: "print the version of this binary and all running service instances",
Flags: []cli.Flag{
&cli.BoolFlag{
Name: _skipServiceListingFlagName,
Usage: "skip service listing",
},
},
Category: "info",
Action: func(c *cli.Context) error {
fmt.Println("Version: " + version.GetString())
fmt.Printf("Edition: %s\n", version.Edition)
fmt.Printf("Compiled: %s\n", version.Compiled())
skipServiceListing, _ := cmd.Flags().GetBool(_skipServiceListingFlagName)
if skipServiceListing {
if c.Bool(_skipServiceListingFlagName) {
return nil
}
@@ -71,8 +74,6 @@ func VersionCommand(cfg *config.Config) *cobra.Command {
return nil
},
}
versionCmd.Flags().Bool(_skipServiceListingFlagName, false, "skip service listing")
return versionCmd
}
func init() {

View File

@@ -5,7 +5,7 @@ import (
"os"
"path"
"github.com/google/uuid"
"github.com/gofrs/uuid"
"gopkg.in/yaml.v2"
"github.com/opencloud-eu/opencloud/pkg/generators"
@@ -68,7 +68,7 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
systemUserID, adminUserID, graphApplicationID, storageUsersMountID, serviceAccountID string
idmServicePassword, idpServicePassword, ocAdminServicePassword, revaServicePassword string
tokenManagerJwtSecret, collaborationWOPISecret, machineAuthAPIKey, systemUserAPIKey string
revaTransferSecret, thumbnailsTransferSecret, serviceAccountSecret, urlSigningSecret string
revaTransferSecret, thumbnailsTransferSecret, serviceAccountSecret string
)
if diff {
@@ -95,19 +95,12 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
revaTransferSecret = oldCfg.TransferSecret
thumbnailsTransferSecret = oldCfg.Thumbnails.Thumbnail.TransferSecret
serviceAccountSecret = oldCfg.Graph.ServiceAccount.ServiceAccountSecret
urlSigningSecret = oldCfg.URLSigningSecret
if urlSigningSecret == "" {
urlSigningSecret, err = generators.GenerateRandomPassword(passwordLength)
if err != nil {
return fmt.Errorf("could not generate random secret for urlSigningSecret: %s", err)
}
}
} else {
systemUserID = uuid.NewString()
adminUserID = uuid.NewString()
graphApplicationID = uuid.NewString()
storageUsersMountID = uuid.NewString()
serviceAccountID = uuid.NewString()
systemUserID = uuid.Must(uuid.NewV4()).String()
adminUserID = uuid.Must(uuid.NewV4()).String()
graphApplicationID = uuid.Must(uuid.NewV4()).String()
storageUsersMountID = uuid.Must(uuid.NewV4()).String()
serviceAccountID = uuid.Must(uuid.NewV4()).String()
idmServicePassword, err = generators.GenerateRandomPassword(passwordLength)
if err != nil {
@@ -149,17 +142,13 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
if err != nil {
return fmt.Errorf("could not generate random password for revaTransferSecret: %s", err)
}
urlSigningSecret, err = generators.GenerateRandomPassword(passwordLength)
if err != nil {
return fmt.Errorf("could not generate random secret for urlSigningSecret: %s", err)
}
thumbnailsTransferSecret, err = generators.GenerateRandomPassword(passwordLength)
if err != nil {
return fmt.Errorf("could not generate random password for thumbnailsTransferSecret: %s", err)
}
serviceAccountSecret, err = generators.GenerateRandomPassword(passwordLength)
if err != nil {
return fmt.Errorf("could not generate random secret for serviceAccountSecret: %s", err)
return fmt.Errorf("could not generate random password for thumbnailsTransferSecret: %s", err)
}
}
@@ -175,7 +164,6 @@ func CreateConfig(insecure, forceOverwrite, diff bool, configPath, adminPassword
MachineAuthAPIKey: machineAuthAPIKey,
SystemUserAPIKey: systemUserAPIKey,
TransferSecret: revaTransferSecret,
URLSigningSecret: urlSigningSecret,
SystemUserID: systemUserID,
AdminUserID: adminUserID,
Idm: IdmService{

View File

@@ -19,7 +19,6 @@ type OpenCloudConfig struct {
MachineAuthAPIKey string `yaml:"machine_auth_api_key"`
SystemUserAPIKey string `yaml:"system_user_api_key"`
TransferSecret string `yaml:"transfer_secret"`
URLSigningSecret string `yaml:"url_signing_secret"`
SystemUserID string `yaml:"system_user_id"`
AdminUserID string `yaml:"admin_user_id"`
Graph GraphService `yaml:"graph"`

View File

@@ -1,18 +1,17 @@
package register
import (
"github.com/spf13/cobra"
"github.com/opencloud-eu/opencloud/pkg/config"
"github.com/urfave/cli/v2"
)
var (
// Commands define the slice of commands.
Commands []Command
// Commands defines the slice of commands.
Commands = []Command{}
)
// Command defines the register command.
type Command func(*config.Config) *cobra.Command
type Command func(*config.Config) *cli.Command
// AddCommand appends a command to Commands.
func AddCommand(cmd Command) {

View File

@@ -2,12 +2,14 @@ package runtime
import (
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/urfave/cli/v2"
)
// Options is a runtime option
type Options struct {
Services []string
Logger log.Logger
Context *cli.Context
}
// Option undocumented
@@ -19,3 +21,10 @@ func Services(s []string) Option {
o.Services = append(o.Services, s...)
}
}
// Context option
func Context(c *cli.Context) Option {
return func(o *Options) {
o.Context = c
}
}

View File

@@ -3,6 +3,7 @@ package service
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"net/rpc"
@@ -124,7 +125,7 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) {
if s.Services[priority] == nil {
s.Services[priority] = make(serviceFuncMap)
}
s.Services[priority][name] = NewSutureServiceBuilder(name, exec)
s.Services[priority][name] = NewSutureServiceBuilder(exec)
}
// nats is in priority group 0. It needs to start before all other services
@@ -316,11 +317,11 @@ func NewService(ctx context.Context, options ...Option) (*Service, error) {
// populate optional services
areg := func(name string, exec func(context.Context, *occfg.Config) error) {
s.Additional[name] = NewSutureServiceBuilder(name, exec)
s.Additional[name] = NewSutureServiceBuilder(exec)
}
areg(opts.Config.Antivirus.Service.Name, func(ctx context.Context, cfg *occfg.Config) error {
cfg.Antivirus.Context = ctx
cfg.Antivirus.Commons = cfg.Commons
// cfg.Antivirus.Commons = cfg.Commons // antivirus holds no Commons atm
return antivirus.Execute(cfg.Antivirus)
})
areg(opts.Config.Audit.Service.Name, func(ctx context.Context, cfg *occfg.Config) error {
@@ -381,32 +382,7 @@ func Start(ctx context.Context, o ...Option) error {
cancel()
}
}
switch ev := e.(type) {
case suture.EventServicePanic:
l := s.Log.Fatal()
if ev.Restarting {
l = s.Log.Error()
}
l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold).
Str("message", ev.PanicMsg).Msg("service panic")
case suture.EventServiceTerminate:
l := s.Log.Fatal()
if ev.Restarting {
l = s.Log.Error()
}
l.Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).
Bool("restarting", ev.Restarting).Float64("failures", ev.CurrentFailures).Float64("threshold", ev.FailureThreshold).
Interface("error", ev.Err).Msg("service terminated")
case suture.EventBackoff:
s.Log.Warn().Str("event", e.String()).Str("supervisor", ev.SupervisorName).Msg("service backoff")
case suture.EventResume:
s.Log.Info().Str("event", e.String()).Str("supervisor", ev.SupervisorName).Msg("service resume")
case suture.EventStopTimeout:
s.Log.Warn().Str("event", e.String()).Str("service", ev.ServiceName).Str("supervisor", ev.SupervisorName).Msg("service resume")
default:
s.Log.Warn().Str("event", e.String()).Msgf("supervisor: %v", e.Map()["supervisor_name"])
}
s.Log.Info().Str("event", e.String()).Msg(fmt.Sprintf("supervisor: %v", e.Map()["supervisor_name"]))
},
FailureThreshold: 5,
FailureBackoff: 3 * time.Second,
@@ -545,24 +521,6 @@ func trapShutdownCtx(s *Service, srv *http.Server, ctx context.Context) error {
s.Log.Debug().Msg("runtime listener shutdown done")
}()
// shutdown services in the order defined in the config
// any services not listed will be shutdown in parallel afterwards
for _, sName := range s.cfg.Runtime.ShutdownOrder {
if _, ok := s.serviceToken[sName]; !ok {
s.Log.Warn().Str("service", sName).Msg("unknown service for ordered shutdown, skipping")
continue
}
for i := range s.serviceToken[sName] {
if err := s.Supervisor.RemoveAndWait(s.serviceToken[sName][i], _defaultShutdownTimeoutDuration); err != nil && !errors.Is(err, suture.ErrSupervisorNotRunning) {
s.Log.Error().Err(err).Str("service", sName).Msg("could not shutdown service in order, skipping to next")
// continue shutting down other services
continue
}
s.Log.Debug().Str("service", sName).Msg("graceful ordered shutdown for service done")
}
delete(s.serviceToken, sName)
}
for sName := range s.serviceToken {
for i := range s.serviceToken[sName] {
wg.Add(1)

View File

@@ -10,17 +10,15 @@ import (
// SutureService allows for the settings command to be embedded and supervised by a suture supervisor tree.
type SutureService struct {
exec func(ctx context.Context) error
name string
}
// NewSutureServiceBuilder creates a new suture service
func NewSutureServiceBuilder(name string, f func(context.Context, *occfg.Config) error) func(*occfg.Config) suture.Service {
func NewSutureServiceBuilder(f func(context.Context, *occfg.Config) error) func(*occfg.Config) suture.Service {
return func(cfg *occfg.Config) suture.Service {
return SutureService{
exec: func(ctx context.Context) error {
return f(ctx, cfg)
},
name: name,
}
}
}
@@ -29,8 +27,3 @@ func NewSutureServiceBuilder(name string, f func(context.Context, *occfg.Config)
func (s SutureService) Serve(ctx context.Context) error {
return s.exec(ctx)
}
// String to fullfil fmt.Stringer interface, used to log the service name
func (s SutureService) String() string {
return s.name
}

View File

@@ -1,18 +1,26 @@
package clihelper
import (
"fmt"
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// DefaultApp is a wrapper for DefaultApp that adds Cobra specific settings
func DefaultApp(app *cobra.Command) *cobra.Command {
// TODO: when migration is done this has to become DefaultApp
func DefaultApp(app *cli.App) *cli.App {
// version info
app.Version = fmt.Sprintf("%s (%s <%s>) (%s)", version.String, "OpenCloud GmbH", "support@opencloud.eu", version.Compiled())
app.Version = version.String
app.Compiled = version.Compiled()
// author info
app.Authors = []*cli.Author{
{
Name: "OpenCloud GmbH",
Email: "support@opencloud.eu",
},
}
// disable global version flag
// instead we provide the version command
app.HideVersion = true
return app
}

View File

@@ -50,18 +50,18 @@ type Mode int
// Runtime configures the OpenCloud runtime when running in supervised mode.
type Runtime struct {
Port string `yaml:"port" env:"OC_RUNTIME_PORT" desc:"The TCP port at which OpenCloud will be available" introductionVersion:"1.0.0"`
Host string `yaml:"host" env:"OC_RUNTIME_HOST" desc:"The host at which OpenCloud will be available" introductionVersion:"1.0.0"`
Services []string `yaml:"services" env:"OC_RUN_EXTENSIONS;OC_RUN_SERVICES" desc:"A comma-separated list of service names. Will start only the listed services." introductionVersion:"1.0.0"`
Disabled []string `yaml:"disabled_services" env:"OC_EXCLUDE_RUN_SERVICES" desc:"A comma-separated list of service names. Will start all default services except of the ones listed. Has no effect when OC_RUN_SERVICES is set." introductionVersion:"1.0.0"`
Additional []string `yaml:"add_services" env:"OC_ADD_RUN_SERVICES" desc:"A comma-separated list of service names. Will add the listed services to the default configuration. Has no effect when OC_RUN_SERVICES is set. Note that one can add services not started by the default list and exclude services from the default list by using both envvars at the same time." introductionVersion:"1.0.0"`
ShutdownOrder []string `yaml:"shutdown_order" env:"OC_SHUTDOWN_ORDER" desc:"A comma-separated list of service names defining the order in which services are shut down. Services not listed will be stopped after the listed ones in random order." introductionVersion:"4.0.0"`
Port string `yaml:"port" env:"OC_RUNTIME_PORT" desc:"The TCP port at which OpenCloud will be available" introductionVersion:"1.0.0"`
Host string `yaml:"host" env:"OC_RUNTIME_HOST" desc:"The host at which OpenCloud will be available" introductionVersion:"1.0.0"`
Services []string `yaml:"services" env:"OC_RUN_EXTENSIONS;OC_RUN_SERVICES" desc:"A comma-separated list of service names. Will start only the listed services." introductionVersion:"1.0.0"`
Disabled []string `yaml:"disabled_services" env:"OC_EXCLUDE_RUN_SERVICES" desc:"A comma-separated list of service names. Will start all default services except of the ones listed. Has no effect when OC_RUN_SERVICES is set." introductionVersion:"1.0.0"`
Additional []string `yaml:"add_services" env:"OC_ADD_RUN_SERVICES" desc:"A comma-separated list of service names. Will add the listed services to the default configuration. Has no effect when OC_RUN_SERVICES is set. Note that one can add services not started by the default list and exclude services from the default list by using both envvars at the same time." introductionVersion:"1.0.0"`
}
// Config combines all available configuration parts.
type Config struct {
*shared.Commons `yaml:"shared"`
Tracing *shared.Tracing `yaml:"tracing"`
Log *shared.Log `yaml:"log"`
Cache *shared.Cache `yaml:"cache"`
GRPCClientTLS *shared.GRPCClientTLS `yaml:"grpc_client_tls"`
@@ -77,7 +77,6 @@ type Config struct {
TokenManager *shared.TokenManager `yaml:"token_manager"`
MachineAuthAPIKey string `yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
TransferSecret string `yaml:"transfer_secret" env:"OC_TRANSFER_SECRET" desc:"Transfer secret for signing file up- and download requests." introductionVersion:"1.0.0"`
URLSigningSecret string `yaml:"url_signing_secret" env:"OC_URL_SIGNING_SECRET" desc:"The shared secret used to sign URLs e.g. for image downloads by the web office suite." introductionVersion:"4.0.0"`
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
SystemUserAPIKey string `yaml:"system_user_api_key" env:"OC_SYSTEM_USER_API_KEY" desc:"API key for the storage-system system user." introductionVersion:"1.0.0"`
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`

View File

@@ -50,9 +50,8 @@ func DefaultConfig() *Config {
return &Config{
OpenCloudURL: "https://localhost:9200",
Runtime: Runtime{
Port: "9250",
Host: "localhost",
ShutdownOrder: []string{"proxy"},
Port: "9250",
Host: "localhost",
},
Reva: &shared.Reva{
Address: "eu.opencloud.api.gateway",

View File

@@ -40,6 +40,9 @@ func ParseConfig(cfg *config.Config, skipValidate bool) error {
// EnsureDefaults ensures that all pointers in the
// OpenCloud config (not the services configs) are initialized
func EnsureDefaults(cfg *config.Config) {
if cfg.Tracing == nil {
cfg.Tracing = &shared.Tracing{}
}
if cfg.Log == nil {
cfg.Log = &shared.Log{}
}
@@ -68,6 +71,7 @@ func EnsureCommons(cfg *config.Config) {
}
cfg.Commons.Log = structs.CopyOrZeroValue(cfg.Log)
cfg.Commons.Tracing = structs.CopyOrZeroValue(cfg.Tracing)
cfg.Commons.Cache = structs.CopyOrZeroValue(cfg.Cache)
if cfg.GRPCClientTLS != nil {
@@ -96,14 +100,6 @@ func EnsureCommons(cfg *config.Config) {
cfg.Commons.TransferSecret = cfg.TransferSecret
}
// make sure url signing secret is set and copy it to the commons part
// fall back to transfer secret for url signing secret to avoid
// issues when upgrading from an older release
if cfg.URLSigningSecret == "" {
cfg.URLSigningSecret = cfg.TransferSecret
}
cfg.Commons.URLSigningSecret = cfg.URLSigningSecret
// copy metadata user id to the commons part if set
if cfg.SystemUserID != "" {
cfg.Commons.SystemUserID = cfg.SystemUserID
@@ -132,10 +128,6 @@ func Validate(cfg *config.Config) error {
return shared.MissingRevaTransferSecretError("opencloud")
}
if cfg.URLSigningSecret == "" {
return shared.MissingURLSigningSecret("opencloud")
}
if cfg.MachineAuthAPIKey == "" {
return shared.MissingMachineAuthApiKeyError("opencloud")
}

View File

@@ -6,8 +6,7 @@ import (
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/shared"
"github.com/spf13/pflag"
"github.com/urfave/cli/v2"
"go.opentelemetry.io/otel/trace"
)
@@ -24,7 +23,7 @@ type Options struct {
Address string
Handler http.Handler
Context context.Context
Flags []pflag.Flag
Flags []cli.Flag
TraceProvider trace.TracerProvider
}
@@ -84,7 +83,7 @@ func Context(ctx context.Context) Option {
}
// Flags provides a function to set the flags option.
func Flags(flags ...pflag.Flag) Option {
func Flags(flags ...cli.Flag) Option {
return func(o *Options) {
o.Flags = append(o.Flags, flags...)
}

View File

@@ -49,8 +49,6 @@ func NewService(opts ...Option) (Service, error) {
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
NextProtos: []string{"h2", "http/1.1"},
}
mServer = mhttps.NewServer(server.TLSConfig(tlsConfig))
} else {
@@ -64,8 +62,7 @@ func NewService(opts ...Option) (Service, error) {
micro.Name(strings.Join([]string{sopts.Namespace, sopts.Name}, ".")),
micro.Version(sopts.Version),
micro.Context(sopts.Context),
// TODO: clarify if this is actually used on the go-micro side
//micro.Flags(sopts.Flags...),
micro.Flags(sopts.Flags...),
micro.Registry(registry.GetRegistry()),
micro.RegisterTTL(registry.GetRegisterTTL()),
micro.RegisterInterval(registry.GetRegisterInterval()),

View File

@@ -93,11 +93,3 @@ func MissingWOPISecretError(service string) error {
"the config/corresponding environment variable).",
service, defaults.BaseConfigPath())
}
func MissingURLSigningSecret(service string) error {
return fmt.Errorf("The URL signing secret has not been set properly in your config for %s. "+
"Make sure your %s config contains the proper values "+
"(e.g. by using 'opencloud init --diff' and applying the patch or setting a value manually in "+
"the config/corresponding environment variable).",
service, defaults.BaseConfigPath())
}

View File

@@ -18,6 +18,14 @@ type Log struct {
File string `yaml:"file" env:"OC_LOG_FILE" desc:"The path to the log file. Activates logging to this file if set." introductionVersion:"1.0.0"`
}
// Tracing defines the available tracing configuration.
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OC_TRACING_ENABLED" desc:"Activates tracing." introductionVersion:"1.0.0"`
Type string `yaml:"type" env:"OC_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now." introductionVersion:"1.0.0"`
Endpoint string `yaml:"endpoint" env:"OC_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent." introductionVersion:"1.0.0"`
Collector string `yaml:"collector" env:"OC_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset." introductionVersion:"1.0.0"`
}
// TokenManager is the config for using the reva token manager
type TokenManager struct {
JWTSecret string `mask:"password" yaml:"jwt_secret" env:"OC_JWT_SECRET" desc:"The secret to mint and validate jwt tokens." introductionVersion:"1.0.0"`
@@ -61,22 +69,20 @@ type Cache struct {
// Commons holds configuration that are common to all extensions. Each extension can then decide whether
// to overwrite its values.
type Commons struct {
TracesExporter string `yaml:"traces_exporter" env:"OTEL_TRACES_EXPORTER" desc:"The exporter used for traces. Supports 'otlp', 'console' and 'none' (default)." introductionVersion:"%%NEXT%%"`
Log *Log `yaml:"log"`
Cache *Cache `yaml:"cache"`
GRPCClientTLS *GRPCClientTLS `yaml:"grpc_client_tls"`
GRPCServiceTLS *GRPCServiceTLS `yaml:"grpc_service_tls"`
HTTPServiceTLS HTTPServiceTLS `yaml:"http_service_tls"`
OpenCloudURL string `yaml:"opencloud_url" env:"OC_URL" desc:"URL, where OpenCloud is reachable for users." introductionVersion:"1.0.0"`
TokenManager *TokenManager `mask:"struct" yaml:"token_manager"`
Reva *Reva `yaml:"reva"`
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
TransferSecret string `mask:"password" yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET" desc:"The secret used for signing the requests towards the data gateway for up- and downloads." introductionVersion:"1.0.0"`
URLSigningSecret string `yaml:"url_signing_secret" env:"OC_URL_SIGNING_SECRET" desc:"The shared secret used to sign URLs e.g. for image downloads by the web office suite." introductionVersion:"4.0.0"`
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
SystemUserAPIKey string `mask:"password" yaml:"system_user_api_key" env:"SYSTEM_USER_API_KEY" desc:"API key for all system users." introductionVersion:"1.0.0"`
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`
MultiTenantEnabled bool `yaml:"multi_tenant_enabled" env:"OC_MULTI_TENANT_ENABLED" desc:"Set this to true to enable multi-tenant support." introductionVersion:"4.0.0"`
Log *Log `yaml:"log"`
Tracing *Tracing `yaml:"tracing"`
Cache *Cache `yaml:"cache"`
GRPCClientTLS *GRPCClientTLS `yaml:"grpc_client_tls"`
GRPCServiceTLS *GRPCServiceTLS `yaml:"grpc_service_tls"`
HTTPServiceTLS HTTPServiceTLS `yaml:"http_service_tls"`
OpenCloudURL string `yaml:"opencloud_url" env:"OC_URL" desc:"URL, where OpenCloud is reachable for users." introductionVersion:"1.0.0"`
TokenManager *TokenManager `mask:"struct" yaml:"token_manager"`
Reva *Reva `yaml:"reva"`
MachineAuthAPIKey string `mask:"password" yaml:"machine_auth_api_key" env:"OC_MACHINE_AUTH_API_KEY" desc:"Machine auth API key used to validate internal requests necessary for the access to resources from other services." introductionVersion:"1.0.0"`
TransferSecret string `mask:"password" yaml:"transfer_secret,omitempty" env:"REVA_TRANSFER_SECRET" desc:"The secret used for signing the requests towards the data gateway for up- and downloads." introductionVersion:"1.0.0"`
SystemUserID string `yaml:"system_user_id" env:"OC_SYSTEM_USER_ID" desc:"ID of the OpenCloud storage-system system user. Admins need to set the ID for the storage-system system user in this config option which is then used to reference the user. Any reasonable long string is possible, preferably this would be an UUIDv4 format." introductionVersion:"1.0.0"`
SystemUserAPIKey string `mask:"password" yaml:"system_user_api_key" env:"SYSTEM_USER_API_KEY" desc:"API key for all system users." introductionVersion:"1.0.0"`
AdminUserID string `yaml:"admin_user_id" env:"OC_ADMIN_USER_ID" desc:"ID of a user, that should receive admin privileges. Consider that the UUID can be encoded in some LDAP deployment configurations like in .ldif files. These need to be decoded beforehand." introductionVersion:"1.0.0"`
// NOTE: you will not fing GRPCMaxReceivedMessageSize size being used in the code. The envvar is actually extracted in revas `pool` package: https://github.com/cs3org/reva/blob/edge/pkg/rgrpc/todo/pool/connection.go
// It is mentioned here again so it is documented

14
pkg/tracing/config.go Normal file
View File

@@ -0,0 +1,14 @@
package tracing
// ConfigConverter is the interface for external configuration.
type ConfigConverter interface {
Convert() Config
}
// Tracing defines the available tracing configuration.
type Config struct {
Enabled bool `yaml:"enabled" env:"OC_TRACING_ENABLED" desc:"Activates tracing." introductionVersion:"1.0.0"`
Type string `yaml:"type" env:"OC_TRACING_TYPE" desc:"The type of tracing. Defaults to \"\", which is the same as \"jaeger\". Allowed tracing types are \"jaeger\" and \"\" as of now." introductionVersion:"1.0.0"`
Endpoint string `yaml:"endpoint" env:"OC_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent." introductionVersion:"1.0.0"`
Collector string `yaml:"collector" env:"OC_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset." introductionVersion:"1.0.0"`
}

View File

@@ -3,16 +3,22 @@ package tracing
import (
"context"
"fmt"
"net/url"
"reflect"
"strings"
"time"
rtrace "github.com/opencloud-eu/reva/v2/pkg/trace"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
// Propagator ensures the importer module uses the same trace propagation strategy.
@@ -21,9 +27,25 @@ var Propagator = propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{},
)
// Deprecated: GetServiceTraceProvider returns a configured open-telemetry trace provider. Use GetTraceProvider.
func GetServiceTraceProvider(exporter, serviceName string) (trace.TracerProvider, error) {
return GetTraceProvider(context.Background(), exporter, serviceName)
// GetServiceTraceProvider returns a configured open-telemetry trace provider.
func GetServiceTraceProvider(c ConfigConverter, serviceName string) (trace.TracerProvider, error) {
var cfg Config
if c == nil || reflect.ValueOf(c).IsNil() {
cfg = Config{Enabled: false}
} else {
cfg = c.Convert()
}
if cfg.Enabled {
return GetTraceProvider(cfg.Endpoint, cfg.Collector, serviceName, cfg.Type)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.NeverSample()),
)
rtrace.SetDefaultTracerProvider(tp)
return tp, nil
}
// GetPropagator gets a configured propagator.
@@ -35,93 +57,116 @@ func GetPropagator() propagation.TextMapPropagator {
}
// GetTraceProvider returns a configured open-telemetry trace provider.
func GetTraceProvider(ctx context.Context, exporter, serviceName string) (*sdktrace.TracerProvider, error) {
// Create resource - shared across all exporters
resources, err := createResource(ctx, serviceName)
if err != nil {
return nil, fmt.Errorf("failed to create resource: %w", err)
}
var tp *sdktrace.TracerProvider
switch exporter {
case "", "none":
// No-op exporter - never sample
tp = sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.NeverSample()),
sdktrace.WithResource(resources),
func GetTraceProvider(endpoint, collector, serviceName, traceType string) (*sdktrace.TracerProvider, error) {
switch t := traceType; t {
case "", "jaeger":
var (
exp *jaeger.Exporter
err error
)
case "console":
// Console exporter - prints to stdout (useful for debugging)
consoleExporter, err := stdouttrace.New(
stdouttrace.WithPrettyPrint(),
)
if endpoint != "" {
var agentHost string
var agentPort string
agentHost, agentPort, err = parseAgentConfig(endpoint)
if err != nil {
return nil, err
}
exp, err = jaeger.New(
jaeger.WithAgentEndpoint(
jaeger.WithAgentHost(agentHost),
jaeger.WithAgentPort(agentPort),
),
)
} else if collector != "" {
exp, err = jaeger.New(
jaeger.WithCollectorEndpoint(
jaeger.WithEndpoint(collector),
),
)
} else {
return sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.NeverSample())), nil
}
if err != nil {
return nil, fmt.Errorf("failed to create console exporter: %w", err)
return nil, err
}
// Use SimpleSpanProcessor for console to get immediate output
tp = sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(sdktrace.NewSimpleSpanProcessor(consoleExporter)),
sdktrace.WithResource(resources),
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(serviceName)),
),
)
rtrace.SetDefaultTracerProvider(tp)
return tp, nil
case "otlp":
// OTLP exporter - connects to collector
// This automatically reads:
// - OTEL_EXPORTER_OTLP_ENDPOINT
// - OTEL_EXPORTER_OTLP_TRACES_ENDPOINT (takes precedence)
// - OTEL_EXPORTER_OTLP_HEADERS
// - OTEL_EXPORTER_OTLP_INSECURE
// - OTEL_EXPORTER_OTLP_CERTIFICATE (for custom CA)
otlpExporter, err := otlptracegrpc.New(ctx)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
conn, err := grpc.DialContext(ctx, endpoint,
// Note the use of insecure transport here. TLS is recommended in production.
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithBlock(),
)
if err != nil {
return nil, fmt.Errorf("failed to create OTLP exporter: %w", err)
return nil, fmt.Errorf("failed to create gRPC connection to collector: %w", err)
}
exporter, err := otlptracegrpc.New(
context.Background(),
otlptracegrpc.WithGRPCConn(conn),
)
if err != nil {
return nil, err
}
resources, err := resource.New(
context.Background(),
resource.WithAttributes(
attribute.String("service.name", serviceName),
attribute.String("library.language", "go"),
),
)
if err != nil {
return nil, err
}
// Create tracer provider
// This automatically reads:
// - OTEL_TRACES_SAMPLER
// - OTEL_TRACES_SAMPLER_ARG
tp = sdktrace.NewTracerProvider(
sdktrace.WithBatcher(otlpExporter),
tp := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithBatcher(exporter),
sdktrace.WithResource(resources),
)
rtrace.SetDefaultTracerProvider(tp)
return tp, nil
case "agent":
fallthrough
case "zipkin":
fallthrough
default:
return nil, fmt.Errorf("unsupported trace exporter: %q (supported: none, console, otlp)", exporter)
return nil, fmt.Errorf("unknown trace type %s", traceType)
}
}
func parseAgentConfig(ae string) (string, string, error) {
u, err := url.Parse(ae)
// as per url.go:
// [...] Trying to parse a hostname and path
// without a scheme is invalid but may not necessarily return an
// error, due to parsing ambiguities.
if err == nil && u.Hostname() != "" && u.Port() != "" {
return u.Hostname(), u.Port(), nil
}
// Set as global default
rtrace.SetDefaultTracerProvider(tp)
p := strings.Split(ae, ":")
if len(p) != 2 {
return "", "", fmt.Errorf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)
}
return tp, nil
}
// createResource creates a resource with service information
func createResource(ctx context.Context, serviceName string) (*resource.Resource, error) {
return resource.New(ctx,
// Reads OTEL_RESOURCE_ATTRIBUTES and OTEL_SERVICE_NAME
resource.WithFromEnv(),
// Host Information
resource.WithHost(),
// Process Information
// Resource WithProcessOwner is deliberately omitted because
// inside containers where process might run as an arbitrary
// uid without a username associated this would fail.
resource.WithProcessPID(),
resource.WithProcessCommandArgs(),
resource.WithProcessExecutableName(),
resource.WithProcessExecutablePath(),
resource.WithProcessRuntimeDescription(),
resource.WithProcessRuntimeName(),
resource.WithProcessRuntimeVersion(),
// Service attributes
resource.WithAttributes(
semconv.ServiceName(serviceName),
attribute.String("library.language", "go"),
),
)
switch {
case p[0] == "" && p[1] == "": // case ae = ":"
return "", "", fmt.Errorf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)
case p[0] == "":
return "", "", fmt.Errorf("invalid agent endpoint `%s`. expected format: `hostname:port`", ae)
}
return p[0], p[1], nil
}

View File

@@ -0,0 +1,77 @@
package tracing
import "testing"
func Test_parseAgentConfig(t *testing.T) {
type args struct {
ae string
}
tests := []struct {
name string
args args
want string
want1 string
wantErr bool
}{
{
name: "docker-style config",
args: args{
ae: "docker-jaeger:6666",
},
want: "docker-jaeger",
want1: "6666",
wantErr: false,
},
{
name: "agent in an url config",
args: args{
ae: "https://example-agent.com:6666",
},
want: "example-agent.com",
want1: "6666",
wantErr: false,
},
{
name: "agent as ipv4",
args: args{
ae: "127.0.0.1:6666",
},
want: "127.0.0.1",
want1: "6666",
wantErr: false,
},
{
name: "no hostname config should error",
args: args{
ae: ":6666",
},
want: "",
want1: "",
wantErr: true,
},
{
name: "no hostname nor port but separator should error",
args: args{
ae: ":",
},
want: "",
want1: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, got1, err := parseAgentConfig(tt.args.ae)
if (err != nil) != tt.wantErr {
t.Errorf("parseAgentConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("parseAgentConfig() got = %v, want %v", got, tt.want)
}
if got1 != tt.want1 {
t.Errorf("parseAgentConfig() got1 = %v, want %v", got1, tt.want1)
}
})
}
}

View File

@@ -1,4 +0,0 @@
package version
// InitEdition exports the private edition initialization func for testing
var InitEdition = initEdition

View File

@@ -1,27 +1,9 @@
package version
import (
"fmt"
"slices"
"strings"
"time"
"github.com/Masterminds/semver"
"github.com/opencloud-eu/reva/v2/pkg/logger"
)
const (
// Dev is used as a placeholder.
Dev = "dev"
// EditionDev indicates the development build channel was used to build the binary.
EditionDev = Dev
// EditionRolling indicates the rolling release build channel was used to build the binary.
EditionRolling = "rolling"
// EditionStable indicates the stable release build channel was used to build the binary.
EditionStable = "stable"
// EditionLTS indicates the lts release build channel was used to build the binary.
EditionLTS = "lts"
)
var (
@@ -34,64 +16,22 @@ var (
// LatestTag is the latest released version plus the dev meta version.
// Will be overwritten by the release pipeline
// Needs a manual change for every tagged release
LatestTag = "4.0.0-rc.3+dev"
LatestTag = "3.5.0+dev"
// Date indicates the build date.
// This has been removed, it looks like you can only replace static strings with recent go versions
//Date = time.Now().Format("20060102")
Date = Dev
Date = "dev"
// Legacy defines the old long 4 number OpenCloud version needed for some clients
Legacy = "0.1.0.0"
// LegacyString defines the old OpenCloud version needed for some clients
LegacyString = "0.1.0"
// Edition describes the build channel (stable, rolling, nightly, daily, dev)
Edition = Dev // default for self-compiled builds
)
func init() { //nolint:gochecknoinits
if err := initEdition(); err != nil {
logger.New().Error().Err(err).Msg("falling back to dev")
}
}
func initEdition() error {
regularEditions := []string{EditionDev, EditionRolling, EditionStable}
versionedEditions := []string{EditionLTS}
if !slices.ContainsFunc(slices.Concat(regularEditions, versionedEditions), func(s string) bool {
isRegularEdition := slices.Contains(regularEditions, Edition)
if isRegularEdition && s == Edition {
return true
}
// handle editions with a version
editionParts := strings.Split(Edition, "-")
if len(editionParts) != 2 { // a versioned edition channel must consist of exactly 2 parts.
return false
}
isVersionedEdition := slices.Contains(versionedEditions, editionParts[0])
if !isVersionedEdition { // not all channels can contain version information
return false
}
_, err := semver.NewVersion(editionParts[1])
return err == nil
}) {
defer func() {
Edition = Dev
}()
return fmt.Errorf(`unknown edition channel '%s'`, Edition)
}
return nil
}
// Compiled returns the compile time of this service.
func Compiled() time.Time {
if Date == Dev {
if Date == "dev" {
return time.Now()
}
t, _ := time.Parse("20060102", Date)

View File

@@ -1,68 +0,0 @@
package version_test
import (
"fmt"
"strings"
"testing"
"github.com/opencloud-eu/opencloud/pkg/version"
)
func TestChannel(t *testing.T) {
tests := map[string]struct {
got string
valid bool
}{
"no channel, defaults to dev": {
got: "",
valid: false,
},
"dev channel": {
got: version.EditionDev,
valid: true,
},
"rolling channel": {
got: version.EditionRolling,
valid: true,
},
"stable channel": {
got: version.EditionStable,
valid: true,
},
"lts channel without version": {
got: version.EditionLTS,
valid: false,
},
"lts-1.0.0 channel": {
got: fmt.Sprintf("%s-1", version.EditionLTS),
valid: true,
},
"lts-one invalid version": {
got: fmt.Sprintf("%s-one", version.EditionLTS),
valid: false,
},
"known channel with version": {
got: fmt.Sprintf("%s-1", version.EditionStable),
valid: false,
},
"unknown channel": {
got: "foo",
valid: false,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
version.Edition = test.got
switch err := version.InitEdition(); {
case err != nil && !test.valid && version.Edition != version.Dev: // if a given edition is unknown, the value is always dev
fallthrough
case test.valid != (err == nil):
t.Fatalf("invalid edition: %s", version.Edition)
case !test.valid && !strings.Contains(err.Error(), "'"+test.got+"'"):
t.Fatalf("no mention of invalid edition '%s' in error: %s", test.got, err.Error())
}
})
}
}

View File

@@ -0,0 +1,19 @@
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/command"
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/config/defaults"
)
func main() {
cfg := defaults.DefaultConfig()
cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
if err := command.Execute(cfg); err != nil {
os.Exit(1)
}
}

View File

@@ -2,16 +2,16 @@ package command
import (
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// Health is the entrypoint for the health command.
func Health(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "health",
Short: "Check health status",
RunE: func(cmd *cobra.Command, args []string) error {
// not implemented
func Health(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "health",
Usage: "Check health status",
Action: func(c *cli.Context) error {
// Not implemented
return nil
},
}

View File

@@ -5,12 +5,12 @@ import (
"github.com/opencloud-eu/opencloud/pkg/clihelper"
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// GetCommands provides all commands for this service
func GetCommands(cfg *config.Config) []*cobra.Command {
return []*cobra.Command{
func GetCommands(cfg *config.Config) cli.Commands {
return []*cli.Command{
// start this service
Server(cfg),
@@ -24,11 +24,11 @@ func GetCommands(cfg *config.Config) []*cobra.Command {
// Execute is the entry point for the activitylog command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cobra.Command{
Use: "activitylog",
Short: "starts activitylog service",
app := clihelper.DefaultApp(&cli.App{
Name: "activitylog",
Usage: "starts activitylog service",
Commands: GetCommands(cfg),
})
app.AddCommand(GetCommands(cfg)...)
app.SetArgs(os.Args[1:])
return app.ExecuteContext(cfg.Context)
return app.RunContext(cfg.Context, os.Args)
}

View File

@@ -9,7 +9,7 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/events/stream"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/store"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
microstore "go-micro.dev/v4/store"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
@@ -47,23 +47,24 @@ var _registeredEvents = []events.Unmarshaller{
}
// Server is the entrypoint for the server command.
func Server(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "server",
Short: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
PreRunE: func(cmd *cobra.Command, args []string) error {
func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "server",
Usage: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Before: func(c *cli.Context) error {
return configlog.ReturnFatal(parser.ParseConfig(cfg))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
logger := logging.Configure(cfg.Service.Name, cfg.Log)
tracerProvider, err := tracing.GetTraceProvider(cmd.Context(), cfg.Commons.TracesExporter, cfg.Service.Name)
tracerProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
if err != nil {
logger.Error().Err(err).Msg("Failed to initialize tracer")
return err
}
gr := run.Group{}
ctx, cancel := context.WithCancel(cmd.Context())
ctx, cancel := context.WithCancel(c.Context)
mtrcs := metrics.New()
mtrcs.BuildInfo.WithLabelValues(version.GetString()).Set(1)

View File

@@ -2,15 +2,16 @@ package command
import (
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// Version prints the service versions of all running instances.
func Version(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Print the version of this binary and the running service instances",
RunE: func(cmd *cobra.Command, args []string) error {
func Version(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "version",
Usage: "print the version of this binary and the running service instances",
Category: "info",
Action: func(c *cli.Context) error {
// not implemented
return nil
},

View File

@@ -13,8 +13,9 @@ type Config struct {
Service Service `yaml:"-"`
Log *Log `yaml:"log"`
Debug Debug `yaml:"debug"`
Tracing *Tracing `yaml:"tracing"`
Log *Log `yaml:"log"`
Debug Debug `yaml:"debug"`
Events Events `yaml:"events"`
Store Store `yaml:"store"`
@@ -32,15 +33,15 @@ type Config struct {
Context context.Context `yaml:"-"`
WriteBufferDuration time.Duration `yaml:"write_buffer_duration" env:"ACTIVITYLOG_WRITE_BUFFER_DURATION" desc:"The duration to wait before flushing the write buffer. This is used to reduce the number of writes to the store." introductionVersion:"4.0.0"`
MaxActivities int `yaml:"max_activities" env:"ACTIVITYLOG_MAX_ACTIVITIES" desc:"The maximum number of activities to keep in the store per resource. If the number of activities exceeds this value, the oldest activities will be removed." introductionVersion:"4.0.0"`
WriteBufferDuration time.Duration `yaml:"write_buffer_duration" env:"ACTIVITYLOG_WRITE_BUFFER_DURATION" desc:"The duration to wait before flushing the write buffer. This is used to reduce the number of writes to the store." introductionVersion:"%%NEXT%%"`
MaxActivities int `yaml:"max_activities" env:"ACTIVITYLOG_MAX_ACTIVITIES" desc:"The maximum number of activities to keep in the store per resource. If the number of activities exceeds this value, the oldest activities will be removed." introductionVersion:"%%NEXT%%"`
}
// Events combines the configuration options for the event bus.
type Events struct {
Endpoint string `yaml:"endpoint" env:"OC_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture." introductionVersion:"1.0.0"`
Cluster string `yaml:"cluster" env:"OC_EVENTS_CLUSTER" desc:"The clusterID of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture. Mandatory when using NATS as event system." introductionVersion:"1.0.0"`
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"1.0.0"`
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"1.0.0"`
TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_EVENTS_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided NOTIFICATIONS_EVENTS_TLS_INSECURE will be seen as false." introductionVersion:"1.0.0"`
EnableTLS bool `yaml:"enable_tls" env:"OC_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"1.0.0"`
AuthUsername string `yaml:"username" env:"OC_EVENTS_AUTH_USERNAME" desc:"The username to authenticate with the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"1.0.0"`

View File

@@ -86,6 +86,19 @@ func EnsureDefaults(cfg *config.Config) {
if cfg.Commons != nil {
cfg.HTTP.TLS = cfg.Commons.HTTPServiceTLS
}
// provide with defaults for shared tracing, since we need a valid destination address for "envdecode".
if cfg.Tracing == nil && cfg.Commons != nil && cfg.Commons.Tracing != nil {
cfg.Tracing = &config.Tracing{
Enabled: cfg.Commons.Tracing.Enabled,
Type: cfg.Commons.Tracing.Type,
Endpoint: cfg.Commons.Tracing.Endpoint,
Collector: cfg.Commons.Tracing.Collector,
}
} else if cfg.Tracing == nil {
cfg.Tracing = &config.Tracing{}
}
}
// Sanitize sanitizes the config

View File

@@ -0,0 +1,21 @@
package config
import "github.com/opencloud-eu/opencloud/pkg/tracing"
// Tracing defines the available tracing configuration.
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OC_TRACING_ENABLED;ACTIVITYLOG_TRACING_ENABLED" desc:"Activates tracing." introductionVersion:"1.0.0"`
Type string `yaml:"type" env:"OC_TRACING_TYPE;ACTIVITYLOG_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now." introductionVersion:"1.0.0"`
Endpoint string `yaml:"endpoint" env:"OC_TRACING_ENDPOINT;ACTIVITYLOG_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent." introductionVersion:"1.0.0"`
Collector string `yaml:"collector" env:"OC_TRACING_COLLECTOR;ACTIVITYLOG_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset." introductionVersion:"1.0.0"`
}
// Convert Tracing to the tracing package's Config struct.
func (t Tracing) Convert() tracing.Config {
return tracing.Config{
Enabled: t.Enabled,
Type: t.Type,
Endpoint: t.Endpoint,
Collector: t.Collector,
}
}

View File

@@ -11,8 +11,7 @@ import (
"github.com/opencloud-eu/opencloud/services/activitylog/pkg/metrics"
"github.com/opencloud-eu/reva/v2/pkg/events"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/spf13/pflag"
"github.com/urfave/cli/v2"
"go-micro.dev/v4/store"
"go.opentelemetry.io/otel/trace"
)
@@ -26,7 +25,7 @@ type Options struct {
Context context.Context
Config *config.Config
Metrics *metrics.Metrics
Flags []pflag.Flag
Flags []cli.Flag
Namespace string
Store store.Store
Stream events.Stream
@@ -77,9 +76,9 @@ func Metrics(val *metrics.Metrics) Option {
}
// Flags provides a function to set the flags option.
func Flags(flags ...pflag.Flag) Option {
func Flags(val []cli.Flag) Option {
return func(o *Options) {
o.Flags = append(o.Flags, flags...)
o.Flags = append(o.Flags, val...)
}
}

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Ivan Fustero, 2025\n"
"Language-Team: Catalan (https://app.transifex.com/opencloud-eu/teams/204053/ca/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jörn Friedrich Dreyer <jfd@butonic.de>, 2025\n"
"Language-Team: German (https://app.transifex.com/opencloud-eu/teams/204053/de/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Elías Martín, 2025\n"
"Language-Team: Spanish (https://app.transifex.com/opencloud-eu/teams/204053/es/)\n"

View File

@@ -1,103 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Jiri Grönroos <jiri.gronroos@iki.fi>, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-16 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Jiri Grönroos <jiri.gronroos@iki.fi>, 2025\n"
"Language-Team: Finnish (https://app.transifex.com/opencloud-eu/teams/204053/fi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: fi\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "kuvaus"
#: pkg/service/response.go:43
msgid "display name"
msgstr "näyttönimi"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "vanhenemispäivä"
#: pkg/service/response.go:41
msgid "password"
msgstr "salasana"
#: pkg/service/response.go:40
msgid "permission"
msgstr "käyttöoikeus"
#: pkg/service/response.go:39
msgid "some field"
msgstr "jokin kieltä"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} ladattiin julkisen linkin {token} kautta"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} lisäsi {resource} kansioon {folder}"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} lisäsi {sharee} jäseneksi avaruuteen {space}"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} poisti {resource} kansiosta {folder}"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} siirsi {resource} kansioon {folder}"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} poisti linkin resurssiin {resource}"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} poisti {sharee} resurssista {resource}"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} poisti {sharee} avaruudesta {space}"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} muutti kohteen {oldResource} uudeksi nimeksi {resource}"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} jakoi {resource} linkin kautta"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} jakoi {resource} käyttäjän {sharee} kanssa"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr ""
"{user} päivitti kentän {field} linkkiin {token} resurssissa {resource}"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} päivitti kentän {field} resurssille {resource}"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} päivitti {resource} kansiossa {folder}"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: eric_G <junk.eg@free.fr>, 2025\n"
"Language-Team: French (https://app.transifex.com/opencloud-eu/teams/204053/fr/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Simone Broglia, 2025\n"
"Language-Team: Italian (https://app.transifex.com/opencloud-eu/teams/204053/it/)\n"

View File

@@ -1,102 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# ii kaka, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-18 00:04+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: ii kaka, 2025\n"
"Language-Team: Japanese (https://app.transifex.com/opencloud-eu/teams/204053/ja/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "詳細"
#: pkg/service/response.go:43
msgid "display name"
msgstr "表示名"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "有効期限"
#: pkg/service/response.go:41
msgid "password"
msgstr "パスワード"
#: pkg/service/response.go:40
msgid "permission"
msgstr "権限"
#: pkg/service/response.go:39
msgid "some field"
msgstr "特定の項目"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} が公開リンク {token} 経由でダウンロードされました"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} が %{resource} を {folder} に追加しました"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} が {sharee} を {space} のメンバーに追加しました"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} が {folder} から {resource} を削除しました"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} が {resource} を {folder} に移動しました"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} が {resource} へのリンクを解除しました"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} が {resource} の共有から {sharee} を削除しました"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} が {space} の共有から {sharee} を削除しました"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} が {oldResource} の名前を {resource} に変更しました"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} がリンク経由で {resource} を共有しました"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} が {resource} を {sharee} と共有しました"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} が {resource} のリンク {token}の {field} を更新しました"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} が {resource} の {field} を更新しました"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} が {folder} 内の {resource} を更新しました"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Junghyuk Kwon <kwon@junghy.uk>, 2025\n"
"Language-Team: Korean (https://app.transifex.com/opencloud-eu/teams/204053/ko/)\n"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-23 00:05+0000\n"
"POT-Creation-Date: 2025-09-11 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Stephan Paternotte <stephan@paternottes.net>, 2025\n"
"Language-Team: Dutch (https://app.transifex.com/opencloud-eu/teams/204053/nl/)\n"

View File

@@ -1,102 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Mário Machado, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-13 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Mário Machado, 2025\n"
"Language-Team: Portuguese (https://app.transifex.com/opencloud-eu/teams/204053/pt/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt\n"
"Plural-Forms: nplurals=3; plural=(n == 0 || n == 1) ? 0 : n != 0 && n % 1000000 == 0 ? 1 : 2;\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "descrição"
#: pkg/service/response.go:43
msgid "display name"
msgstr "nome de exibição"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "data de expiração"
#: pkg/service/response.go:41
msgid "password"
msgstr "palavra-passe"
#: pkg/service/response.go:40
msgid "permission"
msgstr "permissão"
#: pkg/service/response.go:39
msgid "some field"
msgstr "algum campo"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} foi descarregado através da ligação pública {token}"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} adicionou {resource} a {folder}"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} adicionou {sharee} como membro de {space}"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} eliminou {resource} de {folder}"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} moveu {resource} para {folder}"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} removeu a ligação para {resource}"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} removeu {sharee} de {resource}"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} removeu {sharee} de {space}"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} renomeou {oldResource} para {resource}"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} partilhou {resource} via ligação"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} partilhou {resource} com {sharee}"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} atualizou {field} para a ligação {token} em {resource}"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} atualizou {field} para o {resource}"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} atualizou {resource} em {folder}"

View File

@@ -12,7 +12,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-23 00:05+0000\n"
"POT-Creation-Date: 2025-09-11 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Lulufox, 2025\n"
"Language-Team: Russian (https://app.transifex.com/opencloud-eu/teams/204053/ru/)\n"

View File

@@ -1,102 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Daniel Nylander <po@danielnylander.se>, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-19 00:05+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Daniel Nylander <po@danielnylander.se>, 2025\n"
"Language-Team: Swedish (https://app.transifex.com/opencloud-eu/teams/204053/sv/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: sv\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "beskrivning"
#: pkg/service/response.go:43
msgid "display name"
msgstr "visningsnamn"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "utgångsdatum"
#: pkg/service/response.go:41
msgid "password"
msgstr "lösenord"
#: pkg/service/response.go:40
msgid "permission"
msgstr "behörighet"
#: pkg/service/response.go:39
msgid "some field"
msgstr "något fält"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} hämtades via en offentlig länk {token}"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} lade till {resource} till {folder}"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} lade till {sharee} som medlem av {space}"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} raderade {resource} från {folder}"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} flyttade {resource} till {folder}"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} tog bort länk till {resource}"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} tog bort {sharee} från {resource}"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} tog bort {sharee} från {space}"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} döpte om {oldResource} till {resource}"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} delade {resource} via länk"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} delade {resource} med {sharee}"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} uppdaterade {field} för en länk {token} på {resource}"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} uppdaterade {field} för {resource}"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} uppdaterade {resource} i {folder}"

View File

@@ -1,102 +0,0 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
# Translators:
# Quan Tran, 2025
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-17 00:03+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: Quan Tran, 2025\n"
"Language-Team: Vietnamese (https://app.transifex.com/opencloud-eu/teams/204053/vi/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: pkg/service/response.go:44
msgid "description"
msgstr "mô tả"
#: pkg/service/response.go:43
msgid "display name"
msgstr "tên hiển thị"
#: pkg/service/response.go:42
msgid "expiration date"
msgstr "ngày hết hạn"
#: pkg/service/response.go:41
msgid "password"
msgstr "mật khẩu"
#: pkg/service/response.go:40
msgid "permission"
msgstr "quyền"
#: pkg/service/response.go:39
msgid "some field"
msgstr "một số trường"
#: pkg/service/response.go:26
msgid "{resource} was downloaded via public link {token}"
msgstr "{resource} được tải xuống qua đường dẫn công khai {token}"
#: pkg/service/response.go:24
msgid "{user} added {resource} to {folder}"
msgstr "{user} thêm {resource} vào {folder}"
#: pkg/service/response.go:36
msgid "{user} added {sharee} as member of {space}"
msgstr "{user} thêm {sharee} vào {space}"
#: pkg/service/response.go:27
msgid "{user} deleted {resource} from {folder}"
msgstr "{user} xóa {resource} khỏi {folder}"
#: pkg/service/response.go:28
msgid "{user} moved {resource} to {folder}"
msgstr "{user} chuyển{resource} đến {folder}"
#: pkg/service/response.go:35
msgid "{user} removed link to {resource}"
msgstr "{user} xóa đường liên kết tới {resource}"
#: pkg/service/response.go:32
msgid "{user} removed {sharee} from {resource}"
msgstr "{user} xóa {sharee} khỏi {resource}"
#: pkg/service/response.go:37
msgid "{user} removed {sharee} from {space}"
msgstr "{user} xóa {sharee} khỏi {space}"
#: pkg/service/response.go:29
msgid "{user} renamed {oldResource} to {resource}"
msgstr "{user} đổi tên {oldResource} thành {resource}"
#: pkg/service/response.go:33
msgid "{user} shared {resource} via link"
msgstr "{user} chia sẻ {resource} qua đường liên kết"
#: pkg/service/response.go:30
msgid "{user} shared {resource} with {sharee}"
msgstr "{user} chia sẻ {resource} với {sharee}"
#: pkg/service/response.go:34
msgid "{user} updated {field} for a link {token} on {resource}"
msgstr "{user} cập nhật {field} của đường liên kết {token} đến {resource}"
#: pkg/service/response.go:31
msgid "{user} updated {field} for the {resource}"
msgstr "{user} cập nhật {field} của {resource}"
#: pkg/service/response.go:25
msgid "{user} updated {resource} in {folder}"
msgstr "{user} cập nhật {resource} trong {folder}"

View File

@@ -11,7 +11,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: EMAIL\n"
"POT-Creation-Date: 2025-12-20 00:05+0000\n"
"POT-Creation-Date: 2025-09-09 00:02+0000\n"
"PO-Revision-Date: 2025-01-27 10:17+0000\n"
"Last-Translator: YQS Yang, 2025\n"
"Language-Team: Chinese (https://app.transifex.com/opencloud-eu/teams/204053/zh/)\n"

View File

@@ -36,13 +36,13 @@ Several factors can make it necessary to limit the maximum filesize the antiviru
Use the `ANTIVIRUS_MAX_SCAN_SIZE` environment variable to scan only a given number of bytes,
or to skip the whole resource.
Even if it is recommended to scan the whole file, several factors like scanner type and version,
Even if it's recommended to scan the whole file, several factors like scanner type and version,
bandwidth, performance issues, etc. might make a limit necessary.
In such cases, the antivirus max scan size mode can be handy, the following modes are available:
In such cases, the antivirus the max scan size mode can be handy, the following modes are available:
- `partial`: The file is scanned up to the given size. The rest of the file is not scanned. This is the default mode `ANTIVIRUS_MAX_SCAN_SIZE_MODE=partial`
- `skip`: The file is skipped and not scanned. `ANTIVIRUS_MAX_SCAN_SIZE_MODE=skip`
- `partial`: The file is scanned up to the given size. The rest of the file is not scanned. This is the default mode `ANTIVIRUS_MAX_SCAN_SIZE=partial`
- `skip`: The file is skipped and not scanned. `ANTIVIRUS_MAX_SCAN_SIZE=skip`
**IMPORTANT**
> Streaming of files to the virus scan service still [needs to be implemented](https://github.com/owncloud/ocis/issues/6803).

View File

@@ -0,0 +1,19 @@
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/command"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config/defaults"
)
func main() {
cfg := defaults.DefaultConfig()
cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
if err := command.Execute(cfg); err != nil {
os.Exit(1)
}
}

View File

@@ -5,22 +5,23 @@ import (
"net/http"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/spf13/cobra"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config/parser"
"github.com/urfave/cli/v2"
)
// Health is the entrypoint for the health command.
func Health(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "health",
Short: "check health status",
PreRunE: func(cmd *cobra.Command, args []string) error {
func Health(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "health",
Usage: "check health status",
Category: "info",
Before: func(c *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
logger := log.NewLogger(
log.Name(cfg.Service.Name),
log.Level(cfg.Log.Level),

View File

@@ -5,12 +5,12 @@ import (
"github.com/opencloud-eu/opencloud/pkg/clihelper"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// GetCommands provides all commands for this service
func GetCommands(cfg *config.Config) []*cobra.Command {
return []*cobra.Command{
func GetCommands(cfg *config.Config) cli.Commands {
return []*cli.Command{
Server(cfg),
Health(cfg),
Version(cfg),
@@ -19,11 +19,11 @@ func GetCommands(cfg *config.Config) []*cobra.Command {
// Execute is the entry point for the antivirus command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cobra.Command{
Use: "antivirus",
Short: "Antivirus service for OpenCloud",
app := clihelper.DefaultApp(&cli.App{
Name: "antivirus",
Usage: "Antivirus service for OpenCloud",
Commands: GetCommands(cfg),
})
app.AddCommand(GetCommands(cfg)...)
app.SetArgs(os.Args[1:])
return app.ExecuteContext(cfg.Context)
return app.RunContext(cfg.Context, os.Args)
}

View File

@@ -3,9 +3,10 @@ package command
import (
"context"
"fmt"
"os"
"os/signal"
"github.com/urfave/cli/v2"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/runner"
@@ -14,18 +15,18 @@ import (
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config/parser"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/server/debug"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/service"
"github.com/spf13/cobra"
)
// Server is the entrypoint for the server command.
func Server(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "server",
Short: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
PreRunE: func(cmd *cobra.Command, args []string) error {
func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "server",
Usage: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Before: func(c *cli.Context) error {
return configlog.ReturnFatal(parser.ParseConfig(cfg))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
var cancel context.CancelFunc
if cfg.Context == nil {
cfg.Context, cancel = signal.NotifyContext(context.Background(), runner.StopSignals...)
@@ -41,7 +42,7 @@ func Server(cfg *config.Config) *cobra.Command {
log.File(cfg.Log.File),
)
traceProvider, err := tracing.GetTraceProvider(cmd.Context(), cfg.Commons.TracesExporter, cfg.Service.Name)
traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
if err != nil {
return err
}
@@ -50,8 +51,7 @@ func Server(cfg *config.Config) *cobra.Command {
{
svc, err := service.NewAntivirus(cfg, logger, traceProvider)
if err != nil {
fmt.Errorf("failed to initialize antivirus service: %v", err)
os.Exit(1)
return cli.Exit(err.Error(), 1)
}
gr.Add(runner.New(cfg.Service.Name+".svc", func() error {

View File

@@ -4,17 +4,18 @@ import (
"fmt"
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/spf13/cobra"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/config"
"github.com/urfave/cli/v2"
)
// Version prints the service versions of all running instances.
func Version(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "print the version of this binary and the running service instances",
RunE: func(cmd *cobra.Command, args []string) error {
func Version(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "version",
Usage: "print the version of this binary and the running service instances",
Category: "info",
Action: func(c *cli.Context) error {
fmt.Println("Version: " + version.GetString())
fmt.Printf("Compiled: %s\n", version.Compiled())
fmt.Println("")

View File

@@ -3,8 +3,6 @@ package config
import (
"context"
"time"
"github.com/opencloud-eu/opencloud/pkg/shared"
)
// ScannerType gives info which scanner is used
@@ -29,14 +27,15 @@ const (
// Config combines all available configuration parts.
type Config struct {
Commons *shared.Commons `yaml:"-"` // don't use this directly as configuration for a service
File string
Log *Log
File string
Log *Log
Debug Debug `yaml:"debug" mask:"struct"`
Service Service `yaml:"-"`
Tracing *Tracing `yaml:"tracing"`
InfectedFileHandling string `yaml:"infected-file-handling" env:"ANTIVIRUS_INFECTED_FILE_HANDLING" desc:"Defines the behaviour when a virus has been found. Supported options are: 'delete', 'continue' and 'abort '. Delete will delete the file. Continue will mark the file as infected but continues further processing. Abort will keep the file in the uploads folder for further admin inspection and will not move it to its final destination." introductionVersion:"1.0.0"`
Events Events
Workers int `yaml:"workers" env:"ANTIVIRUS_WORKERS" desc:"The number of concurrent go routines that fetch events from the event queue." introductionVersion:"1.0.0"`
@@ -75,7 +74,7 @@ type Debug struct {
type Events struct {
Endpoint string `yaml:"endpoint" env:"OC_EVENTS_ENDPOINT;ANTIVIRUS_EVENTS_ENDPOINT" desc:"The address of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture." introductionVersion:"1.0.0"`
Cluster string `yaml:"cluster" env:"OC_EVENTS_CLUSTER;ANTIVIRUS_EVENTS_CLUSTER" desc:"The clusterID of the event system. The event system is the message queuing service. It is used as message broker for the microservice architecture. Mandatory when using NATS as event system." introductionVersion:"1.0.0"`
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;OC_EVENTS_TLS_INSECURE;ANTIVIRUS_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"1.0.0"`
TLSInsecure bool `yaml:"tls_insecure" env:"OC_INSECURE;ANTIVIRUS_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates." introductionVersion:"1.0.0"`
TLSRootCACertificate string `yaml:"tls_root_ca_certificate" env:"OC_EVENTS_TLS_ROOT_CA_CERTIFICATE;ANTIVIRUS_EVENTS_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided ANTIVIRUS_EVENTS_TLS_INSECURE will be seen as false." introductionVersion:"1.0.0"`
EnableTLS bool `yaml:"enable_tls" env:"OC_EVENTS_ENABLE_TLS;ANTIVIRUS_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"1.0.0"`
AuthUsername string `yaml:"username" env:"OC_EVENTS_AUTH_USERNAME;ANTIVIRUS_EVENTS_AUTH_USERNAME" desc:"The username to authenticate with the events broker. The events broker is the OpenCloud service which receives and delivers events between the services." introductionVersion:"1.0.0"`

View File

@@ -54,6 +54,10 @@ func EnsureDefaults(cfg *config.Config) {
if cfg.Log == nil {
cfg.Log = &config.Log{}
}
if cfg.Tracing == nil {
cfg.Tracing = &config.Tracing{}
}
}
// Sanitize sanitizes the configuration

View File

@@ -0,0 +1,21 @@
package config
import "github.com/opencloud-eu/opencloud/pkg/tracing"
// Tracing defines the available tracing configuration.
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OC_TRACING_ENABLED;ANTIVIRUS_TRACING_ENABLED" desc:"Activates tracing." introductionVersion:"1.0.0"`
Type string `yaml:"type" env:"OC_TRACING_TYPE;ANTIVIRUS_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now." introductionVersion:"1.0.0"`
Endpoint string `yaml:"endpoint" env:"OC_TRACING_ENDPOINT;ANTIVIRUS_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent." introductionVersion:"1.0.0"`
Collector string `yaml:"collector" env:"OC_TRACING_COLLECTOR;ANTIVIRUS_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset." introductionVersion:"1.0.0"`
}
// Convert Tracing to the tracing package's Config struct.
func (t Tracing) Convert() tracing.Config {
return tracing.Config{
Enabled: t.Enabled,
Type: t.Type,
Endpoint: t.Endpoint,
Collector: t.Collector,
}
}

View File

@@ -11,7 +11,7 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/mime"
ic "github.com/opencloud-eu/icap-client"
ic "github.com/egirna/icap-client"
)
// Scanner is the interface that wraps the basic Do method

View File

@@ -9,8 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
ic "github.com/opencloud-eu/icap-client"
ic "github.com/egirna/icap-client"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/scanners"
"github.com/opencloud-eu/opencloud/services/antivirus/pkg/scanners/mocks"
)

View File

@@ -5,8 +5,8 @@
package mocks
import (
"github.com/opencloud-eu/icap-client"
"github.com/stretchr/testify/mock"
"github.com/egirna/icap-client"
mock "github.com/stretchr/testify/mock"
)
// NewScanner creates a new instance of Scanner. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.

View File

@@ -1,20 +0,0 @@
# App Provider
The `app-provider` service provides the CS3 App Provider API for OpenCloud. It is responsible for managing and serving applications that can open files based on their MIME types.
The service works in conjunction with the `app-registry` service, which maintains the registry of available applications and their supported MIME types. When a client requests to open a file with a specific application, the `app-provider` service handles the request and coordinates with the application to provide the appropriate interface.
## Integration
The `app-provider` service integrates with:
- `app-registry` - For discovering which applications are available for specific MIME types
- `frontend` - The frontend service forwards app provider requests (default endpoint `/app`) to this service
## Configuration
The service can be configured via environment variables. Key configuration options include:
- `APP_PROVIDER_EXTERNAL_ADDR` - External address where the gateway service can reach the app provider
## Scalability
The app-provider service can be scaled horizontally as it primarily acts as a coordinator between applications and the OpenCloud backend services.

View File

@@ -0,0 +1,19 @@
package main
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/command"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config/defaults"
)
func main() {
cfg := defaults.DefaultConfig()
cfg.Context, _ = signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
if err := command.Execute(cfg); err != nil {
os.Exit(1)
}
}

View File

@@ -8,18 +8,19 @@ import (
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config/parser"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/logging"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// Health is the entrypoint for the health command.
func Health(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "health",
Short: "check health status",
PreRunE: func(cmd *cobra.Command, args []string) error {
func Health(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "health",
Usage: "check health status",
Category: "info",
Before: func(c *cli.Context) error {
return configlog.ReturnError(parser.ParseConfig(cfg))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
logger := logging.Configure(cfg.Service.Name, cfg.Log)
resp, err := http.Get(

View File

@@ -5,12 +5,12 @@ import (
"github.com/opencloud-eu/opencloud/pkg/clihelper"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
)
// GetCommands provides all commands for this service
func GetCommands(cfg *config.Config) []*cobra.Command {
return []*cobra.Command{
func GetCommands(cfg *config.Config) cli.Commands {
return []*cli.Command{
// start this service
Server(cfg),
@@ -24,12 +24,11 @@ func GetCommands(cfg *config.Config) []*cobra.Command {
// Execute is the entry point for the opencloud app-provider command.
func Execute(cfg *config.Config) error {
app := clihelper.DefaultApp(&cobra.Command{
Use: "app-provider",
Short: "Provide apps for OpenCloud",
app := clihelper.DefaultApp(&cli.App{
Name: "app-provider",
Usage: "Provide apps for OpenCloud",
Commands: GetCommands(cfg),
})
app.AddCommand(GetCommands(cfg)...)
app.SetArgs(os.Args[1:])
return app.ExecuteContext(cfg.Context)
return app.RunContext(cfg.Context, os.Args)
}

View File

@@ -6,7 +6,7 @@ import (
"os/signal"
"github.com/opencloud-eu/reva/v2/cmd/revad/runtime"
"github.com/spf13/cobra"
"github.com/urfave/cli/v2"
"github.com/opencloud-eu/opencloud/pkg/config/configlog"
"github.com/opencloud-eu/opencloud/pkg/registry"
@@ -21,16 +21,17 @@ import (
)
// Server is the entry point for the server command.
func Server(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "server",
Short: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
PreRunE: func(cmd *cobra.Command, args []string) error {
func Server(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "server",
Usage: fmt.Sprintf("start the %s service without runtime (unsupervised mode)", cfg.Service.Name),
Category: "server",
Before: func(c *cli.Context) error {
return configlog.ReturnFatal(parser.ParseConfig(cfg))
},
RunE: func(cmd *cobra.Command, args []string) error {
Action: func(c *cli.Context) error {
logger := logging.Configure(cfg.Service.Name, cfg.Log)
traceProvider, err := tracing.GetTraceProvider(cmd.Context(), cfg.Commons.TracesExporter, cfg.Service.Name)
traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name)
if err != nil {
return err
}

View File

@@ -6,19 +6,20 @@ import (
"github.com/opencloud-eu/opencloud/pkg/registry"
"github.com/opencloud-eu/opencloud/pkg/version"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/tw"
"github.com/spf13/cobra"
"github.com/opencloud-eu/opencloud/services/app-provider/pkg/config"
"github.com/urfave/cli/v2"
)
// Version prints the service versions of all running instances.
func Version(cfg *config.Config) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "print the version of this binary and the running service instances",
RunE: func(cmd *cobra.Command, args []string) error {
func Version(cfg *config.Config) *cli.Command {
return &cli.Command{
Name: "version",
Usage: "print the version of this binary and the running service instances",
Category: "info",
Action: func(c *cli.Context) error {
fmt.Println("Version: " + version.GetString())
fmt.Printf("Compiled: %s\n", version.Compiled())
fmt.Println("")

View File

@@ -9,6 +9,7 @@ import (
type Config struct {
Commons *shared.Commons `yaml:"-"` // don't use this directly as configuration for a service
Service Service `yaml:"-"`
Tracing *Tracing `yaml:"tracing"`
Log *Log `yaml:"log"`
Debug Debug `yaml:"debug"`

View File

@@ -56,6 +56,17 @@ func EnsureDefaults(cfg *config.Config) {
} else if cfg.Log == nil {
cfg.Log = &config.Log{}
}
// provide with defaults for shared tracing, since we need a valid destination address for "envdecode".
if cfg.Tracing == nil && cfg.Commons != nil && cfg.Commons.Tracing != nil {
cfg.Tracing = &config.Tracing{
Enabled: cfg.Commons.Tracing.Enabled,
Type: cfg.Commons.Tracing.Type,
Endpoint: cfg.Commons.Tracing.Endpoint,
Collector: cfg.Commons.Tracing.Collector,
}
} else if cfg.Tracing == nil {
cfg.Tracing = &config.Tracing{}
}
if cfg.Reva == nil && cfg.Commons != nil {
cfg.Reva = structs.CopyOrZeroValue(cfg.Commons.Reva)

View File

@@ -0,0 +1,21 @@
package config
import "github.com/opencloud-eu/opencloud/pkg/tracing"
// Tracing defines the configuration options for tracing.
type Tracing struct {
Enabled bool `yaml:"enabled" env:"OC_TRACING_ENABLED;APP_PROVIDER_TRACING_ENABLED" desc:"Activates tracing." introductionVersion:"1.0.0"`
Type string `yaml:"type" env:"OC_TRACING_TYPE;APP_PROVIDER_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now." introductionVersion:"1.0.0"`
Endpoint string `yaml:"endpoint" env:"OC_TRACING_ENDPOINT;APP_PROVIDER_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent." introductionVersion:"1.0.0"`
Collector string `yaml:"collector" env:"OC_TRACING_COLLECTOR;APP_PROVIDER_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset." introductionVersion:"1.0.0"`
}
// Convert Tracing to the tracing package's Config struct.
func (t Tracing) Convert() tracing.Config {
return tracing.Config{
Enabled: t.Enabled,
Type: t.Type,
Endpoint: t.Endpoint,
Collector: t.Collector,
}
}

View File

@@ -9,10 +9,9 @@ import (
func AppProviderConfigFromStruct(cfg *config.Config) map[string]interface{} {
rcfg := map[string]interface{}{
"shared": map[string]interface{}{
"jwt_secret": cfg.TokenManager.JWTSecret,
"gatewaysvc": cfg.Reva.Address,
"grpc_client_options": cfg.Reva.GetGRPCClientConfig(),
"multi_tenant_enabled": cfg.Commons.MultiTenantEnabled,
"jwt_secret": cfg.TokenManager.JWTSecret,
"gatewaysvc": cfg.Reva.Address,
"grpc_client_options": cfg.Reva.GetGRPCClientConfig(),
},
"grpc": map[string]interface{}{
"network": cfg.GRPC.Protocol,

Some files were not shown because too many files have changed in this diff Show More