Exemple #1
0
func TestClients(t *testing.T) {
	var (
		builder = testutil.NewBuilder(nil)

		idA = machine.ID("servA")
		idB = machine.ID("servB")

		servA = &testutil.Server{}
		servB = &testutil.Server{}
	)

	cs, err := clients.New(testOptions(builder))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer cs.Close()

	var g errgroup.Group
	create := map[machine.ID]client.DynamicAddrFunc{
		idA: servA.AddrFunc(),
		idB: servB.AddrFunc(),
		idA: servA.AddrFunc(), // duplicate.
		idA: servA.AddrFunc(), // duplicate.
	}

	for id, dynAddr := range create {
		id, dynAddr := id, dynAddr // Local copy for concurrency.
		g.Go(func() error {
			return cs.Create(id, dynAddr)
		})
	}
	if err := g.Wait(); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if regs := cs.Registered(); len(regs) != 2 {
		t.Fatalf("want clients count = 2; got %d", len(regs))
	}

	if _, err := cs.Client(idA); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if err := cs.Drop(idA); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if _, err := cs.Client(idA); err != machine.ErrMachineNotFound {
		t.Fatalf("want machine not found; got %v", err)
	}

	if regs := cs.Registered(); len(regs) != 1 {
		t.Fatalf("want clients count = 1; got %d", len(regs))
	}
}
Exemple #2
0
func TestAliasesMachineID(t *testing.T) {
	m := map[machine.ID]string{
		"ID_1": "blue_banana",
		"ID_2": "red_orange1",
		"ID_3": "white_mango",
		"ID_4": "black_tomato2",
		"ID_5": "silver_kiwi",
	}

	as := aliases.New()
	for id, alias := range m {
		if err := as.Add(id, alias); err != nil {
			t.Fatalf("want err = nil; got %v", err)
		}
	}

	tests := map[string]struct {
		Alias    string
		Expected machine.ID
		NotFound bool
	}{
		"full alias": {
			Alias:    "white_mango",
			Expected: machine.ID("ID_3"),
			NotFound: false,
		},
		"machine id": {
			Alias:    "ID_5",
			Expected: machine.ID("ID_5"),
			NotFound: false,
		},
		"unknown": {
			Alias:    "green_kiwi",
			Expected: machine.ID(""),
			NotFound: true,
		},
	}

	for name, test := range tests {
		t.Run(name, func(t *testing.T) {
			id, err := as.MachineID(test.Alias)
			if (err == machine.ErrMachineNotFound) != test.NotFound {
				t.Fatalf("want err machine not found = %t; got %v", test.NotFound, err)
			}

			if id != test.Expected {
				t.Fatalf("want id = %v; got %v", test.Expected, id)
			}
		})
	}
}
Exemple #3
0
// MachineID checks if there is a machine ID that is binded to provided alias.
// If yes, the machine ID is returned. machine.ErrMachineNotFound is returned
// if there is no machine ID with provided alias.
//
// TODO: Add support for shortcuts like rb1 == red_banana1 etc.
func (a *Aliases) MachineID(alias string) (machine.ID, error) {
	a.mu.RLock()
	defer a.mu.RUnlock()
	for id, a := range a.m {
		// provided alias can be the machine ID itself.
		if machine.ID(alias) == id || alias == a {
			return id, nil
		}
	}

	return "", machine.ErrMachineNotFound
}
Exemple #4
0
func TestAddressesMachineIDDuplicated(t *testing.T) {
	makeAddr := func(updatedAt time.Time) machine.Addr {
		return machine.Addr{
			Network:   "ip",
			Value:     "52.254.159.36",
			UpdatedAt: updatedAt,
		}
	}

	machines := []struct {
		ID   machine.ID
		Addr machine.Addr
	}{
		{
			ID:   "ID_1",
			Addr: makeAddr(time.Date(2010, time.May, 1, 0, 0, 0, 0, time.UTC)),
		},
		{
			ID:   "ID_2",
			Addr: makeAddr(time.Date(2012, time.May, 1, 0, 0, 0, 0, time.UTC)),
		},
		{
			ID:   "ID_3",
			Addr: makeAddr(time.Date(2011, time.May, 1, 0, 0, 0, 0, time.UTC)),
		},
	}

	addrs := addresses.New()
	machineIDs := make(map[machine.ID]struct{})

	for i, machine := range machines {
		machineIDs[machine.ID] = struct{}{}
		if err := addrs.Add(machine.ID, machine.Addr); err != nil {
			t.Fatalf("want err = nil; got %v (i:%v)", err, i)
		}
	}

	if len(machineIDs) != len(addrs.Registered()) {
		t.Fatal("want %d machines; got %d", len(machineIDs), len(addrs.Registered()))
	}

	id, err := addrs.MachineID(makeAddr(time.Time{}))
	if err != nil {
		t.Errorf("want err = nil; got %v", err)
	}

	if wantID := machine.ID("ID_2"); wantID != id {
		t.Errorf("want machine ID = %v; got %v", wantID, id)
	}
}
Exemple #5
0
func TestAliasesCreate(t *testing.T) {
	const wantAliases = 500
	m := make(map[string]struct{})

	as := aliases.New()
	for i := 0; i < wantAliases; i++ {
		alias, err := as.Create(machine.ID(i))
		if err != nil {
			t.Fatalf("want err = nil; got %v", err)
		}
		m[alias] = struct{}{}

		// Second creation for the same ID should be no-op.
		alias, err = as.Create(machine.ID(i))
		if err != nil {
			t.Fatalf("want err = nil; got %v", err)
		}
		m[alias] = struct{}{}
	}

	if len(m) != wantAliases {
		t.Fatalf("want %d aliases; got %d", wantAliases, len(m))
	}
}
Exemple #6
0
func TestMachineGroupNoAliases(t *testing.T) {
	st, stop, err := testBoltStorage()
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer stop()

	// Add initial address.
	id := machine.ID("servA")
	address, err := addresses.NewCached(st)
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if err := address.Add(id, testutil.TurnOnAddr()); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if len(address.Registered()) != 1 {
		t.Errorf("want one registered machine; got %v", address.Registered())
	}

	builder := testutil.NewBuilder(nil)
	g, err := New(testOptionsStorage(builder, st))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer g.Close()

	// Machine group should add alias for missing ID.
	alias, err := aliases.NewCached(st)
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if len(alias.Registered()) != 1 {
		t.Errorf("want one registered machine; got %v", address.Registered())
	}

	// Dynamic client should be started.
	if err := builder.WaitForBuild(time.Second); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	if builder.BuildsCount() != 1 {
		t.Errorf("want dynamic builds number = 1; got %d", builder.BuildsCount())
	}
}
Exemple #7
0
func TestCreateBalance(t *testing.T) {
	var (
		client  = testutil.NewClient()
		builder = testutil.NewBuilder(client)
		id      = machine.ID("serv")
	)

	g, err := New(testOptions(builder))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer g.Close()

	req := &CreateRequest{
		Addresses: map[machine.ID][]machine.Addr{
			id: {testutil.TurnOffAddr()},
		},
	}

	if _, err := g.Create(req); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if err := builder.WaitForBuild(time.Second); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// Create with empty addresses should remove previously added machine.
	if _, err := g.Create(&CreateRequest{}); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	// Client context should be closed.
	if err := testutil.WaitForContextClose(client.Context(), time.Second); err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
}
Exemple #8
0
// List retrieves user's machines from kloud.
func List(options *ListOptions) ([]*Info, error) {
	var (
		listReq = stack.MachineListRequest{}
		listRes = stack.MachineListResponse{}
	)

	// Get info from kloud.
	if err := kloud.Call("machine.list", &listReq, &listRes); err != nil {
		return nil, err
	}

	// Register machines to klient and get aliases.
	//
	// TODO(ppknap): this is copied from klientctl old list and will be reworked.
	k, err := klient.CreateKlientWithDefaultOpts()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Error creating klient:", err)
		return nil, err
	}

	if err := k.Dial(); err != nil {
		fmt.Fprintln(os.Stderr, "Error dialing klient:", err)
		return nil, err
	}

	createReq := machinegroup.CreateRequest{
		Addresses: make(map[kmachine.ID][]kmachine.Addr),
	}
	for _, m := range listRes.Machines {
		createReq.Addresses[kmachine.ID(m.ID)] = []kmachine.Addr{
			{
				Network:   "ip",
				Value:     m.IP,
				UpdatedAt: time.Now(),
			},
			{
				Network:   "kite",
				Value:     m.QueryString,
				UpdatedAt: time.Now(),
			},
			{
				Network:   "http",
				Value:     m.RegisterURL,
				UpdatedAt: time.Now(),
			},
		}
	}
	createRaw, err := k.Tell("machine.create", createReq)
	if err != nil {
		return nil, err
	}

	createRes := machinegroup.CreateResponse{}
	if err := createRaw.Unmarshal(&createRes); err != nil {
		return nil, err
	}

	infos := make([]*Info, len(listRes.Machines))
	for i, m := range listRes.Machines {
		infos[i] = &Info{
			ID:          m.ID,
			Alias:       createRes.Aliases[kmachine.ID(m.ID)],
			Team:        m.Team,
			Stack:       m.Stack,
			Provider:    m.Provider,
			Label:       m.Label,
			IP:          m.IP,
			QueryString: m.QueryString,
			RegisterURL: m.RegisterURL,
			CreatedAt:   m.CreatedAt,
			Status: kmachine.MergeStatus(kmachine.Status{
				State:  fromMachineStateString(m.Status.State),
				Reason: m.Status.Reason,
				Since:  m.Status.ModifiedAt,
			}, createRes.Statuses[kmachine.ID(m.ID)]),
			Username: machineUserFromUsers(m.Users),
			Owner:    ownerFromUsers(m.Users),
		}
	}

	// Sort items before we return.
	sort.Sort(InfoSlice(infos))

	return infos, nil
}
Exemple #9
0
func TestCreate(t *testing.T) {
	var (
		builder = testutil.NewBuilder(nil)

		idA = machine.ID("servA")
		idB = machine.ID("servB")
	)

	g, err := New(testOptions(builder))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer g.Close()

	const AddedServersCount = 2
	req := &CreateRequest{
		Addresses: map[machine.ID][]machine.Addr{
			idA: {testutil.TurnOffAddr()},
			idB: {testutil.TurnOnAddr()},
		},
	}

	res, err := g.Create(req)
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if la := len(res.Aliases); la != AddedServersCount {
		t.Fatalf("want aliases count = %d; got: %d", AddedServersCount, la)
	}

	// Check generated aliases which must be unique and not empty.
	aliasA := res.Aliases[idA]
	if aliasA == "" {
		t.Errorf("want aliasA != ``; got ``")
	}
	aliasB := res.Aliases[idB]
	if aliasB == "" {
		t.Errorf("want aliasB != ``; got ``")
	}
	if aliasA == aliasB {
		t.Errorf("want aliasA != aliasB; got %s == %s", aliasA, aliasB)
	}

	for i := 0; i < AddedServersCount; i++ {
		if err := builder.WaitForBuild(time.Second); err != nil {
			t.Fatalf("want err = nil; got %v", err)
		}
	}

	// Already added, update statuses; don't change aliases.
	res, err = g.Create(req)
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	if aliasA != res.Aliases[idA] {
		t.Errorf("want aliasA = %s; got %s", aliasA, res.Aliases[idA])
	}
	if aliasB != res.Aliases[idB] {
		t.Errorf("want aliasB = %s; got %s", aliasB, res.Aliases[idB])
	}

	// Machines were pinged and they clients were build.
	statuses := map[machine.ID]machine.Status{
		idA: machine.Status{State: machine.StateOffline},
		idB: machine.Status{State: machine.StateOnline},
	}
	if !reflect.DeepEqual(statuses, res.Statuses) {
		t.Fatalf("want statuses = %#v; got %#v", statuses, res.Statuses)
	}
}
Exemple #10
0
func TestID(t *testing.T) {
	var (
		idA = machine.ID("servA")
		idB = machine.ID("servB")

		ipA = machine.Addr{Network: "ip", Value: "52.24.123.32", UpdatedAt: time.Now()}
		ipB = machine.Addr{Network: "ip", Value: "10.0.1.16", UpdatedAt: time.Now()}
	)

	g, err := New(testOptions(testutil.NewBuilder(nil)))
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}
	defer g.Close()

	req := &CreateRequest{
		Addresses: map[machine.ID][]machine.Addr{
			idA: {ipA},
			idB: {ipB},
		},
	}

	res, err := g.Create(req)
	if err != nil {
		t.Fatalf("want err = nil; got %v", err)
	}

	tests := map[string]struct {
		Identifier string
		ID         machine.ID
		Found      bool
	}{
		"by ID": {
			Identifier: string(idA),
			ID:         idA,
			Found:      true,
		},
		"by alias": {
			Identifier: res.Aliases[idB],
			ID:         idB,
			Found:      true,
		},
		"by IP": {
			Identifier: ipA.Value,
			ID:         idA,
			Found:      true,
		},
		"not found alias": {
			Identifier: "unknown_alias",
			ID:         "",
			Found:      false,
		},
		"not found IP": {
			Identifier: "127.0.0.12",
			ID:         "",
			Found:      false,
		},
		"not found TCP": {
			Identifier: ipB.Value + ":8080",
			ID:         "",
			Found:      false,
		},
	}

	for name, test := range tests {
		test := test // capture range variable.
		t.Run(name, func(t *testing.T) {
			t.Parallel()
			req := &IDRequest{
				Identifier: test.Identifier,
			}

			res, err := g.ID(req)
			if (err == nil) != test.Found {
				t.Fatalf("want (err == nil) = %t; got err: %v", test.Found, err)
			}

			if !test.Found {
				return
			}

			if res.ID != test.ID {
				t.Fatalf("want ID = %v; got %v", test.ID, res.ID)
			}
		})
	}
}