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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
secrets/db.password
secrets/mqtt.password
secrets/mqtt.config
secrets/pubsub.config
hack/mosquitto-passwd.txt

# Ignore image environment file
Expand Down
42 changes: 38 additions & 4 deletions .tekton/integration-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ spec:
TARGET_COMPONENT_NAME="maestro"
REPO_URL=$(echo $SNAPSHOT | jq -r '.components[] | select(.name == "maestro").source.git.url')
REPO_COMMIT=$(echo $SNAPSHOT | jq -r '.components[] | select(.name == "maestro").source.git.revision')
test_output_file=${PWD}/test_output.json
mqtt_test_output_file=${PWD}/mqtt_test_output.json
pubsub_test_output_file=${PWD}/pubsub_test_output.json
grpc_test_output_file=${PWD}/grpc_test_output.json

# Log Vars for Tracibility
echo "REPO_URL: $REPO_URL"
Expand All @@ -84,16 +86,38 @@ spec:
# Generate mqtt config file
echo '{"brokerHost":"localhost:1883","username":"","password":"","topics":{"sourceEvents":"sources/maestro/consumers/+/sourceevents","agentEvents":"sources/maestro/consumers/+/agentevents"}}' > secrets/mqtt.config

# Generate pubsub config file
echo '{"projectID":"maestro-test","endpoint":"localhost:8085","insecure":true,"topics":{"sourceEvents":"projects/maestro-test/topics/sourceevents","sourceBroadcast":"projects/maestro-test/topics/sourcebroadcast"},"subscriptions":{"agentEvents":"projects/maestro-test/subscriptions/agentevents-maestro","agentBroadcast":"projects/maestro-test/subscriptions/agentbroadcast-maestro"}}' > secrets/pubsub.config

# Generate db.password
echo 'foobar-bizz-buzz' > secrets/db.password

# Wait for the pubsub emulator to be ready
echo "[INFO] Waiting for pubsub emulator to be ready for connection"
timeout 5m bash -c 'until curl -s http://localhost:8085 > /dev/null 2>&1; do sleep 2s; done'

# Initialize pubsub topics and subscriptions
export PUBSUB_EMULATOR_HOST=localhost:8085
export PUBSUB_PROJECT_ID=maestro-test
bash hack/init-pubsub-emulator.sh

# Run integration tests with JSON output
make test-integration integration_test_json_output="$test_output_file"
make test-integration \
mqtt_integration_test_json_output="$mqtt_test_output_file" \
pubsub_integration_test_json_output="$pubsub_test_output_file" \
grpc_integration_test_json_output="$grpc_test_output_file"

# Read, process, and write output in accepted format
# Formatting docs: https://redhat-appstudio.github.io/book/ADR/0030-tekton-results-naming-convention.html#test_output-schema-validation
FAILURES=$(cat $test_output_file | jq 'select(.Action == "fail")' | jq -r --slurp 'length')
SUCCESSES=$(cat $test_output_file | jq 'select(.Action == "pass")' | jq -r --slurp 'length')
# Combine results from all three broker tests
MQTT_FAILURES=$(cat $mqtt_test_output_file | jq 'select(.Action == "fail")' | jq -r --slurp 'length')
MQTT_SUCCESSES=$(cat $mqtt_test_output_file | jq 'select(.Action == "pass")' | jq -r --slurp 'length')
PUBSUB_FAILURES=$(cat $pubsub_test_output_file | jq 'select(.Action == "fail")' | jq -r --slurp 'length')
PUBSUB_SUCCESSES=$(cat $pubsub_test_output_file | jq 'select(.Action == "pass")' | jq -r --slurp 'length')
GRPC_FAILURES=$(cat $grpc_test_output_file | jq 'select(.Action == "fail")' | jq -r --slurp 'length')
GRPC_SUCCESSES=$(cat $grpc_test_output_file | jq 'select(.Action == "pass")' | jq -r --slurp 'length')
FAILURES=$((MQTT_FAILURES + PUBSUB_FAILURES + GRPC_FAILURES))
SUCCESSES=$((MQTT_SUCCESSES + PUBSUB_SUCCESSES + GRPC_SUCCESSES))
# Hard-code warnings
WARNINGS=0
RESULT="$(if [[ $FAILURES == 0 ]]; then echo "SUCCESS"; else echo "FAILURE"; fi)"
Expand Down Expand Up @@ -129,6 +153,16 @@ spec:
volumeMounts:
- mountPath: /mosquitto/data
name: mqttdata
- image: gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators
name: pubsub-test
command:
- gcloud
- beta
- emulators
- pubsub
- start
- --host-port=0.0.0.0:8085
- --project=maestro-test
volumes:
- name: pgdata
emptyDir: {}
Expand Down
55 changes: 49 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,25 @@ mqtt_port ?= 1883
mqtt_user ?= maestro
mqtt_password_file ?= ${PWD}/secrets/mqtt.password
mqtt_config_file ?= ${PWD}/secrets/mqtt.config
mqtt_image ?= quay.io/maestro/eclipse-mosquitto:2.0.18

# Pub/Sub emulator configuration
pubsub_host ?= maestro-pubsub.$(namespace)
pubsub_port ?= 8085
pubsub_project_id ?= maestro-test
pubsub_config_file ?= ${PWD}/secrets/pubsub.config
pubsub_image ?= gcr.io/google.com/cloudsdktool/google-cloud-cli:emulators

# Log verbosity level
klog_v:=2

# message driver type, mqtt, grpc or pubsub, default is mqtt.
MESSAGE_DRIVER_TYPE ?= mqtt

# Test output files
unit_test_json_output ?= ${PWD}/unit-test-results.json
mqtt_integration_test_json_output ?= ${PWD}/mqtt-integration-test-results.json
pubsub_integration_test_json_output ?= ${PWD}/pubsub-integration-test-results.json
grpc_integration_test_json_output ?= ${PWD}/grpc-integration-test-results.json

# Prints a list of useful targets.
Expand All @@ -77,6 +89,13 @@ help:
@echo "make lint run golangci-lint"
@echo "make binary compile binaries"
@echo "make install compile binaries and install in GOPATH bin"
@echo "make db/setup setup local PostgreSQL database"
@echo "make db/teardown teardown local PostgreSQL database"
@echo "make mqtt/setup setup local MQTT broker"
@echo "make mqtt/teardown teardown local MQTT broker"
@echo "make pubsub/setup setup local Pub/Sub emulator"
@echo "make pubsub/init initialize Pub/Sub topics and subscriptions"
@echo "make pubsub/teardown teardown local Pub/Sub emulator"
@echo "make run run the application"
@echo "make run/docs run swagger and host the api spec"
@echo "make test run unit tests"
Expand Down Expand Up @@ -206,16 +225,21 @@ test:
# make test-integration TESTFLAGS="-run TestAccounts" acts as TestAccounts* and run TestAccountsGet, TestAccountsPost, etc.
# make test-integration TESTFLAGS="-run TestAccountsGet" runs TestAccountsGet
# make test-integration TESTFLAGS="-short" skips long-run tests
test-integration: test-integration-mqtt test-integration-grpc
test-integration: test-integration-mqtt test-integration-pubsub test-integration-grpc
.PHONY: test-integration

test-integration-mqtt:
BROKER=mqtt MAESTRO_ENV=testing gotestsum --jsonfile-timing-events=$(mqtt_integration_test_json_output) --format $(TEST_SUMMARY_FORMAT) -- -p 1 -ldflags -s -v -timeout 1h $(TESTFLAGS) \
MESSAGE_DRIVER_TYPE=mqtt MESSAGE_DRIVER_CONFIG=$(PWD)/secrets/mqtt.config MAESTRO_ENV=testing gotestsum --jsonfile-timing-events=$(mqtt_integration_test_json_output) --format $(TEST_SUMMARY_FORMAT) -- -count=1 -p 1 -ldflags -s -v -timeout 1h $(TESTFLAGS) \
./test/integration
.PHONY: test-integration-mqtt

test-integration-pubsub:
MESSAGE_DRIVER_TYPE=pubsub MESSAGE_DRIVER_CONFIG=$(PWD)/secrets/pubsub.config PUBSUB_EMULATOR_HOST=localhost:$(pubsub_port) MAESTRO_ENV=testing gotestsum --jsonfile-timing-events=$(pubsub_integration_test_json_output) --format $(TEST_SUMMARY_FORMAT) -- -count=1 -p 1 -ldflags -s -v -timeout 1h $(TESTFLAGS) \
./test/integration
.PHONY: test-integration-pubsub

test-integration-grpc:
BROKER=grpc MAESTRO_ENV=testing gotestsum --jsonfile-timing-events=$(grpc_integration_test_json_output) --format $(TEST_SUMMARY_FORMAT) -- -count=1 -p 1 -ldflags -s -v -timeout 1h $(TESTFLAGS) \
MESSAGE_DRIVER_TYPE=grpc MAESTRO_ENV=testing gotestsum --jsonfile-timing-events=$(grpc_integration_test_json_output) --format $(TEST_SUMMARY_FORMAT) -- -count=1 -p 1 -ldflags -s -v -timeout 1h $(TESTFLAGS) \
./test/integration
.PHONY: test-integration-grpc

Expand All @@ -230,7 +254,11 @@ generate:

run: install
maestro migration
maestro server
@if [ "$(MESSAGE_DRIVER_TYPE)" = "grpc" ]; then \
maestro server --message-broker-type=$(MESSAGE_DRIVER_TYPE); \
else \
maestro server --message-broker-type=$(MESSAGE_DRIVER_TYPE) --message-broker-config-file=./secrets/$(MESSAGE_DRIVER_TYPE).config; \
fi
.PHONY: run

# Run Swagger and host the api docs
Expand Down Expand Up @@ -325,14 +353,29 @@ mqtt/prepare:
.PHONY: mqtt/setup
mqtt/setup: mqtt/prepare
@echo '{"brokerHost":"localhost:1883","username":"$(mqtt_user)","password":"$(shell cat $(mqtt_password_file))","topics":{"sourceEvents":"sources/maestro/consumers/+/sourceevents","agentEvents":"sources/maestro/consumers/+/agentevents"}}' > $(mqtt_config_file)
$(container_tool) run --rm -v $(shell pwd)/hack:/mosquitto/data:z $(MQTT_IMAGE) mosquitto_passwd -c -b /mosquitto/data/mosquitto-passwd.txt $(mqtt_user) $(shell cat $(mqtt_password_file))
$(container_tool) run --name mqtt-maestro -p 1883:1883 -v $(shell pwd)/hack/mosquitto-passwd.txt:/mosquitto/config/password.txt -v $(shell pwd)/hack/mosquitto.conf:/mosquitto/config/mosquitto.conf -d $(MQTT_IMAGE)
$(container_tool) run --rm -v $(shell pwd)/hack:/mosquitto/data:z $(mqtt_image) mosquitto_passwd -c -b /mosquitto/data/mosquitto-passwd.txt $(mqtt_user) $(shell cat $(mqtt_password_file))
$(container_tool) run --name mqtt-maestro -p 1883:1883 -v $(shell pwd)/hack/mosquitto-passwd.txt:/mosquitto/config/password.txt -v $(shell pwd)/hack/mosquitto.conf:/mosquitto/config/mosquitto.conf -d $(mqtt_image)

.PHONY: mqtt/teardown
mqtt/teardown:
$(container_tool) stop mqtt-maestro
$(container_tool) rm mqtt-maestro

.PHONY: pubsub/setup
pubsub/setup:
@mkdir -p ${PWD}/secrets
@echo '{"projectID":"$(pubsub_project_id)","endpoint":"localhost:$(pubsub_port)","insecure":true,"topics":{"sourceEvents":"projects/$(pubsub_project_id)/topics/sourceevents","sourceBroadcast":"projects/$(pubsub_project_id)/topics/sourcebroadcast"},"subscriptions":{"agentEvents":"projects/$(pubsub_project_id)/subscriptions/agentevents-maestro","agentBroadcast":"projects/$(pubsub_project_id)/subscriptions/agentbroadcast-maestro"}}' > $(pubsub_config_file)
$(container_tool) run --name pubsub-maestro -p $(pubsub_port):8085 -e PUBSUB_PROJECT_ID=$(pubsub_project_id) -d $(pubsub_image) gcloud beta emulators pubsub start --host-port=0.0.0.0:8085 --project=$(pubsub_project_id)

.PHONY: pubsub/teardown
pubsub/teardown:
$(container_tool) stop pubsub-maestro
$(container_tool) rm pubsub-maestro

.PHONY: pubsub/init
pubsub/init:
@PUBSUB_EMULATOR_HOST=localhost:$(pubsub_port) PUBSUB_PROJECT_ID=$(pubsub_project_id) bash hack/init-pubsub-emulator.sh

crc/login:
@echo "Logging into CRC"
@crc console --credentials -ojson | jq -r .clusterConfig.adminCredentials.password | oc login --username kubeadmin --insecure-skip-tls-verify=true https://api.crc.testing:6443
Expand Down
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,40 @@ reducing the need for direct access to clusters.

## Run in Local Environment

### Make a build, run postgres and mqtt broker
### Make a build, run postgres and message broker (MQTT or Pub/Sub)

```shell

# 1. build the project

$ go install gotest.tools/gotestsum@latest
$ go install gotest.tools/gotestsum@latest
$ make binary

# 2. run a postgres database locally in docker
# 2. run a postgres database locally in docker

$ make db/setup
$ make db/login

root@f076ddf94520:/# psql -h localhost -U maestro maestro
psql (14.4 (Debian 14.4-1.pgdg110+1))
Type "help" for help.

maestro=# \dt
Did not find any relations.

# 3. run a mqtt broker locally in docker
# 3a. run a MQTT broker locally in docker

$ make mqtt/setup

# OR

# 3b. run a Pub/Sub emulator locally in docker

$ make pubsub/setup

# Initialize topics and subscriptions in the emulator
# Note: Requires google-cloud-pubsub Python package (pip3 install google-cloud-pubsub)
$ make pubsub/init
```

### Run database migrations
Expand Down Expand Up @@ -101,7 +111,12 @@ maestro=# \dt
### Running the Service

```shell
# Run with MQTT broker (default)
$ make run

# OR run with Pub/Sub emulator
# First, ensure the Pub/Sub emulator is running and configured
$ MESSAGE_DRIVER_TYPE=pubsub make run
```

#### List the consumers
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/openshift-online/maestro
go 1.25.0

require (
cloud.google.com/go/pubsub/v2 v2.3.0
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Masterminds/squirrel v1.5.4
Expand Down Expand Up @@ -42,6 +43,7 @@ require (
go.opentelemetry.io/otel/sdk v1.39.0
go.opentelemetry.io/otel/trace v1.39.0
golang.org/x/oauth2 v0.32.0
google.golang.org/api v0.255.0
google.golang.org/grpc v1.78.0
google.golang.org/protobuf v1.36.11
gopkg.in/resty.v1 v1.12.0
Expand All @@ -68,7 +70,6 @@ require (
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.9.0 // indirect
cloud.google.com/go/iam v1.5.2 // indirect
cloud.google.com/go/pubsub/v2 v2.3.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
Expand Down Expand Up @@ -184,7 +185,6 @@ require (
golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.39.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/api v0.255.0 // indirect
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
Expand Down
Loading
Loading