Example #1
0
func TestWatchLeaseAdded(t *testing.T) {
	msr := newDummyRegistry()
	sm := NewMockManager(msr)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	l := acquireLease(ctx, t, sm)

	events := make(chan []Event)
	go WatchLeases(ctx, sm, "_", l, events)

	evtBatch := <-events
	for _, evt := range evtBatch {
		if evt.Lease.Key() == l.Key() {
			t.Errorf("WatchLeases returned our own lease")
		}
	}

	expected := ip.IP4Net{
		IP:        ip.MustParseIP4("10.3.30.0"),
		PrefixLen: 24,
	}
	// Sanity check to make sure acquired lease is not this.
	// It shouldn't be as SubnetMin/SubnetMax in config is [10.3.1.0/24 to 10.3.25.0/24]
	if l.Subnet.Equal(expected) {
		t.Fatalf("Acquired lease conflicts with one about to create")
	}

	attrs := &LeaseAttrs{
		PublicIP: ip.MustParseIP4("1.1.1.1"),
	}
	_, err := msr.createSubnet(ctx, "_", expected, attrs, 0)
	if err != nil {
		t.Fatalf("createSubnet filed: %v", err)
	}

	evtBatch = <-events

	if len(evtBatch) != 1 {
		t.Fatalf("WatchLeases produced wrong sized event batch: got %v, expected 1", len(evtBatch))
	}

	evt := evtBatch[0]

	if evt.Type != EventAdded {
		t.Fatalf("WatchLeases produced wrong event type")
	}

	actual := evt.Lease.Subnet
	if !actual.Equal(expected) {
		t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
	}
}
Example #2
0
func TestRemoveReservation(t *testing.T) {
	msr := newDummyRegistry()
	sm := NewMockManager(msr)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	r := Reservation{
		Subnet:   newIP4Net("10.3.10.0", 24),
		PublicIP: ip.MustParseIP4("52.195.12.13"),
	}
	if err := sm.AddReservation(ctx, "_", &r); err != nil {
		t.Fatalf("failed to add reservation: %v", err)
	}

	if err := sm.RemoveReservation(ctx, "_", r.Subnet); err != nil {
		t.Fatalf("failed to remove reservation: %v", err)
	}

	// The node should have a TTL
	sub, _, err := msr.getSubnet(ctx, "_", r.Subnet)
	if err != nil {
		t.Fatalf("getSubnet failed: %v", err)
	}

	if sub.Expiration.IsZero() {
		t.Fatalf("removed reservation resulted in no TTL")
	}
}
Example #3
0
func TestAddReservation(t *testing.T) {
	msr := newDummyRegistry()
	sm := NewMockManager(msr)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	r := Reservation{
		Subnet:   newIP4Net("10.4.3.0", 24),
		PublicIP: ip.MustParseIP4("52.195.12.13"),
	}
	if err := sm.AddReservation(ctx, "_", &r); err == nil {
		t.Fatalf("unexpectedly added a reservation outside of configured network")
	}

	r.Subnet = newIP4Net("10.3.10.0", 24)
	if err := sm.AddReservation(ctx, "_", &r); err != nil {
		t.Fatalf("failed to add reservation: %v", err)
	}

	// Add the same reservation -- should succeed
	if err := sm.AddReservation(ctx, "_", &r); err != nil {
		t.Fatalf("failed to add reservation: %v", err)
	}

	// Add a reservation with a different public IP -- should fail
	r2 := r
	r2.PublicIP = ip.MustParseIP4("52.195.12.17")
	if err := sm.AddReservation(ctx, "_", &r2); err != ErrLeaseTaken {
		t.Fatalf("taken add reservation returned: %v", err)
	}

	attrs := &LeaseAttrs{
		PublicIP: r.PublicIP,
	}
	l, err := sm.AcquireLease(ctx, "_", attrs)
	if err != nil {
		t.Fatalf("failed to acquire subnet: %v", err)
	}
	if !l.Subnet.Equal(r.Subnet) {
		t.Fatalf("acquired subnet is not the reserved one: expected %v, got %v", r.Subnet, l.Subnet)
	}
	if !l.Expiration.IsZero() {
		t.Fatalf("acquired lease (prev reserved) has expiration set")
	}
}
Example #4
0
func newDummyRegistry() *MockSubnetRegistry {
	attrs := LeaseAttrs{
		PublicIP: ip.MustParseIP4("1.1.1.1"),
	}

	exp := time.Time{}

	subnets := []Lease{
		{ip.IP4Net{ip.MustParseIP4("10.3.1.0"), 24}, attrs, exp, 10},
		{ip.IP4Net{ip.MustParseIP4("10.3.2.0"), 24}, attrs, exp, 11},
		{ip.IP4Net{ip.MustParseIP4("10.3.4.0"), 24}, attrs, exp, 12},
		{ip.IP4Net{ip.MustParseIP4("10.3.5.0"), 24}, attrs, exp, 13},
	}

	config := `{ "Network": "10.3.0.0/16", "SubnetMin": "10.3.1.0", "SubnetMax": "10.3.25.0" }`
	return NewMockRegistry("_", config, subnets)
}
Example #5
0
func TestWatchLeaseAdded(t *testing.T) {
	msr := newDummyRegistry()
	sm := NewMockManager(msr)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	l := acquireLease(ctx, t, sm)

	events := make(chan []Event)
	go WatchLeases(ctx, sm, "_", l, events)

	evtBatch := <-events
	for _, evt := range evtBatch {
		if evt.Lease.Key() == l.Key() {
			t.Errorf("WatchLeases returned our own lease")
		}
	}

	expected := ip.IP4Net{
		IP:        ip.MustParseIP4("10.3.6.0"),
		PrefixLen: 24,
	}
	attrs := &LeaseAttrs{
		PublicIP: ip.MustParseIP4("1.1.1.1"),
	}
	msr.createSubnet(ctx, "_", expected, attrs, 0)

	evtBatch = <-events

	if len(evtBatch) != 1 {
		t.Fatalf("WatchLeases produced wrong sized event batch")
	}

	evt := evtBatch[0]

	if evt.Type != EventAdded {
		t.Fatalf("WatchLeases produced wrong event type")
	}

	actual := evt.Lease.Subnet
	if !actual.Equal(expected) {
		t.Errorf("WatchSubnet produced wrong subnet: expected %s, got %s", expected, actual)
	}
}
Example #6
0
func TestListReservations(t *testing.T) {
	msr := newDummyRegistry()
	sm := NewMockManager(msr)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	r1 := Reservation{
		Subnet:   newIP4Net("10.3.10.0", 24),
		PublicIP: ip.MustParseIP4("52.195.12.13"),
	}
	if err := sm.AddReservation(ctx, "_", &r1); err != nil {
		t.Fatalf("failed to add reservation: %v", err)
	}

	r2 := Reservation{
		Subnet:   newIP4Net("10.3.20.0", 24),
		PublicIP: ip.MustParseIP4("52.195.12.14"),
	}
	if err := sm.AddReservation(ctx, "_", &r2); err != nil {
		t.Fatalf("failed to add reservation: %v", err)
	}

	rs, err := sm.ListReservations(ctx, "_")
	if err != nil {
		if len(rs) != 2 {
			t.Fatalf("unexpected number of reservations, expected 2, got %v", len(rs))
		}
		if !resvEqual(rs[0], r1) && !resvEqual(rs[1], r1) {
			t.Fatalf("reservation not found")
		}
		if !resvEqual(rs[0], r2) && !resvEqual(rs[1], r2) {
			t.Fatalf("reservation not found")
		}
	}
}
Example #7
0
func newDummyRegistry() *MockSubnetRegistry {
	attrs := LeaseAttrs{
		PublicIP: ip.MustParseIP4("1.1.1.1"),
	}

	exp := time.Time{}

	subnets := []Lease{
		// leases within SubnetMin-SubnetMax range
		{ip.IP4Net{ip.MustParseIP4("10.3.1.0"), 24}, attrs, exp, 10},
		{ip.IP4Net{ip.MustParseIP4("10.3.2.0"), 24}, attrs, exp, 11},
		{ip.IP4Net{ip.MustParseIP4("10.3.4.0"), 24}, attrs, exp, 12},
		{ip.IP4Net{ip.MustParseIP4("10.3.5.0"), 24}, attrs, exp, 13},

		// hand created lease outside the range of subnetMin-SubnetMax for testing removal
		{ip.IP4Net{ip.MustParseIP4("10.3.31.0"), 24}, attrs, exp, 13},
	}

	config := `{ "Network": "10.3.0.0/16", "SubnetMin": "10.3.1.0", "SubnetMax": "10.3.25.0" }`
	return NewMockRegistry("_", config, subnets)
}
Example #8
0
func TestEtcdRegistry(t *testing.T) {
	r, m := newTestEtcdRegistry(t)

	ctx, _ := context.WithCancel(context.Background())

	networks, _, err := r.getNetworks(ctx)
	if err != nil {
		t.Fatal("Failed to get networks")
	}
	if len(networks) != 0 {
		t.Fatal("Networks should be empty")
	}

	// Populate etcd with a network
	netKey := "/coreos.com/network/foobar/config"
	netValue := "{ \"Network\": \"10.1.0.0/16\", \"Backend\": { \"Type\": \"host-gw\" } }"
	m.Create(ctx, netKey, netValue)

	networks, _, err = r.getNetworks(ctx)
	if err != nil {
		t.Fatal("Failed to get networks the second time")
	}
	if len(networks) != 1 {
		t.Fatal("Failed to find expected network foobar")
	}

	config, err := r.getNetworkConfig(ctx, "foobar")
	if err != nil {
		t.Fatal("Failed to get network config")
	}
	if config != netValue {
		t.Fatal("Failed to match network config")
	}

	sn := ip.IP4Net{
		IP:        ip.MustParseIP4("10.1.5.0"),
		PrefixLen: 24,
	}

	wg := sync.WaitGroup{}
	wg.Add(1)
	startWg := sync.WaitGroup{}
	startWg.Add(1)
	result := make(chan error, 1)
	go func() {
		startWg.Done()
		watchSubnets(t, r, ctx, sn, m.index, result)
		wg.Done()
	}()

	startWg.Wait()
	// Lease a subnet for the network
	attrs := &LeaseAttrs{
		PublicIP: ip.MustParseIP4("1.2.3.4"),
	}
	exp, err := r.createSubnet(ctx, "foobar", sn, attrs, 24*time.Hour)
	if err != nil {
		t.Fatal("Failed to create subnet lease")
	}
	if !exp.After(time.Now()) {
		t.Fatal("Subnet lease duration %v not in the future", exp)
	}

	// Make sure the lease got created
	resp, err := m.Get(ctx, "/coreos.com/network/foobar/subnets/10.1.5.0-24", nil)
	if err != nil {
		t.Fatal("Failed to verify subnet lease directly in etcd: %v", err)
	}
	if resp == nil || resp.Node == nil {
		t.Fatal("Failed to retrive node in subnet lease")
	}
	if resp.Node.Value != "{\"PublicIP\":\"1.2.3.4\"}" {
		t.Fatal("Unexpected subnet lease node %s value %s", resp.Node.Key, resp.Node.Value)
	}

	leases, _, err := r.getSubnets(ctx, "foobar")
	if len(leases) != 1 {
		t.Fatalf("Unexpected number of leases %d (expected 1)", len(leases))
	}
	if !leases[0].Subnet.Equal(sn) {
		t.Fatalf("Mismatched subnet %v (expected %v)", leases[0].Subnet, sn)
	}

	lease, _, err := r.getSubnet(ctx, "foobar", sn)
	if lease == nil {
		t.Fatal("Missing subnet lease")
	}

	err = r.deleteSubnet(ctx, "foobar", sn)
	if err != nil {
		t.Fatalf("Failed to delete subnet %v: %v", sn, err)
	}

	// Make sure the lease got deleted
	resp, err = m.Get(ctx, "/coreos.com/network/foobar/subnets/10.1.5.0-24", nil)
	if err == nil {
		t.Fatal("Unexpected success getting deleted subnet")
	}

	wg.Wait()

	// Check errors from watch goroutine
	watchResult := <-result
	if watchResult != nil {
		t.Fatalf("Error watching keys: %v", watchResult)
	}

	// TODO: watchSubnet and watchNetworks
}