Skip to content

Commit 65a47a5

Browse files
authored
Followup fixes for Pushpin integration (#1520)
This PR is a followup to #1509 that includes the following fixes: * Fix to Pushpin context that inadvertently left out the path to the routes file and the cleanup function when building the context * Adds an output message indicating when "Experimental Pushpin mode" is enable * Makes Pushpin-related logs slightly less noisy
1 parent 914f007 commit 65a47a5

File tree

2 files changed

+81
-95
lines changed

2 files changed

+81
-95
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
### Enhancements:
88
- feat(vcl): Allow showing of generated VCL for a service version [#1498](https://github.com/fastly/cli/pull/1498)
9-
- feat(compute/serve): Add experimental "enable Pushpin" mode ([#1509](https://github.com/fastly/cli/pull/1509))
9+
- feat(compute/serve): Add experimental "enable Pushpin" mode ([#1509](https://github.com/fastly/cli/pull/1509), [#1520](https://github.com/fastly/cli/pull/1520))
1010
- feat(object-storage): improve access-keys list output ([#1513](https://github.com/fastly/cli/pull/1513))
1111
- refactor(domainv1,tools): use updated go-fastly domainmanagement imports and types ([#1517](https://github.com/fastly/cli/pull/1517))
1212
- feat (imageoptimizerdefaults): Support for retrieving and updating Image Optimizer defaults for a given VCL service ([#1518](https://github.com/fastly/cli/pull/1518))

pkg/commands/compute/serve.go

Lines changed: 80 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func NewServeCommand(parent argparser.Registerer, g *global.Data, build *BuildCo
106106
c.CmdClause.Flag("metadata-filter-envvars", "Redact specified environment variables from [scripts.env_vars] using comma-separated list").Action(c.metadataFilterEnvVars.Set).StringVar(&c.metadataFilterEnvVars.Value)
107107
c.CmdClause.Flag("metadata-show", "Inspect the Wasm binary metadata").Action(c.metadataShow.Set).BoolVar(&c.metadataShow.Value)
108108
c.CmdClause.Flag("package-name", "Package name").Action(c.packageName.Set).StringVar(&c.packageName.Value)
109-
c.CmdClause.Flag("experimental-enable-pushpin", "Enable experimental Pushpin support for local testing of Fanout and WebSockets").BoolVar(&c.enablePushpin)
109+
c.CmdClause.Flag("experimental-enable-pushpin", "Enable experimental Pushpin support for local testing of Fanout").BoolVar(&c.enablePushpin)
110110
c.CmdClause.Flag("pushpin-path", "The path to a user installed version of the Pushpin runner binary").StringVar(&c.pushpinRunnerBinPath)
111111
c.CmdClause.Flag("pushpin-proxy-port", "The port to run the Pushpin runner on. Overrides 'local_server.pushpin.proxy_port' from 'fastly.toml', and if not specified there, defaults to 7677.").StringVar(&c.pushpinProxyPort)
112112
c.CmdClause.Flag("pushpin-publish-port", "The port to run the Pushpin publish handler on. Overrides 'local_server.pushpin.publish_port' from 'fastly.toml', and if not specified there, defaults to 5561.").StringVar(&c.pushpinPublishPort)
@@ -600,22 +600,22 @@ func (c *ServeCommand) GetPushpinProxyPort(out io.Writer) (uint16, error) {
600600
}
601601
pushpinProxyPort = uint16(pushpinProxyPortInt)
602602
if c.Globals.Verbose() {
603-
text.Info(out, "Using Pushpin proxy port from --pushpin-proxy-port flag: %d\n\n", pushpinProxyPort)
603+
text.Info(out, "Using Pushpin proxy port from --pushpin-proxy-port flag: %d", pushpinProxyPort)
604604
}
605605
return pushpinProxyPort, nil
606606
}
607607

608608
pushpinProxyPort = c.Globals.Manifest.File.LocalServer.Pushpin.PushpinProxyPort
609609
if pushpinProxyPort != 0 {
610610
if c.Globals.Verbose() {
611-
text.Info(out, "Using Pushpin proxy port via `local_server.pushpin.proxy_port` setting: %d\n\n", pushpinProxyPort)
611+
text.Info(out, "Using Pushpin proxy port via `local_server.pushpin.proxy_port` setting: %d", pushpinProxyPort)
612612
}
613613
return pushpinProxyPort, nil
614614
}
615615

616616
pushpinProxyPort = 7677
617617
if c.Globals.Verbose() {
618-
text.Info(out, "Using default Pushpin proxy port %d\n\n", pushpinProxyPort)
618+
text.Info(out, "Using default Pushpin proxy port %d", pushpinProxyPort)
619619
}
620620
return pushpinProxyPort, nil
621621
}
@@ -640,22 +640,22 @@ func (c *ServeCommand) GetPushpinPublishPort(out io.Writer) (uint16, error) {
640640
}
641641
pushpinPublishPort = uint16(pushpinPublishPortInt)
642642
if c.Globals.Verbose() {
643-
text.Info(out, "Using Pushpin publish handler port from --pushpin-publish-port flag: %d\n\n", pushpinPublishPort)
643+
text.Info(out, "Using Pushpin publish handler port from --pushpin-publish-port flag: %d", pushpinPublishPort)
644644
}
645645
return pushpinPublishPort, nil
646646
}
647647

648648
pushpinPublishPort = c.Globals.Manifest.File.LocalServer.Pushpin.PushpinPublishPort
649649
if pushpinPublishPort != 0 {
650650
if c.Globals.Verbose() {
651-
text.Info(out, "Using Pushpin publish handler port via `local_server.pushpin.publish_port` setting: %d\n\n", pushpinPublishPort)
651+
text.Info(out, "Using Pushpin publish handler port via `local_server.pushpin.publish_port` setting: %d", pushpinPublishPort)
652652
}
653653
return pushpinPublishPort, nil
654654
}
655655

656656
pushpinPublishPort = 5561
657657
if c.Globals.Verbose() {
658-
text.Info(out, "Using default Pushpin publish handler port %d\n\n", pushpinPublishPort)
658+
text.Info(out, "Using default Pushpin publish handler port %d", pushpinPublishPort)
659659
}
660660
return pushpinPublishPort, nil
661661
}
@@ -669,15 +669,15 @@ func (c *ServeCommand) GetPushpinRunner(out io.Writer) (bin string, err error) {
669669
pushpinRunnerBinPath := c.pushpinRunnerBinPath
670670
if pushpinRunnerBinPath != "" {
671671
if c.Globals.Verbose() {
672-
text.Info(out, "Using user provided install of Pushpin runner via --pushpin-path flag: %s\n\n", pushpinRunnerBinPath)
672+
text.Info(out, "Using user provided install of Pushpin runner via --pushpin-path flag: %s", pushpinRunnerBinPath)
673673
}
674674
return filepath.Abs(pushpinRunnerBinPath)
675675
}
676676

677677
pushpinRunnerBinPath = c.Globals.Manifest.File.LocalServer.Pushpin.PushpinPath
678678
if pushpinRunnerBinPath != "" {
679679
if c.Globals.Verbose() {
680-
text.Info(out, "Using user provided install of Pushpin runner via `local_server.pushpin.pushpin_path` setting: %s\n\n", pushpinRunnerBinPath)
680+
text.Info(out, "Using user provided install of Pushpin runner via `local_server.pushpin.pushpin_path` setting: %s", pushpinRunnerBinPath)
681681
}
682682
return filepath.Abs(pushpinRunnerBinPath)
683683
}
@@ -694,7 +694,7 @@ func (c *ServeCommand) GetPushpinRunner(out io.Writer) (bin string, err error) {
694694
}
695695

696696
if c.Globals.Verbose() {
697-
text.Info(out, "Found Pushpin runner via $PATH lookup: %s\n\n", pushpinRunnerBinPath)
697+
text.Info(out, "Found Pushpin runner via $PATH lookup: %s", pushpinRunnerBinPath)
698698
}
699699
return filepath.Abs(pushpinRunnerBinPath)
700700
}
@@ -767,6 +767,8 @@ func formatPushpinLog(line string) (string, string) {
767767
// pushpinContext contains information about the instance of Pushpin that is
768768
// executed when enabled.
769769
type pushpinContext struct {
770+
instanceID uint32
771+
confFilePath string
770772
pushpinRunnerBin string
771773
pushpinRunDir string
772774
pushpinLogDir string
@@ -810,43 +812,76 @@ func (c *pushpinContext) buildPushpinConf() string {
810812
// command line and/or fastly.toml. The cleanup function on the returned pushpinContext
811813
// needs to eventually be called by the caller to shut down Pushpin.
812814
func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpinContext, error) {
815+
text.Info(out, "Enabling experimental Pushpin support for local testing of Fanout.")
816+
813817
pushpinCtx := pushpinContext{}
814818

815-
var cleanup func()
819+
// Generate a non-zero instance ID to represent this Pushpin instance and build temporary
820+
// files
821+
for {
822+
p := make([]byte, 4)
823+
_, _ = rand.Read(p)
824+
pushpinCtx.instanceID = binary.BigEndian.Uint32(p)
825+
if pushpinCtx.instanceID != 0 {
826+
break
827+
}
828+
}
816829

817-
err := spinner.Start()
830+
var err error
831+
pushpinCtx.proxyPort, err = c.GetPushpinProxyPort(out)
818832
if err != nil {
819833
return pushpinCtx, err
820834
}
821-
msg := "Running local Pushpin"
822-
spinner.Message(msg + "...")
823-
824-
spinner.StopMessage(msg)
825-
err = spinner.Stop()
835+
pushpinCtx.publishPort, err = c.GetPushpinPublishPort(out)
836+
if err != nil {
837+
return pushpinCtx, err
838+
}
839+
pushpinCtx.pushpinRunnerBin, err = c.GetPushpinRunner(out)
826840
if err != nil {
827841
return pushpinCtx, err
828842
}
829843

830844
pwd, _ := os.Getwd()
831845
pushpinCtx.pushpinLogDir = filepath.Join(pwd, "pushpin-logs")
832846

833-
pushpinCtx.proxyPort, err = c.GetPushpinProxyPort(out)
847+
pushpinCtx.pushpinRunDir = filepath.Join(
848+
os.TempDir(),
849+
fmt.Sprintf("pushpin-%08x", pushpinCtx.instanceID),
850+
)
851+
pushpinCtx.confFilePath = filepath.Join(
852+
os.TempDir(),
853+
fmt.Sprintf("pushpin-%08x.conf", pushpinCtx.instanceID),
854+
)
855+
pushpinCtx.routesFilePath = filepath.Join(
856+
os.TempDir(),
857+
fmt.Sprintf("pushpin-routes-%08x", pushpinCtx.instanceID),
858+
)
859+
860+
text.Break(out)
861+
862+
err = spinner.Start()
834863
if err != nil {
835864
return pushpinCtx, err
836865
}
837-
pushpinCtx.publishPort, err = c.GetPushpinPublishPort(out)
866+
msg := "Starting Pushpin"
867+
spinner.Message(msg + "...")
868+
869+
spinner.StopMessage(msg)
870+
err = spinner.Stop()
838871
if err != nil {
839872
return pushpinCtx, err
840873
}
841-
pushpinCtx.pushpinRunnerBin, err = c.GetPushpinRunner(out)
874+
875+
pushpinConfContents := pushpinCtx.buildPushpinConf()
876+
err = os.WriteFile(pushpinCtx.confFilePath, []byte(pushpinConfContents), 0o600)
842877
if err != nil {
843-
return pushpinCtx, err
878+
return pushpinCtx, fmt.Errorf("error writing config file %s: %w", pushpinCtx.confFilePath, err)
844879
}
845-
if c.Globals.Verbose() {
846-
text.Info(out, "Local pushpin proxy port: %d", pushpinCtx.proxyPort)
847-
text.Info(out, "Local pushpin publisher port: %d", pushpinCtx.publishPort)
848-
text.Info(out, "Local pushpin other reserved ports: %d - %d", pushpinCtx.publishPort+1, pushpinCtx.publishPort+3)
849-
text.Info(out, "Local pushpin runner: %s", pushpinCtx.pushpinRunnerBin)
880+
881+
pushpinRoutesContents := strings.Join(c.BuildPushpinRoutes(), "\n") + "\n"
882+
err = os.WriteFile(pushpinCtx.routesFilePath, []byte(pushpinRoutesContents), 0o600)
883+
if err != nil {
884+
return pushpinCtx, fmt.Errorf("error writing routes file %s: %w", pushpinCtx.routesFilePath, err)
850885
}
851886

852887
// Pushpin is configured with the following.
@@ -863,72 +898,20 @@ func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpi
863898
// - if the backend enables HTTPS, then we enable that
864899
// - if the backend has a path prefix, then we set that up
865900
// - enables WebSocket-over-HTTP
866-
867901
// The runtime temporary directory, as well as the conf file and routes file
868902
// are set up and torn down along with fastly compute serve.
869-
var pushpinInstanceID uint32
870-
for {
871-
p := make([]byte, 4)
872-
_, _ = rand.Read(p)
873-
pushpinInstanceID = binary.BigEndian.Uint32(p)
874-
if pushpinInstanceID != 0 {
875-
break
876-
}
877-
}
878-
879-
pushpinRunDir := filepath.Join(
880-
os.TempDir(),
881-
fmt.Sprintf("pushpin-%08x", pushpinInstanceID),
882-
)
883-
if c.Globals.Verbose() {
884-
text.Break(out)
885-
text.Info(out, "Pushpin temporary runtime directory is %s", pushpinRunDir)
886-
}
887-
888-
pushpinConfFilePath := filepath.Join(
889-
os.TempDir(),
890-
fmt.Sprintf("pushpin-%08x.conf", pushpinInstanceID),
891-
)
892-
pushpinRoutesFilePath := filepath.Join(
893-
os.TempDir(),
894-
fmt.Sprintf("pushpin-routes-%08x", pushpinInstanceID),
895-
)
896-
897-
if c.Globals.Verbose() {
898-
text.Info(out, "Writing config file to %s...", pushpinConfFilePath)
899-
}
900-
901-
pushpinConfContents := pushpinCtx.buildPushpinConf()
902-
err = os.WriteFile(pushpinConfFilePath, []byte(pushpinConfContents), 0o600)
903-
if err != nil {
904-
return pushpinCtx, fmt.Errorf("error writing config file %s: %w", pushpinConfFilePath, err)
905-
}
906-
907-
if c.Globals.Verbose() {
908-
text.Info(out, "Writing routes file to %s...", pushpinRoutesFilePath)
909-
}
910-
pushpinRoutesContents := strings.Join(c.BuildPushpinRoutes(), "\n") + "\n"
911-
err = os.WriteFile(pushpinRoutesFilePath, []byte(pushpinRoutesContents), 0o600)
912-
if err != nil {
913-
return pushpinCtx, fmt.Errorf("error writing routes file %s: %w", pushpinRoutesFilePath, err)
914-
}
915-
916-
if c.Globals.Verbose() {
917-
text.Info(out, "Starting local Pushpin...")
918-
text.Break(out)
919-
}
920903

921904
args := []string{
922-
fmt.Sprintf("--config=%s", pushpinConfFilePath),
905+
fmt.Sprintf("--config=%s", pushpinCtx.confFilePath),
923906
"--verbose",
924907
}
925908

926-
// Set up a context that can be canceled (prevent rogue Pushpin process)
909+
// Set up a context that can be canceled (prevent zombie Pushpin process)
927910
var pushpinCmd *exec.Cmd
928911
ctx, cancel := context.WithCancel(context.Background())
929912

930913
var once sync.Once
931-
cleanup = func() {
914+
pushpinCtx.cleanup = func() {
932915
once.Do(func() {
933916
if pushpinCmd != nil && pushpinCmd.Process != nil {
934917
if c.Globals.Verbose() {
@@ -937,17 +920,17 @@ func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpi
937920
killProcessTree(pushpinCmd.Process.Pid)
938921
}
939922
if c.Globals.Verbose() {
940-
text.Output(out, "removing %s", pushpinRunDir)
923+
text.Output(out, "removing %s", pushpinCtx.pushpinRunDir)
941924
}
942-
_ = os.RemoveAll(pushpinRunDir)
925+
_ = os.RemoveAll(pushpinCtx.pushpinRunDir)
943926
if c.Globals.Verbose() {
944-
text.Output(out, "deleting %s", pushpinConfFilePath)
927+
text.Output(out, "deleting %s", pushpinCtx.confFilePath)
945928
}
946-
_ = os.Remove(pushpinConfFilePath)
929+
_ = os.Remove(pushpinCtx.confFilePath)
947930
if c.Globals.Verbose() {
948-
text.Output(out, "deleting %s", pushpinRoutesFilePath)
931+
text.Output(out, "deleting %s", pushpinCtx.routesFilePath)
949932
}
950-
_ = os.Remove(pushpinRoutesFilePath)
933+
_ = os.Remove(pushpinCtx.routesFilePath)
951934
cancel()
952935
})
953936
}
@@ -957,7 +940,7 @@ func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpi
957940
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
958941
go func() {
959942
<-sigCh
960-
cleanup()
943+
pushpinCtx.Close()
961944
}()
962945

963946
// gosec flagged this:
@@ -974,8 +957,13 @@ func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpi
974957

975958
// Start Pushpin
976959
if c.Globals.Verbose() {
977-
text.Info(out, "Starting Pushpin runner in the background...")
978960
text.Output(out, "%s: %s", text.BoldYellow("Pushpin command"), strings.Join(pushpinCmd.Args, " "))
961+
text.Output(out, "%s: %d", text.BoldYellow("Pushpin proxy port"), pushpinCtx.proxyPort)
962+
text.Output(out, "%s: %d", text.BoldYellow("Pushpin publisher port"), pushpinCtx.publishPort)
963+
text.Output(out, "%s: %d - %d", text.BoldYellow("Pushpin other reserved ports"), pushpinCtx.publishPort+1, pushpinCtx.publishPort+3)
964+
text.Output(out, "%s: %s", text.BoldYellow("Pushpin temporary runtime directory"), pushpinCtx.pushpinRunDir)
965+
text.Output(out, "%s: %s", text.BoldYellow("Pushpin conf file"), pushpinCtx.confFilePath)
966+
text.Output(out, "%s: %s", text.BoldYellow("Pushpin routes file"), pushpinCtx.routesFilePath)
979967
}
980968
if err := pushpinCmd.Start(); err != nil {
981969
return pushpinCtx, fmt.Errorf("failed to start Pushpin runner: %w", err)
@@ -1015,14 +1003,12 @@ func (c *ServeCommand) startPushpin(spinner text.Spinner, out io.Writer) (pushpi
10151003
if err != nil {
10161004
return pushpinCtx, fsterr.RemediationError{
10171005
Inner: err,
1018-
Remediation: fmt.Sprintf("A process may already be running on port %d.", pushpinCtx.proxyPort),
1006+
Remediation: fmt.Sprintf("Check that your disk isn't full and that a process isn't already running on ports %d or %d - %d.", pushpinCtx.proxyPort, pushpinCtx.publishPort, pushpinCtx.publishPort+3),
10191007
}
10201008
}
10211009

1022-
if c.Globals.Verbose() {
1023-
text.Info(out, "Local Pushpin started on port %d.", pushpinCtx.proxyPort)
1024-
text.Break(out)
1025-
}
1010+
text.Success(out, "Pushpin started.")
1011+
text.Break(out)
10261012

10271013
return pushpinCtx, nil
10281014
}

0 commit comments

Comments
 (0)