Add depot, attendant, jetfire, optimus, ota services with kustomize overlays
This commit is contained in:
336
services/depot/handlers/trex_init.go
Normal file
336
services/depot/handlers/trex_init.go
Normal file
@@ -0,0 +1,336 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/services/depot/services"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/cache"
|
||||
"github.com/fiskerinc/cloud-services/pkg/carcommand"
|
||||
"github.com/fiskerinc/cloud-services/pkg/common"
|
||||
"github.com/fiskerinc/cloud-services/pkg/db/queries"
|
||||
"github.com/fiskerinc/cloud-services/pkg/dbc/state"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
"github.com/fiskerinc/cloud-services/pkg/mongo"
|
||||
"github.com/fiskerinc/cloud-services/pkg/redis"
|
||||
"github.com/fiskerinc/cloud-services/pkg/userconsent"
|
||||
"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
|
||||
"github.com/fiskerinc/cloud-services/pkg/utils"
|
||||
"github.com/fiskerinc/cloud-services/pkg/utils/elptr"
|
||||
"github.com/go-pg/pg/v10"
|
||||
redigo "github.com/gomodule/redigo/redis"
|
||||
"github.com/pkg/errors"
|
||||
mon "go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var errInvalidICCID = errors.New("invalid iccid submitted")
|
||||
var errBlocked = errors.New("unable to connect: car is blocked")
|
||||
var logLevel = envtool.GetEnv("TREX_LOG_LEVEL", common.CriticalLabel)
|
||||
var wakeUpVINS = envtool.GetEnv("WAKE_UP_VINS", "VCF1EBU2XPG001140")
|
||||
var defaultFleet = envtool.GetEnv("DEFAULT_FLEET", "Default-Ocean")
|
||||
|
||||
// id is the vehicles VIN
|
||||
func TRexInit(id string, vMap map[string]string) error {
|
||||
carsDB := services.GetDB().GetCars()
|
||||
blocked, err := insertIfNotExist(id, carsDB)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if blocked {
|
||||
return errBlocked
|
||||
}
|
||||
|
||||
if strings.Contains(wakeUpVINS, id) {
|
||||
go wakeup(id)
|
||||
}
|
||||
|
||||
client := services.RedisClientPool().GetFromPool()
|
||||
defer client.Close()
|
||||
err = addTRexSession(client, id)
|
||||
if err != nil {
|
||||
logger.Warn().Str("id", id).Err(err).Send()
|
||||
}
|
||||
|
||||
m, err := services.GetMongoClient()
|
||||
if err != nil {
|
||||
logger.Warn().Str("id", id).Err(err).Send()
|
||||
} else {
|
||||
msg, err := retrieveTRexSettings(client, m, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Log the config that will be sent to TREX
|
||||
config, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info().Msgf("TREX Config sent for vin %s: \n%s", id, config)
|
||||
|
||||
err = sendTRexSettings(client, id, msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = setTRexVersion(client, id, vMap["version"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = setDBCVersion(client, id, vMap["dbc_version"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = setTRexIP(client, id, vMap["ip"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = addICCID(carsDB, id, vMap["iccid"])
|
||||
if err != nil {
|
||||
logger.Warn().Err(err).Str("VIN", id).Str("ICCID", vMap["iccid"]).Msg("failed to add iccid to car")
|
||||
}
|
||||
|
||||
uMsg, err := getUserConsentData(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = sendTRexUserConsentData(client, id, uMsg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = checkAndRenewCertificate(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAndRenewCertificate(id string) error {
|
||||
logger.Debug().Msg("on trex init: checking TBOX cert for vin " + id)
|
||||
|
||||
cs := services.GetCertService()
|
||||
certNeedsRenewal, err := cs.CheckCertificateNeedsRenewal(id, common.CertTBOX)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if certNeedsRenewal {
|
||||
logger.Debug().Msg("TBOX cert for vin " + id + " is out of date")
|
||||
|
||||
cert, err := cs.RenewCertificate(id, common.CertTBOX)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client := services.RedisClientPool().GetFromPool()
|
||||
defer client.Close()
|
||||
|
||||
err = client.SafeQueueMessage(
|
||||
common.TRex.Key(id),
|
||||
common.Message{
|
||||
Handler: "update_cert",
|
||||
Data: common.UpdateCert{
|
||||
SSLCertBase64: cert.PublicKey,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
logger.Debug().Msg("TBOX cert for vin " + id + " is not out of date")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getUserConsentData(id string) ([]common.UserConsentDataTrexMsg, error) {
|
||||
var ucdToSend = []common.UserConsentDataTrexMsg{}
|
||||
|
||||
resp, err := userconsent.GetUserConsentService().UserConsentByVehicleNumber(id)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New("call to user-consent/byVehicleNumber endpoint returned " + resp.Status)
|
||||
}
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
ucdResult := []common.UserConsentDataResponse{}
|
||||
err = json.Unmarshal(respBody, &ucdResult)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
if len(ucdResult) < 1 {
|
||||
return ucdToSend, nil
|
||||
}
|
||||
|
||||
// only send to TREX the consents that have the userID of the first consent returned
|
||||
var userId = ucdResult[0].UserID
|
||||
for _, ucd := range ucdResult {
|
||||
if ucd.UserID == userId {
|
||||
ucdToSend = append(ucdToSend, common.BuildUserConsentTrexMessage(ucd))
|
||||
}
|
||||
}
|
||||
|
||||
return ucdToSend, nil
|
||||
}
|
||||
|
||||
func sendTRexUserConsentData(r redis.Client, id string, msg []common.UserConsentDataTrexMsg) error {
|
||||
|
||||
if len(msg) > 0 {
|
||||
return r.SafePublishMessage(
|
||||
common.TRex.Key(id),
|
||||
common.Message{
|
||||
Handler: "consent",
|
||||
Data: msg,
|
||||
},
|
||||
)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func insertIfNotExist(id string, carsDB queries.CarsInterface) (bool, error) {
|
||||
car, err := carsDB.SelectByVIN(id)
|
||||
if err == nil && car != nil {
|
||||
return car.Blocked, nil
|
||||
}
|
||||
if errors.Is(err, pg.ErrNoRows) {
|
||||
err = nil
|
||||
|
||||
c, err := utils.ParseVIN(id)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
_, err = carsDB.Insert(c)
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
client, err := services.GetMongoClient()
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
v := &mongo.Vehicle{
|
||||
VIN: id,
|
||||
CANBus: common.CANBus{Enabled: true, DataLogger: true, DTCEnabled: elptr.ElPtr(false)},
|
||||
LogLevel: common.UnmarshalLogLevelString(logLevel),
|
||||
}
|
||||
err = client.GetVehicles().AddVehicle(v)
|
||||
if mon.IsDuplicateKeyError(err) {
|
||||
err = client.GetVehicles().UpdateVehicle(v)
|
||||
}
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
err = client.GetFleets().AddVehiclesToFleet(defaultFleet, []string{id})
|
||||
if err != nil {
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func addICCID(db queries.CarsInterface, id, iccid string) error {
|
||||
// Going to only update where an iccid is valid
|
||||
if len(iccid) != 20 {
|
||||
return errInvalidICCID
|
||||
}
|
||||
|
||||
car := &common.Car{ICCID: iccid, VIN: id}
|
||||
|
||||
if ct, err := db.UpdateICCID(car); err != nil {
|
||||
return errors.Wrapf(err, "failed to update car's iccid %s", id)
|
||||
} else if ct.RowsAffected() == 1 {
|
||||
logger.Info().Msgf("car %s has been updated with iccid %s", id, iccid)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addTRexSession(client redis.Client, id string) error {
|
||||
_, err := client.Execute("SADD", redis.CarSessionsKey(), id)
|
||||
return err
|
||||
}
|
||||
|
||||
func retrieveTRexSettings(r redis.Client, m mongo.Client, id string) (*common.TRexConfigResponse, error) {
|
||||
return cache.RetrieveVehicleConfig(r, m, id)
|
||||
}
|
||||
|
||||
func sendTRexSettings(r redis.Client, id string, msg *common.TRexConfigResponse) error {
|
||||
err := r.SafePublishMessage(
|
||||
common.TRex.Key(id),
|
||||
common.Message{
|
||||
Handler: "config",
|
||||
Data: msg,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func setTRexIP(r redis.Client, vin, ip string) error {
|
||||
elms := strings.Split(ip, ":")
|
||||
|
||||
return r.SetObjectField(redis.CarStateHashKey(vin), state.TREX_IP, elms[0])
|
||||
}
|
||||
|
||||
func setDBCVersion(r redis.Client, vin, version string) error {
|
||||
return setVersion(r, vin, version, state.DBC_VERSION, common.DBCVersionSource)
|
||||
}
|
||||
|
||||
func setTRexVersion(r redis.Client, vin, version string) error {
|
||||
return setVersion(r, vin, version, state.TREX_VERSION, common.TREXVersionSource)
|
||||
}
|
||||
|
||||
func setVersion(r redis.Client, vin, version, redisField string, versionSource common.VersionSource) error {
|
||||
v, err := r.GetObjectField(redis.CarStateHashKey(vin), redisField)
|
||||
if err != nil && !errors.Is(err, redigo.ErrNil) {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
if v == version {
|
||||
return nil
|
||||
}
|
||||
|
||||
db := services.GetDB().GetCarVersionsLog()
|
||||
err = r.SetObjectField(redis.CarStateHashKey(vin), redisField, version)
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
_, err = db.LogVersionChange(&common.CarVersionLogs{
|
||||
VIN: vin,
|
||||
VersionSource: versionSource,
|
||||
Version: version,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func wakeup(vin string) {
|
||||
wake := carcommand.NewCarWakeUp(services.GetDB().GetCars(), services.GetSMSClient())
|
||||
err := wake.WakeUp(vin, false)
|
||||
loggerdataresp.BadDataError(err)
|
||||
}
|
||||
Reference in New Issue
Block a user