diff --git a/.conform.yaml b/.conform.yaml index f1c27c9edd..dc63c3815c 100644 --- a/.conform.yaml +++ b/.conform.yaml @@ -29,7 +29,6 @@ policies: - timed - talosctl - trustd - - routerd - talosctl - kernel - security diff --git a/Dockerfile b/Dockerfile index 5c283ed1d5..2f56728f7e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -213,18 +213,6 @@ WORKDIR /src/internal/app/trustd RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /trustd RUN chmod +x /trustd -# The routerd target builds the routerd binary. - -FROM base AS routerd-build -ARG SHA -ARG TAG -ARG PKGS -ARG EXTRAS -ARG VERSION_PKG="github.com/talos-systems/talos/pkg/version" -WORKDIR /src/internal/app/routerd -RUN --mount=type=cache,target=/.cache/go-build go build -ldflags "-s -w -X ${VERSION_PKG}.Name=Server -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG} -X ${VERSION_PKG}.PkgsVersion=${PKGS} -X ${VERSION_PKG}.ExtrasVersion=${EXTRAS}" -o /routerd -RUN chmod +x /routerd - # The talosctl targets build the talosctl binaries. FROM base AS talosctl-linux-amd64-build @@ -353,9 +341,8 @@ RUN ln -s /etc/ssl /rootfs/etc/pki RUN ln -s /etc/ssl /rootfs/usr/share/ca-certificates RUN ln -s /etc/ssl /rootfs/usr/local/share/ca-certificates RUN ln -s /etc/ssl /rootfs/etc/ca-certificates -RUN mkdir -pv /rootfs/opt/{apid,routerd,timed,trustd} +RUN mkdir -pv /rootfs/opt/{apid,timed,trustd} RUN ln /rootfs/sbin/init /rootfs/opt/apid/apid -RUN ln /rootfs/sbin/init /rootfs/opt/routerd/routerd RUN ln /rootfs/sbin/init /rootfs/opt/timed/timed RUN ln /rootfs/sbin/init /rootfs/opt/trustd/trustd diff --git a/internal/app/apid/main.go b/internal/app/apid/main.go index 9218313994..0771abddcb 100644 --- a/internal/app/apid/main.go +++ b/internal/app/apid/main.go @@ -74,7 +74,7 @@ func Main() { } backendFactory := apidbackend.NewAPIDFactory(clientTLSConfig) - localBackend := backend.NewLocal("routerd", constants.RouterdSocketPath) + localBackend := backend.NewLocal("machined", constants.MachineSocketPath) router := director.NewRouter(backendFactory.Get, localBackend) diff --git a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go index 8c2c960794..8f3e7f11da 100644 --- a/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_server.go @@ -46,6 +46,7 @@ import ( "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/adv" "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader/grub" "github.com/talos-systems/talos/internal/app/machined/pkg/system" + networkserver "github.com/talos-systems/talos/internal/app/networkd/pkg/server" storaged "github.com/talos-systems/talos/internal/app/storaged" "github.com/talos-systems/talos/internal/pkg/configuration" "github.com/talos-systems/talos/internal/pkg/containers" @@ -63,8 +64,10 @@ import ( "github.com/talos-systems/talos/pkg/machinery/api/common" "github.com/talos-systems/talos/pkg/machinery/api/inspect" "github.com/talos-systems/talos/pkg/machinery/api/machine" + "github.com/talos-systems/talos/pkg/machinery/api/network" "github.com/talos-systems/talos/pkg/machinery/api/resource" "github.com/talos-systems/talos/pkg/machinery/api/storage" + timeapi "github.com/talos-systems/talos/pkg/machinery/api/time" "github.com/talos-systems/talos/pkg/machinery/config" machinetype "github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine" "github.com/talos-systems/talos/pkg/machinery/constants" @@ -110,6 +113,8 @@ func (s *Server) Register(obj *grpc.Server) { resource.RegisterResourceServiceServer(obj, &ResourceServer{server: s}) inspect.RegisterInspectServiceServer(obj, &InspectServer{server: s}) storage.RegisterStorageServiceServer(obj, &storaged.Server{}) + timeapi.RegisterTimeServiceServer(obj, &TimeServer{ConfigProvider: s.Controller.Runtime()}) + network.RegisterNetworkServiceServer(obj, &networkserver.NetworkServer{}) } // ApplyConfiguration implements machine.MachineService. diff --git a/internal/app/machined/internal/server/v1alpha1/v1alpha1_time.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_time.go new file mode 100644 index 0000000000..949bd0eccd --- /dev/null +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_time.go @@ -0,0 +1,71 @@ +// 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 runtime + +import ( + "context" + "fmt" + "time" + + "github.com/beevik/ntp" + "github.com/golang/protobuf/ptypes/empty" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" + + timeapi "github.com/talos-systems/talos/pkg/machinery/api/time" + "github.com/talos-systems/talos/pkg/machinery/config" +) + +// ConfigProvider defines an interface sufficient for the TimeServer. +type ConfigProvider interface { + Config() config.Provider +} + +// TimeServer implements TimeService API. +type TimeServer struct { + timeapi.UnimplementedTimeServiceServer + + ConfigProvider ConfigProvider +} + +// Register implements the factory.Registrator interface. +func (r *TimeServer) Register(s *grpc.Server) { + timeapi.RegisterTimeServiceServer(s, r) +} + +// Time issues a query to the configured ntp server and displays the results. +func (r *TimeServer) Time(ctx context.Context, in *empty.Empty) (reply *timeapi.TimeResponse, err error) { + timeServers := r.ConfigProvider.Config().Machine().Time().Servers() + + if len(timeServers) == 0 { + return nil, fmt.Errorf("no time servers configured") + } + + return r.TimeCheck(ctx, &timeapi.TimeRequest{ + Server: timeServers[0], + }) +} + +// TimeCheck issues a query to the specified ntp server and displays the results. +func (r *TimeServer) TimeCheck(ctx context.Context, in *timeapi.TimeRequest) (reply *timeapi.TimeResponse, err error) { + rt, err := ntp.Query(in.Server) + if err != nil { + return nil, fmt.Errorf("error querying NTP server %q: %w", in.Server, err) + } + + if err = rt.Validate(); err != nil { + return nil, fmt.Errorf("error validating NTP response: %w", err) + } + + return &timeapi.TimeResponse{ + Messages: []*timeapi.Time{ + { + Server: in.Server, + Localtime: timestamppb.New(time.Now()), + Remotetime: timestamppb.New(rt.Time), + }, + }, + }, nil +} diff --git a/internal/app/timed/pkg/reg/reg_test.go b/internal/app/machined/internal/server/v1alpha1/v1alpha1_time_test.go similarity index 76% rename from internal/app/timed/pkg/reg/reg_test.go rename to internal/app/machined/internal/server/v1alpha1/v1alpha1_time_test.go index 8984dd10ed..edf836e984 100644 --- a/internal/app/timed/pkg/reg/reg_test.go +++ b/internal/app/machined/internal/server/v1alpha1/v1alpha1_time_test.go @@ -2,7 +2,7 @@ // 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_test +package runtime_test import ( "context" @@ -16,11 +16,12 @@ import ( "github.com/stretchr/testify/suite" "google.golang.org/grpc" - "github.com/talos-systems/talos/internal/app/timed/pkg/ntp" - "github.com/talos-systems/talos/internal/app/timed/pkg/reg" + runtime "github.com/talos-systems/talos/internal/app/machined/internal/server/v1alpha1" "github.com/talos-systems/talos/pkg/grpc/dialer" "github.com/talos-systems/talos/pkg/grpc/factory" timeapi "github.com/talos-systems/talos/pkg/machinery/api/time" + "github.com/talos-systems/talos/pkg/machinery/config" + "github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1" ) type TimedSuite struct { @@ -33,14 +34,27 @@ func TestTimedSuite(t *testing.T) { suite.Run(t, new(TimedSuite)) } +type mockConfigProvider struct { + timeServer string +} + +func (provider *mockConfigProvider) Config() config.Provider { + return &v1alpha1.Config{ + MachineConfig: &v1alpha1.MachineConfig{ + MachineTime: &v1alpha1.TimeConfig{ + TimeServers: []string{provider.timeServer}, + }, + }, + } +} + func (suite *TimedSuite) TestTime() { testServer := "time.cloudflare.com" - // Create ntp client - n, err := ntp.NewNTPClient(ntp.WithServer(testServer)) - suite.Assert().NoError(err) // Create gRPC server - api := reg.NewRegistrator(n) + api := &runtime.TimeServer{ + ConfigProvider: &mockConfigProvider{timeServer: testServer}, + } server := factory.NewServer(api) listener, err := fakeTimedRPC() suite.Assert().NoError(err) @@ -58,24 +72,23 @@ func (suite *TimedSuite) TestTime() { grpc.WithInsecure(), grpc.WithContextDialer(dialer.DialUnix()), ) - suite.Assert().NoError(err) + suite.Require().NoError(err) nClient := timeapi.NewTimeServiceClient(conn) reply, err := nClient.Time(context.Background(), &empty.Empty{}) - suite.Assert().NoError(err) + suite.Require().NoError(err) suite.Assert().Equal(reply.Messages[0].Server, testServer) } func (suite *TimedSuite) TestTimeCheck() { testServer := "time.cloudflare.com" + // Create ntp client with bogus server // so we can check that we explicitly check the time of the // specified server ( testserver ) - n, err := ntp.NewNTPClient(ntp.WithServer("127.0.0.1")) - suite.Assert().NoError(err) // Create gRPC server - api := reg.NewRegistrator(n) + api := &runtime.TimeServer{} server := factory.NewServer(api) listener, err := fakeTimedRPC() suite.Assert().NoError(err) @@ -93,11 +106,11 @@ func (suite *TimedSuite) TestTimeCheck() { grpc.WithInsecure(), grpc.WithContextDialer(dialer.DialUnix()), ) - suite.Assert().NoError(err) + suite.Require().NoError(err) nClient := timeapi.NewTimeServiceClient(conn) reply, err := nClient.TimeCheck(context.Background(), &timeapi.TimeRequest{Server: testServer}) - suite.Assert().NoError(err) + suite.Require().NoError(err) suite.Assert().Equal(reply.Messages[0].Server, testServer) } diff --git a/internal/app/machined/main.go b/internal/app/machined/main.go index f47799cd46..08a8170072 100644 --- a/internal/app/machined/main.go +++ b/internal/app/machined/main.go @@ -30,7 +30,6 @@ import ( "github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/bootloader" "github.com/talos-systems/talos/internal/app/machined/pkg/system" "github.com/talos-systems/talos/internal/app/machined/pkg/system/services" - "github.com/talos-systems/talos/internal/app/routerd" "github.com/talos-systems/talos/internal/app/timed" "github.com/talos-systems/talos/internal/app/trustd" "github.com/talos-systems/talos/internal/pkg/mount" @@ -268,10 +267,6 @@ func main() { case "/apid": apid.Main() - return - case "/routerd": - routerd.Main() - return case "/timed": timed.Main() diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index 10c563865f..db686ecb4e 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -664,7 +664,6 @@ func StartAllServices(seq runtime.Sequence, data interface{}) (runtime.TaskExecu svcs.Load( &services.APID{}, - &services.Routerd{}, &services.Networkd{}, &services.CRI{}, &services.Kubelet{}, diff --git a/internal/app/machined/pkg/system/services/apid.go b/internal/app/machined/pkg/system/services/apid.go index d6bfc67ed2..b6054018e7 100644 --- a/internal/app/machined/pkg/system/services/apid.go +++ b/internal/app/machined/pkg/system/services/apid.go @@ -109,7 +109,7 @@ func (o *APID) Runner(r runtime.Runtime) (runner.Runner, error) { // Set the mounts. mounts := []specs.Mount{ {Type: "bind", Destination: "/etc/ssl", Source: "/etc/ssl", Options: []string{"bind", "ro"}}, - {Type: "bind", Destination: filepath.Dir(constants.RouterdSocketPath), Source: filepath.Dir(constants.RouterdSocketPath), Options: []string{"rbind", "ro"}}, + {Type: "bind", Destination: filepath.Dir(constants.MachineSocketPath), Source: filepath.Dir(constants.MachineSocketPath), Options: []string{"rbind", "ro"}}, {Type: "bind", Destination: filepath.Dir(constants.APISocketPath), Source: filepath.Dir(constants.APISocketPath), Options: []string{"rbind", "rw"}}, } diff --git a/internal/app/machined/pkg/system/services/routerd.go b/internal/app/machined/pkg/system/services/routerd.go deleted file mode 100644 index c537e96c71..0000000000 --- a/internal/app/machined/pkg/system/services/routerd.go +++ /dev/null @@ -1,132 +0,0 @@ -// 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/. - -//nolint:golint -package services - -import ( - "context" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/containerd/containerd/oci" - specs "github.com/opencontainers/runtime-spec/specs-go" - "google.golang.org/grpc" - - "github.com/talos-systems/talos/internal/app/machined/pkg/runtime" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/events" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/health" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/runner" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/containerd" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/runner/restart" - "github.com/talos-systems/talos/pkg/conditions" - "github.com/talos-systems/talos/pkg/grpc/dialer" - "github.com/talos-systems/talos/pkg/machinery/constants" -) - -// Routerd implements the Service interface. It serves as the concrete type with -// the required methods. -type Routerd struct{} - -// ID implements the Service interface. -func (o *Routerd) ID(r runtime.Runtime) string { - return "routerd" -} - -// PreFunc implements the Service interface. -func (o *Routerd) PreFunc(ctx context.Context, r runtime.Runtime) error { - return nil -} - -// PostFunc implements the Service interface. -func (o *Routerd) PostFunc(r runtime.Runtime, state events.ServiceState) (err error) { - return nil -} - -// Condition implements the Service interface. -func (o *Routerd) Condition(r runtime.Runtime) conditions.Condition { - return nil -} - -// DependsOn implements the Service interface. -func (o *Routerd) DependsOn(r runtime.Runtime) []string { - return []string{"containerd"} -} - -func (o *Routerd) Runner(r runtime.Runtime) (runner.Runner, error) { - // Set the process arguments. - args := runner.Args{ - ID: o.ID(r), - ProcessArgs: []string{ - "/routerd", - }, - } - - // Ensure socket dir exists - if err := os.MkdirAll(filepath.Dir(constants.RouterdSocketPath), 0o750); err != nil { - return nil, err - } - - // Set the mounts. - mounts := []specs.Mount{ - {Type: "bind", Destination: "/tmp", Source: "/tmp", Options: []string{"rbind", "rshared", "rw"}}, - {Type: "bind", Destination: constants.SystemRunPath, Source: constants.SystemRunPath, Options: []string{"bind", "ro"}}, - {Type: "bind", Destination: filepath.Dir(constants.RouterdSocketPath), Source: filepath.Dir(constants.RouterdSocketPath), Options: []string{"rbind", "rw"}}, - } - - env := []string{} - - for key, val := range r.Config().Machine().Env() { - switch strings.ToLower(key) { - // explicitly exclude proxy variables from routerd since this will - // negatively impact grpc connections. - // ref: https://github.com/grpc/grpc-go/blob/0f32486dd3c9bc29705535bd7e2e43801824cbc4/clientconn.go#L199-L206 - // ref: https://github.com/grpc/grpc-go/blob/63ae68c9686cc0dd26c4f7476d66bb2f5c31789f/proxy.go#L118-L144 - case "no_proxy": - case "http_proxy": - case "https_proxy": - default: - env = append(env, fmt.Sprintf("%s=%s", key, val)) - } - } - - return restart.New(containerd.NewRunner( - r.Config().Debug(), - &args, - runner.WithLoggingManager(r.Logging()), - runner.WithContainerdAddress(constants.SystemContainerdAddress), - runner.WithEnv(env), - runner.WithOCISpecOpts( - oci.WithMounts(mounts), - oci.WithRootFSPath("/opt/routerd"), - oci.WithRootFSReadonly(), - ), - ), - restart.WithType(restart.Forever), - ), nil -} - -// HealthFunc implements the HealthcheckedService interface. -func (o *Routerd) HealthFunc(runtime.Runtime) health.Check { - return func(ctx context.Context) error { - conn, err := grpc.DialContext( - ctx, - fmt.Sprintf("%s://%s", "unix", constants.RouterdSocketPath), - grpc.WithInsecure(), - grpc.WithContextDialer(dialer.DialUnix()), - ) - if err != nil { - return err - } - - return conn.Close() - } -} - -// HealthSettings implements the HealthcheckedService interface. -func (o *Routerd) HealthSettings(runtime.Runtime) *health.Settings { - return &health.DefaultSettings -} diff --git a/internal/app/machined/pkg/system/services/routerd_test.go b/internal/app/machined/pkg/system/services/routerd_test.go deleted file mode 100644 index 7ab8281008..0000000000 --- a/internal/app/machined/pkg/system/services/routerd_test.go +++ /dev/null @@ -1,18 +0,0 @@ -// 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 services_test - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/talos-systems/talos/internal/app/machined/pkg/system" - "github.com/talos-systems/talos/internal/app/machined/pkg/system/services" -) - -func TestRouterdInterfaces(t *testing.T) { - assert.Implements(t, (*system.HealthcheckedService)(nil), new(services.Routerd)) -} diff --git a/internal/app/maintenance/server/server.go b/internal/app/maintenance/server/server.go index 293cfef2e0..cf0d9307bd 100644 --- a/internal/app/maintenance/server/server.go +++ b/internal/app/maintenance/server/server.go @@ -9,11 +9,10 @@ import ( "fmt" "log" - "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc" "github.com/talos-systems/talos/internal/app/machined/pkg/runtime" - "github.com/talos-systems/talos/internal/app/networkd/pkg/networkd" + networkserver "github.com/talos-systems/talos/internal/app/networkd/pkg/server" storaged "github.com/talos-systems/talos/internal/app/storaged" "github.com/talos-systems/talos/internal/pkg/configuration" "github.com/talos-systems/talos/pkg/machinery/api/machine" @@ -26,7 +25,6 @@ import ( // Server implements machine.MachineService, network.NetworkService, and storage.StorageService. type Server struct { machine.UnimplementedMachineServiceServer - network.UnimplementedNetworkServiceServer runtime runtime.Runtime logger *log.Logger @@ -49,7 +47,7 @@ func (s *Server) Register(obj *grpc.Server) { storage.RegisterStorageServiceServer(obj, &storaged.Server{}) machine.RegisterMachineServiceServer(obj, s) - network.RegisterNetworkServiceServer(obj, s) + network.RegisterNetworkServiceServer(obj, &networkserver.NetworkServer{}) } // ApplyConfiguration implements machine.MachineService. @@ -92,8 +90,3 @@ func (s *Server) GenerateConfiguration(ctx context.Context, in *machine.Generate return configuration.Generate(ctx, in) } - -// Interfaces implements the machine.NetworkService interface. -func (s *Server) Interfaces(ctx context.Context, in *empty.Empty) (reply *network.InterfacesResponse, err error) { - return networkd.GetDevices() -} diff --git a/internal/app/networkd/main.go b/internal/app/networkd/main.go index d5b89aa8a4..d9ca5131ce 100644 --- a/internal/app/networkd/main.go +++ b/internal/app/networkd/main.go @@ -41,7 +41,7 @@ func run(ctx context.Context, r runtime.Runtime, logger *log.Logger) error { return err } - registrator, err := reg.NewRegistrator(logger, nwd) + registrator, err := reg.NewRegistrator(nwd) if err != nil { return err } diff --git a/internal/app/networkd/pkg/networkd/devices.go b/internal/app/networkd/pkg/networkd/devices.go deleted file mode 100644 index 8d2cc1fff8..0000000000 --- a/internal/app/networkd/pkg/networkd/devices.go +++ /dev/null @@ -1,50 +0,0 @@ -// 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 networkd - -import ( - "net" - - networkapi "github.com/talos-systems/talos/pkg/machinery/api/network" -) - -// GetDevices gathers information about existing network interfaces and their flags. -func GetDevices() (reply *networkapi.InterfacesResponse, err error) { - ifaces, err := net.Interfaces() - if err != nil { - return reply, err - } - - resp := &networkapi.Interfaces{} - - for _, iface := range ifaces { - ifaceaddrs, err := iface.Addrs() - if err != nil { - return reply, err - } - - addrs := make([]string, 0, len(ifaceaddrs)) - for _, addr := range ifaceaddrs { - addrs = append(addrs, addr.String()) - } - - ifmsg := &networkapi.Interface{ - Index: uint32(iface.Index), - Mtu: uint32(iface.MTU), - Name: iface.Name, - Hardwareaddr: iface.HardwareAddr.String(), - Flags: networkapi.InterfaceFlags(iface.Flags), - Ipaddress: addrs, - } - - resp.Interfaces = append(resp.Interfaces, ifmsg) - } - - return &networkapi.InterfacesResponse{ - Messages: []*networkapi.Interfaces{ - resp, - }, - }, nil -} diff --git a/internal/app/networkd/pkg/reg/reg.go b/internal/app/networkd/pkg/reg/reg.go index 887ca45a6e..ff7416f135 100644 --- a/internal/app/networkd/pkg/reg/reg.go +++ b/internal/app/networkd/pkg/reg/reg.go @@ -8,125 +8,35 @@ package reg import ( "context" "errors" - "fmt" - "log" - "net" "time" "github.com/golang/protobuf/ptypes/empty" - "github.com/jsimonetti/rtnetlink" - "golang.org/x/sys/unix" "google.golang.org/grpc" "github.com/talos-systems/talos/internal/app/networkd/pkg/networkd" healthapi "github.com/talos-systems/talos/pkg/machinery/api/health" - networkapi "github.com/talos-systems/talos/pkg/machinery/api/network" ) // Registrator is the concrete type that implements the factory.Registrator and // healthapi.HealthServer and networkapi.NetworkServiceServer interfaces. type Registrator struct { healthapi.UnimplementedHealthServer - networkapi.UnimplementedNetworkServiceServer Networkd *networkd.Networkd - Conn *rtnetlink.Conn - - logger *log.Logger } // NewRegistrator builds new Registrator instance. -func NewRegistrator(logger *log.Logger, n *networkd.Networkd) (*Registrator, error) { - nlConn, err := rtnetlink.Dial(nil) - if err != nil { - return nil, err - } - +func NewRegistrator(n *networkd.Networkd) (*Registrator, error) { return &Registrator{ Networkd: n, - Conn: nlConn, - logger: logger, }, nil } // Register implements the factory.Registrator interface. func (r *Registrator) Register(s *grpc.Server) { - networkapi.RegisterNetworkServiceServer(s, r) healthapi.RegisterHealthServer(s, r) } -// Routes returns the hosts routing table. -func (r *Registrator) Routes(ctx context.Context, in *empty.Empty) (reply *networkapi.RoutesResponse, err error) { - list, err := r.Conn.Route.List() - if err != nil { - return nil, fmt.Errorf("failed to get route list: %w", err) - } - - routes := []*networkapi.Route{} - - for _, rMesg := range list { - ifaceData, err := r.Conn.Link.Get((rMesg.Attributes.OutIface)) - if err != nil { - r.logger.Printf("failed to get interface details for interface index %d: %v", rMesg.Attributes.OutIface, err) - // TODO: Remove once we get this sorted on why there's a - // failure here - r.logger.Printf("%+v", rMesg) - - continue - } - - routes = append(routes, &networkapi.Route{ - Interface: ifaceData.Attributes.Name, - Destination: toCIDR(rMesg.Family, rMesg.Attributes.Dst, int(rMesg.DstLength)), - Gateway: toCIDR(rMesg.Family, rMesg.Attributes.Gateway, 32), - Metric: rMesg.Attributes.Priority, - Scope: uint32(rMesg.Scope), - Source: toCIDR(rMesg.Family, rMesg.Attributes.Src, int(rMesg.SrcLength)), - Family: networkapi.AddressFamily(rMesg.Family), - Protocol: networkapi.RouteProtocol(rMesg.Protocol), - Flags: rMesg.Flags, - }) - } - - return &networkapi.RoutesResponse{ - Messages: []*networkapi.Routes{ - { - Routes: routes, - }, - }, - }, nil -} - -// Interfaces returns the hosts network interfaces and addresses. -func (r *Registrator) Interfaces(ctx context.Context, in *empty.Empty) (reply *networkapi.InterfacesResponse, err error) { - return networkd.GetDevices() -} - -func toCIDR(family uint8, prefix net.IP, prefixLen int) string { - netLen := 32 - - if family == unix.AF_INET6 { - netLen = 128 - } - - // Set a friendly readable value instead of "" - if prefix == nil { - switch family { - case unix.AF_INET6: - prefix = net.ParseIP("::") - case unix.AF_INET: - prefix = net.ParseIP("0.0.0.0") - } - } - - ipNet := &net.IPNet{ - IP: prefix, - Mask: net.CIDRMask(prefixLen, netLen), - } - - return ipNet.String() -} - // Check implements the Health api and provides visibilty into the state of networkd. func (r *Registrator) Check(ctx context.Context, in *empty.Empty) (reply *healthapi.HealthCheckResponse, err error) { reply = &healthapi.HealthCheckResponse{ diff --git a/internal/app/networkd/pkg/reg/reg_test.go b/internal/app/networkd/pkg/reg/reg_test.go index 5720016354..8b64e0464c 100644 --- a/internal/app/networkd/pkg/reg/reg_test.go +++ b/internal/app/networkd/pkg/reg/reg_test.go @@ -16,14 +16,12 @@ import ( "github.com/golang/protobuf/ptypes/empty" "github.com/stretchr/testify/suite" - "golang.org/x/sys/unix" "google.golang.org/grpc" "github.com/talos-systems/talos/internal/app/networkd/pkg/networkd" "github.com/talos-systems/talos/pkg/grpc/dialer" "github.com/talos-systems/talos/pkg/grpc/factory" healthapi "github.com/talos-systems/talos/pkg/machinery/api/health" - networkapi "github.com/talos-systems/talos/pkg/machinery/api/network" ) type NetworkdSuite struct { @@ -34,63 +32,13 @@ 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(), - grpc.WithContextDialer(dialer.DialUnix()), - ) - 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(), - grpc.WithContextDialer(dialer.DialUnix()), - ) - 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(log.New(os.Stderr, "", log.LstdFlags), nil) suite.Assert().NoError(err) // Create gRPC server - api, err := NewRegistrator(log.New(os.Stderr, "", log.LstdFlags), n) + api, err := NewRegistrator(n) suite.Require().NoError(err) server := factory.NewServer(api) @@ -106,13 +54,6 @@ func (suite *NetworkdSuite) fakeNetworkdRPC() (*networkd.Networkd, *grpc.Server, 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() diff --git a/internal/app/networkd/pkg/server/server.go b/internal/app/networkd/pkg/server/server.go new file mode 100644 index 0000000000..6b1d5c4d9a --- /dev/null +++ b/internal/app/networkd/pkg/server/server.go @@ -0,0 +1,144 @@ +// 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 server implements network API gRPC server. +package server + +import ( + "context" + "fmt" + "log" + "net" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/jsimonetti/rtnetlink" + "golang.org/x/sys/unix" + "google.golang.org/grpc" + + networkapi "github.com/talos-systems/talos/pkg/machinery/api/network" +) + +// NetworkServer implements NetworkService API. +type NetworkServer struct { + networkapi.UnimplementedNetworkServiceServer +} + +// Register implements the factory.Registrator interface. +func (r *NetworkServer) Register(s *grpc.Server) { + networkapi.RegisterNetworkServiceServer(s, r) +} + +// Routes returns the hosts routing table. +func (r *NetworkServer) Routes(ctx context.Context, in *empty.Empty) (reply *networkapi.RoutesResponse, err error) { + conn, err := rtnetlink.Dial(nil) + if err != nil { + return nil, err + } + + defer conn.Close() //nolint: errcheck + + list, err := conn.Route.List() + if err != nil { + return nil, fmt.Errorf("failed to get route list: %w", err) + } + + routes := []*networkapi.Route{} + + for _, rMesg := range list { + ifaceData, err := conn.Link.Get((rMesg.Attributes.OutIface)) + if err != nil { + log.Printf("failed to get interface details for interface index %d: %v", rMesg.Attributes.OutIface, err) + // TODO: Remove once we get this sorted on why there's a + // failure here + log.Printf("%+v", rMesg) + + continue + } + + routes = append(routes, &networkapi.Route{ + Interface: ifaceData.Attributes.Name, + Destination: ToCIDR(rMesg.Family, rMesg.Attributes.Dst, int(rMesg.DstLength)), + Gateway: ToCIDR(rMesg.Family, rMesg.Attributes.Gateway, 32), + Metric: rMesg.Attributes.Priority, + Scope: uint32(rMesg.Scope), + Source: ToCIDR(rMesg.Family, rMesg.Attributes.Src, int(rMesg.SrcLength)), + Family: networkapi.AddressFamily(rMesg.Family), + Protocol: networkapi.RouteProtocol(rMesg.Protocol), + Flags: rMesg.Flags, + }) + } + + return &networkapi.RoutesResponse{ + Messages: []*networkapi.Routes{ + { + Routes: routes, + }, + }, + }, nil +} + +// Interfaces returns the hosts network interfaces and addresses. +func (r *NetworkServer) Interfaces(ctx context.Context, in *empty.Empty) (reply *networkapi.InterfacesResponse, err error) { + ifaces, err := net.Interfaces() + if err != nil { + return reply, err + } + + resp := &networkapi.Interfaces{} + + for _, iface := range ifaces { + ifaceaddrs, err := iface.Addrs() + if err != nil { + return reply, err + } + + addrs := make([]string, 0, len(ifaceaddrs)) + for _, addr := range ifaceaddrs { + addrs = append(addrs, addr.String()) + } + + ifmsg := &networkapi.Interface{ + Index: uint32(iface.Index), + Mtu: uint32(iface.MTU), + Name: iface.Name, + Hardwareaddr: iface.HardwareAddr.String(), + Flags: networkapi.InterfaceFlags(iface.Flags), + Ipaddress: addrs, + } + + resp.Interfaces = append(resp.Interfaces, ifmsg) + } + + return &networkapi.InterfacesResponse{ + Messages: []*networkapi.Interfaces{ + resp, + }, + }, nil +} + +// ToCIDR formats IP address as CIDR. +func ToCIDR(family uint8, prefix net.IP, prefixLen int) string { + netLen := 32 + + if family == unix.AF_INET6 { + netLen = 128 + } + + // Set a friendly readable value instead of "" + if prefix == nil { + switch family { + case unix.AF_INET6: + prefix = net.ParseIP("::") + case unix.AF_INET: + prefix = net.ParseIP("0.0.0.0") + } + } + + ipNet := &net.IPNet{ + IP: prefix, + Mask: net.CIDRMask(prefixLen, netLen), + } + + return ipNet.String() +} diff --git a/internal/app/networkd/pkg/server/server_test.go b/internal/app/networkd/pkg/server/server_test.go new file mode 100644 index 0000000000..96c7018816 --- /dev/null +++ b/internal/app/networkd/pkg/server/server_test.go @@ -0,0 +1,106 @@ +// 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 server_test + +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" + + "github.com/talos-systems/talos/internal/app/networkd/pkg/server" + "github.com/talos-systems/talos/pkg/grpc/dialer" + "github.com/talos-systems/talos/pkg/grpc/factory" + networkapi "github.com/talos-systems/talos/pkg/machinery/api/network" +) + +type NetworkSuite struct { + suite.Suite +} + +func TestNetwordSuite(t *testing.T) { + suite.Run(t, new(NetworkSuite)) +} + +//nolint:dupl +func (suite *NetworkSuite) TestRoutes() { + server, listener := suite.fakeNetworkRPC() + + //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(), + grpc.WithContextDialer(dialer.DialUnix()), + ) + 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 *NetworkSuite) TestInterfaces() { + server, listener := suite.fakeNetworkRPC() + + //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(), + grpc.WithContextDialer(dialer.DialUnix()), + ) + 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 *NetworkSuite) fakeNetworkRPC() (*grpc.Server, net.Listener) { + // Create gRPC server + api := &server.NetworkServer{} + + 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 server, listener +} + +func (suite *NetworkSuite) TestToCIDR() { + suite.Assert().Equal(server.ToCIDR(unix.AF_INET, net.ParseIP("192.168.254.0"), 24), "192.168.254.0/24") + suite.Assert().Equal(server.ToCIDR(unix.AF_INET6, net.ParseIP("2001:db8::"), 16), "2001:db8::/16") + suite.Assert().Equal(server.ToCIDR(unix.AF_INET, nil, 0), "0.0.0.0/0") + suite.Assert().Equal(server.ToCIDR(unix.AF_INET6, nil, 0), "::/0") +} diff --git a/internal/app/routerd/main.go b/internal/app/routerd/main.go deleted file mode 100644 index 62b6e924db..0000000000 --- a/internal/app/routerd/main.go +++ /dev/null @@ -1,57 +0,0 @@ -// 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 routerd - -import ( - "log" - - "github.com/talos-systems/grpc-proxy/proxy" - "google.golang.org/grpc" - - "github.com/talos-systems/talos/internal/app/routerd/pkg/director" - "github.com/talos-systems/talos/pkg/grpc/factory" - "github.com/talos-systems/talos/pkg/grpc/proxy/backend" - "github.com/talos-systems/talos/pkg/machinery/constants" - "github.com/talos-systems/talos/pkg/startup" -) - -// Main is the entrypoint into routerd. -func Main() { - log.SetFlags(log.Lshortfile | log.Ldate | log.Lmicroseconds | log.Ltime) - - if err := startup.RandSeed(); err != nil { - log.Fatalf("failed to seed RNG: %v", err) - } - - router := director.NewRouter() - - // TODO: this should be dynamic based on plugin registration - machinedBackend := backend.NewLocal("machined", constants.MachineSocketPath) - router.RegisterLocalBackend("os.OSService", machinedBackend) - router.RegisterLocalBackend("machine.MachineService", machinedBackend) - router.RegisterLocalBackend("resource.ResourceService", machinedBackend) - router.RegisterLocalBackend("inspect.InspectService", machinedBackend) - router.RegisterLocalBackend("time.TimeService", backend.NewLocal("timed", constants.TimeSocketPath)) - router.RegisterLocalBackend("network.NetworkService", backend.NewLocal("networkd", constants.NetworkSocketPath)) - router.RegisterLocalBackend("cluster.ClusterService", machinedBackend) - router.RegisterLocalBackend("storage.StorageService", machinedBackend) - - err := factory.ListenAndServe( - router, - factory.Network("unix"), - factory.SocketPath(constants.RouterdSocketPath), - factory.WithDefaultLog(), - factory.ServerOptions( - grpc.CustomCodec(proxy.Codec()), //nolint:staticcheck - grpc.UnknownServiceHandler( - proxy.TransparentHandler( - router.Director, - )), - ), - ) - if err != nil { - log.Fatalf("listen: %v", err) - } -} diff --git a/internal/app/routerd/pkg/director/director.go b/internal/app/routerd/pkg/director/director.go deleted file mode 100644 index 7f08af06c2..0000000000 --- a/internal/app/routerd/pkg/director/director.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 director provides proxy call routing facility -package director - -import ( - "context" - "fmt" - "strings" - - "github.com/talos-systems/grpc-proxy/proxy" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// Router wraps grpc-proxy StreamDirector. -type Router struct { - localBackends map[string]proxy.Backend -} - -// NewRouter builds new Router. -func NewRouter() *Router { - return &Router{ - localBackends: map[string]proxy.Backend{}, - } -} - -// Register is no-op to implement factory.Registrator interface. -// -// Actual proxy handler is installed via grpc.UnknownServiceHandler option. -func (r *Router) Register(srv *grpc.Server) { -} - -// Director implements proxy.StreamDirector function. -func (r *Router) Director(ctx context.Context, fullMethodName string) (proxy.Mode, []proxy.Backend, error) { - parts := strings.SplitN(fullMethodName, "/", 3) - serviceName := parts[1] - - if backend, ok := r.localBackends[serviceName]; ok { - return proxy.One2One, []proxy.Backend{backend}, nil - } - - return proxy.One2One, nil, status.Errorf(codes.Unknown, "service %v is not defined", serviceName) -} - -// RegisterLocalBackend registers local backend by service name. -func (r *Router) RegisterLocalBackend(serviceName string, backend proxy.Backend) { - if _, exists := r.localBackends[serviceName]; exists { - panic(fmt.Sprintf("local backend %v already registered", serviceName)) - } - - r.localBackends[serviceName] = backend -} diff --git a/internal/app/routerd/pkg/director/director_test.go b/internal/app/routerd/pkg/director/director_test.go deleted file mode 100644 index d99bc33e03..0000000000 --- a/internal/app/routerd/pkg/director/director_test.go +++ /dev/null @@ -1,68 +0,0 @@ -// 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 director_test - -import ( - "context" - "testing" - - "github.com/stretchr/testify/suite" - "github.com/talos-systems/grpc-proxy/proxy" - "google.golang.org/grpc/metadata" - - "github.com/talos-systems/talos/internal/app/routerd/pkg/director" -) - -type DirectorSuite struct { - suite.Suite - - router *director.Router -} - -func (suite *DirectorSuite) SetupSuite() { - suite.router = director.NewRouter() -} - -func (suite *DirectorSuite) TestRegisterLocalBackend() { - suite.router.RegisterLocalBackend("a.A", &mockBackend{}) - suite.router.RegisterLocalBackend("b.B", &mockBackend{}) - - suite.Require().Panics(func() { suite.router.RegisterLocalBackend("a.A", &mockBackend{}) }) -} - -func (suite *DirectorSuite) TestDirectorLocal() { - ctx := context.Background() - - mode, backends, err := suite.router.Director(ctx, "/service.Service/method") - suite.Assert().Equal(proxy.One2One, mode) - suite.Assert().Nil(backends) - suite.Assert().EqualError(err, "rpc error: code = Unknown desc = service service.Service is not defined") - - suite.router.RegisterLocalBackend("service.Service", &mockBackend{target: "local"}) - - mode, backends, err = suite.router.Director(ctx, "/service.Service/method") - suite.Assert().Equal(proxy.One2One, mode) - suite.Assert().Len(backends, 1) - suite.Assert().Equal("local", backends[0].(*mockBackend).target) - suite.Assert().NoError(err) - - ctxProxyFrom := metadata.NewIncomingContext(ctx, metadata.Pairs("proxyfrom", "127.0.0.1")) - mode, backends, err = suite.router.Director(ctxProxyFrom, "/service.Service/method") - suite.Assert().Equal(proxy.One2One, mode) - suite.Assert().Len(backends, 1) - suite.Assert().Equal("local", backends[0].(*mockBackend).target) - suite.Assert().NoError(err) - - ctxNoTargets := metadata.NewIncomingContext(ctx, metadata.Pairs(":authority", "127.0.0.1")) - mode, backends, err = suite.router.Director(ctxNoTargets, "/service.Service/method") - suite.Assert().Equal(proxy.One2One, mode) - suite.Assert().Len(backends, 1) - suite.Assert().Equal("local", backends[0].(*mockBackend).target) - suite.Assert().NoError(err) -} - -func TestDirectorSuite(t *testing.T) { - suite.Run(t, new(DirectorSuite)) -} diff --git a/internal/app/routerd/pkg/director/mocks_test.go b/internal/app/routerd/pkg/director/mocks_test.go deleted file mode 100644 index a5cf9640b5..0000000000 --- a/internal/app/routerd/pkg/director/mocks_test.go +++ /dev/null @@ -1,31 +0,0 @@ -// 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 director_test - -import ( - "context" - - "google.golang.org/grpc" -) - -type mockBackend struct { - target string -} - -func (m *mockBackend) String() string { - return m.target -} - -func (m *mockBackend) GetConnection(ctx context.Context) (context.Context, *grpc.ClientConn, error) { - return ctx, nil, nil -} - -func (m *mockBackend) AppendInfo(streaming bool, resp []byte) ([]byte, error) { - return resp, nil -} - -func (m *mockBackend) BuildError(streaming bool, err error) ([]byte, error) { - return nil, nil -} diff --git a/internal/app/timed/main.go b/internal/app/timed/main.go index e486cfcb00..65a4e55240 100644 --- a/internal/app/timed/main.go +++ b/internal/app/timed/main.go @@ -16,15 +16,6 @@ import ( "github.com/talos-systems/talos/pkg/startup" ) -// https://access.redhat.com/solutions/39194 -// Using the above as reference for setting min/max. -const ( - // TODO: Once we get naming sorted we need to apply - // for a project specific address - // https://manage.ntppool.org/manage/vendor - DefaultServer = "pool.ntp.org" -) - // Main is the entrypoint into timed. // // New instantiates a new ntp instance against a given server @@ -38,8 +29,6 @@ func Main() { log.Fatalf("startup: %v", err) } - server := DefaultServer - config, err := configloader.NewFromStdin() if err != nil { log.Fatal(err) @@ -47,10 +36,12 @@ func Main() { // Check if ntp servers are defined // Support for only a single time server currently - if len(config.Machine().Time().Servers()) >= 1 { - server = config.Machine().Time().Servers()[0] + if len(config.Machine().Time().Servers()) == 0 { + log.Fatal("no time servers configured") } + server := config.Machine().Time().Servers()[0] + n, err := ntp.NewNTPClient( ntp.WithServer(server), ) diff --git a/internal/app/timed/pkg/reg/reg.go b/internal/app/timed/pkg/reg/reg.go index 39e49d9e74..4f542482a3 100644 --- a/internal/app/timed/pkg/reg/reg.go +++ b/internal/app/timed/pkg/reg/reg.go @@ -11,18 +11,15 @@ import ( "github.com/golang/protobuf/ptypes/empty" "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/timestamppb" "github.com/talos-systems/talos/internal/app/timed/pkg/ntp" healthapi "github.com/talos-systems/talos/pkg/machinery/api/health" - timeapi "github.com/talos-systems/talos/pkg/machinery/api/time" ) // Registrator is the concrete type that implements the factory.Registrator and -// healthapi.HealthServer and timeapi.TimeServiceServer interfaces. +// healthapi.HealthServer interfaces. type Registrator struct { healthapi.UnimplementedHealthServer - timeapi.UnimplementedTimeServiceServer Timed *ntp.NTP } @@ -38,51 +35,9 @@ func NewRegistrator(n *ntp.NTP) *Registrator { // //nolint:interfacer func (r *Registrator) Register(s *grpc.Server) { - timeapi.RegisterTimeServiceServer(s, r) healthapi.RegisterHealthServer(s, r) } -// Time issues a query to the configured ntp server and displays the results. -func (r *Registrator) Time(ctx context.Context, in *empty.Empty) (reply *timeapi.TimeResponse, err error) { - reply = &timeapi.TimeResponse{} - - rt, err := r.Timed.Query(ctx) - if err != nil { - return reply, err - } - - return genProtobufTimeResponse(r.Timed.GetTime(), rt.Time, r.Timed.Server) -} - -// TimeCheck issues a query to the specified ntp server and displays the results. -func (r *Registrator) TimeCheck(ctx context.Context, in *timeapi.TimeRequest) (reply *timeapi.TimeResponse, err error) { - reply = &timeapi.TimeResponse{} - - tc, err := ntp.NewNTPClient(ntp.WithServer(in.Server)) - if err != nil { - return reply, err - } - - rt, err := tc.Query(ctx) - if err != nil { - return reply, err - } - - return genProtobufTimeResponse(tc.GetTime(), rt.Time, in.Server) -} - -func genProtobufTimeResponse(local, remote time.Time, server string) (*timeapi.TimeResponse, error) { - return &timeapi.TimeResponse{ - Messages: []*timeapi.Time{ - { - Server: server, - Localtime: timestamppb.New(local), - Remotetime: timestamppb.New(remote), - }, - }, - }, nil -} - // Check implements the Health api and provides visibilty into the state of timed. func (r *Registrator) Check(ctx context.Context, in *empty.Empty) (reply *healthapi.HealthCheckResponse, err error) { reply = &healthapi.HealthCheckResponse{ diff --git a/internal/integration/cli/services.go b/internal/integration/cli/services.go index 6bec780496..0b1816cb35 100644 --- a/internal/integration/cli/services.go +++ b/internal/integration/cli/services.go @@ -26,7 +26,6 @@ func (suite *ServicesSuite) SuiteName() string { func (suite *ServicesSuite) TestList() { suite.RunCLI([]string{"services", "--nodes", suite.RandomDiscoveredNode()}, base.StdoutShouldMatch(regexp.MustCompile(`STATE`)), - base.StdoutShouldMatch(regexp.MustCompile(`routerd`)), base.StdoutShouldMatch(regexp.MustCompile(`apid`)), ) } @@ -38,12 +37,6 @@ func (suite *ServicesSuite) TestStatus() { base.StdoutShouldMatch(regexp.MustCompile(`apid`)), base.StdoutShouldMatch(regexp.MustCompile(`\[Running\]`)), ) - - suite.RunCLI([]string{"service", "routerd", "status", "--nodes", suite.RandomDiscoveredNode()}, - base.StdoutShouldMatch(regexp.MustCompile(`STATE`)), - base.StdoutShouldMatch(regexp.MustCompile(`routerd`)), - base.StdoutShouldMatch(regexp.MustCompile(`\[Running\]`)), - ) } func init() { diff --git a/internal/integration/cli/stats.go b/internal/integration/cli/stats.go index 7044cf9705..03c35150e2 100644 --- a/internal/integration/cli/stats.go +++ b/internal/integration/cli/stats.go @@ -27,7 +27,7 @@ func (suite *StatsSuite) SuiteName() string { func (suite *StatsSuite) TestContainerd() { suite.RunCLI([]string{"stats", "--nodes", suite.RandomDiscoveredNode()}, base.StdoutShouldMatch(regexp.MustCompile(`CPU`)), - base.StdoutShouldMatch(regexp.MustCompile(`routerd`)), + base.StdoutShouldMatch(regexp.MustCompile(`apid`)), ) } diff --git a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go index b08e69b774..30b385ac9b 100644 --- a/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go +++ b/pkg/machinery/config/types/v1alpha1/v1alpha1_provider.go @@ -1196,6 +1196,10 @@ func (t *TimeConfig) Disabled() bool { // Servers implements the config.Provider interface. func (t *TimeConfig) Servers() []string { + if len(t.TimeServers) == 0 { + return []string{constants.DefaultNTPServer} + } + return t.TimeServers } diff --git a/pkg/machinery/constants/constants.go b/pkg/machinery/constants/constants.go index eb2d50c097..36764fb254 100644 --- a/pkg/machinery/constants/constants.go +++ b/pkg/machinery/constants/constants.go @@ -312,9 +312,6 @@ const ( // NetworkSocketPath is the path to file socket of network API. NetworkSocketPath = SystemRunPath + "/networkd/networkd.sock" - // RouterdSocketPath is the path to file socket of router API. - RouterdSocketPath = SystemRunPath + "/routerd/routerd.sock" - // ArchVariable is replaced automatically by the target cluster arch. ArchVariable = "${ARCH}" @@ -401,6 +398,12 @@ const ( // AnnotationStaticPodConfigVersion is the annotation key for the static pod config version. AnnotationStaticPodConfigVersion = "talos.dev/config-version" + + // DefaultNTPServer is the NTP server to use if not configured explicitly. + // + // TODO: Once we get naming sorted we need to apply for a project specific address + // https://manage.ntppool.org/manage/vendor + DefaultNTPServer = "pool.ntp.org" ) // See https://linux.die.net/man/3/klogctl diff --git a/website/content/docs/v0.10/Learn More/components.md b/website/content/docs/v0.10/Learn More/components.md index a67a8d637e..5bb13a4727 100644 --- a/website/content/docs/v0.10/Learn More/components.md +++ b/website/content/docs/v0.10/Learn More/components.md @@ -9,13 +9,12 @@ In this section, we discuss the various components that underpin Talos. | Component | Description | | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| apid | When interacting with Talos, the gRPC API endpoint you interact with directly is provided by `apid`. `apid` acts as the gateway for all component interactions and forwards the requests to `routerd`. | +| apid | When interacting with Talos, the gRPC API endpoint you interact with directly is provided by `apid`. `apid` acts as the gateway for all component interactions and forwards the requests to `machined`. | | containerd | An industry-standard container runtime with an emphasis on simplicity, robustness, and portability. To learn more, see the [containerd website](https://containerd.io). | | machined | Talos replacement for the traditional Linux init-process. Specially designed to run Kubernetes and does not allow starting arbitrary user services. | | networkd | Handles all of the host level network configuration. The configuration is defined under the `networking` key | | timed | Handles the host time synchronization by acting as a NTP-client. | | kernel | The Linux kernel included with Talos is configured according to the recommendations outlined in the [Kernel Self Protection Project](http://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project). | -| routerd | Responsible for routing an incoming API request from `apid` to the appropriate backend (e.g. `networkd`, `machined` and `timed`). | | trustd | To run and operate a Kubernetes cluster, a certain level of trust is required. Based on the concept of a 'Root of Trust', `trustd` is a simple daemon responsible for establishing trust within the system. | | udevd | Implementation of `eudev` into `machined`. `eudev` is Gentoo's fork of udev, systemd's device file manager for the Linux kernel. It manages device nodes in /dev and handles all user space actions when adding or removing devices. To learn more, see the [Gentoo Wiki](https://wiki.gentoo.org/wiki/Eudev). |