m/c/metroctl: implement the "describe" command

This implements metroctl's "describe".

cmd.TerminateIfFound was adjusted to meet new test needs.

Change-Id: If86f35bc648d99396e7d5be48ab459d6b13334ce
Reviewed-on: https://review.monogon.dev/c/monogon/+/850
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/pkg/cmd/run.go b/metropolis/pkg/cmd/run.go
index f92cb84..9f554b5 100644
--- a/metropolis/pkg/cmd/run.go
+++ b/metropolis/pkg/cmd/run.go
@@ -79,9 +79,25 @@
 // TerminateIfFound creates RunCommand predicates that instantly terminate
 // program execution in the event the given string is found in any line
 // produced. RunCommand will return true, if the string searched for was found,
-// and false otherwise.
-func TerminateIfFound(needle string) func(string) bool {
+// and false otherwise. If logf isn't nil, it will be called whenever a new
+// line is received.
+func TerminateIfFound(needle string, logf func(string)) func(string) bool {
 	return func(haystack string) bool {
+		if logf != nil {
+			logf(haystack)
+		}
 		return strings.Contains(haystack, needle)
 	}
 }
+
+// WaitUntilCompletion creates a RunCommand predicate that will make it wait
+// for the process to exit on its own. If logf isn't nil, it will be called
+// whenever a new line is received.
+func WaitUntilCompletion(logf func(string)) func(string) bool {
+	return func(line string) bool {
+		if logf != nil {
+			logf(line)
+		}
+		return false
+	}
+}