cluster/identd/ident: add IdentError

This adds a Go error type that can be used to wrap any ErrorResponse.

Change-Id: I57fbd056ac774f4e2ae3bdf85941c1010ada0656
diff --git a/cluster/identd/ident/errors.go b/cluster/identd/ident/errors.go
new file mode 100644
index 0000000..0581f3c
--- /dev/null
+++ b/cluster/identd/ident/errors.go
@@ -0,0 +1,38 @@
+package ident
+
+// IdentError is an ErrorResponse received from a ident server, wrapped as a Go
+// error type.
+// When using errors.Is/errors.As against an IdentError, the Inner field
+// controls the matching behaviour.
+//  - If set, the error will match if the tested error is an IdentError with
+//    same ErrorResponse as the IdentError tested against
+//  - If not set, the error will always match if the tested error is any
+//    IdentError.
+//
+// For example:
+//    errors.Is(err, &IdentError{}
+// will be true if err is any *IdentError, but:
+//    errors.Is(err, &IdentError{NoUser})
+// will be true only if err is an *IdentError with an Inner NoUser.
+type IdentError struct {
+	// Inner is the ErrorResponse contained by this error.
+	Inner ErrorResponse
+}
+
+func (e *IdentError) Error() string {
+	return string(e.Inner)
+}
+
+func (e *IdentError) Is(target error) bool {
+	t, ok := target.(*IdentError)
+	if !ok {
+		return false
+	}
+	if t.Inner == "" {
+		return true
+	}
+	if t.Inner == e.Inner {
+		return true
+	}
+	return false
+}