From b19e8db2c47268eea25a2cb59327aa5599f1461d Mon Sep 17 00:00:00 2001 From: Julien Duchesne Date: Fri, 10 Nov 2023 10:29:21 -0500 Subject: [PATCH] OpenAPI: Fix API calls pointing to subpath (#1145) Closes https://github.com/grafana/terraform-provider-grafana/issues/1137 Currently, the test suite is pointing to a subpath BUT Grafana redirects from the root to the subpath The provider is badly configured but the tests still pass because of the redirect To fix the test suite, I add a nginx proxy in this PR, so that calling the host directly fails and you have to go through the subpath I've also reworked the Makefile so that it has more common args (less repetition of configs), so it's harder to make a mistake --- GNUmakefile | 58 ++++++++++++++--------------------- docker-compose.yml | 14 +++++++-- internal/provider/provider.go | 6 +++- testdata/nginx.conf | 34 ++++++++++++++++++++ 4 files changed, 74 insertions(+), 38 deletions(-) create mode 100644 testdata/nginx.conf diff --git a/GNUmakefile b/GNUmakefile index 8acab0ee5..b2f27bb39 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,15 +1,16 @@ GRAFANA_VERSION ?= 10.1.5 +DOCKER_COMPOSE_ARGS ?= --force-recreate --detach --remove-orphans --wait testacc: TF_ACC=1 go test ./... -v $(TESTARGS) -timeout 120m # Test OSS features testacc-oss: - TF_ACC_OSS=true make testacc + GRAFANA_AUTH="$${GRAFANA_AUTH:-admin:admin}" TF_ACC_OSS=true make testacc # Test Enterprise features testacc-enterprise: - TF_ACC_ENTERPRISE=true make testacc + GRAFANA_AUTH="$${GRAFANA_AUTH:-admin:admin}" TF_ACC_ENTERPRISE=true make testacc # Test Cloud API features testacc-cloud-api: @@ -20,48 +21,35 @@ testacc-cloud-instance: TF_ACC_CLOUD_INSTANCE=true make testacc testacc-oss-docker: - GRAFANA_VERSION=$(GRAFANA_VERSION) docker compose up --force-recreate --detach --remove-orphans --wait - - GRAFANA_VERSION=$(GRAFANA_VERSION) \ - GRAFANA_URL="http://0.0.0.0:3000" \ - GRAFANA_AUTH="admin:admin" \ - make testacc-oss - + export GRAFANA_URL=http://0.0.0.0:3000 && \ + export GRAFANA_VERSION=$(GRAFANA_VERSION) && \ + docker compose up $(DOCKER_COMPOSE_ARGS) && \ + make testacc-oss && \ docker compose down testacc-enterprise-docker: - GRAFANA_IMAGE=grafana/grafana-enterprise GRAFANA_VERSION=$(GRAFANA_VERSION) docker compose up --force-recreate --detach --remove-orphans --wait - - GRAFANA_VERSION=$(GRAFANA_VERSION) \ - GRAFANA_URL="http://0.0.0.0:3000" \ - GRAFANA_AUTH="admin:admin" \ - make testacc-enterprise - + export GRAFANA_URL=http://0.0.0.0:3000 && \ + export GRAFANA_VERSION=$(GRAFANA_VERSION) && \ + GRAFANA_IMAGE=grafana/grafana-enterprise docker compose up $(DOCKER_COMPOSE_ARGS) && \ + make testacc-enterprise && \ docker compose down testacc-tls-docker: - make -C testdata generate - GRAFANA_VERSION=$(GRAFANA_VERSION) docker compose --profile tls up --force-recreate --detach --remove-orphans --wait - - GRAFANA_VERSION=$(GRAFANA_VERSION) \ - GRAFANA_URL="http://0.0.0.0:3000" \ - GRAFANA_AUTH="admin:admin" \ - GRAFANA_TLS_KEY=$$(pwd)/testdata/client.key \ - GRAFANA_TLS_CERT=$$(pwd)/testdata/client.crt \ - GRAFANA_CA_CERT=$$(pwd)/testdata/ca.crt \ - make testacc-oss - + export GRAFANA_URL=https://0.0.0.0:3001 && \ + export GRAFANA_VERSION=$(GRAFANA_VERSION) && \ + make -C testdata generate && \ + docker compose --profile tls up $(DOCKER_COMPOSE_ARGS) && \ + GRAFANA_TLS_KEY=$$(pwd)/testdata/client.key GRAFANA_TLS_CERT=$$(pwd)/testdata/client.crt GRAFANA_CA_CERT=$$(pwd)/testdata/ca.crt make testacc-oss && \ docker compose --profile tls down testacc-subpath-docker: - GRAFANA_VERSION=$(GRAFANA_VERSION) GRAFANA_SUBPATH=/grafana/ GF_SERVER_SERVE_FROM_SUB_PATH=true docker compose up --force-recreate --detach --remove-orphans --wait - - GRAFANA_VERSION=$(GRAFANA_VERSION) \ - GRAFANA_URL="http://0.0.0.0:3000/grafana" \ - GRAFANA_AUTH="admin:admin" \ - make testacc-oss - - docker compose down + export GRAFANA_SUBPATH=/grafana/ && \ + export GF_SERVER_SERVE_FROM_SUB_PATH=true && \ + export GRAFANA_URL=http://0.0.0.0:3001$${GRAFANA_SUBPATH} && \ + export GRAFANA_VERSION=$(GRAFANA_VERSION) && \ + docker compose --profile proxy up $(DOCKER_COMPOSE_ARGS) && \ + make testacc-oss && \ + docker compose --profile proxy down release: @test $${RELEASE_VERSION?Please set environment variable RELEASE_VERSION} diff --git a/docker-compose.yml b/docker-compose.yml index ce4629575..773834eda 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,11 +5,11 @@ services: - 3000:3000 image: ${GRAFANA_IMAGE:-grafana/grafana}:${GRAFANA_VERSION} environment: - - GF_SERVER_ROOT_URL=http://0.0.0.0:3000${GRAFANA_SUBPATH:-} + - GF_SERVER_ROOT_URL=${GRAFANA_URL} - GF_ENTERPRISE_LICENSE_TEXT=${GF_ENTERPRISE_LICENSE_TEXT:-} - GF_SERVER_SERVE_FROM_SUB_PATH=${GF_SERVER_SERVE_FROM_SUB_PATH:-} healthcheck: - test: wget --no-verbose --tries=1 --spider http://0.0.0.0:3000${GRAFANA_SUBPATH:-}/api/health || exit 1 # Use wget because older versions of Grafana don't have curl + test: wget --no-verbose --tries=1 --spider http://0.0.0.0:3000/api/health || exit 1 # Use wget because older versions of Grafana don't have curl interval: 10s retries: 10 start_period: 10s @@ -32,3 +32,13 @@ services: - ./testdata:/certs ports: - 3001:3001 + nginx: + profiles: + - "proxy" + depends_on: + - grafana + image: nginx:latest + ports: + - 3001:3001 + volumes: + - ./testdata/nginx.conf:/etc/nginx/nginx.conf diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 07302bc3a..7d3fb677b 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -430,6 +430,10 @@ func createGrafanaOAPIClient(apiURL string, d *schema.ResourceData) (*goapi.Graf if err != nil { return nil, fmt.Errorf("failed to parse API url: %v", err.Error()) } + apiPath, err := url.JoinPath(u.Path, "api") + if err != nil { + return nil, fmt.Errorf("failed to join API path: %v", err.Error()) + } userInfo, orgID, APIKey, err := parseAuth(d) if err != nil { @@ -438,7 +442,7 @@ func createGrafanaOAPIClient(apiURL string, d *schema.ResourceData) (*goapi.Graf cfg := goapi.TransportConfig{ Host: u.Host, - BasePath: "/api", + BasePath: apiPath, Schemes: []string{u.Scheme}, NumRetries: d.Get("retries").(int), RetryTimeout: time.Second * time.Duration(d.Get("retry_wait").(int)), diff --git a/testdata/nginx.conf b/testdata/nginx.conf new file mode 100644 index 000000000..c581f8732 --- /dev/null +++ b/testdata/nginx.conf @@ -0,0 +1,34 @@ +events{} + +http { + # this is required to proxy Grafana Live WebSocket connections. + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + upstream grafana { + server grafana:3000; + } + + server { + listen 3001; + root /usr/share/nginx/html; + index index.html index.htm; + server_name 0.0.0.0; + + location /grafana/ { + proxy_set_header Host $host; + proxy_pass http://grafana; + } + + # Proxy Grafana Live WebSocket connections. + location /api/live/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_pass http://grafana; + } + } +}