summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-12-17 10:11:45 -0700
committerMatthew Holt <mholt@users.noreply.github.com>2019-12-17 10:11:45 -0700
commit6455efa5d327377b41e708a063d1b7a71a131165 (patch)
tree4532f26949b89a2fa1224dc566af3daa49c55368
parent5ab17a3a371c1f84ef5a649d9310971eb7959271 (diff)
admin: POST /... expands and appends all array elements
Makes it easy to append many items to an array in one command
-rw-r--r--admin.go39
-rw-r--r--admin_test.go6
2 files changed, 39 insertions, 6 deletions
diff --git a/admin.go b/admin.go
index 0f8144b..89c007d 100644
--- a/admin.go
+++ b/admin.go
@@ -636,6 +636,19 @@ func unsyncedConfigAccess(method, path string, body []byte, out io.Writer) error
return fmt.Errorf("path missing")
}
+ // A path that ends with "..." implies:
+ // 1) the part before it is an array
+ // 2) the payload is an array
+ // and means that the user wants to expand the elements
+ // in the payload array and append each one into the
+ // destination array, like so:
+ // array = append(array, elems...)
+ // This special case is handled below.
+ ellipses := parts[len(parts)-1] == "..."
+ if ellipses {
+ parts = parts[:len(parts)-1]
+ }
+
var ptr interface{} = rawCfg
traverseLoop:
@@ -666,7 +679,15 @@ traverseLoop:
return fmt.Errorf("encoding config: %v", err)
}
case http.MethodPost:
- v[part] = append(arr, val)
+ if ellipses {
+ valArray, ok := val.([]interface{})
+ if !ok {
+ return fmt.Errorf("final element is not an array")
+ }
+ v[part] = append(arr, valArray...)
+ } else {
+ v[part] = append(arr, val)
+ }
case http.MethodPut:
// avoid creation of new slice and a second copy (see
// https://github.com/golang/go/wiki/SliceTricks#insert)
@@ -692,13 +713,19 @@ traverseLoop:
return fmt.Errorf("encoding config: %v", err)
}
case http.MethodPost:
+ // if the part is an existing list, POST appends to
+ // it, otherwise it just sets or creates the value
if arr, ok := v[part].([]interface{}); ok {
- // if the part is an existing list, POST appends to it
- // TODO: Do we ever reach this point, since we handle arrays
- // separately above?
- v[part] = append(arr, val)
+ if ellipses {
+ valArray, ok := val.([]interface{})
+ if !ok {
+ return fmt.Errorf("final element is not an array")
+ }
+ v[part] = append(arr, valArray...)
+ } else {
+ v[part] = append(arr, val)
+ }
} else {
- // otherwise, it simply sets the value
v[part] = val
}
case http.MethodPut:
diff --git a/admin_test.go b/admin_test.go
index e8563b7..cfb4ab7 100644
--- a/admin_test.go
+++ b/admin_test.go
@@ -77,6 +77,12 @@ func TestUnsyncedConfigAccess(t *testing.T) {
payload: `"d"`,
expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d"]}`,
},
+ {
+ method: "POST",
+ path: "/list/...",
+ payload: `["e", "f", "g"]`,
+ expect: `{"foo": "jet", "bar": {"aa": "bb"}, "list": ["a", "b", "c", "d", "e", "f", "g"]}`,
+ },
} {
err := unsyncedConfigAccess(tc.method, rawConfigKey+tc.path, []byte(tc.payload), nil)