test: prepare

This commit is contained in:
Suyono 2023-12-09 08:40:07 +00:00
parent d5eb872b13
commit dd66cb9f1e
12 changed files with 221 additions and 35 deletions

View File

@ -1,2 +1,4 @@
/dummy/dummy
/starter/starter
/starter/starter
/oneshot/oneshot
/spawner/spawner

View File

@ -0,0 +1,67 @@
package main
import (
"log"
"math/rand"
"os"
"os/exec"
"gitea.suyono.dev/suyono/wingmate"
"github.com/spf13/viper"
)
const (
// DummyPath = "/workspaces/wingmate/cmd/experiment/dummy/dummy"
DummyPath = "/usr/local/bin/wmdummy"
EnvDummyPath = "DUMMY_PATH"
EnvPrefix = "WINGMATE"
EnvLog = "LOG"
EnvLogMessage = "LOG_MESSAGE"
EnvDefaultLogMessage = "oneshot executed"
)
func main() {
viper.SetEnvPrefix(EnvPrefix)
viper.BindEnv(EnvDummyPath, EnvLog, EnvLogMessage)
viper.SetDefault(EnvDummyPath, DummyPath)
viper.SetDefault(EnvLogMessage, EnvDefaultLogMessage)
exePath := viper.GetString(EnvDummyPath)
logPath := viper.GetString(EnvLog)
logMessage := viper.GetString(EnvLogMessage)
if logPath != "" {
var (
err error
file *os.File
)
if file, err = os.OpenFile(logPath, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o666); err == nil {
defer func() {
_ = file.Close()
}()
if err = wingmate.NewLog(file); err == nil {
wingmate.Log().Info().Msg(logMessage)
}
}
}
StartRandomInstances(exePath)
}
func StartRandomInstances(exePath string) {
num := (rand.Uint32() % 16) + 16
var (
ctr uint32
cmd *exec.Cmd
err error
)
for ctr = 0; ctr < num; ctr++ {
cmd = exec.Command(exePath)
if err = cmd.Start(); err != nil {
log.Printf("failed to run %s: %+v\n", exePath, err)
}
}
}

View File

@ -0,0 +1,40 @@
package main
import (
"log"
"os/exec"
"time"
"github.com/spf13/viper"
)
const (
EnvPrefix = "WINGMATE"
EnvOneShotPath = "ONESHOT_PATH"
OneShotPath = "/usr/local/bin/wmoneshot"
)
func main() {
var (
cmd *exec.Cmd
err error
t *time.Ticker
)
viper.SetEnvPrefix(EnvPrefix)
viper.BindEnv(EnvOneShotPath)
viper.SetDefault(EnvOneShotPath, OneShotPath)
exePath := viper.GetString(EnvOneShotPath)
t = time.NewTicker(time.Second * 5)
for {
cmd = exec.Command(exePath)
if err = cmd.Run(); err != nil {
log.Printf("failed to run %s: %+v\n", exePath, err)
} else {
log.Printf("%s executed\n", exePath)
}
<-t.C
}
}

View File

@ -6,21 +6,32 @@ import (
"log"
"os/exec"
"sync"
"github.com/spf13/viper"
)
const (
// DummyPath = "/workspaces/wingmate/cmd/experiment/dummy/dummy"
DummyPath = "/usr/local/bin/wmdummy"
DummyPath = "/usr/local/bin/wmdummy"
EnvDummyPath = "DUMMY_PATH"
EnvPrefix = "WINGMATE"
)
func main() {
var (
stdout io.ReadCloser
stderr io.ReadCloser
wg *sync.WaitGroup
err error
stdout io.ReadCloser
stderr io.ReadCloser
wg *sync.WaitGroup
err error
exePath string
)
cmd := exec.Command(DummyPath)
viper.SetEnvPrefix(EnvPrefix)
viper.BindEnv(EnvDummyPath)
viper.SetDefault(EnvDummyPath, DummyPath)
exePath = viper.GetString(EnvDummyPath)
cmd := exec.Command(exePath)
if stdout, err = cmd.StdoutPipe(); err != nil {
log.Panic(err)

View File

@ -89,27 +89,27 @@ func readCrontab(path string) ([]*Cron, error) {
hasRun: false,
}
if err = c.setField(minute, parts[1]); err != nil {
wingmate.Log().Error().Msgf("error parsing minute field %#v", err)
wingmate.Log().Error().Msgf("error parsing minute field %+v", err)
continue
}
if err = c.setField(hour, parts[2]); err != nil {
wingmate.Log().Error().Msgf("error parsing hour field %#v", err)
wingmate.Log().Error().Msgf("error parsing hour field %+v", err)
continue
}
if err = c.setField(dom, parts[3]); err != nil {
wingmate.Log().Error().Msgf("error parsing day of month field %#v", err)
wingmate.Log().Error().Msgf("error parsing day of month field %+v", err)
continue
}
if err = c.setField(month, parts[4]); err != nil {
wingmate.Log().Error().Msgf("error parsing month field %#v", err)
wingmate.Log().Error().Msgf("error parsing month field %+v", err)
continue
}
if err = c.setField(dow, parts[5]); err != nil {
wingmate.Log().Error().Msgf("error parsing day of week field %#v", err)
wingmate.Log().Error().Msgf("error parsing day of week field %+v", err)
continue
}
@ -201,12 +201,12 @@ func (c *Cron) setField(field cronField, input string) error {
*cField = &specAny{}
} else if strings.HasPrefix(input, "*/") {
if parsed64, err = strconv.ParseUint(input[2:], 10, 8); err != nil {
return fmt.Errorf("error parse field %#v with input %s: %w", field, input, err)
return fmt.Errorf("error parse field %+v with input %s: %w", field, input, err)
}
parsed = uint8(parsed64)
if fr.valid(parsed) {
return fmt.Errorf("error parse field %#v with input %s: invalid value", field, input)
if !fr.valid(parsed) {
return fmt.Errorf("error parse field %+v with input %s parsed to %d: invalid value", field, input, parsed)
}
multi = make([]uint8, 0)
current = parsed
@ -224,12 +224,12 @@ func (c *Cron) setField(field cronField, input string) error {
multi = make([]uint8, 0)
for _, s := range multiStr {
if parsed64, err = strconv.ParseUint(s, 10, 8); err != nil {
return fmt.Errorf("error parse field %#v with input %s: %w", field, input, err)
return fmt.Errorf("error parse field %+v with input %s: %w", field, input, err)
}
parsed = uint8(parsed64)
if fr.valid(parsed) {
return fmt.Errorf("error parse field %#v with input %s: invalid value", field, input)
if !fr.valid(parsed) {
return fmt.Errorf("error parse field %+v with input %s: invalid value", field, input)
}
multi = append(multi, parsed)
@ -240,12 +240,12 @@ func (c *Cron) setField(field cronField, input string) error {
}
} else {
if parsed64, err = strconv.ParseUint(input, 10, 8); err != nil {
return fmt.Errorf("error parse field %#v with input %s: %w", field, input, err)
return fmt.Errorf("error parse field %+v with input %s: %w", field, input, err)
}
parsed = uint8(parsed64)
if fr.valid(parsed) {
return fmt.Errorf("error parse field %#v with input %s: invalid value", field, input)
if !fr.valid(parsed) {
return fmt.Errorf("error parse field %+v with input %s: invalid value", field, input)
}
*cField = &specExact{

View File

@ -10,6 +10,11 @@ RUN go build -v
WORKDIR /root/wingmate/cmd/experiment/starter
RUN go build -v
WORKDIR /root/wingmate/cmd/experiment/spawner
RUN go build -v
WORKDIR /root/wingmate/cmd/experiment/oneshot
RUN go build -v
@ -19,6 +24,8 @@ RUN apk add tzdata && ln -s /usr/share/zoneinfo/Australia/Sydney /etc/localtime
COPY --from=builder /root/wingmate/cmd/wingmate/wingmate /usr/local/bin/wingmate
COPY --from=builder /root/wingmate/cmd/experiment/dummy/dummy /usr/local/bin/wmdummy
COPY --from=builder /root/wingmate/cmd/experiment/starter/starter /usr/local/bin/wmstarter
COPY --from=builder /root/wingmate/cmd/experiment/oneshot/oneshot /usr/local/bin/wmoneshot
COPY --from=builder /root/wingmate/cmd/experiment/spawner/spawner /usr/local/bin/wmspawner
ADD --chmod=755 docker/alpine/entry.sh /usr/local/bin/entry.sh
ADD --chmod=755 docker/alpine/etc /etc

View File

@ -0,0 +1 @@
*/5 * * * * /etc/wingmate/crontab.d/cron1.sh

View File

@ -0,0 +1,6 @@
#!/bin/sh
export WINGMATE_DUMMY_PATH=/usr/local/bin/wmdummy
export WINGMATE_LOG=/var/log/cron1.log
export WINGMATE_LOG_MESSAGE="cron executed in minute 5,10,15,20,25,30,35,40,45,50,55"
exec /usr/local/bin/wmoneshot

View File

@ -0,0 +1,5 @@
#!/bin/sh
export WINGMATE_ONESHOT_PATH=/usr/local/bin/wmoneshot
export WINGMATE_DUMMY_PATH=/usr/local/bin/wmdummy
exec /usr/local/bin/wmspawner

View File

@ -1,6 +1,7 @@
package init
import (
"io"
"os/exec"
"sync"
"time"
@ -8,19 +9,60 @@ import (
"gitea.suyono.dev/suyono/wingmate"
)
const (
cronTag = "cron"
)
func (i *Init) cron(wg *sync.WaitGroup, cron Cron, exitFlag <-chan any) {
defer wg.Done()
var (
iwg *sync.WaitGroup
err error
stdout io.ReadCloser
stderr io.ReadCloser
)
ticker := time.NewTicker(time.Second * 20)
cron:
for {
if cron.TimeToRun(time.Now()) {
cmd := exec.Command(cron.Command().Path())
if err := cmd.Run(); err != nil {
wingmate.Log().Error().Msgf("running cron %s error %#v", cron.Command().Path(), err)
iwg = &sync.WaitGroup{}
if stdout, err = cmd.StdoutPipe(); err != nil {
wingmate.Log().Error().Str(cronTag, cron.Command().Path()).Msgf("stdout pipe: %+v", err)
goto fail
}
if stderr, err = cmd.StderrPipe(); err != nil {
wingmate.Log().Error().Str(cronTag, cron.Command().Path()).Msgf("stderr pipe: %+v", err)
_ = stdout.Close()
goto fail
}
iwg.Add(1)
go i.pipeReader(iwg, stdout, cronTag, cron.Command().Path())
iwg.Add(1)
go i.pipeReader(iwg, stderr, cronTag, cron.Command().Path())
if err := cmd.Start(); err != nil {
wingmate.Log().Error().Msgf("starting cron %s error %+v", cron.Command().Path(), err)
_ = stdout.Close()
_ = stderr.Close()
iwg.Wait()
goto fail
}
iwg.Wait()
if err = cmd.Wait(); err != nil {
wingmate.Log().Error().Str(cronTag, cron.Command().Path()).Msgf("got error when waiting: %+v", err)
}
}
fail:
select {
case <-exitFlag:
ticker.Stop()

View File

@ -29,9 +29,9 @@ func (i *Init) service(wg *sync.WaitGroup, path Path, exitFlag <-chan any) {
wingmate.Log().Info().Str(serviceTag, path.Path()).Msg("stopped")
}()
failStatus = false
service:
for {
failStatus = false
cmd := exec.Command(path.Path())
iwg = &sync.WaitGroup{}
@ -41,7 +41,7 @@ service:
goto fail
}
iwg.Add(1)
go i.pipeReader(iwg, stdout, path.Path())
go i.pipeReader(iwg, stdout, serviceTag, path.Path())
if stderr, err = cmd.StderrPipe(); err != nil {
wingmate.Log().Error().Str(serviceTag, path.Path()).Msgf("stderr pipe: %#v", err)
@ -50,11 +50,14 @@ service:
goto fail
}
iwg.Add(1)
go i.pipeReader(iwg, stderr, path.Path())
go i.pipeReader(iwg, stderr, serviceTag, path.Path())
if err = cmd.Start(); err != nil {
wingmate.Log().Error().Msgf("starting service %s error %#v", path.Path(), err)
failStatus = true
_ = stdout.Close()
_ = stderr.Close()
iwg.Wait()
goto fail
}
@ -77,17 +80,17 @@ service:
}
func (i *Init) pipeReader(wg *sync.WaitGroup, pipe io.ReadCloser, serviceName string) {
func (i *Init) pipeReader(wg *sync.WaitGroup, pipe io.ReadCloser, tag, serviceName string) {
defer wg.Done()
scanner := bufio.NewScanner(pipe)
for scanner.Scan() {
wingmate.Log().Info().Str(serviceTag, serviceName).Msg(scanner.Text())
wingmate.Log().Info().Str(tag, serviceName).Msg(scanner.Text())
}
if err := scanner.Err(); err != nil {
wingmate.Log().Error().Str(serviceTag, serviceName).Msgf("got error when reading pipe: %#v", err)
wingmate.Log().Error().Str(tag, serviceName).Msgf("got error when reading pipe: %#v", err)
}
wingmate.Log().Info().Str(serviceTag, serviceName).Msg("closing pipe")
wingmate.Log().Info().Str(tag, serviceName).Msg("closing pipe")
}

View File

@ -27,11 +27,13 @@ func (i *Init) waiter(wg *sync.WaitGroup, runningFlag <-chan any, sigHandlerFlag
flagged = true
wait:
for {
select {
case <-runningFlag:
wingmate.Log().Info().Msg("waiter received shutdown signal...")
running = false
default:
if running {
select {
case <-runningFlag:
wingmate.Log().Info().Msg("waiter received shutdown signal...")
running = false
default:
}
}
if _, err = unix.Wait4(-1, &ws, 0, nil); err != nil {