-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
347 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,24 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/gojek/darkroom/cmd/signals" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var rootCmd = &cobra.Command{ | ||
Use: "darkroom", | ||
Short: "Darkroom is an Image Proxy on your image source", | ||
// newRootCmd represents the base command when called without any subcommands. | ||
func newRootCmd() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "darkroom", | ||
Short: "Darkroom is an Image Proxy on your image source", | ||
} | ||
cmd.AddCommand(newRunCmdWithOpts(runCmdOpts{ | ||
SetupSignalHandler: signals.SetupSignalHandler, | ||
})) | ||
return cmd | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(serverCmd) | ||
} | ||
|
||
// Run function lets you run the commands | ||
func Run(args []string) error { | ||
rootCmd.SetArgs(args) | ||
return rootCmd.Execute() | ||
// Execute adds all child commands to the root command and sets flags appropriately. | ||
// This is called by main.main(). It only needs to happen once to the rootCmd. | ||
func Execute() error { | ||
return newRootCmd().Execute() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestRootCmd(t *testing.T) { | ||
// when | ||
err := Execute() | ||
// then | ||
assert.NoError(t, err) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,36 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/gojek/darkroom/pkg/logger" | ||
"github.com/gojek/darkroom/pkg/router" | ||
"github.com/gojek/darkroom/pkg/server" | ||
"github.com/gojek/darkroom/pkg/service" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var serverCmd = &cobra.Command{ | ||
Use: "server", | ||
Short: "Start the app server", | ||
Run: serverCmdF, | ||
type runCmdOpts struct { | ||
SetupSignalHandler func() (stopCh <-chan struct{}) | ||
} | ||
|
||
func serverCmdF(cmd *cobra.Command, args []string) { | ||
defer func() { | ||
if e := recover(); e != nil { | ||
logger.Errorf("failed to start the app due to error: %s", e) | ||
} | ||
}() | ||
startServer() | ||
} | ||
|
||
func startServer() { | ||
handler := router.NewRouter(service.NewDependencies()) | ||
s := server.NewServer(server.WithHandler(handler)) | ||
s.Start() | ||
func newRunCmdWithOpts(opts runCmdOpts) *cobra.Command { | ||
args := struct { | ||
port int | ||
}{} | ||
cmd := &cobra.Command{ | ||
Use: "server", | ||
Short: "Start the app server", | ||
RunE: func(cmd *cobra.Command, _ []string) error { | ||
deps, err := service.NewDependencies() | ||
if err != nil { | ||
return err | ||
} | ||
handler := router.NewRouter(deps) | ||
s := server.NewServer(server.Options{ | ||
Handler: handler, | ||
Port: args.port, | ||
}) | ||
return s.Start(opts.SetupSignalHandler()) | ||
}, | ||
} | ||
cmd.PersistentFlags().IntVarP(&args.port, "port", "p", 3000, "server port") | ||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"github.com/gojek/darkroom/pkg/config" | ||
"github.com/stretchr/testify/assert" | ||
"net/http" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestRunServer(t *testing.T) { | ||
// setup | ||
errCh := make(chan error) | ||
stopCh := make(chan struct{}) | ||
diagnosticsPort := 9999 | ||
v := config.Viper() | ||
v.Set("source.kind", "WebFolder") | ||
v.Set("source.baseURL", "https://example.com/path/to/folder") | ||
config.Update() | ||
|
||
// given | ||
cmd := newRunCmdWithOpts(runCmdOpts{ | ||
SetupSignalHandler: func() <-chan struct{} { | ||
return stopCh | ||
}, | ||
}) | ||
cmd.SetArgs([]string{"-p", fmt.Sprintf("%d", diagnosticsPort)}) | ||
|
||
// when | ||
go func() { | ||
defer close(errCh) | ||
errCh <- cmd.Execute() | ||
}() | ||
|
||
assert.True(t, assert.Eventually(t, func() bool { | ||
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/ping", diagnosticsPort)) | ||
if err != nil { | ||
return false | ||
} | ||
defer func() { | ||
_ = resp.Body.Close() | ||
}() | ||
return resp.StatusCode == http.StatusOK | ||
}, 5*time.Second, 100*time.Millisecond), "failed to run server") | ||
|
||
// when | ||
close(stopCh) | ||
|
||
// then | ||
assert.NoError(t, <-errCh) | ||
} | ||
|
||
func TestRunServerWithInvalidPort(t *testing.T) { | ||
// setup | ||
errCh := make(chan error) | ||
stopCh := make(chan struct{}) | ||
v := config.Viper() | ||
v.Set("source.kind", "WebFolder") | ||
v.Set("source.baseURL", "https://example.com/path/to/folder") | ||
config.Update() | ||
|
||
// given | ||
cmd := newRunCmdWithOpts(runCmdOpts{ | ||
SetupSignalHandler: func() <-chan struct{} { | ||
return stopCh | ||
}, | ||
}) | ||
cmd.SetArgs([]string{"-p", fmt.Sprintf("%d", -9000)}) | ||
|
||
// when | ||
go func() { | ||
defer close(errCh) | ||
errCh <- cmd.Execute() | ||
}() | ||
|
||
// then | ||
assert.Error(t, <-errCh) | ||
} | ||
|
||
func TestRunServerWithInvalidDependencies(t *testing.T) { | ||
// setup | ||
errCh := make(chan error) | ||
stopCh := make(chan struct{}) | ||
v := config.Viper() | ||
v.Set("source.kind", "") | ||
v.Set("source.baseURL", "") | ||
config.Update() | ||
|
||
// given | ||
cmd := newRunCmdWithOpts(runCmdOpts{ | ||
SetupSignalHandler: func() <-chan struct{} { | ||
return stopCh | ||
}, | ||
}) | ||
|
||
// when | ||
go func() { | ||
defer close(errCh) | ||
errCh <- cmd.Execute() | ||
}() | ||
|
||
// then | ||
assert.EqualError(t, <-errCh, "handler dependencies are not valid") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package signals | ||
|
||
import ( | ||
"os" | ||
"os/signal" | ||
"syscall" | ||
) | ||
|
||
var onlyOneSignalHandler = make(chan struct{}) | ||
|
||
// SetupSignalHandler registers for SIGTERM and SIGINT. A stop channel is returned | ||
// which is closed on one of these signals. If a second signal is caught, the program | ||
// is terminated with exit code 1. | ||
func SetupSignalHandler() (stopCh <-chan struct{}) { | ||
close(onlyOneSignalHandler) // panics when SetupSignalHandler is called twice | ||
|
||
stop := make(chan struct{}) | ||
c := make(chan os.Signal, 2) | ||
signal.Notify(c, os.Interrupt, syscall.SIGTERM) | ||
go func() { | ||
<-c | ||
close(stop) | ||
<-c | ||
os.Exit(1) // second signal. Exit directly. | ||
}() | ||
|
||
return stop | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package signals | ||
|
||
import ( | ||
"fmt" | ||
"github.com/stretchr/testify/assert" | ||
"os" | ||
"os/signal" | ||
"sync" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestSetupSignalHandler(t *testing.T) { | ||
stop := SetupSignalHandler() | ||
task := &Task{ | ||
ticker: time.NewTicker(time.Second * 2), | ||
} | ||
c := make(chan os.Signal, 1) | ||
signal.Notify(c, os.Interrupt) | ||
task.wg.Add(1) | ||
go func(c chan os.Signal) { | ||
defer task.wg.Done() | ||
task.Run(c) | ||
}(c) | ||
|
||
select { | ||
case sig := <-c: | ||
fmt.Printf("Got %s signal. Aborting...\n", sig) | ||
case _, ok := <-stop: | ||
assert.False(t, ok) | ||
} | ||
} | ||
|
||
type Task struct { | ||
wg sync.WaitGroup | ||
ticker *time.Ticker | ||
} | ||
|
||
func (t *Task) Run(c chan os.Signal) { | ||
for { | ||
go sendSignal(c) | ||
handle() | ||
} | ||
} | ||
|
||
func handle() { | ||
for i := 0; i < 5; i++ { | ||
fmt.Print("#") | ||
time.Sleep(time.Millisecond * 100) | ||
} | ||
fmt.Println() | ||
} | ||
|
||
func sendSignal(stopChan chan os.Signal) { | ||
fmt.Printf("...") | ||
time.Sleep(1 * time.Second) | ||
stopChan <- os.Interrupt | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.