Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.16.1] - 2026-09-02
- Fix: the Instances tab of the performance view now shows every pod of a k8s scope. The instance list had a hard cap of 10 that nothing could override, so a scope with 20 pods showed only the first 10 and the table had no next page. A `limit` in the request is honored, the `LIMIT` env var on the agent stays as the operator override, and with neither every pod is returned

## [1.16.0] - 2026-09-02
- k8s scopes now show live, step-by-step progress in the dashboard when a scope is created, updated or deleted, and for every deployment action (deploy, switch traffic, finalize, rollback, delete, diagnose, kill instance, restart pods, pause/resume autoscaling, set instance count): each step with its duration, and long waits (load balancer, DNS, instance health) saying what they are waiting for. Requires `NP_API_KEY` on the agent; without it everything works as before
- Failed k8s deployments now explain why on the step that failed, and what to do about it: image pull errors with the registry's message, out-of-memory kills, crash exit codes with the application's last log lines, and failing health checks with the path and response detected
Expand Down
7 changes: 6 additions & 1 deletion k8s/instance/build_context
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ export APPLICATION_ID=$(echo "$ARGUMENTS" | jq -r 'if (.application_id | type) =
export SCOPE_ID=$(echo "$ARGUMENTS" | jq -r 'if (.scope_id | type) == "array" then .scope_id[0] else .scope_id end')
export DEPLOYMENT_ID=$(echo "$ARGUMENTS" | jq -r 'if (.deployment_id | type) == "array" then .deployment_id[0] else .deployment_id end')

export LIMIT=${LIMIT:-10}
REQUEST_LIMIT=$(echo "$ARGUMENTS" | jq -r '(if (.limit | type) == "array" then .limit[0] else .limit end) // empty')
LIMIT="${REQUEST_LIMIT:-$LIMIT}"
if ! [[ "$LIMIT" =~ ^[0-9]+$ ]]; then
LIMIT=""
fi
export LIMIT
4 changes: 2 additions & 2 deletions k8s/instance/list
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fi

PODS=$(kubectl get pods -n "$K8S_NAMESPACE" -l "$LABEL_SELECTOR" -o json)

echo "$PODS" | jq --argjson limit ${LIMIT:-10} '{
results: .items[:$limit] | map({
echo "$PODS" | jq --argjson limit "${LIMIT:-0}" '{
results: (if $limit > 0 then .items[:$limit] else .items end) | map({
id: .metadata.name,
selector: .metadata.labels,
details: {
Expand Down
47 changes: 47 additions & 0 deletions k8s/instance/tests/build_context.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bats
# =============================================================================
# Unit tests for instance/build_context - limit resolution
# =============================================================================

setup() {
export PROJECT_ROOT="$(cd "$BATS_TEST_DIRNAME/../../.." && pwd)"
unset LIMIT
}

@test "no limit in the request and no LIMIT env leaves LIMIT empty" {
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ -z "$LIMIT" ]
}

@test "limit in the request is exported as LIMIT" {
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9,"limit":25}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ "$LIMIT" = "25" ]
}

@test "array-valued limit takes the first element" {
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9,"limit":["7"]}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ "$LIMIT" = "7" ]
}

@test "LIMIT env is used when the request has no limit" {
export LIMIT=50
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ "$LIMIT" = "50" ]
}

@test "request limit wins over LIMIT env" {
export LIMIT=50
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9,"limit":25}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ "$LIMIT" = "25" ]
}

@test "non-numeric limit is ignored" {
export CONTEXT='{"arguments":{"application_id":1,"scope_id":9,"limit":"all"}}'
source "$PROJECT_ROOT/k8s/instance/build_context"
[ -z "$LIMIT" ]
}
39 changes: 39 additions & 0 deletions k8s/instance/tests/list.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env bats
# =============================================================================
# Unit tests for instance/list - how LIMIT caps the pod list
# =============================================================================

setup() {
export PROJECT_ROOT="$(cd "$BATS_TEST_DIRNAME/../../.." && pwd)"
unset LIMIT APPLICATION_ID SCOPE_ID DEPLOYMENT_ID

kubectl() {
jq -n '{items: [range(1; 4) | {
metadata: {name: "pod-\(.)", namespace: "nullplatform", creationTimestamp: "2025-01-01T00:00:00Z", labels: {}},
status: {phase: "Running", podIP: "10.0.0.\(.)", containerStatuses: [{image: "app:x86"}]},
spec: {nodeName: "node-1", containers: [{resources: {requests: {cpu: "100m", memory: "128Mi"}, limits: {cpu: "200m", memory: "256Mi"}}}]}
}]}'
}
export -f kubectl
}

@test "without LIMIT every pod is returned" {
run bash "$PROJECT_ROOT/k8s/instance/list"
[ "$status" -eq 0 ]
[ "$(echo "$output" | jq '.results | length')" -eq 3 ]
}

@test "LIMIT caps the list to the first N pods" {
export LIMIT=2
run bash "$PROJECT_ROOT/k8s/instance/list"
[ "$status" -eq 0 ]
[ "$(echo "$output" | jq '.results | length')" -eq 2 ]
[ "$(echo "$output" | jq -r '.results[0].id')" = "pod-1" ]
}

@test "LIMIT=0 means no cap" {
export LIMIT=0
run bash "$PROJECT_ROOT/k8s/instance/list"
[ "$status" -eq 0 ]
[ "$(echo "$output" | jq '.results | length')" -eq 3 ]
}
Loading