Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions kurtosis-devnet/pkg/kurtosis/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type ServiceFinder struct {
services inspect.ServiceMap
nodeServices []string
l2ServicePrefix string
l2Networks []string
}

// ServiceFinderOption configures a ServiceFinder
Expand All @@ -32,6 +33,13 @@ func WithL2ServicePrefix(prefix string) ServiceFinderOption {
}
}

// WithL2Networks sets the L2 networks
func WithL2Networks(networks []string) ServiceFinderOption {
return func(f *ServiceFinder) {
f.l2Networks = networks
}
}

// NewServiceFinder creates a new ServiceFinder with the given options
func NewServiceFinder(services inspect.ServiceMap, opts ...ServiceFinderOption) *ServiceFinder {
f := &ServiceFinder{
Expand Down Expand Up @@ -69,6 +77,20 @@ func (f *ServiceFinder) FindL2Services(network string) ([]descriptors.Node, desc
tag, idx := f.serviceTag(strings.TrimPrefix(name, f.l2ServicePrefix))
return tag, idx, true
}

// skip over the other L2 services
for _, l2Network := range f.l2Networks {
if strings.HasSuffix(serviceName, "-"+l2Network) {
return "", 0, false
}
}

// Some services don't have a network suffix, as they span multiple chains
// TODO(14849): ideally we'd need to handle *partial* chain coverage.
if strings.HasPrefix(serviceName, f.l2ServicePrefix) {
tag, idx := f.serviceTag(strings.TrimPrefix(serviceName, f.l2ServicePrefix))
return tag, idx, true
}
return "", 0, false
})
}
Expand Down
145 changes: 144 additions & 1 deletion kurtosis-devnet/pkg/kurtosis/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,153 @@ func TestFindRPCEndpoints(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
finder := NewServiceFinder(tt.services)
finder := NewServiceFinder(tt.services, WithL2Networks([]string{"op-kurtosis", "network1", "network2", "custom-host"}))
gotNodes, gotServices := tt.findFn(finder)
assert.Equal(t, tt.wantNodes, gotNodes)
assert.Equal(t, tt.wantServices, gotServices)
})
}
}

func TestFindL2ServicesSkipsOtherNetworks(t *testing.T) {
// Create a service map with services from multiple L2 networks
services := inspect.ServiceMap{
// network1 services
"op-batcher-network1": inspect.PortMap{
"http": {Port: 8080},
},
"op-proposer-network1": inspect.PortMap{
"http": {Port: 8082},
},
"op-cl-1-op-node-op-geth-network1": inspect.PortMap{
"http": {Port: 8084},
},

// network2 services
"op-batcher-network2": inspect.PortMap{
"http": {Port: 8081},
},
"op-proposer-network2": inspect.PortMap{
"http": {Port: 8083},
},
"op-cl-1-op-node-op-geth-network2": inspect.PortMap{
"http": {Port: 8085},
},

// network3 services
"op-batcher-network3": inspect.PortMap{
"http": {Port: 8086},
},
"op-proposer-network3": inspect.PortMap{
"http": {Port: 8087},
},
"op-cl-1-op-node-op-geth-network3": inspect.PortMap{
"http": {Port: 8088},
},

// Common service without network suffix
"op-common-service": inspect.PortMap{
"http": {Port: 8089},
},
}

// Create a service finder with all networks configured
finder := NewServiceFinder(
services,
WithL2Networks([]string{"network1", "network2", "network3"}),
)

// Test finding services for network2
t.Run("find network2 services", func(t *testing.T) {
nodes, serviceMap := finder.FindL2Services("network2")

// Verify nodes
assert.Len(t, nodes, 1)
if len(nodes) > 0 {
assert.Contains(t, nodes[0].Services, "cl")
assert.Equal(t, "op-cl-1-op-node-op-geth-network2", nodes[0].Services["cl"].Name)
}

// Verify services
assert.Len(t, serviceMap, 3) // batcher, proposer, common-service
assert.Contains(t, serviceMap, "batcher")
assert.Contains(t, serviceMap, "proposer")
assert.Contains(t, serviceMap, "common-service")
assert.Equal(t, "op-batcher-network2", serviceMap["batcher"].Name)
assert.Equal(t, "op-proposer-network2", serviceMap["proposer"].Name)
assert.Equal(t, "op-common-service", serviceMap["common-service"].Name)

// Verify network1 and network3 services are not included
for _, service := range serviceMap {
assert.NotContains(t, service.Name, "network1")
assert.NotContains(t, service.Name, "network3")
}
})

// Test with a network that doesn't exist
t.Run("find non-existent network services", func(t *testing.T) {
nodes, serviceMap := finder.FindL2Services("non-existent")

// Should only find common services
assert.Len(t, nodes, 0)
assert.Len(t, serviceMap, 1)
assert.Contains(t, serviceMap, "common-service")
assert.Equal(t, "op-common-service", serviceMap["common-service"].Name)
})
}

func TestServiceTag(t *testing.T) {
finder := NewServiceFinder(inspect.ServiceMap{})

tests := []struct {
name string
input string
wantTag string
wantIndex int
}{
{
name: "simple service without index",
input: "batcher",
wantTag: "batcher",
wantIndex: 0,
},
{
name: "service with index 1",
input: "node-1",
wantTag: "node",
wantIndex: 1,
},
{
name: "service with index 2",
input: "node-2",
wantTag: "node",
wantIndex: 2,
},
{
name: "service with double digit index",
input: "node-10",
wantTag: "node",
wantIndex: 10,
},
{
name: "service with index in the middle",
input: "node-1-suffix",
wantTag: "node",
wantIndex: 1,
},
{
name: "service with multiple hyphens",
input: "multi-part-name-1",
wantTag: "multi-part-name",
wantIndex: 1,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotTag, gotIndex := finder.serviceTag(tt.input)
assert.Equal(t, tt.wantTag, gotTag)
assert.Equal(t, tt.wantIndex, gotIndex)
})
}
}
6 changes: 5 additions & 1 deletion kurtosis-devnet/pkg/kurtosis/kurtosis.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,11 @@ func (d *KurtosisDeployer) GetEnvironmentInfo(ctx context.Context, spec *spec.En
}

// Find L1 endpoint
finder := NewServiceFinder(inspectResult.UserServices)
networks := make([]string, len(spec.Chains))
for idx, chainSpec := range spec.Chains {
networks[idx] = chainSpec.Name
}
finder := NewServiceFinder(inspectResult.UserServices, WithL2Networks(networks))
if nodes, services := finder.FindL1Services(); len(nodes) > 0 {
chain := &descriptors.Chain{
ID: deployerState.L1ChainID,
Expand Down