github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/state/deployment_events_test.go (about)

     1  package state
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/hashicorp/nomad/ci"
     9  	"github.com/hashicorp/nomad/nomad/mock"
    10  	"github.com/hashicorp/nomad/nomad/stream"
    11  	"github.com/hashicorp/nomad/nomad/structs"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestDeploymentEventFromChanges(t *testing.T) {
    16  	ci.Parallel(t)
    17  	s := TestStateStoreCfg(t, TestStateStorePublisher(t))
    18  	defer s.StopEventBroker()
    19  
    20  	// setup
    21  	setupTx := s.db.WriteTxn(10)
    22  
    23  	j := mock.Job()
    24  	e := mock.Eval()
    25  	e.JobID = j.ID
    26  
    27  	d := mock.Deployment()
    28  	d.JobID = j.ID
    29  
    30  	require.NoError(t, s.upsertJobImpl(10, j, false, setupTx))
    31  	require.NoError(t, s.upsertDeploymentImpl(10, d, setupTx))
    32  
    33  	setupTx.Txn.Commit()
    34  
    35  	msgType := structs.DeploymentStatusUpdateRequestType
    36  
    37  	req := &structs.DeploymentStatusUpdateRequest{
    38  		DeploymentUpdate: &structs.DeploymentStatusUpdate{
    39  			DeploymentID:      d.ID,
    40  			Status:            structs.DeploymentStatusPaused,
    41  			StatusDescription: structs.DeploymentStatusDescriptionPaused,
    42  		},
    43  		Eval: e,
    44  		// Exlude Job and assert its added
    45  	}
    46  
    47  	require.NoError(t, s.UpdateDeploymentStatus(msgType, 100, req))
    48  
    49  	events := WaitForEvents(t, s, 100, 1, 1*time.Second)
    50  	require.Len(t, events, 2)
    51  
    52  	got := events[0]
    53  	require.Equal(t, uint64(100), got.Index)
    54  	require.Equal(t, d.ID, got.Key)
    55  
    56  	de := got.Payload.(*structs.DeploymentEvent)
    57  	require.Equal(t, structs.DeploymentStatusPaused, de.Deployment.Status)
    58  	require.Contains(t, got.FilterKeys, j.ID)
    59  
    60  }
    61  
    62  func WaitForEvents(t *testing.T, s *StateStore, index uint64, minEvents int, timeout time.Duration) []structs.Event {
    63  	ctx, cancel := context.WithCancel(context.Background())
    64  	defer cancel()
    65  
    66  	go func() {
    67  		select {
    68  		case <-ctx.Done():
    69  			return
    70  		case <-time.After(timeout):
    71  			require.Fail(t, "timeout waiting for events")
    72  		}
    73  	}()
    74  
    75  	maxAttempts := 10
    76  	for {
    77  		got := EventsForIndex(t, s, index)
    78  		if len(got) >= minEvents {
    79  			return got
    80  		}
    81  		maxAttempts--
    82  		if maxAttempts == 0 {
    83  			require.Failf(t, "reached max attempts waiting for desired event count", "count %d", len(got))
    84  		}
    85  		time.Sleep(10 * time.Millisecond)
    86  	}
    87  }
    88  
    89  func EventsForIndex(t *testing.T, s *StateStore, index uint64) []structs.Event {
    90  	pub, err := s.EventBroker()
    91  	require.NoError(t, err)
    92  
    93  	sub, err := pub.Subscribe(&stream.SubscribeRequest{
    94  		Topics: map[structs.Topic][]string{
    95  			"*": {"*"},
    96  		},
    97  		Namespace:           "default",
    98  		Index:               index,
    99  		StartExactlyAtIndex: true,
   100  	})
   101  	if err != nil {
   102  		return []structs.Event{}
   103  	}
   104  	defer sub.Unsubscribe()
   105  
   106  	require.NoError(t, err)
   107  
   108  	var events []structs.Event
   109  	for {
   110  		e, err := sub.NextNoBlock()
   111  		require.NoError(t, err)
   112  		if e == nil {
   113  			break
   114  		}
   115  		events = append(events, e...)
   116  	}
   117  	return events
   118  }