Merge "Add vlog.Infof's to test."
diff --git a/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.css b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.css
new file mode 100644
index 0000000..2a054d8
--- /dev/null
+++ b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.css
@@ -0,0 +1,46 @@
+:host {
+ background-color: #000000;
+ height: 100%;
+ display: block;
+ overflow: auto;
+}
+
+pre {
+ margin: 0;
+ padding: 0.5em;
+
+ font-family: Fixed, monospace;
+ line-height: 1.2em;
+ word-break: break-word;
+
+ color: #ffffff;
+}
+
+.auto-scroll {
+ position: fixed;
+ right: 40px;
+ bottom: 0;
+ opacity: 0.8;
+ padding: 0.8em;
+ background-color: #ffeb3b;
+ z-index: 1;
+}
+
+paper-input {
+ position: fixed;
+ right: 50px;
+ color: #cccccc;
+ background-color: #ffffff;
+ z-index: 1;
+}
+
+core-item.showHide {
+ background-color: #ff0000;
+ color: #ffffff;
+ cursor: pointer;
+ margin: 5px;
+}
+
+.yellowback {
+ background-color: #666600;
+}
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.html b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.html
new file mode 100644
index 0000000..6669be4
--- /dev/null
+++ b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/component.html
@@ -0,0 +1,122 @@
+<link rel="import" href="../../../../third-party/polymer/polymer.html">
+<link rel="import" href="../../../../third-party/paper-checkbox/paper-checkbox.html">
+
+<polymer-element name="p2b-plugin-console-panic">
+ <template>
+ <link rel="stylesheet" href="component.css">
+ <link rel="stylesheet" href="../../../../libs/css/common-style.css">
+ <div title="Auto Scroll" class="auto-scroll {{ {hidden : !scrolling} | tokenList}}">
+ <paper-checkbox checked="{{autoScroll}}" label="Auto Scroll" id="autoscroll"></paper-checkbox>
+ </div>
+ <paper-input id="filter" label="Filter by keyword..."></paper-input>
+ <pre id="console"></pre>
+ </template>
+ <script>
+ Polymer('p2b-plugin-console-panic', {
+ ready: function() {
+ this.autoScroll = true;
+
+ // Prepare our current container and current line
+ this.startNewContainer(false);
+ this.startNewLine();
+
+ this.$.filter.addEventListener('input', this.filterAllText.bind(this), false);
+ },
+ /*
+ * Scrolls the plugin console, if this.autoScroll is true
+ */
+ scrollAuto: function() {
+ // Scroll if we need to.
+ var scrollTop = this.scrollTop;
+ this.scrolling = scrollTop > 0;
+ if (this.autoScroll) {
+ this.scrollTop = this.scrollHeight;
+ }
+ },
+ /*
+ * Turns off autoscrolling
+ */
+ scrollOff: function() {
+ this.autoScroll = false;
+ },
+ /*
+ * Create a new container div for lines of text
+ * @param {boolean} whether or not the container should start hidden or not
+ * @param {string} (optional) the control button's name for toggling hidden on this container.
+ */
+ startNewContainer: function(isCollapsed, withToggleButtonName) {
+ this.container = document.createElement('div');
+
+ // If the container should be collapsed, hide it.
+ if (isCollapsed) {
+ this.container.classList.toggle('hidden');
+ }
+
+ if (withToggleButtonName) {
+ // This button controls whether to show/hide the container.
+ var control = document.createElement('core-item');
+ control.label = withToggleButtonName;
+ control.classList.add("showHide");
+ control.icon = "swap-vert";
+ var container = this.container;
+ control.addEventListener(
+ 'click',
+ function toggle() {
+ container.classList.toggle('hidden');
+ },
+ false
+ );
+ this.$.console.appendChild(control);
+ }
+
+ this.$.console.appendChild(this.container);
+ },
+ /*
+ * Create a new div for the current line of text. Scroll if necessary.
+ */
+ startNewLine: function() {
+ this.line = document.createElement('div');
+ this.line.classList.add('line');
+ this.container.appendChild(this.line);
+ this.scrollAuto();
+ },
+ /*
+ * Add a <br> element to the container. Scroll if necessary.
+ */
+ addLineBreak: function() {
+ this.container.appendChild(document.createElement('br'));
+ this.scrollAuto();
+ },
+ /*
+ * Append text to the current line of text.
+ * Additionally, filter this line since it was modified.
+ * @param {string} the text to be appended
+ */
+ addText: function(text) {
+ this.line.appendChild(document.createTextNode(text));
+ this.filter(this.line);
+ },
+ /*
+ * All elements with class 'line' are filtered.
+ */
+ filterAllText: function() {
+ var elems = this.$.console.getElementsByClassName('line');
+ for (var i = 0; i < elems.length; i++) {
+ this.filter(elems[i]);
+ }
+ },
+ /*
+ * If the given element's text contains the filter's input value,
+ * a yellow background is assigned. Otherwise, it is removed.
+ * @param {div} the given element whose background will be modified
+ */
+ filter: function(elem) {
+ var value = this.$.filter.inputValue;
+
+ // Force add/remove the yellowback class depending on if the element has the value or not. Don't highlight if the value is empty.
+ var shouldHighlight = (value && elem.textContent.indexOf(value) >= 0);
+ elem.classList.toggle('yellowback', shouldHighlight);
+ }
+ });
+ </script>
+</polymer-element>
diff --git a/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/plugin.js b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/plugin.js
new file mode 100644
index 0000000..256f631
--- /dev/null
+++ b/examples/pipetobrowser/browser/pipe-viewers/builtin/console/panic/plugin.js
@@ -0,0 +1,68 @@
+/*
+ * Console is a Pipe Viewer that displays a text stream as unformatted text
+ * @tutorial echo "Hello World" | p2b google/p2b/[name]/console/panic
+ * @fileoverview
+ */
+
+import { View } from 'view';
+import { PipeViewer } from 'pipe-viewer';
+
+class ConsolePanicPipeViewer extends PipeViewer {
+ get name() {
+ return 'console-panic';
+ }
+
+ play(stream) {
+ var consoleView = document.createElement('p2b-plugin-console-panic');
+
+ // Internal stream variables
+ var panicked = false;
+ var lastPiece = "";
+
+ // read data as UTF8
+ stream.setEncoding('utf8');
+ stream.on('data', (buf) => {
+ // Always split the incoming text by newline.
+ var pieces = buf.toString().split("\n");
+ for (var i = 0; i < pieces.length; i++) {
+ var piece = pieces[i];
+
+ // flags for the status of the current line
+ var goroutine = (piece.search(/goroutine \d+ \[\D+\]:/) == 0);
+ var startOfLine = (i != 0 || lastPiece == "");
+
+ if (goroutine && startOfLine) {
+ // We spotted a goroutine at the start of a line, so create a new container.
+ consoleView.startNewContainer(panicked, piece);
+
+ // Stop scrolling if we've already panicked.
+ // This will focus the element on the first crashed goroutine.
+ if (panicked) {
+ consoleView.scrollAuto();
+ consoleView.scrollOff();
+ }
+ panicked = true;
+
+ // We also need a new line for our new container.
+ consoleView.startNewLine();
+ } else if (i > 0) {
+ // These lines followed a \n in the buffer and thus should go on a new line.
+ if (lastPiece == "") {
+ // The previous line was empty; empty div's have 0 height.
+ // We need to add a <br /> to print the linebreak properly.
+ consoleView.addLineBreak();
+ }
+ consoleView.startNewLine();
+ }
+
+ // Add the relevant text.
+ consoleView.addText(piece);
+ lastPiece = piece;
+ }
+ });
+
+ return new View(consoleView);
+ }
+}
+
+export default ConsolePanicPipeViewer;
\ No newline at end of file
diff --git a/examples/pipetobrowser/browser/views/help/component.html b/examples/pipetobrowser/browser/views/help/component.html
index ba5112c..d3861ef 100644
--- a/examples/pipetobrowser/browser/views/help/component.html
+++ b/examples/pipetobrowser/browser/views/help/component.html
@@ -35,6 +35,10 @@
<p>If you want to pipe logs from a Veyron service directly, you need to pipe stderr or strout first using <span class="mono">2>&1</span></p>
<pre class="code">myVeyronServerd -v=3 2>&1 | p2b {{publishedName}}/vlog</pre>
+ <h4>Panic Console</h4>
+ <span class="name">console/panic</span> renders plaintext as <span class="name">console</span> until it detects a Go panic. Go panics crash every running goroutine, leading to a spew of stderr logs. This plugin groups goroutine crash logs into show/hide blocks. The plugin stops scrolling at the first goroutine block, which caused the panic. To further assist the debugging process, lines can be highlighted by keyword using an input filter. Don't forget to pipe both stdout and stderr to this plugin!
+ <pre class="code">./goProgram 2>&1 | p2b {{publishedName}}/console/panic</pre>
+
<h4>dev/null</h4>
<p>No system is complete without a <span class="name">dev/null</span>. Similar to *nix <span class="mono">dev/null</span>, anything piped to it will be discarded without mercy.</p>
<pre class="code">cat /dev/urandom | p2b {{publishedName}}/dev/null</pre>
diff --git a/examples/pipetobrowser/browser/views/page/component.html b/examples/pipetobrowser/browser/views/page/component.html
index 4e5b72d..423f92e 100644
--- a/examples/pipetobrowser/browser/views/page/component.html
+++ b/examples/pipetobrowser/browser/views/page/component.html
@@ -21,6 +21,7 @@
<link rel="import" href="../../views/redirect-pipe-dialog/component.html"/>
<link rel="import" href="../../views/neighborhood/component.html"/>
<link rel="import" href="../../pipe-viewers/builtin/console/component.html"/>
+<link rel="import" href="../../pipe-viewers/builtin/console/panic/component.html"/>
<link rel="import" href="../../pipe-viewers/builtin/git/status/component.html"/>
<link rel="import" href="../../pipe-viewers/builtin/vlog/component.html"/>
<link rel="import" href="../../libs/ui-components/blackhole/component.html"/>
diff --git a/lib/testutil/modules/ls.go b/lib/testutil/modules/ls.go
index 88ae4d0..fa6f05e 100644
--- a/lib/testutil/modules/ls.go
+++ b/lib/testutil/modules/ls.go
@@ -94,7 +94,7 @@
}
func lsUsingResolve(name, pattern string) ([]string, error) {
- mtpt, err := mounttable.BindGlobable(name)
+ mtpt, err := mounttable.BindGlobbable(name)
if err != nil {
return []string{}, err
}
diff --git a/runtimes/google/lib/netconfig/isgloballyroutable.go b/runtimes/google/lib/netconfig/isgloballyroutable.go
new file mode 100644
index 0000000..4fa5916
--- /dev/null
+++ b/runtimes/google/lib/netconfig/isgloballyroutable.go
@@ -0,0 +1,29 @@
+package netconfig
+
+import (
+ "net"
+)
+
+var privateCIDRs = []net.IPNet{
+ net.IPNet{IP: net.IPv4(10, 0, 0, 0), Mask: net.IPv4Mask(0xff, 0, 0, 0)},
+ net.IPNet{IP: net.IPv4(172, 16, 0, 0), Mask: net.IPv4Mask(0xff, 0xf0, 0, 0)},
+ net.IPNet{IP: net.IPv4(192, 168, 0, 0), Mask: net.IPv4Mask(0xff, 0xff, 0, 0)},
+}
+
+// IsGloballyRoutable returns true if the argument is a globally routable IP address.
+func IsGloballyRoutable(ip net.IP) bool {
+ if !ip.IsGlobalUnicast() {
+ return false
+ }
+ if ip4 := ip.To4(); ip4 != nil {
+ for _, cidr := range privateCIDRs {
+ if cidr.Contains(ip4) {
+ return false
+ }
+ }
+ if ip4.Equal(net.IPv4bcast) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/runtimes/google/lib/netconfig/isgloballyroutable_test.go b/runtimes/google/lib/netconfig/isgloballyroutable_test.go
new file mode 100644
index 0000000..3cce082
--- /dev/null
+++ b/runtimes/google/lib/netconfig/isgloballyroutable_test.go
@@ -0,0 +1,31 @@
+package netconfig
+
+import (
+ "net"
+ "testing"
+)
+
+func TestIsGloballyRoutable(t *testing.T) {
+ tests := []struct {
+ ip string
+ want bool
+ }{
+ {"192.168.1.1", false},
+ {"192.169.0.3", true},
+ {"10.1.1.1", false},
+ {"172.17.100.255", false},
+ {"172.32.0.1", true},
+ {"255.255.255.255", false},
+ {"127.0.0.1", false},
+ {"224.0.0.1", false},
+ {"FF02::FB", false},
+ {"fe80::be30:5bff:fed3:843f", false},
+ {"2620:0:1000:8400:be30:5bff:fed3:843f", true},
+ }
+ for _, test := range tests {
+ ip := net.ParseIP(test.ip)
+ if got := IsGloballyRoutable(ip); got != test.want {
+ t.Fatalf("%s: want %v got %v", test.ip, test.want, got)
+ }
+ }
+}
diff --git a/runtimes/google/naming/namespace/all_test.go b/runtimes/google/naming/namespace/all_test.go
index 17e399e..c5879f9 100644
--- a/runtimes/google/naming/namespace/all_test.go
+++ b/runtimes/google/naming/namespace/all_test.go
@@ -403,7 +403,7 @@
mu sync.Mutex
}
-func (g *GlobbableServer) Glob(ipc.ServerContext, string, mounttable.GlobableServiceGlobStream) error {
+func (g *GlobbableServer) Glob(ipc.ServerContext, string, mounttable.GlobbableServiceGlobStream) error {
g.mu.Lock()
defer g.mu.Unlock()
g.callCount++
@@ -429,7 +429,7 @@
globServer := &GlobbableServer{}
name := naming.JoinAddressName(mts["mt4/foo/bar"].name, "glob")
- runningGlobServer := runServer(t, r, ipc.SoloDispatcher(mounttable.NewServerGlobable(globServer), nil), name)
+ runningGlobServer := runServer(t, r, ipc.SoloDispatcher(mounttable.NewServerGlobbable(globServer), nil), name)
defer runningGlobServer.server.Stop()
ns := r.Namespace()
diff --git a/services/mounttable/lib/mounttable.go b/services/mounttable/lib/mounttable.go
index fe0cecf..367230f 100644
--- a/services/mounttable/lib/mounttable.go
+++ b/services/mounttable/lib/mounttable.go
@@ -315,7 +315,7 @@
name string
}
-func (mt *mountTable) globStep(n *node, name string, pattern *glob.Glob, context ipc.ServerContext, reply mounttable.GlobableServiceGlobStream) {
+func (mt *mountTable) globStep(n *node, name string, pattern *glob.Glob, context ipc.ServerContext, reply mounttable.GlobbableServiceGlobStream) {
vlog.VI(2).Infof("globStep(%s, %s)", name, pattern)
if mt.acls != nil {
@@ -363,7 +363,7 @@
// Glob finds matches in the namespace. If we reach a mount point before matching the
// whole pattern, return that mount point.
// pattern is a glob pattern as defined by the veyron/lib/glob package.
-func (ms *mountContext) Glob(context ipc.ServerContext, pattern string, reply mounttable.GlobableServiceGlobStream) error {
+func (ms *mountContext) Glob(context ipc.ServerContext, pattern string, reply mounttable.GlobbableServiceGlobStream) error {
vlog.VI(2).Infof("mt.Glob %v", ms.elems)
g, err := glob.Parse(pattern)
diff --git a/services/mounttable/lib/neighborhood.go b/services/mounttable/lib/neighborhood.go
index bcc555d..7653604 100644
--- a/services/mounttable/lib/neighborhood.go
+++ b/services/mounttable/lib/neighborhood.go
@@ -231,7 +231,7 @@
}
// Glob implements Glob
-func (ns *neighborhoodService) Glob(_ ipc.ServerContext, pattern string, reply mounttable.GlobableServiceGlobStream) error {
+func (ns *neighborhoodService) Glob(_ ipc.ServerContext, pattern string, reply mounttable.GlobbableServiceGlobStream) error {
g, err := glob.Parse(pattern)
if err != nil {
return err
diff --git a/services/store/server/object.go b/services/store/server/object.go
index f0b329e..51313c0 100644
--- a/services/store/server/object.go
+++ b/services/store/server/object.go
@@ -198,7 +198,7 @@
}
type globStreamAdapter struct {
- stream mounttable.GlobableServiceGlobStream
+ stream mounttable.GlobbableServiceGlobStream
}
func (a *globStreamAdapter) Send(item string) error {
@@ -208,7 +208,7 @@
}
// Glob streams a series of names that match the given pattern.
-func (o *object) Glob(ctx ipc.ServerContext, pattern string, stream mounttable.GlobableServiceGlobStream) error {
+func (o *object) Glob(ctx ipc.ServerContext, pattern string, stream mounttable.GlobbableServiceGlobStream) error {
t, err := o.server.findTransaction(ctx, o.tid)
if err != nil {
return err
diff --git a/tools/mounttable/impl/impl_test.go b/tools/mounttable/impl/impl_test.go
index d188797..ef40175 100644
--- a/tools/mounttable/impl/impl_test.go
+++ b/tools/mounttable/impl/impl_test.go
@@ -20,7 +20,7 @@
suffix string
}
-func (s *server) Glob(_ ipc.ServerContext, pattern string, stream mounttable.GlobableServiceGlobStream) error {
+func (s *server) Glob(_ ipc.ServerContext, pattern string, stream mounttable.GlobbableServiceGlobStream) error {
vlog.VI(2).Infof("Glob() was called. suffix=%v pattern=%q", s.suffix, pattern)
stream.Send(mounttable.MountEntry{"name1", []mounttable.MountedServer{{"server1", 123}}})
stream.Send(mounttable.MountEntry{"name2", []mounttable.MountedServer{{"server2", 456}, {"server3", 789}}})