mirror of
https://github.com/netbirdio/netbird.git
synced 2026-10-22 13:29:08 +02:00
fix api object
This commit is contained in:
@@ -98,10 +98,11 @@ func (h *Handler) ListJobs(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
respBody := make([]*api.Job, 0, len(jobs))
|
||||
respBody := make([]*api.JobResponse, 0, len(jobs))
|
||||
for _, job := range jobs {
|
||||
resp, err := toSingleJobResponse(job)
|
||||
if err != nil {
|
||||
log.WithContext(ctx).Errorf("failed xxx: %v", err)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
@@ -518,27 +519,25 @@ func toPeerListItemResponse(peer *nbpeer.Peer, groupsInfo []api.GroupMinimum, dn
|
||||
}
|
||||
}
|
||||
|
||||
func toSingleJobResponse(job *types.Job) (*api.Job, error) {
|
||||
var parameters map[string]any
|
||||
if err := job.DecodeParameters(¶meters); err != nil {
|
||||
func toSingleJobResponse(job *types.Job) (*api.JobResponse, error) {
|
||||
var workloadResponse api.WorkloadResponse
|
||||
if err := job.BuildWorkloadResponse(&workloadResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &api.Job{
|
||||
|
||||
var failed *string
|
||||
if job.FailedReason != "" {
|
||||
failed = &job.FailedReason
|
||||
}
|
||||
|
||||
return &api.JobResponse{
|
||||
Id: job.ID,
|
||||
Status: (*api.JobStatus)(&job.Status),
|
||||
CompletedAt: job.CompletedAt,
|
||||
CreatedAt: job.CreatedAt,
|
||||
FailedReason: &job.FailedReason,
|
||||
CompletedAt: job.CompletedAt,
|
||||
TriggeredBy: job.TriggeredBy,
|
||||
Workload: struct {
|
||||
Parameters *map[string]any "json:\"parameters,omitempty\""
|
||||
Result *string "json:\"result,omitempty\""
|
||||
Type *api.JobWorkloadType "json:\"type,omitempty\""
|
||||
}{
|
||||
Type: (*api.JobWorkloadType)(&job.Type),
|
||||
Parameters: ¶meters,
|
||||
Result: &job.Result,
|
||||
},
|
||||
Status: api.JobResponseStatus(job.Status),
|
||||
FailedReason: failed,
|
||||
Workload: workloadResponse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ type JobType string
|
||||
|
||||
const (
|
||||
JobTypeBundle JobType = "bundle"
|
||||
JobTypeOther JobType = "other"
|
||||
// add more job types here
|
||||
)
|
||||
|
||||
@@ -51,109 +52,113 @@ type Job struct {
|
||||
FailedReason string
|
||||
|
||||
// Result can contain job output (JSON, URL, etc.)
|
||||
Result string
|
||||
Result json.RawMessage `gorm:"type:json"`
|
||||
|
||||
// Parameters is a JSON blob storing job configuration (untyped)
|
||||
Parameters json.RawMessage `gorm:"type:json"`
|
||||
}
|
||||
|
||||
// JobParametersBundle represents parameters for bundle/debug jobs
|
||||
type JobParametersBundle struct {
|
||||
BundleFor bool `json:"bundle_for"`
|
||||
BundleForTime int `json:"bundle_for_time"` // minutes
|
||||
LogFileCount int `json:"log_file_count"`
|
||||
Anonymize bool `json:"anonymize"`
|
||||
}
|
||||
|
||||
// NewJob creates a new job with default fields and validation
|
||||
func NewJob(triggeredBy, accountID, peerID string, req *api.JobRequest) (*Job, error) {
|
||||
if req.Workload.Type == nil {
|
||||
return nil, fmt.Errorf("Job type required")
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("job request cannot be nil")
|
||||
}
|
||||
|
||||
if req.Workload.Parameters == nil {
|
||||
return nil, fmt.Errorf("Job parameters required")
|
||||
// Determine job type
|
||||
jobTypeStr, err := req.Workload.Discriminator()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not determine job type: %w", err)
|
||||
}
|
||||
jobType := JobType(jobTypeStr)
|
||||
|
||||
var params []byte
|
||||
|
||||
switch jobType {
|
||||
case JobTypeBundle:
|
||||
bundle, err := req.Workload.AsBundleWorkloadRequest()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid parameters for bundle job: %w", err)
|
||||
}
|
||||
if err := validateDebugBundleJobParams(bundle); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params, err = json.Marshal(bundle.Parameters)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal workload parameters: %w", err)
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported job type: %s", jobType)
|
||||
}
|
||||
|
||||
job := &Job{
|
||||
return &Job{
|
||||
ID: uuid.New().String(),
|
||||
TriggeredBy: triggeredBy,
|
||||
PeerID: peerID,
|
||||
AccountID: accountID,
|
||||
Type: JobType(*req.Workload.Type),
|
||||
Type: jobType,
|
||||
Status: JobStatusPending,
|
||||
Parameters: params,
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
|
||||
// Encode parameters
|
||||
if err := job.encodeParameters(*req.Workload.Parameters); err != nil {
|
||||
return nil, fmt.Errorf("failed to encode job parameters: %w", err)
|
||||
}
|
||||
|
||||
// Validate job
|
||||
if err := job.validateJobRequest(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return job, nil
|
||||
Result: []byte("{}"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// DecodeParameters decodes raw parameters into a target struct
|
||||
func (j *Job) DecodeParameters(target any) error {
|
||||
if len(j.Parameters) == 0 {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(j.Parameters, target)
|
||||
}
|
||||
|
||||
// EncodeParameters replaces raw parameters with marshaled JSON
|
||||
func (j *Job) encodeParameters(params map[string]any) error {
|
||||
if params == nil {
|
||||
return fmt.Errorf("parameters cannot be empty")
|
||||
}
|
||||
data, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
j.Parameters = data
|
||||
return nil
|
||||
}
|
||||
|
||||
func (j *Job) validateJobRequest() error {
|
||||
if j == nil {
|
||||
return fmt.Errorf("job cannot be nil")
|
||||
}
|
||||
|
||||
if len(j.Parameters) == 0 {
|
||||
return fmt.Errorf("job parameters must be provided")
|
||||
}
|
||||
|
||||
func (j *Job) BuildWorkloadResponse(wl *api.WorkloadResponse) error {
|
||||
switch j.Type {
|
||||
case JobTypeBundle:
|
||||
if err := j.validateDebugBundleJobParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return j.buildBundleWorkload(wl)
|
||||
case JobTypeOther:
|
||||
return j.buildOtherWorkload(wl)
|
||||
default:
|
||||
return fmt.Errorf("unsupported job type: %s", j.Type)
|
||||
return fmt.Errorf("unknown job type: %v", j.Type)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (j *Job) validateDebugBundleJobParams() error {
|
||||
var params JobParametersBundle
|
||||
if err := j.DecodeParameters(¶ms); err != nil {
|
||||
func (j *Job) buildBundleWorkload(wl *api.WorkloadResponse) error {
|
||||
var p api.BundleParameters
|
||||
|
||||
if err := json.Unmarshal(j.Parameters, &p); err != nil {
|
||||
return fmt.Errorf("invalid parameters for bundle job: %w", err)
|
||||
}
|
||||
// validate bundle_for_time <= 5 minutes
|
||||
if params.BundleForTime < 0 || params.BundleForTime > 5 {
|
||||
return fmt.Errorf("bundle_for_time must be between 0 and 5, got %d", params.BundleForTime)
|
||||
|
||||
var r api.BundleResult
|
||||
if err := json.Unmarshal(j.Result, &r); err != nil {
|
||||
return fmt.Errorf("invalid result for bundle job: %w", err)
|
||||
}
|
||||
|
||||
return wl.FromBundleWorkloadResponse(api.BundleWorkloadResponse{
|
||||
Type: api.WorkloadTypeBundle,
|
||||
Parameters: p,
|
||||
Result: r,
|
||||
})
|
||||
}
|
||||
|
||||
func (j *Job) buildOtherWorkload(wl *api.WorkloadResponse) error {
|
||||
var p api.OtherParameters
|
||||
if err := json.Unmarshal(j.Parameters, &p); err != nil {
|
||||
return fmt.Errorf("invalid parameters for bundle job: %w", err)
|
||||
}
|
||||
|
||||
var r api.OtherResult
|
||||
if err := json.Unmarshal(j.Result, &r); err != nil {
|
||||
return fmt.Errorf("invalid result for bundle job: %w", err)
|
||||
}
|
||||
|
||||
return wl.FromOtherWorkloadResponse(api.OtherWorkloadResponse{
|
||||
Type: api.WorkloadTypeOther,
|
||||
Parameters: p,
|
||||
Result: r,
|
||||
})
|
||||
}
|
||||
|
||||
func validateDebugBundleJobParams(bundle api.BundleWorkloadRequest) error {
|
||||
// validate bundle_for_time <= 5 minutes
|
||||
if bundle.Parameters.BundleForTime < 0 || bundle.Parameters.BundleForTime > 5 {
|
||||
return fmt.Errorf("bundle_for_time must be between 0 and 5, got %d", bundle.Parameters.BundleForTime)
|
||||
}
|
||||
// validate log-file-count ≥ 1 and ≤ 1000
|
||||
if params.LogFileCount < 1 || params.LogFileCount > 1000 {
|
||||
return fmt.Errorf("log-file-count must be between 1 and 1000, got %d", params.LogFileCount)
|
||||
if bundle.Parameters.LogFileCount < 1 || bundle.Parameters.LogFileCount > 1000 {
|
||||
return fmt.Errorf("log-file-count must be between 1 and 1000, got %d", bundle.Parameters.LogFileCount)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user