Skip to content

Commit

Permalink
Merge pull request #6 from cloudradar-monitoring/DEV-2496
Browse files Browse the repository at this point in the history
[DEV-2496] Add pagination support
  • Loading branch information
thorstenkramm authored Apr 20, 2022
2 parents dbe86a0 + ec9c736 commit 8907afd
Show file tree
Hide file tree
Showing 20 changed files with 108 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
version: v1.30
version: v1.45
args: -c .golangci.yml
test:
name: Test
Expand Down
6 changes: 4 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ linters-settings:
- octalLiteral
- whyNoLint
- wrapperFunc
- ioutilDeprecated
- httpNoBody
- sprintfQuotedString
gocyclo:
min-complexity: 15
goimports:
Expand All @@ -33,8 +36,7 @@ linters-settings:
gomnd:
settings:
mnd:
# don't include the "operation" and "assign"
checks: argument,case,condition,return
checks: case,condition,return
govet:
check-shadowing: true
settings:
Expand Down
4 changes: 3 additions & 1 deletion cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"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 @@ -17,6 +18,7 @@ import (
)

func init() {
addPaginationFlags(clientsListCmd, api.ClientsLimitDefault)
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 @@ -57,7 +59,7 @@ var clientsListCmd = &cobra.Command{
ctx, cancel := buildContext(context.Background())
defer cancel()

return clientsController.Clients(ctx)
return clientsController.Clients(ctx, params)
},
}

Expand Down
11 changes: 11 additions & 0 deletions cmd/pagination.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cmd

import (
"github.com/cloudradar-monitoring/rportcli/internal/pkg/api"
"github.com/spf13/cobra"
)

func addPaginationFlags(cmd *cobra.Command, defaultLimit int) {
cmd.Flags().IntP(api.PaginationLimit, "", defaultLimit, "Number of items to fetch")
cmd.Flags().IntP(api.PaginationOffset, "", 0, "Offset for fetch")
}
11 changes: 6 additions & 5 deletions cmd/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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"
Expand All @@ -31,6 +32,7 @@ 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")

Expand Down Expand Up @@ -113,10 +115,10 @@ rportcli tunnel create -l 0.0.0.0:3394 -r 22 -d bc0b705d-b5fb-4df5-84e3-82dba437
this example opens port 3394 on the rport server and forwards to port 22 of the client bc0b705d-b5fb-4df5-84e3-82dba437bbef
with ssh url scheme and an IP address 10:1:2:3 allowed to access the tunnel
`
createTunnelLocalDescr = `refers to the ports of the rport server address to use for a new tunnel, e.g. '3390' or '0.0.0.0:3390'.
createTunnelLocalDescr = `refers to the ports of the rport server address to use for a new tunnel, e.g. '3390' or '0.0.0.0:3390'.
If local is not specified, a random server port will be assigned automatically`

createTunnelLaunchSSHDescr = `Start the ssh client after the tunnel is established and close tunnel on ssh exit.
createTunnelLaunchSSHDescr = `Start the ssh client after the tunnel is established and close tunnel on ssh exit.
Any parameter passed are append to the ssh command. i.e. -b "-l root"`
)

Expand Down Expand Up @@ -212,7 +214,7 @@ func getCreateTunnelRequirements() []config.ParameterRequirement {
},
{
Field: controllers.LaunchRDP,
Description: `Start the default RDP client after the tunnel is established, e.g. -d 1
Description: `Start the default RDP client after the tunnel is established, e.g. -d 1
Optionally pass the rdp-width and rdp-height params for RDP window size`,
ShortName: "d",
Type: config.BoolRequirementType,
Expand All @@ -237,7 +239,6 @@ Optionally pass the rdp-width and rdp-height params for RDP window size`,
Description: `username for a RDP session`,
ShortName: "u",
Type: config.StringRequirementType,
Validate: config.RequiredValidate,
Help: "Enter a RDP user name",
IsEnabled: func(providedParams *options.ParameterBag) bool { return IsRDPUserRequired },
},
Expand Down Expand Up @@ -285,7 +286,7 @@ func getDeleteTunnelRequirements() []config.ParameterRequirement {
{
Field: controllers.TunnelID,
Description: "[required] tunnel id to delete",
ShortName: "t",
ShortName: "u", // t is used for timeout
IsRequired: true,
Validate: config.RequiredValidate,
Help: "Enter a tunnel id",
Expand Down
1 change: 1 addition & 0 deletions cmd/tunnelRDP_linux.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build linux
// +build linux

package cmd
Expand Down
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/dustin/go-humanize v1.0.0
github.com/fatih/color v1.10.0
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/gorilla/websocket v1.4.2
github.com/magiconair/properties v1.8.4
github.com/mattn/go-runewidth v0.0.10 // indirect
Expand Down
3 changes: 0 additions & 3 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-jwt/jwt v1.0.2 h1:Nj1npK0K5RnXGo1SxoOixRGAehIZ2326eXuca9gX9A4=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
Expand Down
9 changes: 6 additions & 3 deletions internal/pkg/api/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,24 @@ import (
)

const (
ClientsURL = "/api/v1/clients"
ClientsURL = "/api/v1/clients"
ClientsLimitDefault = 50
ClientsLimitMax = 500
)

type ClientsResponse struct {
Data []*models.Client
}

func (rp *Rport) Clients(ctx context.Context) (cr *ClientsResponse, err error) {
func (rp *Rport) Clients(ctx context.Context, pagination Pagination) (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")
pagination.Apply(q)
u.RawQuery = q.Encode()

req, err = http.NewRequestWithContext(
Expand All @@ -46,7 +49,7 @@ func (rp *Rport) Clients(ctx context.Context) (cr *ClientsResponse, err error) {

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

if err != nil {
return
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/api/clients_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,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", r.URL.String())
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())
jsonEnc := json.NewEncoder(rw)
e := jsonEnc.Encode(ClientsResponse{Data: clientsStub})
assert.NoError(t, e)
Expand All @@ -98,7 +98,7 @@ func TestClientsList(t *testing.T) {
},
})

clientsResp, err := cl.Clients(context.Background())
clientsResp, err := cl.Clients(context.Background(), NewPaginationWithLimit(ClientsLimitMax))
assert.NoError(t, err)
if err != nil {
return
Expand Down
37 changes: 37 additions & 0 deletions internal/pkg/api/pagination.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package api

import (
"net/url"
"strconv"

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

const (
PaginationOffset = "offset"
PaginationLimit = "limit"
)

type Pagination struct {
Limit int
Offset int
}

func NewPaginationFromParams(params *options.ParameterBag) Pagination {
return Pagination{
Offset: params.ReadInt(PaginationOffset, 0),
Limit: params.ReadInt(PaginationLimit, -1),
}
}

func NewPaginationWithLimit(max int) Pagination {
return Pagination{
Offset: 0,
Limit: max,
}
}

func (p Pagination) Apply(q url.Values) {
q.Set("page[offset]", strconv.Itoa(p.Offset))
q.Set("page[limit]", strconv.Itoa(p.Limit))
}
22 changes: 22 additions & 0 deletions internal/pkg/api/pagination_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package api

import (
"net/url"
"testing"

options "github.com/breathbath/go_utils/v2/pkg/config"
"github.com/stretchr/testify/assert"
)

func TestPaginationFromParams(t *testing.T) {
pagination := NewPaginationFromParams(options.New(options.NewMapValuesProvider(map[string]interface{}{
"limit": 30,
"offset": 90,
})))

q := url.Values{}
pagination.Apply(q)

assert.Equal(t, q.Get("page[limit]"), "30")
assert.Equal(t, q.Get("page[offset]"), "90")
}
2 changes: 1 addition & 1 deletion internal/pkg/config/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (fvp *FlagValuesProvider) ToKeyValues() map[string]interface{} {

func (fvp *FlagValuesProvider) Read(name string) (val interface{}, found bool) {
fl := fvp.flags.Lookup(name)
if fl == nil || !fl.Changed {
if fl == nil {
return nil, false
}

Expand Down
11 changes: 6 additions & 5 deletions internal/pkg/config/load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,19 +331,20 @@ func TestCollectParams(t *testing.T) {

func TestFlagValuesProvider(t *testing.T) {
fl := &pflag.FlagSet{}
fl.StringP("somekey", "s", "", "")
fl.StringP("somekey", "s", "test-default", "")

flagValuesProv := CreateFlagValuesProvider(fl)

_, found := flagValuesProv.Read("somekey")
assert.False(t, found)
val, found := flagValuesProv.Read("somekey")
assert.True(t, found)
assert.Equal(t, "test-default", val)

err := fl.Parse([]string{"--somekey", "someval"})
require.NoError(t, err)

val, found2 := flagValuesProv.Read("somekey")
val2, found2 := flagValuesProv.Read("somekey")
assert.True(t, found2)
assert.Equal(t, "someval", val.(string))
assert.Equal(t, "someval", val2)

actualKeyValues := flagValuesProv.ToKeyValues()
assert.Equal(t, map[string]interface{}{"somekey": "someval"}, actualKeyValues)
Expand Down
6 changes: 3 additions & 3 deletions internal/pkg/controllers/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ type ClientController struct {
ClientRenderer ClientRenderer
}

func (cc *ClientController) Clients(ctx context.Context) error {
clResp, err := cc.Rport.Clients(ctx)
func (cc *ClientController) Clients(ctx context.Context, params *options.ParameterBag) error {
clResp, err := cc.Rport.Clients(ctx, api.NewPaginationFromParams(params))
if err != nil {
return err
}
Expand All @@ -42,7 +42,7 @@ func (cc *ClientController) Client(ctx context.Context, params *options.Paramete
renderDetails := params.ReadBool("all", false)

if id != "" {
clResp, err := cc.Rport.Clients(ctx)
clResp, err := cc.Rport.Clients(ctx, api.NewPaginationWithLimit(api.ClientsLimitMax))
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/controllers/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestClientsController(t *testing.T) {
ClientRenderer: &ClientRendererMock{Writer: &buf},
}

err := clController.Clients(context.Background())
err := clController.Clients(context.Background(), options.New(nil))
assert.NoError(t, err)
if err != nil {
return
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/controllers/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (tc *TunnelController) Tunnels(ctx context.Context, params *options.Paramet
}
} else {
var clResp *api.ClientsResponse
clResp, err = tc.Rport.Clients(ctx)
clResp, err = tc.Rport.Clients(ctx, api.NewPaginationFromParams(params))
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/rdp/exec_nix.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build linux
// +build linux

package rdp
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/rdp/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (rfw *FileWriter) WriteRDPFile(fi models.FileInput) (filePath string, err e

logrus.Debugf("will write an rdp file %s", file.Name())

_, err = file.Write([]byte(content))
_, err = file.WriteString(content)
if err != nil {
return "", err
}
Expand Down
1 change: 1 addition & 0 deletions internal/pkg/utils/io_nix.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris

package utils
Expand Down

0 comments on commit 8907afd

Please sign in to comment.