Skip to content

Commit abb6af4

Browse files
committed
Clean up...
1 parent 3d2ce1c commit abb6af4

5 files changed

Lines changed: 3 additions & 39 deletions

File tree

internal/infra/mcp/tools/tool_k8s_list_top_unavailable_pods.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,6 @@ func buildTopUnavailablePodsQuery(limit int, clusterName, namespaceName, workloa
100100
}
101101

102102
if !tw.IsZero() {
103-
// Sysdig-canonical pattern (backend/.../advisories.json:206 — WorkloadReplicasMismatch):
104-
// min_over_time(kube_workload_status_unavailable[W]) >= 1 — workload was unavailable
105-
// for every scrape tick in the window. Simpler and more accurate than computing
106-
// desired - ready across the window.
107103
filtersStr := strings.Join(baseFilters, ",")
108104
return fmt.Sprintf("topk(%d, sum by (kube_cluster_name, kube_namespace_name, kube_workload_name) (min_over_time(kube_workload_status_unavailable{%s}%s) >= 1))",
109105
limit, filtersStr, tw.RangeSelector())

internal/infra/mcp/tools/tool_k8s_list_workloads.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,6 @@ func buildKubeWorkloadInfoQuery(status, clusterName, namespaceName, workloadName
118118
}
119119

120120
if !tw.IsZero() {
121-
// For "unavailable" the canonical Sysdig idiom keeps a > 0 guard to drop
122-
// workloads that were healthy all window (see advisories.json:206).
123-
// For desired/ready/running, zero is a legitimate observed value.
124121
wrapped := fmt.Sprintf("max_over_time(%s%s)", metric, tw.RangeSelector())
125122
if status == "unavailable" {
126123
return wrapped + " > 0"

internal/infra/mcp/tools/tools_suite_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@ func TestTools(t *testing.T) {
1515
RunSpecs(t, "Tools Suite")
1616
}
1717

18-
// newWindowedQueryParams constructs the GetQueryV1Params value that a windowed tool
19-
// invocation is expected to produce: Query string, Time = end.Unix() via FromQueryTime1,
20-
// and a 60s Timeout.
2118
func newWindowedQueryParams(query string, end time.Time) sysdig.GetQueryV1Params {
2219
var qt sysdig.Time
2320
Expect(qt.FromQueryTime1(end.Unix())).To(Succeed())
@@ -29,8 +26,6 @@ func newWindowedQueryParams(query string, end time.Time) sysdig.GetQueryV1Params
2926
}
3027
}
3128

32-
// mergeLimit attaches a Limit field to an existing GetQueryV1Params value.
33-
// Used by tools that set params.Limit (memory_*, count_pods, underutilized_*).
3429
func mergeLimit(p sysdig.GetQueryV1Params, limit int) sysdig.GetQueryV1Params {
3530
lq := sysdig.LimitQuery(limit)
3631
p.Limit = &lq

internal/infra/mcp/tools/utils.go

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ func RequiredPermissionsFromTool(tool mcp.Tool) []string {
5757
return requiredPermissions
5858
}
5959

60-
// --- Time-window support for k8s_list_* Monitor tools --------------------
61-
6260
const (
6361
windowedQueryTimeout = "60s"
6462
timeParamStart = "start"
@@ -67,32 +65,23 @@ const (
6765
endParamDescription = "End of the query window as an RFC3339 timestamp (e.g. 2026-04-01T01:00:00Z). Requires start. If in the future, clamped to now."
6866
)
6967

70-
// TimeWindow is a resolved, validated [Start, End] pair for a historical PromQL query.
71-
// A zero-value TimeWindow means no window was requested — the caller should emit its
72-
// existing instant query and leave GetQueryV1Params.Time nil.
7368
type TimeWindow struct {
7469
Start time.Time
7570
End time.Time
7671
}
7772

78-
// IsZero reports whether no time window was requested.
7973
func (w TimeWindow) IsZero() bool {
8074
return w.Start.IsZero() && w.End.IsZero()
8175
}
8276

83-
// RangeSelector returns the PromQL range-selector literal for this window, e.g. "[3600s]".
8477
func (w TimeWindow) RangeSelector() string {
8578
return fmt.Sprintf("[%ds]", int64(w.End.Sub(w.Start).Seconds()))
8679
}
8780

88-
// WindowSeconds returns the duration of the window in whole seconds.
8981
func (w TimeWindow) WindowSeconds() int64 {
9082
return int64(w.End.Sub(w.Start).Seconds())
9183
}
9284

93-
// EvalTime returns a *sysdig.Time suitable for GetQueryV1Params.Time. The value is
94-
// the End instant as unix seconds — the native format accepted by Sysdig's internal
95-
// PromQL stack (confirmed against backend PrometheusFacadeController.java:113).
9685
func (w TimeWindow) EvalTime() (*sysdig.Time, error) {
9786
if w.IsZero() {
9887
return nil, nil
@@ -104,9 +93,6 @@ func (w TimeWindow) EvalTime() (*sysdig.Time, error) {
10493
return &qt, nil
10594
}
10695

107-
// ApplyToParams sets Time and, for windowed queries, Timeout on params.
108-
// It consolidates the three-step boilerplate (EvalTime, set Time, set Timeout)
109-
// that every k8s_list_* handler would otherwise repeat.
11096
func (w TimeWindow) ApplyToParams(params *sysdig.GetQueryV1Params) error {
11197
evalTime, err := w.EvalTime()
11298
if err != nil {
@@ -120,23 +106,15 @@ func (w TimeWindow) ApplyToParams(params *sysdig.GetQueryV1Params) error {
120106
return nil
121107
}
122108

123-
// WithTimeWindowParams returns a ToolOption that declares the shared "start" and "end"
124-
// RFC3339 parameters on a tool.
125109
func WithTimeWindowParams() mcp.ToolOption {
126110
return func(t *mcp.Tool) {
127111
mcp.WithString(timeParamStart, mcp.Description(startParamDescription))(t)
128112
mcp.WithString(timeParamEnd, mcp.Description(endParamDescription))(t)
129113
}
130114
}
131115

132-
// ParseTimeWindow reads "start" and "end" from the request, validates them, and returns
133-
// the resolved TimeWindow.
134-
//
135-
// - Both absent: returns zero-value TimeWindow, nil error.
136-
// - end without start: error ("end requires start").
137-
// - start without end: end = clk.Now().
138-
// - invalid RFC3339: error naming the bad field.
139-
// - end <= start: error.
116+
// Reads "start" and "end" from the request, validates them, and return the resolved TimeWindow.
117+
140118
func ParseTimeWindow(request mcp.CallToolRequest, clk clock.Clock) (TimeWindow, error) {
141119
startStr := mcp.ParseString(request, timeParamStart, "")
142120
endStr := mcp.ParseString(request, timeParamEnd, "")

internal/infra/mcp/tools/utils_test.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ var _ = Describe("ParseTimeWindow", func() {
2222
BeforeEach(func() {
2323
ctrl = gomock.NewController(GinkgoT())
2424
mockClock = mocks_clock.NewMockClock(ctrl)
25-
now = time.Date(2026, time.April, 16, 12, 0, 0, 500000000, time.UTC) // has sub-second part
25+
now = time.Date(2026, time.April, 16, 12, 0, 0, 500000000, time.UTC)
2626
})
2727

2828
AfterEach(func() { ctrl.Finish() })
@@ -102,8 +102,6 @@ var _ = Describe("ParseTimeWindow", func() {
102102
})
103103

104104
It("truncates sub-second precision from now so RangeSelector never emits [0s]", func() {
105-
// now has 500ms; start is in the same second — after truncation end == start,
106-
// which must be rejected rather than silently producing [0s].
107105
mockClock.EXPECT().Now().Return(now)
108106
_, err := tools.ParseTimeWindow(makeRequest(map[string]any{
109107
"start": "2026-04-16T12:00:00Z",

0 commit comments

Comments
 (0)