prow/spyglass/lenses/metadata/lens.go
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	var buf bytes.Buffer
	type MetadataViewData struct {
		Status       string
		StartTime    time.Time
		FinishedTime time.Time
		Elapsed      time.Duration
		Metadata     map[string]string
	}
	metadataViewData := MetadataViewData{Status: "Pending"}
	started := gcs.Started{}
	finished := gcs.Finished{}
	for _, a := range artifacts {
		read, err := a.ReadAll()
		if err != nil {
			logrus.WithError(err).Error("Failed reading from artifact.")
		}
		if a.JobPath() == "started.json" {
			if err = json.Unmarshal(read, &started); err != nil {
				logrus.WithError(err).Error("Error unmarshaling started.json")
			}
			metadataViewData.StartTime = time.Unix(started.Timestamp, 0)
		} else if a.JobPath() == "finished.json" {
			if err = json.Unmarshal(read, &finished); err != nil {
				logrus.WithError(err).Error("Error unmarshaling finished.json")
			}
			if finished.Timestamp != nil {
				metadataViewData.FinishedTime = time.Unix(*finished.Timestamp, 0)
			}
			metadataViewData.Status = finished.Result
		}
	}

	if !metadataViewData.StartTime.IsZero() {
		if metadataViewData.FinishedTime.IsZero() {
			metadataViewData.Elapsed = time.Now().Sub(metadataViewData.StartTime)
		} else {
			metadataViewData.Elapsed =
				metadataViewData.FinishedTime.Sub(metadataViewData.StartTime)
		}
		metadataViewData.Elapsed = metadataViewData.Elapsed.Round(time.Second)
	}

	metadataViewData.Metadata = map[string]string{"node": started.Node}

	metadatas := []metadata.Metadata{started.Metadata, finished.Metadata}
	for _, m := range metadatas {
		for k, v := range m {
			if s, ok := v.(string); ok && v != "" {
				metadataViewData.Metadata[k] = s
			}
		}
	}

	metadataTemplate, err := template.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		return fmt.Sprintf("Failed to load template: %v", err)
	}

	if err := metadataTemplate.ExecuteTemplate(&buf, "body", metadataViewData); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}
	return buf.String()
}
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	var buf bytes.Buffer
	type MetadataViewData struct {
		Status       string
		StartTime    time.Time
		FinishedTime time.Time
		Elapsed      time.Duration
		Metadata     map[string]string
	}
	metadataViewData := MetadataViewData{Status: "Pending"}
	started := gcs.Started{}
	finished := gcs.Finished{}
	for _, a := range artifacts {
		read, err := a.ReadAll()
		if err != nil {
			logrus.WithError(err).Error("Failed reading from artifact.")
		}
		if a.JobPath() == "started.json" {
			if err = json.Unmarshal(read, &started); err != nil {
				logrus.WithError(err).Error("Error unmarshaling started.json")
			}
			metadataViewData.StartTime = time.Unix(started.Timestamp, 0)
		} else if a.JobPath() == "finished.json" {
			if err = json.Unmarshal(read, &finished); err != nil {
				logrus.WithError(err).Error("Error unmarshaling finished.json")
			}
			if finished.Timestamp != nil {
				metadataViewData.FinishedTime = time.Unix(*finished.Timestamp, 0)
			}
			metadataViewData.Status = finished.Result
		}
	}

	if !metadataViewData.StartTime.IsZero() {
		if metadataViewData.FinishedTime.IsZero() {
			metadataViewData.Elapsed = time.Now().Sub(metadataViewData.StartTime)
		} else {
			metadataViewData.Elapsed =
				metadataViewData.FinishedTime.Sub(metadataViewData.StartTime)
		}
		metadataViewData.Elapsed = metadataViewData.Elapsed.Round(time.Second)
	}

	metadataViewData.Metadata = map[string]string{"node": started.Node}

	metadatas := []metadata.Metadata{started.Metadata, finished.Metadata}
	for _, m := range metadatas {
		for k, v := range m {
			if s, ok := v.(string); ok && v != "" {
				metadataViewData.Metadata[k] = s
			}
		}
	}

	metadataTemplate, err := template.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		return fmt.Sprintf("Failed to load template: %v", err)
	}

	if err := metadataTemplate.ExecuteTemplate(&buf, "body", metadataViewData); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}
	return buf.String()
}
// Body creates a view for prow job metadata.