[Management/Client] Trigger debug bundle runs from API/Dashboard (#4592) (#4832)

This PR adds the ability to trigger debug bundle generation remotely from the Management API/Dashboard.
This commit is contained in:
Zoltan Papp
2026-01-19 11:22:16 +01:00
committed by GitHub
parent 245481f33b
commit 58daa674ef
61 changed files with 3657 additions and 1239 deletions

View File

@@ -11,6 +11,6 @@ fi
old_pwd=$(pwd)
script_path=$(dirname $(realpath "$0"))
cd "$script_path"
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@4a1477f6a8ba6ca8115cc23bb2fb67f0b9fca18e
go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest
oapi-codegen --config cfg.yaml openapi.yml
cd "$old_pwd"
cd "$old_pwd"

View File

@@ -38,8 +38,128 @@ tags:
description: Interact with and view information about identity providers.
- name: Instance
description: Instance setup and status endpoints for initial configuration.
- name: Jobs
description: Interact with and view information about remote jobs.
x-experimental: true
components:
schemas:
WorkloadType:
type: string
description: |
Identifies the type of workload the job will execute.
Currently only `"bundle"` is supported.
enum:
- bundle
example: "bundle"
BundleParameters:
type: object
description: These parameters control what gets included in the bundle and how it is processed.
properties:
bundle_for:
type: boolean
description: Whether to generate a bundle for the given timeframe.
example: true
bundle_for_time:
type: integer
minimum: 1
maximum: 5
description: Time period in minutes for which to generate the bundle.
example: 2
log_file_count:
type: integer
minimum: 1
maximum: 1000
description: Maximum number of log files to include in the bundle.
example: 100
anonymize:
type: boolean
description: Whether sensitive data should be anonymized in the bundle.
example: false
required:
- bundle_for
- bundle_for_time
- log_file_count
- anonymize
BundleResult:
type: object
properties:
upload_key:
type: string
example: "upload_key_123"
nullable: true
BundleWorkloadRequest:
type: object
properties:
type:
$ref: '#/components/schemas/WorkloadType'
parameters:
$ref: '#/components/schemas/BundleParameters'
required:
- type
- parameters
BundleWorkloadResponse:
type: object
properties:
type:
$ref: '#/components/schemas/WorkloadType'
parameters:
$ref: '#/components/schemas/BundleParameters'
result:
$ref: '#/components/schemas/BundleResult'
required:
- type
- parameters
- result
WorkloadRequest:
oneOf:
- $ref: '#/components/schemas/BundleWorkloadRequest'
discriminator:
propertyName: type
mapping:
bundle: '#/components/schemas/BundleWorkloadRequest'
WorkloadResponse:
oneOf:
- $ref: '#/components/schemas/BundleWorkloadResponse'
discriminator:
propertyName: type
mapping:
bundle: '#/components/schemas/BundleWorkloadResponse'
JobRequest:
type: object
properties:
workload:
$ref: '#/components/schemas/WorkloadRequest'
required:
- workload
JobResponse:
type: object
properties:
id:
type: string
created_at:
type: string
format: date-time
completed_at:
type: string
format: date-time
nullable: true
triggered_by:
type: string
status:
type: string
enum: [pending, succeeded, failed]
failed_reason:
type: string
nullable: true
workload:
$ref: '#/components/schemas/WorkloadResponse'
required:
- id
- created_at
- status
- triggered_by
- workload
Account:
type: object
properties:
@@ -2554,6 +2674,110 @@ paths:
content: { }
'500':
"$ref": "#/components/responses/internal_error"
/api/peers/{peerId}/jobs:
get:
summary: List Jobs
description: Retrieve all jobs for a given peer
tags: [ Jobs ]
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
description: The unique identifier of a peer
required: true
schema:
type: string
responses:
'200':
description: List of jobs
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/JobResponse'
'400':
$ref: '#/components/responses/bad_request'
'401':
$ref: '#/components/responses/requires_authentication'
'403':
$ref: '#/components/responses/forbidden'
'500':
$ref: '#/components/responses/internal_error'
post:
summary: Create Job
description: Create a new job for a given peer
tags: [ Jobs ]
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
description: The unique identifier of a peer
required: true
schema:
type: string
requestBody:
description: Create job request
content:
application/json:
schema:
$ref: '#/components/schemas/JobRequest'
required: true
responses:
'201':
description: Job created
content:
application/json:
schema:
$ref: '#/components/schemas/JobResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/peers/{peerId}/jobs/{jobId}:
get:
summary: Get Job
description: Retrieve details of a specific job
tags: [ Jobs ]
security:
- BearerAuth: []
- TokenAuth: []
parameters:
- in: path
name: peerId
required: true
description: The unique identifier of a peer
schema:
type: string
- in: path
name: jobId
required: true
description: The unique identifier of a job
schema:
type: string
responses:
'200':
description: A Job object
content:
application/json:
schema:
$ref: '#/components/schemas/JobResponse'
'400':
"$ref": "#/components/responses/bad_request"
'401':
"$ref": "#/components/responses/requires_authentication"
'403':
"$ref": "#/components/responses/forbidden"
'500':
"$ref": "#/components/responses/internal_error"
/api/accounts:
get:
summary: List all Accounts

View File

@@ -1,10 +1,14 @@
// Package api provides primitives to interact with the openapi HTTP API.
//
// Code generated by github.com/deepmap/oapi-codegen version v1.11.1-0.20220912230023-4a1477f6a8ba DO NOT EDIT.
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.5.1 DO NOT EDIT.
package api
import (
"encoding/json"
"errors"
"time"
"github.com/oapi-codegen/runtime"
)
const (
@@ -122,6 +126,13 @@ const (
IngressPortAllocationRequestPortRangeProtocolUdp IngressPortAllocationRequestPortRangeProtocol = "udp"
)
// Defines values for JobResponseStatus.
const (
JobResponseStatusFailed JobResponseStatus = "failed"
JobResponseStatusPending JobResponseStatus = "pending"
JobResponseStatusSucceeded JobResponseStatus = "succeeded"
)
// Defines values for NameserverNsType.
const (
NameserverNsTypeUdp NameserverNsType = "udp"
@@ -200,6 +211,11 @@ const (
UserStatusInvited UserStatus = "invited"
)
// Defines values for WorkloadType.
const (
WorkloadTypeBundle WorkloadType = "bundle"
)
// Defines values for GetApiEventsNetworkTrafficParamsType.
const (
GetApiEventsNetworkTrafficParamsTypeTYPEDROP GetApiEventsNetworkTrafficParamsType = "TYPE_DROP"
@@ -368,6 +384,47 @@ type AvailablePorts struct {
Udp int `json:"udp"`
}
// BundleParameters These parameters control what gets included in the bundle and how it is processed.
type BundleParameters struct {
// Anonymize Whether sensitive data should be anonymized in the bundle.
Anonymize bool `json:"anonymize"`
// BundleFor Whether to generate a bundle for the given timeframe.
BundleFor bool `json:"bundle_for"`
// BundleForTime Time period in minutes for which to generate the bundle.
BundleForTime int `json:"bundle_for_time"`
// LogFileCount Maximum number of log files to include in the bundle.
LogFileCount int `json:"log_file_count"`
}
// BundleResult defines model for BundleResult.
type BundleResult struct {
UploadKey *string `json:"upload_key"`
}
// BundleWorkloadRequest defines model for BundleWorkloadRequest.
type BundleWorkloadRequest struct {
// Parameters These parameters control what gets included in the bundle and how it is processed.
Parameters BundleParameters `json:"parameters"`
// Type Identifies the type of workload the job will execute.
// Currently only `"bundle"` is supported.
Type WorkloadType `json:"type"`
}
// BundleWorkloadResponse defines model for BundleWorkloadResponse.
type BundleWorkloadResponse struct {
// Parameters These parameters control what gets included in the bundle and how it is processed.
Parameters BundleParameters `json:"parameters"`
Result BundleResult `json:"result"`
// Type Identifies the type of workload the job will execute.
// Currently only `"bundle"` is supported.
Type WorkloadType `json:"type"`
}
// Checks List of objects that perform the actual checks
type Checks struct {
// GeoLocationCheck Posture check for geo location
@@ -755,6 +812,25 @@ type InstanceStatus struct {
SetupRequired bool `json:"setup_required"`
}
// JobRequest defines model for JobRequest.
type JobRequest struct {
Workload WorkloadRequest `json:"workload"`
}
// JobResponse defines model for JobResponse.
type JobResponse struct {
CompletedAt *time.Time `json:"completed_at"`
CreatedAt time.Time `json:"created_at"`
FailedReason *string `json:"failed_reason"`
Id string `json:"id"`
Status JobResponseStatus `json:"status"`
TriggeredBy string `json:"triggered_by"`
Workload WorkloadResponse `json:"workload"`
}
// JobResponseStatus defines model for JobResponse.Status.
type JobResponseStatus string
// Location Describe geographical location information
type Location struct {
// CityName Commonly used English name of the city
@@ -2042,6 +2118,20 @@ type UserRequest struct {
Role string `json:"role"`
}
// WorkloadRequest defines model for WorkloadRequest.
type WorkloadRequest struct {
union json.RawMessage
}
// WorkloadResponse defines model for WorkloadResponse.
type WorkloadResponse struct {
union json.RawMessage
}
// WorkloadType Identifies the type of workload the job will execute.
// Currently only `"bundle"` is supported.
type WorkloadType string
// Zone defines model for Zone.
type Zone struct {
// DistributionGroups Group IDs that defines groups of peers that will resolve this zone
@@ -2225,6 +2315,9 @@ type PostApiPeersPeerIdIngressPortsJSONRequestBody = IngressPortAllocationReques
// PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody defines body for PutApiPeersPeerIdIngressPortsAllocationId for application/json ContentType.
type PutApiPeersPeerIdIngressPortsAllocationIdJSONRequestBody = IngressPortAllocationRequest
// PostApiPeersPeerIdJobsJSONRequestBody defines body for PostApiPeersPeerIdJobs for application/json ContentType.
type PostApiPeersPeerIdJobsJSONRequestBody = JobRequest
// PostApiPeersPeerIdTemporaryAccessJSONRequestBody defines body for PostApiPeersPeerIdTemporaryAccess for application/json ContentType.
type PostApiPeersPeerIdTemporaryAccessJSONRequestBody = PeerTemporaryAccessRequest
@@ -2263,3 +2356,121 @@ type PutApiUsersUserIdJSONRequestBody = UserRequest
// PostApiUsersUserIdTokensJSONRequestBody defines body for PostApiUsersUserIdTokens for application/json ContentType.
type PostApiUsersUserIdTokensJSONRequestBody = PersonalAccessTokenRequest
// AsBundleWorkloadRequest returns the union data inside the WorkloadRequest as a BundleWorkloadRequest
func (t WorkloadRequest) AsBundleWorkloadRequest() (BundleWorkloadRequest, error) {
var body BundleWorkloadRequest
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromBundleWorkloadRequest overwrites any union data inside the WorkloadRequest as the provided BundleWorkloadRequest
func (t *WorkloadRequest) FromBundleWorkloadRequest(v BundleWorkloadRequest) error {
v.Type = "bundle"
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeBundleWorkloadRequest performs a merge with any union data inside the WorkloadRequest, using the provided BundleWorkloadRequest
func (t *WorkloadRequest) MergeBundleWorkloadRequest(v BundleWorkloadRequest) error {
v.Type = "bundle"
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t WorkloadRequest) Discriminator() (string, error) {
var discriminator struct {
Discriminator string `json:"type"`
}
err := json.Unmarshal(t.union, &discriminator)
return discriminator.Discriminator, err
}
func (t WorkloadRequest) ValueByDiscriminator() (interface{}, error) {
discriminator, err := t.Discriminator()
if err != nil {
return nil, err
}
switch discriminator {
case "bundle":
return t.AsBundleWorkloadRequest()
default:
return nil, errors.New("unknown discriminator value: " + discriminator)
}
}
func (t WorkloadRequest) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *WorkloadRequest) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}
// AsBundleWorkloadResponse returns the union data inside the WorkloadResponse as a BundleWorkloadResponse
func (t WorkloadResponse) AsBundleWorkloadResponse() (BundleWorkloadResponse, error) {
var body BundleWorkloadResponse
err := json.Unmarshal(t.union, &body)
return body, err
}
// FromBundleWorkloadResponse overwrites any union data inside the WorkloadResponse as the provided BundleWorkloadResponse
func (t *WorkloadResponse) FromBundleWorkloadResponse(v BundleWorkloadResponse) error {
v.Type = "bundle"
b, err := json.Marshal(v)
t.union = b
return err
}
// MergeBundleWorkloadResponse performs a merge with any union data inside the WorkloadResponse, using the provided BundleWorkloadResponse
func (t *WorkloadResponse) MergeBundleWorkloadResponse(v BundleWorkloadResponse) error {
v.Type = "bundle"
b, err := json.Marshal(v)
if err != nil {
return err
}
merged, err := runtime.JSONMerge(t.union, b)
t.union = merged
return err
}
func (t WorkloadResponse) Discriminator() (string, error) {
var discriminator struct {
Discriminator string `json:"type"`
}
err := json.Unmarshal(t.union, &discriminator)
return discriminator.Discriminator, err
}
func (t WorkloadResponse) ValueByDiscriminator() (interface{}, error) {
discriminator, err := t.Discriminator()
if err != nil {
return nil, err
}
switch discriminator {
case "bundle":
return t.AsBundleWorkloadResponse()
default:
return nil, errors.New("unknown discriminator value: " + discriminator)
}
}
func (t WorkloadResponse) MarshalJSON() ([]byte, error) {
b, err := t.union.MarshalJSON()
return b, err
}
func (t *WorkloadResponse) UnmarshalJSON(b []byte) error {
err := t.union.UnmarshalJSON(b)
return err
}