Skip to content

Commit

Permalink
Merge pull request #102 from hmrc/BDOG-3097
Browse files Browse the repository at this point in the history
BDOG-3097
  • Loading branch information
jordanrowe authored Apr 10, 2024
2 parents a168765 + bc8b84e commit c49ad53
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 97 deletions.
20 changes: 6 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,24 @@ If you'd prefer to carry out these steps manually, then follow these steps:

**Linux Intel**
```shell
curl -L -O https://github.com/hmrc/sm2/releases/download/v1.2.0/sm2-1.2.0-linux-intel.zip && unzip sm2-1.2.0-linux-intel.zip && rm sm2-1.2.0-linux-intel.zip && chmod +x sm2
curl -L -O https://github.com/hmrc/sm2/releases/download/v2.0.0/sm2-2.0.0-linux-intel.zip && unzip sm2-2.0.0-linux-intel.zip && rm sm2-2.0.0-linux-intel.zip && chmod +x sm2
```

**Linux Arm64**
```shell
curl -L -O https://github.com/hmrc/sm2/releases/download/v1.2.0/sm2-1.2.0-linux-arm64.zip && unzip sm2-1.2.0-linux-arm64.zip && rm sm2-1.2.0-linux-arm64.zip && chmod +x sm2
curl -L -O https://github.com/hmrc/sm2/releases/download/v2.0.0/sm2-2.0.0-linux-arm64.zip && unzip sm2-2.0.0-linux-arm64.zip && rm sm2-2.0.0-linux-arm64.zip && chmod +x sm2
```

**OSX/Apple (latest M1/M2 cpus)**

```shell
curl -L -O https://github.com/hmrc/sm2/releases/download/v1.2.0/sm2-1.2.0-apple-arm64.zip && unzip sm2-1.2.0-apple-arm64.zip && rm sm2-1.2.0-apple-arm64.zip && chmod +x sm2
curl -L -O https://github.com/hmrc/sm2/releases/download/v2.0.0/sm2-2.0.0-apple-arm64.zip && unzip sm2-2.0.0-apple-arm64.zip && rm sm2-2.0.0-apple-arm64.zip && chmod +x sm2
```

**OSX/Apple (older Intel cpus)**

```shell
curl -L -O https://github.com/hmrc/sm2/releases/download/v1.2.0/sm2-1.2.0-apple-intel.zip && unzip sm2-1.2.0-apple-intel.zip && rm sm2-1.2.0-apple-intel.zip && chmod +x sm2
curl -L -O https://github.com/hmrc/sm2/releases/download/v2.0.0/sm2-2.0.0-apple-intel.zip && unzip sm2-2.0.0-apple-intel.zip && rm sm2-2.0.0-apple-intel.zip && chmod +x sm2
```

If everything has worked you should have an executable called `sm2`.
Expand Down Expand Up @@ -130,14 +130,6 @@ Alternatively you can start more than one service at once by typing multiple ser
$ sm2 -start SERVICE_ONE SERVICE_TWO
```

#### Starting a large group of services
Starting a large group of services can overload the cpu of a machine and lead to services failing to start.
If this happens use the following command to start the services at a slower pace.
```shell
$ sm2 --start LARGE_PROFILE_NAME --workers 1 --delay-seconds 5
```
The workers argument starts one service at a time and the DelaySeconds argument adds a 5 second delay inbetween services.

### Starting specific versions
If you need to run a specific version of a service you can do so by adding a colon followed by the version number to the service name, e.g.
```shell
Expand All @@ -160,7 +152,7 @@ When starting more than one service, the `-r` flag only applies to the first ser
| -noprogress | Disabled the progress bars. Useful for scripting and automation.
| -src | Runs the service(s) from source instead of downloading the binary artifacts. Service manager will attempt to clone the repository and start the service using sbt start. Assumes the system has git configured and a working sbt installation.
| -update-config | Updates workspace copy of service-manager from git. Will fail if there are uncommitted changes or if the config repo is not on the main branch.
| -wait 120 | Waits a given number of seconds for the service to start before exiting.
| -wait 120 | Waits a given number of seconds (default 30) for the service to respond to a healthcheck after startup.
| -workers 4 | Sets the number of concurrent downloads (default 2). Can also be set via SM_WORKERS environment variable.

### Stopping services (-stop)
Expand Down Expand Up @@ -238,7 +230,7 @@ Sometimes a service will fail to start up. To help determine why, service manage
Before doing anything else, it’s worth running service-manager’s self-checks to ensure it is installed correctly.
```shell
$ sm2 -diagnostic
version: 1.2.0
version: 2.0.0
build: ef49b60
OS: OK (linux, amd64)
JAVA: OK (11.0.17)
Expand Down
2 changes: 1 addition & 1 deletion USERGUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ sm2 --start SERVICE_ONE SERVICE_TWO SERVICE_THREE
| `--noprogress` | Supresses the progress bars when downloading the service. Suitable for scripts etc. |
| `--offline` | Starts services that are already without attempting to download the latest version |
| `--clean` | Removes existing install, forcing a re-download |
| `--wait 20` | Waits a specified number of seconds for all services to reach a healthy state |
| `--wait 20` | Waits a specified number of seconds (default 30) for each service to reach a healthy state |
| `--appendArgs` | A json map of extra args for services being started: `{"SERVICE_NAME":["-DFoo=Bar","SOMETHING"]}` |
| `--workers 4` | The number of services to download/start at the same time (default 2) |
| `--reverse-proxy` | Starts a reverse proxy |
Expand Down
6 changes: 2 additions & 4 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ type UserOption struct {
Verbose bool // shows extra logging
Version bool // prints sm2 version number
Verify bool // checks if a given service or profile is running
Wait int // waits given number of secs after starting services for then to respond to pings
Wait int // waits a given number of secs (default 30) after starting a service for it to respond to healthcheck
Workers int // sets the number of concurrent downloads/service starts
DelaySeconds int // sets the pause in seconds between starting services
}

func Parse(args []string) (*UserOption, error) {
Expand Down Expand Up @@ -197,9 +196,8 @@ func BuildFlagSet(opts *UserOption) *flag.FlagSet {
flagset.BoolVar(&opts.Verbose, "v", false, "enable verbose output")
flagset.BoolVar(&opts.Version, "version", false, "show the version of service-manager")
flagset.BoolVar(&opts.Verify, "verify", false, "for scripts, checks if a service/profile is running")
flagset.IntVar(&opts.Wait, "wait", 0, "used with --start, waits a specified number of seconds for the services to become available before exiting (use with --start)")
flagset.IntVar(&opts.Wait, "wait", 30, "used with --start, waits a specified number of seconds for each service to respond to a healthcheck, defaults to 30")
flagset.IntVar(&opts.Workers, "workers", defaultWorkers(), "how many services should be downloaded at the same time (use with --start)")
flagset.IntVar(&opts.DelaySeconds, "delay-seconds", 0, "how long to pause, in seconds, after starting a service before starting another")

return flagset
}
Expand Down
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ IFS=$'\n\t'

TARGET_OS="linux"
TARGET_ARCH="intel"
TARGET_VERSION="1.2.0"
TARGET_VERSION="2.0.0"

if [[ "$(uname)" == "Darwin" ]]; then
TARGET_OS="apple"
Expand Down
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))

BINARY := sm2
VERSION := 1.2.0
VERSION := 2.0.0
BUILD := `git rev-parse HEAD`

# Setup linker flags option for build that interoperate with variable names in src code
Expand Down
3 changes: 1 addition & 2 deletions servicemanager/autocomplete.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,7 @@ func dontComplete(previousWord string) bool {
"-ports",
"-search",
"-wait",
"-workers",
"-delay-seconds":
"-workers":
return true
}
return false
Expand Down
46 changes: 0 additions & 46 deletions servicemanager/await.go

This file was deleted.

33 changes: 15 additions & 18 deletions servicemanager/startservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,24 @@ func (sm *ServiceManager) StartService(serviceAndVersion ServiceAndVersion) erro
state.HealthcheckUrl = healthcheckUrl
// and finally, we record out success
err = sm.Ledger.SaveStateFile(installDir, state)
sm.pauseTillHealthy(healthcheckUrl)
if err != nil {
sm.progress.update(serviceAndVersion.service, 0, "Failed")
return err
}
err = sm.pauseTillHealthy(healthcheckUrl)
return err
}

func (sm *ServiceManager) pauseTillHealthy(healthcheckUrl string) {
if sm.Commands.DelaySeconds > 0 {
count := 0
for count < sm.Commands.DelaySeconds*2 && !sm.CheckHealth(healthcheckUrl) {
count++
time.Sleep(500 * time.Millisecond)
func (sm *ServiceManager) pauseTillHealthy(healthcheckUrl string) error {
count := 0
for count < sm.Commands.Wait*2 {
if sm.CheckHealth(healthcheckUrl) {
return nil
}
count++
time.Sleep(500 * time.Millisecond)
}
return fmt.Errorf("health check unsuccessful after %d seconds", sm.Commands.Wait)
}

func (sm *ServiceManager) installService(installDir string, serviceId string, group string, artifact string, version string) (ledger.InstallFile, error) {
Expand Down Expand Up @@ -347,17 +353,13 @@ func (sm *ServiceManager) asyncStart(services []ServiceAndVersion) {
fmt.Println("Starting 1 service")
} else {
workerPlural := "workers"
delay := ""

if sm.Commands.Workers == 1 {
workerPlural = "worker"
}

if sm.Commands.DelaySeconds != 0 {
delay = fmt.Sprintf(", with a delay of %d seconds", sm.Commands.DelaySeconds)
}

fmt.Printf("Starting %d services on %d %s%s\n", len(services), sm.Commands.Workers, workerPlural, delay)
fmt.Printf("Starting %d services on %d %s\n", len(services), sm.Commands.Workers, workerPlural)
}

// start up a number of workers (controlled by --workers param)
Expand All @@ -376,13 +378,8 @@ func (sm *ServiceManager) asyncStart(services []ServiceAndVersion) {
// this could be way better, wait groups, or force a final paint or something??
time.Sleep(time.Millisecond)

if sm.Commands.Wait > 0 {
fmt.Printf("Waiting %d secs for all services to start.", sm.Commands.Wait)
sm.Await(services, sm.Commands.Wait)
}

// if anything has failed to start, report why
if len(sm.progress.errors) > 0 && !sm.progress.noProgress {
if len(sm.progress.errors) > 0 {
fmt.Println("\n\033[1;31mSome services failed to start:\033[0m")
for k, v := range sm.progress.errors {
fmt.Printf(" %s: %s\n", k, v.Error())
Expand Down
12 changes: 2 additions & 10 deletions servicemanager/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (sm *ServiceManager) PrintStatus() {

longestServiceName := getLongestServiceName(append(statuses, unmanaged...))
printTable(statuses, termWidth, longestServiceName, os.Stdout)
printHelpIfRequired(statuses, sm.Commands.DelaySeconds)
printHelpIfRequired(statuses)

if len(unmanaged) > 0 {
fmt.Print("\n\033[34mAlso, the following processes are running which occupy ports of services\n")
Expand Down Expand Up @@ -332,7 +332,7 @@ func printUnmanagedTable(statuses []serviceStatus, maxWidth int, longestServiceN
fmt.Fprint(out, border)
}

func printHelpIfRequired(statuses []serviceStatus, delay int) {
func printHelpIfRequired(statuses []serviceStatus) {
for _, status := range statuses {
if status.health == FAIL && status.service != "MONGO" {
fmt.Print("\n\033[1;31mOne or more services have failed to start.\033[0m\n")
Expand All @@ -342,14 +342,6 @@ func printHelpIfRequired(statuses []serviceStatus, delay int) {
fmt.Print("Alternatively, you can remove them from this list by using:\n")
fmt.Print(" sm2 -prune\n\n")

if delay == 0 && len(statuses) >= 10 { // not already using --delay-seconds
fmt.Println("Note: If you're starting a profile that contains a lot of services,")
fmt.Println("try using `--delay-seconds 5` to add a 5 second delay after starting")
fmt.Println("each service. This will help prevent your CPU getting overloaded,")
fmt.Println("which can cause the services to take too long to respond to the healthcheck.")
fmt.Println("See `sm2 --help` for more information.")
}

return
}
}
Expand Down

0 comments on commit c49ad53

Please sign in to comment.