Add depot, attendant, jetfire, optimus, ota services with kustomize overlays
This commit is contained in:
113
services/depot/services/cert.go
Normal file
113
services/depot/services/cert.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/common"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
certService CertServiceInterface
|
||||
certOnce sync.Once
|
||||
)
|
||||
|
||||
func GetCertService() CertServiceInterface {
|
||||
certOnce.Do(func() {
|
||||
if certService != nil {
|
||||
return
|
||||
}
|
||||
certService = NewCertService()
|
||||
})
|
||||
|
||||
return certService
|
||||
}
|
||||
|
||||
func SetCertService(cs CertServiceInterface) {
|
||||
certService = cs
|
||||
}
|
||||
|
||||
func NewCertService() CertServiceInterface {
|
||||
return &CertService{
|
||||
certURL: envtool.GetEnv("CERT_URL", "REPLACE_ME"),
|
||||
certAPIToken: envtool.GetEnv("CERTIFICATE_API_KEY", "REPLACE_ME"),
|
||||
}
|
||||
}
|
||||
|
||||
type CertServiceInterface interface {
|
||||
CheckCertificateNeedsRenewal(vin string, certType string) (bool, error)
|
||||
RenewCertificate(vin string, certType string) (*common.Certificate, error)
|
||||
}
|
||||
|
||||
type CertService struct {
|
||||
certURL string
|
||||
certAPIToken string
|
||||
}
|
||||
|
||||
func (cs *CertService) CheckCertificateNeedsRenewal(vin string, certType string) (bool, error) {
|
||||
logger.Debug().Msg("checking " + certType + " cert for vin " + vin)
|
||||
|
||||
cert, err := GetDB().GetCertificates().SelectMostRecent(vin, certType)
|
||||
if err != nil && !errors.Is(err, pg.ErrNoRows) {
|
||||
return false, err
|
||||
}
|
||||
if cert == nil {
|
||||
logger.Debug().Msg("no existing " + certType + " cert to renew for vin " + vin)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var daysBeforeExp = 183 // six months
|
||||
switch certType {
|
||||
case common.CertTBOX:
|
||||
daysBeforeExp = envtool.GetEnvInt("TBOX_CERT_RENEW_DAYS_BEFORE_EXP", daysBeforeExp)
|
||||
case common.CertICC:
|
||||
daysBeforeExp = envtool.GetEnvInt("ICC_CERT_RENEW_DAYS_BEFORE_EXP", daysBeforeExp)
|
||||
}
|
||||
|
||||
logger.Debug().Msg("checking validity of " + certType + " cert with serial number " + cert.SerialNumber + " for vin " + vin)
|
||||
|
||||
return cert.IsExpiredOrInvalidAtTime(time.Now(), daysBeforeExp)
|
||||
}
|
||||
|
||||
func (cs *CertService) RenewCertificate(vin string, certType string) (*common.Certificate, error) {
|
||||
logger.Debug().Msg("renewing " + certType + " cert for vin " + vin)
|
||||
|
||||
jsonBytes, err := json.Marshal(common.CertificateRenewRequest{
|
||||
Type: certType,
|
||||
CommonName: vin,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
request, err := http.NewRequest(http.MethodPost, cs.certURL+"renew", bytes.NewReader(jsonBytes))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
request.Header.Add("Api-Key", cs.certAPIToken)
|
||||
|
||||
resp, err := http.DefaultClient.Do(request)
|
||||
if err != nil {
|
||||
return nil, errors.WithStack(err)
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.New("renew " + certType + " certificate returned " + resp.Status + " for vin " + vin)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
var cert common.Certificate
|
||||
err = json.NewDecoder(resp.Body).Decode(&cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &cert, err
|
||||
}
|
||||
170
services/depot/services/db.go
Normal file
170
services/depot/services/db.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/common"
|
||||
"github.com/fiskerinc/cloud-services/pkg/db"
|
||||
q "github.com/fiskerinc/cloud-services/pkg/db/queries"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
dbOnce sync.Once
|
||||
dbInstance *DB
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
client *db.DBClient
|
||||
cars q.CarsInterface
|
||||
carVersionsLog q.CarVersionsLogInterface
|
||||
certificates q.CertificatesInterface
|
||||
updateManifest q.UpdateManifestsInterface
|
||||
updateManifestSUMSVersions q.SUMSVersionsInterface
|
||||
|
||||
onceClient sync.Once
|
||||
onceCars sync.Once
|
||||
onceCarVersionsLog sync.Once
|
||||
onceCertificates sync.Once
|
||||
onceUpdateManifest sync.Once
|
||||
onceUpdateManifestSUMSVersions sync.Once
|
||||
}
|
||||
|
||||
func GetDB() *DB {
|
||||
dbOnce.Do(func() {
|
||||
if dbInstance != nil {
|
||||
return
|
||||
}
|
||||
logger.Info().Msg("init DB instance")
|
||||
dbInstance = &DB{}
|
||||
})
|
||||
return dbInstance
|
||||
}
|
||||
|
||||
func SetDB(db *DB) {
|
||||
if dbInstance != nil {
|
||||
dbInstance.Close()
|
||||
}
|
||||
dbInstance = db
|
||||
}
|
||||
|
||||
func (d *DB) GetDBClient() *db.DBClient {
|
||||
d.onceClient.Do(func() {
|
||||
if d.client != nil {
|
||||
return
|
||||
}
|
||||
logger.Info().Msg("init DBClient instance")
|
||||
client := &db.DBClient{}
|
||||
|
||||
err := client.InitSchema([]interface{}{
|
||||
(*common.UpdateManifest)(nil),
|
||||
(*common.CarUpdate)(nil),
|
||||
(*common.CarToDriver)(nil),
|
||||
(*common.CarSetting)(nil),
|
||||
(*common.SUMSVersion)(nil),
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
d.client = client
|
||||
})
|
||||
return d.client
|
||||
}
|
||||
|
||||
func (d *DB) SetDBClient(client *db.DBClient) {
|
||||
if d.client != nil {
|
||||
d.client.Close()
|
||||
}
|
||||
d.client = client
|
||||
}
|
||||
|
||||
func (d *DB) Close() {
|
||||
if d.client == nil {
|
||||
return
|
||||
}
|
||||
d.client.Close()
|
||||
}
|
||||
|
||||
///----------
|
||||
|
||||
func (d *DB) GetCars() q.CarsInterface {
|
||||
d.onceCars.Do(func() {
|
||||
if d.cars != nil {
|
||||
return
|
||||
}
|
||||
instance := &q.Cars{}
|
||||
instance.SetClient(d.GetDBClient())
|
||||
d.cars = instance
|
||||
})
|
||||
return d.cars
|
||||
}
|
||||
|
||||
func (d *DB) SetCars(cars q.CarsInterface) {
|
||||
d.cars = cars
|
||||
}
|
||||
|
||||
func (d *DB) GetCarVersionsLog() q.CarVersionsLogInterface {
|
||||
d.onceCarVersionsLog.Do(func() {
|
||||
if d.carVersionsLog != nil {
|
||||
return
|
||||
}
|
||||
instance := &q.CarVersionsLog{}
|
||||
instance.SetClient(d.GetDBClient())
|
||||
d.carVersionsLog = instance
|
||||
})
|
||||
return d.carVersionsLog
|
||||
}
|
||||
|
||||
func (d *DB) SetCarVersionsLog(log q.CarVersionsLogInterface) {
|
||||
d.carVersionsLog = log
|
||||
}
|
||||
|
||||
func (d *DB) GetCertificates() q.CertificatesInterface {
|
||||
d.onceCertificates.Do(func() {
|
||||
if d.certificates != nil {
|
||||
return
|
||||
}
|
||||
logger.Debug().Msg("Init Certificates instance")
|
||||
certificates := &q.Certificates{}
|
||||
certificates.SetClient(d.GetDBClient())
|
||||
d.certificates = certificates
|
||||
})
|
||||
return d.certificates
|
||||
}
|
||||
|
||||
func (d *DB) SetCertificates(certificates q.CertificatesInterface) {
|
||||
d.certificates = certificates
|
||||
}
|
||||
|
||||
func (d *DB) GetUpdateManifests() q.UpdateManifestsInterface {
|
||||
d.onceUpdateManifest.Do(func() {
|
||||
if d.updateManifest != nil {
|
||||
return
|
||||
}
|
||||
logger.Debug().Msg("Init UpdateManifest instance")
|
||||
updateManifest := q.NewUpdateManifest(nil)
|
||||
updateManifest.SetClient(d.GetDBClient())
|
||||
d.updateManifest = updateManifest
|
||||
})
|
||||
return d.updateManifest
|
||||
}
|
||||
|
||||
func (d *DB) SetUpdateManifests(updateManifest q.UpdateManifestsInterface) {
|
||||
d.updateManifest = updateManifest
|
||||
}
|
||||
|
||||
func (d *DB) GetUpdateManifestSUMSVersions() q.SUMSVersionsInterface {
|
||||
d.onceUpdateManifestSUMSVersions.Do(func() {
|
||||
if d.updateManifestSUMSVersions != nil {
|
||||
return
|
||||
}
|
||||
instance := &q.SUMSVersions{}
|
||||
instance.SetClient(d.GetDBClient())
|
||||
d.updateManifestSUMSVersions = instance
|
||||
})
|
||||
return d.updateManifestSUMSVersions
|
||||
}
|
||||
|
||||
func (d *DB) SetUpdateManifestVersions(umv q.SUMSVersionsInterface) {
|
||||
d.updateManifestSUMSVersions = umv
|
||||
}
|
||||
23
services/depot/services/digital_twin.go
Normal file
23
services/depot/services/digital_twin.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/digitaltwin"
|
||||
)
|
||||
|
||||
// There is no need to recreate the digital twin sender every time we send a digital twin
|
||||
// so keeping a reference here
|
||||
|
||||
var sendDigitalTwin *digitaltwin.SendDigitalTwin
|
||||
var sendDigitalTwinOnce sync.Once
|
||||
|
||||
func GetSendDigitalTwin()(*digitaltwin.SendDigitalTwin){
|
||||
sendDigitalTwinOnce.Do(func(){
|
||||
if sendDigitalTwin == nil {
|
||||
notSureWhyIcantTakeAddress := digitaltwin.NewSendDigitalTwin(RedisClientPool(), GetDB().GetCars())
|
||||
sendDigitalTwin = ¬SureWhyIcantTakeAddress
|
||||
}
|
||||
})
|
||||
return sendDigitalTwin
|
||||
}
|
||||
36
services/depot/services/kafka.go
Normal file
36
services/depot/services/kafka.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/kafka"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
)
|
||||
|
||||
const serviceName = "depot"
|
||||
const oldServiceName = "old-depot"
|
||||
|
||||
var consumer kafka.ConsumerInterface
|
||||
var oldConsumer kafka.ConsumerInterface
|
||||
var consumerOnce sync.Once
|
||||
|
||||
// GetKafkaConsumer returns singleton instance of kafka consumer
|
||||
func GetKafkaConsumer() (kafka.ConsumerInterface, kafka.ConsumerInterface, error) {
|
||||
var err error
|
||||
|
||||
consumerOnce.Do(func() {
|
||||
consumer, err = kafka.NewConsumer(serviceName)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
oldConsumer, err = kafka.NewConsumer(oldServiceName)
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return consumer, oldConsumer, err
|
||||
}
|
||||
|
||||
return consumer, oldConsumer, nil
|
||||
}
|
||||
72
services/depot/services/mongo.go
Normal file
72
services/depot/services/mongo.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/mongo"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sony/gobreaker"
|
||||
)
|
||||
|
||||
var (
|
||||
clientlock sync.Mutex
|
||||
client mongo.Client
|
||||
cb *gobreaker.CircuitBreaker
|
||||
)
|
||||
|
||||
func init() {
|
||||
cb = gobreaker.NewCircuitBreaker(
|
||||
gobreaker.Settings{
|
||||
Timeout: 10 * time.Second,
|
||||
Interval: 15 * time.Minute,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// GetMongoClient returns singleton instance of mongo client
|
||||
func GetMongoClient() (mongo.Client, error) {
|
||||
err := ping()
|
||||
if err != nil {
|
||||
return initMongoClient()
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func initMongoClient() (mongo.Client, error) {
|
||||
clientlock.Lock()
|
||||
defer clientlock.Unlock()
|
||||
var err error
|
||||
|
||||
client, err = mongo.NewClient(mongo.StandardDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, _ = cb.Execute(func() (interface{}, error) {
|
||||
err = ping()
|
||||
return nil, err
|
||||
})
|
||||
|
||||
return client, errors.WithStack(err)
|
||||
}
|
||||
|
||||
func ping() error {
|
||||
if client == nil {
|
||||
return errors.New("client is nil")
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
defer cancel()
|
||||
return client.Ping(ctx)
|
||||
}
|
||||
|
||||
// SetMongoClient is supposed to be used for tests.
|
||||
func SetMongoClient(cl mongo.Client) {
|
||||
client = cl
|
||||
}
|
||||
|
||||
|
||||
// db.dtc_lookup.aggregate({"$match": {"ecuName": "TBOX", "DtcUniqueId": "V2.6.0"}}, {"$unwind": "$dtcData.DtcList"}, {"$match": {"dtcData.DtcList.TroubleCodeHex":"D77F16"}}, {"$project":{"_id": 0, "Obj": "$dtcData.DtcList"}})
|
||||
28
services/depot/services/redis.go
Normal file
28
services/depot/services/redis.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/fiskerinc/cloud-services/pkg/redis"
|
||||
)
|
||||
|
||||
var (
|
||||
clientPoolOnce sync.Once
|
||||
clientPool redis.ClientPoolInterface
|
||||
)
|
||||
|
||||
func RedisClientPool() redis.ClientPoolInterface {
|
||||
clientPoolOnce.Do(func() {
|
||||
if clientPool != nil {
|
||||
return
|
||||
}
|
||||
|
||||
clientPool = redis.NewClientPool()
|
||||
})
|
||||
|
||||
return clientPool
|
||||
}
|
||||
|
||||
func SetRedisClientPool(cp redis.ClientPoolInterface) {
|
||||
clientPool = cp
|
||||
}
|
||||
42
services/depot/services/sms.go
Normal file
42
services/depot/services/sms.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/fiskerinc/cloud-services/pkg/grpc/sms"
|
||||
"github.com/fiskerinc/cloud-services/pkg/logger"
|
||||
"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
|
||||
"fmt"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var smsClient sms.SMSServiceClient
|
||||
var smsClientOnce sync.Once
|
||||
|
||||
func newSmsClient() {
|
||||
logger.Info().Msg("Init SMS client")
|
||||
target := fmt.Sprintf("%s:%s",
|
||||
envtool.GetEnv("SMS_HOST", "sms"),
|
||||
envtool.GetEnv("SMS_PORT", "8077"))
|
||||
c, err := grpc.Dial(target, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
logger.Error().Err(err).Send()
|
||||
}
|
||||
|
||||
smsClient = sms.NewSMSServiceClient(c)
|
||||
}
|
||||
|
||||
func GetSMSClient() sms.SMSServiceClient {
|
||||
smsClientOnce.Do(func() {
|
||||
if smsClient != nil {
|
||||
return
|
||||
}
|
||||
newSmsClient()
|
||||
})
|
||||
|
||||
return smsClient
|
||||
}
|
||||
|
||||
func SetSmsClient(c sms.SMSServiceClient) {
|
||||
smsClient = c
|
||||
}
|
||||
Reference in New Issue
Block a user