sync file-type support across upload/convert and fix collected_at timezone handling

This commit is contained in:
2026-02-28 23:27:49 +03:00
parent 736b77f055
commit 4940cd9645
20 changed files with 931 additions and 49 deletions

View File

@@ -26,6 +26,9 @@ type RawExportPackage struct {
ExportedAt time.Time `json:"exported_at"`
Source RawExportSource `json:"source"`
Analysis *models.AnalysisResult `json:"analysis_result,omitempty"`
// CollectedAtHint is extracted from parser_fields.json when importing
// a raw-export bundle and represents original collection time.
CollectedAtHint time.Time `json:"-"`
}
type RawExportSource struct {
@@ -36,6 +39,7 @@ type RawExportSource struct {
Data string `json:"data,omitempty"`
Protocol string `json:"protocol,omitempty"`
TargetHost string `json:"target_host,omitempty"`
SourceTimezone string `json:"source_timezone,omitempty"`
RawPayloads map[string]any `json:"raw_payloads,omitempty"`
CollectLogs []string `json:"collect_logs,omitempty"`
CollectMeta *CollectRequestMeta `json:"collect_meta,omitempty"`
@@ -53,6 +57,7 @@ func newRawExportFromUploadedFile(filename, mimeType string, payload []byte, res
Data: base64.StdEncoding.EncodeToString(payload),
Protocol: resultProtocol(result),
TargetHost: resultTargetHost(result),
SourceTimezone: resultSourceTimezone(result),
},
}
}
@@ -79,6 +84,7 @@ func newRawExportFromLiveCollect(result *models.AnalysisResult, req CollectReque
Kind: "live_redfish",
Protocol: req.Protocol,
TargetHost: req.Host,
SourceTimezone: resultSourceTimezone(result),
RawPayloads: rawPayloads,
CollectLogs: append([]string(nil), logs...),
CollectMeta: &meta,
@@ -158,23 +164,62 @@ func parseRawExportBundle(payload []byte) (*RawExportPackage, bool, error) {
if err != nil {
return nil, false, nil
}
var pkgBody []byte
var parserFieldsBody []byte
for _, f := range zr.File {
if f.Name != rawExportBundlePackageFile {
if f.Name != rawExportBundlePackageFile && f.Name != rawExportBundleFieldsFile {
continue
}
rc, err := f.Open()
if err != nil {
return nil, true, err
}
defer rc.Close()
body, err := io.ReadAll(rc)
rc.Close()
if err != nil {
return nil, true, err
}
pkg, ok, err := parseRawExportPackage(body)
switch f.Name {
case rawExportBundlePackageFile:
pkgBody = body
case rawExportBundleFieldsFile:
parserFieldsBody = body
}
}
if len(pkgBody) == 0 {
return nil, false, nil
}
pkg, ok, err := parseRawExportPackage(pkgBody)
if err != nil || !ok {
return pkg, ok, err
}
return nil, false, nil
if ts, ok := parseCollectedAtHint(parserFieldsBody); ok {
pkg.CollectedAtHint = ts.UTC()
}
return pkg, true, nil
}
func parseCollectedAtHint(parserFieldsBody []byte) (time.Time, bool) {
if len(parserFieldsBody) == 0 {
return time.Time{}, false
}
var payload struct {
CollectedAt string `json:"collected_at"`
}
if err := json.Unmarshal(parserFieldsBody, &payload); err != nil {
return time.Time{}, false
}
collectedAt := strings.TrimSpace(payload.CollectedAt)
if collectedAt == "" {
return time.Time{}, false
}
ts, err := time.Parse(time.RFC3339Nano, collectedAt)
if err != nil {
return time.Time{}, false
}
return ts, true
}
func buildHumanReadableCollectionLog(pkg *RawExportPackage, result *models.AnalysisResult, clientVersion string) string {
@@ -333,6 +378,7 @@ func buildParserFieldSummary(result *models.AnalysisResult) map[string]any {
out["source_type"] = result.SourceType
out["protocol"] = result.Protocol
out["target_host"] = result.TargetHost
out["source_timezone"] = result.SourceTimezone
out["collected_at"] = result.CollectedAt
if result.Hardware == nil {
@@ -382,3 +428,10 @@ func resultTargetHost(result *models.AnalysisResult) string {
}
return result.TargetHost
}
func resultSourceTimezone(result *models.AnalysisResult) string {
if result == nil {
return ""
}
return strings.TrimSpace(result.SourceTimezone)
}