diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c49cf3b9d7..af3bc0ad75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -180,8 +180,8 @@ jobs: path: /tmp/integration-test-logs/ retention-days: 3 - official-image-integration-tests: - name: Integration Tests - Official Images + official-oss-image-integration-tests: + name: Integration Tests - Official OSS Images needs: build-unsigned-snapshot runs-on: ubuntu-24.04 strategy: @@ -234,9 +234,86 @@ jobs: if: success() || failure() uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: - name: integration-test-logs-${{ matrix.container.image }}-${{ matrix.container.version }}-new + name: official-oss-integration-test-logs-${{ matrix.container.image }}-${{ matrix.container.version }} path: /tmp/integration-test-logs/ retention-days: 3 + + official-plus-image-integration-tests: + name: Integration Tests - Official Plus Images + needs: build-unsigned-snapshot + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + container: + - image: "alpine" + version: "3.18" + plus: "r30" + release: "alpine" + path: "/nginx-plus/agent" + - image: "alpine" + version: "3.20" + plus: "r32" + release: "alpine" + path: "/nginx-plus/agent" + - image: "alpine" + version: "3.19" + plus: "r31" + release: "alpine" + path: "/nginx-plus/agent" + - image: "debian" + version: "bookworm" + plus: "r32" + release: "debian" + path: "/nginx-plus/agent" + - image: "debian" + version: "bookworm" + plus: "r31" + release: "debian" + path: "/nginx-plus/agent" + - image: "debian" + version: "bookworm" + plus: "r30" + release: "debian" + path: "/nginx-plus/agent" + steps: + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + with: + fetch-depth: 0 + - uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 + with: + go-version-file: 'go.mod' + - name: Download Packages + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: nginx-agent-unsigned-snapshots + path: build + - name: Login to Docker Registry + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: ${{ secrets.REGISTRY_URL }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + - name: Run Integration Tests + run: | + go install github.com/goreleaser/nfpm/v2/cmd/nfpm@${{ env.NFPM_VERSION }} + CONTAINER_NGINX_IMAGE_REGISTRY="${{ secrets.REGISTRY_URL }}" TAG="${{ matrix.container.plus }}-${{ matrix.container.image }}-${{ matrix.container.version }}" \ + OS_RELEASE="${{ matrix.container.release }}" IMAGE_PATH="${{ matrix.container.path }}" \ + make official-image-integration-test + - name: Container Output Logs + if: failure() + run: | + docker ps -a + dockerid=$(docker ps -a --format "{{.ID}}") + docker logs "$dockerid" + + - name: Archive integration test logs + if: success() || failure() + uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 + with: + name: official-plus-integration-test-logs-${{ matrix.container.image }}-${{ matrix.container.version }}-${{ matrix.container.plus }} + path: /tmp/integration-test-logs/ + retention-days: 3 performance-test: name: Performance Tests diff --git a/Makefile b/Makefile index 38fef30cba..8945cd7143 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ OS_RELEASE ?= ubuntu OS_VERSION ?= 24.04 BASE_IMAGE = "${CONTAINER_REGISTRY}/${OS_RELEASE}:${OS_VERSION}" IMAGE_TAG = "agent_${OS_RELEASE}_${OS_VERSION}" -AGENT_IMAGE_PATH = "/nginx/agent" +IMAGE_PATH ?= "/nginx/agent" VERSION_WITH_V := v${VERSION} LDFLAGS = "-w -X main.version=${VERSION_WITH_V} -X main.commit=${COMMIT} -X main.date=${DATE}" @@ -227,14 +227,14 @@ integration-test: official-image-integration-test: PACKAGE_NAME=${PACKAGE_NAME} CONTAINER_NGINX_IMAGE_REGISTRY=${CONTAINER_NGINX_IMAGE_REGISTRY} ARCH=${OSARCH} OS_VERSION=${OS_VERSION} \ - OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${AGENT_IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ - ${GOTEST} -v ./test/integration/api - PACKAGE_NAME=${PACKAGE_NAME} CONTAINER_NGINX_IMAGE_REGISTRY=${CONTAINER_NGINX_IMAGE_REGISTRY} ARCH=${OSARCH} OS_VERSION=${OS_VERSION} \ - OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${AGENT_IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ + OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ ${GOTEST} -v ./test/integration/features PACKAGE_NAME=${PACKAGE_NAME} CONTAINER_NGINX_IMAGE_REGISTRY=${CONTAINER_NGINX_IMAGE_REGISTRY} ARCH=${OSARCH} OS_VERSION=${OS_VERSION} \ - OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${AGENT_IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ + OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ ${GOTEST} -v ./test/integration/grpc + PACKAGE_NAME=${PACKAGE_NAME} CONTAINER_NGINX_IMAGE_REGISTRY=${CONTAINER_NGINX_IMAGE_REGISTRY} ARCH=${OSARCH} OS_VERSION=${OS_VERSION} \ + OS_RELEASE=${OS_RELEASE} TAG=${TAG} CONTAINER_OS_TYPE=${CONTAINER_OS_TYPE} IMAGE_PATH=${IMAGE_PATH} DOCKER_COMPOSE_FILE="docker-compose-official-image.yml" \ + ${GOTEST} -v ./test/integration/api test-bench: ## Run benchmark tests cd test/performance && GOWORK=off CGO_ENABLED=0 ${GOTEST} -mod=vendor -count 5 -timeout 2m -bench=. -benchmem metrics_test.go diff --git a/test/integration/api/api_test.go b/test/integration/api/api_test.go index c9e2516e06..ec3691c813 100644 --- a/test/integration/api/api_test.go +++ b/test/integration/api/api_test.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "os" "strconv" "strings" "testing" @@ -82,8 +83,11 @@ func TestAPI_Metrics(t *testing.T) { assert.NotContains(t, resp.String(), "test_fail_metric") // Validate that the agent can call the stub status API assert.Contains(t, resp.String(), "nginx_http_request_count") - // Validate that the agent can read the NGINX access logs - assert.Contains(t, resp.String(), "nginx_http_status_2xx") + + if os.Getenv("IMAGE_PATH") == "/nginx/agent" { + // Validate that the agent can read the NGINX access logs + assert.Contains(t, resp.String(), "nginx_http_status_2xx") + } metrics := tutils.ProcessResponse(resp) diff --git a/test/integration/api/docker-compose-official-image.yml b/test/integration/api/docker-compose-official-image.yml index 79b6db1e69..1db62732be 100644 --- a/test/integration/api/docker-compose-official-image.yml +++ b/test/integration/api/docker-compose-official-image.yml @@ -21,5 +21,5 @@ services: networks: - monitoring volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ./nginx-agent.conf:/etc/nginx-agent/nginx-agent.conf + - ${NGINX_CONF_FILE} + - ${AGENT_CONF_FILE} diff --git a/test/integration/api/docker-compose.yml b/test/integration/api/docker-compose.yml index d801910112..48ca3efed4 100644 --- a/test/integration/api/docker-compose.yml +++ b/test/integration/api/docker-compose.yml @@ -22,5 +22,5 @@ services: networks: - monitoring volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ./nginx-agent.conf:/etc/nginx-agent/nginx-agent.conf + - ${NGINX_CONF_FILE} + - ${AGENT_CONF_FILE} diff --git a/test/integration/api/nginx.conf b/test/integration/api/nginx-oss.conf similarity index 100% rename from test/integration/api/nginx.conf rename to test/integration/api/nginx-oss.conf diff --git a/test/integration/api/nginx-plus.conf b/test/integration/api/nginx-plus.conf new file mode 100644 index 0000000000..7adc686293 --- /dev/null +++ b/test/integration/api/nginx-plus.conf @@ -0,0 +1,50 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$bytes_sent" "$request_length" "$request_time" ' + '"$gzip_ratio" $server_protocol '; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + ## + # Enable Metrics + ## + location /api/ { + api write=on; + allow 127.0.0.1; + deny all; + status_zone my_location_zone1; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/test/integration/features/docker-compose-official-image.yml b/test/integration/features/docker-compose-official-image.yml index 805f8a7af0..1db62732be 100644 --- a/test/integration/features/docker-compose-official-image.yml +++ b/test/integration/features/docker-compose-official-image.yml @@ -21,5 +21,5 @@ services: networks: - monitoring volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ${CONF_FILE} + - ${NGINX_CONF_FILE} + - ${AGENT_CONF_FILE} diff --git a/test/integration/features/docker-compose.yml b/test/integration/features/docker-compose.yml index 6d16e6aff6..94e457d482 100644 --- a/test/integration/features/docker-compose.yml +++ b/test/integration/features/docker-compose.yml @@ -22,5 +22,5 @@ services: networks: - monitoring volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - - ${CONF_FILE} + - ${NGINX_CONF_FILE} + - ${AGENT_CONF_FILE} diff --git a/test/integration/features/nginx.conf b/test/integration/features/nginx-oss.conf similarity index 100% rename from test/integration/features/nginx.conf rename to test/integration/features/nginx-oss.conf diff --git a/test/integration/features/nginx-plus.conf b/test/integration/features/nginx-plus.conf new file mode 100644 index 0000000000..48ae54ecd8 --- /dev/null +++ b/test/integration/features/nginx-plus.conf @@ -0,0 +1,49 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$bytes_sent" "$request_length" "$request_time" ' + '"$gzip_ratio" $server_protocol '; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + ## + # Enable Metrics + ## + location /api/ { + api write=on; + allow 127.0.0.1; + deny all; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/test/integration/grpc/docker-compose-official-image.yml b/test/integration/grpc/docker-compose-official-image.yml index ac65c5a5a7..d4f9b7b647 100644 --- a/test/integration/grpc/docker-compose-official-image.yml +++ b/test/integration/grpc/docker-compose-official-image.yml @@ -15,4 +15,4 @@ services: extra_hosts: - "host.docker.internal:host-gateway" volumes: - - ./nginx-agent.conf:/etc/nginx-agent/nginx-agent.conf + - ${AGENT_CONF_FILE} diff --git a/test/integration/grpc/docker-compose.yml b/test/integration/grpc/docker-compose.yml index 34c6cfe778..95785ff8c6 100644 --- a/test/integration/grpc/docker-compose.yml +++ b/test/integration/grpc/docker-compose.yml @@ -16,4 +16,4 @@ services: extra_hosts: - "host.docker.internal:host-gateway" volumes: - - ./nginx-agent.conf:/etc/nginx-agent/nginx-agent.conf + - ${AGENT_CONF_FILE} diff --git a/test/integration/install/docker-compose.yml b/test/integration/install/docker-compose.yml index 4f79793ceb..29c83b2cb7 100644 --- a/test/integration/install/docker-compose.yml +++ b/test/integration/install/docker-compose.yml @@ -17,4 +17,4 @@ services: ports: - 80 volumes: - - ./nginx.conf:/etc/nginx/nginx.conf # default nginx apk conf does not listen on localhost + - ${NGINX_CONF_FILE} # default nginx apk conf does not listen on localhost diff --git a/test/integration/install/nginx.conf b/test/integration/install/nginx-oss.conf similarity index 100% rename from test/integration/install/nginx.conf rename to test/integration/install/nginx-oss.conf diff --git a/test/integration/install/nginx-plus.conf b/test/integration/install/nginx-plus.conf new file mode 100644 index 0000000000..48ae54ecd8 --- /dev/null +++ b/test/integration/install/nginx-plus.conf @@ -0,0 +1,49 @@ +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$bytes_sent" "$request_length" "$request_time" ' + '"$gzip_ratio" $server_protocol '; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + server { + listen 8080; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + ## + # Enable Metrics + ## + location /api/ { + api write=on; + allow 127.0.0.1; + deny all; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } + } +} diff --git a/test/integration/utils/test_container_utils.go b/test/integration/utils/test_container_utils.go index 04934c6a4a..ca674bc0e8 100644 --- a/test/integration/utils/test_container_utils.go +++ b/test/integration/utils/test_container_utils.go @@ -24,7 +24,7 @@ const ( ) // SetupTestContainerWithAgent sets up a container with nginx and nginx-agent installed -func SetupTestContainerWithAgent(t *testing.T, testName string, conf string, waitForLog string) *testcontainers.DockerContainer { +func SetupTestContainerWithAgent(t *testing.T, testName string, agentConf string, waitForLog string) *testcontainers.DockerContainer { comp, err := compose.NewDockerCompose(os.Getenv("DOCKER_COMPOSE_FILE")) assert.NoError(t, err, "NewDockerComposeAPI()") @@ -33,6 +33,12 @@ func SetupTestContainerWithAgent(t *testing.T, testName string, conf string, wai ctxCancel, cancel := context.WithCancel(ctx) t.Cleanup(cancel) + nginxConf := "./nginx-oss.conf:/etc/nginx/nginx.conf" + + if os.Getenv("IMAGE_PATH") == "/nginx-plus/agent" { + nginxConf = "./nginx-plus.conf:/etc/nginx/nginx.conf" + } + require.NoError(t, comp.WaitForService("agent", wait.ForLog(waitForLog)).WithEnv( map[string]string{ @@ -45,7 +51,8 @@ func SetupTestContainerWithAgent(t *testing.T, testName string, conf string, wai "CONTAINER_NGINX_IMAGE_REGISTRY": os.Getenv("CONTAINER_NGINX_IMAGE_REGISTRY"), "TAG": os.Getenv("TAG"), "IMAGE_PATH": os.Getenv("IMAGE_PATH"), - "CONF_FILE": conf, + "AGENT_CONF_FILE": agentConf, + "NGINX_CONF_FILE": nginxConf, }, ).Up(ctxCancel, compose.Wait(true)), "compose.Up()") @@ -79,6 +86,14 @@ func SetupTestContainerWithoutAgent(t *testing.T) *testcontainers.DockerContaine ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) + nginxConf := "./nginx-oss.conf:/etc/nginx/nginx.conf" + + log := "nginx_pid" + + if os.Getenv("IMAGE_PATH") == "/nginx-plus/agent" { + nginxConf = "./nginx-plus.conf:/etc/nginx/nginx.conf" + } + err = comp. WithEnv(map[string]string{ "PACKAGE_NAME": os.Getenv("PACKAGE_NAME"), @@ -91,8 +106,9 @@ func SetupTestContainerWithoutAgent(t *testing.T) *testcontainers.DockerContaine "TAG": os.Getenv("TAG"), "CONTAINER_OS_TYPE": os.Getenv("CONTAINER_OS_TYPE"), "IMAGE_PATH": os.Getenv("IMAGE_PATH"), + "NGINX_CONF_FILE": nginxConf, }). - WaitForService("agent", wait.NewLogStrategy("nginx_pid").WithOccurrence(1)). + WaitForService("agent", wait.NewLogStrategy(log).WithOccurrence(1)). Up(ctx, compose.Wait(true)) assert.NoError(t, err, "compose.Up()")