Skip to content

Commit 27cb102

Browse files
wu-shengclaude
andcommitted
Support the OAP admin-server REST API and adapt to OAP 11.0.0
Add a first-class admin-host (REST) client and a `swctl admin ...` command tree, alongside the existing GraphQL surface, and adapt to the OAP 11.0.0 breaking changes. Admin REST surface (default port 17128): - New global `--admin-url` flag (env SW_ADMIN_URL / config key `admin-url`), derived from `--base-url`'s host with port 17128 when unset. - New pkg/transport (shared TLS/basic-auth) and pkg/admin/client REST client with a typed error envelope and admin-module preflight detection. - `swctl admin ...` covering every feature module: preflight; cluster nodes, config dump/ttl, alarm rules/rule (status); inspect metrics/entities; ui-template list/get/create/update/disable; runtime-rule list/bundled/get/add/inactivate/delete/dump; dsl-debug status/sessions/ session start|get|stop and oal files/file/rules/rule. OAP 11.0.0 adaptations: - alarm list: migrate getAlarm -> queryAlarms, add --layer/--rules filters. - menu get: detect the retired getMenuItems and report a clear message instead of a raw GraphQL error. E2E: - Bump OAP to 11.0.0+, switch storage from Elasticsearch to BanyanDB. - basic: layer list normalized via `yq sort`; trace cases migrated to trace-v2 (BanyanDB rejects the v1 trace API). - New `admin` case (static admin REST) and `live-debugging` case (OAL live capture, asserting the captured pipeline is exactly the bound metric). - New admin-command-tests and live-debugging-tests CI jobs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8c709ce commit 27cb102

46 files changed

Lines changed: 3052 additions & 224 deletions

File tree

Some content is hidden

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

.github/workflows/CI.yaml

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
strategy:
8989
matrix:
9090
oap:
91-
- 42c613bea94999a6cc8e805ed4c8c7659f3a735c
91+
- 768d0693aac34ed49ce4d1c89e4a56df353e4140
9292
steps:
9393
- uses: actions/checkout@v4
9494
- name: Set up Go
@@ -107,6 +107,62 @@ jobs:
107107
e2e-file: test/cases/basic/test.yaml
108108

109109

110+
admin-command-tests:
111+
name: Admin Command Tests
112+
runs-on: ubuntu-latest
113+
if: github.repository == 'apache/skywalking-cli'
114+
strategy:
115+
matrix:
116+
# Must be an admin-capable OAP build: the admin-server REST host (port 17128)
117+
# and the queryAlarms / menu-retirement changes landed in OAP 11.0.0.
118+
oap:
119+
- 768d0693aac34ed49ce4d1c89e4a56df353e4140
120+
steps:
121+
- uses: actions/checkout@v4
122+
- name: Set up Go
123+
uses: actions/setup-go@v5
124+
with:
125+
go-version: "1.26"
126+
127+
- name: Install swctl
128+
run: make install DESTDIR=/usr/local/bin
129+
130+
- name: Test admin commands
131+
uses: apache/skywalking-infra-e2e@cf589b4a0b9f8e6f436f78e9cfd94a1ee5494180
132+
env:
133+
OAP_TAG: ${{ matrix.oap }}
134+
with:
135+
e2e-file: test/cases/admin/test.yaml
136+
137+
138+
live-debugging-tests:
139+
name: Live Debugging Tests
140+
runs-on: ubuntu-latest
141+
if: github.repository == 'apache/skywalking-cli'
142+
strategy:
143+
matrix:
144+
# OAL live debugging needs the admin host (OAP 11.0.0+); the demo traffic drives
145+
# the captured OAL pipeline.
146+
oap:
147+
- 768d0693aac34ed49ce4d1c89e4a56df353e4140
148+
steps:
149+
- uses: actions/checkout@v4
150+
- name: Set up Go
151+
uses: actions/setup-go@v5
152+
with:
153+
go-version: "1.26"
154+
155+
- name: Install swctl
156+
run: make install DESTDIR=/usr/local/bin
157+
158+
- name: Test OAL live debugging
159+
uses: apache/skywalking-infra-e2e@cf589b4a0b9f8e6f436f78e9cfd94a1ee5494180
160+
env:
161+
OAP_TAG: ${{ matrix.oap }}
162+
with:
163+
e2e-file: test/cases/live-debugging/test.yaml
164+
165+
110166
unit-tests:
111167
name: Unit Tests
112168
runs-on: ubuntu-latest
@@ -130,6 +186,8 @@ jobs:
130186
- check-license
131187
- build
132188
- command-tests
189+
- admin-command-tests
190+
- live-debugging-tests
133191
- unit-tests
134192
runs-on: ubuntu-latest
135193
timeout-minutes: 10
@@ -140,8 +198,12 @@ jobs:
140198
[[ ${checkLicense} == 'success' ]] || exit 1;
141199
build=${{ needs.build.result }};
142200
commandTests=${{ needs.command-tests.result }};
201+
adminCommandTests=${{ needs.admin-command-tests.result }};
202+
liveDebuggingTests=${{ needs.live-debugging-tests.result }};
143203
unitTests=${{ needs.unit-tests.result }};
144204
[[ ${build} == 'success' ]] || [[ ${build} == 'skipped' ]] || exit 3;
145205
[[ ${commandTests} == 'success' ]] || [[ ${commandTests} == 'skipped' ]] || exit 4;
206+
[[ ${adminCommandTests} == 'success' ]] || [[ ${adminCommandTests} == 'skipped' ]] || exit 6;
207+
[[ ${liveDebuggingTests} == 'success' ]] || [[ ${liveDebuggingTests} == 'skipped' ]] || exit 7;
146208
[[ ${unitTests} == 'success' ]] || [[ ${unitTests} == 'skipped' ]] || exit 5;
147209
exit 0;

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ Release Notes.
1616
* Add the duration field in the `trace list` command by @mrproliu in https://github.com/apache/skywalking-cli/pull/225
1717
* Remove the oldest `queryTraceFromColdStage` query call in the `trace list` command by @mrproliu in https://github.com/apache/skywalking-cli/pull/225
1818
* Add the sub-command `profiling pprof` for pprof query API by @JophieQu in https://github.com/apache/skywalking-cli/pull/226
19+
* Add the `admin` command group for the OAP admin-server REST host (default port `17128`), with a new global `--admin-url` flag (derived from `--base-url` when unset). Covers every admin feature module: `admin preflight`; `admin cluster nodes`, `admin config dump|ttl`, `admin alarm rules|rule` (status); `admin inspect metrics|entities` (inspect); `admin ui-template list|get|create|update|disable` (ui-management); `admin runtime-rule list|bundled|get|add|inactivate|delete|dump` (runtime-rule); and `admin dsl-debug status|sessions|session start|get|stop` plus `admin oal files|file|rules|rule` (dsl-debugging).
1920

2021
### Bug Fixes
2122

2223
* Fix wrong process id format by @mrproliu in https://github.com/apache/skywalking-cli/pull/215
24+
* Migrate `alarm list` from the deprecated `getAlarm` GraphQL query to `queryAlarms`, adding `--layer` and `--rules` filters (OAP 11.0.0).
25+
* `menu get` now reports a clear message when the OAP backend no longer serves the UI menu (retired in OAP 11.0.0) instead of a raw GraphQL error.
2326

2427
0.14.0
2528
------------------

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ The compatibility table here only lists fully compatible OAP versions, which mea
178178
| \> = 0.12.0 | \> = 9.5.0 |
179179
| \> = 0.13.0 | \> = 9.6.0 |
180180
| \> = 0.14.0 | \> = 10.2.0 |
181+
| \> = 0.15.0 | \> = 11.0.0 |
181182

182183
# Contributing
183184

assets/graphqls/alarm/alarms.graphql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
query ($duration: Duration!, $scope: Scope, $keyword: String, $paging: Pagination!, $tags: [AlarmTag]) {
19-
result: getAlarm(duration: $duration, scope: $scope, keyword: $keyword, paging: $paging, tags: $tags) {
18+
query ($condition: AlarmQueryCondition!) {
19+
result: queryAlarms(condition: $condition) {
2020
msgs {
2121
startTime
2222
scope

cmd/swctl/main.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"os"
2323
"runtime"
2424

25+
"github.com/apache/skywalking-cli/internal/commands/admin"
2526
"github.com/apache/skywalking-cli/internal/commands/alarm"
2627
"github.com/apache/skywalking-cli/internal/commands/browser"
2728
"github.com/apache/skywalking-cli/internal/commands/completion"
@@ -115,6 +116,7 @@ services, service instances, etc.`
115116
records.Command,
116117
menu.Command,
117118
hierarchy.Command,
119+
admin.Command,
118120
}
119121

120122
app.Before = interceptor.BeforeChain(
@@ -150,6 +152,15 @@ func flags() []cli.Flag {
150152
Usage: "base `url` of the OAP backend graphql service",
151153
Value: "http://127.0.0.1:12800/graphql",
152154
}),
155+
altsrc.NewStringFlag(&cli.StringFlag{
156+
Name: "admin-url",
157+
Required: false,
158+
EnvVars: []string{"SW_ADMIN_URL"},
159+
Usage: "base `url` of the OAP admin-server REST service (default port 17128), " +
160+
"used by `swctl admin ...` sub-commands. If empty, it is derived from `--base-url` " +
161+
"by reusing its host with port 17128.",
162+
Value: "",
163+
}),
153164
altsrc.NewStringFlag(&cli.StringFlag{
154165
Name: "grpc-addr",
155166
Usage: "backend gRPC service address `<host:port>`",

examples/.skywalking.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
# under the License.
1717

1818
base-url: http://demo.skywalking.apache.org/graphql
19+
# admin-url is the OAP admin-server REST host used by `swctl admin ...` sub-commands.
20+
# When omitted, it is derived from base-url's host with port 17128.
21+
admin-url: http://demo.skywalking.apache.org:17128
1922
grpc-addr: 127.0.0.1:11800
2023
username: basic-auth-username
2124
password: basic-auth-password

internal/commands/admin/admin.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package admin
19+
20+
import (
21+
"github.com/urfave/cli/v2"
22+
23+
"github.com/apache/skywalking-cli/internal/commands/admin/alarm"
24+
"github.com/apache/skywalking-cli/internal/commands/admin/cluster"
25+
"github.com/apache/skywalking-cli/internal/commands/admin/config"
26+
"github.com/apache/skywalking-cli/internal/commands/admin/dsldebug"
27+
"github.com/apache/skywalking-cli/internal/commands/admin/inspect"
28+
"github.com/apache/skywalking-cli/internal/commands/admin/oal"
29+
"github.com/apache/skywalking-cli/internal/commands/admin/runtimerule"
30+
"github.com/apache/skywalking-cli/internal/commands/admin/uitemplate"
31+
)
32+
33+
// Command is the parent of every sub-command that talks to the OAP admin-server
34+
// REST host (default port 17128), as opposed to the public GraphQL surface on
35+
// `--base-url` (default port 12800). The admin host bundles the status, inspect,
36+
// ui-management, dsl-debugging and runtime-rule feature modules. Its address comes
37+
// from `--admin-url` (or is derived from `--base-url` with port 17128).
38+
var Command = &cli.Command{
39+
Name: "admin",
40+
Usage: "Admin (REST) sub-commands that talk to the OAP admin-server (default port 17128)",
41+
UsageText: `Admin sub-commands call the OAP admin-server REST host, a separate surface from the
42+
public GraphQL endpoint used by the other commands.
43+
44+
The admin host address defaults to the "--base-url" host with port 17128; override it
45+
with the global "--admin-url" flag (or the SW_ADMIN_URL env var / "admin-url" config key).
46+
The admin host has no built-in authentication and is expected to sit behind a gateway;
47+
"--username"/"--password"/"--authorization" and "--insecure" apply to it the same way.`,
48+
Subcommands: []*cli.Command{
49+
preflightCommand,
50+
cluster.Command,
51+
config.Command,
52+
alarm.Command,
53+
inspect.Command,
54+
uitemplate.Command,
55+
runtimerule.Command,
56+
dsldebug.Command,
57+
oal.Command,
58+
},
59+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
// Package alarm exposes the admin-server alarm runtime status (loaded rule
19+
// definitions and per-entity evaluation/window state). This is distinct from the
20+
// top-level `swctl alarm` command, which reads fired alarm records via GraphQL.
21+
package alarm
22+
23+
import (
24+
"fmt"
25+
26+
"github.com/urfave/cli/v2"
27+
28+
"github.com/apache/skywalking-cli/pkg/admin/preflight"
29+
"github.com/apache/skywalking-cli/pkg/admin/status"
30+
"github.com/apache/skywalking-cli/pkg/display"
31+
"github.com/apache/skywalking-cli/pkg/display/displayable"
32+
)
33+
34+
var Command = &cli.Command{
35+
Name: "alarm",
36+
Usage: "Inspect alarm runtime status from the admin-server `status` module",
37+
UsageText: `Inspect the alarm-running kernel: loaded rule definitions and per-entity
38+
evaluation/window state. This differs from "swctl alarm list", which returns fired
39+
alarm records from the GraphQL surface.`,
40+
Subcommands: []*cli.Command{
41+
rulesCommand,
42+
ruleCommand,
43+
},
44+
}
45+
46+
var rulesCommand = &cli.Command{
47+
Name: "rules",
48+
Usage: "List the loaded alarm rules per OAP node (GET /status/alarm/rules)",
49+
UsageText: `List the loaded alarm rules, fanned out across every OAP node.
50+
51+
Examples:
52+
1. List alarm rules:
53+
$ swctl admin alarm rules`,
54+
Action: func(ctx *cli.Context) error {
55+
rules, err := status.AlarmRules(ctx.Context)
56+
if err != nil {
57+
return preflight.Explain(ctx.Context, err, preflight.ModuleStatus, "SW_STATUS")
58+
}
59+
return display.Display(ctx.Context, &displayable.Displayable{Data: rules})
60+
},
61+
}
62+
63+
var ruleCommand = &cli.Command{
64+
Name: "rule",
65+
Usage: "Show one alarm rule's definition and running state (GET /status/alarm/{ruleId}[/{entityName}])",
66+
ArgsUsage: "<ruleId> [<entityName>]",
67+
UsageText: `Show the definition and running state of a single alarm rule. When an
68+
entity name is given, the per-entity evaluation/window state is returned instead.
69+
70+
Examples:
71+
1. Show a rule's running state:
72+
$ swctl admin alarm rule service_resp_time_rule
73+
74+
2. Show the per-entity state of a rule:
75+
$ swctl admin alarm rule service_resp_time_rule mock_b_service`,
76+
Action: func(ctx *cli.Context) error {
77+
args := ctx.Args()
78+
ruleID := args.Get(0)
79+
if ruleID == "" {
80+
return fmt.Errorf("a <ruleId> argument is required")
81+
}
82+
entityName := args.Get(1)
83+
84+
var (
85+
result *status.ClusterAlarmStatus
86+
err error
87+
)
88+
if entityName == "" {
89+
result, err = status.AlarmRule(ctx.Context, ruleID)
90+
} else {
91+
result, err = status.AlarmRuleEntity(ctx.Context, ruleID, entityName)
92+
}
93+
if err != nil {
94+
return preflight.Explain(ctx.Context, err, preflight.ModuleStatus, "SW_STATUS")
95+
}
96+
return display.Display(ctx.Context, &displayable.Displayable{Data: result})
97+
},
98+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package cluster
19+
20+
import (
21+
"github.com/urfave/cli/v2"
22+
23+
"github.com/apache/skywalking-cli/pkg/admin/preflight"
24+
"github.com/apache/skywalking-cli/pkg/admin/status"
25+
"github.com/apache/skywalking-cli/pkg/display"
26+
"github.com/apache/skywalking-cli/pkg/display/displayable"
27+
)
28+
29+
var Command = &cli.Command{
30+
Name: "cluster",
31+
Usage: "Inspect the OAP cluster from the admin-server `status` module",
32+
Subcommands: []*cli.Command{
33+
nodesCommand,
34+
},
35+
}
36+
37+
var nodesCommand = &cli.Command{
38+
Name: "nodes",
39+
Usage: "List the OAP cluster peer nodes (GET /status/cluster/nodes)",
40+
UsageText: `List the OAP cluster peer nodes as seen by the cluster coordinator.
41+
42+
Examples:
43+
1. List cluster nodes:
44+
$ swctl admin cluster nodes`,
45+
Action: func(ctx *cli.Context) error {
46+
nodes, err := status.ClusterNodesQuery(ctx.Context)
47+
if err != nil {
48+
return preflight.Explain(ctx.Context, err, preflight.ModuleStatus, "SW_STATUS")
49+
}
50+
return display.Display(ctx.Context, &displayable.Displayable{Data: nodes})
51+
},
52+
}

0 commit comments

Comments
 (0)