Files
opencloud/tests/ociswrapper/ocis/ocis.go
T
Sawjan Gurung 58c083d311 [tests-only][full-ci] Add option to check ocis connection by authenticating user (#8540)
* Revert "use capabilites in ociswrapper"

This reverts commit 0768723c89.

* tests: check ocis connection with basic auth when provided

* ci: check ocis connection with admin basic auth

* list all ocis services

* list services with timeout

* ci: check ocis connection with admin basic auth

* list all ocis services
2024-03-01 14:54:09 +01:00

217 lines
4.7 KiB
Go

package ocis
import (
"bufio"
"crypto/tls"
"fmt"
"net/http"
"os"
"os/exec"
"strconv"
"strings"
"sync"
"syscall"
"time"
"ociswrapper/common"
"ociswrapper/log"
"ociswrapper/ocis/config"
)
var cmd *exec.Cmd
var retryCount = 0
var stopSignal = false
func Start(envMap map[string]any) {
// wait for the log scanner to finish
var wg sync.WaitGroup
wg.Add(2)
stopSignal = false
if retryCount == 0 {
defer common.Wg.Done()
}
cmd = exec.Command(config.Get("bin"), "server")
cmd.Env = os.Environ()
var environments []string
if envMap != nil {
for key, value := range envMap {
environments = append(environments, fmt.Sprintf("%s=%v", key, value))
}
}
cmd.Env = append(cmd.Env, environments...)
logs, err := cmd.StderrPipe()
if err != nil {
log.Panic(err)
}
output, err := cmd.StdoutPipe()
if err != nil {
log.Panic(err)
}
err = cmd.Start()
if err != nil {
log.Panic(err)
}
logScanner := bufio.NewScanner(logs)
outputScanner := bufio.NewScanner(output)
outChan := make(chan string)
// Read the logs when the 'ocis server' command is running
go func() {
defer wg.Done()
for logScanner.Scan() {
outChan <- logScanner.Text()
}
}()
go func() {
defer wg.Done()
for outputScanner.Scan() {
outChan <- outputScanner.Text()
}
}()
// Fetch logs from the channel and print them
go func() {
for s := range outChan {
fmt.Println(s)
}
}()
if err := cmd.Wait(); err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
status := exitErr.Sys().(syscall.WaitStatus)
// retry only if oCIS server exited with code > 0
// -1 exit code means that the process was killed by a signal (syscall.SIGINT)
if status.ExitStatus() > 0 && !stopSignal {
waitUntilCompleteShutdown()
log.Println(fmt.Sprintf("oCIS server exited with code %v", status.ExitStatus()))
// retry to start oCIS server
retryCount++
maxRetry, _ := strconv.Atoi(config.Get("retry"))
if retryCount <= maxRetry {
wg.Wait()
close(outChan)
log.Println(fmt.Sprintf("Retry starting oCIS server... (retry %v)", retryCount))
// wait 500 milliseconds before retrying
time.Sleep(500 * time.Millisecond)
Start(envMap)
return
}
}
}
}
wg.Wait()
close(outChan)
}
func Stop() {
log.Println("Stopping oCIS server...")
stopSignal = true
err := cmd.Process.Signal(syscall.SIGINT)
if err != nil {
if !strings.HasSuffix(err.Error(), "process already finished") {
log.Fatalln(err)
}
}
cmd.Process.Wait()
waitUntilCompleteShutdown()
}
func listAllServices(startTime time.Time, timeout time.Duration) {
timeoutS := timeout * time.Second
c := exec.Command(config.Get("bin"), "list")
_, err := c.CombinedOutput()
if err != nil {
if time.Since(startTime) <= timeoutS {
time.Sleep(500 * time.Millisecond)
listAllServices(startTime, timeout)
}
return
}
log.Println("All services are up")
}
func WaitForConnection() bool {
listAllServices(time.Now(), 30)
transport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
// 30 seconds timeout
timeoutValue := 30 * time.Second
client := http.Client{
Timeout: timeoutValue,
Transport: transport,
}
var req *http.Request
if config.Get("adminUsername") != "" && config.Get("adminPassword") != "" {
req, _ = http.NewRequest("GET", config.Get("url")+"/graph/v1.0/me/drives", nil)
req.SetBasicAuth(config.Get("adminUsername"), config.Get("adminPassword"))
} else {
req, _ = http.NewRequest("GET", config.Get("url")+"/ocs/v1.php/cloud/capabilities?format=json", nil)
}
timeout := time.After(timeoutValue)
for {
select {
case <-timeout:
log.Println(fmt.Sprintf("%v seconds timeout waiting for oCIS server", int64(timeoutValue.Seconds())))
return false
default:
req.Header.Set("X-Request-ID", "ociswrapper-"+strconv.Itoa(int(time.Now().UnixMilli())))
res, err := client.Do(req)
if err != nil || res.StatusCode != 200 {
// 500 milliseconds poll interval
time.Sleep(500 * time.Millisecond)
continue
}
log.Println("oCIS server is ready to accept requests")
return true
}
}
}
func waitUntilCompleteShutdown() {
timeout := 30 * time.Second
startTime := time.Now()
c := exec.Command("sh", "-c", "ps ax | grep 'ocis server' | grep -v grep | awk '{print $1}'")
output, err := c.CombinedOutput()
if err != nil {
log.Println(err.Error())
}
for strings.TrimSpace(string(output)) != "" {
output, _ = c.CombinedOutput()
log.Println("Process found. Waiting...")
if time.Since(startTime) >= timeout {
log.Println(fmt.Sprintf("Unable to kill oCIS server after %v seconds", int64(timeout.Seconds())))
break
}
}
}
func Restart(envMap map[string]any) bool {
Stop()
log.Println("Restarting oCIS server...")
common.Wg.Add(1)
go Start(envMap)
return WaitForConnection()
}