mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 19:25:52 +00:00
91 lines
3.7 KiB
Go
91 lines
3.7 KiB
Go
//go:build integration
|
|
|
|
package integration
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
|
types "github.com/mulgadc/spinifex/contracts/cluster/v1"
|
|
"github.com/nats-io/nats.go"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestRunInstances_MultiCountExpansion asserts that a RunInstances call with
|
|
// MinCount=MaxCount=2 returns 2 instances with non-empty InstanceIds. That
|
|
// expansion is gateway-side logic — distributeInstances in
|
|
// spinifex/gateway/ec2/instance/placement.go queries node capacity over NATS,
|
|
// computes how many instances to launch, and dispatches a single targeted
|
|
// launch per node — resolved entirely before the daemon-facing NATS hop, so a
|
|
// static stub of the daemon side is sufficient; no real guest is needed.
|
|
//
|
|
// The live test's WaitForInstanceState(running)/TerminateInstances/
|
|
// WaitForInstanceState(terminated) sequence is left behind: it is teardown
|
|
// hygiene for a real throwaway VM, not part of what this test asserts.
|
|
//
|
|
// To prove the expansion is genuinely exercised rather than short-circuited by
|
|
// the zero-daemon degenerate path (placement.go's queryNodeCapacity returning
|
|
// no eligible nodes, which also yields InsufficientInstanceCapacity — see
|
|
// placement.go:44), this test subscribes to the per-node launch subject
|
|
// directly instead of using StubSubject's static responder, and asserts the
|
|
// daemon actually received MinCount=MaxCount=2 on that targeted request.
|
|
func TestRunInstances_MultiCountExpansion(t *testing.T) {
|
|
gw := StartGateway(t)
|
|
|
|
const (
|
|
instanceType = "t3.micro"
|
|
nodeID = "node-1"
|
|
)
|
|
|
|
// A single node reporting capacity for 2 of instanceType — enough for
|
|
// distributeInstances to resolve MinCount=MaxCount=2 onto one node.
|
|
statusResp := mustMarshal(t, &types.NodeStatusResponse{
|
|
Node: nodeID,
|
|
InstanceTypes: []types.InstanceTypeCap{
|
|
{Name: instanceType, Available: 2},
|
|
},
|
|
})
|
|
gw.StubSubject(t, "spinifex.node.status", statusResp)
|
|
|
|
var gotMinCount, gotMaxCount int64
|
|
launchSubject := fmt.Sprintf("ec2.RunInstances.%s.%s", instanceType, nodeID)
|
|
sub, err := gw.NATSConn.Subscribe(launchSubject, func(msg *nats.Msg) {
|
|
var nodeInput ec2.RunInstancesInput
|
|
if jsonErr := json.Unmarshal(msg.Data, &nodeInput); jsonErr != nil {
|
|
t.Errorf("unmarshal per-node RunInstances request: %v", jsonErr)
|
|
return
|
|
}
|
|
gotMinCount = aws.Int64Value(nodeInput.MinCount)
|
|
gotMaxCount = aws.Int64Value(nodeInput.MaxCount)
|
|
_ = msg.Respond(mustMarshal(t, &ec2.Reservation{
|
|
ReservationId: aws.String("r-multi-count"),
|
|
Instances: []*ec2.Instance{
|
|
{InstanceId: aws.String("i-multi-count-1")},
|
|
{InstanceId: aws.String("i-multi-count-2")},
|
|
},
|
|
}))
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = sub.Unsubscribe() })
|
|
|
|
out, err := gw.EC2Client(t).RunInstances(&ec2.RunInstancesInput{
|
|
ImageId: aws.String("ami-0123456789abcdef0"),
|
|
InstanceType: aws.String(instanceType),
|
|
MinCount: aws.Int64(2),
|
|
MaxCount: aws.Int64(2),
|
|
})
|
|
require.NoError(t, err, "run-instances --count 2")
|
|
require.Lenf(t, out.Instances, 2, "expected 2 instances from run-instances, got %d", len(out.Instances))
|
|
require.NotEmpty(t, aws.StringValue(out.Instances[0].InstanceId), "first sibling InstanceId empty")
|
|
require.NotEmpty(t, aws.StringValue(out.Instances[1].InstanceId), "second sibling InstanceId empty")
|
|
|
|
// Proves the gateway genuinely expanded the count onto the per-node
|
|
// launch, rather than the zero-daemon path (which never reaches this
|
|
// subject at all) or a daemon stub that ignores its input.
|
|
require.Equal(t, int64(2), gotMinCount, "gateway must dispatch MinCount=2 on the per-node launch")
|
|
require.Equal(t, int64(2), gotMaxCount, "gateway must dispatch MaxCount=2 on the per-node launch")
|
|
}
|