Koncur - A test harness for Konveyor tools that "concurs with your expected results!"
Koncur is a declarative test harness for running and validating end-to-end tests for Konveyor tools (Kantra, Tackle, Kai). Define what you want to analyze, not how to run commands.
- Declarative test definitions - Specify application, label selector, and analysis mode
- Multiple execution targets - Kantra CLI, Tackle Hub API, Tackle UI, Kai RPC, VSCode extension
- Flexible target configuration - Separate target config from test definitions
- Exact match validation - Compare actual output against expected RuleSets
- Clear diff output - See exactly what differs when tests fail
- Multiple input formats - Support for inline expected results or file references
- Built on Konveyor types - Uses analyzer-lsp RuleSet structures directly
- Automatic output filtering - Filters empty rulesets for cleaner expected outputs
- Test output management - Clean up old test runs with the
cleancommand
go build -o koncur ./cmd/koncur# my-test.yaml
name: "Sample Kantra Test"
description: "Test cloud-readiness analysis"
analysis:
application: /path/to/application/source
labelSelector: "konveyor.io/target=quarkus"
analysisMode: source-only
expect:
exitCode: 0
output:
result:
- name: cloud-readiness
violations:
session-00001:
description: "Avoid use of HttpSession"
category: mandatory
incidents:
- uri: "file:///src/main/java/MyServlet.java"
lineNumber: 42# Use default target (kantra)
koncur run my-test.yaml
# Specify target type
koncur run my-test.yaml --target kantra
# Use a target configuration file
koncur run my-test.yaml --target-config target-tackle-hub.yamlname: "Test Name"
description: "Optional description"
analysis:
# Application to analyze (file path or git URL)
application: /path/to/source
# Optional: Label selector expression
labelSelector: "konveyor.io/target=quarkus"
# Analysis mode: source-only | full
analysisMode: source-only
# Optional: Execution timeout (default: 5m)
timeout: 10m
# Optional: Work directory (default: .koncur/output)
workDir: /tmp/my-tests
expect:
exitCode: 0
output:
# Option 1: Inline expected RuleSets
result:
- name: ruleset-name
violations: {...}
# Option 2: Reference to external file
file: /absolute/path/to/expected.yamlTarget configuration is separate from test definitions, allowing the same test to run against different targets/environments.
type: kantra
kantra:
binaryPath: /usr/local/bin/kantra # Optional
# forceLocal: true # optional: pass --run-local=true for local/containerless mode (default is --run-local=false)
# Container image overrides (optional, for container mode)
# javaProviderImage: my-java-provider:dev
# goProviderImage: my-go-provider:dev
# pythonProviderImage: my-python-provider:dev
# nodejsProviderImage: my-nodejs-provider:dev
# runnerImage: my-kantra:devtype: tackle-hub
tackleHub:
url: https://tackle-hub.example.com
username: admin
password: secret
# Or use token:
# token: your-api-token
# Override component images (koncur patches the Tackle CR automatically)
images:
analyzer: my-analyzer:dev
javaProvider: my-java-provider:dev
goProvider: my-go-provider:dev
pythonProvider: my-python-provider:dev
nodejsProvider: my-nodejs-provider:dev
# csharpProvider: my-csharp-provider:dev
# runner: my-kantra:dev
# discoveryAddon: my-discovery:dev
# platformAddon: my-platform:devWhen images is specified, koncur patches the Tackle Custom Resource on the cluster via kubectl and waits for the Hub to become ready before running tests. See Local Testing with Custom Images for detailed workflows.
Not Implemented
type: tackle-ui
tackleUI:
url: https://tackle.example.com
username: admin
password: secret
browser: chrome # chrome or firefox
headless: trueNot Implemented
type: kai-rpc
kaiRPC:
host: localhost
port: 8080** Not Implemented **
type: vscode
vscode:
binaryPath: /usr/local/bin/code # Optional
extensionId: konveyor.konveyor-analyzer
workspaceDir: /path/to/workspace # OptionalExecute a test and validate output against expected results.
koncur run testdata/examples/sample_test.yamlValidate a test definition without running it.
koncur validate testdata/examples/sample_test.yamlGenerate expected outputs by running tests and capturing their results. This command:
- Finds all
test.yamlfiles in the specified directory - Executes each test using the specified target
- Filters out empty rulesets (no violations, insights, or tags)
- Saves the filtered output as
expected-output.yamlin each test directory - Updates test definitions to use file-based expectations
# Generate expected outputs for all tests
koncur generate -d ./tests
# Generate for a specific test
koncur generate -d ./tests/my-test
# Filter by test name pattern
koncur generate -d ./tests --filter "tackle"
# Dry run (show what would be done)
koncur generate -d ./tests --dry-run
# Use a specific target
koncur generate -d ./tests --target kantraFlags:
-d, --test-dir- Directory containing test definitions (default:./tests)-f, --filter- Filter tests by name pattern--dry-run- Show what would be done without executing-t, --target- Target type to use (default:kantra)
Clean up old test run outputs from the .koncur/output directory.
By default, keeps the most recent run for each test and deletes older ones.
# Clean old test runs (keeps latest for each test)
koncur clean
# Preview what would be deleted
koncur clean --dry-run
# Remove all output directories
koncur clean --all
# Preview removing everything
koncur clean --all --dry-runFlags:
--all- Remove all output directories (not just old ones)--dry-run- Show what would be deleted without actually deleting
-v, --verbose- Enable verbose logging
See testdata/examples/ for sample test definitions.
pkg/config/- Test definition types and loadingpkg/targets/- Target executors (Kantra, Tackle, Kai)pkg/parser/- Output parsing (RuleSets)pkg/validator/- Exact match validation with diffpkg/cli/- CLI commands
# Build
go build -o koncur ./cmd/koncur
# Run tests
go test ./...
# Validate a test definition
./koncur validate testdata/examples/sample_test.yamlKoncur includes a Makefile for quickly setting up and testing against a local Tackle Hub instance running in Kind (Kubernetes in Docker).
# Complete setup: create cluster, install hub, build binary
make setup
# This runs:
# 1. make kind-create - Creates Kind cluster with ingress
# 2. make hub-install - Installs Tackle Hub with OLM (auth disabled)
# 3. make build - Builds the koncur binaryTo install Tackle Hub with authentication enabled:
# Complete setup with auth: create cluster, install hub with auth required, build binary
make setup-auth
# This runs:
# 1. make kind-create - Creates Kind cluster with ingress
# 2. make hub-install-auth - Installs Tackle Hub with auth required
# 3. make build - Builds the koncur binaryThe hub provides its own built-in OIDC provider — no separate identity server
is deployed. Enabling auth just sets feature_auth_required: "true" on the
Tackle CR, which makes the hub reject unauthenticated API requests.
Default credentials (seeded by the hub's built-in OIDC provider):
- Username:
admin - Password:
admin
Once setup is complete, Tackle Hub is accessible via:
Ingress (HTTP):
- Hub API:
http://localhost:8080/hub - Hub UI:
http://localhost:8080
Port-forward (alternative):
make hub-forward
# Hub will be available at http://localhost:8081Access is the same with or without auth; when auth is enabled, API requests must authenticate (koncur uses HTTP Basic auth with the credentials from the target config).
# Run a test against Tackle Hub
make test-hub
# Or run manually with koncur
./koncur run tests/tackle-testapp-with-deps/test.yaml \
--target-config .koncur/config/target-tackle-hub.yamlYou can package the test suite into a portable archive for running tests without the full repo:
# Build the archive (~200KB)
make test-archive
# Run tests from the archive against any target
./koncur run --test-archive koncur-tests.tar.gz \
-t tackle-hub --target-config .koncur/config/target-tackle-hub.yamlSee Local Testing with Custom Images for the full portable testing workflow.
Setup & Teardown:
make setup- Complete setup (cluster + hub + build, no auth)make setup-auth- Complete setup with authentication requiredmake teardown- Complete teardown (uninstall hub + delete cluster)
Cluster Management:
make kind-create- Create Kind cluster with ingress-nginxmake kind-delete- Delete the Kind cluster
Tackle Hub:
make hub-install- Install Tackle Hub with auth disabledmake hub-install-auth- Install Tackle Hub with auth required (built-in OIDC, admin/admin)make hub-uninstall- Uninstall Tackle Hubmake hub-status- Check Tackle Hub statusmake hub-forward- Port-forward to access Hub at :8081
Build & Test:
make build- Build koncur binarymake test-hub- Run tackle-testapp test against Hubmake clean- Clean build artifacts and test outputs
The Makefile uses these configurable variables:
# Cluster Configuration
KIND_CLUSTER_NAME ?= koncur-test
KONVEYOR_NAMESPACE ?= konveyor-tackle
KUBECTL ?= kubectl
# Image Overrides (optional)
# Override any image by setting environment variables:
HUB ?= quay.io/konveyor/tackle2-hub:latest
ANALYZER_ADDON ?= quay.io/konveyor/tackle2-addon-analyzer:latest
CSHARP_PROVIDER_IMG ?= quay.io/konveyor/c-sharp-provider:latest
GO_PROVIDER_IMG ?= quay.io/konveyor/go-external-provider:latest
PYTHON_PROVIDER_IMG ?= quay.io/konveyor/python-external-provider:latest
NODEJS_PROVIDER_IMG ?= quay.io/konveyor/nodejs-external-provider:latest
JAVA_PROVIDER_IMG ?= quay.io/konveyor/java-external-provider:latest
RUNNER_IMG ?= quay.io/konveyor/kantra:latest
DISCOVERY_ADDON ?= quay.io/konveyor/tackle2-addon-discovery:latest
PLATFORM_ADDON ?= quay.io/konveyor/tackle2-addon-platform:latestRecommended: target config (patches the Tackle CR automatically)
Put image overrides in your target config and koncur will patch the Tackle CR and wait for readiness before running tests:
# target-tackle-hub.yaml
type: tackle-hub
tackleHub:
url: http://localhost:8080/hub
images:
analyzer: my-analyzer:dev
javaProvider: my-java-provider:dev./koncur run tests -t tackle-hub --target-config target-tackle-hub.yamlAlternative: Makefile env vars (at install time)
Override images when first installing Hub:
ANALYZER_ADDON=my-analyzer:dev make hub-installFor a complete guide on building, loading, and testing with locally-built images (including Kind image loading and iteration workflows), see Local Testing with Custom Images.
Without auth - the default target config (.koncur/config/target-tackle-hub.yaml):
type: tackle-hub
tackleHub:
url: http://localhost:8080/hub
token: ""
mavenSettings: settings.xmlWith auth - when using make setup-auth, the target config must include
username and password (koncur authenticates with HTTP Basic auth):
type: tackle-hub
tackleHub:
url: http://localhost:8080/hub
username: admin
password: admin
mavenSettings: settings.xmlA token may be provided instead of username/password to authenticate
with a bearer token (e.g. a hub personal access token). When targeting a
remote hub served over HTTPS with a self-signed certificate, set
insecure: true to skip TLS verification.
The make hub-install target automatically:
- Installs OLM (Operator Lifecycle Manager)
- Installs Tackle Operator from main branch
- Creates Tackle CR with:
- Authentication disabled (
feature_auth_required: "false") - Cache storage configured (10Gi RWX PV)
- Resource limits optimized for testing (100m CPU for providers)
- All component images configurable via environment variables
- Authentication disabled (
- Patches ingress to disable SSL redirect (allows HTTP access at
http://localhost:8080) - Waits for readiness with automatic health checks
The make hub-install-auth target does all of the above, but sets
feature_auth_required: "true" on the Tackle CR instead. The hub's built-in
OIDC provider seeds a default admin/admin user at startup — no additional
setup is required.
Ingress redirecting to HTTPS:
- The Makefile automatically patches the ingress to disable SSL redirect
- If you see 308 redirects, run:
kubectl annotate ingress tackle -n konveyor-tackle nginx.ingress.kubernetes.io/ssl-redirect="false" --overwrite
Ingress not working:
- Ensure Kind cluster was created with ingress support:
kubectl get pods -n ingress-nginx - Verify ingress controller is running and ready
- Check ingress resource:
kubectl get ingress -n konveyor-tackle
Operator not ready:
- Check operator logs:
kubectl logs -n konveyor-tackle -l name=tackle-operator - Verify CRD installed:
kubectl get crd tackles.tackle.konveyor.io
Hub pods not starting:
- Check pod status:
make hub-status - View pod logs:
kubectl logs -n konveyor-tackle -l app.kubernetes.io/name=tackle-hub
Auth setup: requests failing with 401:
- Verify the target config includes
username: admin/password: admin(or a validtoken) - Confirm auth is enforced:
curl -s -o /dev/null -w '%{http_code}' http://localhost:8081/applicationsshould return401without credentials and200with-u admin:admin
Apache 2.0