[lxc-devel] [lxd/master] api: Replace Command with APIEndpoint

stgraber on Github lxc-bot at linuxcontainers.org
Wed Apr 24 22:35:36 UTC 2019


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190424/4cfaddf0/attachment-0001.bin>
-------------- next part --------------
From fbc47ef37aedce7f3e239a341c94d6f2d6ee48de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:32:24 -0400
Subject: [PATCH 01/14] lxd/api: Replace Command with APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_1.0.go      |  2 +-
 lxd/api_internal.go |  2 +-
 lxd/daemon.go       | 55 ++++++++++++++++++++++++---------------------
 3 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index 056d60d5b7..c92c76e6f1 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -29,7 +29,7 @@ var api10Cmd = Command{
 	patch:        api10Patch,
 }
 
-var api10 = []Command{
+var api10 = []APIEndpoint{
 	api10Cmd,
 	api10ResourcesCmd,
 	certificateCmd,
diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 38ea706cd9..0ac9a6e912 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -29,7 +29,7 @@ import (
 	runtimeDebug "runtime/debug"
 )
 
-var apiInternal = []Command{
+var apiInternal = []APIEndpoint{
 	internalReadyCmd,
 	internalShutdownCmd,
 	internalContainerOnStartCmd,
diff --git a/lxd/daemon.go b/lxd/daemon.go
index 1dc254cce1..254936a982 100644
--- a/lxd/daemon.go
+++ b/lxd/daemon.go
@@ -144,16 +144,21 @@ func DefaultDaemon() *Daemon {
 	return NewDaemon(config, os)
 }
 
-// Command is the basic structure for every API call.
-type Command struct {
-	name          string
-	untrustedGet  bool
-	untrustedPost bool
-	get           func(d *Daemon, r *http.Request) Response
-	put           func(d *Daemon, r *http.Request) Response
-	post          func(d *Daemon, r *http.Request) Response
-	delete        func(d *Daemon, r *http.Request) Response
-	patch         func(d *Daemon, r *http.Request) Response
+// APIEndpoint represents a URL in our API.
+type APIEndpoint struct {
+	Name   string
+	Get    APIEndpointAction
+	Put    APIEndpointAction
+	Post   APIEndpointAction
+	Delete APIEndpointAction
+	Patch  APIEndpointAction
+}
+
+// APIEndpointAction represents an action on an API endpoint.
+type APIEndpointAction struct {
+	Handler        func(d *Daemon, r *http.Request) Response
+	AccessHandler  func(d *Daemon, r *http.Request) Response
+	AllowUntrusted bool
 }
 
 // Convenience function around Authenticate
@@ -297,12 +302,12 @@ func (d *Daemon) UnixSocket() string {
 	return filepath.Join(d.os.VarDir, "unix.socket")
 }
 
-func (d *Daemon) createCmd(restAPI *mux.Router, version string, c Command) {
+func (d *Daemon) createCmd(restAPI *mux.Router, version string, c APIEndpoint) {
 	var uri string
-	if c.name == "" {
+	if c.Name == "" {
 		uri = fmt.Sprintf("/%s", version)
 	} else {
-		uri = fmt.Sprintf("/%s/%s", version, c.name)
+		uri = fmt.Sprintf("/%s/%s", version, c.Name)
 	}
 
 	restAPI.HandleFunc(uri, func(w http.ResponseWriter, r *http.Request) {
@@ -332,14 +337,14 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c Command) {
 		// Reject internal queries to remote, non-cluster, clients
 		if version == "internal" && !shared.StringInSlice(protocol, []string{"unix", "cluster"}) {
 			// Except for the initial cluster accept request (done over trusted TLS)
-			if !trusted || c.name != "cluster/accept" || protocol != "tls" {
+			if !trusted || c.Name != "cluster/accept" || protocol != "tls" {
 				logger.Warn("Rejecting remote internal API request", log.Ctx{"ip": r.RemoteAddr})
 				Forbidden(nil).Render(w)
 				return
 			}
 		}
 
-		untrustedOk := (r.Method == "GET" && c.untrustedGet) || (r.Method == "POST" && c.untrustedPost)
+		untrustedOk := (r.Method == "GET" && c.Get.AllowUntrusted) || (r.Method == "POST" && c.Post.AllowUntrusted)
 		if trusted {
 			logger.Debug("Handling", log.Ctx{"method": r.Method, "url": r.URL.RequestURI(), "ip": r.RemoteAddr, "user": username})
 			r = r.WithContext(context.WithValue(r.Context(), "username", username))
@@ -374,24 +379,24 @@ func (d *Daemon) createCmd(restAPI *mux.Router, version string, c Command) {
 
 		switch r.Method {
 		case "GET":
-			if c.get != nil {
-				resp = c.get(d, r)
+			if c.Get.Handler != nil {
+				resp = c.Get.Handler(d, r)
 			}
 		case "PUT":
-			if c.put != nil {
-				resp = c.put(d, r)
+			if c.Put.Handler != nil {
+				resp = c.Put.Handler(d, r)
 			}
 		case "POST":
-			if c.post != nil {
-				resp = c.post(d, r)
+			if c.Post.Handler != nil {
+				resp = c.Post.Handler(d, r)
 			}
 		case "DELETE":
-			if c.delete != nil {
-				resp = c.delete(d, r)
+			if c.Delete.Handler != nil {
+				resp = c.Delete.Handler(d, r)
 			}
 		case "PATCH":
-			if c.patch != nil {
-				resp = c.patch(d, r)
+			if c.Patch.Handler != nil {
+				resp = c.Patch.Handler(d, r)
 			}
 		default:
 			resp = NotFound(fmt.Errorf("Method '%s' not found", r.Method))

From 004336eb4581b1824777a3b45c32341820aaea28 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:32:38 -0400
Subject: [PATCH 02/14] lxd/storage: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/storage_pools.go            | 22 ++++++------
 lxd/storage_volumes.go          | 63 ++++++++++++++++++---------------
 lxd/storage_volumes_snapshot.go | 22 ++++++------
 3 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/lxd/storage_pools.go b/lxd/storage_pools.go
index 2f685e3f23..0c08101c99 100644
--- a/lxd/storage_pools.go
+++ b/lxd/storage_pools.go
@@ -21,18 +21,20 @@ import (
 // Lock to prevent concurent storage pools creation
 var storagePoolCreateLock sync.Mutex
 
-var storagePoolsCmd = Command{
-	name: "storage-pools",
-	get:  storagePoolsGet,
-	post: storagePoolsPost,
+var storagePoolsCmd = APIEndpoint{
+	Name: "storage-pools",
+
+	Get:  APIEndpointAction{Handler: storagePoolsGet},
+	Post: APIEndpointAction{Handler: storagePoolsPost},
 }
 
-var storagePoolCmd = Command{
-	name:   "storage-pools/{name}",
-	get:    storagePoolGet,
-	put:    storagePoolPut,
-	patch:  storagePoolPatch,
-	delete: storagePoolDelete,
+var storagePoolCmd = APIEndpoint{
+	Name: "storage-pools/{name}",
+
+	Delete: APIEndpointAction{Handler: storagePoolDelete},
+	Get:    APIEndpointAction{Handler: storagePoolGet},
+	Patch:  APIEndpointAction{Handler: storagePoolPatch},
+	Put:    APIEndpointAction{Handler: storagePoolPut},
 }
 
 // /1.0/storage-pools
diff --git a/lxd/storage_volumes.go b/lxd/storage_volumes.go
index 3ed6115162..7ec27cc8a3 100644
--- a/lxd/storage_volumes.go
+++ b/lxd/storage_volumes.go
@@ -21,43 +21,48 @@ import (
 	log "github.com/lxc/lxd/shared/log15"
 )
 
-var storagePoolVolumesCmd = Command{
-	name: "storage-pools/{name}/volumes",
-	get:  storagePoolVolumesGet,
-	post: storagePoolVolumesPost,
+var storagePoolVolumesCmd = APIEndpoint{
+	Name: "storage-pools/{name}/volumes",
+
+	Get:  APIEndpointAction{Handler: storagePoolVolumesGet},
+	Post: APIEndpointAction{Handler: storagePoolVolumesPost},
 }
 
-var storagePoolVolumesTypeCmd = Command{
-	name: "storage-pools/{name}/volumes/{type}",
-	get:  storagePoolVolumesTypeGet,
-	post: storagePoolVolumesTypePost,
+var storagePoolVolumesTypeCmd = APIEndpoint{
+	Name: "storage-pools/{name}/volumes/{type}",
+
+	Get:  APIEndpointAction{Handler: storagePoolVolumesTypeGet},
+	Post: APIEndpointAction{Handler: storagePoolVolumesTypePost},
 }
 
-var storagePoolVolumeTypeContainerCmd = Command{
-	name:   "storage-pools/{pool}/volumes/container/{name:.*}",
-	post:   storagePoolVolumeTypeContainerPost,
-	get:    storagePoolVolumeTypeContainerGet,
-	put:    storagePoolVolumeTypeContainerPut,
-	patch:  storagePoolVolumeTypeContainerPatch,
-	delete: storagePoolVolumeTypeContainerDelete,
+var storagePoolVolumeTypeContainerCmd = APIEndpoint{
+	Name: "storage-pools/{pool}/volumes/container/{name:.*}",
+
+	Delete: APIEndpointAction{Handler: storagePoolVolumeTypeContainerDelete},
+	Get:    APIEndpointAction{Handler: storagePoolVolumeTypeContainerGet},
+	Patch:  APIEndpointAction{Handler: storagePoolVolumeTypeContainerPatch},
+	Post:   APIEndpointAction{Handler: storagePoolVolumeTypeContainerPost},
+	Put:    APIEndpointAction{Handler: storagePoolVolumeTypeContainerPut},
 }
 
-var storagePoolVolumeTypeCustomCmd = Command{
-	name:   "storage-pools/{pool}/volumes/custom/{name}",
-	post:   storagePoolVolumeTypeCustomPost,
-	get:    storagePoolVolumeTypeCustomGet,
-	put:    storagePoolVolumeTypeCustomPut,
-	patch:  storagePoolVolumeTypeCustomPatch,
-	delete: storagePoolVolumeTypeCustomDelete,
+var storagePoolVolumeTypeCustomCmd = APIEndpoint{
+	Name: "storage-pools/{pool}/volumes/custom/{name}",
+
+	Delete: APIEndpointAction{Handler: storagePoolVolumeTypeCustomDelete},
+	Get:    APIEndpointAction{Handler: storagePoolVolumeTypeCustomGet},
+	Patch:  APIEndpointAction{Handler: storagePoolVolumeTypeCustomPatch},
+	Post:   APIEndpointAction{Handler: storagePoolVolumeTypeCustomPost},
+	Put:    APIEndpointAction{Handler: storagePoolVolumeTypeCustomPut},
 }
 
-var storagePoolVolumeTypeImageCmd = Command{
-	name:   "storage-pools/{pool}/volumes/image/{name}",
-	post:   storagePoolVolumeTypeImagePost,
-	get:    storagePoolVolumeTypeImageGet,
-	put:    storagePoolVolumeTypeImagePut,
-	patch:  storagePoolVolumeTypeImagePatch,
-	delete: storagePoolVolumeTypeImageDelete,
+var storagePoolVolumeTypeImageCmd = APIEndpoint{
+	Name: "storage-pools/{pool}/volumes/image/{name}",
+
+	Delete: APIEndpointAction{Handler: storagePoolVolumeTypeImageDelete},
+	Get:    APIEndpointAction{Handler: storagePoolVolumeTypeImageGet},
+	Patch:  APIEndpointAction{Handler: storagePoolVolumeTypeImagePatch},
+	Post:   APIEndpointAction{Handler: storagePoolVolumeTypeImagePost},
+	Put:    APIEndpointAction{Handler: storagePoolVolumeTypeImagePut},
 }
 
 // /1.0/storage-pools/{name}/volumes
diff --git a/lxd/storage_volumes_snapshot.go b/lxd/storage_volumes_snapshot.go
index 43a515ad0e..2db90b3736 100644
--- a/lxd/storage_volumes_snapshot.go
+++ b/lxd/storage_volumes_snapshot.go
@@ -15,18 +15,20 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-var storagePoolVolumeSnapshotsTypeCmd = Command{
-	name: "storage-pools/{pool}/volumes/{type}/{name}/snapshots",
-	post: storagePoolVolumeSnapshotsTypePost,
-	get:  storagePoolVolumeSnapshotsTypeGet,
+var storagePoolVolumeSnapshotsTypeCmd = APIEndpoint{
+	Name: "storage-pools/{pool}/volumes/{type}/{name}/snapshots",
+
+	Get:  APIEndpointAction{Handler: storagePoolVolumeSnapshotsTypeGet},
+	Post: APIEndpointAction{Handler: storagePoolVolumeSnapshotsTypePost},
 }
 
-var storagePoolVolumeSnapshotTypeCmd = Command{
-	name:   "storage-pools/{pool}/volumes/{type}/{name}/snapshots/{snapshotName}",
-	post:   storagePoolVolumeSnapshotTypePost,
-	get:    storagePoolVolumeSnapshotTypeGet,
-	put:    storagePoolVolumeSnapshotTypePut,
-	delete: storagePoolVolumeSnapshotTypeDelete,
+var storagePoolVolumeSnapshotTypeCmd = APIEndpoint{
+	Name: "storage-pools/{pool}/volumes/{type}/{name}/snapshots/{snapshotName}",
+
+	Delete: APIEndpointAction{Handler: storagePoolVolumeSnapshotTypeDelete},
+	Get:    APIEndpointAction{Handler: storagePoolVolumeSnapshotTypeGet},
+	Post:   APIEndpointAction{Handler: storagePoolVolumeSnapshotTypePost},
+	Put:    APIEndpointAction{Handler: storagePoolVolumeSnapshotTypePut},
 }
 
 func storagePoolVolumeSnapshotsTypePost(d *Daemon, r *http.Request) Response {

From a67653e7cbd34b32100fca7c738f9104b05160d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:32:46 -0400
Subject: [PATCH 03/14] lxd/network: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/networks.go | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/lxd/networks.go b/lxd/networks.go
index f7bf561220..1f5494b0ff 100644
--- a/lxd/networks.go
+++ b/lxd/networks.go
@@ -34,29 +34,33 @@ import (
 // Lock to prevent concurent networks creation
 var networkCreateLock sync.Mutex
 
-var networksCmd = Command{
-	name: "networks",
-	get:  networksGet,
-	post: networksPost,
+var networksCmd = APIEndpoint{
+	Name: "networks",
+
+	Get:  APIEndpointAction{Handler: networksGet},
+	Post: APIEndpointAction{Handler: networksPost},
 }
 
-var networkCmd = Command{
-	name:   "networks/{name}",
-	get:    networkGet,
-	delete: networkDelete,
-	post:   networkPost,
-	put:    networkPut,
-	patch:  networkPatch,
+var networkCmd = APIEndpoint{
+	Name: "networks/{name}",
+
+	Delete: APIEndpointAction{Handler: networkDelete},
+	Get:    APIEndpointAction{Handler: networkGet},
+	Patch:  APIEndpointAction{Handler: networkPatch},
+	Post:   APIEndpointAction{Handler: networkPost},
+	Put:    APIEndpointAction{Handler: networkPut},
 }
 
-var networkLeasesCmd = Command{
-	name: "networks/{name}/leases",
-	get:  networkLeasesGet,
+var networkLeasesCmd = APIEndpoint{
+	Name: "networks/{name}/leases",
+
+	Get: APIEndpointAction{Handler: networkLeasesGet},
 }
 
-var networkStateCmd = Command{
-	name: "networks/{name}/state",
-	get:  networkStateGet,
+var networkStateCmd = APIEndpoint{
+	Name: "networks/{name}/state",
+
+	Get: APIEndpointAction{Handler: networkStateGet},
 }
 
 // API endpoints

From 67143f498497163647fbf96ae73b9cb8f5a4f603 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:32:59 -0400
Subject: [PATCH 04/14] lxd/container: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/container_logs.go |  16 ++---
 lxd/container_post.go |   7 ++-
 lxd/containers.go     | 133 +++++++++++++++++++++++-------------------
 3 files changed, 86 insertions(+), 70 deletions(-)

diff --git a/lxd/container_logs.go b/lxd/container_logs.go
index 9490ac4ec2..1a41e4971d 100644
--- a/lxd/container_logs.go
+++ b/lxd/container_logs.go
@@ -13,15 +13,17 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-var containerLogCmd = Command{
-	name:   "containers/{name}/logs/{file}",
-	get:    containerLogGet,
-	delete: containerLogDelete,
+var containerLogCmd = APIEndpoint{
+	Name: "containers/{name}/logs/{file}",
+
+	Delete: APIEndpointAction{Handler: containerLogDelete},
+	Get:    APIEndpointAction{Handler: containerLogGet},
 }
 
-var containerLogsCmd = Command{
-	name: "containers/{name}/logs",
-	get:  containerLogsGet,
+var containerLogsCmd = APIEndpoint{
+	Name: "containers/{name}/logs",
+
+	Get: APIEndpointAction{Handler: containerLogsGet},
 }
 
 func containerLogsGet(d *Daemon, r *http.Request) Response {
diff --git a/lxd/container_post.go b/lxd/container_post.go
index 8655ea24d1..b822432676 100644
--- a/lxd/container_post.go
+++ b/lxd/container_post.go
@@ -19,9 +19,10 @@ import (
 	"github.com/lxc/lxd/shared/logger"
 )
 
-var internalClusterContainerMovedCmd = Command{
-	name: "cluster/container-moved/{name}",
-	post: internalClusterContainerMovedPost,
+var internalClusterContainerMovedCmd = APIEndpoint{
+	Name: "cluster/container-moved/{name}",
+
+	Post: APIEndpointAction{Handler: internalClusterContainerMovedPost},
 }
 
 func containerPost(d *Daemon, r *http.Request) Response {
diff --git a/lxd/containers.go b/lxd/containers.go
index 30aa2b6c63..2318514de5 100644
--- a/lxd/containers.go
+++ b/lxd/containers.go
@@ -16,90 +16,103 @@ import (
 	log "github.com/lxc/lxd/shared/log15"
 )
 
-var containersCmd = Command{
-	name: "containers",
-	get:  containersGet,
-	post: containersPost,
+var containersCmd = APIEndpoint{
+	Name: "containers",
+
+	Get:  APIEndpointAction{Handler: containersGet},
+	Post: APIEndpointAction{Handler: containersPost},
 }
 
-var containerCmd = Command{
-	name:   "containers/{name}",
-	get:    containerGet,
-	put:    containerPut,
-	delete: containerDelete,
-	post:   containerPost,
-	patch:  containerPatch,
+var containerCmd = APIEndpoint{
+	Name: "containers/{name}",
+
+	Get:    APIEndpointAction{Handler: containerGet},
+	Put:    APIEndpointAction{Handler: containerPut},
+	Delete: APIEndpointAction{Handler: containerDelete},
+	Post:   APIEndpointAction{Handler: containerPost},
+	Patch:  APIEndpointAction{Handler: containerPatch},
 }
 
-var containerStateCmd = Command{
-	name: "containers/{name}/state",
-	get:  containerState,
-	put:  containerStatePut,
+var containerStateCmd = APIEndpoint{
+	Name: "containers/{name}/state",
+
+	Get: APIEndpointAction{Handler: containerState},
+	Put: APIEndpointAction{Handler: containerStatePut},
 }
 
-var containerFileCmd = Command{
-	name:   "containers/{name}/files",
-	get:    containerFileHandler,
-	post:   containerFileHandler,
-	delete: containerFileHandler,
+var containerFileCmd = APIEndpoint{
+	Name: "containers/{name}/files",
+
+	Get:    APIEndpointAction{Handler: containerFileHandler},
+	Post:   APIEndpointAction{Handler: containerFileHandler},
+	Delete: APIEndpointAction{Handler: containerFileHandler},
 }
 
-var containerSnapshotsCmd = Command{
-	name: "containers/{name}/snapshots",
-	get:  containerSnapshotsGet,
-	post: containerSnapshotsPost,
+var containerSnapshotsCmd = APIEndpoint{
+	Name: "containers/{name}/snapshots",
+
+	Get:  APIEndpointAction{Handler: containerSnapshotsGet},
+	Post: APIEndpointAction{Handler: containerSnapshotsPost},
 }
 
-var containerSnapshotCmd = Command{
-	name:   "containers/{name}/snapshots/{snapshotName}",
-	get:    containerSnapshotHandler,
-	post:   containerSnapshotHandler,
-	delete: containerSnapshotHandler,
-	put:    containerSnapshotHandler,
+var containerSnapshotCmd = APIEndpoint{
+	Name: "containers/{name}/snapshots/{snapshotName}",
+
+	Get:    APIEndpointAction{Handler: containerSnapshotHandler},
+	Post:   APIEndpointAction{Handler: containerSnapshotHandler},
+	Delete: APIEndpointAction{Handler: containerSnapshotHandler},
+	Put:    APIEndpointAction{Handler: containerSnapshotHandler},
 }
 
-var containerConsoleCmd = Command{
-	name:   "containers/{name}/console",
-	get:    containerConsoleLogGet,
-	post:   containerConsolePost,
-	delete: containerConsoleLogDelete,
+var containerConsoleCmd = APIEndpoint{
+	Name: "containers/{name}/console",
+
+	Get:    APIEndpointAction{Handler: containerConsoleLogGet},
+	Post:   APIEndpointAction{Handler: containerConsolePost},
+	Delete: APIEndpointAction{Handler: containerConsoleLogDelete},
 }
 
-var containerExecCmd = Command{
-	name: "containers/{name}/exec",
-	post: containerExecPost,
+var containerExecCmd = APIEndpoint{
+	Name: "containers/{name}/exec",
+
+	Post: APIEndpointAction{Handler: containerExecPost},
 }
 
-var containerMetadataCmd = Command{
-	name: "containers/{name}/metadata",
-	get:  containerMetadataGet,
-	put:  containerMetadataPut,
+var containerMetadataCmd = APIEndpoint{
+	Name: "containers/{name}/metadata",
+
+	Get: APIEndpointAction{Handler: containerMetadataGet},
+	Put: APIEndpointAction{Handler: containerMetadataPut},
 }
 
-var containerMetadataTemplatesCmd = Command{
-	name:   "containers/{name}/metadata/templates",
-	get:    containerMetadataTemplatesGet,
-	post:   containerMetadataTemplatesPostPut,
-	put:    containerMetadataTemplatesPostPut,
-	delete: containerMetadataTemplatesDelete,
+var containerMetadataTemplatesCmd = APIEndpoint{
+	Name: "containers/{name}/metadata/templates",
+
+	Get:    APIEndpointAction{Handler: containerMetadataTemplatesGet},
+	Post:   APIEndpointAction{Handler: containerMetadataTemplatesPostPut},
+	Put:    APIEndpointAction{Handler: containerMetadataTemplatesPostPut},
+	Delete: APIEndpointAction{Handler: containerMetadataTemplatesDelete},
 }
 
-var containerBackupsCmd = Command{
-	name: "containers/{name}/backups",
-	get:  containerBackupsGet,
-	post: containerBackupsPost,
+var containerBackupsCmd = APIEndpoint{
+	Name: "containers/{name}/backups",
+
+	Get:  APIEndpointAction{Handler: containerBackupsGet},
+	Post: APIEndpointAction{Handler: containerBackupsPost},
 }
 
-var containerBackupCmd = Command{
-	name:   "containers/{name}/backups/{backupName}",
-	get:    containerBackupGet,
-	post:   containerBackupPost,
-	delete: containerBackupDelete,
+var containerBackupCmd = APIEndpoint{
+	Name: "containers/{name}/backups/{backupName}",
+
+	Get:    APIEndpointAction{Handler: containerBackupGet},
+	Post:   APIEndpointAction{Handler: containerBackupPost},
+	Delete: APIEndpointAction{Handler: containerBackupDelete},
 }
 
-var containerBackupExportCmd = Command{
-	name: "containers/{name}/backups/{backupName}/export",
-	get:  containerBackupExportGet,
+var containerBackupExportCmd = APIEndpoint{
+	Name: "containers/{name}/backups/{backupName}/export",
+
+	Get: APIEndpointAction{Handler: containerBackupExportGet},
 }
 
 type containerAutostartList []container

From fd3a4d582e58462dd39aecd8f866e6d56dfe22df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:33:08 -0400
Subject: [PATCH 05/14] lxd/profile: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/profiles.go | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lxd/profiles.go b/lxd/profiles.go
index 3be0be4229..de67d574ba 100644
--- a/lxd/profiles.go
+++ b/lxd/profiles.go
@@ -20,19 +20,21 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-var profilesCmd = Command{
-	name: "profiles",
-	get:  profilesGet,
-	post: profilesPost,
+var profilesCmd = APIEndpoint{
+	Name: "profiles",
+
+	Get:  APIEndpointAction{Handler: profilesGet},
+	Post: APIEndpointAction{Handler: profilesPost},
 }
 
-var profileCmd = Command{
-	name:   "profiles/{name}",
-	get:    profileGet,
-	put:    profilePut,
-	delete: profileDelete,
-	post:   profilePost,
-	patch:  profilePatch,
+var profileCmd = APIEndpoint{
+	Name: "profiles/{name}",
+
+	Delete: APIEndpointAction{Handler: profileDelete},
+	Get:    APIEndpointAction{Handler: profileGet},
+	Patch:  APIEndpointAction{Handler: profilePatch},
+	Post:   APIEndpointAction{Handler: profilePost},
+	Put:    APIEndpointAction{Handler: profilePut},
 }
 
 /* This is used for both profiles post and profile put */

From bfa15c1e640b3b4e42c0002ed6b15951822db6ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:33:18 -0400
Subject: [PATCH 06/14] lxd/operation: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/operations.go | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/lxd/operations.go b/lxd/operations.go
index dc096c617c..4043db0804 100644
--- a/lxd/operations.go
+++ b/lxd/operations.go
@@ -23,26 +23,29 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-var operationCmd = Command{
-	name:   "operations/{id}",
-	get:    operationGet,
-	delete: operationDelete,
+var operationCmd = APIEndpoint{
+	Name: "operations/{id}",
+
+	Delete: APIEndpointAction{Handler: operationDelete},
+	Get:    APIEndpointAction{Handler: operationGet},
 }
 
-var operationsCmd = Command{
-	name: "operations",
-	get:  operationsGet,
+var operationsCmd = APIEndpoint{
+	Name: "operations",
+
+	Get: APIEndpointAction{Handler: operationsGet},
 }
 
-var operationWait = Command{
-	name: "operations/{id}/wait",
-	get:  operationWaitGet,
+var operationWait = APIEndpoint{
+	Name: "operations/{id}/wait",
+
+	Get: APIEndpointAction{Handler: operationWaitGet},
 }
 
-var operationWebsocket = Command{
-	name:         "operations/{id}/websocket",
-	untrustedGet: true,
-	get:          operationWebsocketGet,
+var operationWebsocket = APIEndpoint{
+	Name: "operations/{id}/websocket",
+
+	Get: APIEndpointAction{Handler: operationWebsocketGet, AllowUntrusted: true},
 }
 
 var operationsLock sync.Mutex

From ada335b8216a8627c13b0c3567a775b886f9fe94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:33:41 -0400
Subject: [PATCH 07/14] lxd/project: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_project.go | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/lxd/api_project.go b/lxd/api_project.go
index 814a021d51..e8ddd4b320 100644
--- a/lxd/api_project.go
+++ b/lxd/api_project.go
@@ -19,19 +19,21 @@ import (
 	"github.com/lxc/lxd/shared/version"
 )
 
-var projectsCmd = Command{
-	name: "projects",
-	get:  projectsGet,
-	post: projectsPost,
+var projectsCmd = APIEndpoint{
+	Name: "projects",
+
+	Get:  APIEndpointAction{Handler: projectsGet},
+	Post: APIEndpointAction{Handler: projectsPost},
 }
 
-var projectCmd = Command{
-	name:   "projects/{name}",
-	get:    projectGet,
-	post:   projectPost,
-	put:    projectPut,
-	patch:  projectPatch,
-	delete: projectDelete,
+var projectCmd = APIEndpoint{
+	Name: "projects/{name}",
+
+	Delete: APIEndpointAction{Handler: projectDelete},
+	Get:    APIEndpointAction{Handler: projectGet},
+	Patch:  APIEndpointAction{Handler: projectPatch},
+	Post:   APIEndpointAction{Handler: projectPost},
+	Put:    APIEndpointAction{Handler: projectPut},
 }
 
 func projectsGet(d *Daemon, r *http.Request) Response {

From bbd106cf1575e5a42f57849381c30864d1dba02a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:33:50 -0400
Subject: [PATCH 08/14] lxd/internal: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_internal.go | 65 ++++++++++++++++++++++++++-------------------
 1 file changed, 37 insertions(+), 28 deletions(-)

diff --git a/lxd/api_internal.go b/lxd/api_internal.go
index 0ac9a6e912..508801f243 100644
--- a/lxd/api_internal.go
+++ b/lxd/api_internal.go
@@ -45,50 +45,59 @@ var apiInternal = []APIEndpoint{
 	internalRAFTSnapshotCmd,
 }
 
-var internalShutdownCmd = Command{
-	name: "shutdown",
-	put:  internalShutdown,
+var internalShutdownCmd = APIEndpoint{
+	Name: "shutdown",
+
+	Put: APIEndpointAction{Handler: internalShutdown},
 }
 
-var internalReadyCmd = Command{
-	name: "ready",
-	get:  internalWaitReady,
+var internalReadyCmd = APIEndpoint{
+	Name: "ready",
+
+	Get: APIEndpointAction{Handler: internalWaitReady},
 }
 
-var internalContainerOnStartCmd = Command{
-	name: "containers/{id}/onstart",
-	get:  internalContainerOnStart,
+var internalContainerOnStartCmd = APIEndpoint{
+	Name: "containers/{id}/onstart",
+
+	Get: APIEndpointAction{Handler: internalContainerOnStart},
 }
 
-var internalContainerOnStopCmd = Command{
-	name: "containers/{id}/onstop",
-	get:  internalContainerOnStop,
+var internalContainerOnStopCmd = APIEndpoint{
+	Name: "containers/{id}/onstop",
+
+	Get: APIEndpointAction{Handler: internalContainerOnStop},
 }
 
-var internalContainerOnNetworkUpCmd = Command{
-	name: "containers/{id}/onnetwork-up",
-	get:  internalContainerOnNetworkUp,
+var internalContainerOnNetworkUpCmd = APIEndpoint{
+	Name: "containers/{id}/onnetwork-up",
+
+	Get: APIEndpointAction{Handler: internalContainerOnNetworkUp},
 }
 
-var internalSQLCmd = Command{
-	name: "sql",
-	get:  internalSQLGet,
-	post: internalSQLPost,
+var internalSQLCmd = APIEndpoint{
+	Name: "sql",
+
+	Get:  APIEndpointAction{Handler: internalSQLGet},
+	Post: APIEndpointAction{Handler: internalSQLPost},
 }
 
-var internalContainersCmd = Command{
-	name: "containers",
-	post: internalImport,
+var internalContainersCmd = APIEndpoint{
+	Name: "containers",
+
+	Post: APIEndpointAction{Handler: internalImport},
 }
 
-var internalGarbageCollectorCmd = Command{
-	name: "gc",
-	get:  internalGC,
+var internalGarbageCollectorCmd = APIEndpoint{
+	Name: "gc",
+
+	Get: APIEndpointAction{Handler: internalGC},
 }
 
-var internalRAFTSnapshotCmd = Command{
-	name: "raft-snapshot",
-	get:  internalRAFTSnapshot,
+var internalRAFTSnapshotCmd = APIEndpoint{
+	Name: "raft-snapshot",
+
+	Get: APIEndpointAction{Handler: internalRAFTSnapshot},
 }
 
 func internalWaitReady(d *Daemon, r *http.Request) Response {

From 7128a7d4d6aeb23cb7602b75facf1da2e0eb5949 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:33:59 -0400
Subject: [PATCH 09/14] lxd/certificate: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/certificates.go | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/lxd/certificates.go b/lxd/certificates.go
index 8c0b8bcc2b..b17b2a41b3 100644
--- a/lxd/certificates.go
+++ b/lxd/certificates.go
@@ -24,19 +24,20 @@ import (
 	log "github.com/lxc/lxd/shared/log15"
 )
 
-var certificatesCmd = Command{
-	name:          "certificates",
-	untrustedPost: true,
-	get:           certificatesGet,
-	post:          certificatesPost,
+var certificatesCmd = APIEndpoint{
+	Name: "certificates",
+
+	Get:  APIEndpointAction{Handler: certificatesGet, AllowUntrusted: true},
+	Post: APIEndpointAction{Handler: certificatesPost},
 }
 
-var certificateCmd = Command{
-	name:   "certificates/{fingerprint}",
-	get:    certificateGet,
-	delete: certificateDelete,
-	put:    certificatePut,
-	patch:  certificatePatch,
+var certificateCmd = APIEndpoint{
+	Name: "certificates/{fingerprint}",
+
+	Delete: APIEndpointAction{Handler: certificateDelete},
+	Get:    APIEndpointAction{Handler: certificateGet},
+	Patch:  APIEndpointAction{Handler: certificatePatch},
+	Put:    APIEndpointAction{Handler: certificatePut},
 }
 
 func certificatesGet(d *Daemon, r *http.Request) Response {

From 030a21ea775112c51e8adc89fc35c09dd6f3b858 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:34:06 -0400
Subject: [PATCH 10/14] lxd/image: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/images.go | 71 +++++++++++++++++++++++++++------------------------
 1 file changed, 37 insertions(+), 34 deletions(-)

diff --git a/lxd/images.go b/lxd/images.go
index 746904a49b..91ab7e8f91 100644
--- a/lxd/images.go
+++ b/lxd/images.go
@@ -42,52 +42,55 @@ import (
 	log "github.com/lxc/lxd/shared/log15"
 )
 
-var imagesCmd = Command{
-	name:         "images",
-	post:         imagesPost,
-	untrustedGet: true,
-	get:          imagesGet,
+var imagesCmd = APIEndpoint{
+	Name: "images",
+
+	Get:  APIEndpointAction{Handler: imagesGet, AllowUntrusted: true},
+	Post: APIEndpointAction{Handler: imagesPost},
 }
 
-var imageCmd = Command{
-	name:         "images/{fingerprint}",
-	untrustedGet: true,
-	get:          imageGet,
-	put:          imagePut,
-	delete:       imageDelete,
-	patch:        imagePatch,
+var imageCmd = APIEndpoint{
+	Name: "images/{fingerprint}",
+
+	Delete: APIEndpointAction{Handler: imageDelete},
+	Get:    APIEndpointAction{Handler: imageGet, AllowUntrusted: true},
+	Patch:  APIEndpointAction{Handler: imagePatch},
+	Put:    APIEndpointAction{Handler: imagePut},
 }
 
-var imageExportCmd = Command{
-	name:         "images/{fingerprint}/export",
-	untrustedGet: true,
-	get:          imageExport,
+var imageExportCmd = APIEndpoint{
+	Name: "images/{fingerprint}/export",
+
+	Get: APIEndpointAction{Handler: imageExport, AllowUntrusted: true},
 }
 
-var imageSecretCmd = Command{
-	name: "images/{fingerprint}/secret",
-	post: imageSecret,
+var imageSecretCmd = APIEndpoint{
+	Name: "images/{fingerprint}/secret",
+
+	Post: APIEndpointAction{Handler: imageSecret},
 }
 
-var imageRefreshCmd = Command{
-	name: "images/{fingerprint}/refresh",
-	post: imageRefresh,
+var imageRefreshCmd = APIEndpoint{
+	Name: "images/{fingerprint}/refresh",
+
+	Post: APIEndpointAction{Handler: imageRefresh},
 }
 
-var imageAliasesCmd = Command{
-	name: "images/aliases",
-	post: imageAliasesPost,
-	get:  imageAliasesGet,
+var imageAliasesCmd = APIEndpoint{
+	Name: "images/aliases",
+
+	Get:  APIEndpointAction{Handler: imageAliasesGet},
+	Post: APIEndpointAction{Handler: imageAliasesPost},
 }
 
-var imageAliasCmd = Command{
-	name:         "images/aliases/{name:.*}",
-	untrustedGet: true,
-	get:          imageAliasGet,
-	delete:       imageAliasDelete,
-	put:          imageAliasPut,
-	post:         imageAliasPost,
-	patch:        imageAliasPatch,
+var imageAliasCmd = APIEndpoint{
+	Name: "images/aliases/{name:.*}",
+
+	Delete: APIEndpointAction{Handler: imageAliasDelete},
+	Get:    APIEndpointAction{Handler: imageAliasGet, AllowUntrusted: true},
+	Patch:  APIEndpointAction{Handler: imageAliasPatch},
+	Post:   APIEndpointAction{Handler: imageAliasPost},
+	Put:    APIEndpointAction{Handler: imageAliasPut},
 }
 
 /* We only want a single publish running at any one time.

From 0653a9582e0231740e50185a885aea3c5bd6f002 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:34:25 -0400
Subject: [PATCH 11/14] lxd/cluster: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_cluster.go | 48 ++++++++++++++++++++++++++--------------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/lxd/api_cluster.go b/lxd/api_cluster.go
index b930c8a18c..8912a622d1 100644
--- a/lxd/api_cluster.go
+++ b/lxd/api_cluster.go
@@ -25,37 +25,43 @@ import (
 	"github.com/pkg/errors"
 )
 
-var clusterCmd = Command{
-	name: "cluster",
-	get:  clusterGet,
-	put:  clusterPut,
+var clusterCmd = APIEndpoint{
+	Name: "cluster",
+
+	Get: APIEndpointAction{Handler: clusterGet},
+	Put: APIEndpointAction{Handler: clusterPut},
 }
 
-var clusterNodesCmd = Command{
-	name: "cluster/members",
-	get:  clusterNodesGet,
+var clusterNodesCmd = APIEndpoint{
+	Name: "cluster/members",
+
+	Get: APIEndpointAction{Handler: clusterNodesGet},
 }
 
-var clusterNodeCmd = Command{
-	name:   "cluster/members/{name}",
-	get:    clusterNodeGet,
-	post:   clusterNodePost,
-	delete: clusterNodeDelete,
+var clusterNodeCmd = APIEndpoint{
+	Name: "cluster/members/{name}",
+
+	Delete: APIEndpointAction{Handler: clusterNodeDelete},
+	Get:    APIEndpointAction{Handler: clusterNodeGet},
+	Post:   APIEndpointAction{Handler: clusterNodePost},
 }
 
-var internalClusterAcceptCmd = Command{
-	name: "cluster/accept",
-	post: internalClusterPostAccept,
+var internalClusterAcceptCmd = APIEndpoint{
+	Name: "cluster/accept",
+
+	Post: APIEndpointAction{Handler: internalClusterPostAccept},
 }
 
-var internalClusterRebalanceCmd = Command{
-	name: "cluster/rebalance",
-	post: internalClusterPostRebalance,
+var internalClusterRebalanceCmd = APIEndpoint{
+	Name: "cluster/rebalance",
+
+	Post: APIEndpointAction{Handler: internalClusterPostRebalance},
 }
 
-var internalClusterPromoteCmd = Command{
-	name: "cluster/promote",
-	post: internalClusterPostPromote,
+var internalClusterPromoteCmd = APIEndpoint{
+	Name: "cluster/promote",
+
+	Post: APIEndpointAction{Handler: internalClusterPostPromote},
 }
 
 // Return information about the cluster.

From 34b2954abcd9f5062fef01c45cc92ef08106c6c6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:34:40 -0400
Subject: [PATCH 12/14] lxd/resource: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/resources.go | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/lxd/resources.go b/lxd/resources.go
index 161dbcc91a..5c900ca243 100644
--- a/lxd/resources.go
+++ b/lxd/resources.go
@@ -10,14 +10,16 @@ import (
 	"github.com/lxc/lxd/shared/api"
 )
 
-var api10ResourcesCmd = Command{
-	name: "resources",
-	get:  api10ResourcesGet,
+var api10ResourcesCmd = APIEndpoint{
+	Name: "resources",
+
+	Get: APIEndpointAction{Handler: api10ResourcesGet},
 }
 
-var storagePoolResourcesCmd = Command{
-	name: "storage-pools/{name}/resources",
-	get:  storagePoolResourcesGet,
+var storagePoolResourcesCmd = APIEndpoint{
+	Name: "storage-pools/{name}/resources",
+
+	Get: APIEndpointAction{Handler: storagePoolResourcesGet},
 }
 
 // /1.0/resources

From 5451afd8d69ce6bf98c4275bb86d8190852001e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:34:54 -0400
Subject: [PATCH 13/14] lxd/event: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/events.go | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lxd/events.go b/lxd/events.go
index 10434b415a..bc050c350a 100644
--- a/lxd/events.go
+++ b/lxd/events.go
@@ -18,9 +18,10 @@ import (
 	"github.com/lxc/lxd/shared/logger"
 )
 
-var eventsCmd = Command{
-	name: "events",
-	get:  eventsGet,
+var eventsCmd = APIEndpoint{
+	Name: "events",
+
+	Get: APIEndpointAction{Handler: eventsGet},
 }
 
 type eventsHandler struct {

From 2754cb48f819dc4ada848154cfdc09b1c054a3b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber at ubuntu.com>
Date: Wed, 24 Apr 2019 18:35:07 -0400
Subject: [PATCH 14/14] lxd/daemon: Port to APIEndpoint
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber at ubuntu.com>
---
 lxd/api_1.0.go | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lxd/api_1.0.go b/lxd/api_1.0.go
index c92c76e6f1..98ce46c196 100644
--- a/lxd/api_1.0.go
+++ b/lxd/api_1.0.go
@@ -21,12 +21,10 @@ import (
 	"github.com/pkg/errors"
 )
 
-var api10Cmd = Command{
-	name:         "",
-	untrustedGet: true,
-	get:          api10Get,
-	put:          api10Put,
-	patch:        api10Patch,
+var api10Cmd = APIEndpoint{
+	Get:   APIEndpointAction{Handler: api10Get, AllowUntrusted: true},
+	Patch: APIEndpointAction{Handler: api10Patch},
+	Put:   APIEndpointAction{Handler: api10Put},
 }
 
 var api10 = []APIEndpoint{


More information about the lxc-devel mailing list