Skip to content

Commit

Permalink
Some scoping on some resources somewhere.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit91 committed Feb 6, 2025
1 parent 7d61ac9 commit 4a0dca5
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 193 deletions.
6 changes: 5 additions & 1 deletion cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/metal-stack/api-server/pkg/db/generic"
"github.com/metal-stack/api-server/pkg/invite"
ratelimiter "github.com/metal-stack/api-server/pkg/rate-limiter"
"github.com/metal-stack/api-server/pkg/repository"
"github.com/metal-stack/api-server/pkg/service/health"
"github.com/metal-stack/api-server/pkg/service/ip"
"github.com/metal-stack/api-server/pkg/service/method"
Expand Down Expand Up @@ -164,7 +165,10 @@ func (s *server) Run() error {
if err != nil {
return err
}
ipService := ip.New(ip.Config{Log: s.log, Datastore: ds, Ipam: s.c.Ipam})

repo := repository.New(s.log, s.c.MasterClient, ds, s.c.Ipam)

ipService := ip.New(ip.Config{Log: s.log, Repo: repo})
tokenService := token.New(token.Config{
Log: s.log,
CertStore: certStore,
Expand Down
10 changes: 4 additions & 6 deletions pkg/db/generic/rethinkdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ type (
SetCreated(created time.Time)
}

EntityQuery interface {
Query(q r.Term) *r.Term
}
EntityQuery func(q r.Term) r.Term

Storage[E Entity] interface {
Create(ctx context.Context, e E) (E, error)
Expand Down Expand Up @@ -161,7 +159,7 @@ func (rs *rethinkStore[E]) Delete(ctx context.Context, e E) error {
// Find implements Storage.
func (rs *rethinkStore[E]) Find(ctx context.Context, query EntityQuery) (E, error) {
var zero E
res, err := query.Query(rs.table).Run(rs.queryExecutor, r.RunOpts{Context: ctx})
res, err := query(rs.table).Run(rs.queryExecutor, r.RunOpts{Context: ctx})
if err != nil {
return zero, fmt.Errorf("cannot find %v in database: %w", rs.tableName, err)
}
Expand All @@ -186,8 +184,8 @@ func (rs *rethinkStore[E]) Find(ctx context.Context, query EntityQuery) (E, erro
}

func (rs *rethinkStore[E]) Search(ctx context.Context, query EntityQuery) ([]E, error) {
rs.log.Info("search", "table", rs.table, "query", query.Query(rs.table))
res, err := query.Query(rs.table).Run(rs.queryExecutor, r.RunOpts{Context: ctx})
rs.log.Info("search", "table", rs.table, "query", query(rs.table).String())
res, err := query(rs.table).Run(rs.queryExecutor, r.RunOpts{Context: ctx})
if err != nil {
return nil, fmt.Errorf("cannot search %v in database: %w", rs.tableName, err)
}
Expand Down
90 changes: 90 additions & 0 deletions pkg/db/queries/ip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package queries

import (
"fmt"

apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
"github.com/metal-stack/metal-lib/pkg/tag"

r "gopkg.in/rethinkdb/rethinkdb-go.v6"
)

func IpProjectScoped(project string) func(q r.Term) r.Term {
return func(q r.Term) r.Term {
return q.Filter(func(row r.Term) r.Term {
return row.Field("projectid").Eq(project)
})
}
}

func IpFilter(rq *apiv2.IPServiceListRequest) func(q r.Term) r.Term {
return func(q r.Term) r.Term {
// Project is mandatory
q = q.Filter(func(row r.Term) r.Term {
return row.Field("projectid").Eq(rq.Project)
})

if rq.Ip != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("id").Eq(*rq.Ip)
})
}

if rq.Uuid != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("allocationuuid").Eq(*rq.Uuid)
})
}

if rq.Name != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("name").Eq(*rq.Name)
})
}

if rq.Network != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("networkid").Eq(*rq.Network)
})
}

if rq.ParentPrefixCidr != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("prefix").Eq(*rq.ParentPrefixCidr)
})
}

if rq.MachineId != nil {
rq.Tags = append(rq.Tags, fmt.Sprintf("%s=%s", tag.MachineID, *rq.MachineId))
}

for _, t := range rq.Tags {
t := t
q = q.Filter(func(row r.Term) r.Term {
return row.Field("tags").Contains(r.Expr(t))
})
}

if rq.Type != nil {
q = q.Filter(func(row r.Term) r.Term {
return row.Field("type").Eq(rq.Type.String())
})
}

if rq.AddressFamily != nil {
var separator string
switch rq.AddressFamily.String() {
case apiv2.IPAddressFamily_IP_ADDRESS_FAMILY_V4.String():
separator = "\\."
case apiv2.IPAddressFamily_IP_ADDRESS_FAMILY_V6.String():
separator = ":"
}

q = q.Filter(func(row r.Term) r.Term {
return row.Field("id").Match(separator)
})
}

return q
}
}
82 changes: 68 additions & 14 deletions pkg/repository/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,86 @@ package repository
import (
"context"
"fmt"

"connectrpc.com/connect"
"github.com/metal-stack/api-server/pkg/db/metal"
"github.com/metal-stack/api-server/pkg/db/queries"
apiv2 "github.com/metal-stack/api/go/metalstack/api/v2"
)

type ipRepository struct {
r *Repository
r *Repository
scope ProjectScope
}

// nolint:unused
type ipUnscopedRepository struct {
r *Repository
func (r *ipRepository) Get(ctx context.Context, id string) (*metal.IP, error) {
ip, err := r.r.ds.IP().Get(ctx, id)
if err != nil {
return nil, err
}

if r.scope != ProjectScope(ip.ProjectID) {
return nil, fmt.Errorf("TODO: NOT YOUR ENTITY NOT FOUND")
}

return ip, nil
}

func (r *ipRepository) Get(ctx context.Context, id string) (string, error) {
func (r *ipRepository) Update(ctx context.Context, rq *apiv2.IPServiceUpdateRequest) (*metal.IP, error) {
old, err := r.Get(ctx, rq.Ip)
if err != nil {
return nil, err
}

ip, err := r.r.ds.IP().Get(ctx, id)
new := *old

if rq.Description != nil {
new.Description = *rq.Description
}
if rq.Name != nil {
new.Name = *rq.Name
}
if rq.Type != nil {
var t metal.IPType
switch rq.Type.String() {
case apiv2.IPType_IP_TYPE_EPHEMERAL.String():
t = metal.Ephemeral
case apiv2.IPType_IP_TYPE_STATIC.String():
t = metal.Static
case apiv2.IPType_IP_TYPE_UNSPECIFIED.String():
return nil, connect.NewError(connect.CodeInvalidArgument, fmt.Errorf("ip type cannot be unspecified: %s", rq.Type))
}
new.Type = t
}
new.Tags = rq.Tags

err = r.r.ds.IP().Update(ctx, &new, old)
if err != nil {
return nil, err
}

return &new, nil
}

func (r *ipRepository) Delete(ctx context.Context, id string) (*metal.IP, error) {
ip, err := r.Get(ctx, id)
if err != nil {
return "", err
return nil, err
}

fmt.Print(ip)
err = r.r.ds.IP().Delete(ctx, ip)
if err != nil {
return nil, err
}

nw, _ := r.r.Network().Get(ctx, "asdf")
fmt.Print(nw)
return "1.2.3.4", nil
return ip, nil
}

// nolint:unused
func (ur *ipUnscopedRepository) List() []string {
return []string{"1.2.3.4", "fe80::1"}
func (r *ipRepository) List(ctx context.Context, rq *apiv2.IPServiceListRequest) ([]*metal.IP, error) {
ip, err := r.r.ds.IP().Search(ctx, queries.IpFilter(rq))
if err != nil {
return nil, err
}

return ip, nil
}
15 changes: 15 additions & 0 deletions pkg/repository/ip_unscoped.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package repository

import (
"context"

"github.com/metal-stack/api-server/pkg/db/metal"
)

type ipUnscopedRepository struct {
r *Repository
}

func (ur *ipUnscopedRepository) List(ctx context.Context) ([]*metal.IP, error) {
return ur.r.ds.IP().List(ctx)
}
8 changes: 8 additions & 0 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,17 @@ func New(log *slog.Logger, mdc mdm.Client, ds *generic.Datastore, ipam ipamv1con

func (r *Repository) IP(scope ProjectScope) *ipRepository {
return &ipRepository{
r: r,
scope: scope,
}
}

func (r *Repository) UnscopedIP() *ipUnscopedRepository {
return &ipUnscopedRepository{
r: r,
}
}

func (r *Repository) Network() *networkRepository {
return &networkRepository{
r: r,
Expand Down
24 changes: 24 additions & 0 deletions pkg/repository/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/metal-stack/api-server/pkg/db/generic"
"github.com/metal-stack/api-server/pkg/repository"
"github.com/metal-stack/api-server/pkg/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -36,3 +37,26 @@ func TestGet(t *testing.T) {

fmt.Printf("%s %s", ip, nw)
}

func TestIpUnscopedList(t *testing.T) {
ctx := context.Background()
log := slog.Default()

container, c, err := test.StartRethink(t)
require.NoError(t, err)
defer func() {
_ = container.Terminate(context.Background())
}()

ipam := test.StartIpam(t)

ds, err := generic.New(log, "metal", c)
require.NoError(t, err)

repo := repository.New(log, nil, ds, ipam)

ips, err := repo.UnscopedIP().List(ctx)
require.NoError(t, err)

assert.Empty(t, ips)
}
Loading

0 comments on commit 4a0dca5

Please sign in to comment.