Files
cloud-services/services/ota_update_go/handlers/flashpack_version_add.go

142 lines
4.8 KiB
Go

package handlers
import (
"errors"
"net/http"
"otaupdate/services"
"sort"
"strconv"
"github.com/fiskerinc/cloud-services/pkg/common"
"github.com/fiskerinc/cloud-services/pkg/httphandlers"
"github.com/fiskerinc/cloud-services/pkg/loggerdataresp"
"github.com/fiskerinc/cloud-services/pkg/utils"
"github.com/fiskerinc/cloud-services/pkg/utils/envtool"
"github.com/fiskerinc/cloud-services/pkg/validator"
)
var apiCreateToken string = envtool.GetEnv("MIGRATE_CREATE_TOKEN", "")
// HandleFlashpackVersionAdd godoc
// @Summary Add a flashpack version
// @Description Add a flashpack version
// @Accept json
// @Produce json
// @Param Authorization header string false "Bearer <ID token>"
// @Param Api-Key header string false "<API token>"
// @Param data body common.CarFlashpackVersionAddRequest true "Mappings between ECU versions and a flashpack number"
// @Success 200 {object} common.JSONDBQueryResult "Created flashpack ecu mapping result"
// @Failure 400 {object} common.JSONError "Bad request"
// @Failure 401 {object} common.JSONError "Unauthorized"
// @Failure 503 {object} common.JSONError "Service unavailable"
// @Router /flashpack_version [post]
func HandleFlashpackVersionAdd(w http.ResponseWriter, r *http.Request) {
var req common.CarFlashpackVersionAddRequest
err := httphandlers.ParseRequest(r, &req)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
if len(req.ECUVersions) < 1 {
loggerdataresp.BadDataErrorResp(w, errors.New("CarECUName and CarECUVersion required"), http.StatusBadRequest)
return
}
// Include previous flashpack mappings
previousMappings, err := services.GetDB().GetCars().GetCarFlashpackVersionMappingsByModelTrim(req.CarModel, req.CarTrim, nil)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusServiceUnavailable) {
return
}
// the flashpacks are stored in the database as strings, so we have to sort them numerically
// in descending order by year and flashpack
sort.Slice(previousMappings, func(i, j int) bool {
iFp, _ := strconv.ParseFloat(previousMappings[i].Flashpack, 64) // guaranteed numeric
jFp, _ := strconv.ParseFloat(previousMappings[j].Flashpack, 64) // guaranteed numeric
iYear := previousMappings[i].CarYear
jYear := previousMappings[j].CarYear
if iYear == jYear {
return iFp > jFp
} else {
return iYear > jYear
}
})
// Put all the mappings into one array, still in descending order by flashpack number
// only include the ones that are less than or equal to the new flashpack number being added
mappings := []common.CarFlashpackVersion{}
for _, v := range req.ECUVersions {
mappings = append(mappings, common.CarFlashpackVersion{
CarECUName: v.CarECUName,
CarECUVersion: v.CarECUVersion,
Flashpack: req.Flashpack,
CarModel: req.CarModel,
CarTrim: req.CarTrim,
CarYear: req.CarYear,
})
}
for _, m := range previousMappings {
reqFp, _ := strconv.ParseFloat(req.Flashpack, 64) // already validated as numeric
mFp, _ := strconv.ParseFloat(m.Flashpack, 64) // already validated as numeric
if (m.CarYear < req.CarYear) ||
(m.CarYear == req.CarYear && mFp <= reqFp) {
mappings = append(mappings, m)
}
}
// Put the mappings in a map by ecu name
// There can be more than one ECU version for an ECU for a flashpack
var newMappings = make(map[string][]common.CarFlashpackVersion)
for _, m := range mappings {
// Only include the mapping if it is one of the latest
latestVersionMappings, ok := newMappings[m.CarECUName]
// Include multiple versions for the same ecu and flashpack number
if (ok && m.Flashpack == latestVersionMappings[0].Flashpack) || !ok {
newMappings[m.CarECUName] = append(newMappings[m.CarECUName], m)
}
}
// Flatten the map into an array
var newMappingsArray []common.CarFlashpackVersion
for _, m := range newMappings {
newMappingsArray = append(newMappingsArray, m...)
}
// Apply the new flashpack number to all the mappings to be inserted
for i := range newMappingsArray {
newMappingsArray[i].Flashpack = req.Flashpack
newMappingsArray[i].CarYear = req.CarYear
}
err = services.GetDB().GetCars().AddCarFlashpackVersionMappings(newMappingsArray)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusServiceUnavailable) {
return
}
// Also add to other environments, as required
for _, targetURL := range targetURLS {
if !validator.ValidateURL(targetURL) || apiCreateToken == "" {
break // No URL in MANIFEST_MIGRATE_URLS
}
otaService := services.NewOtaService(targetURL, apiCreateToken)
resp, err := otaService.FlashpackVersionAdd(req)
if loggerdataresp.BadDataErrorResp(w, err, http.StatusBadRequest) {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
utils.ForwardResponse(w, resp)
}
}
utils.RespJSON(w, http.StatusOK, common.JSONMessage{
Message: "Created",
})
}