mirror of https://github.com/hak5/overseer.git
use bin dir as tmp dir for next binary, copy owner
parent
0de2aea26b
commit
29e33ed1c7
|
@ -110,12 +110,12 @@ app#3 (286848c2aefcd3f7321a65b5e4efae987fb17911) exiting...
|
||||||
1. Then run it with:
|
1. Then run it with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
#run app inside alpine linux (5MB linux distro)
|
docker run -d -v /path/on/docker/host/myapp/:/home/ -w /home/ debian -w /home/app
|
||||||
docker run -d -v /path/on/docker/host/myapp/:/home/ -w /home/ alpine -w /home/app
|
|
||||||
```
|
```
|
||||||
|
|
||||||
1. For testing, swap out `-d` (daemonize) for `--rm -it` (remove on exit, input, terminal)
|
1. For testing, swap out `-d` (daemonize) for `--rm -it` (remove on exit, input, terminal)
|
||||||
1. `app` can use the current working directory as storage
|
1. `app` can use the current working directory as storage
|
||||||
|
1. `debian` doesn't ship with TLS certs, you can mount them in with `-v /etc/ssl/certs/ca-certificates.crt:/etc/ssl/certs/ca-certificates.crt`
|
||||||
|
|
||||||
### Alternatives
|
### Alternatives
|
||||||
|
|
||||||
|
@ -124,8 +124,8 @@ app#3 (286848c2aefcd3f7321a65b5e4efae987fb17911) exiting...
|
||||||
|
|
||||||
### TODO
|
### TODO
|
||||||
|
|
||||||
* Github fetcher (given a repo)
|
* Log levels
|
||||||
* S3 fetcher (given a bucket and credentials)
|
* Github fetcher (given a repo, poll releases)
|
||||||
* etcd fetcher (given a cluster, watch key)
|
* etcd fetcher (given a cluster, watch key)
|
||||||
* `overseer` CLI tool ([TODO](cmd/overseer/TODO.md))
|
* `overseer` CLI tool ([TODO](cmd/overseer/TODO.md))
|
||||||
* `overseer` package
|
* `overseer` package
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jpillora/overseer"
|
"github.com/jpillora/overseer"
|
||||||
|
"github.com/jpillora/overseer/fetcher"
|
||||||
)
|
)
|
||||||
|
|
||||||
//see example.sh for the use-case
|
//see example.sh for the use-case
|
||||||
|
@ -32,9 +33,9 @@ func main() {
|
||||||
Log: true, //display log of overseer actions
|
Log: true, //display log of overseer actions
|
||||||
Program: prog,
|
Program: prog,
|
||||||
Address: ":5001",
|
Address: ":5001",
|
||||||
// Fetcher: &fetcher.HTTP{
|
Fetcher: &fetcher.HTTP{
|
||||||
// URL: "http://localhost:5002/myappnew",
|
URL: "http://localhost:5002/myappnew",
|
||||||
// Interval: 1 * time.Second,
|
Interval: 1 * time.Second,
|
||||||
// },
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,14 +21,14 @@ import (
|
||||||
"github.com/kardianos/osext"
|
"github.com/kardianos/osext"
|
||||||
)
|
)
|
||||||
|
|
||||||
var tmpBinPath = filepath.Join(os.TempDir(), "overseer")
|
var tmpBinPath = filepath.Join(os.TempDir(), "overseer-"+token())
|
||||||
|
|
||||||
//a overseer master process
|
//a overseer master process
|
||||||
type master struct {
|
type master struct {
|
||||||
Config
|
Config
|
||||||
slaveCmd *exec.Cmd
|
slaveCmd *exec.Cmd
|
||||||
slaveExtraFiles []*os.File
|
slaveExtraFiles []*os.File
|
||||||
binPath string
|
binPath, tmpBinPath string
|
||||||
binPerms os.FileMode
|
binPerms os.FileMode
|
||||||
binHash []byte
|
binHash []byte
|
||||||
restartMux sync.Mutex
|
restartMux sync.Mutex
|
||||||
|
@ -90,12 +90,11 @@ func (mp *master) checkBinary() error {
|
||||||
io.Copy(hash, f)
|
io.Copy(hash, f)
|
||||||
mp.binHash = hash.Sum(nil)
|
mp.binHash = hash.Sum(nil)
|
||||||
f.Close()
|
f.Close()
|
||||||
//tmp path
|
//test bin<->tmpbin moves
|
||||||
tmpPath := mp.binPath + ".tmp"
|
if err := os.Rename(mp.binPath, tmpBinPath); err != nil {
|
||||||
if err := os.Rename(mp.binPath, tmpPath); err != nil {
|
|
||||||
return fmt.Errorf("cannot move binary (%s)", err)
|
return fmt.Errorf("cannot move binary (%s)", err)
|
||||||
}
|
}
|
||||||
if err := os.Rename(tmpPath, mp.binPath); err != nil {
|
if err := os.Rename(tmpBinPath, mp.binPath); err != nil {
|
||||||
return fmt.Errorf("cannot move binary back (%s)", err)
|
return fmt.Errorf("cannot move binary back (%s)", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -195,6 +194,7 @@ func (mp *master) fetch() {
|
||||||
if mp.restarting {
|
if mp.restarting {
|
||||||
return //skip if restarting
|
return //skip if restarting
|
||||||
}
|
}
|
||||||
|
|
||||||
mp.logf("checking for updates...")
|
mp.logf("checking for updates...")
|
||||||
reader, err := mp.Fetcher.Fetch()
|
reader, err := mp.Fetcher.Fetch()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -205,19 +205,20 @@ func (mp *master) fetch() {
|
||||||
mp.logf("no updates")
|
mp.logf("no updates")
|
||||||
return //fetcher has explicitly said there are no updates
|
return //fetcher has explicitly said there are no updates
|
||||||
}
|
}
|
||||||
|
mp.logf("streaming update...")
|
||||||
//optional closer
|
//optional closer
|
||||||
if closer, ok := reader.(io.Closer); ok {
|
if closer, ok := reader.(io.Closer); ok {
|
||||||
defer closer.Close()
|
defer closer.Close()
|
||||||
}
|
}
|
||||||
tmpBin, err := os.Create(tmpBinPath)
|
tmpBin, err := os.OpenFile(tmpBinPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mp.logf("failed to open temp binary: %s", err)
|
mp.logf("failed to open temp binary: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() {
|
// defer func() {
|
||||||
tmpBin.Close()
|
// tmpBin.Close()
|
||||||
os.Remove(tmpBinPath)
|
// os.Remove(tmpBinPath)
|
||||||
}()
|
// }()
|
||||||
//tee off to sha1
|
//tee off to sha1
|
||||||
hash := sha1.New()
|
hash := sha1.New()
|
||||||
reader = io.TeeReader(reader, hash)
|
reader = io.TeeReader(reader, hash)
|
||||||
|
@ -235,20 +236,30 @@ func (mp *master) fetch() {
|
||||||
}
|
}
|
||||||
//copy permissions
|
//copy permissions
|
||||||
if err := tmpBin.Chmod(mp.binPerms); err != nil {
|
if err := tmpBin.Chmod(mp.binPerms); err != nil {
|
||||||
mp.logf("failed to make binary executable: %s", err)
|
mp.logf("failed to make temp binary executable: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := tmpBin.Chown(uid, gid); err != nil {
|
||||||
|
mp.logf("failed to change owner of binary: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err := tmpBin.Stat(); err != nil {
|
||||||
|
mp.logf("failed to stat temp binary: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tmpBin.Close()
|
tmpBin.Close()
|
||||||
|
if _, err := os.Stat(tmpBinPath); err != nil {
|
||||||
|
mp.logf("failed to stat temp binary by path: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
if mp.Config.PreUpgrade != nil {
|
if mp.Config.PreUpgrade != nil {
|
||||||
if err := mp.Config.PreUpgrade(tmpBinPath); err != nil {
|
if err := mp.Config.PreUpgrade(tmpBinPath); err != nil {
|
||||||
mp.logf("user cancelled upgrade: %s", err)
|
mp.logf("user cancelled upgrade: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//overseer sanity check, dont replace our good binary with a text file
|
//overseer sanity check, dont replace our good binary with a non-executable file
|
||||||
buff := make([]byte, 8)
|
tokenIn := token()
|
||||||
rand.Read(buff)
|
|
||||||
tokenIn := hex.EncodeToString(buff)
|
|
||||||
cmd := exec.Command(tmpBinPath)
|
cmd := exec.Command(tmpBinPath)
|
||||||
cmd.Env = []string{envBinCheck + "=" + tokenIn}
|
cmd.Env = []string{envBinCheck + "=" + tokenIn}
|
||||||
tokenOut, err := cmd.Output()
|
tokenOut, err := cmd.Output()
|
||||||
|
@ -261,7 +272,7 @@ func (mp *master) fetch() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//overwrite!
|
//overwrite!
|
||||||
if err := move(mp.binPath, tmpBinPath); err != nil {
|
if err := os.Rename(tmpBinPath, mp.binPath); err != nil {
|
||||||
mp.logf("failed to overwrite binary: %s", err)
|
mp.logf("failed to overwrite binary: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -372,3 +383,9 @@ func (mp *master) logf(f string, args ...interface{}) {
|
||||||
log.Printf("[overseer master] "+f, args...)
|
log.Printf("[overseer master] "+f, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func token() string {
|
||||||
|
buff := make([]byte, 8)
|
||||||
|
rand.Read(buff)
|
||||||
|
return hex.EncodeToString(buff)
|
||||||
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
const supported = true
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
supported = true
|
||||||
|
uid = syscall.Getuid()
|
||||||
|
gid = syscall.Getgid()
|
||||||
SIGUSR1 = syscall.SIGUSR1
|
SIGUSR1 = syscall.SIGUSR1
|
||||||
SIGUSR2 = syscall.SIGUSR2
|
SIGUSR2 = syscall.SIGUSR2
|
||||||
SIGTERM = syscall.SIGTERM
|
SIGTERM = syscall.SIGTERM
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
|
|
||||||
package overseer
|
package overseer
|
||||||
|
|
||||||
const supported = false
|
var supported = false
|
||||||
|
|
Loading…
Reference in New Issue