Skip to content

Commit

Permalink
Merge branch 'v3' into PMM-13235-grafana-11
Browse files Browse the repository at this point in the history
  • Loading branch information
matejkubinec committed Aug 12, 2024
2 parents 78dac45 + 6a42b21 commit 155b89e
Show file tree
Hide file tree
Showing 139 changed files with 2,749 additions and 2,989 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
* @percona/pmm-review-be
/docs/ @percona/pmm-docs
/ui/ @percona/pmm-review-fe
/agent/agents/postgres/ @JiriCtvrtka @percona/pmm-review-be
/api/ @BupycHuk @percona/pmm-review-be
/managed/services/checks/ @idoqo @percona/pmm-review-be
Expand Down
31 changes: 18 additions & 13 deletions .github/workflows/doc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,31 @@ on:
- "docs/api/**"

workflow_dispatch:
inputs:
version:
description: "API Version on readme.io"
required: true
default: "v1.0" # v0.0 stands for the dev version

jobs:
sync:
name: Sync
runs-on: ubuntu-22.04

steps:
- name: Check out code
uses: actions/checkout@v4

- name: API
uses: readmeio/rdme@v8
with:
rdme: openapi ./api/swagger/swagger.json --id=626badcabbc59c02acc1a53f --key=${{ secrets.README_TOKEN }}
- name: Detect PMM version and API ID
run: |
# For reference:
# PMM 2: VERSION=v2, ID=626badcabbc59c02acc1a53f
# PMM 3: VERSION=v3, ID=622892a957a7410330bc6184
export VERSION=$(cat api/swagger/swagger.json | jq -r '.info.version')
export ID=$(cat api/swagger/swagger.json | jq -r '."x-readme-id"')
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "ID=$ID" >> $GITHUB_ENV
- name: Provision rdme
run: npm install -g rdme

- name: Sync API spec
run: rdme openapi ./api/swagger/swagger.json --id=${{ env.ID }} --key=${{ secrets.README_TOKEN }}

- name: Markdown docs
uses: readmeio/rdme@v8
with:
rdme: docs docs/api --version=${{ github.event.inputs.version || 'v1.0' }} --key=${{ secrets.README_TOKEN }}
- name: Sync Markdown docs
run: rdme docs docs/api --version=${{ env.VERSION }} --key=${{ secrets.README_TOKEN }}
4 changes: 1 addition & 3 deletions admin/commands/management/management.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
// Package management provides management commands.
package management

import (
"github.com/percona/pmm/api/inventory/v1/types"
)
import "github.com/percona/pmm/api/inventory/v1/types"

var (
allNodeTypes = map[string]string{
Expand Down
40 changes: 20 additions & 20 deletions agent/runner/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,36 +156,36 @@ func TestPerDBInstanceLimit(t *testing.T) {
db2j2 := testJob{id: "test-5", timeout: time.Second, dsn: "postgresql://db2"}
db2j3 := testJob{id: "test-6", timeout: time.Second, dsn: "postgresql://db2"}

require.NoError(t, cr.StartJob(db1j1))
require.NoError(t, cr.StartJob(db2j1))
require.NoError(t, cr.StartJob(db1j1), "start job db1j1 failed")
require.NoError(t, cr.StartJob(db2j1), "start job db2j1 failed")

// Let jobs to start
time.Sleep(200 * time.Millisecond)

require.NoError(t, cr.StartJob(db1j2))
require.NoError(t, cr.StartJob(db2j2))
require.NoError(t, cr.StartJob(db1j3))
require.NoError(t, cr.StartJob(db2j3))
require.NoError(t, cr.StartJob(db1j2), "start job db1j2 failed")
require.NoError(t, cr.StartJob(db2j2), "start job db2j2 failed")
require.NoError(t, cr.StartJob(db1j3), "start job db1j3 failed")
require.NoError(t, cr.StartJob(db2j3), "start job db2j3 failed")

// Let rest jobs to reach semaphores
time.Sleep(300 * time.Millisecond)

assert.True(t, cr.IsRunning(db1j1.ID()))
assert.True(t, cr.IsRunning(db2j1.ID()))
assert.False(t, cr.IsRunning(db1j2.ID()))
assert.False(t, cr.IsRunning(db2j2.ID()))
assert.False(t, cr.IsRunning(db1j3.ID()))
assert.False(t, cr.IsRunning(db2j3.ID()))
assert.True(t, cr.IsRunning(db1j1.ID()), "db1j1 is not running")
assert.True(t, cr.IsRunning(db2j1.ID()), "db2j1 is not running")
assert.False(t, cr.IsRunning(db1j2.ID()), "db1j2 is running")
assert.False(t, cr.IsRunning(db2j2.ID()), "db2j2 is running")
assert.False(t, cr.IsRunning(db1j3.ID()), "db1j3 is running")
assert.False(t, cr.IsRunning(db2j3.ID()), "db2j3 is running")

// Over time all jobs are terminated
time.Sleep(2 * time.Second)

assert.False(t, cr.IsRunning(db1j1.ID()))
assert.False(t, cr.IsRunning(db2j1.ID()))
assert.False(t, cr.IsRunning(db1j2.ID()))
assert.False(t, cr.IsRunning(db2j2.ID()))
assert.False(t, cr.IsRunning(db1j3.ID()))
assert.False(t, cr.IsRunning(db2j3.ID()))
time.Sleep(3 * time.Second)

assert.False(t, cr.IsRunning(db1j1.ID()), "db1j1 is running")
assert.False(t, cr.IsRunning(db2j1.ID()), "db2j1 is running")
assert.False(t, cr.IsRunning(db1j2.ID()), "db1j2 is running")
assert.False(t, cr.IsRunning(db2j2.ID()), "db2j2 is running")
assert.False(t, cr.IsRunning(db1j3.ID()), "db1j3 is running")
assert.False(t, cr.IsRunning(db2j3.ID()), "db2j3 is running")
}

func TestDefaultPerDBInstanceLimit(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions api-tests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ func TestString(t TestingT, name string) string {
t.Helper()

// Without proper seed parallel tests can generate same "random" number.
n, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
rnd, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
require.NoError(t, err)

return strings.ReplaceAll(fmt.Sprintf("pmm-api-tests-%s-%s-%s-%d", Hostname, t.Name(), name, n), "/", "-")
return strings.ReplaceAll(fmt.Sprintf("api-test-%s-%s-%d", t.Name(), name, rnd), "/", "-")
}

// AssertAPIErrorf check that actual API error equals expected.
Expand Down
37 changes: 33 additions & 4 deletions api-tests/management/annotation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package management

import (
"fmt"
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -55,7 +57,7 @@ func TestAddAnnotation(t *testing.T) {
pmmapitests.AssertAPIErrorf(t, err, 400, codes.InvalidArgument, "invalid AddAnnotationRequest.Text: value length must be at least 1 runes")
})

t.Run("Non-existing service", func(t *testing.T) {
t.Run("Non-existent service", func(t *testing.T) {
params := &mservice.AddAnnotationParams{
Body: mservice.AddAnnotationBody{
Text: "Some text",
Expand All @@ -67,7 +69,7 @@ func TestAddAnnotation(t *testing.T) {
pmmapitests.AssertAPIErrorf(t, err, 404, codes.NotFound, `Service with name "no-service" not found.`)
})

t.Run("Non-existing node", func(t *testing.T) {
t.Run("Non-existent node", func(t *testing.T) {
params := &mservice.AddAnnotationParams{
Body: mservice.AddAnnotationBody{
Text: "Some text",
Expand All @@ -79,6 +81,33 @@ func TestAddAnnotation(t *testing.T) {
pmmapitests.AssertAPIErrorf(t, err, 404, codes.NotFound, `Node with name "no-node" not found.`)
})

t.Run("Tag length exceeded", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, strings.Repeat("long-annotation-node-name-", 10))
paramsNode := &nodes.AddNodeParams{
Body: nodes.AddNodeBody{
Generic: &nodes.AddNodeParamsBodyGeneric{
NodeName: nodeName,
Address: "10.0.0.1",
},
},
Context: pmmapitests.Context,
}
resNode, err := inventoryClient.Default.NodesService.AddNode(paramsNode)
assert.NoError(t, err)
genericNodeID := resNode.Payload.Generic.NodeID
defer pmmapitests.RemoveNodes(t, genericNodeID)

params := &mservice.AddAnnotationParams{
Body: mservice.AddAnnotationBody{
Text: "Some text",
NodeName: nodeName,
},
Context: pmmapitests.Context,
}
_, err = client.Default.ManagementService.AddAnnotation(params)
pmmapitests.AssertAPIErrorf(t, err, 400, codes.InvalidArgument, fmt.Sprintf("tag length cannot exceed 100 characters, tag: %s", nodeName))
})

t.Run("Existing service", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "annotation-node")
paramsNode := &nodes.AddNodeParams{
Expand All @@ -95,7 +124,7 @@ func TestAddAnnotation(t *testing.T) {
genericNodeID := resNode.Payload.Generic.NodeID
defer pmmapitests.RemoveNodes(t, genericNodeID)

serviceName := pmmapitests.TestString(t, "annotation-service")
serviceName := "annotation-service"
paramsService := &services.AddServiceParams{
Body: services.AddServiceBody{
Mysql: &services.AddServiceParamsBodyMysql{
Expand Down Expand Up @@ -126,7 +155,7 @@ func TestAddAnnotation(t *testing.T) {
})

t.Run("Existing node", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "annotation-node")
nodeName := "annotation-node"
params := &nodes.AddNodeParams{
Body: nodes.AddNodeBody{
Generic: &nodes.AddNodeParamsBodyGeneric{
Expand Down
8 changes: 4 additions & 4 deletions api-tests/management/nodes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func TestNodeRegister(t *testing.T) {
})

t.Run("Reregister with same node name (no re-register - should fail)", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "node-name-for-all-fields")
nodeName := pmmapitests.TestString(t, "node-all")
nodeID, pmmAgentID := RegisterGenericNode(t, mservice.RegisterNodeBody{
NodeName: nodeName,
NodeType: pointer.ToString(mservice.RegisterNodeBodyNodeTypeNODETYPEGENERICNODE),
Expand All @@ -85,7 +85,7 @@ func TestNodeRegister(t *testing.T) {
})

t.Run("Reregister with same node name (re-register)", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "node-name-for-all-fields")
nodeName := pmmapitests.TestString(t, "node-all")
nodeID, pmmAgentID := RegisterGenericNode(t, mservice.RegisterNodeBody{
NodeName: nodeName,
NodeType: pointer.ToString(mservice.RegisterNodeBodyNodeTypeNODETYPEGENERICNODE),
Expand Down Expand Up @@ -116,7 +116,7 @@ func TestNodeRegister(t *testing.T) {
})

t.Run("Reregister with different node name (no re-register - should fail)", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "node-name-for-all-fields")
nodeName := pmmapitests.TestString(t, "node-all")
nodeID, pmmAgentID := RegisterGenericNode(t, mservice.RegisterNodeBody{
NodeName: nodeName,
NodeType: pointer.ToString(mservice.RegisterNodeBodyNodeTypeNODETYPEGENERICNODE),
Expand All @@ -142,7 +142,7 @@ func TestNodeRegister(t *testing.T) {
})

t.Run("Reregister with different node name (re-register)", func(t *testing.T) {
nodeName := pmmapitests.TestString(t, "node-name-for-all-fields")
nodeName := pmmapitests.TestString(t, "node-all")
nodeID, pmmAgentID := RegisterGenericNode(t, mservice.RegisterNodeBody{
NodeName: nodeName,
NodeType: pointer.ToString(mservice.RegisterNodeBodyNodeTypeNODETYPEGENERICNODE),
Expand Down
91 changes: 0 additions & 91 deletions api-tests/server/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"net/http/httputil"
"net/url"
"strconv"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -98,96 +97,6 @@ func TestAuth(t *testing.T) {
})
}

func TestSetup(t *testing.T) {
t.Parallel()
// make a BaseURL without authentication
baseURL, err := url.Parse(pmmapitests.BaseURL.String())
require.NoError(t, err)
baseURL.User = nil

// make client that does not follow redirects
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}

t.Run("WebPage", func(t *testing.T) {
t.Parallel()

uri := baseURL.ResolveReference(&url.URL{
Path: "/setup",
})
t.Logf("URI: %s", uri)
req, err := http.NewRequestWithContext(pmmapitests.Context, http.MethodGet, uri.String(), nil)
require.NoError(t, err)
req.Header.Set("X-Test-Must-Setup", "1")

resp, b := doRequest(t, client, req) //nolint:bodyclose

assert.Equal(t, 200, resp.StatusCode, "response:\n%s", b)
assert.True(t, strings.HasPrefix(string(b), `<!doctype html>`), string(b))
})

t.Run("Redirect", func(t *testing.T) {
t.Parallel()
paths := map[string]int{
"graph": 303,
"graph/": 303,
"prometheus": 303,
"prometheus/": 303,
"swagger": 200,
"swagger/": 301,

"v1/server/readyz": 200,
"v1/server/AWSInstance": 400, // It must accept a parameter
"v1/server/version": 401, // Grafana authentication required
}
for path, code := range paths {
path, code := path, code
t.Run(fmt.Sprintf("%s=%d", path, code), func(t *testing.T) {
t.Parallel()

uri := baseURL.ResolveReference(&url.URL{
Path: path,
})
t.Logf("URI: %s", uri)
req, err := http.NewRequestWithContext(pmmapitests.Context, http.MethodGet, uri.String(), nil)
require.NoError(t, err)
req.Header.Set("X-Test-Must-Setup", "1")

resp, b := doRequest(t, client, req) //nolint:bodyclose

assert.Equal(t, code, resp.StatusCode, "response:\n%s", b)
if code == 303 {
assert.Equal(t, "/setup", resp.Header.Get("Location"))
}
})
}
})

t.Run("API", func(t *testing.T) {
t.Parallel()

q := make(url.Values)
q.Set("instance_id", "123")
uri := baseURL.ResolveReference(&url.URL{
Path: "v1/server/AWSInstance",
RawQuery: q.Encode(),
})
t.Logf("URI: %s", uri)
require.NoError(t, err)
req, err := http.NewRequestWithContext(pmmapitests.Context, http.MethodGet, uri.String(), nil)
require.NoError(t, err)
req.Header.Set("X-Test-Must-Setup", "1")

resp, b := doRequest(t, client, req) //nolint:bodyclose

assert.Equal(t, 200, resp.StatusCode, "response:\n%s", b)
assert.Equal(t, "{}", string(b), "response:\n%s", b)
})
}

func TestSwagger(t *testing.T) {
t.Parallel()
for _, path := range []string{
Expand Down
9 changes: 5 additions & 4 deletions api/accesscontrol/v1beta1/accesscontrol.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 155b89e

Please sign in to comment.