From 5b599f85ce2fa114629074e394c63a4898c488bc Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Wed, 21 Aug 2024 12:38:12 +0200 Subject: [PATCH 1/4] dockerfile: fix syntax Signed-off-by: Javier Lopez --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 151d638..3b131d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22-bookworm as builder +FROM golang:1.22-bookworm AS builder WORKDIR /app From ad4662d824b827e9b7776caa1b5fb2036c57a119 Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Wed, 21 Aug 2024 12:38:34 +0200 Subject: [PATCH 2/4] refactor: make manifest v2 syntax Signed-off-by: Javier Lopez --- okteto.yml | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/okteto.yml b/okteto.yml index 32d344e..919373f 100644 --- a/okteto.yml +++ b/okteto.yml @@ -1,17 +1,23 @@ -name: supervisor -image: okteto/golang:1 -command: -- bash -workdir: /okteto -volumes: -- /go/pkg/ -- /root/.cache/go-build/ -securityContext: - capabilities: - add: - - SYS_PTRACE -forward: -- 8080:8080 -- 2345:2345 -persistentVolume: - enabled: true \ No newline at end of file +build: + supervisor: + context: . + image: ${REGISTRY_AND_USER:-okteto}/supervisor:${VERSION:-latest} +dev: + supervisor: + image: okteto/golang:1 + command: + - bash + workdir: /okteto + volumes: + - /go/pkg/ + - /root/.cache/go-build/ + securityContext: + capabilities: + add: + - SYS_PTRACE + forward: + - 8080:8080 + - 2345:2345 + persistentVolume: + enabled: true + autocreate: true \ No newline at end of file From 75bab0b25dac245c7630c4971cd529c5f018555f Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Wed, 21 Aug 2024 12:38:54 +0200 Subject: [PATCH 3/4] copy files before starting syncthing Signed-off-by: Javier Lopez --- cmd/main.go | 18 ++++++++++-- go.mod | 4 ++- go.sum | 8 ++++-- pkg/monitor/monitor.go | 58 ++++++++++++++++++++++++++++++++------ pkg/monitor/process.go | 2 ++ pkg/setup/copy.go | 60 ++++++++++++++++++++++++++++++++++++++++ pkg/setup/permissions.go | 28 +++++++++++++++++++ pkg/setup/setup.go | 16 +++++++++++ 8 files changed, 180 insertions(+), 14 deletions(-) create mode 100644 pkg/setup/copy.go create mode 100644 pkg/setup/permissions.go create mode 100644 pkg/setup/setup.go diff --git a/cmd/main.go b/cmd/main.go index 97e06de..9afd3ce 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/okteto/supervisor/pkg/monitor" + "github.com/okteto/supervisor/pkg/setup" reaper "github.com/ramr/go-reaper" log "github.com/sirupsen/logrus" ) @@ -16,6 +17,12 @@ import ( // CommitString is the commit used to build the server var CommitString string +const ( + defaultSyncthingData = "/var/syncthing/data" + defaultSyncthingConfig = "/var/syncthing" + defaultSyncthingSecret = "/var/syncthing/secret" +) + func main() { log.WithField("commit", CommitString).Infof("supervisor started") @@ -25,6 +32,7 @@ func main() { remoteFlag := flag.Bool("remote", false, "start the remote server") resetFlag := flag.Bool("reset", false, "reset syncthing database") verboseFlag := flag.Bool("verbose", true, "syncthing verbosity") + flag.Parse() ctx, cancel := context.WithCancel(context.Background()) @@ -36,16 +44,20 @@ func main() { }() if *resetFlag { - cmd := exec.Command(monitor.SyncthingBin, "-home", "/var/syncthing", "-reset-database") + if err := setup.Setup(defaultSyncthingSecret, defaultSyncthingConfig); err != nil { + log.WithError(err).Error("error setting up syncthing") + os.Exit(1) + } + cmd := exec.Command(monitor.SyncthingBin, "-config", defaultSyncthingConfig, "-data", defaultSyncthingData, "-reset-database") output, err := cmd.CombinedOutput() if err != nil { log.WithError(err).Errorf("error resetting syncthing database: %s", output) } } - m := monitor.NewMonitor(ctx) + m := monitor.NewMonitor(ctx, monitor.NewSyncthingConfig(defaultSyncthingConfig, defaultSyncthingSecret, defaultSyncthingData)) - syncthingArgs := []string{"-home", "/var/syncthing", "-gui-address", "0.0.0.0:8384"} + syncthingArgs := []string{"-config", defaultSyncthingConfig, "-data", defaultSyncthingData, "-gui-address", "0.0.0.0:8384"} if *verboseFlag { syncthingArgs = append(syncthingArgs, "-verbose") } diff --git a/go.mod b/go.mod index 94ebaf9..b08b5b6 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/ramr/go-reaper v0.2.0 github.com/shirou/gopsutil v3.21.11+incompatible github.com/sirupsen/logrus v1.4.2 + github.com/spf13/afero v1.11.0 ) require ( @@ -15,5 +16,6 @@ require ( github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index 4719732..4589137 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,8 @@ github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKl github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -28,5 +30,7 @@ github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= diff --git a/pkg/monitor/monitor.go b/pkg/monitor/monitor.go index 03949f6..fdf2e42 100644 --- a/pkg/monitor/monitor.go +++ b/pkg/monitor/monitor.go @@ -7,21 +7,40 @@ import ( "sync" "time" + "github.com/okteto/supervisor/pkg/setup" log "github.com/sirupsen/logrus" ) // Monitor makes sure the list of processes is running type Monitor struct { - ps []*Process - err chan error - ctx context.Context + ps []*Process + err chan error + ctx context.Context + syncthingConfig SyncthingConfig +} + +// SyncthingConfig represents the syncthing configuration +type SyncthingConfig struct { + config string + data string + secret string +} + +// NewSyncthingConfig returns a new syncthing config +func NewSyncthingConfig(config, secret, data string) SyncthingConfig { + return SyncthingConfig{ + config: config, + data: data, + secret: secret, + } } // NewMonitor returns an initialized monitor -func NewMonitor(ctx context.Context) *Monitor { +func NewMonitor(ctx context.Context, syncthingConfig SyncthingConfig) *Monitor { return &Monitor{ - ctx: ctx, - err: make(chan error, 1), + ctx: ctx, + err: make(chan error, 1), + syncthingConfig: syncthingConfig, } } @@ -69,10 +88,19 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { defer wg.Done() switch p.state { case neverStarted: - log.Infof("starting %s for the first time", p.Name) + p.logger.Printf("starting %s for the first time", p.Name) + if p.Path == SyncthingBin { + if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { + p.logger.Errorf("failed to setup %s: %w", p.Name, err) + m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) + return + } + } p.start() + p.logger.Printf("%s started 1", p.Name) case stopped: if !p.shouldStart() { + log.Errorf("%s started %d times", p.Name, p.startCount) m.err <- fmt.Errorf("%s started %d times", p.Name, p.startCount) return } @@ -80,7 +108,15 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { p.killAllByName() log.Infof("Restarting process %s", p.Name) + if p.Path == SyncthingBin { + if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { + p.logger.Printf("failed to setup %s: %w", p.Name, err) + m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) + return + } + } p.start() + p.logger.Printf("%s started 2", p.Name) case fatal: if !p.shouldStart() { m.err <- fmt.Errorf("%s started %d times", p.Name, p.startCount) @@ -91,7 +127,12 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { if p.Path == SyncthingBin { log.Info("Resetting syncthing database after error...") - cmd := exec.Command(SyncthingBin, "-home", "/var/syncthing", "-reset-database") + if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { + p.logger.Errorf("failed to setup %s: %w", p.Name, err) + m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) + return + } + cmd := exec.Command(SyncthingBin, "-config", m.syncthingConfig.config, "-data", m.syncthingConfig.data, "-reset-database") output, err := cmd.CombinedOutput() if err != nil { log.WithError(err).Errorf("error resetting syncthing database: %s", output) @@ -102,6 +143,7 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { log.Errorf("Restarting process %s after failure", p.Name) p.start() + p.logger.Printf("%s started 3", p.Name) case started: //do nothing default: diff --git a/pkg/monitor/process.go b/pkg/monitor/process.go index 58ef2d3..d7f1e1a 100644 --- a/pkg/monitor/process.go +++ b/pkg/monitor/process.go @@ -120,7 +120,9 @@ func (p *Process) shouldStart() bool { } func (p *Process) monitor() { + p.logger.Infof("monitoring process %s", p.Name) <-p.cmd.Done() + p.logger.Infof("process %s done", p.Name) if p.state == stopping { return } diff --git a/pkg/setup/copy.go b/pkg/setup/copy.go new file mode 100644 index 0000000..1c47b26 --- /dev/null +++ b/pkg/setup/copy.go @@ -0,0 +1,60 @@ +package setup + +import ( + "errors" + "fmt" + "log" + "os" + "os/exec" + "path/filepath" +) + +func copy(src, dst string) error { + log.Default().Printf("copying %s to %s", src, dst) + + fs, err := os.Stat(dst) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + if err := os.MkdirAll(dst, 0755); err != nil { + return fmt.Errorf("failed to create directory: %w", err) + } + } else { + return fmt.Errorf("failed to get file info: %w", err) + } + } + if !fs.IsDir() { + return fmt.Errorf("source is not a directory: %s", dst) + } + + files := []string{ + "cert.pem", + "config.xml", + "key.pem", + } + for _, file := range files { + src := filepath.Join(src, file) + dst := filepath.Join(dst, file) + if _, err := os.Stat(dst); err == nil { + log.Default().Printf("file already exists: %s", dst) + continue + } + log.Default().Printf("copying %s to %s", src, dst) + err := runCommand("cp", src, dst) + if err != nil { + return fmt.Errorf("failed to copy files: %w", err) + } + } + return nil +} + +func runCommand(name string, args ...string) error { + cmd := exec.Command(name, args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + log.Default().Printf("running command: %s", cmd.String()) + if err := cmd.Run(); err != nil { + return fmt.Errorf("failed to run command: %w", err) + } + log.Default().Printf("command executed correctly: %s", cmd.String()) + return nil +} diff --git a/pkg/setup/permissions.go b/pkg/setup/permissions.go new file mode 100644 index 0000000..635ac64 --- /dev/null +++ b/pkg/setup/permissions.go @@ -0,0 +1,28 @@ +package setup + +import ( + "fmt" + "log" + "os" + "path/filepath" +) + +func addPermissions(configPath string) error { + // Define the files to set permissions + files := []string{ + filepath.Join(configPath, "cert.pem"), + filepath.Join(configPath, "config.xml"), + filepath.Join(configPath, "key.pem"), + } + + // Set the permissions to 644 + for _, file := range files { + log.Default().Printf("setting permissions to 644 for %s", file) + err := os.Chmod(file, 0644) + if err != nil { + return fmt.Errorf("failed to change permissions for %s: %w", file, err) + } + log.Default().Printf("permissions set to 644 for %s", file) + } + return nil +} diff --git a/pkg/setup/setup.go b/pkg/setup/setup.go new file mode 100644 index 0000000..3bec4e7 --- /dev/null +++ b/pkg/setup/setup.go @@ -0,0 +1,16 @@ +package setup + +import "log" + +func Setup(secretPath, configPath string) error { + log.Default().Printf("starting setup") + if err := copy(secretPath, configPath); err != nil { + return err + } + log.Default().Printf("copy done") + if err := addPermissions(configPath); err != nil { + return err + } + log.Default().Printf("permissions done") + return nil +} From 4d9ad43321253cb9de451bb7d496403cad71646c Mon Sep 17 00:00:00 2001 From: Javier Lopez Date: Fri, 23 Aug 2024 12:01:47 +0200 Subject: [PATCH 4/4] fix: linter Signed-off-by: Javier Lopez --- pkg/monitor/monitor.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/monitor/monitor.go b/pkg/monitor/monitor.go index fdf2e42..524ae16 100644 --- a/pkg/monitor/monitor.go +++ b/pkg/monitor/monitor.go @@ -91,7 +91,7 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { p.logger.Printf("starting %s for the first time", p.Name) if p.Path == SyncthingBin { if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { - p.logger.Errorf("failed to setup %s: %w", p.Name, err) + p.logger.Errorf("failed to setup %s: %s", p.Name, err.Error()) m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) return } @@ -110,7 +110,7 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { log.Infof("Restarting process %s", p.Name) if p.Path == SyncthingBin { if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { - p.logger.Printf("failed to setup %s: %w", p.Name, err) + p.logger.Printf("failed to setup %s: %s", p.Name, err.Error()) m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) return } @@ -128,7 +128,7 @@ func (m *Monitor) checkState(p *Process, wg *sync.WaitGroup) { if p.Path == SyncthingBin { log.Info("Resetting syncthing database after error...") if err := setup.Setup(m.syncthingConfig.secret, m.syncthingConfig.config); err != nil { - p.logger.Errorf("failed to setup %s: %w", p.Name, err) + p.logger.Errorf("failed to setup %s: %s", p.Name, err.Error()) m.err <- fmt.Errorf("failed to setup %s: %w", p.Name, err) return }