Esempio n. 1
0
func (s server) GetMinionConfig(cts context.Context,
	_ *pb.Request) (*pb.MinionConfig, error) {

	var cfg pb.MinionConfig

	if m, err := s.MinionSelf(); err == nil {
		cfg.Role = db.RoleToPB(m.Role)
		cfg.PrivateIP = m.PrivateIP
		cfg.Spec = m.Spec
		cfg.Provider = m.Provider
		cfg.Size = m.Size
		cfg.Region = m.Region
	} else {
		cfg.Role = db.RoleToPB(db.None)
	}

	return &cfg, nil
}
Esempio n. 2
0
func (fm *foreman) runOnce() {
	var machines []db.Machine
	fm.conn.Transact(func(view db.Database) error {
		machines = view.SelectFromMachine(func(m db.Machine) bool {
			return m.PublicIP != "" && m.PrivateIP != "" && m.CloudID != ""
		})

		fm.spec = ""
		clst, _ := view.GetCluster()
		fm.spec = clst.Spec
		return nil
	})

	fm.updateMinionMap(machines)

	/* Request the current configuration from each minion. */
	fm.forEachMinion(func(m *minion) {
		var err error
		m.config, err = m.client.getMinion()

		connected := err == nil
		if connected && !m.connected {
			log.WithField("machine", m.machine).Info("New connection.")
		}

		m.connected = connected
	})

	var etcdIPs []string
	for _, m := range fm.minions {
		if m.machine.Role == db.Master && m.machine.PrivateIP != "" {
			etcdIPs = append(etcdIPs, m.machine.PrivateIP)
		}
	}

	// Assign all of the minions their new configs
	fm.forEachMinion(func(m *minion) {
		if !m.connected {
			return
		}

		newConfig := pb.MinionConfig{
			Role:      db.RoleToPB(m.machine.Role),
			PrivateIP: m.machine.PrivateIP,
			Spec:      fm.spec,
			Provider:  string(m.machine.Provider),
			Size:      m.machine.Size,
			Region:    m.machine.Region,
		}

		if newConfig == m.config {
			return
		}

		if err := m.client.setMinion(newConfig); err != nil {
			return
		}

		if err := m.client.bootEtcd(pb.EtcdMembers{IPs: etcdIPs}); err != nil {
			log.WithError(err).Warn("Failed send etcd members.")
		}
	})
}
Esempio n. 3
0
// RunOnce should be called regularly to allow the foreman to update minion roles.
func RunOnce(conn db.Conn) {
	var spec string
	var machines []db.Machine
	conn.Transact(func(view db.Database) error {
		machines = view.SelectFromMachine(func(m db.Machine) bool {
			return m.PublicIP != "" && m.PrivateIP != "" && m.CloudID != ""
		})

		clst, _ := view.GetCluster()
		spec = clst.Spec

		return nil
	})

	updateMinionMap(machines)

	/* Request the current configuration from each minion. */
	forEachMinion(func(m *minion) {
		var err error
		m.config, err = m.client.getMinion()

		connected := err == nil
		if connected && !m.connected {
			log.WithField("machine", m.machine).Debug("New connection.")
		}

		if connected != m.machine.Connected {
			conn.Transact(func(view db.Database) error {
				m.machine.Connected = connected
				view.Commit(m.machine)
				return nil
			})
		}

		m.connected = connected
	})

	var etcdIPs []string
	for _, m := range minions {
		if m.machine.Role == db.Master && m.machine.PrivateIP != "" {
			etcdIPs = append(etcdIPs, m.machine.PrivateIP)
		}
	}

	// Assign all of the minions their new configs
	forEachMinion(func(m *minion) {
		if !m.connected {
			return
		}

		newConfig := pb.MinionConfig{
			Role:           db.RoleToPB(m.machine.Role),
			PrivateIP:      m.machine.PrivateIP,
			Spec:           spec,
			Provider:       string(m.machine.Provider),
			Size:           m.machine.Size,
			Region:         m.machine.Region,
			EtcdMembers:    etcdIPs,
			AuthorizedKeys: m.machine.SSHKeys,
		}

		if reflect.DeepEqual(newConfig, m.config) {
			return
		}

		if err := m.client.setMinion(newConfig); err != nil {
			log.WithError(err).Error("Failed to set minion config.")
			return
		}
	})
}
Esempio n. 4
0
func TestConfigConsistency(t *testing.T) {
	masterRole := db.RoleToPB(db.Master)
	workerRole := db.RoleToPB(db.Worker)

	fm, _ := startTest()
	var master, worker db.Machine
	fm.conn.Transact(func(view db.Database) error {
		master = view.InsertMachine()
		master.PublicIP = "1.1.1.1"
		master.PrivateIP = master.PublicIP
		master.CloudID = "ID1"
		view.Commit(master)
		worker = view.InsertMachine()
		worker.PublicIP = "2.2.2.2"
		worker.PrivateIP = worker.PublicIP
		worker.CloudID = "ID2"
		view.Commit(worker)
		return nil
	})

	fm.init()
	fm.conn.Transact(func(view db.Database) error {
		master.Role = db.Master
		worker.Role = db.Worker
		view.Commit(master)
		view.Commit(worker)
		return nil
	})

	fm.runOnce()
	checkRoles := func(fore foreman) {
		r := fore.minions["1.1.1.1"].client.(*fakeClient).mc.Role
		if r != masterRole {
			t.Errorf("Master has role %v, should be %v", r, masterRole)
		}
		r = fore.minions["2.2.2.2"].client.(*fakeClient).mc.Role
		if r != workerRole {
			t.Errorf("Worker has role %v, should be %v", r, workerRole)
		}
	}
	checkRoles(fm)
	fm.stop()

	newfm, clients := startTest()
	newfm.conn = fm.conn

	// Insert the clients into the client list to simulate fetching
	// from the remote cluster
	clients.clients["1.1.1.1"] = &fakeClient{clients, "1.1.1.1",
		pb.MinionConfig{Role: masterRole}, pb.EtcdMembers{}}
	clients.clients["2.2.2.2"] = &fakeClient{clients, "2.2.2.2",
		pb.MinionConfig{Role: workerRole}, pb.EtcdMembers{}}

	newfm.init()
	newfm.runOnce()
	checkRoles(newfm)

	// After many runs, the roles should never change
	for i := 0; i < 25; i++ {
		newfm.runOnce()
	}
	checkRoles(newfm)

	// Ensure that the DB machines have the correct roles as well.
	newfm.conn.Transact(func(view db.Database) error {
		machines := view.SelectFromMachine(nil)
		for _, m := range machines {
			if m.PublicIP == "1.1.1.1" && m.Role != db.Master {
				t.Errorf("db Master had role %v, expected %v", m.Role,
					db.Master)
			}
			if m.PublicIP == "2.2.2.2" && m.Role != db.Worker {
				t.Errorf("db Worker had role %v, expected %v", m.Role,
					db.Worker)
			}
		}
		return nil
	})
}
Esempio n. 5
0
func TestConfigConsistency(t *testing.T) {
	masterRole := db.RoleToPB(db.Master)
	workerRole := db.RoleToPB(db.Worker)

	conn, clients := startTest()
	var master, worker db.Machine
	conn.Transact(func(view db.Database) error {
		master = view.InsertMachine()
		master.PublicIP = "1.1.1.1"
		master.PrivateIP = master.PublicIP
		master.CloudID = "ID1"
		view.Commit(master)
		worker = view.InsertMachine()
		worker.PublicIP = "2.2.2.2"
		worker.PrivateIP = worker.PublicIP
		worker.CloudID = "ID2"
		view.Commit(worker)
		return nil
	})

	Init(conn)
	conn.Transact(func(view db.Database) error {
		master.Role = db.Master
		worker.Role = db.Worker
		view.Commit(master)
		view.Commit(worker)
		return nil
	})

	RunOnce(conn)
	checkRoles := func() {
		r := minions["1.1.1.1"].client.(*fakeClient).mc.Role
		assert.Equal(t, masterRole, r)

		r = minions["2.2.2.2"].client.(*fakeClient).mc.Role
		assert.Equal(t, workerRole, r)
	}
	checkRoles()

	minions = map[string]*minion{}

	// Insert the clients into the client list to simulate fetching
	// from the remote cluster
	clients.clients["1.1.1.1"] = &fakeClient{clients, "1.1.1.1",
		pb.MinionConfig{Role: masterRole}}
	clients.clients["2.2.2.2"] = &fakeClient{clients, "2.2.2.2",
		pb.MinionConfig{Role: workerRole}}

	Init(conn)
	RunOnce(conn)
	checkRoles()

	// After many runs, the roles should never change
	for i := 0; i < 25; i++ {
		RunOnce(conn)
	}
	checkRoles()

	// Ensure that the DB machines have the correct roles as well.
	conn.Transact(func(view db.Database) error {
		machines := view.SelectFromMachine(nil)
		for _, m := range machines {
			if m.PublicIP == "1.1.1.1" {
				assert.Equal(t, db.Role(db.Master), m.Role)
			}
			if m.PublicIP == "2.2.2.2" {
				assert.Equal(t, db.Role(db.Worker), m.Role)
			}
		}
		return nil
	})
}