Skip to content

feat: PlaceholderResolver for dynamic placeholder resolution#1188

Draft
matheusandre1 wants to merge 1 commit into
wanaku-ai:mainfrom
matheusandre1:issue1143
Draft

feat: PlaceholderResolver for dynamic placeholder resolution#1188
matheusandre1 wants to merge 1 commit into
wanaku-ai:mainfrom
matheusandre1:issue1143

Conversation

@matheusandre1
Copy link
Copy Markdown
Contributor

@matheusandre1 matheusandre1 commented May 22, 2026

Closes: #1143

Summary by Sourcery

Introduce version placeholder resolution for service catalog dependency files via a shared versions properties file and integrate it across CLI commands, backend deployment, and templates.

New Features:

  • Add PlaceholderResolver utility for resolving ${placeholder} variables from properties-based bindings.
  • Extend ServiceCatalogIndex to support an optional catalog.versions file and resolve placeholders in dependency files within ZIP archives.
  • Add --resolve-versions option to service packaging and deployment CLI commands to substitute dependency placeholders before creating ZIPs.
  • Initialize new service catalogs with a versions.properties skeleton and wire existing service templates to use a shared versions.properties file for dependency versions.

Enhancements:

  • Validate referenced catalog.versions files in ServiceCatalogIndex and expose helper methods to query their presence and path.
  • Resolve dependency placeholders in router backend catalog/template deployment flows when a versions file is present.
  • Refactor and extend ServiceCatalogIndex tests to cover versions file handling and placeholder resolution behavior.

Tests:

  • Add unit tests for PlaceholderResolver covering resolution, placeholder detection, and bindings loading.
  • Add ServiceCatalogIndex tests for versions file discovery, validation, and end-to-end placeholder resolution in dependency files.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 22, 2026

Reviewer's Guide

Introduces a reusable PlaceholderResolver utility and wires version placeholder resolution for service catalog dependency files across CLI packaging/deploy flows, backend deployment, and service templates, including support for an optional catalog.versions file in ServiceCatalogIndex and associated tests and templates.

Sequence diagram for resolving catalog dependency placeholders during backend deploy

sequenceDiagram
    participant Client
    participant ServiceCatalogBean
    participant ServiceCatalogIndex

    Client->>ServiceCatalogBean: deploy(DataStore)
    ServiceCatalogBean->>ServiceCatalogIndex: fromBase64(dataStore.data)
    ServiceCatalogIndex-->>ServiceCatalogBean: index
    ServiceCatalogBean->>ServiceCatalogIndex: hasVersionsFile()
    alt versions file present
        ServiceCatalogBean->>ServiceCatalogBean: Base64.getDecoder().decode(dataStore.data)
        ServiceCatalogBean->>ServiceCatalogIndex: resolvePlaceholders(zipBytes)
        ServiceCatalogIndex-->>ServiceCatalogBean: resolvedZip
        ServiceCatalogBean->>ServiceCatalogBean: Base64.getEncoder().encodeToString(resolvedZip)
        ServiceCatalogBean->>ServiceCatalogBean: dataStore.setData(encodedZip)
    else no versions file
        ServiceCatalogBean-->>Client: deploy continues without placeholder resolution
    end
Loading

Sequence diagram for ServiceCatalogIndex ZIP placeholder resolution

sequenceDiagram
    participant ServiceCatalogIndex
    participant ZipInputStream
    participant PlaceholderResolver
    participant ZipOutputStream

    ServiceCatalogIndex->>ZipInputStream: new ZipInputStream(ByteArrayInputStream(zipBytes))
    loop for each ZipEntry
        ZipInputStream-->>ServiceCatalogIndex: readAllBytes()
        ServiceCatalogIndex->>ServiceCatalogIndex: entries.put(name, bytes)
    end
    ServiceCatalogIndex->>ServiceCatalogIndex: versionsBytes = entries.get(versionsPath)
    alt versionsBytes present
        ServiceCatalogIndex->>PlaceholderResolver: loadBindings(String(versionsBytes))
        PlaceholderResolver-->>ServiceCatalogIndex: bindings
    else no versionsBytes
        ServiceCatalogIndex-->>ServiceCatalogIndex: bindings is null
    end
    alt bindings empty or null
        ServiceCatalogIndex-->>ServiceCatalogIndex: return original zipBytes
    else bindings available
        loop for each system in serviceNames
            ServiceCatalogIndex->>ServiceCatalogIndex: depsPath = getDependenciesFile(system)
            alt depsPath entry exists
                ServiceCatalogIndex->>PlaceholderResolver: resolve(content, bindings)
                PlaceholderResolver-->>ServiceCatalogIndex: resolved
                ServiceCatalogIndex->>ServiceCatalogIndex: entries.put(depsPath, resolvedBytes)
            end
        end
        ServiceCatalogIndex->>ZipOutputStream: new ZipOutputStream(ByteArrayOutputStream())
        loop for each entry
            ZipOutputStream-->>ZipOutputStream: putNextEntry(name)
            ZipOutputStream-->>ZipOutputStream: write(bytes)
        end
        ZipOutputStream-->>ServiceCatalogIndex: baos.toByteArray()
        ServiceCatalogIndex-->>ServiceCatalogIndex: return resolvedZip
    end
Loading

File-Level Changes

Change Details Files
Add PlaceholderResolver utility for resolving ${name} placeholders from properties-based bindings with unit tests.
  • Introduce PlaceholderResolver class with regex-based resolution, hasPlaceholders helper, and multiple loadBindings overloads for Reader, InputStream, and String content.
  • Implement robust error handling via WanakuException when reading properties fails.
  • Add comprehensive PlaceholderResolverTest to cover resolution, unresolved placeholders, null/empty inputs, and end-to-end scenarios.
core/core-util/src/main/java/ai/wanaku/core/util/PlaceholderResolver.java
core/core-util/src/test/java/ai/wanaku/core/util/PlaceholderResolverTest.java
Extend ServiceCatalogIndex to support an optional versions properties file and to resolve placeholders inside dependency files contained in a catalog ZIP.
  • Document new catalog.versions property and placeholder semantics in Javadoc.
  • Add PROP_VERSIONS, getter, and hasVersionsFile to expose versions file reference.
  • Validate catalog.versions path and existence during index parsing, throwing WanakuException if missing in ZIP.
  • Implement resolvePlaceholders(byte[]) to read ZIP entries, load bindings from versions file, and rewrite dependency files with resolved placeholders, returning original bytes when unchanged or no bindings present.
  • Extend ServiceCatalogIndexTest with constants, new tests for versions file presence/absence and resolution behavior, helper ZIP builders for various versions/deps combinations, and a ZIP entry extraction helper.
  • Refactor tests to use INDEX_PROPERTIES_PATH constant instead of hardcoded "index.properties".
core/core-services-api/src/main/java/ai/wanaku/core/services/api/ServiceCatalogIndex.java
core/core-services-api/src/test/java/ai/wanaku/core/services/api/ServiceCatalogIndexTest.java
core/core-services-api/pom.xml
Resolve version placeholders during CLI service packaging and deployment when a versions.properties file is configured.
  • Add --resolve-versions flag (default true) to ServicePackage and ServiceDeploy commands to control placeholder resolution.
  • In both commands, when enabled and catalog.versions points to an existing file, load bindings via PlaceholderResolver and resolve placeholders in each system's dependencies file in-place before zipping.
  • Add shared resolveDependencyPlaceholders helper in each command to iterate systems, locate catalog.dependencies. files, and rewrite content only when changes occur.
  • Emit informative log messages on successful resolution and errors, failing commands on resolution errors.
apps/wanaku-cli/src/main/java/ai/wanaku/cli/main/commands/service/ServicePackage.java
apps/wanaku-cli/src/main/java/ai/wanaku/cli/main/commands/service/ServiceDeploy.java
Ensure backend deployment paths also resolve dependency placeholders based on catalog.versions during catalog/template deployment.
  • Update ServiceTemplateBean.deploy and ServiceCatalogBean.deploy to parse ServiceCatalogIndex, then, if a versions file is declared, decode ZIP data, call ServiceCatalogIndex.resolvePlaceholders, and re-encode only when changes are made.
  • Extend ServiceTemplateBean.buildCatalogZip to load bindings from the versions file inside the template ZIP and resolve placeholders in dependency entries when present.
apps/wanaku-router-backend/src/main/java/ai/wanaku/backend/api/v1/servicecatalog/ServiceTemplateBean.java
apps/wanaku-router-backend/src/main/java/ai/wanaku/backend/api/v1/servicecatalog/ServiceCatalogBean.java
Update service initialization and existing service templates to declare catalog.versions and provide shared versions.properties and dependency placeholder guidance.
  • Modify ServiceInit.createIndexProperties to always set catalog.versions=versions.properties and generate a versions.properties skeleton with documentation and an example camel.version entry.
  • Update generated *.dependencies.txt skeleton to document use of ${camel.version} placeholders.
  • Add catalog.versions=versions.properties to all existing service template index.properties files so they participate in placeholder resolution.
  • Introduce a shared services/service-templates/src/main/services/versions.properties with standard version keys like camel.version, forage.version, and artemis.version.
  • Ensure template dependency files (various *.dependencies.txt) are present/updated to align with the new placeholder model.
apps/wanaku-cli/src/main/java/ai/wanaku/cli/main/commands/service/ServiceInit.java
services/service-templates/src/main/services/aws-s3-resource/index.properties
services/service-templates/src/main/services/azure-files-resource/index.properties
services/service-templates/src/main/services/ftp-resource/index.properties
services/service-templates/src/main/services/github-pr-comments-tool/index.properties
services/service-templates/src/main/services/github-pullrequest-source-tool/index.properties
services/service-templates/src/main/services/google-vertexai-sink-tool/index.properties
services/service-templates/src/main/services/jira-add-comment-tool/index.properties
services/service-templates/src/main/services/jira-add-issue-tool/index.properties
services/service-templates/src/main/services/jira-update-issue-tool/index.properties
services/service-templates/src/main/services/jms-tool/index.properties
services/service-templates/src/main/services/kafka-tool/index.properties
services/service-templates/src/main/services/mail-sink-tool/index.properties
services/service-templates/src/main/services/rabbitmq-tool/index.properties
services/service-templates/src/main/services/sftp-resource/index.properties
services/service-templates/src/main/services/tavily-search-tool/index.properties
services/service-templates/src/main/services/telegram-sink-tool/index.properties
services/service-templates/src/main/services/watson-nlu-sink-tool/index.properties
services/service-templates/src/main/services/versions.properties
services/service-templates/src/main/services/aws-s3-resource/aws-s3/aws-s3.dependencies.txt
services/service-templates/src/main/services/azure-files-resource/azure-files/azure-files.dependencies.txt
services/service-templates/src/main/services/ftp-resource/ftp/ftp.dependencies.txt
services/service-templates/src/main/services/github-pr-comments-tool/github-pr-comments/github-pr-comments.dependencies.txt
services/service-templates/src/main/services/github-pullrequest-source-tool/github-pullrequest-source/github-pullrequest-source.dependencies.txt
services/service-templates/src/main/services/google-vertexai-sink-tool/google-vertexai-sink/google-vertexai-sink.dependencies.txt
services/service-templates/src/main/services/jira-add-comment-tool/jira-add-comment/jira-add-comment.dependencies.txt
services/service-templates/src/main/services/jira-add-issue-tool/jira-add-issue/jira-add-issue.dependencies.txt
services/service-templates/src/main/services/jira-update-issue-tool/jira-update-issue/jira-update-issue.dependencies.txt
services/service-templates/src/main/services/jms-tool/jms/jms.dependencies.txt
services/service-templates/src/main/services/kafka-tool/kafka/kafka.dependencies.txt
services/service-templates/src/main/services/mail-sink-tool/mail-sink/mail-sink.dependencies.txt
services/service-templates/src/main/services/rabbitmq-tool/rabbitmq/rabbitmq.dependencies.txt
services/service-templates/src/main/services/sftp-resource/sftp/sftp.dependencies.txt
services/service-templates/src/main/services/tavily-search-tool/tavily-search/tavily-search.dependencies.txt
services/service-templates/src/main/services/telegram-sink-tool/telegram-sink/telegram-sink.dependencies.txt
services/service-templates/src/main/services/watson-nlu-sink-tool/watson-nlu-sink/watson-nlu-sink.dependencies.txt

Assessment against linked issues

Issue Objective Addressed Explanation
#1143 Add support in service catalogs for declaring dependency versions via placeholders (e.g. ${camel.version}) backed by a shared versions properties file.
#1143 Introduce pre/post-processing to resolve placeholders to concrete versions when packaging and deploying service catalogs, while leaving unknown placeholders and non-placeholder hard-coded versions untouched.
#1143 Keep placeholders optional so catalogs with explicit, hard-coded versions remain valid and functional without requiring a versions file.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Signed-off-by: Matheus André <matheusandr2@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support version placeholders in service catalogs

1 participant