From be2860af7d82d788d556fd5ddb60e8c358e29df4 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 14 Mar 2017 14:01:28 -0700 Subject: [PATCH 01/30] db rp documentation WIP --- server/swagger.json | 209 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 208 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index 4b67b131c..d5730e84c 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -769,6 +769,174 @@ } } }, + "/sources/{id}/dbs/": { + "get": { + "summary": "Retrieve all databases for a source", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + } + ], + "responses": { + "200": { + "description": "Listing of all databases for a source", + "schema": { + "$ref": "#/definitions/Databases" + } + }, + "404": { + "description": "Data source id does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "summary": "Create new database for a source", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + } + ], + "responses": { + "201": { + "description": "Database successfully created.", + "schema": { + "$ref": "#/definitions/Database" + } + }, + "404": { + "description": "Data source id does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/sources/{id}/dbs/{db_id}": { + "get": { + + }, + "patch": { + + }, + "delete": { + + } + }, + "/sources/{id}/dbs/{db_id}/rps": { + "get": { + "summary": "Retrieve all retention policies for a database", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + }, + { + "name": "db_id", + "in": "path", + "type": "string", + "description": "ID of the database", + "required": true + } + ], + "responses": { + "200": { + "description": "Listing of all retention policies for a database", + "schema": { + "$ref": "#/definitions/RetentionPolicies" + } + }, + "404": { + "description": "Specified retention policy does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + }, + "post": { + "summary": "Create new retention policy for a database", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + }, + { + "name": "db_id", + "in": "path", + "type": "string", + "description": "ID of the database", + "required": true + } + ], + "responses": { + "201": { + "description": "Retention Policy successfully created.", + "schema": { + "$ref": "#/definitions/RetentionPolicy" + } + }, + "404": { + "description": "Data source id does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } + } + }, + "/sources/{id}/dbs/{db_id}/rps/{rp_id}": { + "get": { + + }, + "patch": { + + }, + "delete": { + + } + }, "/sources/{id}/kapacitors": { "get": { "tags": [ @@ -1912,6 +2080,45 @@ } }, "definitions": { + "Databases": { + "type": "object", + "required": [ + "databases" + ], + "properties": { + "databases": { + "type": "array", + "items": { + "$ref": "#/definitions/Database" + } + } + } + }, + "Database": { + "type": "object", + "required": [ + "name" + ], + "example": { + + }, + "properties": { + "name": { + "type": "string", + "description": "The identifying name of the database", + }, + "duration": { + "type": "", + "description": "the duration of the default retention policy" + }, + "replication": { + + }, + "shardDuration": { + + } + } + }, "Kapacitors": { "type": "object", "required": [ @@ -3313,4 +3520,4 @@ } } } -} \ No newline at end of file +} From 460f23c0c0362841a800e3a62e45b763915b7a2a Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 14 Mar 2017 15:31:57 -0700 Subject: [PATCH 02/30] first whack at db rp server endpoints --- server/swagger.json | 136 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 12 deletions(-) diff --git a/server/swagger.json b/server/swagger.json index d5730e84c..b1dc3e59c 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -811,6 +811,15 @@ "type": "string", "description": "ID of the data source", "required": true + }, + { + "name": "database", + "in": "body", + "description": "Configuration options for a database", + "schema": { + "$ref": "#/definitions/Database" + }, + "required": true } ], "responses": { @@ -836,14 +845,41 @@ } }, "/sources/{id}/dbs/{db_id}": { - "get": { - - }, - "patch": { - - }, "delete": { - + "summary": "Delete database for a source", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + }, + { + "name": "db_id", + "in": "path", + "type": "string", + "description": "ID of the database", + "required": true + } + ], + "responses": { + "204": { + "description": "Database has been deleted", + }, + "404": { + "description": "Data source id does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } } }, "/sources/{id}/dbs/{db_id}/rps": { @@ -902,6 +938,15 @@ "type": "string", "description": "ID of the database", "required": true + }, + { + "name": "rp", + "in": "body", + "description": "Configuration options for the retention policy", + "schema": { + "$ref": "#/definitions/RetentionPolicy" + }, + "required": true } ], "responses": { @@ -927,14 +972,81 @@ } }, "/sources/{id}/dbs/{db_id}/rps/{rp_id}": { - "get": { - - }, "patch": { - + "summary": "Alter retention policy for a database", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + }, + { + "name": "db_id", + "in": "path", + "type": "string", + "description": "ID of the database", + "required": true + }, + { + "name": "rp_id", + "in": "path", + "description": "ID of the retention policy", + "required": true + } + { + "name": "rp", + "in": "body", + "description": "Configuration options for the retention policy", + "schema": { + "$ref": "#/definitions/RetentionPolicy" + }, + "required": true + } + ] }, "delete": { - + "summary": "Delete retention policy for a database", + "parameters": [ + { + "name": "id", + "in": "path", + "type": "string", + "description": "ID of the data source", + "required": true + }, + { + "name": "db_id", + "in": "path", + "type": "string", + "description": "ID of the database", + "required": true + }, + { + "name": "rp_id", + "in": "path", + "description": "ID of the retention policy", + "required": true + } + ], + "responses": { + "204": { + "description": "Retention Policy has been deleted", + }, + "404": { + "description": "Data source id does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } } }, "/sources/{id}/kapacitors": { From 141c93bc5f5f7c0e395be767603550c4fb52cb0a Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 14 Mar 2017 16:05:13 -0700 Subject: [PATCH 03/30] db rp server endpoint objects --- server/swagger.json | 61 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/server/swagger.json b/server/swagger.json index b1dc3e59c..9d2a3c6f4 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2212,7 +2212,10 @@ "name" ], "example": { - + "name": "NOAA_water_database", + "duration": "3d", + "replication": 3, + "shardDuration": "3h" }, "properties": { "name": { @@ -2220,14 +2223,17 @@ "description": "The identifying name of the database", }, "duration": { - "type": "", + "type": "string", "description": "the duration of the default retention policy" }, "replication": { - + "type": "integer", + "format": "int32", + "description": "how many copies of the data are stored in the cluster" }, "shardDuration": { - + "type": "string", + "description": "the interval spanned by each shard group" } } }, @@ -2469,6 +2475,53 @@ } } }, + "RetentionPolicies": { + "type": "object", + "required": [ + "retentionPolicies" + ], + "properties": { + "retentionPolicies": { + "type": "array", + "items": { + "$ref": "#/definitions/RetentionPolicy" + } + } + } + }, + "RetentionPolicy": { + "type": "object", + "required": [ + "name", + "duration", + "replication" + ], + "example": { + }, + "properties": { + "name": { + "type": "string", + "description": "The identifying name of the retention policy", + }, + "duration": { + "type": "string", + "description": "the duration of the retention policy" + }, + "replication": { + "type": "integer", + "format": "int32", + "description": "how many copies of the data are stored in the cluster" + }, + "shardDuration": { + "type": "string", + "description": "the interval spanned by each shard group" + }, + "default": { + "type": "boolean", + "description": "Indicates whether this retention policy should be the default" + } + } + }, "Rule": { "type": "object", "example": { From 310f7dc7c57eb701e03bfbc3656125db3fce0214 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 14 Mar 2017 16:44:44 -0700 Subject: [PATCH 04/30] fix swagger errors, add tags --- server/swagger.json | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index 9d2a3c6f4..0baf6630a 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -771,6 +771,9 @@ }, "/sources/{id}/dbs/": { "get": { + "tags": [ + "databases" + ], "summary": "Retrieve all databases for a source", "parameters": [ { @@ -803,6 +806,9 @@ } }, "post": { + "tags": [ + "databases" + ], "summary": "Create new database for a source", "parameters": [ { @@ -846,6 +852,9 @@ }, "/sources/{id}/dbs/{db_id}": { "delete": { + "tags": [ + "databases" + ], "summary": "Delete database for a source", "parameters": [ { @@ -884,6 +893,9 @@ }, "/sources/{id}/dbs/{db_id}/rps": { "get": { + "tags": [ + "retention policies" + ], "summary": "Retrieve all retention policies for a database", "parameters": [ { @@ -923,6 +935,9 @@ } }, "post": { + "tags": [ + "retention policies" + ], "summary": "Create new retention policy for a database", "parameters": [ { @@ -973,6 +988,9 @@ }, "/sources/{id}/dbs/{db_id}/rps/{rp_id}": { "patch": { + "tags": [ + "retention policies" + ], "summary": "Alter retention policy for a database", "parameters": [ { @@ -992,9 +1010,10 @@ { "name": "rp_id", "in": "path", + "type": "string", "description": "ID of the retention policy", "required": true - } + }, { "name": "rp", "in": "body", @@ -1007,6 +1026,9 @@ ] }, "delete": { + "tags": [ + "retention policies" + ], "summary": "Delete retention policy for a database", "parameters": [ { @@ -1026,6 +1048,7 @@ { "name": "rp_id", "in": "path", + "type": "string", "description": "ID of the retention policy", "required": true } From b9e101c83144a93385fda63e1193ffccc802087c Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 14 Mar 2017 16:53:41 -0700 Subject: [PATCH 05/30] add example for retention policy --- server/swagger.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/swagger.json b/server/swagger.json index 0baf6630a..ae2598680 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2520,6 +2520,11 @@ "replication" ], "example": { + "name": "weekly", + "duration": "7d", + "replication": 1, + "shardDuration": "7d", + "default": true }, "properties": { "name": { From 5859beb6031a83aedb59d9551d5221abb5a378ea Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 20 Mar 2017 11:48:25 -0700 Subject: [PATCH 06/30] add links to database swagger object --- server/swagger.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index ae2598680..42c397635 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2238,7 +2238,10 @@ "name": "NOAA_water_database", "duration": "3d", "replication": 3, - "shardDuration": "3h" + "shardDuration": "3h", + "links": { + "self": "/chronograf/v1/sources/1/dbs/NOAA_water_database" + } }, "properties": { "name": { @@ -2257,6 +2260,16 @@ "shardDuration": { "type": "string", "description": "the interval spanned by each shard group" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "Self link mapping to this resource", + "format": "url" + } + } } } }, From 626b313d98609749a6991d7bb64290ad72ea318f Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 20 Mar 2017 11:52:49 -0700 Subject: [PATCH 07/30] add links to retentionpolicy swagger --- server/swagger.json | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index 42c397635..725e56203 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2537,7 +2537,10 @@ "duration": "7d", "replication": 1, "shardDuration": "7d", - "default": true + "default": true, + "links": { + "self": "/chronograf/v1/ousrces/1/dbs/NOAA_water_database/rps/liquid" + } }, "properties": { "name": { @@ -2560,6 +2563,16 @@ "default": { "type": "boolean", "description": "Indicates whether this retention policy should be the default" + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "Self link mapping to this resource", + "format": "url" + } + } } } }, From 4ac8d72902d7b3477f20fc714059039cf776b21c Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 20 Mar 2017 11:58:09 -0700 Subject: [PATCH 08/30] link to retention policies in db response --- server/swagger.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index 725e56203..97e09c58f 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -2240,7 +2240,8 @@ "replication": 3, "shardDuration": "3h", "links": { - "self": "/chronograf/v1/sources/1/dbs/NOAA_water_database" + "self": "/chronograf/v1/sources/1/dbs/NOAA_water_database", + "rps": "/chronograf/v1/sources/1/dbs/NOAA_water_database/rps" } }, "properties": { @@ -2268,6 +2269,11 @@ "type": "string", "description": "Self link mapping to this resource", "format": "url" + }, + "rps": { + "type": "string", + "description": "Link to retention policies for this database", + "format": "url" } } } From b443d857ca71285efce1bffe35cf8789be97e9c6 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 20 Mar 2017 14:23:29 -0700 Subject: [PATCH 09/30] add db and rp routes to mux.go --- server/mux.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/mux.go b/server/mux.go index 1738ba255..e549ca410 100644 --- a/server/mux.go +++ b/server/mux.go @@ -131,6 +131,19 @@ func NewMux(opts MuxOpts, service Service) http.Handler { router.PUT("/chronograf/v1/dashboards/:id", service.ReplaceDashboard) router.PATCH("/chronograf/v1/dashboards/:id", service.UpdateDashboard) + // Databases + router.GET("/chronograf/v1/sources/:id/dbs", service.Databases) + router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) + + router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) + + // Retention Policies + router.GET("/chronograf/v1/sources/:id/dbs/:did/rps", service.RetentionPolicies) + router.POST("/chronograf/v1/sources/:id/dbs/:did/rps", service.NewRetentionPolicy) + + router.PATCH("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.UpdateRetentionPolicy) + router.DELETE("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.DropRetentionPolicy) + var authRoutes AuthRoutes var out http.Handler From e1ccda806cc22e21f732e7cbe2c5171073e8c190 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 20 Mar 2017 15:26:48 -0700 Subject: [PATCH 10/30] WIP db endpoint --- server/databases.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 server/databases.go diff --git a/server/databases.go b/server/databases.go new file mode 100644 index 000000000..a11c69fbb --- /dev/null +++ b/server/databases.go @@ -0,0 +1,25 @@ +package server + +import ( + "net/http" + "fmt" +) + +type jsonResponse struct{ + id int +} + +// Databases queries the list of all databases for a source +func (h *Service) Databases (w http.ResponseWriter, r *http.Request) { + fmt.Print("database endpoint") + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + res := jsonResponse{id: srcID} + + encodeJSON(w, http.StatusOK, res, h.Logger) +} From 36ffe0c436e85105bfa4f3cebbc4fb6851a45adb Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Tue, 21 Mar 2017 12:59:27 -0700 Subject: [PATCH 11/30] dbs GET returns list of databases --- server/databases.go | 82 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/server/databases.go b/server/databases.go index a11c69fbb..0bb112bf4 100644 --- a/server/databases.go +++ b/server/databases.go @@ -1,25 +1,81 @@ package server import ( - "net/http" - "fmt" + "fmt" + "net/http" + + "github.com/influxdata/chronograf" ) -type jsonResponse struct{ - id int +type dbLinks struct { + Self string `json:"self"` // Self link mapping to this resource + RPs string `json:"rps"` // URL for retention policies for this database +} + +type database struct { + Name string `json:"name"` // a unique string identifier for the database + Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) + Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) + ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) + Links dbLinks `json:links` // Links are URI locations related to the database +} + +type postInfluxResponze struct { + Results interface{} `json:"results"` // results from influx } // Databases queries the list of all databases for a source -func (h *Service) Databases (w http.ResponseWriter, r *http.Request) { - fmt.Print("database endpoint") +func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { + id, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } - srcID, err := paramID("id", r) - if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return - } + // res := []database{} - res := jsonResponse{id: srcID} + // move this influxdb communication code somewhere else after it's working + // START + ctx := r.Context() + src, err := h.SourcesStore.Get(ctx, id) + if err != nil { + notFound(w, id, h.Logger) + return + } - encodeJSON(w, http.StatusOK, res, h.Logger) + ts, err := h.TimeSeries(src) + if err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + if err = ts.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + req := chronograf.Query{Command: "SHOW DATABASES"} + + response, err := ts.Query(ctx, req) + if err != nil { + if err == chronograf.ErrUpstreamTimeout { + msg := "Timeout waiting for Influx response" + Error(w, http.StatusRequestTimeout, msg, h.Logger) + return + } + // TODO: Here I want to return the error code from influx. + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + res := postInfluxResponze{ + Results: response, + } + + //fmt.Printf("%+v\n", foo) + // END + + encodeJSON(w, http.StatusOK, res, h.Logger) } From 056abde56dda6dfb030d46e73796fb889ab0c797 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 01:40:30 -0700 Subject: [PATCH 12/30] WIP --- chronograf.go | 14 +++++ enterprise/enterprise.go | 2 + enterprise/types.go | 11 ++++ influx/influx.go | 4 ++ influx/permissions.go | 18 +++++++ server/databases.go | 109 ++++++++++++++++++++------------------- server/mux.go | 20 +++---- 7 files changed, 116 insertions(+), 62 deletions(-) diff --git a/chronograf.go b/chronograf.go index fc624bea4..afd1cbc8d 100644 --- a/chronograf.go +++ b/chronograf.go @@ -59,6 +59,8 @@ type TimeSeries interface { Permissions(context.Context) Permissions // Roles represents the roles associated with this TimesSeriesDatabase Roles(context.Context) (RolesStore, error) + // Databases represents the named databases within an InfluxDB instance + Databases(context.Context) Databases } // Role is a restricted set of permissions assigned to a set of users. @@ -294,6 +296,18 @@ type UsersStore interface { Update(context.Context, *User) error } +// type Database struct { +// Name string `json:"name"` // a unique string identifier for the database +// Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) +// Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) +// ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) +// } +// +// type Databases interface { +// // All lists all databases +// AllDB(context.Context) ([]Database, error) +// } + // DashboardID is the dashboard ID type DashboardID int diff --git a/enterprise/enterprise.go b/enterprise/enterprise.go index 189e5a150..9e82d4695 100644 --- a/enterprise/enterprise.go +++ b/enterprise/enterprise.go @@ -34,6 +34,8 @@ type Ctrl interface { SetRoleUsers(ctx context.Context, name string, users []string) error AddRoleUsers(ctx context.Context, name string, users []string) error RemoveRoleUsers(ctx context.Context, name string, users []string) error + + Databases(ctx context.Context) (*Databases, error) } // Client is a device for retrieving time series data from an Influx Enterprise diff --git a/enterprise/types.go b/enterprise/types.go index d3c241ca2..6e0f161af 100644 --- a/enterprise/types.go +++ b/enterprise/types.go @@ -65,6 +65,17 @@ type RoleAction struct { Role *Role `json:"role"` } +type Database struct { + Name string `json:"name"` // a unique string identifier for the database + Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) + Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) + ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) +} + +type Databases struct { + Databases []Database `json:"databases,omitempty"` +} + // Error is JSON error message return by Influx Enterprise's meta API. type Error struct { Error string `json:"error"` diff --git a/influx/influx.go b/influx/influx.go index 02d8eebf1..857c158fb 100644 --- a/influx/influx.go +++ b/influx/influx.go @@ -180,6 +180,10 @@ func (c *Client) Users(ctx context.Context) chronograf.UsersStore { return c } +func (c *Client) Databases(ctx context.Context) chronograf.Databases { + return c +} + // Roles aren't support in OSS func (c *Client) Roles(ctx context.Context) (chronograf.RolesStore, error) { return nil, fmt.Errorf("Roles not support in open-source InfluxDB. Roles are support in Influx Enterprise") diff --git a/influx/permissions.go b/influx/permissions.go index 809aff953..07fe482c0 100644 --- a/influx/permissions.go +++ b/influx/permissions.go @@ -75,6 +75,24 @@ func (r *showResults) Users() []chronograf.User { return res } +// Databases converts SHOW DATABASES to chronograf Databases +func (r *showResults) Databases() []chronograf.Database { + res := []chronograf.Database{} + for _, u := range *r { + for _, s := range u.Series { + for _, v := range s.Values { + if name, ok := v[0].(string); !ok { + continue + } else { + d := chronograf.Database{Name: name} + res = append(res, d) + } + } + } + } + return res +} + // Permissions converts SHOW GRANTS to chronograf.Permissions func (r *showResults) Permissions() chronograf.Permissions { res := []chronograf.Permission{} diff --git a/server/databases.go b/server/databases.go index 0bb112bf4..7228ea15a 100644 --- a/server/databases.go +++ b/server/databases.go @@ -12,7 +12,7 @@ type dbLinks struct { RPs string `json:"rps"` // URL for retention policies for this database } -type database struct { +type dbResponse struct { Name string `json:"name"` // a unique string identifier for the database Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) @@ -20,62 +20,67 @@ type database struct { Links dbLinks `json:links` // Links are URI locations related to the database } -type postInfluxResponze struct { - Results interface{} `json:"results"` // results from influx +type dbsResponse struct { + Databases []dbResponse `json:"databases"` } +// type influxResponse struct { +// Results interface{} `json:"results"` // results from influx +// } + +// func (h *Service) sourcesSeries(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.TimeSeries, error) { +// srcID, err := paramID("id", r) +// if err != nil { +// Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) +// return 0, nil, err +// } +// +// src, err := h.SourcesStore.Get(ctx, srcID) +// if err != nil { +// notFound(w, srcID, h.Logger) +// return 0, nil, err +// } +// +// ts, err := h.TimeSeries(src) +// if err != nil { +// msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) +// Error(w, http.StatusBadRequest, msg, h.Logger) +// return 0, nil, err +// } +// +// if err = ts.Connect(ctx, &src); err != nil { +// msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) +// Error(w, http.StatusBadRequest, msg, h.Logger) +// return 0, nil, err +// } +// return srcID, ts, nil +// } + // Databases queries the list of all databases for a source func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { - id, err := paramID("id", r) - if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return + ctx := r.Context() + srcID, ts, err := h.sourcesSeries(ctx, w, r) + if err != nil { + return + } + + store := ts.Databases(ctx) + databases, err := store.All(ctx) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + dbs := make([]dbResponse, len(databases)) + for i, d := range databases { + + } + + // res = append(res, database{Name: response}) + + res := dbsResponse{ + Databases: dbs, } - // res := []database{} - - // move this influxdb communication code somewhere else after it's working - // START - ctx := r.Context() - src, err := h.SourcesStore.Get(ctx, id) - if err != nil { - notFound(w, id, h.Logger) - return - } - - ts, err := h.TimeSeries(src) - if err != nil { - msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err) - Error(w, http.StatusBadRequest, msg, h.Logger) - return - } - - if err = ts.Connect(ctx, &src); err != nil { - msg := fmt.Sprintf("Unable to connect to source %d: %v", id, err) - Error(w, http.StatusBadRequest, msg, h.Logger) - return - } - - req := chronograf.Query{Command: "SHOW DATABASES"} - - response, err := ts.Query(ctx, req) - if err != nil { - if err == chronograf.ErrUpstreamTimeout { - msg := "Timeout waiting for Influx response" - Error(w, http.StatusRequestTimeout, msg, h.Logger) - return - } - // TODO: Here I want to return the error code from influx. - Error(w, http.StatusBadRequest, err.Error(), h.Logger) - return - } - - res := postInfluxResponze{ - Results: response, - } - - //fmt.Printf("%+v\n", foo) - // END - encodeJSON(w, http.StatusOK, res, h.Logger) } diff --git a/server/mux.go b/server/mux.go index e549ca410..4a8f2b6d4 100644 --- a/server/mux.go +++ b/server/mux.go @@ -133,16 +133,16 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Databases router.GET("/chronograf/v1/sources/:id/dbs", service.Databases) - router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) - - router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) - - // Retention Policies - router.GET("/chronograf/v1/sources/:id/dbs/:did/rps", service.RetentionPolicies) - router.POST("/chronograf/v1/sources/:id/dbs/:did/rps", service.NewRetentionPolicy) - - router.PATCH("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.UpdateRetentionPolicy) - router.DELETE("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.DropRetentionPolicy) + // router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) + // + // router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) + // + // // Retention Policies + // router.GET("/chronograf/v1/sources/:id/dbs/:did/rps", service.RetentionPolicies) + // router.POST("/chronograf/v1/sources/:id/dbs/:did/rps", service.NewRetentionPolicy) + // + // router.PATCH("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.UpdateRetentionPolicy) + // router.DELETE("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.DropRetentionPolicy) var authRoutes AuthRoutes From aebbb3743fc41b30b9acd50c8367e63f26df40d4 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 02:53:19 -0700 Subject: [PATCH 13/30] WIP ugh --- chronograf.go | 22 +++++++++++----------- enterprise/enterprise.go | 7 ++++++- enterprise/meta.go | 11 +++++++++++ 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/chronograf.go b/chronograf.go index afd1cbc8d..1edb44c2b 100644 --- a/chronograf.go +++ b/chronograf.go @@ -296,17 +296,17 @@ type UsersStore interface { Update(context.Context, *User) error } -// type Database struct { -// Name string `json:"name"` // a unique string identifier for the database -// Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) -// Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) -// ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) -// } -// -// type Databases interface { -// // All lists all databases -// AllDB(context.Context) ([]Database, error) -// } +type Database struct { + Name string `json:"name"` // a unique string identifier for the database + Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) + Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) + ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) +} + +type Databases interface { + // All lists all databases + AllDB(context.Context) ([]Database, error) +} // DashboardID is the dashboard ID type DashboardID int diff --git a/enterprise/enterprise.go b/enterprise/enterprise.go index 9e82d4695..0f9d737f4 100644 --- a/enterprise/enterprise.go +++ b/enterprise/enterprise.go @@ -35,7 +35,8 @@ type Ctrl interface { AddRoleUsers(ctx context.Context, name string, users []string) error RemoveRoleUsers(ctx context.Context, name string, users []string) error - Databases(ctx context.Context) (*Databases, error) + // TODO add error here? + Databases(ctx context.Context) chronograf.Databases } // Client is a device for retrieving time series data from an Influx Enterprise @@ -142,6 +143,10 @@ func (c *Client) Query(ctx context.Context, q chronograf.Query) (chronograf.Resp return c.nextDataNode().Query(ctx, q) } +// func (c *Client) Databases(context.Context) chronograf.Databases { +// return c.Databases +// } + // Users is the interface to the users within Influx Enterprise func (c *Client) Users(context.Context) chronograf.UsersStore { return c.UsersStore diff --git a/enterprise/meta.go b/enterprise/meta.go index cd08730b7..94330a4ac 100644 --- a/enterprise/meta.go +++ b/enterprise/meta.go @@ -46,6 +46,17 @@ func (m *MetaClient) ShowCluster(ctx context.Context) (*Cluster, error) { return out, nil } +func (m *MetaClient) Databases(ctx context.Context) chronograf.Databases { + res, _ := m.Do(ctx, "GET", "/databases", nil, nil) + + defer res.Body.Close() + dec := json.NewDecoder(res.Body) + dbs := []chronograf.Database{} + databases := chronograf.Databases{Databases: dbs} + // _ = dec.Decode(databases) + return databases +} + // Users gets all the users. If name is not nil it filters for a single user func (m *MetaClient) Users(ctx context.Context, name *string) (*Users, error) { params := map[string]string{} From cea9d9a8dc39835aba2622cdc5522f315dcc3732 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 04:01:55 -0700 Subject: [PATCH 14/30] uuuugh --- chronograf.go | 2 -- enterprise/enterprise.go | 7 ------- enterprise/meta.go | 11 ----------- influx/databases.go | 35 +++++++++++++++++++++++++++++++++++ influx/influx.go | 4 ---- server/databases.go | 6 +++--- 6 files changed, 38 insertions(+), 27 deletions(-) create mode 100644 influx/databases.go diff --git a/chronograf.go b/chronograf.go index 1edb44c2b..c8d1c7513 100644 --- a/chronograf.go +++ b/chronograf.go @@ -59,8 +59,6 @@ type TimeSeries interface { Permissions(context.Context) Permissions // Roles represents the roles associated with this TimesSeriesDatabase Roles(context.Context) (RolesStore, error) - // Databases represents the named databases within an InfluxDB instance - Databases(context.Context) Databases } // Role is a restricted set of permissions assigned to a set of users. diff --git a/enterprise/enterprise.go b/enterprise/enterprise.go index 0f9d737f4..189e5a150 100644 --- a/enterprise/enterprise.go +++ b/enterprise/enterprise.go @@ -34,9 +34,6 @@ type Ctrl interface { SetRoleUsers(ctx context.Context, name string, users []string) error AddRoleUsers(ctx context.Context, name string, users []string) error RemoveRoleUsers(ctx context.Context, name string, users []string) error - - // TODO add error here? - Databases(ctx context.Context) chronograf.Databases } // Client is a device for retrieving time series data from an Influx Enterprise @@ -143,10 +140,6 @@ func (c *Client) Query(ctx context.Context, q chronograf.Query) (chronograf.Resp return c.nextDataNode().Query(ctx, q) } -// func (c *Client) Databases(context.Context) chronograf.Databases { -// return c.Databases -// } - // Users is the interface to the users within Influx Enterprise func (c *Client) Users(context.Context) chronograf.UsersStore { return c.UsersStore diff --git a/enterprise/meta.go b/enterprise/meta.go index 94330a4ac..cd08730b7 100644 --- a/enterprise/meta.go +++ b/enterprise/meta.go @@ -46,17 +46,6 @@ func (m *MetaClient) ShowCluster(ctx context.Context) (*Cluster, error) { return out, nil } -func (m *MetaClient) Databases(ctx context.Context) chronograf.Databases { - res, _ := m.Do(ctx, "GET", "/databases", nil, nil) - - defer res.Body.Close() - dec := json.NewDecoder(res.Body) - dbs := []chronograf.Database{} - databases := chronograf.Databases{Databases: dbs} - // _ = dec.Decode(databases) - return databases -} - // Users gets all the users. If name is not nil it filters for a single user func (m *MetaClient) Users(ctx context.Context, name *string) (*Users, error) { params := map[string]string{} diff --git a/influx/databases.go b/influx/databases.go new file mode 100644 index 000000000..1cbd6265a --- /dev/null +++ b/influx/databases.go @@ -0,0 +1,35 @@ +package influx + +import ( + "encoding/json" +) + +// this stuff should probably live elsewhere? +func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) { + databases, err := c.showDatabases(ctx) + if err != nil { + return nil, err + } + + return databases, nil +} + +func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { + res, err := c.Query(ctx, chronograf.Query{ + Command: `SHOW DATABASES`, + }) + if err != nil { + return nil, err + } + octets, err := res.MarshalJSON() + if err != nil { + return nil, err + } + + results := showResults{} + if err := json.Unmarshal(octets, &results); err != nil { + return nil, err + } + + return results.Databases(), nil +} diff --git a/influx/influx.go b/influx/influx.go index 857c158fb..02d8eebf1 100644 --- a/influx/influx.go +++ b/influx/influx.go @@ -180,10 +180,6 @@ func (c *Client) Users(ctx context.Context) chronograf.UsersStore { return c } -func (c *Client) Databases(ctx context.Context) chronograf.Databases { - return c -} - // Roles aren't support in OSS func (c *Client) Roles(ctx context.Context) (chronograf.RolesStore, error) { return nil, fmt.Errorf("Roles not support in open-source InfluxDB. Roles are support in Influx Enterprise") diff --git a/server/databases.go b/server/databases.go index 7228ea15a..f725a738e 100644 --- a/server/databases.go +++ b/server/databases.go @@ -1,8 +1,9 @@ package server import ( - "fmt" "net/http" + "context" + "encoding/json" "github.com/influxdata/chronograf" ) @@ -64,8 +65,7 @@ func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { return } - store := ts.Databases(ctx) - databases, err := store.All(ctx) + databases, err := ts.AllDB(ctx) if err != nil { Error(w, http.StatusBadRequest, err.Error(), h.Logger) return From 19729da202fb7824e3e9a6adc17fcdfca1f9ee16 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 11:29:38 -0700 Subject: [PATCH 15/30] cleanup --- influx/databases.go | 4 +++- server/databases.go | 38 -------------------------------------- 2 files changed, 3 insertions(+), 39 deletions(-) diff --git a/influx/databases.go b/influx/databases.go index 1cbd6265a..d33863249 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -2,9 +2,11 @@ package influx import ( "encoding/json" + "context" + + "github.com/influxdata/chronograf" ) -// this stuff should probably live elsewhere? func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) { databases, err := c.showDatabases(ctx) if err != nil { diff --git a/server/databases.go b/server/databases.go index f725a738e..9e60f198a 100644 --- a/server/databases.go +++ b/server/databases.go @@ -2,10 +2,6 @@ package server import ( "net/http" - "context" - "encoding/json" - - "github.com/influxdata/chronograf" ) type dbLinks struct { @@ -25,38 +21,6 @@ type dbsResponse struct { Databases []dbResponse `json:"databases"` } -// type influxResponse struct { -// Results interface{} `json:"results"` // results from influx -// } - -// func (h *Service) sourcesSeries(ctx context.Context, w http.ResponseWriter, r *http.Request) (int, chronograf.TimeSeries, error) { -// srcID, err := paramID("id", r) -// if err != nil { -// Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) -// return 0, nil, err -// } -// -// src, err := h.SourcesStore.Get(ctx, srcID) -// if err != nil { -// notFound(w, srcID, h.Logger) -// return 0, nil, err -// } -// -// ts, err := h.TimeSeries(src) -// if err != nil { -// msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) -// Error(w, http.StatusBadRequest, msg, h.Logger) -// return 0, nil, err -// } -// -// if err = ts.Connect(ctx, &src); err != nil { -// msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) -// Error(w, http.StatusBadRequest, msg, h.Logger) -// return 0, nil, err -// } -// return srcID, ts, nil -// } - // Databases queries the list of all databases for a source func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -76,8 +40,6 @@ func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { } - // res = append(res, database{Name: response}) - res := dbsResponse{ Databases: dbs, } From 6a4c4122bbcf0cb3a0e56e725e3374c63d07bcf3 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 13:27:36 -0700 Subject: [PATCH 16/30] it's working! --- chronograf.go | 1 + enterprise/types.go | 11 ----------- influx/influx.go | 1 + server/databases.go | 39 ++++++++++++++++++++++++++++----------- server/mux.go | 2 +- server/server.go | 2 ++ server/service.go | 1 + 7 files changed, 34 insertions(+), 23 deletions(-) diff --git a/chronograf.go b/chronograf.go index c8d1c7513..cbf128eac 100644 --- a/chronograf.go +++ b/chronograf.go @@ -304,6 +304,7 @@ type Database struct { type Databases interface { // All lists all databases AllDB(context.Context) ([]Database, error) + Connect(context.Context, *Source) error } // DashboardID is the dashboard ID diff --git a/enterprise/types.go b/enterprise/types.go index 6e0f161af..d3c241ca2 100644 --- a/enterprise/types.go +++ b/enterprise/types.go @@ -65,17 +65,6 @@ type RoleAction struct { Role *Role `json:"role"` } -type Database struct { - Name string `json:"name"` // a unique string identifier for the database - Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) - Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) - ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) -} - -type Databases struct { - Databases []Database `json:"databases,omitempty"` -} - // Error is JSON error message return by Influx Enterprise's meta API. type Error struct { Error string `json:"error"` diff --git a/influx/influx.go b/influx/influx.go index 02d8eebf1..db9d6f332 100644 --- a/influx/influx.go +++ b/influx/influx.go @@ -12,6 +12,7 @@ import ( ) var _ chronograf.TimeSeries = &Client{} +var _ chronograf.Databases = &Client{} // Shared transports for all clients to prevent leaking connections var ( diff --git a/server/databases.go b/server/databases.go index 9e60f198a..5714e5ca3 100644 --- a/server/databases.go +++ b/server/databases.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "net/http" ) @@ -13,8 +14,8 @@ type dbResponse struct { Name string `json:"name"` // a unique string identifier for the database Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) - ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) - Links dbLinks `json:links` // Links are URI locations related to the database + ShardDuration string `json:"shardDuration,omitempty"` // the shard duration (when creating a default retention policy) + Links dbLinks `json:"links"` // Links are URI locations related to the database } type dbsResponse struct { @@ -22,23 +23,39 @@ type dbsResponse struct { } // Databases queries the list of all databases for a source -func (h *Service) Databases(w http.ResponseWriter, r *http.Request) { +func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - srcID, ts, err := h.sourcesSeries(ctx, w, r) - if err != nil { - return - } - databases, err := ts.AllDB(ctx) + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + databases, err := db.AllDB(ctx) if err != nil { Error(w, http.StatusBadRequest, err.Error(), h.Logger) return } dbs := make([]dbResponse, len(databases)) - for i, d := range databases { - - } + // for i, d := range databases { + // + // } res := dbsResponse{ Databases: dbs, diff --git a/server/mux.go b/server/mux.go index 4a8f2b6d4..d50368b90 100644 --- a/server/mux.go +++ b/server/mux.go @@ -132,7 +132,7 @@ func NewMux(opts MuxOpts, service Service) http.Handler { router.PATCH("/chronograf/v1/dashboards/:id", service.UpdateDashboard) // Databases - router.GET("/chronograf/v1/sources/:id/dbs", service.Databases) + router.GET("/chronograf/v1/sources/:id/dbs", service.GetDatabases) // router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) // // router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) diff --git a/server/server.go b/server/server.go index 3a494b9f8..2c0a883d1 100644 --- a/server/server.go +++ b/server/server.go @@ -21,6 +21,7 @@ import ( client "github.com/influxdata/usage-client/v1" flags "github.com/jessevdk/go-flags" "github.com/tylerb/graceful" + "github.com/influxdata/chronograf/influx" ) var ( @@ -292,6 +293,7 @@ func openService(boltPath, cannedPath string, logger chronograf.Logger, useAuth AlertRulesStore: db.AlertsStore, Logger: logger, UseAuth: useAuth, + Databases: &influx.Client{Logger: logger}, } } diff --git a/server/service.go b/server/service.go index 8dfa115a4..34ea80f65 100644 --- a/server/service.go +++ b/server/service.go @@ -20,6 +20,7 @@ type Service struct { TimeSeriesClient TimeSeriesClient Logger chronograf.Logger UseAuth bool + Databases chronograf.Databases } // TimeSeriesClient returns the correct client for a time series database. From 15b2744a5c6334bf7ff476ed41f984cece0beaf4 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 13:46:30 -0700 Subject: [PATCH 17/30] write db info to dbresponse --- server/databases.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/databases.go b/server/databases.go index 5714e5ca3..1c51aa93f 100644 --- a/server/databases.go +++ b/server/databases.go @@ -53,9 +53,11 @@ func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { } dbs := make([]dbResponse, len(databases)) - // for i, d := range databases { - // - // } + for i, d := range databases { + dbs[i] = dbResponse{ + Name: d.Name, + } + } res := dbsResponse{ Databases: dbs, From 523a0788f7dbd3ca7a0a3c780254876659c13392 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 22:21:25 -0700 Subject: [PATCH 18/30] WIP --- chronograf.go | 1 + influx/databases.go | 14 ++++++++++++++ server/databases.go | 34 ++++++++++++++++++++++++++++++++++ server/mux.go | 2 +- 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/chronograf.go b/chronograf.go index cbf128eac..63cf80dde 100644 --- a/chronograf.go +++ b/chronograf.go @@ -305,6 +305,7 @@ type Databases interface { // All lists all databases AllDB(context.Context) ([]Database, error) Connect(context.Context, *Source) error + CreateDB(context.Context, db *chronograf.Database) (*chronograf.Database, error) } // DashboardID is the dashboard ID diff --git a/influx/databases.go b/influx/databases.go index d33863249..e3b29a194 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -3,6 +3,7 @@ package influx import ( "encoding/json" "context" + "fmt" "github.com/influxdata/chronograf" ) @@ -16,6 +17,19 @@ func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) { return databases, nil } +func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chronograf.Database, error) { + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`CREATE DATABASE "%s"`, db.Name), + }) + if err != nil { + return nil, err + } + + res := &chronograf.Database{Name: db.Name} + + return res, nil +} + func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { res, err := c.Query(ctx, chronograf.Query{ Command: `SHOW DATABASES`, diff --git a/server/databases.go b/server/databases.go index 1c51aa93f..3346acaf6 100644 --- a/server/databases.go +++ b/server/databases.go @@ -65,3 +65,37 @@ func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusOK, res, h.Logger) } + +func (h *Service) NewDatabase(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + // need to pass database object from POST + database, err := db.CreateDB(ctx, ) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + res := dbResponse{Name: database.Name} + encodeJSON(w, http.StatusOK, res, h.Logger) +} diff --git a/server/mux.go b/server/mux.go index d50368b90..bb788459c 100644 --- a/server/mux.go +++ b/server/mux.go @@ -133,7 +133,7 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Databases router.GET("/chronograf/v1/sources/:id/dbs", service.GetDatabases) - // router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) + router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) // // router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) // From c21a378629db8763f57c23b30b5330c7c42ec8bf Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Wed, 22 Mar 2017 23:21:21 -0700 Subject: [PATCH 19/30] db creation seems to be working --- chronograf.go | 2 +- server/databases.go | 26 +++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/chronograf.go b/chronograf.go index 63cf80dde..b8e2e09b4 100644 --- a/chronograf.go +++ b/chronograf.go @@ -305,7 +305,7 @@ type Databases interface { // All lists all databases AllDB(context.Context) ([]Database, error) Connect(context.Context, *Source) error - CreateDB(context.Context, db *chronograf.Database) (*chronograf.Database, error) + CreateDB(context.Context, *Database) (*Database, error) } // DashboardID is the dashboard ID diff --git a/server/databases.go b/server/databases.go index 3346acaf6..af707de07 100644 --- a/server/databases.go +++ b/server/databases.go @@ -3,6 +3,9 @@ package server import ( "fmt" "net/http" + "encoding/json" + + "github.com/influxdata/chronograf" ) type dbLinks struct { @@ -89,13 +92,30 @@ func (h *Service) NewDatabase(w http.ResponseWriter, r *http.Request) { return } - // need to pass database object from POST - database, err := db.CreateDB(ctx, ) + postedDB := &chronograf.Database{} + if err := json.NewDecoder(r.Body).Decode(postedDB); err != nil { + invalidJSON(w, h.Logger) + return + } + + if err := ValidDatabaseRequest(postedDB); err != nil { + invalidData(w, err, h.Logger) + return + } + + database, err := db.CreateDB(ctx, postedDB) if err != nil { Error(w, http.StatusBadRequest, err.Error(), h.Logger) return } res := dbResponse{Name: database.Name} - encodeJSON(w, http.StatusOK, res, h.Logger) + encodeJSON(w, http.StatusCreated, res, h.Logger) +} + +func ValidDatabaseRequest(d *chronograf.Database) error { + if len(d.Name) == 0 { + return fmt.Errorf("name is required") + } + return nil } From 766ee9b517b1356d2ada8106218aabb79f8c8a8b Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 01:04:35 -0700 Subject: [PATCH 20/30] drop db API --- chronograf.go | 1 + influx/databases.go | 10 ++++++++++ server/databases.go | 39 +++++++++++++++++++++++++++++++++++++++ server/mux.go | 14 +++++++------- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/chronograf.go b/chronograf.go index b8e2e09b4..b6cb5dc90 100644 --- a/chronograf.go +++ b/chronograf.go @@ -306,6 +306,7 @@ type Databases interface { AllDB(context.Context) ([]Database, error) Connect(context.Context, *Source) error CreateDB(context.Context, *Database) (*Database, error) + DropDB(context.Context, string) error } // DashboardID is the dashboard ID diff --git a/influx/databases.go b/influx/databases.go index e3b29a194..7be081f63 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -30,6 +30,16 @@ func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chrono return res, nil } +func (c *Client) DropDB(ctx context.Context, name string) error { + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`DROP DATABASE "%s"`, name), + }) + if err != nil { + return err + } + return nil +} + func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { res, err := c.Query(ctx, chronograf.Query{ Command: `SHOW DATABASES`, diff --git a/server/databases.go b/server/databases.go index af707de07..83539267e 100644 --- a/server/databases.go +++ b/server/databases.go @@ -5,6 +5,7 @@ import ( "net/http" "encoding/json" + "github.com/bouk/httprouter" "github.com/influxdata/chronograf" ) @@ -113,6 +114,44 @@ func (h *Service) NewDatabase(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusCreated, res, h.Logger) } +func (h *Service) DropDatabase(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + dbID := httprouter.GetParamFromContext(ctx, "dbid") + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + dropErr := db.DropDB(ctx, dbID) + if dropErr != nil { + Error(w, http.StatusBadRequest, dropErr.Error(), h.Logger) + return + } + + w.WriteHeader(http.StatusNoContent) +} + func ValidDatabaseRequest(d *chronograf.Database) error { if len(d.Name) == 0 { return fmt.Errorf("name is required") diff --git a/server/mux.go b/server/mux.go index bb788459c..5c7ea3f26 100644 --- a/server/mux.go +++ b/server/mux.go @@ -134,15 +134,15 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Databases router.GET("/chronograf/v1/sources/:id/dbs", service.GetDatabases) router.POST("/chronograf/v1/sources/:id/dbs", service.NewDatabase) - // - // router.DELETE("/chronograf/v1/sources/:id/dbs/:did", service.DropDatabase) - // + + router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid", service.DropDatabase) + // // Retention Policies - // router.GET("/chronograf/v1/sources/:id/dbs/:did/rps", service.RetentionPolicies) - // router.POST("/chronograf/v1/sources/:id/dbs/:did/rps", service.NewRetentionPolicy) + // router.GET("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.RetentionPolicies) + // router.POST("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.NewRetentionPolicy) // - // router.PATCH("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.UpdateRetentionPolicy) - // router.DELETE("/chronograf/v1/sources/:id/dbs/:did/rps/:rpid", service.DropRetentionPolicy) + // router.PATCH("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.UpdateRetentionPolicy) + // router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.DropRetentionPolicy) var authRoutes AuthRoutes From 2438090e70ad6b75d37814463014c8157859dac2 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 03:06:59 -0700 Subject: [PATCH 21/30] get retention policies --- chronograf.go | 11 ++++++- influx/databases.go | 30 +++++++++++++++++ influx/permissions.go | 31 ++++++++++++++++++ server/databases.go | 76 +++++++++++++++++++++++++++++++++++++++++-- server/mux.go | 4 +-- 5 files changed, 146 insertions(+), 6 deletions(-) diff --git a/chronograf.go b/chronograf.go index b6cb5dc90..1e32234bd 100644 --- a/chronograf.go +++ b/chronograf.go @@ -298,7 +298,15 @@ type Database struct { Name string `json:"name"` // a unique string identifier for the database Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) - ShardDuration string `json:shardDuration,omitempty` // the shard duration (when creating a default retention policy) + ShardDuration string `json:"shardDuration,omitempty"` // the shard duration (when creating a default retention policy) +} + +type RetentionPolicy struct { + Name string `json:"name"` // a unique string identifier for the retention policy + Duration string `json:"duration,omitempty"` // the duration + Replication int32 `json:"replication,omitempty"` // the replication factor + ShardDuration string `json:"shardDuration,omitempty"` // the shard duration + Default bool `json:"default,omitempty"` // whether the RP should be the default } type Databases interface { @@ -307,6 +315,7 @@ type Databases interface { Connect(context.Context, *Source) error CreateDB(context.Context, *Database) (*Database, error) DropDB(context.Context, string) error + AllRP(context.Context, string) ([]RetentionPolicy, error) } // DashboardID is the dashboard ID diff --git a/influx/databases.go b/influx/databases.go index 7be081f63..4450744c1 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -40,6 +40,15 @@ func (c *Client) DropDB(ctx context.Context, name string) error { return nil } +func (c *Client) AllRP(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) { + retentionPolicies, err := c.showRetentionPolicies(ctx, name) + if err != nil { + return nil, err + } + + return retentionPolicies, nil +} + func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { res, err := c.Query(ctx, chronograf.Query{ Command: `SHOW DATABASES`, @@ -59,3 +68,24 @@ func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, erro return results.Databases(), nil } + +func (c *Client) showRetentionPolicies(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) { + retentionPolicies, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`SHOW RETENTION POLICIES ON "%s"`, name), + }) + + if err != nil { + return nil, err + } + octets, err := retentionPolicies.MarshalJSON() + if err != nil { + return nil, err + } + + results := showResults{} + if err := json.Unmarshal(octets, &results); err != nil { + return nil, err + } + + return results.RetentionPolicies(), nil +} diff --git a/influx/permissions.go b/influx/permissions.go index 07fe482c0..573414797 100644 --- a/influx/permissions.go +++ b/influx/permissions.go @@ -93,6 +93,37 @@ func (r *showResults) Databases() []chronograf.Database { return res } +func (r *showResults) RetentionPolicies() []chronograf.RetentionPolicy { + res := []chronograf.RetentionPolicy{} + for _, u := range *r { + for _, s := range u.Series { + for _, v := range s.Values { + if name, ok := v[0].(string); !ok { + continue + } else if duration, ok := v[1].(string); !ok { + continue + } else if sduration, ok := v[2].(string); !ok { + continue + } else if replication, ok := v[3].(int32); !ok { + continue + } else if def, ok := v[4].(bool); !ok { + continue + } else { + d := chronograf.RetentionPolicy{ + Name: name, + Duration: duration, + ShardDuration: sduration, + Replication: replication, + Default: def, + } + res = append(res, d) + } + } + } + } + return res +} + // Permissions converts SHOW GRANTS to chronograf.Permissions func (r *showResults) Permissions() chronograf.Permissions { res := []chronograf.Permission{} diff --git a/server/databases.go b/server/databases.go index 83539267e..d0a1ef9ba 100644 --- a/server/databases.go +++ b/server/databases.go @@ -15,9 +15,9 @@ type dbLinks struct { } type dbResponse struct { - Name string `json:"name"` // a unique string identifier for the database - Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) - Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) + Name string `json:"name"` // a unique string identifier for the database + Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) + Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) ShardDuration string `json:"shardDuration,omitempty"` // the shard duration (when creating a default retention policy) Links dbLinks `json:"links"` // Links are URI locations related to the database } @@ -26,6 +26,23 @@ type dbsResponse struct { Databases []dbResponse `json:"databases"` } +type rpLinks struct { + Self string `json:"self"` // Self link mapping to this resource +} + +type rpResponse struct { + Name string `json:"name"` // a unique string identifier for the retention policy + Duration string `json:"duration"` // the duration + Replication int32 `json:"replication"` // the replication factor + ShardDuration string `json:"shardDuration"` // the shard duration + Default bool `json:"default"` // whether the RP should be the default + Links rpLinks `json:"links"` // Links are URI locations related to the database +} + +type rpsResponse struct { + RetentionPolicies []rpResponse `json:"retentionPolicies"` +} + // Databases queries the list of all databases for a source func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -152,6 +169,59 @@ func (h *Service) DropDatabase(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) } +func (h *Service) RetentionPolicies(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + dbID := httprouter.GetParamFromContext(ctx, "dbid") + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + allRP, err := db.AllRP(ctx, dbID) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + rps := make([]rpResponse, len(allRP)) + for i, rp := range allRP { + rps[i] = rpResponse{ + Name: rp.Name, + Duration: rp.Duration, + Replication: rp.Replication, + ShardDuration: rp.ShardDuration, + Default: rp.Default, + } + } + + res := rpsResponse{ + RetentionPolicies: rps, + } + + encodeJSON(w, http.StatusOK, res, h.Logger) +} + func ValidDatabaseRequest(d *chronograf.Database) error { if len(d.Name) == 0 { return fmt.Errorf("name is required") diff --git a/server/mux.go b/server/mux.go index 5c7ea3f26..1a8cff534 100644 --- a/server/mux.go +++ b/server/mux.go @@ -137,8 +137,8 @@ func NewMux(opts MuxOpts, service Service) http.Handler { router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid", service.DropDatabase) - // // Retention Policies - // router.GET("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.RetentionPolicies) + // Retention Policies + router.GET("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.RetentionPolicies) // router.POST("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.NewRetentionPolicy) // // router.PATCH("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.UpdateRetentionPolicy) From 073c03303dea300cd4dc495744199b61ef846b02 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 03:37:32 -0700 Subject: [PATCH 22/30] fix rp GET --- influx/databases.go | 3 ++- influx/permissions.go | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/influx/databases.go b/influx/databases.go index 4450744c1..b014f6536 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -71,7 +71,8 @@ func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, erro func (c *Client) showRetentionPolicies(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) { retentionPolicies, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`SHOW RETENTION POLICIES ON "%s"`, name), + Command: fmt.Sprintf(`SHOW RETENTION POLICIES`), + DB: name, }) if err != nil { diff --git a/influx/permissions.go b/influx/permissions.go index 573414797..ba3206acb 100644 --- a/influx/permissions.go +++ b/influx/permissions.go @@ -104,7 +104,7 @@ func (r *showResults) RetentionPolicies() []chronograf.RetentionPolicy { continue } else if sduration, ok := v[2].(string); !ok { continue - } else if replication, ok := v[3].(int32); !ok { + } else if replication, ok := v[3].(float64); !ok { continue } else if def, ok := v[4].(bool); !ok { continue @@ -113,7 +113,7 @@ func (r *showResults) RetentionPolicies() []chronograf.RetentionPolicy { Name: name, Duration: duration, ShardDuration: sduration, - Replication: replication, + Replication: int32(replication), Default: def, } res = append(res, d) From b378dd7c27ff077d8b03254941f581a8a63f5fbd Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 04:27:53 -0700 Subject: [PATCH 23/30] createRP --- chronograf.go | 1 + influx/databases.go | 27 ++++++++++++++++--- server/databases.go | 63 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 4 deletions(-) diff --git a/chronograf.go b/chronograf.go index 1e32234bd..94c159a56 100644 --- a/chronograf.go +++ b/chronograf.go @@ -316,6 +316,7 @@ type Databases interface { CreateDB(context.Context, *Database) (*Database, error) DropDB(context.Context, string) error AllRP(context.Context, string) ([]RetentionPolicy, error) + CreateRP(context.Context, string, *RetentionPolicy) (*RetentionPolicy, error) } // DashboardID is the dashboard ID diff --git a/influx/databases.go b/influx/databases.go index b014f6536..b77d3ed45 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -30,9 +30,10 @@ func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chrono return res, nil } -func (c *Client) DropDB(ctx context.Context, name string) error { +func (c *Client) DropDB(ctx context.Context, database string) error { _, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`DROP DATABASE "%s"`, name), + Command: fmt.Sprintf(`DROP DATABASE`), + DB: database, }) if err != nil { return err @@ -40,8 +41,8 @@ func (c *Client) DropDB(ctx context.Context, name string) error { return nil } -func (c *Client) AllRP(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) { - retentionPolicies, err := c.showRetentionPolicies(ctx, name) +func (c *Client) AllRP(ctx context.Context, database string) ([]chronograf.RetentionPolicy, error) { + retentionPolicies, err := c.showRetentionPolicies(ctx, database) if err != nil { return nil, err } @@ -49,6 +50,24 @@ func (c *Client) AllRP(ctx context.Context, name string) ([]chronograf.Retention return retentionPolicies, nil } +func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) { + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`CREATE RETENTION POLICY "%s" DURATION "%s" REPLICATION "%s"`, rp.Name, rp.Duration, rp.Replication), + DB: database, + }) + if err != nil { + return nil, err + } + + res := &chronograf.RetentionPolicy{ + Name: rp.Name, + Duration: rp.Duration, + Replication: rp.Replication, + } + + return res, nil +} + func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { res, err := c.Query(ctx, chronograf.Query{ Command: `SHOW DATABASES`, diff --git a/server/databases.go b/server/databases.go index d0a1ef9ba..6064b629b 100644 --- a/server/databases.go +++ b/server/databases.go @@ -222,9 +222,72 @@ func (h *Service) RetentionPolicies(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusOK, res, h.Logger) } +func (h *Service) NewRetentionPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + postedRP := &chronograf.RetentionPolicy{} + if err := json.NewDecoder(r.Body).Decode(postedRP); err != nil { + invalidJSON(w, h.Logger) + return + } + if err := ValidRetentionPolicyRequest(postedRP); err != nil { + invalidData(w, err, h.Logger) + return + } + + dbID := httprouter.GetParamFromContext(ctx, "dbid") + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + database, err := db.CreateRP(ctx, dbID, postedRP) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + res := dbResponse{Name: database.Name} + encodeJSON(w, http.StatusCreated, res, h.Logger) +} + func ValidDatabaseRequest(d *chronograf.Database) error { if len(d.Name) == 0 { return fmt.Errorf("name is required") } return nil } + +func ValidRetentionPolicyRequest(rp *chronograf.RetentionPolicy) error { + if len(rp.Name) == 0 { + return fmt.Errorf("name is required") + } + if len(rp.Duration) == 0 { + return fmt.Errorf("duration is required") + } + if rp.Replication == 0 { + return fmt.Errorf("replication factor is invalid") + } + + return nil +} From b40a90b9d1e442cf3c614ad2337c364f41aedcf0 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 04:51:08 -0700 Subject: [PATCH 24/30] dropRP --- chronograf.go | 1 + influx/databases.go | 12 ++++++++++++ server/databases.go | 47 +++++++++++++++++++++++++++++++++------------ server/mux.go | 6 +++--- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/chronograf.go b/chronograf.go index 94c159a56..0bfd5e107 100644 --- a/chronograf.go +++ b/chronograf.go @@ -317,6 +317,7 @@ type Databases interface { DropDB(context.Context, string) error AllRP(context.Context, string) ([]RetentionPolicy, error) CreateRP(context.Context, string, *RetentionPolicy) (*RetentionPolicy, error) + DropRP(context.Context, string, string) error } // DashboardID is the dashboard ID diff --git a/influx/databases.go b/influx/databases.go index b77d3ed45..475e03994 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -68,6 +68,18 @@ func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.R return res, nil } +func (c *Client) DropRP(ctx context.Context, database string, rp string) error { + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`DROP RETENTION POLICY`), + DB: database, + RP: rp, + }) + if err != nil { + return err + } + return nil +} + func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { res, err := c.Query(ctx, chronograf.Query{ Command: `SHOW DATABASES`, diff --git a/server/databases.go b/server/databases.go index 6064b629b..4861c0570 100644 --- a/server/databases.go +++ b/server/databases.go @@ -155,10 +155,6 @@ func (h *Service) DropDatabase(w http.ResponseWriter, r *http.Request) { } dbID := httprouter.GetParamFromContext(ctx, "dbid") - if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return - } dropErr := db.DropDB(ctx, dbID) if dropErr != nil { @@ -193,10 +189,6 @@ func (h *Service) RetentionPolicies(w http.ResponseWriter, r *http.Request) { } dbID := httprouter.GetParamFromContext(ctx, "dbid") - if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return - } allRP, err := db.AllRP(ctx, dbID) if err != nil { @@ -256,10 +248,6 @@ func (h *Service) NewRetentionPolicy(w http.ResponseWriter, r *http.Request) { } dbID := httprouter.GetParamFromContext(ctx, "dbid") - if err != nil { - Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) - return - } database, err := db.CreateRP(ctx, dbID, postedRP) if err != nil { @@ -271,6 +259,41 @@ func (h *Service) NewRetentionPolicy(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusCreated, res, h.Logger) } +func (h *Service) DropRetentionPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + dbID := httprouter.GetParamFromContext(ctx, "dbid") + rpID := httprouter.GetParamFromContext(ctx, "rpid") + + dropErr := db.DropRP(ctx, dbID, rpID) + if dropErr != nil { + Error(w, http.StatusBadRequest, dropErr.Error(), h.Logger) + return + } + + w.WriteHeader(http.StatusNoContent) +} + func ValidDatabaseRequest(d *chronograf.Database) error { if len(d.Name) == 0 { return fmt.Errorf("name is required") diff --git a/server/mux.go b/server/mux.go index 1a8cff534..3cf9d4041 100644 --- a/server/mux.go +++ b/server/mux.go @@ -139,10 +139,10 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Retention Policies router.GET("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.RetentionPolicies) - // router.POST("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.NewRetentionPolicy) - // + router.POST("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.NewRetentionPolicy) + // router.PATCH("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.UpdateRetentionPolicy) - // router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.DropRetentionPolicy) + router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.DropRetentionPolicy) var authRoutes AuthRoutes From ba8609d7b69476f3750838c198a5bf30ebe3b506 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 04:56:36 -0700 Subject: [PATCH 25/30] go format --- chronograf.go | 22 +++--- influx/databases.go | 166 ++++++++++++++++++++++---------------------- server/databases.go | 44 ++++++------ 3 files changed, 116 insertions(+), 116 deletions(-) diff --git a/chronograf.go b/chronograf.go index 0bfd5e107..742f43fee 100644 --- a/chronograf.go +++ b/chronograf.go @@ -295,23 +295,23 @@ type UsersStore interface { } type Database struct { - Name string `json:"name"` // a unique string identifier for the database - Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) - Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) - ShardDuration string `json:"shardDuration,omitempty"` // the shard duration (when creating a default retention policy) + Name string `json:"name"` // a unique string identifier for the database + Duration string `json:"duration,omitempty"` // the duration (when creating a default retention policy) + Replication int32 `json:"replication,omitempty"` // the replication factor (when creating a default retention policy) + ShardDuration string `json:"shardDuration,omitempty"` // the shard duration (when creating a default retention policy) } type RetentionPolicy struct { - Name string `json:"name"` // a unique string identifier for the retention policy - Duration string `json:"duration,omitempty"` // the duration - Replication int32 `json:"replication,omitempty"` // the replication factor - ShardDuration string `json:"shardDuration,omitempty"` // the shard duration - Default bool `json:"default,omitempty"` // whether the RP should be the default + Name string `json:"name"` // a unique string identifier for the retention policy + Duration string `json:"duration,omitempty"` // the duration + Replication int32 `json:"replication,omitempty"` // the replication factor + ShardDuration string `json:"shardDuration,omitempty"` // the shard duration + Default bool `json:"default,omitempty"` // whether the RP should be the default } type Databases interface { - // All lists all databases - AllDB(context.Context) ([]Database, error) + // All lists all databases + AllDB(context.Context) ([]Database, error) Connect(context.Context, *Source) error CreateDB(context.Context, *Database) (*Database, error) DropDB(context.Context, string) error diff --git a/influx/databases.go b/influx/databases.go index 475e03994..b60598c91 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -1,123 +1,123 @@ package influx import ( - "encoding/json" - "context" - "fmt" + "context" + "encoding/json" + "fmt" - "github.com/influxdata/chronograf" + "github.com/influxdata/chronograf" ) func (c *Client) AllDB(ctx context.Context) ([]chronograf.Database, error) { - databases, err := c.showDatabases(ctx) - if err != nil { - return nil, err - } + databases, err := c.showDatabases(ctx) + if err != nil { + return nil, err + } - return databases, nil + return databases, nil } func (c *Client) CreateDB(ctx context.Context, db *chronograf.Database) (*chronograf.Database, error) { - _, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`CREATE DATABASE "%s"`, db.Name), - }) - if err != nil { - return nil, err - } + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`CREATE DATABASE "%s"`, db.Name), + }) + if err != nil { + return nil, err + } - res := &chronograf.Database{Name: db.Name} + res := &chronograf.Database{Name: db.Name} - return res, nil + return res, nil } func (c *Client) DropDB(ctx context.Context, database string) error { - _, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`DROP DATABASE`), - DB: database, - }) - if err != nil { - return err - } - return nil + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`DROP DATABASE`), + DB: database, + }) + if err != nil { + return err + } + return nil } func (c *Client) AllRP(ctx context.Context, database string) ([]chronograf.RetentionPolicy, error) { - retentionPolicies, err := c.showRetentionPolicies(ctx, database) - if err != nil { - return nil, err - } + retentionPolicies, err := c.showRetentionPolicies(ctx, database) + if err != nil { + return nil, err + } - return retentionPolicies, nil + return retentionPolicies, nil } func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) { - _, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`CREATE RETENTION POLICY "%s" DURATION "%s" REPLICATION "%s"`, rp.Name, rp.Duration, rp.Replication), - DB: database, - }) - if err != nil { - return nil, err - } + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`CREATE RETENTION POLICY "%s" DURATION "%s" REPLICATION "%s"`, rp.Name, rp.Duration, rp.Replication), + DB: database, + }) + if err != nil { + return nil, err + } - res := &chronograf.RetentionPolicy{ - Name: rp.Name, - Duration: rp.Duration, - Replication: rp.Replication, - } + res := &chronograf.RetentionPolicy{ + Name: rp.Name, + Duration: rp.Duration, + Replication: rp.Replication, + } - return res, nil + return res, nil } func (c *Client) DropRP(ctx context.Context, database string, rp string) error { - _, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`DROP RETENTION POLICY`), - DB: database, - RP: rp, - }) - if err != nil { - return err - } - return nil + _, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`DROP RETENTION POLICY`), + DB: database, + RP: rp, + }) + if err != nil { + return err + } + return nil } func (c *Client) showDatabases(ctx context.Context) ([]chronograf.Database, error) { - res, err := c.Query(ctx, chronograf.Query{ - Command: `SHOW DATABASES`, - }) - if err != nil { - return nil, err - } - octets, err := res.MarshalJSON() - if err != nil { - return nil, err - } + res, err := c.Query(ctx, chronograf.Query{ + Command: `SHOW DATABASES`, + }) + if err != nil { + return nil, err + } + octets, err := res.MarshalJSON() + if err != nil { + return nil, err + } - results := showResults{} - if err := json.Unmarshal(octets, &results); err != nil { - return nil, err - } + results := showResults{} + if err := json.Unmarshal(octets, &results); err != nil { + return nil, err + } - return results.Databases(), nil + return results.Databases(), nil } func (c *Client) showRetentionPolicies(ctx context.Context, name string) ([]chronograf.RetentionPolicy, error) { - retentionPolicies, err := c.Query(ctx, chronograf.Query{ - Command: fmt.Sprintf(`SHOW RETENTION POLICIES`), - DB: name, - }) + retentionPolicies, err := c.Query(ctx, chronograf.Query{ + Command: fmt.Sprintf(`SHOW RETENTION POLICIES`), + DB: name, + }) - if err != nil { - return nil, err - } - octets, err := retentionPolicies.MarshalJSON() - if err != nil { - return nil, err - } + if err != nil { + return nil, err + } + octets, err := retentionPolicies.MarshalJSON() + if err != nil { + return nil, err + } - results := showResults{} - if err := json.Unmarshal(octets, &results); err != nil { - return nil, err - } + results := showResults{} + if err := json.Unmarshal(octets, &results); err != nil { + return nil, err + } - return results.RetentionPolicies(), nil + return results.RetentionPolicies(), nil } diff --git a/server/databases.go b/server/databases.go index 4861c0570..79647280b 100644 --- a/server/databases.go +++ b/server/databases.go @@ -1,11 +1,11 @@ package server import ( + "encoding/json" "fmt" "net/http" - "encoding/json" - "github.com/bouk/httprouter" + "github.com/bouk/httprouter" "github.com/influxdata/chronograf" ) @@ -23,7 +23,7 @@ type dbResponse struct { } type dbsResponse struct { - Databases []dbResponse `json:"databases"` + Databases []dbResponse `json:"databases"` } type rpLinks struct { @@ -40,14 +40,14 @@ type rpResponse struct { } type rpsResponse struct { - RetentionPolicies []rpResponse `json:"retentionPolicies"` + RetentionPolicies []rpResponse `json:"retentionPolicies"` } // Databases queries the list of all databases for a source func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() + ctx := r.Context() - srcID, err := paramID("id", r) + srcID, err := paramID("id", r) if err != nil { Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) return @@ -59,7 +59,7 @@ func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { return } - db := h.Databases + db := h.Databases if err = db.Connect(ctx, &src); err != nil { msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) @@ -67,18 +67,18 @@ func (h *Service) GetDatabases(w http.ResponseWriter, r *http.Request) { return } - databases, err := db.AllDB(ctx) - if err != nil { - Error(w, http.StatusBadRequest, err.Error(), h.Logger) - return - } + databases, err := db.AllDB(ctx) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } - dbs := make([]dbResponse, len(databases)) - for i, d := range databases { - dbs[i] = dbResponse{ - Name: d.Name, - } - } + dbs := make([]dbResponse, len(databases)) + for i, d := range databases { + dbs[i] = dbResponse{ + Name: d.Name, + } + } res := dbsResponse{ Databases: dbs, @@ -199,11 +199,11 @@ func (h *Service) RetentionPolicies(w http.ResponseWriter, r *http.Request) { rps := make([]rpResponse, len(allRP)) for i, rp := range allRP { rps[i] = rpResponse{ - Name: rp.Name, - Duration: rp.Duration, - Replication: rp.Replication, + Name: rp.Name, + Duration: rp.Duration, + Replication: rp.Replication, ShardDuration: rp.ShardDuration, - Default: rp.Default, + Default: rp.Default, } } From c547ca5ebc3664f4b40ead9b0748a5c8c903b655 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 05:16:49 -0700 Subject: [PATCH 26/30] add missing patch responses swagger --- server/swagger.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/server/swagger.json b/server/swagger.json index 97e09c58f..e1afc826b 100644 --- a/server/swagger.json +++ b/server/swagger.json @@ -1023,7 +1023,27 @@ }, "required": true } - ] + ], + "responses": { + "200": { + "description": "Retention Policy was altered", + "schema": { + "$ref": "#/definitions/RetentionPolicy" + } + }, + "404": { + "description": "Database or source does not exist.", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "default": { + "description": "A processing or an unexpected error.", + "schema": { + "$ref": "#/definitions/Error" + } + } + } }, "delete": { "tags": [ From 2a990e2b3e360810c60df8ac093fe850a9b991b8 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 05:49:33 -0700 Subject: [PATCH 27/30] clean up some dashboards code --- server/dashboards.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/server/dashboards.go b/server/dashboards.go index 5eef491c9..9a662d63d 100644 --- a/server/dashboards.go +++ b/server/dashboards.go @@ -4,9 +4,7 @@ import ( "encoding/json" "fmt" "net/http" - "strconv" - "github.com/bouk/httprouter" "github.com/influxdata/chronograf" ) @@ -130,7 +128,7 @@ func (s *Service) RemoveDashboard(w http.ResponseWriter, r *http.Request) { // ReplaceDashboard completely replaces a dashboard func (s *Service) ReplaceDashboard(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - idParam, err := strconv.Atoi(httprouter.GetParamFromContext(ctx, "id")) + idParam, err := paramID("id", r) if err != nil { msg := fmt.Sprintf("Could not parse dashboard ID: %s", err) Error(w, http.StatusInternalServerError, msg, s.Logger) @@ -168,10 +166,11 @@ func (s *Service) ReplaceDashboard(w http.ResponseWriter, r *http.Request) { // UpdateDashboard completely updates either the dashboard name or the cells func (s *Service) UpdateDashboard(w http.ResponseWriter, r *http.Request) { ctx := r.Context() - idParam, err := strconv.Atoi(httprouter.GetParamFromContext(ctx, "id")) + idParam, err := paramID("id", r) if err != nil { msg := fmt.Sprintf("Could not parse dashboard ID: %s", err) Error(w, http.StatusInternalServerError, msg, s.Logger) + return } id := chronograf.DashboardID(idParam) From e58a846f7b2a40e02ef26921e05320e0a48d740d Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 06:13:41 -0700 Subject: [PATCH 28/30] updateRP --- chronograf.go | 1 + influx/databases.go | 25 +++++++++++++++++++++++ server/databases.go | 48 +++++++++++++++++++++++++++++++++++++++++++++ server/mux.go | 2 +- 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/chronograf.go b/chronograf.go index 742f43fee..f71ff508a 100644 --- a/chronograf.go +++ b/chronograf.go @@ -317,6 +317,7 @@ type Databases interface { DropDB(context.Context, string) error AllRP(context.Context, string) ([]RetentionPolicy, error) CreateRP(context.Context, string, *RetentionPolicy) (*RetentionPolicy, error) + UpdateRP(context.Context, string, string, *RetentionPolicy) (*RetentionPolicy, error) DropRP(context.Context, string, string) error } diff --git a/influx/databases.go b/influx/databases.go index b60598c91..84ac06439 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "bytes" "github.com/influxdata/chronograf" ) @@ -68,6 +69,30 @@ func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.R return res, nil } +func (c *Client) UpdateRP(ctx context.Context, database string, name string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) { + var buffer bytes.Buffer + buffer.WriteString("ALTER RETENTION POLICY") + if (len(rp.Duration) > 0) { + buffer.WriteString("DURATION " + rp.Duration) + } + + _, err := c.Query(ctx, chronograf.Query{ + Command: buffer.String(), + DB: database, + RP: name, + }) + if err != nil { + return nil, err + } + + // TODO: use actual information here + res := &chronograf.RetentionPolicy{ + Name: name, + } + + return res, nil +} + func (c *Client) DropRP(ctx context.Context, database string, rp string) error { _, err := c.Query(ctx, chronograf.Query{ Command: fmt.Sprintf(`DROP RETENTION POLICY`), diff --git a/server/databases.go b/server/databases.go index 79647280b..e51afc86f 100644 --- a/server/databases.go +++ b/server/databases.go @@ -259,6 +259,54 @@ func (h *Service) NewRetentionPolicy(w http.ResponseWriter, r *http.Request) { encodeJSON(w, http.StatusCreated, res, h.Logger) } +func (h *Service) UpdateRetentionPolicy(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + srcID, err := paramID("id", r) + if err != nil { + Error(w, http.StatusUnprocessableEntity, err.Error(), h.Logger) + return + } + + src, err := h.SourcesStore.Get(ctx, srcID) + if err != nil { + notFound(w, srcID, h.Logger) + return + } + + db := h.Databases + + if err = db.Connect(ctx, &src); err != nil { + msg := fmt.Sprintf("Unable to connect to source %d: %v", srcID, err) + Error(w, http.StatusBadRequest, msg, h.Logger) + return + } + + postedRP := &chronograf.RetentionPolicy{} + if err := json.NewDecoder(r.Body).Decode(postedRP); err != nil { + invalidJSON(w, h.Logger) + return + } + if err := ValidRetentionPolicyRequest(postedRP); err != nil { + invalidData(w, err, h.Logger) + return + } + + dbID := httprouter.GetParamFromContext(ctx, "dbid") + rpID := httprouter.GetParamFromContext(ctx, "rpid") + + rp, err := db.UpdateRP(ctx, dbID, rpID, postedRP) + + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), h.Logger) + return + } + + // TODO: this needs to be the actual RP information + res := rpResponse{Name: rp.Name} + encodeJSON(w, http.StatusCreated, res, h.Logger) +} + func (h *Service) DropRetentionPolicy(w http.ResponseWriter, r *http.Request) { ctx := r.Context() diff --git a/server/mux.go b/server/mux.go index 3cf9d4041..b655fa0de 100644 --- a/server/mux.go +++ b/server/mux.go @@ -141,7 +141,7 @@ func NewMux(opts MuxOpts, service Service) http.Handler { router.GET("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.RetentionPolicies) router.POST("/chronograf/v1/sources/:id/dbs/:dbid/rps", service.NewRetentionPolicy) - // router.PATCH("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.UpdateRetentionPolicy) + router.PATCH("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.UpdateRetentionPolicy) router.DELETE("/chronograf/v1/sources/:id/dbs/:dbid/rps/:rpid", service.DropRetentionPolicy) var authRoutes AuthRoutes From ffdc14ebdde6ae9b8e86fad4da94a4d086be1a82 Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 06:21:19 -0700 Subject: [PATCH 29/30] add options to alter rp --- influx/databases.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/influx/databases.go b/influx/databases.go index 84ac06439..0e74b7b84 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -73,7 +73,16 @@ func (c *Client) UpdateRP(ctx context.Context, database string, name string, rp var buffer bytes.Buffer buffer.WriteString("ALTER RETENTION POLICY") if (len(rp.Duration) > 0) { - buffer.WriteString("DURATION " + rp.Duration) + buffer.WriteString(" DURATION " + rp.Duration) + } + if (rp.Replication > 0) { + buffer.WriteString(" REPLICATION " + fmt.Sprint(rp.Replication)) + } + if (len(rp.ShardDuration) > 0) { + buffer.WriteString(" SHARD DURATION " + rp.ShardDuration) + } + if (rp.Default == true) { + buffer.WriteString(" DEFAULT") } _, err := c.Query(ctx, chronograf.Query{ From 10a05412c0e37b6e38790e5fa3916c5ae17ab3da Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Thu, 23 Mar 2017 06:24:26 -0700 Subject: [PATCH 30/30] go fmt --- influx/databases.go | 56 ++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/influx/databases.go b/influx/databases.go index 0e74b7b84..0ca5d50ca 100644 --- a/influx/databases.go +++ b/influx/databases.go @@ -1,10 +1,10 @@ package influx import ( + "bytes" "context" "encoding/json" "fmt" - "bytes" "github.com/influxdata/chronograf" ) @@ -70,36 +70,36 @@ func (c *Client) CreateRP(ctx context.Context, database string, rp *chronograf.R } func (c *Client) UpdateRP(ctx context.Context, database string, name string, rp *chronograf.RetentionPolicy) (*chronograf.RetentionPolicy, error) { - var buffer bytes.Buffer - buffer.WriteString("ALTER RETENTION POLICY") - if (len(rp.Duration) > 0) { - buffer.WriteString(" DURATION " + rp.Duration) - } - if (rp.Replication > 0) { - buffer.WriteString(" REPLICATION " + fmt.Sprint(rp.Replication)) - } - if (len(rp.ShardDuration) > 0) { - buffer.WriteString(" SHARD DURATION " + rp.ShardDuration) - } - if (rp.Default == true) { - buffer.WriteString(" DEFAULT") - } + var buffer bytes.Buffer + buffer.WriteString("ALTER RETENTION POLICY") + if len(rp.Duration) > 0 { + buffer.WriteString(" DURATION " + rp.Duration) + } + if rp.Replication > 0 { + buffer.WriteString(" REPLICATION " + fmt.Sprint(rp.Replication)) + } + if len(rp.ShardDuration) > 0 { + buffer.WriteString(" SHARD DURATION " + rp.ShardDuration) + } + if rp.Default == true { + buffer.WriteString(" DEFAULT") + } - _, err := c.Query(ctx, chronograf.Query{ - Command: buffer.String(), - DB: database, - RP: name, - }) - if err != nil { - return nil, err - } + _, err := c.Query(ctx, chronograf.Query{ + Command: buffer.String(), + DB: database, + RP: name, + }) + if err != nil { + return nil, err + } - // TODO: use actual information here - res := &chronograf.RetentionPolicy{ - Name: name, - } + // TODO: use actual information here + res := &chronograf.RetentionPolicy{ + Name: name, + } - return res, nil + return res, nil } func (c *Client) DropRP(ctx context.Context, database string, rp string) error {