Skip to content

Commit bcc0816

Browse files
authored
Merge branch 'main' into PMM-15058-seamless-pmm-ui-redirects
2 parents 9a69193 + 6729e04 commit bcc0816

47 files changed

Lines changed: 3078 additions & 152 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/linkspector.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ jobs:
3131
uses: browser-actions/setup-chrome@48ad923757ca74d66703209fe939badbdf80f2f4 # v2.2.0
3232

3333
- name: Configure Chrome path for puppeteer
34-
run: echo "PUPPETEER_EXECUTABLE_PATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV"
34+
run: |
35+
# ubuntu-24.04 restricts unprivileged user namespaces via AppArmor, which
36+
# leaves Chrome with no usable sandbox. linkspector hardcodes its puppeteer
37+
# launch args, so restore the namespaces rather than disable the sandbox.
38+
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
39+
echo "PUPPETEER_EXECUTABLE_PATH=${{ steps.setup-chrome.outputs.chrome-path }}" >> "$GITHUB_ENV"
3540
3641
- name: Run linkspector
3742
uses: umbrelladocs/action-linkspector@568ec8d29fa92b31fd9ea5381e155c51e922af83 # v1.5.5

admin/commands/inventory/change_agent_valkey_exporter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func (res *changeAgentValkeyExporterResult) String() string {
6262
// ChangeAgentValkeyExporterCommand is used by Kong for CLI flags and commands.
6363
type ChangeAgentValkeyExporterCommand struct {
6464
// Embedded flags
65-
flags.LogLevelFatalChangeFlags
65+
flags.LogLevelNoFatalChangeFlags
6666

6767
AgentID string `arg:"" help:"Valkey Exporter Agent ID"`
6868

admin/commands/inventory/change_agent_valkey_exporter_test.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func TestValkeyExporterChangeAgent(t *testing.T) {
4343
Password: new("redis_pass"),
4444
TLS: new(true),
4545
PushMetrics: new(false),
46-
LogLevelFatalChangeFlags: flags.LogLevelFatalChangeFlags{
46+
LogLevelNoFatalChangeFlags: flags.LogLevelNoFatalChangeFlags{
4747
LogLevel: new(flags.LogLevel("debug")),
4848
},
4949
CustomLabels: &map[string]string{"environment": "test"},
@@ -268,18 +268,25 @@ Configuration changes applied:
268268
assert.Contains(t, strings.ToLower(err.Error()), "agent-id")
269269
})
270270

271-
t.Run("InvalidLogLevel", func(t *testing.T) {
272-
t.Parallel()
273-
274-
cli := []string{"change-agent", "valkey-exporter", "test-agent-id", "--log-level=invalid"}
275-
276-
var cmd ChangeAgentValkeyExporterCommand
277-
parser, err := kong.New(&cmd)
278-
require.NoError(t, err)
279-
280-
_, err = parser.Parse(cli[2:])
281-
require.Error(t, err)
282-
assert.Contains(t, strings.ToLower(err.Error()), "log-level")
283-
})
271+
// valkey_exporter has no fatal level, so the flag must reject it the same way
272+
// `pmm-admin inventory add agent valkey-exporter` does.
273+
for name, level := range map[string]string{
274+
"InvalidLogLevel": "invalid",
275+
"FatalLogLevelRejected": "fatal",
276+
} {
277+
t.Run(name, func(t *testing.T) {
278+
t.Parallel()
279+
280+
cli := []string{"change-agent", "valkey-exporter", "test-agent-id", "--log-level=" + level}
281+
282+
var cmd ChangeAgentValkeyExporterCommand
283+
parser, err := kong.New(&cmd)
284+
require.NoError(t, err)
285+
286+
_, err = parser.Parse(cli[2:])
287+
require.Error(t, err)
288+
assert.Contains(t, strings.ToLower(err.Error()), "log-level")
289+
})
290+
}
284291
})
285292
}

api-tests/server/updates_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package server
1717

1818
import (
19+
"net/url"
1920
"strings"
2021
"testing"
2122
"time"
@@ -182,3 +183,33 @@ func TestListUpdates(t *testing.T) {
182183
pmmapitests.AssertAPIErrorf(t, err, 400, codes.FailedPrecondition, `PMM updates are disabled`)
183184
})
184185
}
186+
187+
// TestUpdateStatus covers the endpoint pre-3.9 clients poll after triggering an update: on a server
188+
// that has finished initializing it must report the update as done, without authentication.
189+
func TestUpdateStatus(t *testing.T) {
190+
baseURL, err := url.Parse(pmmapitests.BaseURL.String())
191+
require.NoError(t, err)
192+
baseURL.User = nil
193+
noAuthClient := serverClient.New(pmmapitests.Transport(baseURL, true), nil)
194+
195+
for _, tc := range []struct {
196+
name string
197+
body server.UpdateStatusBody
198+
}{
199+
{"with a token issued by the previous instance", server.UpdateStatusBody{AuthToken: "unverifiable", LogOffset: 1024}},
200+
{"without a token", server.UpdateStatusBody{}},
201+
} {
202+
t.Run(tc.name, func(t *testing.T) {
203+
res, err := noAuthClient.ServerService.UpdateStatus(&server.UpdateStatusParams{
204+
Body: tc.body,
205+
Context: pmmapitests.Context,
206+
})
207+
require.NoError(t, err)
208+
assert.True(t, res.Payload.Done)
209+
// Pre-3.9 clients join log_lines unconditionally, so it must marshal as an empty array.
210+
assert.NotNil(t, res.Payload.LogLines)
211+
assert.Empty(t, res.Payload.LogLines)
212+
assert.Zero(t, res.Payload.LogOffset)
213+
})
214+
}
215+
}

api/AGENTS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ domain/v1/
7070
- **`v1`** — stable API, backward-compatible changes only
7171
- **`v1beta1`** — beta API, may have breaking changes (e.g., `dump/v1beta1/`, `accesscontrol/v1beta1/`, `ha/v1beta1/`)
7272

73+
## REST Path Naming
74+
75+
PMM follows [AIP-122](https://google.aip.dev/122) and [AIP-136](https://google.aip.dev/136) for `google.api.http` paths.
76+
77+
- **Collection identifiers are `lowerCamelCase`**`/v1/management/enrollmentTokens`, `/v1/advisors/failedServices`. Not kebab-case, not snake_case.
78+
- **Custom methods use `:verb` in `lowerCamelCase`**`/v1/inventory/services:getTypes`, `/v1/realtimeanalytics/sessions:start`.
79+
- **Path parameters keep the proto field name**, which is `snake_case``/v1/management/nodes/{node_id}`.
80+
81+
Two deliberate departures from AIP-136:
82+
83+
- **A POST-based read keeps a `get` prefix**`/v1/qan:getLabels`, `/v1/inventory/services:getTypes`. AIP-136 bars standard method verbs (`get`, `list`, …) from custom methods, but without the prefix `POST /v1/qan:labels` reads like a create. Marking the read intent wins over the rule here.
84+
- **The URI verb is chosen for HTTP readability, not to mirror the RPC name**`ListActiveServiceTypes` is exposed as `:getTypes`. AIP-136 requires the two to match; PMM optimizes the path for REST clients instead.
85+
86+
Nothing enforces this: `buf lint` checks proto identifiers, not the path strings inside `google.api.http` annotations. Two older paths predate the convention and are kebab-case (`/v1/backups/{artifact_id}/compatible-services` and `/v1/backups/artifacts/{artifact_id}/pitr-timeranges`). Don't copy them, and don't rename them either — a released path cannot change without breaking clients.
87+
7388
## Patterns and Conventions
7489

7590
### Do
@@ -80,6 +95,7 @@ domain/v1/
8095
- Use `google.api.http` annotations for REST endpoint mapping
8196
- Use gRPC status codes (`codes.NotFound`, `codes.InvalidArgument`, etc.) not HTTP status codes
8297
- Follow RESTful conventions for HTTP mappings (GET for reads, POST for creates, PUT for updates, DELETE for deletes)
98+
- Name REST paths per [REST Path Naming](#rest-path-naming) above
8399
- Add comments to proto messages and fields — they become API documentation
84100

85101
### Don't

api/descriptor.bin

1.71 KB
Binary file not shown.

api/server/v1/json/client/server_service/server_service_client.go

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/server/v1/json/client/server_service/update_status_parameters.go

Lines changed: 141 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)