Skip to content

Commit

Permalink
Merge pull request #7 from cloudradar-monitoring/DEV-2512
Browse files Browse the repository at this point in the history
[DEV-2512] Use server side search
  • Loading branch information
thorstenkramm authored Apr 20, 2022
2 parents 8907afd + 99d0e19 commit 55db09d
Show file tree
Hide file tree
Showing 19 changed files with 228 additions and 765 deletions.
22 changes: 11 additions & 11 deletions cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/api"
"github.com/cloudradar-monitoring/rportcli/internal/pkg/client"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/config"

Expand All @@ -18,7 +17,8 @@ import (
)

func init() {
addPaginationFlags(clientsListCmd, api.ClientsLimitDefault)
addClientsPaginationFlags(clientsListCmd)
addClientsSearchFlag(clientsListCmd)
clientsCmd.AddCommand(clientsListCmd)
clientCmd.Flags().StringP(controllers.ClientNameFlag, "n", "", "Get client by name")
clientCmd.Flags().BoolP("all", "a", false, "Show client info with additional details")
Expand Down Expand Up @@ -46,14 +46,9 @@ var clientsListCmd = &cobra.Command{
Format: getOutputFormat(),
}

clientSearch := &client.Search{
DataProvider: rportAPI,
}

clientsController := &controllers.ClientController{
Rport: rportAPI,
ClientRenderer: cr,
ClientSearch: clientSearch,
}

ctx, cancel := buildContext(context.Background())
Expand Down Expand Up @@ -88,13 +83,9 @@ var clientCmd = &cobra.Command{
Writer: os.Stdout,
Format: getOutputFormat(),
}
clientSearch := &client.Search{
DataProvider: rportAPI,
}
clientsController := &controllers.ClientController{
Rport: rportAPI,
ClientRenderer: cr,
ClientSearch: clientSearch,
}

ctx, cancel := buildContext(context.Background())
Expand All @@ -103,3 +94,12 @@ var clientCmd = &cobra.Command{
return clientsController.Client(ctx, params, clientID, clientName)
},
}

func addClientsPaginationFlags(cmd *cobra.Command) {
cmd.Flags().IntP(api.PaginationLimit, "", api.ClientsLimitDefault, "Number of clients to fetch")
cmd.Flags().IntP(api.PaginationOffset, "", 0, "Offset for clients fetch")
}

func addClientsSearchFlag(cmd *cobra.Command) {
cmd.Flags().StringP("search", "", "", "Search clients on all fields, supports wildcards (*).")
}
14 changes: 7 additions & 7 deletions cmd/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/breathbath/go_utils/v2/pkg/env"

options "github.com/breathbath/go_utils/v2/pkg/config"
"github.com/cloudradar-monitoring/rportcli/internal/pkg/client"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/output"

Expand Down Expand Up @@ -75,9 +74,6 @@ var executeCmd = &cobra.Command{
}

rportAPI := buildRport(params)
clientSearch := &client.Search{
DataProvider: rportAPI,
}

isFullJobOutput := params.ReadBool(controllers.IsFullOutput, false)
cmdExecutor := &controllers.CommandsController{
Expand All @@ -88,7 +84,7 @@ var executeCmd = &cobra.Command{
Format: getOutputFormat(),
IsFullOutput: isFullJobOutput,
},
ClientSearch: clientSearch,
Rport: rportAPI,
},
}

Expand All @@ -105,10 +101,10 @@ func getCommandRequirements() []config.ParameterRequirement {
Help: "Enter comma separated client IDs",
Validate: config.RequiredValidate,
Description: "[required] Comma separated client ids for which the command should be executed. " +
"Alternatively use -n to execute a command by client name(s)",
"Alternatively use -n to execute a command by client name(s), or use --search flag.",
ShortName: "d",
IsEnabled: func(providedParams *options.ParameterBag) bool {
return providedParams.ReadString(controllers.ClientNameFlag, "") == ""
return providedParams.ReadString(controllers.ClientNameFlag, "") == "" && providedParams.ReadString(controllers.SearchFlag, "") == ""
},
IsRequired: true,
},
Expand All @@ -117,6 +113,10 @@ func getCommandRequirements() []config.ParameterRequirement {
Description: "Comma separated client names for which the command should be executed",
ShortName: "n",
},
{
Field: controllers.SearchFlag,
Description: "Search clients on all fields, supports wildcards (*).",
},
{
Field: controllers.Command,
Help: "Enter command",
Expand Down
11 changes: 0 additions & 11 deletions cmd/pagination.go

This file was deleted.

14 changes: 7 additions & 7 deletions cmd/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/breathbath/go_utils/v2/pkg/env"

options "github.com/breathbath/go_utils/v2/pkg/config"
"github.com/cloudradar-monitoring/rportcli/internal/pkg/client"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/output"

Expand Down Expand Up @@ -75,9 +74,6 @@ var executeScript = &cobra.Command{
}

rportAPI := buildRport(params)
clientSearch := &client.Search{
DataProvider: rportAPI,
}

isFullJobOutput := params.ReadBool(controllers.IsFullOutput, false)
cmdExecutor := &controllers.ScriptsController{
Expand All @@ -88,7 +84,7 @@ var executeScript = &cobra.Command{
Format: getOutputFormat(),
IsFullOutput: isFullJobOutput,
},
ClientSearch: clientSearch,
Rport: rportAPI,
},
}

Expand All @@ -105,10 +101,10 @@ func getScriptRequirements() []config.ParameterRequirement {
Help: "Enter comma separated client IDs",
Validate: config.RequiredValidate,
Description: "[required] Comma separated client ids on which the script should be executed. " +
"Alternatively use -n to execute a script by client name(s)",
"Alternatively use -n to execute a script by client name(s), or use --search flag.",
ShortName: "d",
IsEnabled: func(providedParams *options.ParameterBag) bool {
return providedParams.ReadString(controllers.ClientNameFlag, "") == ""
return providedParams.ReadString(controllers.ClientNameFlag, "") == "" && providedParams.ReadString(controllers.SearchFlag, "") == ""
},
IsRequired: true,
},
Expand All @@ -117,6 +113,10 @@ func getScriptRequirements() []config.ParameterRequirement {
Description: "Comma separated client names on which the script should be executed",
ShortName: "n",
},
{
Field: controllers.SearchFlag,
Description: "Search clients on all fields, supports wildcards (*).",
},
{
Field: controllers.Script,
Help: "Enter script path",
Expand Down
21 changes: 4 additions & 17 deletions cmd/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ import (
"os/signal"
"syscall"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/api"
"github.com/cloudradar-monitoring/rportcli/internal/pkg/rdp"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/client"

options "github.com/breathbath/go_utils/v2/pkg/config"

"github.com/cloudradar-monitoring/rportcli/internal/pkg/config"
Expand All @@ -24,6 +21,10 @@ import (
)

func init() {
addClientsPaginationFlags(tunnelListCmd)
addClientsSearchFlag(tunnelListCmd)
tunnelListCmd.Flags().StringP(controllers.ClientNameFlag, "n", "", "Get tunnels of a client by name")
tunnelListCmd.Flags().StringP(controllers.ClientID, "c", "", "Get tunnels of a client by client id")
tunnelsCmd.AddCommand(tunnelListCmd)

config.DefineCommandInputs(tunnelDeleteCmd, getDeleteTunnelRequirements())
Expand All @@ -32,10 +33,6 @@ func init() {
config.DefineCommandInputs(tunnelCreateCmd, getCreateTunnelRequirements())
tunnelsCmd.AddCommand(tunnelCreateCmd)

addPaginationFlags(tunnelListCmd, api.ClientsLimitDefault)
tunnelListCmd.Flags().StringP(controllers.ClientNameFlag, "n", "", "Get tunnels of a client by name")
tunnelListCmd.Flags().StringP(controllers.ClientID, "c", "", "Get tunnels of a client by client id")

rootCmd.AddCommand(tunnelsCmd)
}

Expand All @@ -60,15 +57,10 @@ var tunnelListCmd = &cobra.Command{
Format: getOutputFormat(),
}

clientSearch := &client.Search{
DataProvider: rportAPI,
}

tunnelController := &controllers.TunnelController{
Rport: rportAPI,
TunnelRenderer: tr,
IPProvider: rportAPI,
ClientSearch: clientSearch,
SSHFunc: utils.RunSSH,
RDPWriter: &rdp.FileWriter{},
RDPExecutor: &rdp.Executor{
Expand Down Expand Up @@ -303,10 +295,6 @@ func createTunnelController(params *options.ParameterBag) *controllers.TunnelCon
Format: getOutputFormat(),
}

clientSearch := &client.Search{
DataProvider: rportAPI,
}

rdpExecutor := &rdp.Executor{
CommandProvider: rdp.CommandProvider,
StdErr: os.Stderr,
Expand All @@ -316,7 +304,6 @@ func createTunnelController(params *options.ParameterBag) *controllers.TunnelCon
Rport: rportAPI,
TunnelRenderer: tr,
IPProvider: rportAPI,
ClientSearch: clientSearch,
SSHFunc: utils.RunSSH,
RDPWriter: &rdp.FileWriter{},
RDPExecutor: rdpExecutor,
Expand Down
36 changes: 30 additions & 6 deletions internal/pkg/api/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"context"
"fmt"
"net/http"
url2 "net/url"

Expand All @@ -12,6 +13,7 @@ import (

const (
ClientsURL = "/api/v1/clients"
ClientURL = "/api/v1/clients/%s"
ClientsLimitDefault = 50
ClientsLimitMax = 500
)
Expand All @@ -20,15 +22,16 @@ type ClientsResponse struct {
Data []*models.Client
}

func (rp *Rport) Clients(ctx context.Context, pagination Pagination) (cr *ClientsResponse, err error) {
func (rp *Rport) Clients(ctx context.Context, pagination Pagination, filters Filters) (cr *ClientsResponse, err error) {
var req *http.Request
u, err := url2.Parse(url.JoinURL(rp.BaseURL, ClientsURL))
if err != nil {
return nil, err
}
q := u.Query()
q.Set("fields[clients]", "id,name,timezone,tunnels,address,hostname,os_kernel,connection_state")
q.Set("fields[clients]", "id,name,timezone,tunnels,address,hostname,os_kernel,connection_state,disconnected_at")
pagination.Apply(q)
filters.Apply(q)
u.RawQuery = q.Encode()

req, err = http.NewRequestWithContext(
Expand All @@ -47,12 +50,33 @@ func (rp *Rport) Clients(ctx context.Context, pagination Pagination) (cr *Client
return
}

func (rp *Rport) GetClients(ctx context.Context) (cls []*models.Client, err error) {
var cr *ClientsResponse
cr, err = rp.Clients(ctx, NewPaginationWithLimit(ClientsLimitMax))
type ClientResponse struct {
Data *models.Client
}

func (rp *Rport) Client(ctx context.Context, id string) (*models.Client, error) {
var req *http.Request
u, err := url2.Parse(url.JoinURL(rp.BaseURL, fmt.Sprintf(ClientURL, id)))
if err != nil {
return
return nil, err
}
q := u.Query()
u.RawQuery = q.Encode()

req, err = http.NewRequestWithContext(
ctx,
http.MethodGet,
u.String(),
nil,
)
if err != nil {
return nil, err
}

cr := &ClientResponse{}
_, err = rp.CallBaseClient(req, cr)
if err != nil {
return nil, err
}

return cr.Data, nil
Expand Down
31 changes: 15 additions & 16 deletions internal/pkg/api/clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/cloudradar-monitoring/rportcli/internal/pkg/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var clientsStub = []*models.Client{
Expand Down Expand Up @@ -83,7 +84,7 @@ func TestClientsList(t *testing.T) {
authHeader := r.Header.Get("Authorization")
assert.Equal(t, "Basic bG9nMTE2Njo1NjQzMjI=", authHeader)

assert.Equal(t, ClientsURL+"?fields%5Bclients%5D=id%2Cname%2Ctimezone%2Ctunnels%2Caddress%2Chostname%2Cos_kernel%2Cconnection_state&page%5Blimit%5D=500&page%5Boffset%5D=0", r.URL.String())
assert.Equal(t, ClientsURL+"?fields%5Bclients%5D=id%2Cname%2Ctimezone%2Ctunnels%2Caddress%2Chostname%2Cos_kernel%2Cconnection_state%2Cdisconnected_at&filter%5Bname%5D=abc&page%5Blimit%5D=500&page%5Boffset%5D=0", r.URL.String())
jsonEnc := json.NewEncoder(rw)
e := jsonEnc.Encode(ClientsResponse{Data: clientsStub})
assert.NoError(t, e)
Expand All @@ -98,36 +99,34 @@ func TestClientsList(t *testing.T) {
},
})

clientsResp, err := cl.Clients(context.Background(), NewPaginationWithLimit(ClientsLimitMax))
assert.NoError(t, err)
if err != nil {
return
}
clientsResp, err := cl.Clients(context.Background(), NewPaginationWithLimit(ClientsLimitMax), NewFilters("name", "abc"))
require.NoError(t, err)

assert.Equal(t, clientsStub, clientsResp.Data)
}

func TestGetClientsList(t *testing.T) {
func TestClientGet(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
assert.Equal(t, "Basic bG9nMTE2Njo1NjQzMjI=", authHeader)

assert.Equal(t, ClientsURL+"/test-client", r.URL.String())
jsonEnc := json.NewEncoder(rw)
e := jsonEnc.Encode(ClientsResponse{Data: clientsStub})
e := jsonEnc.Encode(ClientResponse{Data: clientsStub[0]})
assert.NoError(t, e)
}))
defer srv.Close()

cl := New(srv.URL, &utils.StorageBasicAuth{
AuthProvider: func() (login, pass string, err error) {
login = "log1155"
pass = "564314"
login = "log1166"
pass = "564322"
return
},
})
actualClients, err := cl.GetClients(context.Background())
assert.NoError(t, err)

expectedClients := make([]*models.Client, 0, len(clientsStub))

expectedClients = append(expectedClients, clientsStub...)
client, err := cl.Client(context.Background(), "test-client")
require.NoError(t, err)

assert.Equal(t, expectedClients, actualClients)
assert.Equal(t, clientsStub[0], client)
}
Loading

0 comments on commit 55db09d

Please sign in to comment.