Skip to content

Commit

Permalink
Merge branch 'main' into denopink/patch/allow-fx-to-rollback-after-st…
Browse files Browse the repository at this point in the history
…art-panic
  • Loading branch information
denopink committed May 16, 2024
2 parents dff0a65 + 232dd3a commit 53c1e6f
Show file tree
Hide file tree
Showing 20 changed files with 383 additions and 71 deletions.
10 changes: 10 additions & 0 deletions cmd/xmidt-agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/xmidt-org/sallust"
"github.com/xmidt-org/wrp-go/v3"
"github.com/xmidt-org/xmidt-agent/internal/configuration"
"github.com/xmidt-org/xmidt-agent/internal/net"
"go.uber.org/zap/zapcore"
"gopkg.in/dealancer/validate.v2"
)
Expand All @@ -41,6 +42,7 @@ type Config struct {
Externals []configuration.External
XmidtAgentCrud XmidtAgentCrud
Metadata Metadata
NetworkService NetworkService
}

type QOS struct {
Expand Down Expand Up @@ -214,6 +216,11 @@ type Metadata struct {
Fields []string
}

type NetworkService struct {
// list of allowed network interfaces to connect to xmidt in priority order, first is highest
AllowedInterfaces map[string]net.AllowedInterface
}

// Collect and process the configuration files and env vars and
// produce a configuration object.
func provideConfig(cli *CLI) (*goschtalt.Config, error) {
Expand Down Expand Up @@ -399,4 +406,7 @@ var defaultConfig = Config{
Metadata: Metadata{
Fields: []string{"fw-name", "hw-model", "hw-manufacturer", "hw-serial-number", "hw-last-reboot-reason", "webpa-protocol", "boot-time", "boot-time-retry-wait", "webpa-interface-used", "interfaces-available"},
},
NetworkService: NetworkService{
AllowedInterfaces: map[string]net.AllowedInterface{"erouter0": {Priority: 1, Enabled: true}, "eroutev0": {Priority: 2, Enabled: true}, "br-home": {Priority: 3, Enabled: true}, "brrwan": {Priority: 4, Enabled: true}, "vdsl0": {Priority: 5, Enabled: true}, "wwan0": {Priority: 6, Enabled: true}, "wlan0": {Priority: 7, Enabled: true}, "eth0": {Priority: 8, Enabled: true}, "qmapmux0.127": {Priority: 9, Enabled: true}, "cm0": {Priority: 10, Enabled: true}},
},
}
15 changes: 11 additions & 4 deletions cmd/xmidt-agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/xmidt-org/sallust"
"github.com/xmidt-org/xmidt-agent/internal/credentials"
"github.com/xmidt-org/xmidt-agent/internal/loglevel"
"github.com/xmidt-org/xmidt-agent/internal/metadata"
"github.com/xmidt-org/xmidt-agent/internal/websocket"
"github.com/xmidt-org/xmidt-agent/internal/wrphandlers/qos"

Expand Down Expand Up @@ -97,11 +98,13 @@ func xmidtAgent(args []string) (*fx.App, error) {
goschtalt.UnmarshalFunc[MockTr181]("mock_tr_181"),
goschtalt.UnmarshalFunc[Pubsub]("pubsub"),
goschtalt.UnmarshalFunc[Metadata]("metadata"),
goschtalt.UnmarshalFunc[NetworkService]("network_service"),
goschtalt.UnmarshalFunc[QOS]("qos"),

provideNetworkService,
provideMetadataProvider,
loglevel.New,
metadata.NewInterfaceUsedProvider,
),

fsProvide(),
Expand Down Expand Up @@ -230,10 +233,14 @@ func onStart(cred *credentials.Credentials, ws *websocket.Websocket, qos *qos.Ha
return err
}

ctx, cancel := context.WithTimeout(ctx, waitUntilFetched)
defer cancel()
// blocks until an attempt to fetch the credentials has been made or the context is canceled
cred.WaitUntilFetched(ctx)
// Allow operations where no credentials are desired (cred will be nil).
if cred != nil {
ctx, cancel := context.WithTimeout(ctx, waitUntilFetched)
defer cancel()
// blocks until an attempt to fetch the credentials has been made or the context is canceled
cred.WaitUntilFetched(ctx)
}

ws.Start()
qos.Start()

Expand Down
2 changes: 2 additions & 0 deletions cmd/xmidt-agent/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type metadataIn struct {
ID Identity
Ops OperationalState
Metadata Metadata
InterfaceUsed *metadata.InterfaceUsedProvider
}

func provideMetadataProvider(in metadataIn) (*metadata.MetadataProvider, error) {
Expand All @@ -32,6 +33,7 @@ func provideMetadataProvider(in metadataIn) (*metadata.MetadataProvider, error)
metadata.XmidtProtocolOpt(xmidtProtocol),
metadata.BootTimeOpt(in.Ops.BootTime.String()),
metadata.BootRetryWaitOpt(time.Second), // should this be configured?
metadata.InterfaceUsedOpt(in.InterfaceUsed),
}
return metadata.New(opts...)
}
12 changes: 8 additions & 4 deletions cmd/xmidt-agent/network_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ package main

import (
"github.com/xmidt-org/xmidt-agent/internal/net"
"go.uber.org/fx"
)

func provideNetworkService() net.NetworkServicer {
return &net.NetworkService{
N: net.NewNetworkWrapper(),
}
type networkServiceIn struct {
fx.In
NetworkService NetworkService
}

func provideNetworkService(in networkServiceIn) net.NetworkServicer {
return net.New(net.NewNetworkWrapper(), in.NetworkService.AllowedInterfaces)
}
79 changes: 48 additions & 31 deletions cmd/xmidt-agent/wrphandlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func provideWRPHandlers() fx.Option {
provideCrudHandler,
provideQOSHandler,
provideWSEventorToHandlerAdapter,
provideMockTr181Handler,
),
)
}
Expand Down Expand Up @@ -151,9 +152,8 @@ type pubsubIn struct {

// Configuration
// Note, DeviceID and PartnerID is pulled from the Identity configuration
Identity Identity
Pubsub Pubsub
MockTr181 MockTr181
Identity Identity
Pubsub Pubsub

// wrphandlers
Egress *qos.Handler
Expand All @@ -162,21 +162,17 @@ type pubsubIn struct {
type pubsubOut struct {
fx.Out

PubSub *pubsub.PubSub
Cancels []func() `group:"cancels,flatten"`
PubSub *pubsub.PubSub
Cancel func() `group:"cancels"`
}

func providePubSubHandler(in pubsubIn) (pubsubOut, error) {
var (
egress, mocktr pubsub.CancelFunc
cancels []func()
)
var egress pubsub.CancelFunc

opts := []pubsub.Option{
pubsub.WithPublishTimeout(in.Pubsub.PublishTimeout),
pubsub.WithEgressHandler(in.Egress, &egress),
}

ps, err := pubsub.New(
in.Identity.DeviceID,
opts...,
Expand All @@ -185,27 +181,48 @@ func providePubSubHandler(in pubsubIn) (pubsubOut, error) {
return pubsubOut{}, errors.Join(ErrWRPHandlerConfig, err)
}

cancels = append(cancels, egress)
if in.MockTr181.Enabled {
mockDefaults := []mocktr181.Option{
mocktr181.FilePath(in.MockTr181.FilePath),
mocktr181.Enabled(in.MockTr181.Enabled),
}
mocktr181Handler, err := mocktr181.New(ps, string(in.Identity.DeviceID), mockDefaults...)
if err != nil {
return pubsubOut{}, errors.Join(ErrWRPHandlerConfig, err)
}

mocktr, err = ps.SubscribeService(in.MockTr181.ServiceName, mocktr181Handler)
if err != nil {
return pubsubOut{}, errors.Join(ErrWRPHandlerConfig, err)
}

cancels = append(cancels, mocktr)
}

return pubsubOut{
PubSub: ps,
Cancels: cancels,
PubSub: ps,
Cancel: egress,
}, err
}

type mockTr181In struct {
fx.In

// Configuration
// Note, DeviceID and PartnerID is pulled from the Identity configuration
Identity Identity
MockTr181 MockTr181

PubSub *pubsub.PubSub
}

type mockTr181Out struct {
fx.Out
Cancel func() `group:"cancels"`
}

func provideMockTr181Handler(in mockTr181In) (mockTr181Out, error) {
if !in.MockTr181.Enabled {
return mockTr181Out{}, nil
}

mockDefaults := []mocktr181.Option{
mocktr181.FilePath(in.MockTr181.FilePath),
mocktr181.Enabled(in.MockTr181.Enabled),
}
mocktr181Handler, err := mocktr181.New(in.PubSub, string(in.Identity.DeviceID), mockDefaults...)
if err != nil {
return mockTr181Out{}, errors.Join(ErrWRPHandlerConfig, err)
}

mocktr, err := in.PubSub.SubscribeService(in.MockTr181.ServiceName, mocktr181Handler)
if err != nil {
return mockTr181Out{}, errors.Join(ErrWRPHandlerConfig, err)
}

return mockTr181Out{
Cancel: mocktr,
}, nil
}
27 changes: 17 additions & 10 deletions cmd/xmidt-agent/ws.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ var (
type wsIn struct {
fx.In
// Note, DeviceID is pulled from the Identity configuration
Identity Identity
Logger *zap.Logger
CLI *CLI
JWTXT *jwtxt.Instructions
Cred *credentials.Credentials
Metadata *metadata.MetadataProvider
Websocket Websocket
Identity Identity
Logger *zap.Logger
CLI *CLI
JWTXT *jwtxt.Instructions
Cred *credentials.Credentials
Metadata *metadata.MetadataProvider
InterfaceUsed *metadata.InterfaceUsedProvider
Websocket Websocket
}

type wsOut struct {
Expand Down Expand Up @@ -63,8 +64,14 @@ func provideWS(in wsIn) (wsOut, error) {
return wsOut{}, err
}

var opts []websocket.Option
// Allow operations where no credentials are desired (in.Cred will be nil).
if in.Cred != nil {
opts = append(opts, websocket.CredentialsDecorator(in.Cred.Decorate))
}

// Configuration options
opts := []websocket.Option{
opts = append(opts,
websocket.DeviceID(in.Identity.DeviceID),
websocket.FetchURLTimeout(in.Websocket.FetchURLTimeout),
websocket.FetchURL(
Expand All @@ -76,15 +83,15 @@ func provideWS(in wsIn) (wsOut, error) {
websocket.KeepAliveInterval(in.Websocket.KeepAliveInterval),
websocket.HTTPClient(client),
websocket.MaxMessageBytes(in.Websocket.MaxMessageBytes),
websocket.CredentialsDecorator(in.Cred.Decorate),
websocket.ConveyDecorator(in.Metadata.Decorate),
websocket.AdditionalHeaders(in.Websocket.AdditionalHeaders),
websocket.NowFunc(time.Now),
websocket.WithIPv6(!in.Websocket.DisableV6),
websocket.WithIPv4(!in.Websocket.DisableV4),
websocket.Once(in.Websocket.Once),
websocket.RetryPolicy(in.Websocket.RetryPolicy),
}
websocket.InterfaceUsedProvider(in.InterfaceUsed),
)

// Listener options
var (
Expand Down
24 changes: 24 additions & 0 deletions internal/metadata/interface_used.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-FileCopyrightText: 2024 Comcast Cable Communications Management, LLC
// SPDX-License-Identifier: Apache-2.0

package metadata

const DefaultInterface = "erouter0"

type InterfaceUsedProvider struct {
interfaceUsed string
}

func NewInterfaceUsedProvider() (*InterfaceUsedProvider, error) {
return &InterfaceUsedProvider{
interfaceUsed: DefaultInterface,
}, nil
}

func (i *InterfaceUsedProvider) GetInterfaceUsed() string {
return i.interfaceUsed
}

func (i *InterfaceUsedProvider) SetInterfaceUsed(interfaceUsed string) {
i.interfaceUsed = interfaceUsed
}
5 changes: 4 additions & 1 deletion internal/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type MetadataProvider struct {
protocol string
bootTime string
bootTimeRetryDelay string
interfaceUsed *InterfaceUsedProvider
}

func New(opts ...Option) (*MetadataProvider, error) {
Expand Down Expand Up @@ -88,10 +89,12 @@ func (c *MetadataProvider) GetMetadata() map[string]interface{} {
header[field] = c.bootTime
case BootTimeRetryDelay:
header[field] = c.bootTimeRetryDelay
case InterfaceUsed:
header[field] = c.interfaceUsed.GetInterfaceUsed()
case InterfacesAvailable: // what if we can't get interfaces available?
names, err := c.networkService.GetInterfaceNames()
if err != nil {
// The err itself is ignored.
// The err itself is ignored. Log this somewhere tho
continue
}
header[field] = strings.Join(names, ",")
Expand Down
10 changes: 10 additions & 0 deletions internal/metadata/metadata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package metadata

import (
"net"
"net/http"
"testing"
"time"
Expand All @@ -19,6 +20,11 @@ type mockNetworkService struct {

func newMockNetworkService() *mockNetworkService { return &mockNetworkService{} }

func (m *mockNetworkService) GetInterfaces() ([]net.Interface, error) {
args := m.Called()
return args.Get(0).([]net.Interface), args.Error(1)
}

func (m *mockNetworkService) GetInterfaceNames() ([]string, error) {
args := m.Called()
return args.Get(0).([]string), args.Error(1)
Expand All @@ -33,6 +39,7 @@ type ConveySuite struct {
func (suite *ConveySuite) SetupTest() {
mockNetworkService := newMockNetworkService()
suite.mockNetworkService = mockNetworkService
interfaceUsed, _ := NewInterfaceUsedProvider()

opts := []Option{
NetworkServiceOpt(mockNetworkService),
Expand All @@ -45,6 +52,7 @@ func (suite *ConveySuite) SetupTest() {
XmidtProtocolOpt("some-protocol"),
BootTimeOpt("1111111111"),
BootRetryWaitOpt(time.Second),
InterfaceUsedOpt(interfaceUsed),
}

conveyHeaderProvider, err := New(opts...)
Expand All @@ -71,6 +79,7 @@ func (suite *ConveySuite) TestGetConveyHeader() {
suite.Equal("1111111111", header["boot-time"])
suite.Equal("1", header["boot-time-retry-wait"])
suite.Equal("erouter0,eth0", header["interfaces-available"])
suite.Equal("erouter0", header["webpa-interface-used"])
}

func (suite *ConveySuite) TestGetConveyHeaderSubsetFields() {
Expand All @@ -88,6 +97,7 @@ func (suite *ConveySuite) TestGetConveyHeaderSubsetFields() {
suite.Nil(header["boot-time"])
suite.Nil(header["boot-time-retry-wait"])
suite.Nil(header["interfaces-available"])
suite.Nil(header["webpa-interface-used"])
}

func (suite *ConveySuite) TestDecorate() {
Expand Down
11 changes: 11 additions & 0 deletions internal/metadata/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,14 @@ func BootRetryWaitOpt(bootTimeRetryDelay time.Duration) Option {
return nil
})
}

func InterfaceUsedOpt(interfaceUsed *InterfaceUsedProvider) Option {
return optionFunc(
func(c *MetadataProvider) error {
if interfaceUsed == nil {
return fmt.Errorf("%w: nil interfaceUsed provider", ErrInvalidInput)
}
c.interfaceUsed = interfaceUsed
return nil
})
}
Loading

0 comments on commit 53c1e6f

Please sign in to comment.