Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@ DEV_TAG ?= dev-$(GIT_COMMIT)
BUILD_DATE := $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')

# LDFLAGS for build
# Note: Variables are in package main, so use main.varName (not full import path)
# Version info is set in pkg/version package for use across the codebase
VERSION_PKG := github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/version
LDFLAGS := -w -s
LDFLAGS += -X main.version=$(VERSION)
LDFLAGS += -X main.commit=$(GIT_COMMIT)
LDFLAGS += -X main.buildDate=$(BUILD_DATE)
LDFLAGS += -X $(VERSION_PKG).Version=$(VERSION)
LDFLAGS += -X $(VERSION_PKG).Commit=$(GIT_COMMIT)
LDFLAGS += -X $(VERSION_PKG).BuildDate=$(BUILD_DATE)
ifneq ($(GIT_TAG),)
LDFLAGS += -X main.tag=$(GIT_TAG)
LDFLAGS += -X $(VERSION_PKG).Tag=$(GIT_TAG)
endif

# Go parameters
Expand Down
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,12 +157,26 @@ A HyperFleet Adapter requires several files for configuration:

The adapter supports multiple configuration sources with the following priority order:

1. **Environment Variable** (`ADAPTER_CONFIG_FILE`) - Highest priority
2. **Default location Mount** (`/etc/adapter/adapterconfig.yaml`)
1. **Environment Variable** (`ADAPTER_CONFIG_PATH`) - Highest priority
2. **ConfigMap Mount** (`/etc/adapter/config/adapter-deployment-config.yaml`)

See `configs/adapterconfig-template.yaml` for configuration template.

#### Broker Configuration
### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `ADAPTER_CONFIG_PATH` | Path to adapter configuration file | `/etc/adapter/config/adapter-deployment-config.yaml` |
| `HYPERFLEET_USER_AGENT` | Custom User-Agent string for HTTP clients (Maestro, HyperFleet API) | `hyperfleet-adapter/{version}` |
| `HYPERFLEET_API_BASE_URL` | Base URL for HyperFleet API | (from config) |
| `HYPERFLEET_API_VERSION` | API version for HyperFleet API | (from config) |
| `BROKER_SUBSCRIPTION_ID` | Message broker subscription ID | (required) |
| `BROKER_TOPIC` | Message broker topic | (required) |
| `LOG_LEVEL` | Log level (debug, info, warn, error) | `info` |
| `LOG_FORMAT` | Log format (text, json) | `json` |
| `LOG_OUTPUT` | Log output (stdout, stderr) | `stdout` |
Comment on lines +165 to +177
Copy link

@coderabbitai coderabbitai bot Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Document HYPERFLEET_API_TOKEN here if the template requires it.
Integration tests now set this variable; if it’s required for API auth, the env var table should include it (with default/required status).

📌 Suggested doc update
 | `HYPERFLEET_API_VERSION` | API version for HyperFleet API | (from config) |
+| `HYPERFLEET_API_TOKEN` | API token for HyperFleet API authentication | (required) |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `ADAPTER_CONFIG_PATH` | Path to adapter configuration file | `/etc/adapter/config/adapter-deployment-config.yaml` |
| `HYPERFLEET_USER_AGENT` | Custom User-Agent string for HTTP clients (Maestro, HyperFleet API) | `hyperfleet-adapter/{version}` |
| `HYPERFLEET_API_BASE_URL` | Base URL for HyperFleet API | (from config) |
| `HYPERFLEET_API_VERSION` | API version for HyperFleet API | (from config) |
| `BROKER_SUBSCRIPTION_ID` | Message broker subscription ID | (required) |
| `BROKER_TOPIC` | Message broker topic | (required) |
| `LOG_LEVEL` | Log level (debug, info, warn, error) | `info` |
| `LOG_FORMAT` | Log format (text, json) | `json` |
| `LOG_OUTPUT` | Log output (stdout, stderr) | `stdout` |
### Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `ADAPTER_CONFIG_PATH` | Path to adapter configuration file | `/etc/adapter/config/adapter-deployment-config.yaml` |
| `HYPERFLEET_USER_AGENT` | Custom User-Agent string for HTTP clients (Maestro, HyperFleet API) | `hyperfleet-adapter/{version}` |
| `HYPERFLEET_API_BASE_URL` | Base URL for HyperFleet API | (from config) |
| `HYPERFLEET_API_VERSION` | API version for HyperFleet API | (from config) |
| `HYPERFLEET_API_TOKEN` | API token for HyperFleet API authentication | (required) |
| `BROKER_SUBSCRIPTION_ID` | Message broker subscription ID | (required) |
| `BROKER_TOPIC` | Message broker topic | (required) |
| `LOG_LEVEL` | Log level (debug, info, warn, error) | `info` |
| `LOG_FORMAT` | Log format (text, json) | `json` |
| `LOG_OUTPUT` | Log output (stdout, stderr) | `stdout` |
🤖 Prompt for AI Agents
In `@README.md` around lines 155 - 167, Add a missing environment variable row for
HYPERFLEET_API_TOKEN to the Environment Variables table so the README documents
that API auth token; update the table near the existing entries like
ADAPTER_CONFIG_PATH and HYPERFLEET_API_BASE_URL to include
`HYPERFLEET_API_TOKEN` with a short description such as "API authentication
token for HyperFleet" and mark its default as "(required)" or provide the actual
default if applicable; ensure the new row follows the same column ordering and
formatting as the other rows (Variable | Description | Default).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xueli181114, understood! I'll skip that suggestion.


🧠 Learnings used
Learnt from: xueli181114
Repo: openshift-hyperfleet/hyperfleet-adapter PR: 17
File: internal/config_loader/validator_schema.go:126-133
Timestamp: 2025-12-11T02:06:33.975Z
Learning: In the hyperfleet-adapter repository (Go), environment variable validation for required parameters (those with `env.*` source, `Required=true`, and no default) occurs at config load time in `internal/config_loader/validator_schema.go`. This is intentional design - environment variables must be set before deployment, and the validation ensures fail-fast behavior with clear error messages.


### Broker Configuration

Broker configuration is managed separately and can be provided via:

Expand Down
30 changes: 12 additions & 18 deletions cmd/adapter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,12 @@ import (
"github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/health"
"github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/logger"
"github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/otel"
"github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/version"
"github.com/openshift-hyperfleet/hyperfleet-broker/broker"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// Build-time variables set via ldflags
var (
version = "0.1.0"
commit = "none"
buildDate = "unknown"
tag = "none"
)

// Command-line flags
var (
configPath string
Expand Down Expand Up @@ -107,11 +100,12 @@ and HyperFleet API calls.`,
Use: "version",
Short: "Print version information",
Run: func(cmd *cobra.Command, args []string) {
info := version.Info()
fmt.Printf("HyperFleet Adapter\n")
fmt.Printf(" Version: %s\n", version)
fmt.Printf(" Commit: %s\n", commit)
fmt.Printf(" Built: %s\n", buildDate)
fmt.Printf(" Tag: %s\n", tag)
fmt.Printf(" Version: %s\n", info.Version)
fmt.Printf(" Commit: %s\n", info.Commit)
fmt.Printf(" Built: %s\n", info.BuildDate)
fmt.Printf(" Tag: %s\n", info.Tag)
},
}

Expand Down Expand Up @@ -142,7 +136,7 @@ func buildLoggerConfig(component string) logger.Config {
}

cfg.Component = component
cfg.Version = version
cfg.Version = version.Version

return cfg
}
Expand All @@ -159,12 +153,12 @@ func runServe() error {
return fmt.Errorf("failed to create logger: %w", err)
}

log.Infof(ctx, "Starting Hyperfleet Adapter version=%s commit=%s built=%s tag=%s", version, commit, buildDate, tag)
log.Infof(ctx, "Starting Hyperfleet Adapter version=%s commit=%s built=%s tag=%s", version.Version, version.Commit, version.BuildDate, version.Tag)

// Load adapter configuration
// If configPath flag is empty, config_loader.Load will read from ADAPTER_CONFIG_PATH env var
log.Info(ctx, "Loading adapter configuration...")
adapterConfig, err := config_loader.Load(configPath, config_loader.WithAdapterVersion(version))
adapterConfig, err := config_loader.Load(configPath, config_loader.WithAdapterVersion(version.Version))
if err != nil {
errCtx := logger.WithErrorField(ctx, err)
log.Errorf(errCtx, "Failed to load adapter configuration")
Expand All @@ -187,7 +181,7 @@ func runServe() error {
sampleRatio := otel.GetTraceSampleRatio(log, ctx)

// Initialize OpenTelemetry for trace_id/span_id generation and HTTP propagation
tp, err := otel.InitTracer(adapterConfig.Metadata.Name, version, sampleRatio)
tp, err := otel.InitTracer(adapterConfig.Metadata.Name, version.Version, sampleRatio)
if err != nil {
errCtx := logger.WithErrorField(ctx, err)
log.Errorf(errCtx, "Failed to initialize OpenTelemetry")
Expand Down Expand Up @@ -223,8 +217,8 @@ func runServe() error {
// Start metrics server with build info
metricsServer := health.NewMetricsServer(log, MetricsServerPort, health.MetricsConfig{
Component: adapterConfig.Metadata.Name,
Version: version,
Commit: commit,
Version: version.Version,
Commit: version.Commit,
})
if err := metricsServer.Start(ctx); err != nil {
errCtx := logger.WithErrorField(ctx, err)
Expand Down
105 changes: 105 additions & 0 deletions configs/adapter-deployment-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# HyperFleet Adapter Deployment Configuration
#
# This file contains ONLY infrastructure and deployment-related settings:
# - Client connections (Maestro, HyperFleet API, Kubernetes)
# - Authentication and TLS configuration
# - Connection timeouts and retry policies
#
# NOTE: This is a SAMPLE configuration file for reference and local development.
# It is NOT automatically packaged with the container image (see Dockerfile).
#
# In production, provide configuration via one of these methods:
# 1. ADAPTER_CONFIG_PATH environment variable pointing to a config file (highest priority)
# 2. ConfigMap mounted at /etc/adapter/config/adapter-deployment-config.yaml
#
# Example Kubernetes deployment:
# env:
# - name: ADAPTER_CONFIG_PATH
# value: /etc/adapter/config/adapter-deployment-config.yaml
# volumeMounts:
# - name: config
# mountPath: /etc/adapter/config
#
# For business logic configuration (params, preconditions, resources, post-actions),
# use a separate business config file. See configs/adapter-config-template.yaml

apiVersion: hyperfleet.redhat.com/v1alpha1
kind: AdapterDeploymentConfig
metadata:
name: hyperfleet-adapter
namespace: hyperfleet-system
labels:
hyperfleet.io/component: adapter

spec:
adapter:
version: "0.1.0"

# Client configurations for external services
clients:
# Maestro transport client configuration
maestro:
# gRPC server address
# Environment variable: HYPERFLEET_MAESTRO_GRPC_SERVER_ADDRESS
# Flag: --maestro-grpc-server-address
grpcServerAddress: "maestro-grpc.maestro.svc.cluster.local:8090"

# HTTPS server address for REST API operations (optional)
# Environment variable: HYPERFLEET_MAESTRO_HTTP_SERVER_ADDRESS
httpServerAddress: "https://maestro-api.maestro.svc.cluster.local"

# Source identifier for CloudEvents routing (must be unique across adapters)
# Environment variable: HYPERFLEET_MAESTRO_SOURCE_ID
sourceId: "hyperfleet-adapter"

# Client identifier (defaults to sourceId if not specified)
# Environment variable: HYPERFLEET_MAESTRO_CLIENT_ID
clientId: "hyperfleet-adapter-client"

# Authentication configuration
auth:
type: "tls" # TLS certificate-based mTLS

tlsConfig:
# gRPC TLS configuration
# Certificate paths (mounted from Kubernetes secrets)
# Environment variable: HYPERFLEET_MAESTRO_CA_FILE
caFile: "/etc/maestro/certs/grpc/ca.crt"

# Environment variable: HYPERFLEET_MAESTRO_CERT_FILE
certFile: "/etc/maestro/certs/grpc/client.crt"

# Environment variable: HYPERFLEET_MAESTRO_KEY_FILE
keyFile: "/etc/maestro/certs/grpc/client.key"

# Server name for TLS verification
# Environment variable: HYPERFLEET_MAESTRO_SERVER_NAME
serverName: "maestro-grpc.maestro.svc.cluster.local"

# HTTP API TLS configuration (may use different CA than gRPC)
# If not set, falls back to caFile for backwards compatibility
# Environment variable: HYPERFLEET_MAESTRO_HTTP_CA_FILE
httpCaFile: "/etc/maestro/certs/https/ca.crt"

# Connection settings
timeout: "30s"
retryAttempts: 3
retryBackoff: "exponential"

# Keep-alive for long-lived gRPC connections
keepalive:
time: "30s"
timeout: "10s"
permitWithoutStream: true

# HyperFleet HTTP API client
hyperfleetApi:
timeout: 2s
retryAttempts: 3
retryBackoff: exponential

# Kubernetes client (for direct K8s resources)
kubernetes:
apiVersion: "v1"
# Uses in-cluster service account by default
# Or set kubeconfig path via KUBECONFIG environment variable
87 changes: 0 additions & 87 deletions configs/adapter.yaml

This file was deleted.

Loading