diff --git a/cmd/admin/admin.go b/cmd/admin/admin.go index 785ed1abf0..04741a4a88 100644 --- a/cmd/admin/admin.go +++ b/cmd/admin/admin.go @@ -26,8 +26,8 @@ func New() *cobra.Command { adminCMD.AddCommand( initialise.New(), setup.New(), - start.New(), - start.NewStartFromInit(), + start.New(nil), + start.NewStartFromInit(nil), key.New(), ) diff --git a/cmd/start/start.go b/cmd/start/start.go index c3ba766fea..361619536b 100644 --- a/cmd/start/start.go +++ b/cmd/start/start.go @@ -45,6 +45,7 @@ import ( "github.com/zitadel/zitadel/internal/authz" authz_repo "github.com/zitadel/zitadel/internal/authz/repository" "github.com/zitadel/zitadel/internal/command" + "github.com/zitadel/zitadel/internal/crypto" cryptoDB "github.com/zitadel/zitadel/internal/crypto/database" "github.com/zitadel/zitadel/internal/database" "github.com/zitadel/zitadel/internal/eventstore" @@ -60,7 +61,7 @@ import ( "github.com/zitadel/zitadel/openapi" ) -func New() *cobra.Command { +func New(server chan<- *Server) *cobra.Command { start := &cobra.Command{ Use: "start", Short: "starts ZITADEL instance", @@ -78,7 +79,7 @@ Requirements: return err } - return startZitadel(config, masterKey) + return startZitadel(config, masterKey, server) }, } @@ -87,7 +88,24 @@ Requirements: return start } -func startZitadel(config *Config, masterKey string) error { +type Server struct { + background context.Context + Config *Config + DB *database.DB + KeyStorage crypto.KeyStorage + Keys *encryptionKeys + Eventstore *eventstore.Eventstore + Queries *query.Queries + AuthzRepo authz_repo.Repository + Storage static.Storage + Commands *command.Commands + LogStore *logstore.Service + Router *mux.Router + TLSConfig *tls.Config + Shutdown chan<- os.Signal +} + +func startZitadel(config *Config, masterKey string, server chan<- *Server) error { ctx := context.Background() dbClient, err := database.Connect(config.Database, false) @@ -179,7 +197,31 @@ func startZitadel(config *Config, masterKey string) error { if err != nil { return err } - return listen(ctx, router, config.Port, tlsConfig) + + shutdown := make(chan os.Signal, 1) + signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM) + + if server != nil { + server <- &Server{ + background: ctx, + Config: config, + DB: dbClient, + KeyStorage: keyStorage, + Keys: keys, + Eventstore: eventstoreClient, + Queries: queries, + AuthzRepo: authZRepo, + Storage: storage, + Commands: commands, + LogStore: actionsLogstoreSvc, + Router: router, + TLSConfig: tlsConfig, + Shutdown: shutdown, + } + close(server) + } + + return listen(ctx, router, config.Port, tlsConfig, shutdown) } func startAPIs( @@ -300,7 +342,7 @@ func startAPIs( return nil } -func listen(ctx context.Context, router *mux.Router, port uint16, tlsConfig *tls.Config) error { +func listen(ctx context.Context, router *mux.Router, port uint16, tlsConfig *tls.Config, shutdown <-chan os.Signal) error { http2Server := &http2.Server{} http1Server := &http.Server{Handler: h2c.NewHandler(router, http2Server), TLSConfig: tlsConfig} lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) @@ -320,9 +362,6 @@ func listen(ctx context.Context, router *mux.Router, port uint16, tlsConfig *tls } }() - shutdown := make(chan os.Signal, 1) - signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM) - select { case err := <-errCh: return fmt.Errorf("error starting server: %w", err) diff --git a/cmd/start/start_from_init.go b/cmd/start/start_from_init.go index 89c74d5592..940efb4e84 100644 --- a/cmd/start/start_from_init.go +++ b/cmd/start/start_from_init.go @@ -11,7 +11,7 @@ import ( "github.com/zitadel/zitadel/cmd/tls" ) -func NewStartFromInit() *cobra.Command { +func NewStartFromInit(server chan<- *Server) *cobra.Command { cmd := &cobra.Command{ Use: "start-from-init", Short: "cold starts zitadel", @@ -37,7 +37,7 @@ Requirements: startConfig := MustNewConfig(viper.GetViper()) - err = startZitadel(startConfig, masterKey) + err = startZitadel(startConfig, masterKey, server) logging.OnError(err).Fatal("unable to start zitadel") }, } diff --git a/cmd/start/start_from_setup.go b/cmd/start/start_from_setup.go index 75c2347c2b..0be315fae9 100644 --- a/cmd/start/start_from_setup.go +++ b/cmd/start/start_from_setup.go @@ -10,7 +10,7 @@ import ( "github.com/zitadel/zitadel/cmd/tls" ) -func NewStartFromSetup() *cobra.Command { +func NewStartFromSetup(server chan<- *Server) *cobra.Command { cmd := &cobra.Command{ Use: "start-from-setup", Short: "cold starts zitadel", @@ -35,7 +35,7 @@ Requirements: startConfig := MustNewConfig(viper.GetViper()) - err = startZitadel(startConfig, masterKey) + err = startZitadel(startConfig, masterKey, server) logging.OnError(err).Fatal("unable to start zitadel") }, } diff --git a/cmd/zitadel.go b/cmd/zitadel.go index 9822e1da05..8de2aaf5b4 100644 --- a/cmd/zitadel.go +++ b/cmd/zitadel.go @@ -5,7 +5,9 @@ import ( _ "embed" "errors" "io" + "os" "strings" + "sync" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -26,7 +28,7 @@ var ( defaultConfig []byte ) -func New(out io.Writer, in io.Reader, args []string) *cobra.Command { +func New(out io.Writer, in io.Reader, args []string, server chan<- *start.Server) *cobra.Command { cmd := &cobra.Command{ Use: "zitadel", Short: "The ZITADEL CLI lets you interact with ZITADEL", @@ -51,9 +53,9 @@ func New(out io.Writer, in io.Reader, args []string) *cobra.Command { admin.New(), //is now deprecated, remove later on initialise.New(), setup.New(), - start.New(), - start.NewStartFromInit(), - start.NewStartFromSetup(), + start.New(server), + start.NewStartFromInit(server), + start.NewStartFromSetup(server), key.New(), ) @@ -69,3 +71,30 @@ func initConfig() { logging.WithFields("file", file).OnError(err).Warn("unable to read config file") } } + +type TestServer struct { + *start.Server + wg sync.WaitGroup +} + +func (s *TestServer) Done() { + s.Shutdown <- os.Interrupt + s.wg.Wait() +} + +func NewTestServer(args []string) *TestServer { + testServer := new(TestServer) + server := make(chan *start.Server, 1) + + testServer.wg.Add(1) + go func(wg *sync.WaitGroup) { + defer wg.Done() + + cmd := New(os.Stdout, os.Stdin, args, server) + cmd.SetArgs(args) + logging.OnError(cmd.Execute()).Fatal() + }(&testServer.wg) + + testServer.Server = <-server + return testServer +} diff --git a/cmd/zitadel_test.go b/cmd/zitadel_test.go new file mode 100644 index 0000000000..7302469d3d --- /dev/null +++ b/cmd/zitadel_test.go @@ -0,0 +1,13 @@ +package cmd + +import ( + "strings" + "testing" +) + +const commandLine = `start-from-init --masterkey MasterkeyNeedsToHave32Characters --tlsMode disabled --config ../e2e/config/localhost/zitadel.yaml --steps ../e2e/config/localhost/zitadel.yaml` + +func TestNewTestServer(t *testing.T) { + s := NewTestServer(strings.Split(commandLine, " ")) + defer s.Done() +} diff --git a/main.go b/main.go index 0f3264080e..97689bbe41 100644 --- a/main.go +++ b/main.go @@ -10,6 +10,6 @@ import ( func main() { args := os.Args[1:] - rootCmd := cmd.New(os.Stdout, os.Stdin /*, int(os.Stdin.Fd())*/, args) + rootCmd := cmd.New(os.Stdout, os.Stdin, args, nil) cobra.CheckErr(rootCmd.Execute()) }