Files
netbird/client/jobexec/executor.go
mlsmaycon b08120b369 [management,client] Plumb anonymize level and upload URL through remote debug bundle jobs
PR #7102 added an anonymization level to debug bundles and the
anonymize_level proto field, but nothing on the management side ever set
it: the remote-job builder dropped the field and the REST schema never
exposed it, so a remotely triggered bundle always ran at the default
level regardless of what an operator asked for. The upload destination
for remote jobs was likewise fixed to the default upload server, with no
way to direct a bundle to a self-hosted one.

Expose anonymize_level and a new upload_url on the REST BundleParameters
and the management proto, and map both onto the job request streamed to
the client. Both are optional: an omitted value crosses the wire as the
empty string, which the client resolves to its own defaults — the
default anonymization level and the default upload server — matching how
the netbird CLI defaults the same inputs.
2026-08-13 02:12:47 +09:00

81 lines
1.9 KiB
Go

package jobexec
import (
"context"
"errors"
"fmt"
"os"
"time"
log "github.com/sirupsen/logrus"
"github.com/netbirdio/netbird/client/internal/debug"
"github.com/netbirdio/netbird/upload-server/types"
)
const (
MaxBundleWaitTime = 60 * time.Minute // maximum wait time for bundle generation (1 hour)
)
var (
ErrJobNotImplemented = errors.New("job not implemented")
)
type Executor struct {
}
func NewExecutor() *Executor {
return &Executor{}
}
func (e *Executor) BundleJob(ctx context.Context, debugBundleDependencies debug.GeneratorDependencies, params debug.BundleConfig, waitForDuration time.Duration, mgmURL, uploadURL string) (string, error) {
if uploadURL == "" {
uploadURL = types.DefaultBundleURL
}
if waitForDuration > MaxBundleWaitTime {
log.Warnf("bundle wait time %v exceeds maximum %v, capping to maximum", waitForDuration, MaxBundleWaitTime)
waitForDuration = MaxBundleWaitTime
}
if waitForDuration > 0 {
if err := waitFor(ctx, waitForDuration); err != nil {
return "", err
}
}
log.Infof("execute debug bundle generation")
bundleGenerator := debug.NewBundleGenerator(debugBundleDependencies, params)
path, err := bundleGenerator.Generate()
if err != nil {
return "", fmt.Errorf("generate debug bundle: %w", err)
}
defer func() {
if err := os.Remove(path); err != nil {
log.Errorf("failed to remove debug bundle file: %v", err)
}
}()
key, err := debug.UploadDebugBundle(ctx, uploadURL, mgmURL, path, false)
if err != nil {
log.Errorf("failed to upload debug bundle: %v", err)
return "", fmt.Errorf("upload debug bundle: %w", err)
}
log.Infof("debug bundle has been generated successfully")
return key, nil
}
func waitFor(ctx context.Context, duration time.Duration) error {
log.Infof("wait for %v minutes before executing debug bundle", duration.Minutes())
select {
case <-time.After(duration):
return nil
case <-ctx.Done():
log.Infof("wait cancelled: %v", ctx.Err())
return ctx.Err()
}
}