Add depot, attendant, jetfire, optimus, ota services with kustomize overlays

This commit is contained in:
Chris Rai
2026-01-31 15:35:07 -05:00
parent a0ec642ca1
commit 9a5cb2f547
404 changed files with 38817 additions and 16 deletions

View File

@@ -0,0 +1,130 @@
package utils
import (
"github.com/fiskerinc/cloud-services/pkg/clickhouse"
"github.com/fiskerinc/cloud-services/pkg/logger"
)
// NewVehicleMessageFilters constructs a new VehicleMessageFilters
// should only be called once during lifetime of a service
func NewVehicleMessageFilters() *VehicleMessageFilters {
return &VehicleMessageFilters{
filters: make(map[string]*MessageFilters),
}
}
// VehicleMessageFilters maps vehicle vins to their set of filters
type VehicleMessageFilters struct {
filters map[string]*MessageFilters
}
// NewFiltersForVehicle adds a new vehicle to the sets of filters
func (v *VehicleMessageFilters) NewFiltersForVehicle(client clickhouse.ClientInterface, vin string) *MessageFilters {
var f *MessageFilters
d, ok := v.filters[DEFAULT]
if ok {
f = NewMessageFiltersFromDefault(d)
} else {
f = NewMessageFilters()
}
cFilters, err := client.RetrieveFiltersForVehicle(vin)
if err != nil {
logger.Warn().Err(err).Send()
}
f.PopulateFromClickhouse(cFilters)
v.filters[vin] = f
return f
}
// GetFiltersForVehicle obtains filters for a vehicle
func (v *VehicleMessageFilters) GetFiltersForVehicle(client clickhouse.ClientInterface, vin string) *MessageFilters {
var f *MessageFilters
var ok bool
if f, ok = v.filters[vin]; !ok {
f = v.NewFiltersForVehicle(client, vin)
}
return f
}
// SetDefaultFilters sets the default filters for vehicles to use as a base
func (v *VehicleMessageFilters) SetDefaultFilters(filters []clickhouse.CANFilterSchema) {
d := NewMessageFilters()
d.PopulateFromClickhouse(filters)
v.filters[DEFAULT] = d
}
// NewMessageFilters is a convenience function to setup a map of filters
func NewMessageFilters() *MessageFilters {
return &MessageFilters{
filters: make(map[int]*MessageFilter),
}
}
// NewMessageFiltersFromDefault copies default filters to a new struct
func NewMessageFiltersFromDefault(d *MessageFilters) *MessageFilters {
f := NewMessageFilters()
for id, key := range d.filters {
f.SetMessageFilter(id, key.cycle)
}
return f
}
// MessageFilters maps CAN IDs to MessageFilter structs
type MessageFilters struct {
filters map[int]*MessageFilter
}
// SetMessageFilter adds an ID to the filter maps
// cycle expects an integer in ms
func (m *MessageFilters) SetMessageFilter(id int, cycle int) {
m.filters[id] = &MessageFilter{cycle: cycle}
}
// PopulateFromClickhouse is a helper method to populate
// MessageFilters with filters queried from clickhouse
func (m *MessageFilters) PopulateFromClickhouse(filters []clickhouse.CANFilterSchema) {
for _, filter := range filters {
m.SetMessageFilter(int(filter.ID), int(filter.Period)*1000)
}
}
// AllowMessage verifies if a message can pass through based on timestamp
// if the message passes through calculates the timestamp for the next
// possible message of that ID
// if MessageFilter.Cycle is 0 it means the message should not pass through
// if MessageFilter.Cycle is -1 it means the message should always pass through
// if no filter is present for the ID - it will always pass through (BLACKLIST)
func (m *MessageFilters) AllowMessage(id int, timestamp int) bool {
filter, ok := m.filters[id]
if !ok {
return true
}
if filter.cycle == 0 {
return false
} else if filter.cycle == -1 {
return true
}
if timestamp > filter.next {
filter.next = timestamp + filter.cycle
return true
}
return false
}
// MessageFilter keeps track of message cycle rules and the next possible timestamp for a message
// cycle and next are integers in microseconds (CANFilter data that comes in is in microseconds)
type MessageFilter struct {
cycle, next int
}
const DEFAULT = "DEFAULT"

View File

@@ -0,0 +1,113 @@
package utils_test
import (
"github.com/fiskerinc/cloud-services/services/optimus/utils"
"testing"
"github.com/fiskerinc/cloud-services/pkg/clickhouse"
"github.com/fiskerinc/cloud-services/pkg/testhelper"
)
func TestNewVehicleMessageFilters(t *testing.T) {
_ = utils.NewVehicleMessageFilters()
}
func TestNewFiltersForVehicle(t *testing.T) {
conn := &clickhouse.MockConn{ExpectedResult: testFilters}
client := clickhouse.NewMockClient(conn)
vehicleFilters := utils.NewVehicleMessageFilters()
filters := vehicleFilters.NewFiltersForVehicle(client, "TESTVIN123")
if filters == nil {
t.Errorf(testhelper.TestErrorTemplate, "TestNewFiltersForVehicle", "*MessageFilters", filters)
}
}
func TestGetFiltersForVehicle(t *testing.T) {
conn := &clickhouse.MockConn{ExpectedResult: testFilters}
client := clickhouse.NewMockClient(conn)
vehicleFilters := utils.NewVehicleMessageFilters()
filters := vehicleFilters.GetFiltersForVehicle(client, "TESTVIN123")
if filters == nil {
t.Errorf(testhelper.TestErrorTemplate, "TestGetFiltersForVehicle", "*MessageFilters", filters)
}
}
func TestSetDefaultFilters(t *testing.T) {
vehicleFilters := utils.NewVehicleMessageFilters()
vehicleFilters.SetDefaultFilters(testFilters)
}
func TestNewMessageFilters(t *testing.T) {
_ = utils.NewMessageFilters()
}
func TestNewMessageFiltersFromDefault(t *testing.T) {
d := utils.NewMessageFilters()
d.SetMessageFilter(1, 1)
f := utils.NewMessageFiltersFromDefault(d)
if f.AllowMessage(1, 1) != true {
t.Errorf(testhelper.TestErrorTemplate, "TestNewMessageFiltersFromDefault", true, false)
}
}
func TestSetMessageFilter(t *testing.T) {
f := utils.NewMessageFilters()
f.SetMessageFilter(2, 2)
}
func TestPopulateFromClickhouse(t *testing.T) {
f := utils.NewMessageFilters()
f.PopulateFromClickhouse(testFilters)
if f.AllowMessage(1, 1) != true {
t.Errorf(testhelper.TestErrorTemplate, "TestPopulateFromClickhouse", true, false)
}
}
func TestAllowMessage(t *testing.T) {
f := utils.NewMessageFilters()
f.PopulateFromClickhouse(testFilters)
if f.AllowMessage(1, 1) != true {
t.Errorf(testhelper.TestErrorTemplate, "TestAllowMessage", true, false)
}
if f.AllowMessage(3, 2) != true {
t.Errorf(testhelper.TestErrorTemplate, "TestAllowMessage", true, false)
}
if f.AllowMessage(3, 1) == true {
t.Errorf(testhelper.TestErrorTemplate, "TestAllowMessage", false, true)
}
if f.AllowMessage(5, 1) == true {
t.Errorf(testhelper.TestErrorTemplate, "TestAllowMessage", false, true)
}
if f.AllowMessage(10, 1) != true {
t.Errorf(testhelper.TestErrorTemplate, "TestAllowMessage", true, false)
}
}
var testFilters = []clickhouse.CANFilterSchema{
{
ID: 1,
Period: 2,
},
{
ID: 3,
Period: 4,
},
{
ID: 5,
Period: 0,
},
{
ID: 10,
Period: -1,
},
}