github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/cluster/clusterproviders/k8s/k8s_provider_test.go (about)

     1  package k8s
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"strconv"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/asynkron/protoactor-go/cluster/identitylookup/disthash"
    13  
    14  	"github.com/asynkron/protoactor-go/actor"
    15  	"github.com/asynkron/protoactor-go/cluster"
    16  	"github.com/asynkron/protoactor-go/remote"
    17  	"github.com/stretchr/testify/assert"
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  )
    20  
    21  func newClusterForTest(name string, addr string, cp cluster.ClusterProvider, id cluster.IdentityLookup) *cluster.Cluster {
    22  	host, _port, err := net.SplitHostPort(addr)
    23  	if err != nil {
    24  		panic(err)
    25  	}
    26  	port, _ := strconv.Atoi(_port)
    27  	remoteConfig := remote.Configure(host, port)
    28  	config := cluster.Configure(name, cp, id, remoteConfig)
    29  
    30  	system := actor.NewActorSystem()
    31  	c := cluster.New(system, config)
    32  
    33  	// use for test without start remote
    34  	c.ActorSystem.ProcessRegistry.Address = addr
    35  	c.MemberList = cluster.NewMemberList(c)
    36  	c.Remote = remote.NewRemote(system, config.RemoteConfig)
    37  	return c
    38  }
    39  
    40  func TestStartMember(t *testing.T) {
    41  	if testing.Short() {
    42  		return
    43  	}
    44  	if os.Getenv("KUBERNETES_SERVICE_HOST") == "" {
    45  		t.Skipf("Skipped k8s testcases")
    46  	}
    47  	assert := assert.New(t)
    48  
    49  	p, _ := New()
    50  	p, newErr := New()
    51  	if newErr != nil {
    52  		panic(fmt.Errorf("could not create new cluster provider: %w", newErr))
    53  	}
    54  	id := disthash.New()
    55  	defer p.Shutdown(true)
    56  
    57  	c := newClusterForTest("k8scluster", "127.0.0.1:8000", p, id)
    58  	eventstream := c.ActorSystem.EventStream
    59  	ch := make(chan interface{}, 16)
    60  	eventstream.Subscribe(func(m interface{}) {
    61  		if _, ok := m.(*cluster.ClusterTopology); ok {
    62  			ch <- m
    63  		}
    64  	})
    65  
    66  	err := p.StartMember(c)
    67  	assert.NoError(err)
    68  
    69  	select {
    70  	case <-time.After(10 * time.Second):
    71  		assert.FailNow("no member joined yet")
    72  
    73  	case m := <-ch:
    74  		msg := m.(*cluster.ClusterTopology)
    75  		// member joined
    76  		members := []*cluster.Member{
    77  			{
    78  				Id:    "k8scluster@127.0.0.1:8000",
    79  				Host:  "127.0.0.1",
    80  				Port:  8000,
    81  				Kinds: []string{},
    82  			},
    83  		}
    84  
    85  		expected := &cluster.ClusterTopology{
    86  			Members: members,
    87  			Joined:  members,
    88  		}
    89  		assert.Equal(expected, msg)
    90  	}
    91  }
    92  
    93  func TestRegisterMultipleMembers(t *testing.T) {
    94  	if testing.Short() {
    95  		return
    96  	}
    97  	if os.Getenv("KUBERNETES_SERVICE_HOST") == "" {
    98  		t.Skipf("Skipped k8s testcases")
    99  	}
   100  	assert := assert.New(t)
   101  
   102  	members := []struct {
   103  		cluster string
   104  		host    string
   105  		port    int
   106  	}{
   107  		{"k8scluster2", "127.0.0.1", 8001},
   108  		{"k8scluster2", "127.0.0.1", 8002},
   109  		{"k8scluster2", "127.0.0.1", 8003},
   110  	}
   111  
   112  	p, _ := New()
   113  	defer p.Shutdown(true)
   114  	for _, member := range members {
   115  		addr := fmt.Sprintf("%s:%d", member.host, member.port)
   116  		_p, _ := New()
   117  		_id := disthash.New()
   118  		c := newClusterForTest(member.cluster, addr, _p, _id)
   119  		err := p.StartMember(c)
   120  		assert.NoError(err)
   121  		t.Cleanup(func() {
   122  			_p.Shutdown(true)
   123  		})
   124  	}
   125  
   126  	ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
   127  	defer cancel()
   128  
   129  	pods, err := p.client.CoreV1().Pods(p.retrieveNamespace()).List(ctx, metav1.ListOptions{})
   130  	assert.NoError(err)
   131  	assert.Equal(pods.Size(), len(members))
   132  }
   133  
   134  func TestUpdateMemberState(t *testing.T) {
   135  	if testing.Short() {
   136  		return
   137  	}
   138  	if os.Getenv("KUBERNETES_SERVICE_HOST") == "" {
   139  		t.Skipf("Skipped k8s testcases")
   140  	}
   141  	assert := assert.New(t)
   142  
   143  	p, _ := New()
   144  	id := disthash.New()
   145  	defer p.Shutdown(true)
   146  
   147  	c := newClusterForTest("k8scluster3", "127.0.0.1:8000", p, id)
   148  	err := p.StartMember(c)
   149  	assert.NoError(err)
   150  }
   151  
   152  func TestUpdateMemberState_DoesNotReregisterAfterShutdown(t *testing.T) {
   153  	if testing.Short() {
   154  		return
   155  	}
   156  	if os.Getenv("KUBERNETES_SERVICE_HOST") == "" {
   157  		t.Skipf("Skipped k8s testcases")
   158  	}
   159  	assert := assert.New(t)
   160  
   161  	p, _ := New()
   162  	id := disthash.New()
   163  	c := newClusterForTest("k8scluster4", "127.0.0.1:8001", p, id)
   164  	err := p.StartMember(c)
   165  	assert.NoError(err)
   166  	t.Cleanup(func() {
   167  		p.Shutdown(true)
   168  	})
   169  
   170  	err = p.Shutdown(true)
   171  	assert.NoError(err)
   172  
   173  	assert.Equal(ProviderShuttingDownError, err)
   174  }