diff --git a/kurtosis-devnet/pkg/kurtosis/endpoints.go b/kurtosis-devnet/pkg/kurtosis/endpoints.go index 0072233c93a79..3207e5ccb1ee3 100644 --- a/kurtosis-devnet/pkg/kurtosis/endpoints.go +++ b/kurtosis-devnet/pkg/kurtosis/endpoints.go @@ -13,6 +13,7 @@ type ServiceFinder struct { services inspect.ServiceMap nodeServices []string l2ServicePrefix string + l2Networks []string } // ServiceFinderOption configures a ServiceFinder @@ -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{ @@ -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 }) } diff --git a/kurtosis-devnet/pkg/kurtosis/endpoints_test.go b/kurtosis-devnet/pkg/kurtosis/endpoints_test.go index 515814039699a..90ef905040034 100644 --- a/kurtosis-devnet/pkg/kurtosis/endpoints_test.go +++ b/kurtosis-devnet/pkg/kurtosis/endpoints_test.go @@ -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) + }) + } +} diff --git a/kurtosis-devnet/pkg/kurtosis/kurtosis.go b/kurtosis-devnet/pkg/kurtosis/kurtosis.go index ef394c230fd6f..a47a08e8f7779 100644 --- a/kurtosis-devnet/pkg/kurtosis/kurtosis.go +++ b/kurtosis-devnet/pkg/kurtosis/kurtosis.go @@ -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,