Skip to content

Commit 5430198

Browse files
committed
Adding command to start starter in detached mode
1 parent b394fb0 commit 5430198

File tree

3 files changed

+170
-14
lines changed

3 files changed

+170
-14
lines changed

main.go

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ var (
100100
)
101101

102102
func init() {
103-
f := cmdMain.Flags()
103+
f := cmdMain.PersistentFlags()
104104

105105
f.StringVar(&masterAddress, "starter.join", "", "join a cluster with master at given address")
106106
f.StringVar(&mode, "starter.mode", "cluster", "Set the mode of operation to use (cluster|single)")
@@ -316,12 +316,33 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
316316
}
317317

318318
// Setup log level
319+
configureLogging()
320+
321+
// Interrupt signal:
322+
sigChannel := make(chan os.Signal)
323+
rootCtx, cancel := context.WithCancel(context.Background())
324+
signal.Notify(sigChannel, os.Interrupt, syscall.SIGTERM)
325+
go handleSignal(sigChannel, cancel)
326+
327+
// Create service
328+
service := mustPrepareService(true)
329+
330+
// Run the service
331+
service.Run(rootCtx)
332+
}
333+
334+
// configureLogging configures the log object according to command line arguments.
335+
func configureLogging() {
319336
if verbose {
320337
logging.SetLevel(logging.DEBUG, projectName)
321338
} else {
322339
logging.SetLevel(logging.INFO, projectName)
323340
}
341+
}
324342

343+
// mustPrepareService creates a new Service for the configured arguments,
344+
// creating & checking settings where needed.
345+
func mustPrepareService(generateAutoKeyFile bool) *service.Service {
325346
// Auto detect docker container ID (if needed)
326347
runningInDocker := false
327348
if isRunningInDocker() {
@@ -399,7 +420,7 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
399420
}
400421

401422
// Auto create key file (if needed)
402-
if sslAutoKeyFile {
423+
if sslAutoKeyFile && generateAutoKeyFile {
403424
if sslKeyFile != "" {
404425
log.Fatalf("Cannot specify both --ssl.auto-key and --ssl.keyfile")
405426
}
@@ -422,12 +443,6 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
422443
log.Infof("Using self-signed certificate: %s", sslKeyFile)
423444
}
424445

425-
// Interrupt signal:
426-
sigChannel := make(chan os.Signal)
427-
rootCtx, cancel := context.WithCancel(context.Background())
428-
signal.Notify(sigChannel, os.Interrupt, syscall.SIGTERM)
429-
go handleSignal(sigChannel, cancel)
430-
431446
// Create service
432447
serviceConfig := service.Config{
433448
ID: id,
@@ -471,8 +486,7 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
471486
log.Fatalf("Failed to create service: %#v", err)
472487
}
473488

474-
// Run the service
475-
service.Run(rootCtx)
489+
return service
476490
}
477491

478492
// getEnvVar returns the value of the environment variable with given key of the given default

service/arangodb.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,8 @@ func (s *Service) serverExecutable() string {
245245
return s.ArangodPath
246246
}
247247

248-
// testInstance checks the `up` status of an arangod server instance.
249-
func (s *Service) testInstance(ctx context.Context, address string, port int) (up bool, version string, cancelled bool) {
248+
// TestInstance checks the `up` status of an arangod server instance.
249+
func (s *Service) TestInstance(ctx context.Context, address string, port int) (up bool, version string, cancelled bool) {
250250
instanceUp := make(chan string)
251251
go func() {
252252
client := &http.Client{Timeout: time.Second * 10}
@@ -544,7 +544,7 @@ func (s *Service) startArangod(runner Runner, myHostAddress string, serverType S
544544
if p != nil {
545545
s.log.Infof("%s seems to be running already, checking port %d...", serverType, myPort)
546546
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
547-
up, _, _ := s.testInstance(ctx, myHostAddress, myPort)
547+
up, _, _ := s.TestInstance(ctx, myHostAddress, myPort)
548548
cancel()
549549
if up {
550550
s.log.Infof("%s is already running on %d. No need to start anything.", serverType, myPort)
@@ -639,7 +639,7 @@ func (s *Service) runArangod(runner Runner, myPeer Peer, serverType ServerType,
639639
if err != nil {
640640
s.log.Fatalf("Cannot collect serverPort: %#v", err)
641641
}
642-
if up, version, cancelled := s.testInstance(ctx, myHostAddress, port); !cancelled {
642+
if up, version, cancelled := s.TestInstance(ctx, myHostAddress, port); !cancelled {
643643
if up {
644644
s.log.Infof("%s up and running (version %s).", serverType, version)
645645
if (serverType == ServerTypeCoordinator && !s.isLocalSlave) || serverType == ServerTypeSingle {

start.go

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//
2+
// DISCLAIMER
3+
//
4+
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
// Copyright holder is ArangoDB GmbH, Cologne, Germany
19+
//
20+
// Author Ewout Prangsma
21+
//
22+
23+
package main
24+
25+
import (
26+
"context"
27+
"fmt"
28+
"net/url"
29+
"os"
30+
"os/exec"
31+
"time"
32+
33+
"github.com/arangodb-helper/arangodb/client"
34+
"github.com/spf13/cobra"
35+
"github.com/spf13/pflag"
36+
)
37+
38+
var (
39+
cmdStart = &cobra.Command{
40+
Use: "start",
41+
Short: "Start the ArangoDB starter in the background",
42+
Run: cmdStartRun,
43+
}
44+
waitForServers bool
45+
)
46+
47+
func init() {
48+
f := cmdStart.Flags()
49+
f.BoolVar(&waitForServers, "starter.wait", false, "If set, the (parent) starter waits until all database servers are ready before exiting.")
50+
51+
cmdMain.AddCommand(cmdStart)
52+
}
53+
54+
func cmdStartRun(cmd *cobra.Command, args []string) {
55+
log.Infof("Starting %s version %s, build %s in the background", projectName, projectVersion, projectBuild)
56+
57+
// Setup logging
58+
configureLogging()
59+
60+
// Build service
61+
service := mustPrepareService(false)
62+
63+
// Find executable
64+
exePath, err := os.Executable()
65+
if err != nil {
66+
log.Fatalf("Cannot find executable path: %#v", err)
67+
}
68+
69+
// Build command line
70+
childArgs := make([]string, 0, len(os.Args))
71+
cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) {
72+
if f.Changed {
73+
a := "--" + f.Name
74+
value := f.Value.String()
75+
if value != "" {
76+
a = a + "=" + value
77+
}
78+
childArgs = append(childArgs, a)
79+
}
80+
})
81+
82+
log.Infof("Found child args: %#v", childArgs)
83+
84+
c := exec.Command(exePath, childArgs...)
85+
c.Stderr = os.Stderr
86+
c.Stdout = os.Stdout
87+
c.Stdin = os.Stdin
88+
c.Start()
89+
90+
// Create starter client
91+
scheme := "http"
92+
if sslAutoKeyFile || sslKeyFile != "" {
93+
scheme = "https"
94+
}
95+
starterURL, err := url.Parse(fmt.Sprintf("%s://127.0.0.1:%d", scheme, masterPort))
96+
if err != nil {
97+
log.Fatalf("Failed to create starter URL: %#v", err)
98+
}
99+
client, err := client.NewArangoStarterClient(*starterURL)
100+
if err != nil {
101+
log.Fatalf("Failed to create starter client: %#v", err)
102+
}
103+
104+
// Wait for detached starter to be alive
105+
rootCtx := context.Background()
106+
for {
107+
ctx, cancel := context.WithTimeout(rootCtx, time.Second)
108+
_, err := client.Version(ctx)
109+
cancel()
110+
if err == nil {
111+
break
112+
}
113+
time.Sleep(time.Millisecond * 100)
114+
}
115+
116+
// Wait until all servers ready (if needed)
117+
if waitForServers {
118+
for {
119+
var err error
120+
ctx, cancel := context.WithTimeout(rootCtx, time.Second)
121+
list, err := client.Processes(ctx)
122+
cancel()
123+
if err == nil && list.ServersStarted {
124+
// Start says it has started the servers, now wait for servers to be up.
125+
allUp := true
126+
for _, server := range list.Servers {
127+
ctx, cancel := context.WithTimeout(rootCtx, time.Second)
128+
up, _, _ := service.TestInstance(ctx, server.IP, server.Port)
129+
cancel()
130+
if !up {
131+
allUp = false
132+
break
133+
}
134+
}
135+
if allUp {
136+
break
137+
}
138+
}
139+
time.Sleep(time.Millisecond * 100)
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)