This introduces a health/ready api for networkd. This will allow us to better determine the state of networkd and allow for some level of monitoring. Signed-off-by: Brad Beam <brad.beam@talos-systems.com>
150 lines
4.2 KiB
Go
150 lines
4.2 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package reg
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/golang/protobuf/ptypes/empty"
|
|
"github.com/stretchr/testify/suite"
|
|
"golang.org/x/sys/unix"
|
|
"google.golang.org/grpc"
|
|
|
|
healthapi "github.com/talos-systems/talos/api/health"
|
|
networkapi "github.com/talos-systems/talos/api/network"
|
|
"github.com/talos-systems/talos/internal/app/networkd/pkg/networkd"
|
|
"github.com/talos-systems/talos/pkg/grpc/factory"
|
|
)
|
|
|
|
type NetworkdSuite struct {
|
|
suite.Suite
|
|
}
|
|
|
|
func TestNetworkdSuite(t *testing.T) {
|
|
suite.Run(t, new(NetworkdSuite))
|
|
}
|
|
|
|
// nolint: dupl
|
|
func (suite *NetworkdSuite) TestRoutes() {
|
|
_, server, listener := suite.fakeNetworkdRPC()
|
|
|
|
// nolint: errcheck
|
|
defer os.Remove(listener.Addr().String())
|
|
|
|
defer server.Stop()
|
|
|
|
// nolint: errcheck
|
|
go server.Serve(listener)
|
|
|
|
conn, err := grpc.Dial(fmt.Sprintf("%s://%s", "unix", listener.Addr().String()), grpc.WithInsecure())
|
|
suite.Assert().NoError(err)
|
|
|
|
nClient := networkapi.NewNetworkServiceClient(conn)
|
|
resp, err := nClient.Routes(context.Background(), &empty.Empty{})
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Greater(len(resp.Messages[0].Routes), 0)
|
|
}
|
|
|
|
// nolint: dupl
|
|
func (suite *NetworkdSuite) TestInterfaces() {
|
|
_, server, listener := suite.fakeNetworkdRPC()
|
|
|
|
// nolint: errcheck
|
|
defer os.Remove(listener.Addr().String())
|
|
|
|
defer server.Stop()
|
|
|
|
// nolint: errcheck
|
|
go server.Serve(listener)
|
|
|
|
conn, err := grpc.Dial(fmt.Sprintf("%s://%s", "unix", listener.Addr().String()), grpc.WithInsecure())
|
|
suite.Assert().NoError(err)
|
|
|
|
nClient := networkapi.NewNetworkServiceClient(conn)
|
|
resp, err := nClient.Interfaces(context.Background(), &empty.Empty{})
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Greater(len(resp.Messages[0].Interfaces), 0)
|
|
}
|
|
|
|
func (suite *NetworkdSuite) fakeNetworkdRPC() (*networkd.Networkd, *grpc.Server, net.Listener) {
|
|
// Create networkd instance
|
|
n, err := networkd.New(nil)
|
|
suite.Assert().NoError(err)
|
|
|
|
// Create gRPC server
|
|
api := NewRegistrator(n)
|
|
server := factory.NewServer(api)
|
|
tmpfile, err := ioutil.TempFile("", "networkd")
|
|
suite.Assert().NoError(err)
|
|
|
|
listener, err := factory.NewListener(
|
|
factory.Network("unix"),
|
|
factory.SocketPath(tmpfile.Name()),
|
|
)
|
|
suite.Assert().NoError(err)
|
|
|
|
return n, server, listener
|
|
}
|
|
|
|
func (suite *NetworkdSuite) TestToCIDR() {
|
|
suite.Assert().Equal(toCIDR(unix.AF_INET, net.ParseIP("192.168.254.0"), 24), "192.168.254.0/24")
|
|
suite.Assert().Equal(toCIDR(unix.AF_INET6, net.ParseIP("2001:db8::"), 16), "2001:db8::/16")
|
|
suite.Assert().Equal(toCIDR(unix.AF_INET, nil, 0), "0.0.0.0/0")
|
|
suite.Assert().Equal(toCIDR(unix.AF_INET6, nil, 0), "::/0")
|
|
}
|
|
|
|
func (suite *NetworkdSuite) TestHealthAPI() {
|
|
nwd, server, listener := suite.fakeNetworkdRPC()
|
|
|
|
// nolint: errcheck
|
|
defer os.Remove(listener.Addr().String())
|
|
|
|
defer server.Stop()
|
|
|
|
// nolint: errcheck
|
|
go server.Serve(listener)
|
|
|
|
conn, err := grpc.Dial(fmt.Sprintf("%s://%s", "unix", listener.Addr().String()), grpc.WithInsecure())
|
|
suite.Assert().NoError(err)
|
|
|
|
// Verify base state
|
|
nClient := healthapi.NewHealthClient(conn)
|
|
hcResp, err := nClient.Check(context.Background(), &empty.Empty{})
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Equal(healthapi.HealthCheck_SERVING, hcResp.Messages[0].Status)
|
|
|
|
rResp, err := nClient.Ready(context.Background(), &empty.Empty{})
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Equal(healthapi.ReadyCheck_NOT_READY, rResp.Messages[0].Status)
|
|
|
|
// Trigger ready condition
|
|
nwd.SetReady()
|
|
suite.Assert().NoError(err)
|
|
rResp, err = nClient.Ready(context.Background(), &empty.Empty{})
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Equal(healthapi.ReadyCheck_READY, rResp.Messages[0].Status)
|
|
|
|
// Test watch
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
stream, err := nClient.Watch(ctx, &healthapi.HealthWatchRequest{IntervalSeconds: 1})
|
|
suite.Require().NoError(err)
|
|
|
|
for i := 0; i < 2; i++ {
|
|
hcResp, err = stream.Recv()
|
|
suite.Assert().NoError(err)
|
|
suite.Assert().Equal(healthapi.HealthCheck_SERVING, hcResp.Messages[0].Status)
|
|
}
|
|
|
|
cancel()
|
|
|
|
_, err = stream.Recv()
|
|
suite.Assert().Error(err)
|
|
}
|