mirror of
https://github.com/siderolabs/talos.git
synced 2025-09-17 11:51:12 +02:00
Bump all dependencies, update `grpc.WithInsecure()` which is deprecated now. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
194 lines
4.3 KiB
Go
194 lines
4.3 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 runtime
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/AlekSi/pointer"
|
|
"github.com/cosi-project/runtime/pkg/controller"
|
|
"github.com/cosi-project/runtime/pkg/resource"
|
|
"github.com/cosi-project/runtime/pkg/state"
|
|
"github.com/rs/xid"
|
|
"github.com/talos-systems/go-procfs/procfs"
|
|
"github.com/talos-systems/siderolink/api/events"
|
|
"go.uber.org/atomic"
|
|
"go.uber.org/zap"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"google.golang.org/protobuf/types/known/anypb"
|
|
|
|
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
|
"github.com/talos-systems/talos/pkg/machinery/constants"
|
|
"github.com/talos-systems/talos/pkg/machinery/resources/network"
|
|
)
|
|
|
|
// EventsSinkController watches events and forwards them to the events sink server
|
|
// if it's configured.
|
|
type EventsSinkController struct {
|
|
V1Alpha1Events runtime.Watcher
|
|
Cmdline *procfs.Cmdline
|
|
Drainer *runtime.Drainer
|
|
|
|
drainSub *runtime.DrainSubscription
|
|
drain bool
|
|
backlog atomic.Int32
|
|
eventID xid.ID
|
|
}
|
|
|
|
// Name implements controller.Controller interface.
|
|
func (ctrl *EventsSinkController) Name() string {
|
|
return "v1alpha1.EventsSinkController"
|
|
}
|
|
|
|
// Inputs implements controller.Controller interface.
|
|
func (ctrl *EventsSinkController) Inputs() []controller.Input {
|
|
return []controller.Input{
|
|
{
|
|
Namespace: network.NamespaceName,
|
|
Type: network.StatusType,
|
|
ID: pointer.ToString(network.StatusID),
|
|
Kind: controller.InputWeak,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Outputs implements controller.Controller interface.
|
|
func (ctrl *EventsSinkController) Outputs() []controller.Output {
|
|
return nil
|
|
}
|
|
|
|
// Run implements controller.Controller interface.
|
|
//
|
|
//nolint:gocyclo
|
|
func (ctrl *EventsSinkController) Run(ctx context.Context, r controller.Runtime, logger *zap.Logger) (err error) {
|
|
if ctrl.Cmdline == nil || ctrl.Cmdline.Get(constants.KernelParamEventsSink).First() == nil {
|
|
return nil
|
|
}
|
|
|
|
if ctrl.drainSub == nil {
|
|
ctrl.backlog.Store(-1)
|
|
ctrl.drainSub = ctrl.Drainer.Subscribe()
|
|
}
|
|
|
|
defer func() {
|
|
if ctrl.backlog.Load() == 0 {
|
|
ctrl.drainSub.Cancel()
|
|
}
|
|
}()
|
|
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case <-r.EventCh():
|
|
}
|
|
|
|
var netStatus resource.Resource
|
|
|
|
netStatus, err = r.Get(ctx, resource.NewMetadata(network.NamespaceName, network.StatusType, network.StatusID, resource.VersionUndefined))
|
|
if err != nil {
|
|
if state.IsNotFoundError(err) {
|
|
// no network state yet
|
|
continue
|
|
}
|
|
|
|
return fmt.Errorf("error reading network status: %w", err)
|
|
}
|
|
|
|
if !netStatus.(*network.Status).TypedSpec().AddressReady {
|
|
// wait for address
|
|
continue
|
|
}
|
|
|
|
break
|
|
}
|
|
|
|
errCh := make(chan error)
|
|
|
|
sink := ctrl.Cmdline.Get(constants.KernelParamEventsSink).First()
|
|
|
|
conn, err := grpc.DialContext(ctx, *sink, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
defer conn.Close() //nolint:errcheck
|
|
|
|
client := events.NewEventSinkServiceClient(conn)
|
|
|
|
opts := []runtime.WatchOptionFunc{}
|
|
if ctrl.eventID.IsNil() {
|
|
opts = append(opts, runtime.WithTailEvents(-1))
|
|
} else {
|
|
opts = append(opts, runtime.WithTailID(ctrl.eventID))
|
|
}
|
|
|
|
if err = ctrl.V1Alpha1Events.Watch(func(eventCh <-chan runtime.EventInfo) {
|
|
errCh <- ctrl.handleEvents(ctx, eventCh, client)
|
|
}, opts...); err != nil {
|
|
return err
|
|
}
|
|
|
|
err = <-errCh
|
|
|
|
return err
|
|
}
|
|
|
|
//nolint:gocyclo
|
|
func (ctrl *EventsSinkController) handleEvents(ctx context.Context, eventCh <-chan runtime.EventInfo, client events.EventSinkServiceClient) error {
|
|
for {
|
|
var (
|
|
event runtime.EventInfo
|
|
ok bool
|
|
data *anypb.Any
|
|
err error
|
|
)
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case event, ok = <-eventCh:
|
|
if !ok {
|
|
return nil
|
|
}
|
|
case <-ctrl.drainSub.EventCh():
|
|
backlog := ctrl.backlog.Load()
|
|
|
|
if backlog == 0 {
|
|
return nil
|
|
}
|
|
|
|
ctrl.drain = true
|
|
|
|
continue
|
|
}
|
|
|
|
ctrl.backlog.Store(int32(event.Backlog))
|
|
|
|
data, err = anypb.New(event.Payload)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req := &events.EventRequest{
|
|
Id: event.ID.String(),
|
|
Data: data,
|
|
}
|
|
|
|
_, err = client.Publish(ctx, req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctrl.eventID = event.ID
|
|
|
|
if ctrl.drain && event.Backlog == 0 {
|
|
return nil
|
|
}
|
|
}
|
|
}
|