mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-18 00:06:38 +00:00
apply feedbacks 1
This commit is contained in:
@@ -123,7 +123,7 @@ type Manager interface {
|
||||
UpdateToPrimaryAccount(ctx context.Context, accountId string) error
|
||||
GetOwnerInfo(ctx context.Context, accountId string) (*types.UserInfo, error)
|
||||
GetCurrentUserInfo(ctx context.Context, userAuth nbcontext.UserAuth) (*users.UserInfoWithPermissions, error)
|
||||
CreateJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error
|
||||
GetAllJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error)
|
||||
GetJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error)
|
||||
CreatePeerJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error
|
||||
GetAllPeerJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error)
|
||||
GetPeerJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error)
|
||||
}
|
||||
|
||||
@@ -286,6 +286,8 @@ var activityMap = map[Activity]Code{
|
||||
AccountNetworkRangeUpdated: {"Account network range updated", "account.network.range.update"},
|
||||
|
||||
PeerIPUpdated: {"Peer IP updated", "peer.ip.update"},
|
||||
|
||||
JobCreatedByUser: {"Create Job for peer", "peer.job.created"},
|
||||
}
|
||||
|
||||
// StringCode returns a string code of the activity
|
||||
|
||||
@@ -58,17 +58,17 @@ func (h *Handler) CreateJob(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
req := &api.JobRequest{}
|
||||
if err := json.NewDecoder(r.Body).Decode(req); err != nil {
|
||||
util.WriteErrorResponse("invalid JSON payload", http.StatusBadRequest, w)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
job, err := types.NewJob(userAuth.UserId, userAuth.AccountId, peerID, types.JobType(req.Type), req.Parameters)
|
||||
if err != nil {
|
||||
util.WriteErrorResponse(fmt.Sprintf("invalid Job request %v", err), http.StatusBadRequest, w)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
if err := h.accountManager.CreateJob(ctx, userAuth.AccountId, peerID, userAuth.UserId, job); err != nil {
|
||||
util.WriteErrorResponse(fmt.Sprintf("failed to create job %v", err), http.StatusInternalServerError, w)
|
||||
if err := h.accountManager.CreatePeerJob(ctx, userAuth.AccountId, peerID, userAuth.UserId, job); err != nil {
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,16 +79,16 @@ func (h *Handler) ListJobs(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
userAuth, err := nbcontext.GetUserAuthFromContext(ctx)
|
||||
if err != nil {
|
||||
util.WriteError(r.Context(), err, w)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
vars := mux.Vars(r)
|
||||
peerID := vars["peerId"]
|
||||
|
||||
jobs, err := h.accountManager.GetAllJobs(ctx, userAuth.AccountId, userAuth.UserId, peerID)
|
||||
jobs, err := h.accountManager.GetAllPeerJobs(ctx, userAuth.AccountId, userAuth.UserId, peerID)
|
||||
if err != nil {
|
||||
util.WriteErrorResponse(fmt.Sprintf("failed to fetch jobs %v", err), http.StatusInternalServerError, w)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -107,9 +107,9 @@ func (h *Handler) GetJob(w http.ResponseWriter, r *http.Request) {
|
||||
peerID := vars["peerId"]
|
||||
jobID := vars["jobId"]
|
||||
|
||||
job, err := h.accountManager.GetJobByID(ctx, userAuth.AccountId, userAuth.UserId, peerID, jobID)
|
||||
job, err := h.accountManager.GetPeerJobByID(ctx, userAuth.AccountId, userAuth.UserId, peerID, jobID)
|
||||
if err != nil {
|
||||
util.WriteErrorResponse(fmt.Sprintf("failed to fetch job %v", err), http.StatusInternalServerError, w)
|
||||
util.WriteError(ctx, err, w)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -123,27 +123,27 @@ type MockAccountManager struct {
|
||||
GetOrCreateAccountByPrivateDomainFunc func(ctx context.Context, initiatorId, domain string) (*types.Account, bool, error)
|
||||
UpdateAccountPeersFunc func(ctx context.Context, accountID string)
|
||||
BufferUpdateAccountPeersFunc func(ctx context.Context, accountID string)
|
||||
CreateJobFunc func(ctx context.Context, accountID, peerID, userID string, job *types.Job) error
|
||||
GetAllJobsFunc func(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error)
|
||||
GetJobByIDFunc func(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error)
|
||||
CreatePeerJobFunc func(ctx context.Context, accountID, peerID, userID string, job *types.Job) error
|
||||
GetAllPeerJobsFunc func(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error)
|
||||
GetPeerJobByIDFunc func(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error)
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) CreateJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error {
|
||||
if am.CreateJobFunc != nil {
|
||||
return am.CreateJobFunc(ctx, accountID, peerID, userID, job)
|
||||
func (am *MockAccountManager) CreatePeerJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error {
|
||||
if am.CreatePeerJobFunc != nil {
|
||||
return am.CreatePeerJobFunc(ctx, accountID, peerID, userID, job)
|
||||
}
|
||||
return status.Errorf(codes.Unimplemented, "method CreateJob is not implemented")
|
||||
}
|
||||
|
||||
func (am *MockAccountManager) GetAllJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error) {
|
||||
if am.CreateJobFunc != nil {
|
||||
return am.GetAllJobsFunc(ctx, accountID, userID, peerID)
|
||||
func (am *MockAccountManager) GetAllPeerJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error) {
|
||||
if am.CreatePeerJobFunc != nil {
|
||||
return am.GetAllPeerJobsFunc(ctx, accountID, userID, peerID)
|
||||
}
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAllJobs is not implemented")
|
||||
}
|
||||
func (am *MockAccountManager) GetJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error) {
|
||||
if am.CreateJobFunc != nil {
|
||||
return am.GetJobByIDFunc(ctx, accountID, userID, peerID, jobID)
|
||||
func (am *MockAccountManager) GetPeerJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error) {
|
||||
if am.CreatePeerJobFunc != nil {
|
||||
return am.GetPeerJobByIDFunc(ctx, accountID, userID, peerID, jobID)
|
||||
}
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateJob is not implemented")
|
||||
}
|
||||
|
||||
@@ -333,10 +333,7 @@ func (am *DefaultAccountManager) UpdatePeer(ctx context.Context, accountID, user
|
||||
return peer, nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) CreateJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error {
|
||||
unlock := am.Store.AcquireWriteLockByUID(ctx, accountID)
|
||||
defer unlock()
|
||||
|
||||
func (am *DefaultAccountManager) CreatePeerJob(ctx context.Context, accountID, peerID, userID string, job *types.Job) error {
|
||||
// todo: Create permissions for job
|
||||
allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Delete)
|
||||
if err != nil {
|
||||
@@ -382,23 +379,20 @@ func (am *DefaultAccountManager) CreateJob(ctx context.Context, accountID, peerI
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := transaction.SaveJob(ctx, job); err != nil {
|
||||
if err := transaction.CreatePeerJob(ctx, job); err != nil {
|
||||
return fmt.Errorf("failed to save job for peer %s: %w", peer.ID, err)
|
||||
}
|
||||
|
||||
settings, err := transaction.GetAccountSettings(ctx, store.LockingStrengthNone, accountID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
jobMeta := map[string]any{
|
||||
"job_id": job.ID,
|
||||
"for_peer_id": job.PeerID,
|
||||
"job_type": job.Type,
|
||||
"job_status": job.Status,
|
||||
"job_parameters": job.Parameters,
|
||||
}
|
||||
dnsDomain := am.GetDNSDomain(settings)
|
||||
|
||||
eventsToStore = func() {
|
||||
am.StoreEvent(ctx, userID, peer.ID, accountID, activity.JobCreatedByUser, peer.EventMeta(dnsDomain))
|
||||
}
|
||||
|
||||
if err = transaction.IncrementNetworkSerial(ctx, accountID); err != nil {
|
||||
return fmt.Errorf("failed to increment network serial: %w", err)
|
||||
am.StoreEvent(ctx, userID, peer.ID, accountID, activity.JobCreatedByUser, jobMeta)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -411,7 +405,7 @@ func (am *DefaultAccountManager) CreateJob(ctx context.Context, accountID, peerI
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) GetAllJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error) {
|
||||
func (am *DefaultAccountManager) GetAllPeerJobs(ctx context.Context, accountID, userID, peerID string) ([]*types.Job, error) {
|
||||
// todo: Create permissions for job
|
||||
allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Delete)
|
||||
if err != nil {
|
||||
@@ -430,7 +424,7 @@ func (am *DefaultAccountManager) GetAllJobs(ctx context.Context, accountID, user
|
||||
return []*types.Job{}, nil
|
||||
}
|
||||
|
||||
accountJobs, err := am.Store.GetJobs(ctx, accountID, peerID)
|
||||
accountJobs, err := am.Store.GetPeerJobs(ctx, accountID, peerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -438,7 +432,7 @@ func (am *DefaultAccountManager) GetAllJobs(ctx context.Context, accountID, user
|
||||
return accountJobs, nil
|
||||
}
|
||||
|
||||
func (am *DefaultAccountManager) GetJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error) {
|
||||
func (am *DefaultAccountManager) GetPeerJobByID(ctx context.Context, accountID, userID, peerID, jobID string) (*types.Job, error) {
|
||||
// todo: Create permissions for job
|
||||
allowed, err := am.permissionsManager.ValidateUserPermissions(ctx, accountID, userID, modules.Peers, operations.Delete)
|
||||
if err != nil {
|
||||
@@ -457,7 +451,7 @@ func (am *DefaultAccountManager) GetJobByID(ctx context.Context, accountID, user
|
||||
return &types.Job{}, nil
|
||||
}
|
||||
|
||||
job, err := am.Store.GetJobByID(ctx, accountID, jobID)
|
||||
job, err := am.Store.GetPeerJobByID(ctx, accountID, jobID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -127,24 +127,20 @@ func GetKeyQueryCondition(s *SqlStore) string {
|
||||
}
|
||||
|
||||
// SaveJob persists a job in DB
|
||||
func (s *SqlStore) SaveJob(ctx context.Context, job *types.Job) error {
|
||||
start := time.Now()
|
||||
defer func() {
|
||||
if s.metrics != nil {
|
||||
s.metrics.StoreMetrics().CountPersistenceDuration(time.Since(start))
|
||||
}
|
||||
}()
|
||||
|
||||
return s.db.WithContext(ctx).
|
||||
Clauses(clause.OnConflict{UpdateAll: true}).
|
||||
Create(job).Error
|
||||
func (s *SqlStore) CreatePeerJob(ctx context.Context, job *types.Job) error {
|
||||
result := s.db.Create(job)
|
||||
if result.Error != nil {
|
||||
log.WithContext(ctx).Errorf("failed to create job in store: %s", result.Error)
|
||||
return status.Errorf(status.Internal, "failed to create job in store")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// job was pending for too long and has been cancelled
|
||||
// todo call it when we first start the jobChannel to make sure no stuck jobs
|
||||
func (s *SqlStore) MarkPendingJobsAsFailed(ctx context.Context, peerID string) error {
|
||||
now := time.Now().UTC()
|
||||
return s.db.WithContext(ctx).
|
||||
return s.db.
|
||||
Model(&types.Job{}).
|
||||
Where("peer_id = ? AND status = ?", types.JobStatusPending, peerID).
|
||||
Updates(map[string]any{
|
||||
@@ -155,9 +151,9 @@ func (s *SqlStore) MarkPendingJobsAsFailed(ctx context.Context, peerID string) e
|
||||
}
|
||||
|
||||
// GetJobByID fetches job by ID
|
||||
func (s *SqlStore) GetJobByID(ctx context.Context, accountID, jobID string) (*types.Job, error) {
|
||||
func (s *SqlStore) GetPeerJobByID(ctx context.Context, accountID, jobID string) (*types.Job, error) {
|
||||
var job types.Job
|
||||
err := s.db.WithContext(ctx).
|
||||
err := s.db.
|
||||
Where(accountAndIDQueryCondition, accountID, jobID).
|
||||
First(&job).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
@@ -167,12 +163,13 @@ func (s *SqlStore) GetJobByID(ctx context.Context, accountID, jobID string) (*ty
|
||||
}
|
||||
|
||||
// get all jobs
|
||||
func (s *SqlStore) GetJobs(ctx context.Context, accountID, peerID string) ([]*types.Job, error) {
|
||||
func (s *SqlStore) GetPeerJobs(ctx context.Context, accountID, peerID string) ([]*types.Job, error) {
|
||||
var jobs []*types.Job
|
||||
err := s.db.WithContext(ctx).
|
||||
err := s.db.
|
||||
Where(accountAndPeerIDQueryCondition, accountID, peerID).
|
||||
Order("created_at DESC").
|
||||
Find(&jobs).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -180,19 +177,26 @@ func (s *SqlStore) GetJobs(ctx context.Context, accountID, peerID string) ([]*ty
|
||||
return jobs, nil
|
||||
}
|
||||
|
||||
func (s *SqlStore) CompleteJob(ctx context.Context, accountID, jobID, result string, failedReason string) error {
|
||||
job, err := s.GetJobByID(ctx, accountID, jobID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// mark it as succeeded or failed
|
||||
if result != "" && failedReason == "" {
|
||||
job.MarkSucceeded(result)
|
||||
} else {
|
||||
job.MarkFailed(failedReason)
|
||||
func (s *SqlStore) CompletePeerJob(accountID, jobID, result, failedReason string) error {
|
||||
now := time.Now().UTC()
|
||||
|
||||
updates := map[string]any{
|
||||
"completed_at": now,
|
||||
}
|
||||
|
||||
return s.db.WithContext(ctx).Save(job).Error
|
||||
if result != "" && failedReason == "" {
|
||||
updates["status"] = types.JobStatusSucceeded
|
||||
updates["result"] = result
|
||||
updates["failed_reason"] = ""
|
||||
} else {
|
||||
updates["status"] = types.JobStatusFailed
|
||||
updates["failed_reason"] = failedReason
|
||||
}
|
||||
|
||||
return s.db.
|
||||
Model(&types.Job{}).
|
||||
Where(accountAndIDQueryCondition, accountID, jobID).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
// AcquireGlobalLock acquires global lock across all the accounts and returns a function that releases the lock
|
||||
|
||||
@@ -205,10 +205,10 @@ type Store interface {
|
||||
IsPrimaryAccount(ctx context.Context, accountID string) (bool, string, error)
|
||||
MarkAccountPrimary(ctx context.Context, accountID string) error
|
||||
UpdateAccountNetwork(ctx context.Context, accountID string, ipNet net.IPNet) error
|
||||
SaveJob(ctx context.Context, job *types.Job) error
|
||||
GetJobByID(ctx context.Context, accountID, jobID string) (*types.Job, error)
|
||||
GetJobs(ctx context.Context, accountID, peerID string) ([]*types.Job, error)
|
||||
CompleteJob(ctx context.Context, accountID, jobID, result string, failedReason string) error
|
||||
CreatePeerJob(ctx context.Context, job *types.Job) error
|
||||
CompletePeerJob(accountID, jobID, result, failedReason string) error
|
||||
GetPeerJobByID(ctx context.Context, accountID, jobID string) (*types.Job, error)
|
||||
GetPeerJobs(ctx context.Context, accountID, peerID string) ([]*types.Job, error)
|
||||
MarkPendingJobsAsFailed(ctx context.Context, peerID string) error
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ type Job struct {
|
||||
// TriggeredBy user that triggered this job
|
||||
TriggeredBy string `gorm:"index"`
|
||||
|
||||
PeerID string `gorm:"index"`
|
||||
PeerID string `gorm:"index"`
|
||||
|
||||
AccountID string `gorm:"index"`
|
||||
|
||||
@@ -110,52 +110,19 @@ func (j *Job) encodeParameters(params map[string]any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
// MarkSucceeded sets job as completed successfully
|
||||
func (j *Job) MarkSucceeded(result string) {
|
||||
now := time.Now().UTC()
|
||||
j.Status = JobStatusSucceeded
|
||||
j.Result = result
|
||||
j.CompletedAt = &now
|
||||
}
|
||||
|
||||
// MarkFailed sets job as failed with reason
|
||||
func (j *Job) MarkFailed(reason string) {
|
||||
now := time.Now().UTC()
|
||||
j.Status = JobStatusFailed
|
||||
j.FailedReason = reason
|
||||
j.CompletedAt = &now
|
||||
}
|
||||
|
||||
|
||||
func (j *Job) validateJobRequest() error {
|
||||
if j == nil {
|
||||
return fmt.Errorf("job cannot be nil")
|
||||
}
|
||||
|
||||
if j.Type == "" {
|
||||
return fmt.Errorf("job type must be specified")
|
||||
}
|
||||
|
||||
if len(j.Parameters) == 0 {
|
||||
return fmt.Errorf("job parameters must be provided")
|
||||
}
|
||||
|
||||
switch j.Type {
|
||||
case JobTypeBundle:
|
||||
var params JobParametersBundle
|
||||
if err := json.Unmarshal(j.Parameters, ¶ms); 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)
|
||||
}
|
||||
|
||||
// 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 err := j.validateDebugBundleJobParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -164,3 +131,20 @@ func (j *Job) validateJobRequest() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (j *Job) validateDebugBundleJobParams() error {
|
||||
var params JobParametersBundle
|
||||
if err := j.DecodeParameters(¶ms); 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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,6 +34,86 @@ tags:
|
||||
x-cloud-only: true
|
||||
components:
|
||||
schemas:
|
||||
JobRequest:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: The type of job to execute
|
||||
example: bundle
|
||||
enum: [ "bundle" ]
|
||||
parameters:
|
||||
type: object
|
||||
description: Key-value parameters required for the job
|
||||
additionalProperties: true
|
||||
example:
|
||||
bundle_for: true
|
||||
bundle_for_time: 5
|
||||
log_file_count: 2
|
||||
anonymize: false
|
||||
required:
|
||||
- type
|
||||
- parameters
|
||||
Job:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
description: Primary identifier
|
||||
example: "123456"
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When the job was created (UTC)
|
||||
completedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: When the job finished, null if still running
|
||||
triggeredBy:
|
||||
type: string
|
||||
description: User that triggered this job
|
||||
example: "user_42"
|
||||
peerId:
|
||||
type: string
|
||||
description: Associated peer ID
|
||||
example: "peer_99"
|
||||
accountId:
|
||||
type: string
|
||||
description: Associated account ID
|
||||
example: "acc_77"
|
||||
type:
|
||||
type: string
|
||||
enum: [ bundle ]
|
||||
example: bundle
|
||||
status:
|
||||
type: string
|
||||
enum: [ pending, succeeded, failed ]
|
||||
example: pending
|
||||
failedReason:
|
||||
type: string
|
||||
description: Why the job failed (if failed)
|
||||
example: "Connection timeout"
|
||||
result:
|
||||
type: string
|
||||
description: Job output (JSON, URL, etc.)
|
||||
example: "https://example.com/bundle.zip"
|
||||
parameters:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
description: Job configuration parameters
|
||||
example:
|
||||
bundle_for: true
|
||||
bundle_for_time: 60
|
||||
log_file_count: 10
|
||||
anonymize: false
|
||||
required:
|
||||
- id
|
||||
- createdAt
|
||||
- triggeredBy
|
||||
- peerId
|
||||
- accountId
|
||||
- type
|
||||
- status
|
||||
Account:
|
||||
type: object
|
||||
properties:
|
||||
@@ -2170,6 +2250,108 @@ security:
|
||||
- BearerAuth: [ ]
|
||||
- TokenAuth: [ ]
|
||||
paths:
|
||||
/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
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a peer
|
||||
responses:
|
||||
'200':
|
||||
description: List of jobs
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Job'
|
||||
'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
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
description: The unique identifier of a peer
|
||||
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/Job'
|
||||
'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
|
||||
schema:
|
||||
type: string
|
||||
- in: path
|
||||
name: jobId
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: A Job object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Job'
|
||||
'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
|
||||
|
||||
@@ -104,6 +104,23 @@ const (
|
||||
IngressPortAllocationRequestPortRangeProtocolUdp IngressPortAllocationRequestPortRangeProtocol = "udp"
|
||||
)
|
||||
|
||||
// Defines values for JobStatus.
|
||||
const (
|
||||
JobStatusFailed JobStatus = "failed"
|
||||
JobStatusPending JobStatus = "pending"
|
||||
JobStatusSucceeded JobStatus = "succeeded"
|
||||
)
|
||||
|
||||
// Defines values for JobType.
|
||||
const (
|
||||
JobTypeBundle JobType = "bundle"
|
||||
)
|
||||
|
||||
// Defines values for JobRequestType.
|
||||
const (
|
||||
JobRequestTypeBundle JobRequestType = "bundle"
|
||||
)
|
||||
|
||||
// Defines values for NameserverNsType.
|
||||
const (
|
||||
NameserverNsTypeUdp NameserverNsType = "udp"
|
||||
@@ -199,11 +216,6 @@ const (
|
||||
GetApiEventsNetworkTrafficParamsDirectionINGRESS GetApiEventsNetworkTrafficParamsDirection = "INGRESS"
|
||||
)
|
||||
|
||||
type JobRequest struct {
|
||||
Type string `json:"type" binding:"required"` // Job type, e.g., "bundle"
|
||||
Parameters map[string]any `json:"parameters" binding:"required"` // Dynamic parameters
|
||||
}
|
||||
|
||||
// AccessiblePeer defines model for AccessiblePeer.
|
||||
type AccessiblePeer struct {
|
||||
// CityName Commonly used English name of the city
|
||||
@@ -648,6 +660,56 @@ type IngressPortAllocationRequestPortRange struct {
|
||||
// IngressPortAllocationRequestPortRangeProtocol The protocol accepted by the port range
|
||||
type IngressPortAllocationRequestPortRangeProtocol string
|
||||
|
||||
// Job defines model for Job.
|
||||
type Job struct {
|
||||
// AccountId Associated account ID
|
||||
AccountId string `json:"accountId"`
|
||||
|
||||
// CompletedAt When the job finished, null if still running
|
||||
CompletedAt *time.Time `json:"completedAt,omitempty"`
|
||||
|
||||
// CreatedAt When the job was created (UTC)
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
|
||||
// FailedReason Why the job failed (if failed)
|
||||
FailedReason *string `json:"failedReason,omitempty"`
|
||||
|
||||
// Id Primary identifier
|
||||
Id string `json:"id"`
|
||||
|
||||
// Parameters Job configuration parameters
|
||||
Parameters *map[string]interface{} `json:"parameters,omitempty"`
|
||||
|
||||
// PeerId Associated peer ID
|
||||
PeerId string `json:"peerId"`
|
||||
|
||||
// Result Job output (JSON, URL, etc.)
|
||||
Result *string `json:"result,omitempty"`
|
||||
Status JobStatus `json:"status"`
|
||||
|
||||
// TriggeredBy User that triggered this job
|
||||
TriggeredBy string `json:"triggeredBy"`
|
||||
Type JobType `json:"type"`
|
||||
}
|
||||
|
||||
// JobStatus defines model for Job.Status.
|
||||
type JobStatus string
|
||||
|
||||
// JobType defines model for Job.Type.
|
||||
type JobType string
|
||||
|
||||
// JobRequest defines model for JobRequest.
|
||||
type JobRequest struct {
|
||||
// Parameters Key-value parameters required for the job
|
||||
Parameters map[string]interface{} `json:"parameters"`
|
||||
|
||||
// Type The type of job to execute
|
||||
Type JobRequestType `json:"type"`
|
||||
}
|
||||
|
||||
// JobRequestType The type of job to execute
|
||||
type JobRequestType string
|
||||
|
||||
// Location Describe geographical location information
|
||||
type Location struct {
|
||||
// CityName Commonly used English name of the city
|
||||
@@ -1020,8 +1082,6 @@ type OSVersionCheck struct {
|
||||
|
||||
// Peer defines model for Peer.
|
||||
type Peer struct {
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// ApprovalRequired (Cloud only) Indicates whether peer needs approval
|
||||
ApprovalRequired bool `json:"approval_required"`
|
||||
|
||||
@@ -1037,6 +1097,9 @@ type Peer struct {
|
||||
// CountryCode 2-letter ISO 3166-1 alpha-2 code that represents the country
|
||||
CountryCode CountryCode `json:"country_code"`
|
||||
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||
DnsLabel string `json:"dns_label"`
|
||||
|
||||
@@ -1103,8 +1166,6 @@ type Peer struct {
|
||||
|
||||
// PeerBatch defines model for PeerBatch.
|
||||
type PeerBatch struct {
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// AccessiblePeersCount Number of accessible peers
|
||||
AccessiblePeersCount int `json:"accessible_peers_count"`
|
||||
|
||||
@@ -1123,6 +1184,9 @@ type PeerBatch struct {
|
||||
// CountryCode 2-letter ISO 3166-1 alpha-2 code that represents the country
|
||||
CountryCode CountryCode `json:"country_code"`
|
||||
|
||||
// CreatedAt Peer creation date (UTC)
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// DnsLabel Peer's DNS label is the parsed peer name for domain resolution. It is used to form an FQDN by appending the account's domain to the peer label. e.g. peer-dns-label.netbird.cloud
|
||||
DnsLabel string `json:"dns_label"`
|
||||
|
||||
@@ -1940,6 +2004,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
|
||||
|
||||
// PostApiPoliciesJSONRequestBody defines body for PostApiPolicies for application/json ContentType.
|
||||
type PostApiPoliciesJSONRequestBody = PolicyUpdate
|
||||
|
||||
|
||||
Reference in New Issue
Block a user