Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging Upstream #1

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Here is a complete configuration with the defaults, only `ProgramArgs` is **requ
```toml
# Program to execute (with optional Arguments). Note: the process
# must remain in the foreground (i.e. do NOT fork/run as daemon).
# example: ["/usr/bin/dnsmasq","-config","/etc/dnsmasq.conf"]
ProgramArgs = []

# Interface to serve web UI. Warning: defaults to ALL interfaces.
Expand Down Expand Up @@ -114,7 +115,7 @@ OnExit = "ignore"
# OnSave dictates what action to take when saving a configuration file via the UI:
# "restart" - instantly restart the process
# "continue" - do not restart the process (restart button must be used)
OnExit = "restart"
OnSave = "restart"

# Configuration files to be editable by the web UI.
# For example, dnsmasq would include "/etc/dnsmasq.conf"
Expand Down Expand Up @@ -162,4 +163,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
61 changes: 55 additions & 6 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"github.com/NYTimes/gziphandler"
"github.com/fsnotify/fsnotify"
"github.com/jpillora/cookieauth"
"github.com/jpillora/ipfilter"
"github.com/jpillora/requestlog"
Expand Down Expand Up @@ -137,24 +138,33 @@ func Run(version string, c Config) error {
go a.readLog()
//load from disk
a.readFiles()
//watch files
if c := a.watchFiles(); c != nil {
defer c.Close()
}
//catch all signals
go func() {
signals := make(chan os.Signal)
signal.Notify(signals)
for sig := range signals {
if sig.String() == "urgent I/O condition" {
//ignore due to https://github.com/golang/go/issues/37942
continue
}
if sig == os.Interrupt {
a.log.Printf("webproc interupted, exiting...")
if a.running() {
a.procSigs <- os.Kill
time.Sleep(100 * time.Millisecond)
}
os.Exit(0)
} else if a.running() {
//proxy through to proc
a.procSigs <- sig
} else {
}
if !a.running() {
a.log.Printf("ignored signal: %s", sig)
continue
}
//proxy through to proc
a.procSigs <- sig
}
}()
//serve agent's root handler
Expand Down Expand Up @@ -187,7 +197,7 @@ func (a *agent) restart() {
a.procReqs <- "restart"
}

func (a *agent) readFiles() {
func (a *agent) readFiles() bool {
a.data.Lock()
changed := false
for i, path := range a.data.Config.ConfigurationFiles {
Expand All @@ -200,14 +210,53 @@ func (a *agent) readFiles() {
curr := string(b)
if curr != existing {
a.data.Files[path] = curr
a.log.Printf("loaded config file '%s' from disk", path)
changed = true
}
}
a.data.Unlock()
if changed {
a.log.Printf("loaded config files changes from disk")
a.data.Push()
}
return changed
}

func (a *agent) watchFiles() io.Closer {
restart := a.data.Config.RestartWatch
//fsnotify
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil
}
//watch handler
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write != fsnotify.Write {
continue
}
if !a.readFiles() {
continue
}
if restart {
a.restart()
}
}

}
}()
//watch all config files
for _, path := range a.data.Config.ConfigurationFiles {
if err := watcher.Add(path); err != nil {
return nil
}
}
//success
return watcher
}

func (a *agent) readLog() {
Expand Down
2 changes: 1 addition & 1 deletion agent/agent_proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (a *agent) runProcOnce(prog string, c Config) int {
}()
}
//issue signal
a.log.Printf("sending signal: %s", sig)
a.log.Printf("sending signal: %s (%d)", sig, sig)
time.Sleep(100 * time.Millisecond)
proc.Process.Signal(sig)
case code := <-wait:
Expand Down
1 change: 1 addition & 0 deletions agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Config struct {
OnExit OnExit `opts:"help=process exit action, short=o, default=ignore"`
OnSave OnSave `opts:"help=config save action, short=s, default=restart"`
ConfigurationFiles []string `opts:"mode=flag, help=writable configuration file"`
RestartWatch bool `opts:"short=w,help=changing config files on disk triggers a restart"`
RestartTimeout Duration `opts:"help=restart timeout controls when to perform a force kill, default=30s"`
MaxLines int `opts:"help=maximum number of log lines to show in webui, default=5000"`
}
Expand Down
13 changes: 7 additions & 6 deletions agent/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ <h1 class="title">
class="ui button"
ng-click="start()"
ng-class="{
loading: start.ing, disabled: !saved || start.ed || !connected,
primary: !start.ed, green: start.ed
}"
loading: start.ing, disabled: !saved || start.ed || !connected,
primary: !start.ed, green: start.ed
}"
>
{{ start.ed || (data.Running ? "Restart" : "Start") }}
</button>
Expand All @@ -98,9 +98,9 @@ <h1 class="title">
class="ui button"
ng-click="save()"
ng-class="{
loading: save.ing, disabled: saved || save.ed || !connected,
primary: !save.ed, green: save.ed
}"
loading: save.ing, disabled: saved || save.ed || !connected,
primary: !save.ed, green: save.ed
}"
>
Save{{ save.ed ? "d" : "" }}
</button>
Expand Down Expand Up @@ -145,6 +145,7 @@ <h1 class="title">
<script src="vendor/favico.min.js"></script>
<script src="vendor/angular.min.js"></script>
<script src="vendor/codemirror/lib/codemirror.js"></script>
<script src="vendor/codemirror/addon/comment/comment.js"></script>
<script src="vendor/codemirror/addon/mode/loadmode.js"></script>
<script src="vendor/codemirror/mode/meta.js"></script>
<script src="js/cm.js"></script>
Expand Down
61 changes: 38 additions & 23 deletions agent/static/js/directives.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
app.directive("ago", function() {
var since = (function() {
app.directive("ago", function () {
var since = (function () {
var scale = [
["ms", 1000],
["s", 60],
["m", 60],
["h", 24],
["d", 31],
["mth", 12]
["mth", 12],
];
return function(date) {
return function (date) {
var v = +new Date() - date;
for (var i = 0; i < scale.length; i++) {
var s = scale[i];
Expand All @@ -21,25 +21,25 @@ app.directive("ago", function() {

return {
restrict: "A",
link: function(s, e, attrs) {
link: function (s, e, attrs) {
var d, t;
var check = function() {
var check = function () {
clearTimeout(t);
if (d) e.text(since(d));
t = setTimeout(check, 1000);
};
s.$watch(attrs.ago, function(s) {
s.$watch(attrs.ago, function (s) {
d = new Date(s);
check();
});
}
},
};
});

app.directive("cmContainer", function($rootScope) {
app.directive("cmContainer", function ($rootScope) {
return {
restrict: "C",
link: function(scope, jq, attrs) {
link: function (scope, jq, attrs) {
var elem = jq[0];
var name = attrs.name;
if (!name) {
Expand All @@ -49,31 +49,46 @@ app.directive("cmContainer", function($rootScope) {
if (!api) {
throw "api not there";
}
var opts = angular.extend({ viewportMargin: Infinity }, api.opts);
var mac = /Mac OS X/.test(navigator.userAgent);
var key = mac ? "Cmd" : "Ctrl";
var extraKeys = {};
extraKeys[key + "-S"] = function () {
if (typeof api.onsave === "function") {
api.onsave();
}
};
extraKeys[key + "-/"] = "toggleComment";
var opts = angular.extend(
{
viewportMargin: Infinity,
extraKeys: extraKeys,
},
api.opts
);
var editor = CodeMirror(elem, opts);
window["cm" + name] = api;
//optional handler
if (api.onchange) {
editor.doc.on("change", function() {
editor.doc.on("change", function () {
api.onchange();
});
}
var initialMode = api.mode || null;
//code mirror api
api.set = function(val) {
window.requestAnimationFrame(function() {
api.set = function (val) {
window.requestAnimationFrame(function () {
editor.setValue(val || "");
api.followScroll();
});
};
api.get = function() {
api.get = function () {
return editor.getValue();
};
api.append = function(line) {
api.append = function (line) {
editor.replaceRange(line, CodeMirror.Pos(editor.lastLine()));
api.followScroll();
};
api.mode = function(mode) {
api.mode = function (mode) {
editor.setOption("mode", mode);
CodeMirror.autoLoadMode(editor, mode);
};
Expand All @@ -82,15 +97,15 @@ app.directive("cmContainer", function($rootScope) {
}
if (api.followLock) {
api.following = true;
api.followScroll = function() {
api.followScroll = function () {
if (api.following) {
root.log.editor.doc.setSelection({
line: root.log.editor.doc.lineCount(),
ch: 0
ch: 0,
});
}
};
api.followCheck = function() {
api.followCheck = function () {
var info = editor.getScrollInfo();
var scrollh = elem.clientHeight + info.top;
var p = scrollh / info.height;
Expand All @@ -101,19 +116,19 @@ app.directive("cmContainer", function($rootScope) {

editor.on("scroll", api.followCheck);
} else {
api.followScroll = function() {
api.followScroll = function () {
//noop
};
}

scroll;
var followLock = false;
api.follow = function(f) {
api.follow = function (f) {
follow = f;
//on scroll, detect if bottom, if so following=true
//on append, if following, scroll bottom
};
api.editor = editor;
}
},
};
});
Loading