From ee1859ecf7677a81436d90a92d2b7e73b62872c4 Mon Sep 17 00:00:00 2001 From: chris lee Date: Thu, 9 Jul 2026 10:10:16 -0400 Subject: [PATCH] Add refresh-on-profile-update as a refresh --- README.md | 1 + cmd/browser_pools.go | 57 ++++++++++++++++++++++++--------------- cmd/browser_pools_test.go | 42 +++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +-- 5 files changed, 82 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index bb4178e4..885d97a3 100644 --- a/README.md +++ b/README.md @@ -263,6 +263,7 @@ Commands with JSON output support: - `--fill-rate ` - Percentage of the pool to fill per minute - `--timeout ` - Idle timeout for browsers acquired from the pool - `--stealth`, `--headless`, `--kiosk` - Default pool configuration + - `--refresh-on-profile-update` - Flush idle browsers when the pool's profile is updated (requires a profile) - `--profile-id`, `--profile-name`, `--proxy-id`, `--start-url`, `--extension`, `--viewport` - Same semantics as `kernel browsers create` - `--chrome-policy ` / `--chrome-policy-file ` - Custom Chrome enterprise policy applied to every browser in the pool, as a JSON object or from a file (`-` for stdin). Same semantics as `kernel browsers create`. - `--output json`, `-o json` - Output raw JSON object diff --git a/cmd/browser_pools.go b/cmd/browser_pools.go index 63f98828..81240e2d 100644 --- a/cmd/browser_pools.go +++ b/cmd/browser_pools.go @@ -91,14 +91,15 @@ func (c BrowserPoolsCmd) List(ctx context.Context, in BrowserPoolsListInput) err } type BrowserPoolsCreateInput struct { - Name string - Size int64 - FillRate int64 - TimeoutSeconds int64 - Stealth BoolFlag - Headless BoolFlag - Kiosk BoolFlag - ProfileID string + Name string + Size int64 + FillRate int64 + TimeoutSeconds int64 + Stealth BoolFlag + Headless BoolFlag + Kiosk BoolFlag + RefreshOnProfileUpdate BoolFlag + ProfileID string ProfileName string ProxyID string StartURL string @@ -139,6 +140,9 @@ func (c BrowserPoolsCmd) Create(ctx context.Context, in BrowserPoolsCreateInput) if in.Kiosk.Set { params.KioskMode = kernel.Bool(in.Kiosk.Value) } + if in.RefreshOnProfileUpdate.Set { + params.RefreshOnProfileUpdate = kernel.Bool(in.RefreshOnProfileUpdate.Value) + } profileID, profileName, profileSet, err := resolvePoolProfile(in.ProfileID, in.ProfileName) if err != nil { @@ -230,6 +234,7 @@ func (c BrowserPoolsCmd) Get(ctx context.Context, in BrowserPoolsGetInput) error {"Headless", fmt.Sprintf("%t", cfg.Headless)}, {"Stealth", fmt.Sprintf("%t", cfg.Stealth)}, {"Kiosk Mode", fmt.Sprintf("%t", cfg.KioskMode)}, + {"Refresh On Profile Update", fmt.Sprintf("%t", cfg.RefreshOnProfileUpdate)}, {"Profile", formatProfile(cfg.Profile)}, {"Proxy ID", util.OrDash(cfg.ProxyID)}, {"Start URL", util.OrDash(cfg.StartURL)}, @@ -242,15 +247,16 @@ func (c BrowserPoolsCmd) Get(ctx context.Context, in BrowserPoolsGetInput) error } type BrowserPoolsUpdateInput struct { - IDOrName string - Name string - Size int64 - FillRate int64 - TimeoutSeconds int64 - Stealth BoolFlag - Headless BoolFlag - Kiosk BoolFlag - ProfileID string + IDOrName string + Name string + Size int64 + FillRate int64 + TimeoutSeconds int64 + Stealth BoolFlag + Headless BoolFlag + Kiosk BoolFlag + RefreshOnProfileUpdate BoolFlag + ProfileID string ProfileName string ProxyID string StartURL string @@ -300,6 +306,9 @@ func (c BrowserPoolsCmd) Update(ctx context.Context, in BrowserPoolsUpdateInput) if in.DiscardAllIdle.Set { params.DiscardAllIdle = kernel.Bool(in.DiscardAllIdle.Value) } + if in.RefreshOnProfileUpdate.Set { + params.RefreshOnProfileUpdate = kernel.Bool(in.RefreshOnProfileUpdate.Value) + } profileID, profileName, profileSet, err := resolvePoolProfile(in.ProfileID, in.ProfileName) if err != nil { @@ -565,6 +574,7 @@ func init() { browserPoolsCreateCmd.Flags().Bool("stealth", false, "Enable stealth mode") browserPoolsCreateCmd.Flags().Bool("headless", false, "Enable headless mode") browserPoolsCreateCmd.Flags().Bool("kiosk", false, "Enable kiosk mode") + browserPoolsCreateCmd.Flags().Bool("refresh-on-profile-update", false, "Flush idle browsers when the pool's profile is updated") browserPoolsCreateCmd.Flags().String("profile-id", "", "Profile ID") browserPoolsCreateCmd.Flags().String("profile-name", "", "Profile name") browserPoolsCreateCmd.Flags().String("proxy-id", "", "Proxy ID") @@ -584,6 +594,7 @@ func init() { browserPoolsUpdateCmd.Flags().Bool("stealth", false, "Enable stealth mode") browserPoolsUpdateCmd.Flags().Bool("headless", false, "Enable headless mode") browserPoolsUpdateCmd.Flags().Bool("kiosk", false, "Enable kiosk mode") + browserPoolsUpdateCmd.Flags().Bool("refresh-on-profile-update", false, "Flush idle browsers when the pool's profile is updated") browserPoolsUpdateCmd.Flags().String("profile-id", "", "Profile ID") browserPoolsUpdateCmd.Flags().String("profile-name", "", "Profile name") browserPoolsUpdateCmd.Flags().String("proxy-id", "", "Proxy ID") @@ -643,6 +654,7 @@ func runBrowserPoolsCreate(cmd *cobra.Command, args []string) error { stealth, _ := cmd.Flags().GetBool("stealth") headless, _ := cmd.Flags().GetBool("headless") kiosk, _ := cmd.Flags().GetBool("kiosk") + refreshOnProfileUpdate, _ := cmd.Flags().GetBool("refresh-on-profile-update") profileID, _ := cmd.Flags().GetString("profile-id") profileName, _ := cmd.Flags().GetString("profile-name") proxyID, _ := cmd.Flags().GetString("proxy-id") @@ -660,8 +672,9 @@ func runBrowserPoolsCreate(cmd *cobra.Command, args []string) error { TimeoutSeconds: timeout, Stealth: BoolFlag{Set: cmd.Flags().Changed("stealth"), Value: stealth}, Headless: BoolFlag{Set: cmd.Flags().Changed("headless"), Value: headless}, - Kiosk: BoolFlag{Set: cmd.Flags().Changed("kiosk"), Value: kiosk}, - ProfileID: profileID, + Kiosk: BoolFlag{Set: cmd.Flags().Changed("kiosk"), Value: kiosk}, + RefreshOnProfileUpdate: BoolFlag{Set: cmd.Flags().Changed("refresh-on-profile-update"), Value: refreshOnProfileUpdate}, + ProfileID: profileID, ProfileName: profileName, ProxyID: proxyID, StartURL: startURL, @@ -693,6 +706,7 @@ func runBrowserPoolsUpdate(cmd *cobra.Command, args []string) error { stealth, _ := cmd.Flags().GetBool("stealth") headless, _ := cmd.Flags().GetBool("headless") kiosk, _ := cmd.Flags().GetBool("kiosk") + refreshOnProfileUpdate, _ := cmd.Flags().GetBool("refresh-on-profile-update") profileID, _ := cmd.Flags().GetString("profile-id") profileName, _ := cmd.Flags().GetString("profile-name") proxyID, _ := cmd.Flags().GetString("proxy-id") @@ -713,8 +727,9 @@ func runBrowserPoolsUpdate(cmd *cobra.Command, args []string) error { TimeoutSeconds: timeout, Stealth: BoolFlag{Set: cmd.Flags().Changed("stealth"), Value: stealth}, Headless: BoolFlag{Set: cmd.Flags().Changed("headless"), Value: headless}, - Kiosk: BoolFlag{Set: cmd.Flags().Changed("kiosk"), Value: kiosk}, - ProfileID: profileID, + Kiosk: BoolFlag{Set: cmd.Flags().Changed("kiosk"), Value: kiosk}, + RefreshOnProfileUpdate: BoolFlag{Set: cmd.Flags().Changed("refresh-on-profile-update"), Value: refreshOnProfileUpdate}, + ProfileID: profileID, ProfileName: profileName, ProxyID: proxyID, StartURL: startURL, diff --git a/cmd/browser_pools_test.go b/cmd/browser_pools_test.go index 60ed449a..25ec0ee6 100644 --- a/cmd/browser_pools_test.go +++ b/cmd/browser_pools_test.go @@ -137,6 +137,48 @@ func TestBuildAcquireParams(t *testing.T) { assert.False(t, empty.AcquireTimeoutSeconds.Valid()) } +func TestBrowserPoolsCreate_WithRefreshOnProfileUpdate(t *testing.T) { + setupStdoutCapture(t) + + var captured kernel.BrowserPoolNewParams + fake := &FakeBrowserPoolsService{ + NewFunc: func(ctx context.Context, body kernel.BrowserPoolNewParams, opts ...option.RequestOption) (*kernel.BrowserPool, error) { + captured = body + return &kernel.BrowserPool{ID: "pool-ropu"}, nil + }, + } + + c := BrowserPoolsCmd{client: fake} + err := c.Create(context.Background(), BrowserPoolsCreateInput{ + Size: 1, + RefreshOnProfileUpdate: BoolFlag{Set: true, Value: true}, + }) + assert.NoError(t, err) + assert.True(t, captured.RefreshOnProfileUpdate.Valid()) + assert.True(t, captured.RefreshOnProfileUpdate.Value) +} + +func TestBrowserPoolsUpdate_WithRefreshOnProfileUpdate(t *testing.T) { + setupStdoutCapture(t) + + var captured kernel.BrowserPoolUpdateParams + fake := &FakeBrowserPoolsService{ + UpdateFunc: func(ctx context.Context, id string, body kernel.BrowserPoolUpdateParams, opts ...option.RequestOption) (*kernel.BrowserPool, error) { + captured = body + return &kernel.BrowserPool{ID: id}, nil + }, + } + + c := BrowserPoolsCmd{client: fake} + err := c.Update(context.Background(), BrowserPoolsUpdateInput{ + IDOrName: "pool-1", + RefreshOnProfileUpdate: BoolFlag{Set: true, Value: false}, + }) + assert.NoError(t, err) + assert.True(t, captured.RefreshOnProfileUpdate.Valid()) + assert.False(t, captured.RefreshOnProfileUpdate.Value) +} + func TestBrowserPoolsCreate_WithChromePolicy(t *testing.T) { setupStdoutCapture(t) diff --git a/go.mod b/go.mod index 4c5dcfb7..b3939d33 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 github.com/golang-jwt/jwt/v5 v5.2.2 github.com/joho/godotenv v1.5.1 - github.com/kernel/kernel-go-sdk v0.72.0 + github.com/kernel/kernel-go-sdk v0.75.0 github.com/klauspost/compress v1.18.5 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pterm/pterm v0.12.80 diff --git a/go.sum b/go.sum index 14e37c5c..a182f786 100644 --- a/go.sum +++ b/go.sum @@ -64,8 +64,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/kernel/kernel-go-sdk v0.72.0 h1:QyT5v2PMJjp9GQCGV4fi1IWcCF/fcsFcz1MTXPA/WZU= -github.com/kernel/kernel-go-sdk v0.72.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= +github.com/kernel/kernel-go-sdk v0.75.0 h1:UTlBLOVGQIFa0Vcn9DrTbhR44IQRrcZuhaKcMTwHvms= +github.com/kernel/kernel-go-sdk v0.75.0/go.mod h1:EeZzSuHZVeHKxKCPUzxou2bovNGhXaz0RXrSqKNf1AQ= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=