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
59 changes: 59 additions & 0 deletions .github/workflows/integration-tests-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Integration Tests
on:
push:
branches:
- "master"
paths:
- "**.go"
- "**.golden"
- "Makefile"
- "docker-compose.yaml"
- ".github/workflows/integration-tests-ci.yml"
pull_request:
branches:
- "master"
paths:
Copy link
Member

Choose a reason for hiding this comment

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

It might make sense to invert this list with that of a list of files to ignore.

- "**.go"
- "**.golden"
- "Makefile"
- "docker-compose.yaml"
- ".github/workflows/integration-tests-ci.yml"
workflow_dispatch:
inputs:
logLevel:
description: "Log level"
required: true
default: "warning"

jobs:
integration-tests:
name: Integration tests
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.23"
- name: Install Docker Compose
run: |
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create k8s Kind Cluster
uses: helm/[email protected]
with:
cluster_name: "kind-cluster"
- name: Create k8s meshery namespace
run: kubectl create namespace meshery
- name: Apply k8s resources
run: |
kubectl apply -f https://raw.githubusercontent.com/meshery/meshery/refs/heads/master/install/kubernetes/helm/meshery-operator/crds/crds.yaml
kubectl --namespace meshery apply -f ./integration-test-yamls/meshsync.yaml
- name: Run integration tests
run: |
make integration-test
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ test: check
go test -failfast --short ./... -race
## Lint check Golang
lint:
golangci-lint run ./...
golangci-lint run ./...
## Runs integration tests
## it does not start kind (neither install CRD), only starts nats
## hence to successful run you need a k8s cluster (with installed meshsync CRD);
## docker compose exposes nats on default ports to host, so they must be available
integration-test:
docker compose up -d || exit 1
sleep 4
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The sleep 4 command uses a hardcoded value. It would be better to use a variable or a more dynamic approach to ensure NATS is ready before running the tests. Consider using docker compose ps and checking the status of the NATS container.

# Example using a loop and docker compose ps (untested):
# ready=false
# until $ready; do
#   status=$$(docker compose ps --services --filter "status=running" nats)
#   if [[ "$${status}" == "nats" ]]; then
#     ready=true
#   else
#     sleep 1
#   fi
# done
sleep 4

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks gemi 🤗 , the idea is good, but the suggested snippet is not working.
I briefly tried to play a little with similar ideas, but didn't succeed 😄 , so sleep 4 is the best option for now 👍

Copy link
Member

Choose a reason for hiding this comment

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

This is a good comment from Gemini. While use of sleep() is almost never desired, replacement of its use can sometimes be more trouble than it's worth.

Copy link
Contributor

Choose a reason for hiding this comment

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

You're welcome! I understand the challenges with dynamic checks in docker compose. While sleep 4 might be the most practical option for now, keep an eye on its reliability as the environment evolves. If the tests become flaky, revisiting the dynamic check might be necessary.

RUN_INTEGRATION_TESTS=true go test -v -count=1 -run Integration .
docker compose down
15 changes: 15 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3.8'

# this docker compose is solely for local run with main_test.go
services:
nats:
image: nats:2.11-alpine3.21
container_name: nats
ports:
- "4222:4222" # client connections
- "8222:8222" # HTTP monitoring (optional)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8222/varz"]
interval: 5s
timeout: 3s
retries: 5
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/myntra/pipeline v0.0.0-20180618182531-2babf4864ce8
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
golang.org/x/net v0.36.0
gorm.io/gorm v1.25.12
Expand Down Expand Up @@ -134,6 +135,7 @@ require (
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
Expand Down
15 changes: 15 additions & 0 deletions integration-test-yamls/meshsync.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Source: meshery-operator/charts/meshery-meshsync/templates/meshery_v1alpha1_broker_cr.tpl
apiVersion: meshery.io/v1alpha1
kind: MeshSync
metadata:
name: meshery-meshsync
namespace: meshery
spec:
size: 1
broker:
native:
name: meshery-broker
namespace: meshery
watch-list:
data:
whitelist: "[{\"Resource\":\"grafanas.v1beta1.grafana.integreatly.org\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"prometheuses.v1.monitoring.coreos.com\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"namespaces.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"configmaps.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"nodes.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"secrets.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"persistentvolumes.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"persistentvolumeclaims.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"replicasets.v1.apps\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"pods.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"services.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"deployments.v1.apps\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"statefulsets.v1.apps\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"daemonsets.v1.apps\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"ingresses.v1.networking.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"endpoints.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"endpointslices.v1.discovery.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"cronjobs.v1.batch\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"replicationcontrollers.v1.\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"storageclasses.v1.storage.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"clusterroles.v1.rbac.authorization.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"volumeattachments.v1.storage.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]},{\"Resource\":\"apiservices.v1.apiregistration.k8s.io\",\"Events\":[\"ADDED\",\"MODIFIED\",\"DELETED\"]}]"
69 changes: 69 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"os"
"testing"
"time"

"github.com/layer5io/meshkit/broker"
"github.com/layer5io/meshkit/broker/nats"
"github.com/stretchr/testify/assert"
)

var runIntegrationTest bool
var testMeshsyncTopic = "meshery.meshsync.core"
var testMeshsyncNatsURL = "localhost:4222"

func init() {
runIntegrationTest = os.Getenv("RUN_INTEGRATION_TESTS") == "true"
}

/**
* this test requires k8s cluster (with installed CRDs: meshsync) and nats streaming
* --
* use docker compose to start nats
* ---
* TODO:
* - (maybe) add starting kind cluster to docker compose (this is not necessary anymore, as kind cluster is created in co workflow step, could be useful only for local run);
* - (maybe) run all test in container to avoid port exposure to host (this also could be useful only for local run to avoid port collision with host machine)
*/
func TestWithNatsIntegration(t *testing.T) {
if !runIntegrationTest {
t.Skip("skipping integration test")
}

br, err := nats.New(nats.Options{
URLS: []string{testMeshsyncNatsURL},
ConnectionName: "meshsync",
Username: "",
Password: "",
ReconnectWait: 2 * time.Second,
MaxReconnect: 60,
})
if err != nil {
t.Fatal("error connecting to nats", err)
}
count := 0

out := make(chan *broker.Message)
err = br.SubscribeWithChannel(testMeshsyncTopic, "", out)
if err != nil {
t.Fatalf("error subscribing to topic: %v", err)
}

go func() {
for range out {
count++
}
}()

os.Setenv("BROKER_URL", testMeshsyncNatsURL)
go main()

<-time.After(time.Second * 8)
// TODO some more meaningful check
assert.True(t, count > 0)

t.Logf("received %d messages from broker", count)
t.Log("done")
}