Skip to content

Commit

Permalink
change metadata to labels
Browse files Browse the repository at this point in the history
  • Loading branch information
eutopian committed Jan 31, 2025
1 parent a71b667 commit 2a87ac5
Show file tree
Hide file tree
Showing 7 changed files with 265 additions and 153 deletions.
84 changes: 54 additions & 30 deletions deployment/address_book.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ var (
)

type TypeAndVersion struct {
Type ContractType
Version semver.Version
Metadata MetadataSet
Type ContractType
Version semver.Version
Labels LabelSet
}

func (tv TypeAndVersion) String() string {
if len(tv.Metadata) == 0 {
if len(tv.Labels) == 0 {
return fmt.Sprintf("%s %s", tv.Type, tv.Version.String())
}
mdSlice := tv.Metadata.AsSlice()
mdSlice := tv.Labels.AsSlice()
sort.Strings(mdSlice) // stable order
return fmt.Sprintf("%s %s %s",
tv.Type,
Expand All @@ -52,7 +52,16 @@ func (tv TypeAndVersion) String() string {
}

func (tv TypeAndVersion) Equal(other TypeAndVersion) bool {
return tv.String() == other.String()
// Compare Type
if tv.Type != other.Type {
return false
}
// Compare Versions
if !tv.Version.Equal(&other.Version) {
return false
}
// Compare Labels
return tv.Labels.Equal(other.Labels)
}

func MustTypeAndVersionFromString(s string) TypeAndVersion {
Expand All @@ -74,22 +83,22 @@ func TypeAndVersionFromString(s string) (TypeAndVersion, error) {
if err != nil {
return TypeAndVersion{}, err
}
metadata := make(MetadataSet)
labels := make(LabelSet)
if len(parts) > 2 {
metadata = NewMetadataSet(parts[2:]...)
labels = NewLabelSet(parts[2:]...)
}
return TypeAndVersion{
Type: ContractType(parts[0]),
Version: *v,
Metadata: metadata,
Type: ContractType(parts[0]),
Version: *v,
Labels: labels,
}, nil
}

func NewTypeAndVersion(t ContractType, v semver.Version) TypeAndVersion {
return TypeAndVersion{
Type: t,
Version: v,
Metadata: make(MetadataSet), // empty set,
Type: t,
Version: v,
Labels: make(LabelSet), // empty set,
}
}

Expand Down Expand Up @@ -291,38 +300,53 @@ func AddressBookContains(ab AddressBook, chain uint64, addrToFind string) (bool,
return false, nil
}

// typeVersionKey creates a comparable key from Type and Version
type typeVersionKey struct {
Type ContractType
Version string
Labels string // store labels in a canonical form (comma-joined sorted list)
}

func tvKey(tv TypeAndVersion) typeVersionKey {
sortedLabels := make([]string, 0, len(tv.Labels))
for lbl := range tv.Labels {
sortedLabels = append(sortedLabels, lbl)
}
sort.Strings(sortedLabels)
return typeVersionKey{
Type: tv.Type,
Version: tv.Version.String(),
Labels: strings.Join(sortedLabels, ","),
}
}

// AddressesContainBundle checks if the addresses
// contains a single instance of all the addresses in the bundle.
// It returns an error if there are more than one instance of a contract.
func AddressesContainBundle(addrs map[string]TypeAndVersion, wantTypes []TypeAndVersion) (bool, error) {
// Count how many times each wanted TypeAndVersion is found
counts := make(map[typeVersionKey]int)
for _, wantType := range wantTypes {
key := typeVersionKey{Type: wantType.Type, Version: wantType.Version.String()}
for _, haveType := range addrs {
sameType := (wantType.Type == haveType.Type)
sameVersion := wantType.Version.String() == haveType.Version.String()

if sameType && sameVersion {
counts[key]++
if counts[key] > 1 {
return false, fmt.Errorf("found more than one instance of contract %s %s", key.Type, key.Version)
for _, wantTV := range wantTypes {
wantKey := tvKey(wantTV)
for _, haveTV := range addrs {
if wantTV.Equal(haveTV) {
// They match exactly (Type, Version, Labels)
counts[wantKey]++
if counts[wantKey] > 1 {
return false, fmt.Errorf("found more than one instance of contract %s %s (labels=%v)",
wantTV.Type, wantTV.Version.String(), wantTV.Labels)
}
}
}
}

// Ensure we found *all* wantTypes exactly once
return len(counts) == len(wantTypes), nil
}

// AddMetadata adds a string to the metadata set in the TypeAndVersion.
func (tv *TypeAndVersion) AddMetadata(md string) {
if tv.Metadata == nil {
tv.Metadata = make(MetadataSet)
// AddLabel adds a string to the LabelSet in the TypeAndVersion.
func (tv *TypeAndVersion) AddLabel(label string) {
if tv.Labels == nil {
tv.Labels = make(LabelSet)
}
tv.Metadata.Add(md)
tv.Labels.Add(label)
}
51 changes: 51 additions & 0 deletions deployment/address_book_labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package deployment

// LabelSet represents a set of labels on an address book entry.
type LabelSet map[string]struct{}

// NewLabelSet initializes a new LabelSet with any number of labels.
func NewLabelSet(labels ...string) LabelSet {
set := make(LabelSet)
for _, lb := range labels {
set[lb] = struct{}{}
}
return set
}

// Add inserts a labels into the set.
func (ls LabelSet) Add(labels string) {
ls[labels] = struct{}{}
}

// Remove deletes a labels from the set, if it exists.
func (ls LabelSet) Remove(labels string) {
delete(ls, labels)
}

// Contains checks if the set contains the given labels.
func (ls LabelSet) Contains(labels string) bool {
_, ok := ls[labels]
return ok
}

// AsSlice returns the labels in a slice. Useful for printing or serialization.
func (ls LabelSet) AsSlice() []string {
out := make([]string, 0, len(ls))
for labels := range ls {
out = append(out, labels)
}
return out
}

// Equal checks if two LabelSets are equal.
func (ls LabelSet) Equal(other LabelSet) bool {
if len(ls) != len(other) {
return false
}
for label := range ls {
if _, ok := other[label]; !ok {
return false
}
}
return true
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,36 @@ import (
"github.com/stretchr/testify/assert"
)

func TestNewMetadataSet(t *testing.T) {
t.Run("no metadata", func(t *testing.T) {
ms := NewMetadataSet()
func TestNewLabelSet(t *testing.T) {
t.Run("no labels", func(t *testing.T) {
ms := NewLabelSet()
assert.Empty(t, ms, "expected empty set")
})

t.Run("some metadata", func(t *testing.T) {
ms := NewMetadataSet("foo", "bar")
t.Run("some labels", func(t *testing.T) {
ms := NewLabelSet("foo", "bar")
assert.Len(t, ms, 2)
assert.True(t, ms.Contains("foo"))
assert.True(t, ms.Contains("bar"))
assert.False(t, ms.Contains("baz"))
})
}

func TestMetadataSet_Add(t *testing.T) {
ms := NewMetadataSet("initial")
func TestLabelSet_Add(t *testing.T) {
ms := NewLabelSet("initial")
ms.Add("new")

assert.True(t, ms.Contains("initial"), "expected 'initial' in set")
assert.True(t, ms.Contains("new"), "expected 'new' in set")
assert.Len(t, ms, 2, "expected 2 distinct metadata in set")
assert.Len(t, ms, 2, "expected 2 distinct labels in set")

// Add duplicate "new" again; size should remain 2
ms.Add("new")
assert.Len(t, ms, 2, "expected size to remain 2 after adding a duplicate")
}

func TestMetadataSet_Remove(t *testing.T) {
ms := NewMetadataSet("remove_me", "keep")
func TestLabelSet_Remove(t *testing.T) {
ms := NewLabelSet("remove_me", "keep")
ms.Remove("remove_me")

assert.False(t, ms.Contains("remove_me"), "expected 'remove_me' to be removed")
Expand All @@ -47,20 +47,20 @@ func TestMetadataSet_Remove(t *testing.T) {
assert.Len(t, ms, 1, "expected size to remain 1 after removing a non-existent item")
}

func TestMetadataSet_Contains(t *testing.T) {
ms := NewMetadataSet("foo", "bar")
func TestLabelSet_Contains(t *testing.T) {
ms := NewLabelSet("foo", "bar")

assert.True(t, ms.Contains("foo"))
assert.True(t, ms.Contains("bar"))
assert.False(t, ms.Contains("baz"))
}

func TestMetadataSet_AsSlice(t *testing.T) {
ms := NewMetadataSet("foo", "bar")
func TestLabelSet_AsSlice(t *testing.T) {
ms := NewLabelSet("foo", "bar")
slice := ms.AsSlice()

// We can't rely on order in a map-based set, so we only check membership and length
assert.Len(t, slice, 2, "expected 2 distinct metadata in slice")
assert.Len(t, slice, 2, "expected 2 distinct labels in slice")

// Convert slice to a map for quick membership checks
found := make(map[string]bool)
Expand Down
38 changes: 0 additions & 38 deletions deployment/address_book_metadata.go

This file was deleted.

Loading

0 comments on commit 2a87ac5

Please sign in to comment.