dunno
This commit is contained in:
16
client/README
Executable file
16
client/README
Executable file
@@ -0,0 +1,16 @@
|
||||
* watch for file changes
|
||||
https://github.com/fsnotify/fsnotify
|
||||
https://medium.com/@skdomino/watch-this-file-watching-in-go-5b5a247cf71f
|
||||
|
||||
* fault tolerant
|
||||
https://github.com/klauspost/reedsolomon
|
||||
|
||||
* minio for backup to GCP/AWS/Other
|
||||
or just drive
|
||||
pref minio for fun
|
||||
|
||||
* encryption somehow
|
||||
allow encrypt/decrypt anywhere
|
||||
can restore with little to nothing
|
||||
local/encrypter can encrypt/decrypt given access to pub/pri keys
|
||||
symmetrical encrypt?
|
||||
146
client/main.go
Executable file
146
client/main.go
Executable file
@@ -0,0 +1,146 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"local/watchman/client/remote"
|
||||
"local/watchman/client/watchman"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
)
|
||||
|
||||
func envOrDefault(key, alt string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
log.Printf("ENV variable %q not set, defaulting to %q", key, alt)
|
||||
return alt
|
||||
}
|
||||
|
||||
var defaultKey = envOrDefault("WATCHMANKEY", "key")
|
||||
var defaultID = envOrDefault("WATCHMANID", "ID")
|
||||
|
||||
type empty struct{}
|
||||
|
||||
func catchInterrupt() chan os.Signal {
|
||||
stop := make(chan os.Signal)
|
||||
signal.Notify(stop, os.Interrupt)
|
||||
return stop
|
||||
}
|
||||
|
||||
func main() {
|
||||
stopWatch := make(chan empty)
|
||||
fnames := make(chan string)
|
||||
packs := make(chan *watchman.Package)
|
||||
|
||||
pullPath := flag.String("path", "", "path to pull")
|
||||
flag.Parse()
|
||||
if *pullPath != "" {
|
||||
go packPuller(packs, stopWatch)
|
||||
packs <- &watchman.Package{Path: *pullPath}
|
||||
stopWatch <- empty{}
|
||||
return
|
||||
}
|
||||
|
||||
log.Print("Watching for changes...")
|
||||
go watchFiles("testdir", fnames, stopWatch)
|
||||
|
||||
log.Print("Packing changes...")
|
||||
go filePacker(packs, fnames, stopWatch)
|
||||
|
||||
log.Print("Pushing changes...")
|
||||
go packPusher(packs, stopWatch)
|
||||
|
||||
log.Print("Waiting for signal...")
|
||||
<-catchInterrupt()
|
||||
for i := 0; i < 3; i++ {
|
||||
stopWatch <- empty{}
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
log.Print("Exiting")
|
||||
}
|
||||
|
||||
func packPuller(packs <-chan *watchman.Package, stop <-chan empty) {
|
||||
rem, err := remote.New()
|
||||
if err != nil {
|
||||
log.Fatal("can't connect to remote:", err)
|
||||
}
|
||||
exiting := false
|
||||
for !exiting {
|
||||
select {
|
||||
case pack := <-packs:
|
||||
pack.ID = defaultID
|
||||
backpack, err := rem.Pull(pack)
|
||||
if err != nil {
|
||||
log.Print("error pulling:", err)
|
||||
break
|
||||
}
|
||||
if backpack == nil {
|
||||
break
|
||||
}
|
||||
decrypted, err := watchman.UnpackNDecrypt(backpack, defaultKey)
|
||||
if err != nil {
|
||||
log.Print("error unpacking and decrypting:", err)
|
||||
break
|
||||
}
|
||||
log.Print(string(decrypted))
|
||||
case <-stop:
|
||||
exiting = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func packPusher(packs <-chan *watchman.Package, stop <-chan empty) {
|
||||
rem, err := remote.New()
|
||||
if err != nil {
|
||||
log.Fatal("can't connect to remote:", err)
|
||||
}
|
||||
exiting := false
|
||||
for !exiting {
|
||||
select {
|
||||
case pack := <-packs:
|
||||
if err := rem.Push(pack); err != nil {
|
||||
log.Print("error pushing:", err)
|
||||
}
|
||||
case <-stop:
|
||||
exiting = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func filePacker(packs chan<- *watchman.Package, fnames <-chan string, stop <-chan empty) {
|
||||
exiting := false
|
||||
for !exiting {
|
||||
select {
|
||||
case fname := <-fnames:
|
||||
pack, err := watchman.EncryptNPack(fname, defaultKey, defaultID)
|
||||
if err != nil {
|
||||
log.Printf("err packingNencrypting file %q: %v", fname, err)
|
||||
break
|
||||
}
|
||||
packs <- pack
|
||||
case <-stop:
|
||||
exiting = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func watchFiles(path string, fnames chan<- string, stop <-chan empty) {
|
||||
watcher := watchman.NewWatcher(path)
|
||||
if err := watcher.Start(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
exiting := false
|
||||
for !exiting {
|
||||
select {
|
||||
case fname := <-watcher.Files:
|
||||
fnames <- fname
|
||||
case <-stop:
|
||||
exiting = true
|
||||
watcher.Stop()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
95
client/remote/remote.go
Executable file
95
client/remote/remote.go
Executable file
@@ -0,0 +1,95 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"local/encryptor"
|
||||
"local/system/sysconf"
|
||||
"local/watchman/client/watchman"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Remote struct {
|
||||
enc encryptor.Encryptor
|
||||
client *http.Client
|
||||
url string
|
||||
}
|
||||
|
||||
func New() (*Remote, error) {
|
||||
r := &Remote{
|
||||
url: "https://localhost:" + strings.Split(sysconf.Get("watchmans").Port, ",")[1],
|
||||
client: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
},
|
||||
enc: encryptor.NewEncryptor("", ""),
|
||||
}
|
||||
body, err := r.request("getpub", sysconf.Get("watchmans").Name)
|
||||
if err != nil {
|
||||
return nil, errors.New("can't contact watchmans")
|
||||
}
|
||||
r.enc.SetPublic(string(body))
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *Remote) request(path string, body string) ([]byte, error) {
|
||||
req, err := http.NewRequest("GET", fmt.Sprintf("%v/%v", r.url, path), bytes.NewBuffer([]byte(body)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := r.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New("error when accessing " + path + ": http status " + resp.Status)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return ioutil.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
func (r *Remote) Push(pack *watchman.Package) error {
|
||||
b, err := json.Marshal(pack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
encrypted := r.enc.Encrypt(string(b))
|
||||
_, err = r.request("push", encrypted)
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *Remote) Pull(pack *watchman.Package) (*watchman.Package, error) {
|
||||
transactionKey := encryptor.NewEncryptor("", "").GetPublic()
|
||||
transactionKey = transactionKey[len(transactionKey)/2:]
|
||||
transactionKey = transactionKey[:20]
|
||||
pack.Packs = [][]byte{[]byte(encryptor.NewEncryptor("", "").GetPublic())}
|
||||
dec := encryptor.NewEncryptor("", "")
|
||||
dec.SetSymmetric(string(pack.Packs[0]))
|
||||
b, err := json.Marshal(pack)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
encrypted := r.enc.Encrypt(string(b))
|
||||
var ret watchman.Package
|
||||
b, err = r.request("pull", encrypted)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = []byte(dec.Decrypt(string(b)))
|
||||
if err := json.Unmarshal(b, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
32
client/remote/remote_test.go
Executable file
32
client/remote/remote_test.go
Executable file
@@ -0,0 +1,32 @@
|
||||
package remote
|
||||
|
||||
import (
|
||||
"local/watchman/client/watchman"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPush(t *testing.T) {
|
||||
r := New()
|
||||
cases := []struct {
|
||||
pack *watchman.Package
|
||||
}{}
|
||||
for _, c := range cases {
|
||||
err := r.Push(c.pack)
|
||||
if err != nil {
|
||||
t.Fatalf("error pushing test pack: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPull(t *testing.T) {
|
||||
r := New()
|
||||
cases := []struct {
|
||||
name string
|
||||
}{}
|
||||
for _, c := range cases {
|
||||
_, err := r.Pull(c.name)
|
||||
if err != nil {
|
||||
t.Fatalf("error pulling test pack: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user