Skip to content

Commit

Permalink
add workspace param in FillID methods (#395)
Browse files Browse the repository at this point in the history
  • Loading branch information
randmonkey authored Jan 5, 2024
1 parent ec62201 commit 72313bb
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 17 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,15 @@
- [0.2.0](#020)
- [0.1.0](#010)

## [v0.50.0]

> Release date: TBD
- Added `workspace` parameter to `FillID` method of entities to avoid entities
with same key in different workspaces to have the same ID, which is unique
cross all workspaces.
[#395](https://github.com/Kong/go-kong/pull/395)

## [v0.49.0]

> Release date: 2024/01/04
Expand Down
30 changes: 17 additions & 13 deletions kong/ids.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
// FillID fills the ID of an entity. It is a no-op if the entity already has an ID.
// ID is generated in a deterministic way using UUIDv5. The UUIDv5 namespace is different for each entity type.
// The name used to generate the ID for Service is Service.Name.
func (s *Service) FillID() error {
func (s *Service) FillID(workspace string) error {
if s == nil {
return fmt.Errorf("service is nil")
}
Expand All @@ -27,14 +27,14 @@ func (s *Service) FillID() error {
return fmt.Errorf("could not get id generator: %w", err)
}

s.ID = gen.buildIDFor(*s.Name)
s.ID = gen.buildIDFor(workspace, *s.Name)
return nil
}

// FillID fills the ID of an entity. It is a no-op if the entity already has an ID.
// ID is generated in a deterministic way using UUIDv5. The UUIDv5 namespace is different for each entity type.
// The name used to generate the ID for Route is Route.Name.
func (r *Route) FillID() error {
func (r *Route) FillID(workspace string) error {
if r == nil {
return fmt.Errorf("route is nil")
}
Expand All @@ -51,14 +51,14 @@ func (r *Route) FillID() error {
return fmt.Errorf("could not get id generator: %w", err)
}

r.ID = gen.buildIDFor(*r.Name)
r.ID = gen.buildIDFor(workspace, *r.Name)
return nil
}

// FillID fills the ID of an entity. It is a no-op if the entity already has an ID.
// ID is generated in a deterministic way using UUIDv5. The UUIDv5 namespace is different for each entity type.
// The name used to generate the ID for Consumer is Consumer.Username.
func (c *Consumer) FillID() error {
func (c *Consumer) FillID(workspace string) error {
if c == nil {
return fmt.Errorf("consumer is nil")
}
Expand All @@ -75,14 +75,14 @@ func (c *Consumer) FillID() error {
return fmt.Errorf("could not get id generator: %w", err)
}

c.ID = gen.buildIDFor(*c.Username)
c.ID = gen.buildIDFor(workspace, *c.Username)
return nil
}

// FillID fills the ID of an entity. It is a no-op if the entity already has an ID.
// ID is generated in a deterministic way using UUIDv5. The UUIDv5 namespace is different for each entity type.
// The name used to generate the ID for ConsumerGroup is ConsumerGroup.Name.
func (cg *ConsumerGroup) FillID() error {
func (cg *ConsumerGroup) FillID(workspace string) error {
if cg == nil {
return fmt.Errorf("consumer group is nil")
}
Expand All @@ -99,15 +99,15 @@ func (cg *ConsumerGroup) FillID() error {
return fmt.Errorf("could not get id generator: %w", err)
}

cg.ID = gen.buildIDFor(*cg.Name)
cg.ID = gen.buildIDFor(workspace, *cg.Name)
return nil
}

// FillID fills the ID of an entity. It is a no-op if the entity already has an ID.
// ID is generated in a deterministic way using UUIDv5.
// The UUIDv5 namespace being used for generation is separate from other namespaces used for generating IDs for other types.
// The name used to generate the ID for Vault is Vault.Prefix.
func (v *Vault) FillID() error {
func (v *Vault) FillID(workspace string) error {
if v == nil {
return fmt.Errorf("vault is nil")
}
Expand All @@ -124,7 +124,7 @@ func (v *Vault) FillID() error {
return fmt.Errorf("could not get id generator: %w", err)
}

v.ID = gen.buildIDFor(*v.Prefix)
v.ID = gen.buildIDFor(workspace, *v.Prefix)
return nil
}

Expand All @@ -149,8 +149,12 @@ type idGenerator struct {
namespace uuid.UUID
}

func (g idGenerator) buildIDFor(entityKey string) *string {
id := uuid.NewSHA1(g.namespace, []byte(entityKey)).String()
func (g idGenerator) buildIDFor(workspace string, entityKey string) *string {
key := entityKey
if len(workspace) > 0 {
key = workspace + "/" + key
}
id := uuid.NewSHA1(g.namespace, []byte(key)).String()
return &id
}

Expand All @@ -162,7 +166,7 @@ func newIDGeneratorFor(entityPluralName string) idGenerator {

// IDFillable is a type constraint for entities that can be filled with an ID.
type IDFillable interface {
FillID() error
FillID(workspace string) error
}

// idGeneratorFor returns the ID generator for the given entity type.
Expand Down
22 changes: 18 additions & 4 deletions kong/ids_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
)

type fillEntityIDTestCase struct {
name string
entity kong.IDFillable

name string
entity kong.IDFillable
workspace string
assertEntity func(t *testing.T, entity kong.IDFillable)
expectErr bool
}
Expand Down Expand Up @@ -104,6 +104,20 @@ func TestFillEntityID(t *testing.T) {
require.Equal(t, expectedID, *consumer.ID, "ID should be deterministic")
},
},
{
name: "consumer with username and workspace",
entity: &kong.Consumer{
Username: kong.String("some.username"),
},
workspace: "ws.1",
assertEntity: func(t *testing.T, e kong.IDFillable) {
consumer := e.(*kong.Consumer)
require.NotNil(t, consumer.ID)

const expectedID = "4701c235-f7f0-51ee-8782-0d8e145d6771"
require.Equal(t, expectedID, *consumer.ID, "ID should be deterministic")
},
},
// Consumer Group
{
name: "consumer group nil pointer",
Expand Down Expand Up @@ -173,7 +187,7 @@ func TestFillEntityID(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

err := tc.entity.FillID()
err := tc.entity.FillID(tc.workspace)
if tc.expectErr {
require.Error(t, err)
return
Expand Down

0 comments on commit 72313bb

Please sign in to comment.