Merge branch 'master' into feature/934-ew-users
commit
278579d631
|
@ -1,6 +1,7 @@
|
||||||
## v1.2.0 [unreleased]
|
## v1.2.0 [unreleased]
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
1. [#936](https://github.com/influxdata/chronograf/pull/936): Fix leaking sockets for InfluxQL queries
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"id": "f3bec493-0bc1-49d5-a40a-a09bd5cfb700",
|
||||||
|
"measurement": "consul_consul_fsm_register",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "9e14639d-b8d9-4245-8c45-862ed4383701",
|
||||||
|
"name": "Consul Agent – Number of Go Routines",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") AS \"Go Routines\" FROM \"consul_ip-172-31-6-247_runtime_num_goroutines\"",
|
||||||
|
"groupbys": [
|
||||||
|
],
|
||||||
|
"wheres": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "9e14639d-b8d9-4245-8c45-862ed4383702",
|
||||||
|
"name": "Consul Agent – Runtime Alloc Bytes",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") AS \"Runtime Alloc Bytes\" FROM \"consul_ip-172-31-6-247_runtime_alloc_bytes\"",
|
||||||
|
"groupbys": [
|
||||||
|
],
|
||||||
|
"wheres": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "9e14639d-b8d9-4245-8c45-862ed4383703",
|
||||||
|
"name": "Consul Agent – Heap Objects",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") AS \"Heap Objects\" FROM \"consul_ip-172-31-6-247_runtime_heap_objects\"",
|
||||||
|
"groupbys": [
|
||||||
|
],
|
||||||
|
"wheres": [
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"id": "350b780c-7d32-4b29-ac49-0d4e2c092943",
|
||||||
|
"measurement": "consul_memberlist_msg_alive",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "bd62186a-f475-478b-bf02-8c4ab07eccd1",
|
||||||
|
"name": "Consul – Number of Agents",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT min(\"value\") AS \"num_agents\" FROM \"consul_memberlist_msg_alive\"",
|
||||||
|
"label": "count",
|
||||||
|
"groupbys": [],
|
||||||
|
"wheres": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"id": "b15aaf24-701a-4d9b-920c-9a407e91da71",
|
||||||
|
"measurement": "consul_raft_state_candidate",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "5b2bddce-badb-4594-91fb-0486f62266e5",
|
||||||
|
"name": "Consul – Leadership Election",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") AS \"max_value\" FROM \"consul_raft_state_candidate\"",
|
||||||
|
"label": "count",
|
||||||
|
"groupbys": [],
|
||||||
|
"wheres": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"id": "26809869-8df3-49ad-b2f0-b1e1c72f67b0",
|
||||||
|
"measurement": "consul_consul_http_GET_v1_health_state__",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "dfb4c50f-547e-484a-944b-d6374ba2b4c0",
|
||||||
|
"name": "Consul – HTTP Request Time (ms)",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"upper\") AS \"GET_health_state\" FROM \"consul_consul_http_GET_v1_health_state__\"",
|
||||||
|
"label": "ms",
|
||||||
|
"groupbys": [],
|
||||||
|
"wheres": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"id": "34611ae0-7c3e-4697-8db0-371b16bef345",
|
||||||
|
"measurement": "consul_raft_state_leader",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "ef8eeeb5-b408-46d6-8cfc-20c00c9d7239",
|
||||||
|
"name": "Consul – Leadership Change",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") as \"change\" FROM \"consul_raft_state_leader\"",
|
||||||
|
"label": "count",
|
||||||
|
"groupbys": [],
|
||||||
|
"wheres": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"id": "ef4b596c-77de-41c5-bb5b-d5c9a69fa633",
|
||||||
|
"measurement": "consul_serf_events",
|
||||||
|
"app": "consul_telemetry",
|
||||||
|
"autoflow": true,
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"w": 4,
|
||||||
|
"h": 4,
|
||||||
|
"i": "59df3d73-5fac-48cb-84f1-dbe9a1bb886c",
|
||||||
|
"name": "Consul – Number of serf events",
|
||||||
|
"queries": [
|
||||||
|
{
|
||||||
|
"query": "SELECT max(\"value\") AS \"serf_events\" FROM \"consul_serf_events\"",
|
||||||
|
"label": "count",
|
||||||
|
"groupbys": [],
|
||||||
|
"wheres": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -275,6 +275,7 @@ type User struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Passwd string `json:"password"`
|
Passwd string `json:"password"`
|
||||||
Permissions Permissions `json:"permissions,omitempty"`
|
Permissions Permissions `json:"permissions,omitempty"`
|
||||||
|
Roles []Role `json:"roles,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UsersStore is the Storage and retrieval of authentication information
|
// UsersStore is the Storage and retrieval of authentication information
|
||||||
|
|
|
@ -24,6 +24,8 @@ type Ctrl interface {
|
||||||
ChangePassword(ctx context.Context, name, passwd string) error
|
ChangePassword(ctx context.Context, name, passwd string) error
|
||||||
SetUserPerms(ctx context.Context, name string, perms Permissions) error
|
SetUserPerms(ctx context.Context, name string, perms Permissions) error
|
||||||
|
|
||||||
|
UserRoles(ctx context.Context) (map[string]Roles, error)
|
||||||
|
|
||||||
Roles(ctx context.Context, name *string) (*Roles, error)
|
Roles(ctx context.Context, name *string) (*Roles, error)
|
||||||
Role(ctx context.Context, name string) (*Role, error)
|
Role(ctx context.Context, name string) (*Role, error)
|
||||||
CreateRole(ctx context.Context, name string) error
|
CreateRole(ctx context.Context, name string) error
|
||||||
|
|
|
@ -155,6 +155,27 @@ func (m *MetaClient) SetUserPerms(ctx context.Context, name string, perms Permis
|
||||||
return m.Post(ctx, "/user", a, nil)
|
return m.Post(ctx, "/user", a, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UserRoles returns a map of users to all of their current roles
|
||||||
|
func (m *MetaClient) UserRoles(ctx context.Context) (map[string]Roles, error) {
|
||||||
|
res, err := m.Roles(ctx, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userRoles := make(map[string]Roles)
|
||||||
|
for _, role := range res.Roles {
|
||||||
|
for _, u := range role.Users {
|
||||||
|
ur, ok := userRoles[u]
|
||||||
|
if !ok {
|
||||||
|
ur = Roles{}
|
||||||
|
}
|
||||||
|
ur.Roles = append(ur.Roles, role)
|
||||||
|
userRoles[u] = ur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userRoles, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Roles gets all the roles. If name is not nil it filters for a single role
|
// Roles gets all the roles. If name is not nil it filters for a single role
|
||||||
func (m *MetaClient) Roles(ctx context.Context, name *string) (*Roles, error) {
|
func (m *MetaClient) Roles(ctx context.Context, name *string) (*Roles, error) {
|
||||||
params := map[string]string{}
|
params := map[string]string{}
|
||||||
|
|
|
@ -876,6 +876,110 @@ func TestMetaClient_Role(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMetaClient_UserRoles(t *testing.T) {
|
||||||
|
type fields struct {
|
||||||
|
URL *url.URL
|
||||||
|
client interface {
|
||||||
|
Do(URL *url.URL, path, method string, params map[string]string, body io.Reader) (*http.Response, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type args struct {
|
||||||
|
ctx context.Context
|
||||||
|
name *string
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
fields fields
|
||||||
|
args args
|
||||||
|
want map[string]Roles
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "Successful Show all roles",
|
||||||
|
fields: fields{
|
||||||
|
URL: &url.URL{
|
||||||
|
Host: "twinpinesmall.net:8091",
|
||||||
|
Scheme: "https",
|
||||||
|
},
|
||||||
|
client: NewMockClient(
|
||||||
|
http.StatusOK,
|
||||||
|
[]byte(`{"roles":[{"name":"timetravelers","users":["marty","docbrown"],"permissions":{"":["ViewAdmin","ViewChronograf"]}},{"name":"mcfly","users":["marty","george"],"permissions":{"":["ViewAdmin","ViewChronograf"]}}]}`),
|
||||||
|
nil,
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
name: nil,
|
||||||
|
},
|
||||||
|
want: map[string]Roles{
|
||||||
|
"marty": Roles{
|
||||||
|
Roles: []Role{
|
||||||
|
{
|
||||||
|
Name: "timetravelers",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": []string{
|
||||||
|
"ViewAdmin", "ViewChronograf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []string{"marty", "docbrown"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "mcfly",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": []string{
|
||||||
|
"ViewAdmin", "ViewChronograf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []string{"marty", "george"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"docbrown": Roles{
|
||||||
|
Roles: []Role{
|
||||||
|
{
|
||||||
|
Name: "timetravelers",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": []string{
|
||||||
|
"ViewAdmin", "ViewChronograf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []string{"marty", "docbrown"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"george": Roles{
|
||||||
|
Roles: []Role{
|
||||||
|
{
|
||||||
|
Name: "mcfly",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": []string{
|
||||||
|
"ViewAdmin", "ViewChronograf",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []string{"marty", "george"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
m := &MetaClient{
|
||||||
|
URL: tt.fields.URL,
|
||||||
|
client: tt.fields.client,
|
||||||
|
}
|
||||||
|
got, err := m.UserRoles(tt.args.ctx)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("%q. MetaClient.UserRoles() error = %v, wantErr %v", tt.name, err, tt.wantErr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("%q. MetaClient.UserRoles() = %v, want %v", tt.name, got, tt.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMetaClient_CreateRole(t *testing.T) {
|
func TestMetaClient_CreateRole(t *testing.T) {
|
||||||
type fields struct {
|
type fields struct {
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
|
|
|
@ -68,6 +68,10 @@ func (cc *ControlClient) Role(ctx context.Context, name string) (*enterprise.Rol
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ccm *ControlClient) UserRoles(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ccm *ControlClient) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
func (ccm *ControlClient) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,9 +85,13 @@ func (c *RolesStore) All(ctx context.Context) ([]chronograf.Role, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
res := make([]chronograf.Role, len(all.Roles))
|
return all.ToChronograf(), nil
|
||||||
for i, role := range all.Roles {
|
}
|
||||||
|
|
||||||
|
// ToChronograf converts enterprise roles to chronograf
|
||||||
|
func (r *Roles) ToChronograf() []chronograf.Role {
|
||||||
|
res := make([]chronograf.Role, len(r.Roles))
|
||||||
|
for i, role := range r.Roles {
|
||||||
users := make([]chronograf.User, len(role.Users))
|
users := make([]chronograf.User, len(role.Users))
|
||||||
for i, user := range role.Users {
|
for i, user := range role.Users {
|
||||||
users[i] = chronograf.User{
|
users[i] = chronograf.User{
|
||||||
|
@ -101,5 +105,5 @@ func (c *RolesStore) All(ctx context.Context) ([]chronograf.Role, error) {
|
||||||
Users: users,
|
Users: users,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package enterprise
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdata/chronograf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRoles_ToChronograf(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
roles []Role
|
||||||
|
want []chronograf.Role
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty roles",
|
||||||
|
roles: []Role{},
|
||||||
|
want: []chronograf.Role{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
r := &Roles{
|
||||||
|
Roles: tt.roles,
|
||||||
|
}
|
||||||
|
if got := r.ToChronograf(); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("Roles.ToChronograf() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,9 +35,23 @@ func (c *UserStore) Get(ctx context.Context, name string) (*chronograf.User, err
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ur, err := c.Ctrl.UserRoles(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
role := ur[name]
|
||||||
|
cr := role.ToChronograf()
|
||||||
|
// For now we are removing all users from a role being returned.
|
||||||
|
for i, r := range cr {
|
||||||
|
r.Users = []chronograf.User{}
|
||||||
|
cr[i] = r
|
||||||
|
}
|
||||||
return &chronograf.User{
|
return &chronograf.User{
|
||||||
Name: u.Name,
|
Name: u.Name,
|
||||||
Permissions: ToChronograf(u.Permissions),
|
Permissions: ToChronograf(u.Permissions),
|
||||||
|
Roles: cr,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,11 +73,25 @@ func (c *UserStore) All(ctx context.Context) ([]chronograf.User, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ur, err := c.Ctrl.UserRoles(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
res := make([]chronograf.User, len(all.Users))
|
res := make([]chronograf.User, len(all.Users))
|
||||||
for i, user := range all.Users {
|
for i, user := range all.Users {
|
||||||
|
role := ur[user.Name]
|
||||||
|
cr := role.ToChronograf()
|
||||||
|
// For now we are removing all users from a role being returned.
|
||||||
|
for i, r := range cr {
|
||||||
|
r.Users = []chronograf.User{}
|
||||||
|
cr[i] = r
|
||||||
|
}
|
||||||
|
|
||||||
res[i] = chronograf.User{
|
res[i] = chronograf.User{
|
||||||
Name: user.Name,
|
Name: user.Name,
|
||||||
Permissions: ToChronograf(user.Permissions),
|
Permissions: ToChronograf(user.Permissions),
|
||||||
|
Roles: cr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|
|
@ -180,6 +180,9 @@ func TestClient_Get(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||||
|
return map[string]enterprise.Roles{}, nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -194,6 +197,71 @@ func TestClient_Get(t *testing.T) {
|
||||||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Roles: []chronograf.Role{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Successful Get User with roles",
|
||||||
|
fields: fields{
|
||||||
|
Ctrl: &mockCtrl{
|
||||||
|
user: func(ctx context.Context, name string) (*enterprise.User, error) {
|
||||||
|
return &enterprise.User{
|
||||||
|
Name: "marty",
|
||||||
|
Password: "johnny be good",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": {
|
||||||
|
"ViewChronograf",
|
||||||
|
"ReadData",
|
||||||
|
"WriteData",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||||
|
return map[string]enterprise.Roles{
|
||||||
|
"marty": enterprise.Roles{
|
||||||
|
Roles: []enterprise.Role{
|
||||||
|
{
|
||||||
|
Name: "timetravels",
|
||||||
|
Permissions: map[string][]string{
|
||||||
|
"": {
|
||||||
|
"ViewChronograf",
|
||||||
|
"ReadData",
|
||||||
|
"WriteData",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []string{"marty", "docbrown"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: args{
|
||||||
|
ctx: context.Background(),
|
||||||
|
name: "marty",
|
||||||
|
},
|
||||||
|
want: &chronograf.User{
|
||||||
|
Name: "marty",
|
||||||
|
Permissions: chronograf.Permissions{
|
||||||
|
{
|
||||||
|
Scope: chronograf.AllScope,
|
||||||
|
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Roles: []chronograf.Role{
|
||||||
|
{
|
||||||
|
Name: "timetravels",
|
||||||
|
Permissions: chronograf.Permissions{
|
||||||
|
{
|
||||||
|
Scope: chronograf.AllScope,
|
||||||
|
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Users: []chronograf.User{},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -372,6 +440,9 @@ func TestClient_All(t *testing.T) {
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
userRoles: func(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||||
|
return map[string]enterprise.Roles{}, nil
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
|
@ -386,6 +457,7 @@ func TestClient_All(t *testing.T) {
|
||||||
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
Allowed: chronograf.Allowances{"ViewChronograf", "ReadData", "WriteData"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Roles: []chronograf.Role{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -499,6 +571,8 @@ type mockCtrl struct {
|
||||||
users func(ctx context.Context, name *string) (*enterprise.Users, error)
|
users func(ctx context.Context, name *string) (*enterprise.Users, error)
|
||||||
setUserPerms func(ctx context.Context, name string, perms enterprise.Permissions) error
|
setUserPerms func(ctx context.Context, name string, perms enterprise.Permissions) error
|
||||||
|
|
||||||
|
userRoles func(ctx context.Context) (map[string]enterprise.Roles, error)
|
||||||
|
|
||||||
roles func(ctx context.Context, name *string) (*enterprise.Roles, error)
|
roles func(ctx context.Context, name *string) (*enterprise.Roles, error)
|
||||||
role func(ctx context.Context, name string) (*enterprise.Role, error)
|
role func(ctx context.Context, name string) (*enterprise.Role, error)
|
||||||
createRole func(ctx context.Context, name string) error
|
createRole func(ctx context.Context, name string) error
|
||||||
|
@ -510,25 +584,35 @@ type mockCtrl struct {
|
||||||
func (m *mockCtrl) ShowCluster(ctx context.Context) (*enterprise.Cluster, error) {
|
func (m *mockCtrl) ShowCluster(ctx context.Context) (*enterprise.Cluster, error) {
|
||||||
return m.showCluster(ctx)
|
return m.showCluster(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) User(ctx context.Context, name string) (*enterprise.User, error) {
|
func (m *mockCtrl) User(ctx context.Context, name string) (*enterprise.User, error) {
|
||||||
return m.user(ctx, name)
|
return m.user(ctx, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) CreateUser(ctx context.Context, name, passwd string) error {
|
func (m *mockCtrl) CreateUser(ctx context.Context, name, passwd string) error {
|
||||||
return m.createUser(ctx, name, passwd)
|
return m.createUser(ctx, name, passwd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) DeleteUser(ctx context.Context, name string) error {
|
func (m *mockCtrl) DeleteUser(ctx context.Context, name string) error {
|
||||||
return m.deleteUser(ctx, name)
|
return m.deleteUser(ctx, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) ChangePassword(ctx context.Context, name, passwd string) error {
|
func (m *mockCtrl) ChangePassword(ctx context.Context, name, passwd string) error {
|
||||||
return m.changePassword(ctx, name, passwd)
|
return m.changePassword(ctx, name, passwd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) Users(ctx context.Context, name *string) (*enterprise.Users, error) {
|
func (m *mockCtrl) Users(ctx context.Context, name *string) (*enterprise.Users, error) {
|
||||||
return m.users(ctx, name)
|
return m.users(ctx, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) SetUserPerms(ctx context.Context, name string, perms enterprise.Permissions) error {
|
func (m *mockCtrl) SetUserPerms(ctx context.Context, name string, perms enterprise.Permissions) error {
|
||||||
return m.setUserPerms(ctx, name, perms)
|
return m.setUserPerms(ctx, name, perms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mockCtrl) UserRoles(ctx context.Context) (map[string]enterprise.Roles, error) {
|
||||||
|
return m.userRoles(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *mockCtrl) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
func (m *mockCtrl) Roles(ctx context.Context, name *string) (*enterprise.Roles, error) {
|
||||||
return m.roles(ctx, name)
|
return m.roles(ctx, name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,14 @@ import (
|
||||||
|
|
||||||
var _ chronograf.TimeSeries = &Client{}
|
var _ chronograf.TimeSeries = &Client{}
|
||||||
|
|
||||||
|
// Shared transports for all clients to prevent leaking connections
|
||||||
|
var (
|
||||||
|
skipVerifyTransport = &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
|
}
|
||||||
|
defaultTransport = &http.Transport{}
|
||||||
|
)
|
||||||
|
|
||||||
// Client is a device for retrieving time series data from an InfluxDB instance
|
// Client is a device for retrieving time series data from an InfluxDB instance
|
||||||
type Client struct {
|
type Client struct {
|
||||||
URL *url.URL
|
URL *url.URL
|
||||||
|
@ -74,10 +82,9 @@ func (c *Client) query(u *url.URL, q chronograf.Query) (chronograf.Response, err
|
||||||
|
|
||||||
hc := &http.Client{}
|
hc := &http.Client{}
|
||||||
if c.InsecureSkipVerify {
|
if c.InsecureSkipVerify {
|
||||||
tr := &http.Transport{
|
hc.Transport = skipVerifyTransport
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
} else {
|
||||||
}
|
hc.Transport = defaultTransport
|
||||||
hc.Transport = tr
|
|
||||||
}
|
}
|
||||||
resp, err := hc.Do(req)
|
resp, err := hc.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -52,6 +52,7 @@ func (r *sourceUserRequest) ValidUpdate() error {
|
||||||
type sourceUser struct {
|
type sourceUser struct {
|
||||||
Username string `json:"name,omitempty"` // Username for new account
|
Username string `json:"name,omitempty"` // Username for new account
|
||||||
Permissions chronograf.Permissions `json:"permissions,omitempty"` // Account's permissions
|
Permissions chronograf.Permissions `json:"permissions,omitempty"` // Account's permissions
|
||||||
|
Roles []roleResponse `json:"roles,omitempty"` // Roles if source uses them
|
||||||
Links selfLinks `json:"links"` // Links are URI locations related to user
|
Links selfLinks `json:"links"` // Links are URI locations related to user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,11 +129,19 @@ func (h *Service) SourceUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
su := []sourceUser{}
|
su := []sourceUser{}
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
su = append(su, sourceUser{
|
res := sourceUser{
|
||||||
Username: u.Name,
|
Username: u.Name,
|
||||||
Permissions: u.Permissions,
|
Permissions: u.Permissions,
|
||||||
Links: newSelfLinks(srcID, "users", u.Name),
|
Links: newSelfLinks(srcID, "users", u.Name),
|
||||||
})
|
}
|
||||||
|
if len(u.Roles) > 0 {
|
||||||
|
rr := make([]roleResponse, len(u.Roles))
|
||||||
|
for i, role := range u.Roles {
|
||||||
|
rr[i] = newRoleResponse(srcID, &role)
|
||||||
|
}
|
||||||
|
res.Roles = rr
|
||||||
|
}
|
||||||
|
su = append(su, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := sourceUsers{
|
res := sourceUsers{
|
||||||
|
@ -163,6 +172,13 @@ func (h *Service) SourceUserID(w http.ResponseWriter, r *http.Request) {
|
||||||
Permissions: u.Permissions,
|
Permissions: u.Permissions,
|
||||||
Links: newSelfLinks(srcID, "users", u.Name),
|
Links: newSelfLinks(srcID, "users", u.Name),
|
||||||
}
|
}
|
||||||
|
if len(u.Roles) > 0 {
|
||||||
|
rr := make([]roleResponse, len(u.Roles))
|
||||||
|
for i, role := range u.Roles {
|
||||||
|
rr[i] = newRoleResponse(srcID, &role)
|
||||||
|
}
|
||||||
|
res.Roles = rr
|
||||||
|
}
|
||||||
encodeJSON(w, http.StatusOK, res, h.Logger)
|
encodeJSON(w, http.StatusOK, res, h.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +362,7 @@ func (r *sourceRoleRequest) ValidUpdate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
type roleResponse struct {
|
type roleResponse struct {
|
||||||
Users []sourceUser `json:"users"`
|
Users []sourceUser `json:"users,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Permissions chronograf.Permissions `json:"permissions"`
|
Permissions chronograf.Permissions `json:"permissions"`
|
||||||
Links selfLinks `json:"links"`
|
Links selfLinks `json:"links"`
|
||||||
|
|
|
@ -2565,6 +2565,34 @@
|
||||||
"$ref": "#/definitions/Role"
|
"$ref": "#/definitions/Role"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/users/admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "timetravelers",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"scope": "database",
|
||||||
|
"name": "telegraf",
|
||||||
|
"allowed": [
|
||||||
|
"ReadData",
|
||||||
|
"WriteData"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Role": {
|
"Role": {
|
||||||
|
@ -2596,6 +2624,30 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"example": {
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/users/admin"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "timetravelers",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"scope": "database",
|
||||||
|
"name": "telegraf",
|
||||||
|
"allowed": [
|
||||||
|
"ReadData",
|
||||||
|
"WriteData"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Users": {
|
"Users": {
|
||||||
|
@ -2616,21 +2668,43 @@
|
||||||
{
|
{
|
||||||
"scope": "all",
|
"scope": "all",
|
||||||
"allowed": [
|
"allowed": [
|
||||||
|
"ViewAdmin",
|
||||||
"ViewChronograf",
|
"ViewChronograf",
|
||||||
"ReadData"
|
"CreateDatabase",
|
||||||
]
|
"CreateUserAndRole",
|
||||||
},
|
"DropDatabase",
|
||||||
{
|
"DropData",
|
||||||
"scope": "database",
|
"ReadData",
|
||||||
"name": "telegraf",
|
"WriteData",
|
||||||
"allowed": [
|
"ManageShard",
|
||||||
"ViewChronograf",
|
"ManageContinuousQuery",
|
||||||
"ReadData"
|
"ManageQuery",
|
||||||
|
"ManageSubscription",
|
||||||
|
"Monitor",
|
||||||
|
"KapacitorAPI"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"name": "timetravelers",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"scope": "database",
|
||||||
|
"name": "telegraf",
|
||||||
|
"allowed": [
|
||||||
|
"ReadData",
|
||||||
|
"WriteData"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"links": {
|
"links": {
|
||||||
"self": "/chronograf/v1/source/1/users/docbrown"
|
"self": "/chronograf/v1/sources/3/users/docbrown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2669,21 +2743,43 @@
|
||||||
{
|
{
|
||||||
"scope": "all",
|
"scope": "all",
|
||||||
"allowed": [
|
"allowed": [
|
||||||
|
"ViewAdmin",
|
||||||
"ViewChronograf",
|
"ViewChronograf",
|
||||||
"ReadData"
|
"CreateDatabase",
|
||||||
]
|
"CreateUserAndRole",
|
||||||
},
|
"DropDatabase",
|
||||||
{
|
"DropData",
|
||||||
"scope": "database",
|
"ReadData",
|
||||||
"name": "telegraf",
|
"WriteData",
|
||||||
"allowed": [
|
"ManageShard",
|
||||||
"ViewChronograf",
|
"ManageContinuousQuery",
|
||||||
"ReadData"
|
"ManageQuery",
|
||||||
|
"ManageSubscription",
|
||||||
|
"Monitor",
|
||||||
|
"KapacitorAPI"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"name": "timetravelers",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"scope": "database",
|
||||||
|
"name": "telegraf",
|
||||||
|
"allowed": [
|
||||||
|
"ReadData",
|
||||||
|
"WriteData"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"links": {
|
||||||
|
"self": "/chronograf/v1/sources/3/roles/timetravelers"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"links": {
|
"links": {
|
||||||
"self": "/chronograf/v1/source/1/users/docbrown"
|
"self": "/chronograf/v1/sources/3/users/docbrown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3217,4 +3313,4 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue