예제 #1
0
func (r *RawClient) UpdatePort(port int) error {
	req, tag := newRequest("session-set",
		"peer-port", port,
		"port-forwarding-enabled", true,
		"peer-port-random-on-start", false,
	)

	logger.Debugf("Encoding %v", req)
	body, er := json.Marshal(req)
	if er != nil {
		return er
	}
	logger.Debugf("Requesting transmission peer port update to %d", port)
	out, er := r.Post(string(body))
	if er != nil {
		return er
	}

	response := new(response)
	if er := json.Unmarshal(out, response); er != nil {
		return er
	}
	if response.Tag != tag {
		return errors.New("Request and response tags do not match")
	}
	if response.Result != "success" {
		return errors.New(response.Result)
	}
	logger.Infof("Peer port updated to %d", port)
	return nil
}
예제 #2
0
func (v *vulcan) GetBackend(backendID string) (loadbalancer.Backend, error) {
	logger.Debugf("Lookup Backend: %q", backendID)
	b, er := v.Client.GetBackend(engine.BackendKey{Id: backendID})
	if er != nil {
		logger.Debugf("Lookup failed: %v", er)
		return nil, er
	}
	return newBackend(b), nil
}
예제 #3
0
func addResources(e *Engine, resources kubernetes.ResourceList) error {
	backends := make([]loadbalancer.Backend, 0, len(resources))
	frontends := make([]loadbalancer.Frontend, 0, len(resources))
	for _, rsc := range resources {
		logger.Debugf("[%v] Build Frontends and Backends", rsc.ID())
		backend, er := e.NewBackend(rsc)
		if er != nil {
			return er
		}
		srvs, er := e.NewServers(rsc)
		if er != nil {
			return er
		}
		for i := range srvs {
			backend.AddServer(srvs[i])
		}
		logger.Debugf("[%v] Created new object: %v", rsc.ID(), backend)
		backends = append(backends, backend)

		frontend, er := e.NewFrontend(rsc)
		if er != nil {
			return er
		}
		mids, er := e.NewMiddlewares(rsc)
		if er != nil {
			return er
		}
		for i := range mids {
			frontend.AddMiddleware(mids[i])
		}
		frontends = append(frontends, frontend)
		logger.Debugf("[%v] Created new object: %v", rsc.ID(), frontend)
	}

	return e.Commit(func() error {
		for _, backend := range backends {
			logger.Infof("Upserting %v", backend)
			if er := e.UpsertBackend(backend); er != nil {
				return er
			}
		}
		for _, frontend := range frontends {
			logger.Infof("Upserting %v", frontend)
			if er := e.UpsertFrontend(frontend); er != nil {
				return er
			}
		}
		return nil
	})
}
예제 #4
0
func (c *Client) CleanTorrents() error {
	logger.Infof("Running torrent cleaner")
	torrents, er := c.GetTorrents()
	if er != nil {
		return er
	}

	torrents.SortByID(false)
	logger.Infof("Found %d torrents to process", len(torrents))
	for _, t := range torrents {
		logger.Debugf("[Torrent %d: %q] Checking status", t.ID, t.Name)
		id := util.Hashf(md5.New(), t.ID, t.Name)
		status := &torrentStatus{Torrent: t, id: id, failures: 0}
		status.setFailures()

		if st, ok := seen[id]; ok {
			status.failures = status.failures + st.failures
			if !updated(st.Torrent, status.Torrent) {
				status.failures++
			}
		}

		seen[id] = status
		logger.Debugf("[Torrent %d: %q] Failures: %d", t.ID, t.Name, status.failures)
	}

	b := backoff.NewExponentialBackOff()
	b.MaxElapsedTime = 15 * time.Second
	remove := make([]*torrentStatus, 0, 1)
	for _, t := range seen {
		if t.failed() {
			b.Reset()
			logger.Infof("[Torrent %d: %q] Removing", t.ID, t.Name)
			er := backoff.RetryNotify(delTorrent(c, t.Torrent), b, func(e error, w time.Duration) {
				logger.Errorf("[Torrent %d: %q] Failed to remove (retry in %v): %v", t.ID, t.Name, w, e)
			})
			if er == nil {
				remove = append(remove, t)
			} else {
				logger.Errorf("[Torrent %d: %q] Failed to remove, will retry next cycle", t.ID, t.Name)
			}
		}
	}

	for i := range remove {
		delete(seen, remove[i].id)
	}
	return nil
}
예제 #5
0
func portUpdate(c *config.Config, ctx context.Context) error {
	ip, er := getIP(c.OpenVPN.Tun, c.Timeout.Duration, ctx)
	if er != nil || ctx.Err() != nil {
		return er
	}
	logger.Infof("New bind ip: (%s) %s", c.OpenVPN.Tun, ip)

	port, er := getPort(ip, c.PIA.User, c.PIA.Pass, c.PIA.ClientID, c.Timeout.Duration, ctx)
	if er != nil || ctx.Err() != nil {
		return er
	}

	logger.Infof("New peer port: %d", port)
	notify := func(e error, w time.Duration) {
		logger.Debugf("Failed to update transmission port: %v", er)
	}
	operation := func() error {
		select {
		default:
			return transmission.
				NewRawClient(c.Transmission.URL.String(), c.Transmission.User, c.Transmission.Pass).
				UpdatePort(port)
		case <-ctx.Done():
			return nil
		}
	}
	b := backoff.NewExponentialBackOff()
	b.MaxElapsedTime = c.Timeout.Duration
	return backoff.RetryNotify(operation, b, notify)
}
예제 #6
0
func (t *traefik) UpsertBackend(ba loadbalancer.Backend) error {
	b, ok := ba.(*backend)
	if !ok {
		return fmt.Errorf("Not of expected type: %v", ba)
	}

	pre := path.Join(t.prefix, "backends", ba.GetID())
	if b.CircuitBreaker != nil && b.CircuitBreaker.Expression != "" {
		if er := t.Set(path.Join(pre, cb), b.CircuitBreaker.Expression); er != nil {
			logger.Warnf("[%v] Upsert %s error: %v", ba.GetID(), cb, er)
		}
	}
	if b.LoadBalancer != nil && b.LoadBalancer.Method != "" {
		if er := t.Set(path.Join(pre, lb), b.LoadBalancer.Method); er != nil {
			logger.Warnf("[%v] Upsert %s error: %v", ba.GetID(), lb, er)
		}
	}

	for id, srv := range b.Servers {
		logger.Debugf("[%v] Upserting Server(%v)", ba.GetID(), srv.URL)
		urlK := path.Join(pre, "servers", id, "url")
		weightK := path.Join(pre, "servers", id, "weight")
		if er := t.Set(urlK, srv.URL); er != nil {
			logger.Warnf("[%v] Upsert error: %v", ba.GetID(), er)
		}
		weight := strconv.Itoa(srv.Weight)
		if er := t.Set(weightK, weight); er != nil {
			logger.Warnf("[%v] Upsert error: %v", ba.GetID(), er)
		}
	}
	return nil
}
예제 #7
0
func ReadAndWatch(file string, ctx context.Context) (*Config, error) {
	c, er := Read(file)
	if er != nil {
		return c, er
	}

	go func() {
		logger.Debugf("Watching for config changes: config=%q", file)
		t := time.NewTicker(5 * time.Second)
		defer t.Stop()

		for {
			select {
			case <-ctx.Done():
				return
			case <-t.C:
				if er, ok := c.update(); er == nil && ok {
					logger.Infof("Config updated")
				}
			}
		}
	}()

	return c, nil
}
예제 #8
0
func UpdateSettings(path, ip string, port int) error {
	logger.Infof("Updating transmission settings. bind-ip=%s port=%d", ip, port)
	data, er := ioutil.ReadFile(path)
	if er != nil {
		return er
	}

	s, er := simplejson.NewJson(data)
	if er != nil {
		return er
	}

	s.Set(bindKey, ip)
	s.Set(portKey, port)
	s.Set(forwardKey, true)
	s.Set(randomKey, false)

	data, er = s.Encode()
	if er != nil {
		return er
	}

	logger.Debugf("Writing updated transmission settings")
	info, _ := os.Stat(path)
	return ioutil.WriteFile(path, data, info.Mode().Perm())
}
예제 #9
0
func runShell(container, cache string, pull bool) error {
	cwd, er := os.Getwd()
	if er != nil {
		return er
	}

	var (
		cmd = buildClientCmd(cache)
		pa  = &os.ProcAttr{
			Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
			Dir:   cwd,
		}
	)

	cmd = append(cmd, "-ti", container, "bash")
	logger.Debugf("CMD: %v", cmd)
	if pull {
		doPull(container)
	}
	createCache(cache)
	p, er := os.StartProcess(cmd[0], cmd, pa)
	if er != nil {
		return er
	}
	_, er = p.Wait()
	return er
}
예제 #10
0
func (t *traefik) UpsertFrontend(fr loadbalancer.Frontend) error {
	f, ok := fr.(*frontend)
	if !ok {
		return fmt.Errorf("Not of expected type: %v", fr)
	}

	pre := path.Join(t.prefix, "frontends", fr.GetID())
	if er := t.Set(path.Join(pre, "backend"), f.Backend); er != nil {
		return fmt.Errorf("Upsert %v failed: %v", fr, er)
	}
	if f.PassHostHeader {
		if er := t.Set(path.Join(pre, phh), "true"); er != nil {
			logger.Warnf("[%v] Upsert %s error: %v", fr.GetID(), phh, er)
		}
	}

	for id, rt := range f.Routes {
		logger.Debugf("[%v] Adding Route(%s=%q)", fr.GetID(), rt.Rule, rt.Value)
		ruleK := path.Join(pre, "routes", id, "rule")
		valk := path.Join(pre, "routes", id, "value")
		if er := t.Set(ruleK, rt.Rule); er != nil {
			logger.Warnf("[%v] Upsert rule error: %v", fr.GetID(), er)
		}
		if er := t.Set(valk, rt.Value); er != nil {
			logger.Warnf("[%v] Upsert value error: %v", fr.GetID(), er)
		}
	}
	return nil
}
예제 #11
0
func (v *vulcan) NewMiddlewares(rsc *kubernetes.Resource) ([]loadbalancer.Middleware, error) {
	mids := make([]loadbalancer.Middleware, 0, 1)
	for key, def := range DefaultMiddleware {
		if val, ok := rsc.GetAnnotation(key); ok && len(val) > 0 {
			switch key {
			case RedirectSSLID:
				if b, er := strconv.ParseBool(val); er != nil || !b {
					continue
				}
			case TraceID:
				re := regexp.MustCompile(`\s+`)
				list, er := json.Marshal(strings.Split(re.ReplaceAllString(val, ""), ","))
				if er != nil || string(list) == "" {
					logger.Warnf("Unable to json-ify trace headers: %v", er)
					list = []byte("[]")
				}
				def = fmt.Sprintf(def, string(list), string(list))
			case AuthID:
				bits := strings.SplitN(val, ":", 2)
				switch len(bits) {
				case 1:
					def = fmt.Sprintf(def, bits[0], "")
				case 2:
					def = fmt.Sprintf(def, bits[0], bits[1])
				default:
					logger.Errorf("Failed to parse provided basic auth, using default (admin:admin)")
					def = fmt.Sprintf(def, "admin", "admin")
				}
			case MaintenanceID:
				def = fmt.Sprintf(def, val)
			}

			m, er := engine.MiddlewareFromJSON([]byte(def), v.Registry.GetSpec, key)
			if er != nil {
				logger.Warnf("Failed to parse Middleware %s: %v", key, er)
				logger.Debugf("%q", def)
				continue
			}
			mids = append(mids, newMiddleware(m))
		}
	}

	rg := regexp.MustCompile(CustomMiddlewareKeyPattern)
	matches, _ := rsc.GetAnnotations(CustomMiddlewareKeyPattern)
	for key, val := range matches {
		if match := rg.FindStringSubmatch(key); match != nil {
			id := match[1]
			m, er := engine.MiddlewareFromJSON([]byte(val), v.Registry.GetSpec, id)
			if er != nil {
				logger.Warnf("Failed to parse Middleware %s: %v", id, er)
				continue
			}
			mids = append(mids, newMiddleware(m))
		}
	}

	return mids, nil
}
예제 #12
0
func getListWatch(kind string, getter cache.Getter, selector labels.Selector) *cache.ListWatch {
	return &cache.ListWatch{
		ListFunc: func(options api.ListOptions) (runtime.Object, error) {
			logger.Debugf("Running ListFunc for %q", kind)
			req := getter.Get().Namespace(api.NamespaceAll).Resource(kind).
				LabelsSelectorParam(selector).FieldsSelectorParam(fields.Everything())
			logger.Debugf("Request URL: %v", req.URL())
			obj, er := req.Do().Get()
			if er != nil {
				logger.Debugf("Got error: %v", er)
			}
			return obj, er
		},
		WatchFunc: func(options api.ListOptions) (watch.Interface, error) {
			logger.Debugf("Running WatchFunc for %q", kind)
			req := getter.Get().Prefix("watch").Namespace(api.NamespaceAll).Resource(kind).
				LabelsSelectorParam(selector).FieldsSelectorParam(fields.Everything()).
				Param("resourceVersion", options.ResourceVersion)
			logger.Debugf("Request URL: %v", req.URL())
			w, er := req.Watch()
			if er != nil {
				logger.Debugf("Got error: %v", er)
			} else {
				logger.Debugf("Set watch for %q", kind)
			}
			return w, er
		},
	}
}
예제 #13
0
func (t *traefik) DeleteServer(ba loadbalancer.Backend, srv loadbalancer.Server) error {
	logger.Debugf("[%v] Attempting delete: %v", ba.GetID(), srv)
	key := path.Join(t.prefix, "backends", ba.GetID(), "servers", srv.GetID())
	if er := t.Exists(key); er != nil {
		return fmt.Errorf("Lookup %v failed: %v", srv, er)
	}

	return t.Delete(key)
}
예제 #14
0
func FindIP(dev string) (string, error) {
	logger.Debugf("Looking up ip for interface %q", dev)
	inf, er := net.InterfaceByName(dev)
	if er != nil {
		return "", er
	}
	addrs, er := inf.Addrs()
	if er != nil {
		return "", er
	}
	if len(addrs) < 1 {
		return "", errors.New("Interface has no addresses")
	}

	logger.Debugf("Addresses for %q: %v", dev, addrs)
	bits := strings.SplitN(addrs[0].String(), "/", 2)
	return bits[0], nil
}
예제 #15
0
func RequestPort(ip, user, pass, id string) (int, error) {
	logger.Debugf("Requesting new port from Private Internet Access")
	values := ur.Values{}
	values.Add("user", user)
	values.Add("pass", pass)
	values.Add("client_id", id)
	values.Add("local_ip", ip)

	ep := GetPortForwardEndpoint().String()
	logger.Debugf("POST %v", ep)
	resp, er := http.PostForm(ep, values)
	if er != nil {
		return 0, er
	}

	defer resp.Body.Close()
	port := new(response)
	er = json.NewDecoder(resp.Body).Decode(port)
	return port.Port, er
}
예제 #16
0
func (e *Engine) Update(old, next interface{}) {
	e.Lock()
	defer e.Unlock()
	kubernetes.LogCallback("UPDATE", next)

	logger.Debugf("Gather resources from previous object")
	oldResources, er := kubernetes.GenResources(e.Cache, old)
	if er != nil {
		logger.Errorf(er.Error())
	}

	logger.Debugf("Gather resources from new object")
	newResources, er := kubernetes.GenResources(e.Cache, next)
	if er != nil {
		logger.Errorf(er.Error())
	}

	if er := updateResources(e, newResources, oldResources); er != nil {
		logger.Errorf(er.Error())
	}
}
예제 #17
0
func parseEnvFile(file string) error {
	b, er := ioutil.ReadFile(file)
	if er != nil {
		return er
	}
	for _, line := range strings.Split(string(b), "\n") {
		bits := strings.Split(line, "=")
		if len(bits) == 2 {
			logger.Debugf("Setting %s to %s", bits[0], bits[1])
			os.Setenv(bits[0], bits[1])
		}
	}
	return nil
}
예제 #18
0
func readClientRB(p string) *clientRB {
	var c = &clientRB{p: p, v: make(map[string]string, 0)}
	f, er := ioutil.ReadFile(p)
	if er != nil {
		return nil
	}
	for _, line := range strings.Split(string(f), "\n") {
		bits := strings.Fields(line)
		if len(bits) == 2 {
			logger.Debugf("client.rb: %s = %s", bits[0], bits[1])
			c.v[bits[0]] = bits[1]
		}
	}
	return c
}
예제 #19
0
func read(file string, info os.FileInfo) (*Config, error) {
	logger.Debugf("Reading config from %q", file)
	content, er := ioutil.ReadFile(file)
	if er != nil {
		return nil, er
	}

	c := new(Config)
	if er := yaml.Unmarshal(content, c); er != nil {
		return conf, er
	}

	c.file = file
	c.modTime = info.ModTime()
	return c, mergo.Merge(c, conf)
}
예제 #20
0
func run(name string, cmd []string, w ...io.Writer) error {
	var c, q = context.WithTimeout(context.Background(), *timeout)
	defer q()

	p, er := process.New(name, strings.Join(cmd, " "), w...)
	if er != nil {
		return er
	}
	logger.Debugf("cmd: %s", cmd)
	if er := p.Execute(c); er != nil {
		return er
	}
	select {
	case <-c.Done():
		return fmt.Errorf("cmd %v timed out", p)
	case <-p.Exited():
		return p.Error()
	}
}
예제 #21
0
func workers(conf *config.Config, c context.Context, quit context.CancelFunc) {
	var (
		port    = time.NewTicker(portInterval)
		restart = time.NewTicker(restartInterval)
		check   = time.NewTicker(checkInterval)
	)

	logger.Infof("Port update will run once every hour")
	logger.Infof("VPN restart will run once every day")

	trans, er := process.New("transmission", conf.Transmission.Command, os.Stdout)
	if er != nil {
		quit()
		logger.Fatalf(er.Error())
	}
	vpn, er := process.New("openvpn", conf.OpenVPN.Command, os.Stdout)
	if er != nil {
		quit()
		logger.Fatalf(er.Error())
	}

	if er := startProcesses(trans, vpn, conf, c); er != nil {
		quit()
		logger.Fatalf(er.Error())
	}
	portUpdate(conf, c)

	for {
		select {
		case <-c.Done():
			port.Stop()
			restart.Stop()
			trans.Stop()
			vpn.Stop()
			return
		case t := <-check.C:
			logger.Debugf("Checking transmission port at %v", t)
			if er := portCheck(trans, conf, c); er != nil {
				if er := restartProcesses(trans, vpn, conf, c); er != nil {
					port.Stop()
					restart.Stop()
					trans.Stop()
					vpn.Stop()
					logger.Fatalf(er.Error())
				}
			}
		case t := <-port.C:
			logger.Infof("Update of Transmission port at %v", t)
			if er := portUpdate(conf, c); er != nil {
				if er := restartProcesses(trans, vpn, conf, c); er != nil {
					port.Stop()
					restart.Stop()
					trans.Stop()
					vpn.Stop()
					logger.Fatalf(er.Error())
				}
			}
		case t := <-restart.C:
			logger.Infof("Restarting Transmission and OpenVPN at %v", t)
			if er := restartProcesses(trans, vpn, conf, c); er != nil {
				port.Stop()
				restart.Stop()
				trans.Stop()
				vpn.Stop()
				logger.Fatalf(er.Error())
			}
		}
	}
}
예제 #22
0
func (t *traefik) DeleteFrontend(fr loadbalancer.Frontend) error {
	logger.Debugf("[%v] Attempting to delete: %v", fr.GetID(), fr)
	key := path.Join(t.prefix, "frontends", fr.GetID())
	return t.Delete(key)
}
예제 #23
0
func (t *traefik) DeleteBackend(ba loadbalancer.Backend) error {
	logger.Debugf("[%v] Attempting delete: %v", ba.GetID(), ba)
	key := path.Join(t.prefix, "backends", ba.GetID())
	return t.Delete(key)
}