mirror of
https://github.com/turbot/steampipe.git
synced 2026-04-13 22:00:05 -04:00
245 lines
7.5 KiB
Go
245 lines
7.5 KiB
Go
package dashboardserver
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"github.com/spf13/viper"
|
|
typeHelpers "github.com/turbot/go-kit/types"
|
|
"github.com/turbot/steampipe/pkg/constants"
|
|
"github.com/turbot/steampipe/pkg/dashboard/dashboardevents"
|
|
"github.com/turbot/steampipe/pkg/dashboard/dashboardexecute"
|
|
"github.com/turbot/steampipe/pkg/steampipeconfig"
|
|
"github.com/turbot/steampipe/pkg/steampipeconfig/modconfig"
|
|
"github.com/turbot/steampipe/pkg/version"
|
|
)
|
|
|
|
func buildDashboardMetadataPayload(workspaceResources *modconfig.ResourceMaps, cloudMetadata *steampipeconfig.CloudMetadata) ([]byte, error) {
|
|
installedMods := make(map[string]ModDashboardMetadata)
|
|
for _, mod := range workspaceResources.Mods {
|
|
// Ignore current mod
|
|
if mod.FullName == workspaceResources.Mod.FullName {
|
|
continue
|
|
}
|
|
installedMods[mod.FullName] = ModDashboardMetadata{
|
|
Title: typeHelpers.SafeString(mod.Title),
|
|
FullName: mod.FullName,
|
|
ShortName: mod.ShortName,
|
|
}
|
|
}
|
|
|
|
payload := DashboardMetadataPayload{
|
|
Action: "dashboard_metadata",
|
|
Metadata: DashboardMetadata{
|
|
CLI: DashboardCLIMetadata{
|
|
Version: version.VersionString,
|
|
},
|
|
InstalledMods: installedMods,
|
|
Telemetry: viper.GetString(constants.ArgTelemetry),
|
|
},
|
|
}
|
|
|
|
if mod := workspaceResources.Mod; mod != nil {
|
|
payload.Metadata.Mod = &ModDashboardMetadata{
|
|
Title: typeHelpers.SafeString(mod.Title),
|
|
FullName: mod.FullName,
|
|
ShortName: mod.ShortName,
|
|
}
|
|
}
|
|
// if telemetry is enabled, send cloud metadata
|
|
if payload.Metadata.Telemetry != constants.TelemetryNone {
|
|
payload.Metadata.Cloud = cloudMetadata
|
|
}
|
|
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func addBenchmarkChildren(benchmark *modconfig.Benchmark, recordTrunk bool, trunk []string, trunks map[string][][]string) []ModAvailableBenchmark {
|
|
var children []ModAvailableBenchmark
|
|
for _, child := range benchmark.GetChildren() {
|
|
switch t := child.(type) {
|
|
case *modconfig.Benchmark:
|
|
childTrunk := make([]string, len(trunk)+1)
|
|
copy(childTrunk, trunk)
|
|
childTrunk[len(childTrunk)-1] = t.FullName
|
|
if recordTrunk {
|
|
trunks[t.FullName] = append(trunks[t.FullName], childTrunk)
|
|
}
|
|
availableBenchmark := ModAvailableBenchmark{
|
|
Title: t.GetTitle(),
|
|
FullName: t.FullName,
|
|
ShortName: t.ShortName,
|
|
Tags: t.Tags,
|
|
Children: addBenchmarkChildren(t, recordTrunk, childTrunk, trunks),
|
|
}
|
|
children = append(children, availableBenchmark)
|
|
}
|
|
}
|
|
return children
|
|
}
|
|
|
|
func buildAvailableDashboardsPayload(workspaceResources *modconfig.ResourceMaps) ([]byte, error) {
|
|
|
|
payload := AvailableDashboardsPayload{
|
|
Action: "available_dashboards",
|
|
Dashboards: make(map[string]ModAvailableDashboard),
|
|
Benchmarks: make(map[string]ModAvailableBenchmark),
|
|
Snapshots: workspaceResources.Snapshots,
|
|
}
|
|
|
|
// if workspace resources has a mod, populate dashboards and benchmarks
|
|
if workspaceResources.Mod != nil {
|
|
// build a map of the dashboards provided by each mod
|
|
|
|
// iterate over the dashboards for the top level mod - this will include the dashboards from dependency mods
|
|
for _, dashboard := range workspaceResources.Mod.ResourceMaps.Dashboards {
|
|
mod := dashboard.Mod
|
|
// add this dashboard
|
|
payload.Dashboards[dashboard.FullName] = ModAvailableDashboard{
|
|
Title: typeHelpers.SafeString(dashboard.Title),
|
|
FullName: dashboard.FullName,
|
|
ShortName: dashboard.ShortName,
|
|
Tags: dashboard.Tags,
|
|
ModFullName: mod.FullName,
|
|
}
|
|
}
|
|
|
|
benchmarkTrunks := make(map[string][][]string)
|
|
for _, benchmark := range workspaceResources.Mod.ResourceMaps.Benchmarks {
|
|
if benchmark.IsAnonymous() {
|
|
continue
|
|
}
|
|
|
|
// Find any benchmarks who have a parent that is a mod - we consider these top-level
|
|
isTopLevel := false
|
|
for _, parent := range benchmark.GetParents() {
|
|
switch parent.(type) {
|
|
case *modconfig.Mod:
|
|
isTopLevel = true
|
|
}
|
|
}
|
|
|
|
mod := benchmark.Mod
|
|
trunk := []string{benchmark.FullName}
|
|
|
|
if isTopLevel {
|
|
benchmarkTrunks[benchmark.FullName] = [][]string{trunk}
|
|
}
|
|
|
|
availableBenchmark := ModAvailableBenchmark{
|
|
Title: benchmark.GetTitle(),
|
|
FullName: benchmark.FullName,
|
|
ShortName: benchmark.ShortName,
|
|
Tags: benchmark.Tags,
|
|
IsTopLevel: isTopLevel,
|
|
Children: addBenchmarkChildren(benchmark, isTopLevel, trunk, benchmarkTrunks),
|
|
ModFullName: mod.FullName,
|
|
}
|
|
|
|
payload.Benchmarks[benchmark.FullName] = availableBenchmark
|
|
}
|
|
for benchmarkName, trunks := range benchmarkTrunks {
|
|
if foundBenchmark, ok := payload.Benchmarks[benchmarkName]; ok {
|
|
foundBenchmark.Trunks = trunks
|
|
payload.Benchmarks[benchmarkName] = foundBenchmark
|
|
}
|
|
}
|
|
}
|
|
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildWorkspaceErrorPayload(e *dashboardevents.WorkspaceError) ([]byte, error) {
|
|
payload := ErrorPayload{
|
|
Action: "workspace_error",
|
|
Error: e.Error.Error(),
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildControlCompletePayload(event *dashboardevents.ControlComplete) ([]byte, error) {
|
|
payload := ControlEventPayload{
|
|
Action: "control_complete",
|
|
Control: event.Control,
|
|
Name: event.Name,
|
|
Progress: event.Progress,
|
|
ExecutionId: event.ExecutionId,
|
|
Timestamp: event.Timestamp,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildControlErrorPayload(event *dashboardevents.ControlError) ([]byte, error) {
|
|
payload := ControlEventPayload{
|
|
Action: "control_error",
|
|
Control: event.Control,
|
|
Name: event.Name,
|
|
Progress: event.Progress,
|
|
ExecutionId: event.ExecutionId,
|
|
Timestamp: event.Timestamp,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildLeafNodeUpdatedPayload(event *dashboardevents.LeafNodeUpdated) ([]byte, error) {
|
|
payload := LeafNodeUpdatedPayload{
|
|
SchemaVersion: fmt.Sprintf("%d", LeafNodeUpdatedSchemaVersion),
|
|
Action: "leaf_node_updated",
|
|
DashboardNode: event.LeafNode,
|
|
ExecutionId: event.ExecutionId,
|
|
Timestamp: event.Timestamp,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildExecutionStartedPayload(event *dashboardevents.ExecutionStarted) ([]byte, error) {
|
|
payload := ExecutionStartedPayload{
|
|
SchemaVersion: fmt.Sprintf("%d", ExecutionStartedSchemaVersion),
|
|
Action: "execution_started",
|
|
ExecutionId: event.ExecutionId,
|
|
Panels: event.Panels,
|
|
Layout: event.Root.AsTreeNode(),
|
|
Inputs: event.Inputs,
|
|
Variables: event.Variables,
|
|
StartTime: event.StartTime,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildExecutionErrorPayload(event *dashboardevents.ExecutionError) ([]byte, error) {
|
|
payload := ExecutionErrorPayload{
|
|
Action: "execution_error",
|
|
Error: event.Error.Error(),
|
|
Timestamp: event.Timestamp,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildExecutionCompletePayload(event *dashboardevents.ExecutionComplete) ([]byte, error) {
|
|
snap := dashboardexecute.ExecutionCompleteToSnapshot(event)
|
|
payload := &ExecutionCompletePayload{
|
|
Action: "execution_complete",
|
|
SchemaVersion: fmt.Sprintf("%d", ExecutionCompletePayloadSchemaVersion),
|
|
ExecutionId: event.ExecutionId,
|
|
Snapshot: snap,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildDisplaySnapshotPayload(snap map[string]any) ([]byte, error) {
|
|
payload := &DisplaySnapshotPayload{
|
|
Action: "execution_complete",
|
|
SchemaVersion: fmt.Sprintf("%d", ExecutionCompletePayloadSchemaVersion),
|
|
Snapshot: snap,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|
|
|
|
func buildInputValuesClearedPayload(event *dashboardevents.InputValuesCleared) ([]byte, error) {
|
|
payload := InputValuesClearedPayload{
|
|
Action: "input_values_cleared",
|
|
ClearedInputs: event.ClearedInputs,
|
|
ExecutionId: event.ExecutionId,
|
|
}
|
|
return json.Marshal(payload)
|
|
}
|