Example #1
0
func (svc *service) startRejecting(s *model.Service) (serviceState, error) {
	log.Info("rejecting service: ", s.Summary())
	rule := []interface{}{
		"-p", "tcp",
		"-d", s.IP,
		"--dport", s.Port,
		"-j", "REJECT",
	}

	err := svc.ipTables.addRule("filter", rule)
	if err != nil {
		return nil, err
	}

	return rejecting(func() {
		svc.ipTables.deleteRule("filter", rule)
	}), nil
}
Example #2
0
func (fc forwardingConfig) start(svc *model.Service) (serviceState, error) {
	log.Info("forwarding service: ", svc.Summary())
	ip, err := bridgeIP(fc.bridge)
	if err != nil {
		return nil, err
	}

	listener, err := net.ListenTCP("tcp", &net.TCPAddr{IP: ip})
	if err != nil {
		return nil, err
	}

	success := false
	defer func() {
		if !success {
			listener.Close()
		}
	}()

	rule := []interface{}{
		"-p", "tcp",
		"-d", svc.IP,
		"--dport", svc.Port,
		"-j", "DNAT",
		"--to-destination", listener.Addr(),
	}
	err = fc.ipTables.addRule("nat", rule)
	if err != nil {
		return nil, err
	}

	fwd := &forwarding{
		forwardingConfig: fc,
		rule:             rule,
		listener:         listener,
		Service:          svc,
	}

	fwd.chooseShim()
	go fwd.run()
	success = true
	return fwd, nil
}
Example #3
0
func (fwd *forwarding) update(svc *model.Service) (bool, error) {
	if len(svc.Instances) == 0 {
		return false, nil
	}

	fwd.lock.Lock()
	defer fwd.lock.Unlock()

	if svc.Equal(fwd.Service) {
		return true, nil
	}

	if !svc.IP.Equal(fwd.Service.IP) || svc.Port != fwd.Service.Port {
		return false, nil
	}

	log.Info("forwarding service: ", svc.Summary())
	fwd.Service = svc
	fwd.chooseShim()
	return true, nil
}
Example #4
0
func TestServices(t *testing.T) {
	nc := netConfig{
		chain:  "FLUX",
		bridge: "lo",
	}

	mipt := newMockIPTables(t)
	ipTables := newIPTables(nc, mipt.cmd)
	ipTables.start()

	errorSink := daemon.NewErrorSink()
	updates := make(chan model.ServiceUpdate)
	done := make(chan struct{}, 1)
	svcs := servicesConfig{
		netConfig:    nc,
		updates:      updates,
		ipTables:     ipTables,
		eventHandler: events.NullHandler{},
		errorSink:    errorSink,
		done:         done,
	}.start()

	ip := net.ParseIP("127.42.0.1")
	port := 8888

	// Add a service
	svc := model.Service{
		Name:     "service",
		Protocol: "tcp",
		IP:       ip,
		Port:     port,
		Instances: []model.Instance{
			{
				Name:  "foo",
				Group: "bar",
				IP:    net.ParseIP("127.0.0.1"),
				Port:  10000,
			},
		},
	}
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireForwarding(t, &mipt)

	insts := []model.Instance{
		{
			Name:  "foo",
			Group: "bar",
			IP:    net.ParseIP("127.0.0.1"),
			Port:  10001,
		},
	}

	// Update it
	svc.Instances = insts
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireForwarding(t, &mipt)

	// forwarding -> rejecting
	svc.Instances = nil
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireRejecting(t, &mipt)

	// rejecting -> not forwarding
	svc.IP = nil
	svc.Port = 0
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireNotForwarding(t, &mipt)

	// not forwarding -> forwarding
	svc.IP = ip
	svc.Port = port
	svc.Instances = insts
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireForwarding(t, &mipt)

	// Now back the other way
	// forwarding -> not forwarding
	svc.IP = nil
	svc.Port = 0
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireNotForwarding(t, &mipt)

	// not forwarding -> rejecting
	svc.IP = ip
	svc.Port = port
	svc.Instances = nil
	updates <- model.ServiceUpdate{Service: svc}
	<-done
	requireRejecting(t, &mipt)

	// Delete it
	updates <- model.ServiceUpdate{Service: svc, Delete: true}
	<-done
	requireNotForwarding(t, &mipt)

	// Delete it, even though it doesn't exist
	updates <- model.ServiceUpdate{Service: svc, Delete: true}
	<-done

	svcs.close()
}