mirror of
https://github.com/BishopFox/steampipe.git
synced 2026-11-07 10:25:57 -10:00
rename 'report' to 'dashboard'. Closes #1459
This commit is contained in:
1 parent
41a2c7095c
commit
8b7a32f2e8
93 files changed
+1667
-1941
No files matched your search
+12
-13
@@ -5,15 +5,14 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/turbot/go-kit/helpers"
|
||||
"github.com/turbot/steampipe-plugin-sdk/v3/logging"
|
||||
"github.com/turbot/steampipe/cmdconfig"
|
||||
"github.com/turbot/steampipe/constants"
|
||||
"github.com/turbot/steampipe/contexthelpers"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardassets"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardserver"
|
||||
"github.com/turbot/steampipe/db/db_local"
|
||||
"github.com/turbot/steampipe/report/reportassets"
|
||||
"github.com/turbot/steampipe/report/reportserver"
|
||||
"github.com/turbot/steampipe/utils"
|
||||
)
|
||||
|
||||
@@ -31,13 +30,15 @@ The current mod is the working directory, or the directory specified by the --wo
|
||||
|
||||
cmdconfig.OnCmd(cmd).
|
||||
AddBoolFlag(constants.ArgHelp, "h", false, "Help for report").
|
||||
AddStringFlag(constants.ArgReportServerListen, "", string(reportserver.ListenTypeLocal), "Accept connections from: local (localhost only) or network (open)").
|
||||
AddIntFlag(constants.ArgReportServerPort, "", constants.ReportServerDefaultPort, "Report server port.")
|
||||
AddStringFlag(constants.ArgDashboardServerListen, "", string(dashboardserver.ListenTypeLocal), "Accept connections from: local (localhost only) or network (open)").
|
||||
AddIntFlag(constants.ArgDashboardServerPort, "", constants.ReportServerDefaultPort, "Report server port.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runReportCmd(cmd *cobra.Command, args []string) {
|
||||
ctx := cmd.Context()
|
||||
ctx, cancel := context.WithCancel(cmd.Context())
|
||||
contexthelpers.StartCancelHandler(cancel)
|
||||
|
||||
logging.LogTime("runReportCmd start")
|
||||
defer func() {
|
||||
logging.LogTime("runReportCmd end")
|
||||
@@ -46,26 +47,24 @@ func runReportCmd(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
}()
|
||||
|
||||
serverPort := reportserver.ListenPort(viper.GetInt(constants.ArgReportServerPort))
|
||||
serverPort := dashboardserver.ListenPort(viper.GetInt(constants.ArgDashboardServerPort))
|
||||
utils.FailOnError(serverPort.IsValid())
|
||||
|
||||
serverListen := reportserver.ListenType(viper.GetString(constants.ArgReportServerListen))
|
||||
serverListen := dashboardserver.ListenType(viper.GetString(constants.ArgDashboardServerListen))
|
||||
utils.FailOnError(serverListen.IsValid())
|
||||
|
||||
ctx, cancel := context.WithCancel(cmd.Context())
|
||||
contexthelpers.StartCancelHandler(cancel)
|
||||
|
||||
// ensure report assets are present and extract if not
|
||||
err := reportassets.Ensure(ctx)
|
||||
err := dashboardassets.Ensure(ctx)
|
||||
utils.FailOnError(err)
|
||||
|
||||
|
||||
dbClient, err := db_local.GetLocalClient(ctx, constants.InvokerReport)
|
||||
utils.FailOnError(err)
|
||||
|
||||
refreshResult := dbClient.RefreshConnectionAndSearchPaths(ctx)
|
||||
refreshResult.ShowWarnings()
|
||||
|
||||
server, err := reportserver.NewServer(ctx, dbClient)
|
||||
server, err := dashboardserver.NewServer(ctx, dbClient)
|
||||
if err != nil {
|
||||
utils.FailOnError(err)
|
||||
}
|
||||
|
||||
+4
-4
@@ -12,10 +12,10 @@ const (
|
||||
ArgClear = "clear"
|
||||
ArgDatabasePort = "database-port"
|
||||
ArgListenAddress = "database-listen"
|
||||
ArgServicePassword = "database-password"
|
||||
ArgReportServerListen = "reportserver-listen"
|
||||
ArgReportServerPort = "reportserver-port"
|
||||
ArgForeground = "foreground"
|
||||
ArgServicePassword = "database-password"
|
||||
ArgDashboardServerListen = "dashboardserver-listen"
|
||||
ArgDashboardServerPort = "dashboardserver-port"
|
||||
ArgForeground = "foreground"
|
||||
ArgInvoker = "invoker"
|
||||
ArgUpdateCheck = "update-check"
|
||||
ArgInstallDir = "install-dir"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package reportassets
|
||||
package dashboardassets
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -30,7 +30,7 @@ func Ensure(ctx context.Context) error {
|
||||
|
||||
statushooks.SetStatus(ctx, "Installing reporting server...")
|
||||
defer statushooks.Done(ctx)
|
||||
reportAssetsPath := filepaths.EnsureReportAssetsDir()
|
||||
reportAssetsPath := filepaths.EnsureDashboardAssetsDir()
|
||||
return ociinstaller.InstallAssets(ctx, reportAssetsPath)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type ContainerComplete struct {
|
||||
Container dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*ContainerComplete) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type ContainerError struct {
|
||||
Container dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*ContainerError) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,82 @@
|
||||
package dashboardevents
|
||||
|
||||
import (
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
type DashboardChanged struct {
|
||||
ChangedDashboards []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedContainers []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedControls []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedBenchmarks []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedCards []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedCharts []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedHierarchies []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedImages []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedInputs []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedTables []*modconfig.DashboardTreeItemDiffs
|
||||
ChangedTexts []*modconfig.DashboardTreeItemDiffs
|
||||
|
||||
NewDashboards []*modconfig.DashboardContainer
|
||||
NewContainers []*modconfig.DashboardContainer
|
||||
NewControls []*modconfig.Control
|
||||
NewBenchmarks []*modconfig.Benchmark
|
||||
NewCards []*modconfig.DashboardCard
|
||||
NewCharts []*modconfig.DashboardChart
|
||||
NewHierarchies []*modconfig.DashboardHierarchy
|
||||
NewImages []*modconfig.DashboardImage
|
||||
NewInputs []*modconfig.DashboardInput
|
||||
NewTables []*modconfig.DashboardTable
|
||||
NewTexts []*modconfig.DashboardText
|
||||
|
||||
DeletedDashboards []*modconfig.DashboardContainer
|
||||
DeletedContainers []*modconfig.DashboardContainer
|
||||
DeletedControls []*modconfig.Control
|
||||
DeletedBenchmarks []*modconfig.Benchmark
|
||||
DeletedCards []*modconfig.DashboardCard
|
||||
DeletedCharts []*modconfig.DashboardChart
|
||||
DeletedHierarchies []*modconfig.DashboardHierarchy
|
||||
DeletedImages []*modconfig.DashboardImage
|
||||
DeletedInputs []*modconfig.DashboardInput
|
||||
DeletedTables []*modconfig.DashboardTable
|
||||
DeletedTexts []*modconfig.DashboardText
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*DashboardChanged) IsDashboardEvent() {}
|
||||
|
||||
func (c *DashboardChanged) HasChanges() bool {
|
||||
return len(c.ChangedDashboards)+
|
||||
len(c.ChangedContainers)+
|
||||
len(c.ChangedBenchmarks)+
|
||||
len(c.ChangedControls)+
|
||||
len(c.ChangedCards)+
|
||||
len(c.ChangedCharts)+
|
||||
len(c.ChangedHierarchies)+
|
||||
len(c.ChangedImages)+
|
||||
len(c.ChangedInputs)+
|
||||
len(c.ChangedTables)+
|
||||
len(c.ChangedTexts)+
|
||||
len(c.NewDashboards)+
|
||||
len(c.NewContainers)+
|
||||
len(c.NewBenchmarks)+
|
||||
len(c.NewControls)+
|
||||
len(c.NewCards)+
|
||||
len(c.NewCharts)+
|
||||
len(c.NewHierarchies)+
|
||||
len(c.NewImages)+
|
||||
len(c.NewInputs)+
|
||||
len(c.NewTables)+
|
||||
len(c.NewTexts)+
|
||||
len(c.DeletedDashboards)+
|
||||
len(c.DeletedContainers)+
|
||||
len(c.DeletedBenchmarks)+
|
||||
len(c.DeletedControls)+
|
||||
len(c.DeletedCards)+
|
||||
len(c.DeletedCharts)+
|
||||
len(c.DeletedHierarchies)+
|
||||
len(c.DeletedImages)+
|
||||
len(c.DeletedInputs)+
|
||||
len(c.DeletedTables)+
|
||||
len(c.DeletedTexts) > 0
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type DashboardComplete struct {
|
||||
Dashboard dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*DashboardComplete) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type DashboardError struct {
|
||||
Dashboard dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*DashboardError) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dashboardevents
|
||||
|
||||
type DashboardEvent interface {
|
||||
IsDashboardEvent()
|
||||
}
|
||||
type DashboardEventHandler func(DashboardEvent)
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type ExecutionComplete struct {
|
||||
Dashboard dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*ExecutionComplete) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type ExecutionStarted struct {
|
||||
DashboardNode dashboardinterfaces.DashboardNodeRun `json:"dashboard"`
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*ExecutionStarted) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeComplete struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*LeafNodeComplete) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeError struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*LeafNodeError) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dashboardevents
|
||||
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeProgress struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*LeafNodeProgress) IsDashboardEvent() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dashboardevents
|
||||
|
||||
type WorkspaceError struct {
|
||||
Error error
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
func (*WorkspaceError) IsDashboardEvent() {}
|
||||
@@ -1,18 +1,18 @@
|
||||
package reportexecute
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"reflect"
|
||||
|
||||
"github.com/turbot/steampipe/control/controlexecute"
|
||||
"github.com/turbot/steampipe/control/controlhooks"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
// CheckRun is a struct representing the execution of a leaf reporting node
|
||||
// CheckRun is a struct representing the execution of a leaf dashboard node
|
||||
type CheckRun struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title,omitempty"`
|
||||
@@ -20,15 +20,15 @@ type CheckRun struct {
|
||||
Error error `json:"error,omitempty"`
|
||||
NodeType string `json:"node_type"`
|
||||
ControlExecutionTree *controlexecute.ExecutionTree `json:"execution_tree"`
|
||||
ReportName string `json:"report"`
|
||||
ReportNode modconfig.ReportLeafNode `json:"-"`
|
||||
Path []string `json:"-"`
|
||||
parent reportinterfaces.ReportNodeParent
|
||||
runStatus reportinterfaces.ReportRunStatus
|
||||
executionTree *ReportExecutionTree
|
||||
DashboardName string `json:"dashboard"`
|
||||
DashboardNode modconfig.DashboardLeafNode `json:"-"`
|
||||
Path []string `json:"-"`
|
||||
parent dashboardinterfaces.DashboardNodeParent
|
||||
runStatus dashboardinterfaces.DashboardRunStatus
|
||||
executionTree *DashboardExecutionTree
|
||||
}
|
||||
|
||||
func NewCheckRun(resource modconfig.ReportLeafNode, parent reportinterfaces.ReportNodeParent, executionTree *ReportExecutionTree) (*CheckRun, error) {
|
||||
func NewCheckRun(resource modconfig.DashboardLeafNode, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*CheckRun, error) {
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(resource.Name())
|
||||
|
||||
@@ -37,14 +37,14 @@ func NewCheckRun(resource modconfig.ReportLeafNode, parent reportinterfaces.Repo
|
||||
Title: resource.GetTitle(),
|
||||
Width: resource.GetWidth(),
|
||||
Path: resource.GetPaths()[0],
|
||||
ReportNode: resource,
|
||||
ReportName: executionTree.reportName,
|
||||
DashboardNode: resource,
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
|
||||
// set to complete, optimistically
|
||||
// if any children have SQL we will set this to ReportRunReady instead
|
||||
runStatus: reportinterfaces.ReportRunComplete,
|
||||
// if any children have SQL we will set this to DashboardRunReady instead
|
||||
runStatus: dashboardinterfaces.DashboardRunComplete,
|
||||
}
|
||||
// verify node type
|
||||
switch resource.(type) {
|
||||
@@ -57,16 +57,16 @@ func NewCheckRun(resource modconfig.ReportLeafNode, parent reportinterfaces.Repo
|
||||
}
|
||||
|
||||
// set status to ready
|
||||
r.runStatus = reportinterfaces.ReportRunReady
|
||||
r.runStatus = dashboardinterfaces.DashboardRunReady
|
||||
|
||||
// add r into execution tree
|
||||
executionTree.runs[r.Name] = r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Execute implements ReportRunNode
|
||||
// Execute implements DashboardRunNode
|
||||
func (r *CheckRun) Execute(ctx context.Context) error {
|
||||
executionTree, err := controlexecute.NewExecutionTree(ctx, r.executionTree.workspace, r.executionTree.client, r.ReportNode.Name())
|
||||
executionTree, err := controlexecute.NewExecutionTree(ctx, r.executionTree.workspace, r.executionTree.client, r.DashboardNode.Name())
|
||||
if err != nil {
|
||||
// set the error status on the counter - this will raise counter error event
|
||||
r.SetError(err)
|
||||
@@ -83,47 +83,47 @@ func (r *CheckRun) Execute(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetName implements ReportNodeRun
|
||||
// GetName implements DashboardNodeRun
|
||||
func (r *CheckRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements ReportNodeRun
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *CheckRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements ReportNodeRun
|
||||
func (r *CheckRun) GetRunStatus() reportinterfaces.ReportRunStatus {
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *CheckRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.runStatus
|
||||
}
|
||||
|
||||
// SetError implements ReportNodeRun
|
||||
// SetError implements DashboardNodeRun
|
||||
func (r *CheckRun) SetError(err error) {
|
||||
r.Error = err
|
||||
r.runStatus = reportinterfaces.ReportRunError
|
||||
r.runStatus = dashboardinterfaces.DashboardRunError
|
||||
// raise counter error event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.LeafNodeError{Node: r})
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeError{Node: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
|
||||
}
|
||||
|
||||
// SetComplete implements ReportNodeRun
|
||||
// SetComplete implements DashboardNodeRun
|
||||
func (r *CheckRun) SetComplete() {
|
||||
r.runStatus = reportinterfaces.ReportRunComplete
|
||||
r.runStatus = dashboardinterfaces.DashboardRunComplete
|
||||
// raise counter complete event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.LeafNodeComplete{Node: r})
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeComplete{Node: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
}
|
||||
|
||||
// RunComplete implements ReportNodeRun
|
||||
// RunComplete implements DashboardNodeRun
|
||||
func (r *CheckRun) RunComplete() bool {
|
||||
return r.runStatus == reportinterfaces.ReportRunComplete || r.runStatus == reportinterfaces.ReportRunError
|
||||
return r.runStatus == dashboardinterfaces.DashboardRunComplete || r.runStatus == dashboardinterfaces.DashboardRunError
|
||||
}
|
||||
|
||||
// ChildrenComplete implements ReportNodeRun
|
||||
// ChildrenComplete implements DashboardNodeRun
|
||||
func (r *CheckRun) ChildrenComplete() bool {
|
||||
return r.RunComplete()
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/utils"
|
||||
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
// TODO [reports] split into report and container
|
||||
// update events
|
||||
// DashboardContainerRun is a struct representing a container run
|
||||
|
||||
type DashboardContainerRun struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Width int `json:"width,omitempty"`
|
||||
Height int `json:"height,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
SQL string `json:"sql,omitempty"`
|
||||
Error error `json:"error,omitempty"`
|
||||
Children []dashboardinterfaces.DashboardNodeRun `json:"children,omitempty"`
|
||||
NodeType string `json:"node_type"`
|
||||
Status dashboardinterfaces.DashboardRunStatus `json:"status"`
|
||||
DashboardName string `json:"report"`
|
||||
Path []string `json:"-"`
|
||||
dashboardNode *modconfig.DashboardContainer
|
||||
parent dashboardinterfaces.DashboardNodeParent
|
||||
executionTree *DashboardExecutionTree
|
||||
childComplete chan dashboardinterfaces.DashboardNodeRun
|
||||
}
|
||||
|
||||
func NewDashboardContainerRun(container *modconfig.DashboardContainer, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*DashboardContainerRun, error) {
|
||||
children := container.GetChildren()
|
||||
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(container.Name())
|
||||
|
||||
r := &DashboardContainerRun{
|
||||
Name: name,
|
||||
NodeType: container.HclType,
|
||||
Path: container.Paths[0],
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
dashboardNode: container,
|
||||
|
||||
// set to complete, optimistically
|
||||
// if any children have SQL we will set this to DashboardRunReady instead
|
||||
Status: dashboardinterfaces.DashboardRunComplete,
|
||||
childComplete: make(chan dashboardinterfaces.DashboardNodeRun, len(children)),
|
||||
}
|
||||
if container.Title != nil {
|
||||
r.Title = *container.Title
|
||||
}
|
||||
|
||||
if container.Width != nil {
|
||||
r.Width = *container.Width
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
var childRun dashboardinterfaces.DashboardNodeRun
|
||||
var err error
|
||||
switch i := child.(type) {
|
||||
case *modconfig.DashboardContainer:
|
||||
childRun, err = NewDashboardContainerRun(i, r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *modconfig.Benchmark, *modconfig.Control:
|
||||
childRun, err = NewCheckRun(i.(modconfig.DashboardLeafNode), r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
// ensure this item is a DashboardLeafNode
|
||||
leafNode, ok := i.(modconfig.DashboardLeafNode)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("child %s does not implement DashboardLeafNode", i.Name())
|
||||
}
|
||||
|
||||
childRun, err = NewLeafRun(leafNode, r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// should never happen - container children must be either container or counter
|
||||
if childRun == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// if our child has not completed, we have not completed
|
||||
if childRun.GetRunStatus() == dashboardinterfaces.DashboardRunReady {
|
||||
r.Status = dashboardinterfaces.DashboardRunReady
|
||||
}
|
||||
r.Children = append(r.Children, childRun)
|
||||
}
|
||||
// add r into execution tree
|
||||
executionTree.runs[r.Name] = r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Execute implements DashboardRunNode
|
||||
// execute all children and wait for them to complete
|
||||
func (r *DashboardContainerRun) Execute(ctx context.Context) error {
|
||||
|
||||
errChan := make(chan error, len(r.Children))
|
||||
// execute all children asynchronously
|
||||
for _, child := range r.Children {
|
||||
go r.executeChild(ctx, child, errChan)
|
||||
}
|
||||
|
||||
// wait for children to complete
|
||||
var errors []error
|
||||
for !r.ChildrenComplete() {
|
||||
select {
|
||||
case <-r.childComplete:
|
||||
// fall through to recheck ChildrenComplete
|
||||
case err := <-errChan:
|
||||
errors = append(errors, err)
|
||||
// TODO TIMEOUT??
|
||||
}
|
||||
}
|
||||
|
||||
// so all children have completed - check for errors
|
||||
err := utils.CombineErrors(errors...)
|
||||
if err == nil {
|
||||
// set complete status on dashboard
|
||||
r.SetComplete()
|
||||
} else {
|
||||
r.SetError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *DashboardContainerRun) executeChild(ctx context.Context, child dashboardinterfaces.DashboardNodeRun, errChan chan error) {
|
||||
err := child.Execute(ctx)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
}
|
||||
|
||||
// GetName implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.Status
|
||||
}
|
||||
|
||||
// SetError implements DashboardNodeRun
|
||||
// tell parent we are done
|
||||
func (r *DashboardContainerRun) SetError(err error) {
|
||||
r.Error = err
|
||||
r.Status = dashboardinterfaces.DashboardRunError
|
||||
// raise container error event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.ContainerError{Container: r})
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
|
||||
}
|
||||
|
||||
// SetComplete implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) SetComplete() {
|
||||
r.Status = dashboardinterfaces.DashboardRunComplete
|
||||
// raise container complete event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.ContainerComplete{Container: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
}
|
||||
|
||||
// RunComplete implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) RunComplete() bool {
|
||||
return r.Status == dashboardinterfaces.DashboardRunComplete || r.Status == dashboardinterfaces.DashboardRunError
|
||||
}
|
||||
|
||||
// ChildrenComplete implements DashboardNodeRun
|
||||
func (r *DashboardContainerRun) ChildrenComplete() bool {
|
||||
for _, child := range r.Children {
|
||||
if !child.RunComplete() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *DashboardContainerRun) ChildCompleteChan() chan dashboardinterfaces.DashboardNodeRun {
|
||||
return r.childComplete
|
||||
}
|
||||
|
||||
func (r *DashboardContainerRun) GetRuntimeDependency(dependency *modconfig.RuntimeDependency) (*string, error) {
|
||||
// TOTO [reports] LOCK???
|
||||
|
||||
/// TOTO [reports] nasty - split into report and container
|
||||
if !r.dashboardNode.IsDashboard() {
|
||||
panic("GetRuntimeDependency called on container")
|
||||
}
|
||||
|
||||
// only inputs supported at present
|
||||
if dependency.PropertyPath.ItemType != modconfig.BlockTypeInput {
|
||||
return nil, fmt.Errorf("invalid runtime dependency type %s", dependency.PropertyPath.ItemType)
|
||||
}
|
||||
|
||||
// find the input corresponding to this dependency
|
||||
input, ok := r.dashboardNode.GetInput(dependency.PropertyPath.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("dashboard %s does not contain input %s", r.dashboardNode.Name(), dependency.PropertyPath.ItemType)
|
||||
}
|
||||
return input.Value, nil
|
||||
}
|
||||
+4
-4
@@ -1,10 +1,10 @@
|
||||
package reportexecute
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/turbot/steampipe/control/controlhooks"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
)
|
||||
|
||||
// ControlEventHooks is a struct which implements ControlHooks, and displays the control progress as a status message
|
||||
@@ -23,8 +23,8 @@ func (c *ControlEventHooks) OnStart(ctx context.Context, _ *controlhooks.Control
|
||||
}
|
||||
|
||||
func (c *ControlEventHooks) OnControlEvent(ctx context.Context, _ *controlhooks.ControlProgress) {
|
||||
event := &reportevents.LeafNodeProgress{Node: c.CheckRun}
|
||||
c.CheckRun.executionTree.workspace.PublishReportEvent(event)
|
||||
event := &dashboardevents.LeafNodeProgress{Node: c.CheckRun}
|
||||
c.CheckRun.executionTree.workspace.PublishDashboardEvent(event)
|
||||
}
|
||||
|
||||
func (c *ControlEventHooks) OnDone(ctx context.Context, _ *controlhooks.ControlProgress) {
|
||||
@@ -0,0 +1,116 @@
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
)
|
||||
|
||||
// DashboardExecutionTree is a structure representing the control result hierarchy
|
||||
type DashboardExecutionTree struct {
|
||||
modconfig.UniqueNameProviderBase
|
||||
|
||||
Root *DashboardContainerRun
|
||||
dashboardName string
|
||||
client db_common.Client
|
||||
runs map[string]dashboardinterfaces.DashboardNodeRun
|
||||
workspace *workspace.Workspace
|
||||
runComplete chan dashboardinterfaces.DashboardNodeRun
|
||||
|
||||
inputLock sync.Mutex
|
||||
inputDataSubscriptions map[string][]chan bool
|
||||
}
|
||||
|
||||
// NewReportExecutionTree creates a result group from a ModTreeItem
|
||||
func NewReportExecutionTree(reportName string, client db_common.Client, workspace *workspace.Workspace) (*DashboardExecutionTree, error) {
|
||||
// now populate the DashboardExecutionTree
|
||||
reportExecutionTree := &DashboardExecutionTree{
|
||||
client: client,
|
||||
runs: make(map[string]dashboardinterfaces.DashboardNodeRun),
|
||||
workspace: workspace,
|
||||
runComplete: make(chan dashboardinterfaces.DashboardNodeRun, 1),
|
||||
inputDataSubscriptions: make(map[string][]chan bool),
|
||||
dashboardName: reportName,
|
||||
}
|
||||
|
||||
// create the root run node (either a report run or a counter run)
|
||||
root, err := reportExecutionTree.createRootItem(reportName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reportExecutionTree.Root = root
|
||||
return reportExecutionTree, nil
|
||||
}
|
||||
|
||||
func (e *DashboardExecutionTree) createRootItem(reportName string) (*DashboardContainerRun, error) {
|
||||
parsedName, err := modconfig.ParseResourceName(reportName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if parsedName.ItemType != modconfig.BlockTypeDashboard {
|
||||
return nil, fmt.Errorf("reporting type %s cannot be executed directly - only reports may be executed", parsedName.ItemType)
|
||||
}
|
||||
report, ok := e.workspace.Dashboards[reportName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("report '%s' does not exist in workspace", reportName)
|
||||
}
|
||||
return NewDashboardContainerRun(report, e, e)
|
||||
|
||||
}
|
||||
|
||||
func (e *DashboardExecutionTree) Execute(ctx context.Context) error {
|
||||
log.Println("[TRACE]", "begin DashboardExecutionTree.Execute")
|
||||
defer log.Println("[TRACE]", "end DashboardExecutionTree.Execute")
|
||||
|
||||
if e.runStatus() == dashboardinterfaces.DashboardRunComplete {
|
||||
// there must be no nodes to execute
|
||||
log.Println("[TRACE]", "execution tree already complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
return e.Root.Execute(ctx)
|
||||
}
|
||||
|
||||
func (e *DashboardExecutionTree) runStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return e.Root.GetRunStatus()
|
||||
}
|
||||
|
||||
// GetName implements DashboardNodeParent
|
||||
// use mod chort name - this will be the root name for all child runs
|
||||
func (e *DashboardExecutionTree) GetName() string {
|
||||
return e.workspace.Mod.ShortName
|
||||
}
|
||||
|
||||
// ChildCompleteChan implements DashboardNodeParent
|
||||
func (e *DashboardExecutionTree) ChildCompleteChan() chan dashboardinterfaces.DashboardNodeRun {
|
||||
return e.runComplete
|
||||
}
|
||||
|
||||
func (e *DashboardExecutionTree) waitForRuntimeDependency(ctx context.Context, dependency *modconfig.RuntimeDependency) error {
|
||||
depChan := make(chan (bool), 1)
|
||||
// TOTO [reports] for now verify we only bind inputs to args (somewhere)
|
||||
|
||||
e.subscribeToInput(dependency.PropertyPath.Name, depChan)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-depChan:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DashboardExecutionTree) subscribeToInput(inputName string, depChan chan bool) {
|
||||
e.inputLock.Lock()
|
||||
defer e.inputLock.Unlock()
|
||||
|
||||
e.inputDataSubscriptions[inputName] = append(e.inputDataSubscriptions[inputName], depChan)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/statushooks"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
)
|
||||
|
||||
// map of execution trees, keyed by dashboard name
|
||||
var executions = make(map[string]*DashboardExecutionTree)
|
||||
|
||||
func ExecuteDashboardNode(ctx context.Context, dashboardName string, workspace *workspace.Workspace, client db_common.Client) error {
|
||||
// TODO [reports] if this report is already running - cancel ??? fail???
|
||||
if _, running := executions[dashboardName]; running {
|
||||
return fmt.Errorf("dashboard %s is already running", dashboardName)
|
||||
}
|
||||
|
||||
// create context for the dashboard execution
|
||||
// (for now just disable all status messages - replace with event based? )
|
||||
dashboardCtx := statushooks.DisableStatusHooks(ctx)
|
||||
executionTree, err := NewReportExecutionTree(dashboardName, client, workspace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
executions[dashboardName] = executionTree
|
||||
go func() {
|
||||
workspace.PublishDashboardEvent(&dashboardevents.ExecutionStarted{DashboardNode: executionTree.Root})
|
||||
defer func() {
|
||||
// remove tree from map of executions
|
||||
delete(executions, dashboardName)
|
||||
// send completed event
|
||||
workspace.PublishDashboardEvent(&dashboardevents.ExecutionComplete{Dashboard: executionTree.Root})
|
||||
}()
|
||||
|
||||
if err := executionTree.Execute(dashboardCtx); err != nil {
|
||||
if executionTree.Root.GetRunStatus() != dashboardinterfaces.DashboardRunError {
|
||||
// set error state on the root node
|
||||
executionTree.Root.SetError(err)
|
||||
}
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package reportexecute
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
@@ -1,14 +1,14 @@
|
||||
package reportexecute
|
||||
package dashboardexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
// LeafRun is a struct representing the execution of a leaf reporting node
|
||||
// LeafRun is a struct representing the execution of a leaf dashboard node
|
||||
type LeafRun struct {
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -16,17 +16,17 @@ type LeafRun struct {
|
||||
Width int `json:"width,omitempty"`
|
||||
SQL string `json:"sql,omitempty"`
|
||||
Data *LeafData `json:"data,omitempty"`
|
||||
Error error `json:"error,omitempty"`
|
||||
ReportNode modconfig.ReportLeafNode `json:"properties"`
|
||||
NodeType string `json:"node_type"`
|
||||
ReportName string `json:"report"`
|
||||
Path []string `json:"-"`
|
||||
parent reportinterfaces.ReportNodeParent
|
||||
runStatus reportinterfaces.ReportRunStatus
|
||||
executionTree *ReportExecutionTree
|
||||
Error error `json:"error,omitempty"`
|
||||
DashboardNode modconfig.DashboardLeafNode `json:"properties"`
|
||||
NodeType string `json:"node_type"`
|
||||
DashboardName string `json:"dashboard"`
|
||||
Path []string `json:"-"`
|
||||
parent dashboardinterfaces.DashboardNodeParent
|
||||
runStatus dashboardinterfaces.DashboardRunStatus
|
||||
executionTree *DashboardExecutionTree
|
||||
}
|
||||
|
||||
func NewLeafRun(resource modconfig.ReportLeafNode, parent reportinterfaces.ReportNodeParent, executionTree *ReportExecutionTree) (*LeafRun, error) {
|
||||
func NewLeafRun(resource modconfig.DashboardLeafNode, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*LeafRun, error) {
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(resource.Name())
|
||||
|
||||
@@ -36,14 +36,14 @@ func NewLeafRun(resource modconfig.ReportLeafNode, parent reportinterfaces.Repor
|
||||
Width: resource.GetWidth(),
|
||||
SQL: resource.GetSQL(),
|
||||
Path: resource.GetPaths()[0],
|
||||
ReportNode: resource,
|
||||
ReportName: executionTree.reportName,
|
||||
DashboardNode: resource,
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
|
||||
// set to complete, optimistically
|
||||
// if any children have SQL we will set this to ReportRunReady instead
|
||||
runStatus: reportinterfaces.ReportRunComplete,
|
||||
// if any children have SQL we will set this to DashboardRunReady instead
|
||||
runStatus: dashboardinterfaces.DashboardRunComplete,
|
||||
}
|
||||
|
||||
parsedName, err := modconfig.ParseResourceName(resource.Name())
|
||||
@@ -53,7 +53,7 @@ func NewLeafRun(resource modconfig.ReportLeafNode, parent reportinterfaces.Repor
|
||||
r.NodeType = parsedName.ItemType
|
||||
// if we have sql, set status to ready
|
||||
if r.SQL != "" {
|
||||
r.runStatus = reportinterfaces.ReportRunReady
|
||||
r.runStatus = dashboardinterfaces.DashboardRunReady
|
||||
}
|
||||
|
||||
// add r into execution tree
|
||||
@@ -61,7 +61,7 @@ func NewLeafRun(resource modconfig.ReportLeafNode, parent reportinterfaces.Repor
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Execute implements ReportRunNode
|
||||
// Execute implements DashboardRunNode
|
||||
func (r *LeafRun) Execute(ctx context.Context) error {
|
||||
// if there are any unresolved runtime dependencies, wait for them
|
||||
if err := r.waitForRuntimeDependencies(ctx); err != nil {
|
||||
@@ -86,58 +86,58 @@ func (r *LeafRun) Execute(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetName implements ReportNodeRun
|
||||
// GetName implements DashboardNodeRun
|
||||
func (r *LeafRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements ReportNodeRun
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *LeafRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements ReportNodeRun
|
||||
func (r *LeafRun) GetRunStatus() reportinterfaces.ReportRunStatus {
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *LeafRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.runStatus
|
||||
}
|
||||
|
||||
// SetError implements ReportNodeRun
|
||||
// SetError implements DashboardNodeRun
|
||||
func (r *LeafRun) SetError(err error) {
|
||||
r.Error = err
|
||||
r.runStatus = reportinterfaces.ReportRunError
|
||||
r.runStatus = dashboardinterfaces.DashboardRunError
|
||||
// raise counter error event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.LeafNodeError{Node: r})
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeError{Node: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
|
||||
}
|
||||
|
||||
// SetComplete implements ReportNodeRun
|
||||
// SetComplete implements DashboardNodeRun
|
||||
func (r *LeafRun) SetComplete() {
|
||||
r.runStatus = reportinterfaces.ReportRunComplete
|
||||
r.runStatus = dashboardinterfaces.DashboardRunComplete
|
||||
// raise counter complete event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.LeafNodeComplete{Node: r})
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeComplete{Node: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
}
|
||||
|
||||
// RunComplete implements ReportNodeRun
|
||||
// RunComplete implements DashboardNodeRun
|
||||
func (r *LeafRun) RunComplete() bool {
|
||||
return r.runStatus == reportinterfaces.ReportRunComplete || r.runStatus == reportinterfaces.ReportRunError
|
||||
return r.runStatus == dashboardinterfaces.DashboardRunComplete || r.runStatus == dashboardinterfaces.DashboardRunError
|
||||
}
|
||||
|
||||
// ChildrenComplete implements ReportNodeRun
|
||||
// ChildrenComplete implements DashboardNodeRun
|
||||
func (r *LeafRun) ChildrenComplete() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *LeafRun) waitForRuntimeDependencies(ctx context.Context) error {
|
||||
runtimeDependencies := r.ReportNode.GetRuntimeDependencies()
|
||||
runtimeDependencies := r.DashboardNode.GetRuntimeDependencies()
|
||||
|
||||
// runtime dependencies are always (for now) report inputs
|
||||
// runtime dependencies are always (for now) dashboard inputs
|
||||
|
||||
for _, dependency := range runtimeDependencies {
|
||||
// check with the top level report whether the dependency is available
|
||||
// check with the top level dashboard whether the dependency is available
|
||||
inputValue, err := r.executionTree.Root.GetRuntimeDependency(dependency)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -0,0 +1,31 @@
|
||||
package dashboardinterfaces
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
type DashboardRunStatus string
|
||||
|
||||
const (
|
||||
DashboardRunReady DashboardRunStatus = "ready"
|
||||
DashboardRunComplete = "complete"
|
||||
DashboardRunError = "error"
|
||||
)
|
||||
|
||||
type DashboardNodeRun interface {
|
||||
Execute(ctx context.Context) error
|
||||
GetName() string
|
||||
GetPath() modconfig.NodePath
|
||||
GetRunStatus() DashboardRunStatus
|
||||
SetError(err error)
|
||||
SetComplete()
|
||||
RunComplete() bool
|
||||
ChildrenComplete() bool
|
||||
}
|
||||
|
||||
type DashboardNodeParent interface {
|
||||
GetName() string
|
||||
ChildCompleteChan() chan DashboardNodeRun
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package reportserver
|
||||
package dashboardserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -43,7 +43,7 @@ func StartAPI(ctx context.Context, webSocket *melody.Melody) *http.Server {
|
||||
// only add the Recovery middleware
|
||||
router.Use(gin.Recovery())
|
||||
|
||||
assetsDirectory := filepaths.EnsureReportAssetsDir()
|
||||
assetsDirectory := filepaths.EnsureDashboardAssetsDir()
|
||||
|
||||
router.Use(static.Serve("/", static.LocalFile(assetsDirectory, true)))
|
||||
|
||||
@@ -55,14 +55,14 @@ func StartAPI(ctx context.Context, webSocket *melody.Melody) *http.Server {
|
||||
c.File(path.Join(assetsDirectory, "index.html"))
|
||||
})
|
||||
|
||||
reportServerPort := viper.GetInt(constants.ArgReportServerPort)
|
||||
reportServerListen := "localhost"
|
||||
if viper.GetString(constants.ArgReportServerListen) == string(ListenTypeNetwork) {
|
||||
reportServerListen = ""
|
||||
dashboardServerPort := viper.GetInt(constants.ArgDashboardServerPort)
|
||||
dashboardServerListen := "localhost"
|
||||
if viper.GetString(constants.ArgDashboardServerListen) == string(ListenTypeNetwork) {
|
||||
dashboardServerListen = ""
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: fmt.Sprintf("%s:%d", reportServerListen, reportServerPort),
|
||||
Addr: fmt.Sprintf("%s:%d", dashboardServerListen, dashboardServerPort),
|
||||
Handler: router,
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ func StartAPI(ctx context.Context, webSocket *melody.Melody) *http.Server {
|
||||
}
|
||||
}()
|
||||
|
||||
_ = openBrowser(fmt.Sprintf("http://localhost:%d", reportServerPort))
|
||||
outputReady(ctx, fmt.Sprintf("Report server started on %d and listening on %s", reportServerPort, viper.GetString(constants.ArgReportServerListen)))
|
||||
_ = openBrowser(fmt.Sprintf("http://localhost:%d", dashboardServerPort))
|
||||
outputReady(ctx, fmt.Sprintf("Dashboard server started on %d and listening on %s", dashboardServerPort, viper.GetString(constants.ArgDashboardServerListen)))
|
||||
<-ctx.Done()
|
||||
log.Println("Shutdown Server ...")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package reportserver
|
||||
package dashboardserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package reportserver
|
||||
package dashboardserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,17 +9,16 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"gopkg.in/olahol/melody.v1"
|
||||
|
||||
"github.com/turbot/go-kit/helpers"
|
||||
typeHelpers "github.com/turbot/go-kit/types"
|
||||
"github.com/turbot/steampipe/constants"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardexecute"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/report/reportexecute"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
"gopkg.in/olahol/melody.v1"
|
||||
)
|
||||
|
||||
type ListenType string
|
||||
@@ -48,12 +47,13 @@ func (lp ListenPort) IsValid() error {
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
context context.Context
|
||||
dbClient db_common.Client
|
||||
mutex *sync.Mutex
|
||||
reportClients map[*melody.Session]*ReportClientInfo
|
||||
webSocket *melody.Melody
|
||||
workspace *workspace.Workspace
|
||||
context context.Context
|
||||
dbClient db_common.Client
|
||||
mutex *sync.Mutex
|
||||
dashboardClients map[*melody.Session]*DashboardClientInfo
|
||||
webSocket *melody.Melody
|
||||
workspace *workspace.Workspace
|
||||
workspaceResources *modconfig.WorkspaceResourceMaps
|
||||
}
|
||||
|
||||
type ErrorPayload struct {
|
||||
@@ -62,12 +62,12 @@ type ErrorPayload struct {
|
||||
}
|
||||
|
||||
type ExecutionPayload struct {
|
||||
Action string `json:"action"`
|
||||
ReportNode reportinterfaces.ReportNodeRun `json:"report_node"`
|
||||
Action string `json:"action"`
|
||||
ReportNode dashboardinterfaces.DashboardNodeRun `json:"report_node"`
|
||||
}
|
||||
|
||||
type ReportClientInfo struct {
|
||||
Report *string
|
||||
type DashboardClientInfo struct {
|
||||
Dashboard *string
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, dbClient db_common.Client) (*Server, error) {
|
||||
@@ -79,31 +79,32 @@ func NewServer(ctx context.Context, dbClient db_common.Client) (*Server, error)
|
||||
|
||||
webSocket := melody.New()
|
||||
|
||||
var reportClients = make(map[*melody.Session]*ReportClientInfo)
|
||||
var reportClients = make(map[*melody.Session]*DashboardClientInfo)
|
||||
|
||||
var mutex = &sync.Mutex{}
|
||||
|
||||
server := &Server{
|
||||
context: ctx,
|
||||
dbClient: dbClient,
|
||||
mutex: mutex,
|
||||
reportClients: reportClients,
|
||||
webSocket: webSocket,
|
||||
workspace: loadedWorkspace,
|
||||
context: ctx,
|
||||
dbClient: dbClient,
|
||||
mutex: mutex,
|
||||
dashboardClients: reportClients,
|
||||
webSocket: webSocket,
|
||||
workspace: loadedWorkspace,
|
||||
workspaceResources: loadedWorkspace.GetResourceMaps(),
|
||||
}
|
||||
|
||||
loadedWorkspace.RegisterReportEventHandler(server.HandleWorkspaceUpdate)
|
||||
loadedWorkspace.RegisterDashboardEventHandler(server.HandleWorkspaceUpdate)
|
||||
err = loadedWorkspace.SetupWatcher(ctx, dbClient, func(c context.Context, e error) {})
|
||||
outputMessage(ctx, "Workspace loaded")
|
||||
|
||||
return server, err
|
||||
}
|
||||
|
||||
func buildDashboardMetadataPayload(workspace *workspace.Workspace) ([]byte, error) {
|
||||
func buildDashboardMetadataPayload(workspaceResources *modconfig.WorkspaceResourceMaps) ([]byte, error) {
|
||||
installedMods := make(map[string]ModDashboardMetadata)
|
||||
for _, mod := range workspace.Mods {
|
||||
for _, mod := range workspaceResources.Mods {
|
||||
// Ignore current mod
|
||||
if mod.FullName == workspace.Mod.FullName {
|
||||
if mod.FullName == workspaceResources.Mod.FullName {
|
||||
continue
|
||||
}
|
||||
installedMods[mod.FullName] = ModDashboardMetadata{
|
||||
@@ -117,9 +118,9 @@ func buildDashboardMetadataPayload(workspace *workspace.Workspace) ([]byte, erro
|
||||
Action: "dashboard_metadata",
|
||||
Metadata: DashboardMetadata{
|
||||
Mod: ModDashboardMetadata{
|
||||
Title: typeHelpers.SafeString(workspace.Mod.Title),
|
||||
FullName: workspace.Mod.FullName,
|
||||
ShortName: workspace.Mod.ShortName,
|
||||
Title: typeHelpers.SafeString(workspaceResources.Mod.Title),
|
||||
FullName: workspaceResources.Mod.FullName,
|
||||
ShortName: workspaceResources.Mod.ShortName,
|
||||
},
|
||||
InstalledMods: installedMods,
|
||||
},
|
||||
@@ -127,14 +128,14 @@ func buildDashboardMetadataPayload(workspace *workspace.Workspace) ([]byte, erro
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func buildAvailableDashboardsPayload(workspace *workspace.Workspace) ([]byte, error) {
|
||||
func buildAvailableDashboardsPayload(workspace *modconfig.WorkspaceResourceMaps) ([]byte, error) {
|
||||
dashboardsByMod := make(map[string]map[string]ModAvailableDashboard)
|
||||
for _, mod := range workspace.Mods {
|
||||
_, ok := dashboardsByMod[mod.FullName]
|
||||
if !ok {
|
||||
dashboardsByMod[mod.FullName] = make(map[string]ModAvailableDashboard)
|
||||
}
|
||||
for _, report := range mod.Reports {
|
||||
for _, report := range mod.Dashboards {
|
||||
dashboardsByMod[mod.FullName][report.FullName] = ModAvailableDashboard{
|
||||
Title: typeHelpers.SafeString(report.Title),
|
||||
FullName: report.FullName,
|
||||
@@ -149,7 +150,7 @@ func buildAvailableDashboardsPayload(workspace *workspace.Workspace) ([]byte, er
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func buildWorkspaceErrorPayload(e *reportevents.WorkspaceError) ([]byte, error) {
|
||||
func buildWorkspaceErrorPayload(e *dashboardevents.WorkspaceError) ([]byte, error) {
|
||||
payload := ErrorPayload{
|
||||
Action: "workspace_error",
|
||||
Error: e.Error.Error(),
|
||||
@@ -157,7 +158,7 @@ func buildWorkspaceErrorPayload(e *reportevents.WorkspaceError) ([]byte, error)
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func buildLeafNodeProgressPayload(event *reportevents.LeafNodeProgress) ([]byte, error) {
|
||||
func buildLeafNodeProgressPayload(event *dashboardevents.LeafNodeProgress) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "leaf_node_progress",
|
||||
ReportNode: event.Node,
|
||||
@@ -165,7 +166,7 @@ func buildLeafNodeProgressPayload(event *reportevents.LeafNodeProgress) ([]byte,
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func buildLeafNodeCompletePayload(event *reportevents.LeafNodeComplete) ([]byte, error) {
|
||||
func buildLeafNodeCompletePayload(event *dashboardevents.LeafNodeComplete) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "leaf_node_complete",
|
||||
ReportNode: event.Node,
|
||||
@@ -180,23 +181,23 @@ func buildLeafNodeCompletePayload(event *reportevents.LeafNodeComplete) ([]byte,
|
||||
return jsonString, err
|
||||
}
|
||||
|
||||
func buildExecutionStartedPayload(event *reportevents.ExecutionStarted) ([]byte, error) {
|
||||
func buildExecutionStartedPayload(event *dashboardevents.ExecutionStarted) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "execution_started",
|
||||
ReportNode: event.ReportNode,
|
||||
ReportNode: event.DashboardNode,
|
||||
}
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func buildExecutionCompletePayload(event *reportevents.ExecutionComplete) ([]byte, error) {
|
||||
func buildExecutionCompletePayload(event *dashboardevents.ExecutionComplete) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "execution_complete",
|
||||
ReportNode: event.Report,
|
||||
ReportNode: event.Dashboard,
|
||||
}
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
func getReportsInterestedInResourceChanges(reportsBeingWatched []string, existingChangedReportNames []string, changedItems []*modconfig.ReportTreeItemDiffs) []string {
|
||||
func getReportsInterestedInResourceChanges(reportsBeingWatched []string, existingChangedReportNames []string, changedItems []*modconfig.DashboardTreeItemDiffs) []string {
|
||||
var changedReportNames []string
|
||||
|
||||
for _, changedItem := range changedItems {
|
||||
@@ -205,7 +206,7 @@ func getReportsInterestedInResourceChanges(reportsBeingWatched []string, existin
|
||||
for _, nodeName := range nodePath {
|
||||
resourceParts, _ := modconfig.ParseResourceName(nodeName)
|
||||
// We only care about changes from these resource types
|
||||
if resourceParts.ItemType != modconfig.BlockTypeReport {
|
||||
if resourceParts.ItemType != modconfig.BlockTypeDashboard {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -223,7 +224,7 @@ func getReportsInterestedInResourceChanges(reportsBeingWatched []string, existin
|
||||
|
||||
// Start starts the API server
|
||||
func (s *Server) Start() {
|
||||
go Init(s.context, s.webSocket, s.workspace, s.dbClient, s.reportClients, s.mutex)
|
||||
go s.Init(s.context)
|
||||
go StartAPI(s.context, s.webSocket)
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ func (s *Server) Shutdown(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
var payloadError error
|
||||
var payload []byte
|
||||
defer func() {
|
||||
@@ -258,7 +259,7 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
|
||||
switch e := event.(type) {
|
||||
|
||||
case *reportevents.WorkspaceError:
|
||||
case *dashboardevents.WorkspaceError:
|
||||
log.Println("[TRACE] Got workspace error event", *e)
|
||||
payload, payloadError = buildWorkspaceErrorPayload(e)
|
||||
if payloadError != nil {
|
||||
@@ -267,27 +268,27 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
s.webSocket.Broadcast(payload)
|
||||
outputError(s.context, e.Error)
|
||||
|
||||
case *reportevents.ExecutionStarted:
|
||||
case *dashboardevents.ExecutionStarted:
|
||||
log.Println("[TRACE] Got execution started event", *e)
|
||||
payload, payloadError = buildExecutionStartedPayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
}
|
||||
reportName := e.ReportNode.GetName()
|
||||
dashboardName := e.DashboardNode.GetName()
|
||||
s.mutex.Lock()
|
||||
for session, repoInfo := range s.reportClients {
|
||||
// If this session is interested in this report, broadcast to it
|
||||
if (repoInfo.Report != nil) && *repoInfo.Report == reportName {
|
||||
for session, repoInfo := range s.dashboardClients {
|
||||
// If this session is interested in this dashboard, broadcast to it
|
||||
if (repoInfo.Dashboard != nil) && *repoInfo.Dashboard == dashboardName {
|
||||
session.Write(payload)
|
||||
}
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
outputWait(s.context, fmt.Sprintf("Report execution started: %s", reportName))
|
||||
outputWait(s.context, fmt.Sprintf("Report execution started: %s", dashboardName))
|
||||
|
||||
case *reportevents.LeafNodeError:
|
||||
case *dashboardevents.LeafNodeError:
|
||||
log.Println("[TRACE] Got leaf node error event", *e)
|
||||
|
||||
case *reportevents.LeafNodeProgress:
|
||||
case *dashboardevents.LeafNodeProgress:
|
||||
log.Println("[TRACE] Got leaf node complete event", *e)
|
||||
payload, payloadError = buildLeafNodeProgressPayload(e)
|
||||
if payloadError != nil {
|
||||
@@ -295,15 +296,15 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
}
|
||||
paths := e.Node.GetPath()
|
||||
s.mutex.Lock()
|
||||
for session, repoInfo := range s.reportClients {
|
||||
for session, repoInfo := range s.dashboardClients {
|
||||
// If this session is interested in this report, broadcast to it
|
||||
if (repoInfo.Report != nil) && helpers.StringSliceContains(paths, *repoInfo.Report) {
|
||||
if (repoInfo.Dashboard != nil) && helpers.StringSliceContains(paths, *repoInfo.Dashboard) {
|
||||
session.Write(payload)
|
||||
}
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
||||
case *reportevents.LeafNodeComplete:
|
||||
case *dashboardevents.LeafNodeComplete:
|
||||
log.Println("[TRACE] Got leaf node complete event", *e)
|
||||
payload, payloadError = buildLeafNodeCompletePayload(e)
|
||||
if payloadError != nil {
|
||||
@@ -311,18 +312,18 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
}
|
||||
paths := e.Node.GetPath()
|
||||
s.mutex.Lock()
|
||||
for session, repoInfo := range s.reportClients {
|
||||
for session, repoInfo := range s.dashboardClients {
|
||||
// If this session is interested in this report, broadcast to it
|
||||
if (repoInfo.Report != nil) && helpers.StringSliceContains(paths, *repoInfo.Report) {
|
||||
if (repoInfo.Dashboard != nil) && helpers.StringSliceContains(paths, *repoInfo.Dashboard) {
|
||||
session.Write(payload)
|
||||
}
|
||||
}
|
||||
s.mutex.Unlock()
|
||||
|
||||
case *reportevents.ReportChanged:
|
||||
case *dashboardevents.DashboardChanged:
|
||||
log.Println("[TRACE] Got report changed event", *e)
|
||||
deletedReports := e.DeletedReports
|
||||
newReports := e.NewReports
|
||||
deletedDashboards := e.DeletedDashboards
|
||||
newDashboards := e.NewDashboards
|
||||
|
||||
changedContainers := e.ChangedContainers
|
||||
changedBenchmarks := e.ChangedBenchmarks
|
||||
@@ -334,11 +335,11 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
changedInputs := e.ChangedInputs
|
||||
changedTables := e.ChangedTables
|
||||
changedTexts := e.ChangedTexts
|
||||
changedReports := e.ChangedReports
|
||||
changedDashboards := e.ChangedDashboards
|
||||
|
||||
// If nothing has changed, ignore
|
||||
if len(deletedReports) == 0 &&
|
||||
len(newReports) == 0 &&
|
||||
if len(deletedDashboards) == 0 &&
|
||||
len(newDashboards) == 0 &&
|
||||
len(changedContainers) == 0 &&
|
||||
len(changedBenchmarks) == 0 &&
|
||||
len(changedControls) == 0 &&
|
||||
@@ -349,18 +350,18 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
len(changedInputs) == 0 &&
|
||||
len(changedTables) == 0 &&
|
||||
len(changedTexts) == 0 &&
|
||||
len(changedReports) == 0 {
|
||||
len(changedDashboards) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for k, v := range s.reportClients {
|
||||
log.Printf("[TRACE] Report client: %v %v\n", k, typeHelpers.SafeString(v.Report))
|
||||
for k, v := range s.dashboardClients {
|
||||
log.Printf("[TRACE] Report client: %v %v\n", k, typeHelpers.SafeString(v.Dashboard))
|
||||
}
|
||||
|
||||
// If) any deleted/new/changed reports, emit an available reports message to clients
|
||||
if len(deletedReports) != 0 || len(newReports) != 0 || len(changedReports) != 0 {
|
||||
if len(deletedDashboards) != 0 || len(newDashboards) != 0 || len(changedDashboards) != 0 {
|
||||
outputMessage(s.context, "Available Reports updated")
|
||||
payload, payloadError = buildAvailableDashboardsPayload(s.workspace)
|
||||
payload, payloadError = buildAvailableDashboardsPayload(s.workspaceResources)
|
||||
if payloadError != nil {
|
||||
return
|
||||
}
|
||||
@@ -369,9 +370,9 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
|
||||
var reportsBeingWatched []string
|
||||
s.mutex.Lock()
|
||||
for _, reportClientInfo := range s.reportClients {
|
||||
reportName := typeHelpers.SafeString(reportClientInfo.Report)
|
||||
if reportClientInfo.Report != nil {
|
||||
for _, reportClientInfo := range s.dashboardClients {
|
||||
reportName := typeHelpers.SafeString(reportClientInfo.Dashboard)
|
||||
if reportClientInfo.Dashboard != nil {
|
||||
if helpers.StringSliceContains(reportsBeingWatched, reportName) {
|
||||
continue
|
||||
}
|
||||
@@ -381,7 +382,7 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
s.mutex.Unlock()
|
||||
|
||||
var changedReportNames []string
|
||||
var newReportNames []string
|
||||
var newDashboardNames []string
|
||||
|
||||
// Process the changed items and make a note of the report(s) they're in
|
||||
changedReportNames = append(changedReportNames, getReportsInterestedInResourceChanges(reportsBeingWatched, changedReportNames, changedContainers)...)
|
||||
@@ -395,7 +396,7 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
changedReportNames = append(changedReportNames, getReportsInterestedInResourceChanges(reportsBeingWatched, changedReportNames, changedTables)...)
|
||||
changedReportNames = append(changedReportNames, getReportsInterestedInResourceChanges(reportsBeingWatched, changedReportNames, changedTexts)...)
|
||||
|
||||
for _, changedReport := range changedReports {
|
||||
for _, changedReport := range changedDashboards {
|
||||
if helpers.StringSliceContains(changedReportNames, changedReport.Name) {
|
||||
continue
|
||||
}
|
||||
@@ -404,43 +405,43 @@ func (s *Server) HandleWorkspaceUpdate(event reportevents.ReportEvent) {
|
||||
|
||||
for _, changedReportName := range changedReportNames {
|
||||
if helpers.StringSliceContains(reportsBeingWatched, changedReportName) {
|
||||
reportexecute.ExecuteReportNode(s.context, changedReportName, s.workspace, s.dbClient)
|
||||
dashboardexecute.ExecuteDashboardNode(s.context, changedReportName, s.workspace, s.dbClient)
|
||||
}
|
||||
}
|
||||
|
||||
// Special case - if we previously had a workspace error, any previously existing reports
|
||||
// will come in here as new, so we need to check if any of those new reports are being watched.
|
||||
// If so, execute them
|
||||
for _, newReport := range newReports {
|
||||
if helpers.StringSliceContains(newReportNames, newReport.Name()) {
|
||||
for _, newDashboard := range newDashboards {
|
||||
if helpers.StringSliceContains(newDashboardNames, newDashboard.Name()) {
|
||||
continue
|
||||
}
|
||||
newReportNames = append(newReportNames, newReport.Name())
|
||||
newDashboardNames = append(newDashboardNames, newDashboard.Name())
|
||||
}
|
||||
|
||||
for _, newReportName := range newReportNames {
|
||||
if helpers.StringSliceContains(reportsBeingWatched, newReportName) {
|
||||
reportexecute.ExecuteReportNode(s.context, newReportName, s.workspace, s.dbClient)
|
||||
for _, newDashboardName := range newDashboardNames {
|
||||
if helpers.StringSliceContains(reportsBeingWatched, newDashboardName) {
|
||||
dashboardexecute.ExecuteDashboardNode(s.context, newDashboardName, s.workspace, s.dbClient)
|
||||
}
|
||||
}
|
||||
|
||||
case *reportevents.ReportError:
|
||||
case *dashboardevents.DashboardError:
|
||||
log.Println("[TRACE] Got report error event", *e)
|
||||
|
||||
case *reportevents.ReportComplete:
|
||||
case *dashboardevents.DashboardComplete:
|
||||
log.Println("[TRACE] Got report complete event", *e)
|
||||
|
||||
case *reportevents.ExecutionComplete:
|
||||
case *dashboardevents.ExecutionComplete:
|
||||
log.Println("[TRACE] Got execution complete event", *e)
|
||||
payload, payloadError = buildExecutionCompletePayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
}
|
||||
reportName := e.Report.GetName()
|
||||
reportName := e.Dashboard.GetName()
|
||||
s.mutex.Lock()
|
||||
for session, repoInfo := range s.reportClients {
|
||||
for session, repoInfo := range s.dashboardClients {
|
||||
// If this session is interested in this report, broadcast to it
|
||||
if (repoInfo.Report != nil) && *repoInfo.Report == reportName {
|
||||
if (repoInfo.Dashboard != nil) && *repoInfo.Dashboard == reportName {
|
||||
session.Write(payload)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
package reportserver
|
||||
package dashboardserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/report/reportexecute"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardexecute"
|
||||
"gopkg.in/olahol/melody.v1"
|
||||
)
|
||||
|
||||
@@ -53,23 +50,19 @@ type DashboardMetadataPayload struct {
|
||||
Metadata DashboardMetadata `json:"metadata"`
|
||||
}
|
||||
|
||||
func Init(ctx context.Context, webSocket *melody.Melody, workspace *workspace.Workspace, dbClient db_common.Client, socketSessions map[*melody.Session]*ReportClientInfo, mutex *sync.Mutex) {
|
||||
// Return list of reports on connect
|
||||
webSocket.HandleConnect(func(session *melody.Session) {
|
||||
func (s *Server) Init(ctx context.Context) {
|
||||
// Return list of dashboards on connect
|
||||
s.webSocket.HandleConnect(func(session *melody.Session) {
|
||||
log.Println("[TRACE] Client connected")
|
||||
mutex.Lock()
|
||||
socketSessions[session] = &ReportClientInfo{}
|
||||
mutex.Unlock()
|
||||
s.addSession(session)
|
||||
})
|
||||
|
||||
webSocket.HandleDisconnect(func(session *melody.Session) {
|
||||
s.webSocket.HandleDisconnect(func(session *melody.Session) {
|
||||
log.Println("[TRACE] Client disconnected")
|
||||
mutex.Lock()
|
||||
delete(socketSessions, session)
|
||||
mutex.Unlock()
|
||||
s.clearSession(session)
|
||||
})
|
||||
|
||||
webSocket.HandleMessage(func(session *melody.Session, msg []byte) {
|
||||
s.webSocket.HandleMessage(func(session *melody.Session, msg []byte) {
|
||||
log.Println("[TRACE] Got message", string(msg))
|
||||
var request ClientRequest
|
||||
// if we could not decode message - ignore
|
||||
@@ -77,26 +70,43 @@ func Init(ctx context.Context, webSocket *melody.Melody, workspace *workspace.Wo
|
||||
|
||||
switch request.Action {
|
||||
case "get_dashboard_metadata":
|
||||
payload, err := buildDashboardMetadataPayload(workspace)
|
||||
payload, err := buildDashboardMetadataPayload(s.workspaceResources)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error building payload for get_metadata: %v", err))
|
||||
}
|
||||
session.Write(payload)
|
||||
case "get_available_dashboards":
|
||||
payload, err := buildAvailableDashboardsPayload(workspace)
|
||||
payload, err := buildAvailableDashboardsPayload(s.workspaceResources)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error building payload for get_available_dashboards: %v", err))
|
||||
}
|
||||
session.Write(payload)
|
||||
case "select_dashboard":
|
||||
log.Printf("[TRACE] Got event: %v\n", request.Payload.Dashboard)
|
||||
mutex.Lock()
|
||||
reportClientInfo := socketSessions[session]
|
||||
reportClientInfo.Report = &request.Payload.Dashboard.FullName
|
||||
mutex.Unlock()
|
||||
reportexecute.ExecuteReportNode(ctx, request.Payload.Dashboard.FullName, workspace, dbClient)
|
||||
dashboardClientInfo := s.getSession(session)
|
||||
dashboardClientInfo.Dashboard = &request.Payload.Dashboard.FullName
|
||||
dashboardexecute.ExecuteDashboardNode(ctx, request.Payload.Dashboard.FullName, s.workspace, s.dbClient)
|
||||
}
|
||||
}
|
||||
})
|
||||
outputMessage(ctx, "Initialization complete")
|
||||
}
|
||||
|
||||
func (s *Server) getSession(session *melody.Session) *DashboardClientInfo {
|
||||
s.mutex.Lock()
|
||||
dashboardClientInfo := s.dashboardClients[session]
|
||||
s.mutex.Unlock()
|
||||
return dashboardClientInfo
|
||||
}
|
||||
|
||||
func (s *Server) clearSession(session *melody.Session) {
|
||||
s.mutex.Lock()
|
||||
delete(s.dashboardClients, session)
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
|
||||
func (s *Server) addSession(session *melody.Session) {
|
||||
s.mutex.Lock()
|
||||
s.dashboardClients[session] = &DashboardClientInfo{}
|
||||
s.mutex.Unlock()
|
||||
}
|
||||
@@ -50,15 +50,15 @@ func getCreateTablesSql(commonColumnSql []string) string {
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.Benchmark{}, constants.IntrospectionTableBenchmark, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.Mod{}, constants.IntrospectionTableMod, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.Variable{}, constants.IntrospectionTableVariable, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportContainer{}, constants.IntrospectionTableReport, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportContainer{}, constants.IntrospectionTableContainer, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportCard{}, constants.IntrospectionTableReportCard, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportChart{}, constants.IntrospectionTableReportChart, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportHierarchy{}, constants.IntrospectionTableReportHierarchy, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportImage{}, constants.IntrospectionTableReportImage, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportInput{}, constants.IntrospectionTableReportInput, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportTable{}, constants.IntrospectionTableReportTable, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ReportText{}, constants.IntrospectionTableReportText, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardContainer{}, constants.IntrospectionTableReport, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardContainer{}, constants.IntrospectionTableContainer, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardCard{}, constants.IntrospectionTableReportCard, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardChart{}, constants.IntrospectionTableReportChart, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardHierarchy{}, constants.IntrospectionTableReportHierarchy, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardImage{}, constants.IntrospectionTableReportImage, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardInput{}, constants.IntrospectionTableReportInput, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardTable{}, constants.IntrospectionTableReportTable, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.DashboardText{}, constants.IntrospectionTableReportText, commonColumnSql))
|
||||
createSql = append(createSql, getTableCreateSqlForResource(modconfig.ResourceReference{}, constants.IntrospectionTableReference, commonColumnSql))
|
||||
return strings.Join(createSql, "\n")
|
||||
}
|
||||
@@ -81,31 +81,31 @@ func getTableInsertSql(workspaceResources *modconfig.WorkspaceResourceMaps) stri
|
||||
for _, variable := range workspaceResources.Variables {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(variable, constants.IntrospectionTableVariable))
|
||||
}
|
||||
for _, report := range workspaceResources.Reports {
|
||||
for _, report := range workspaceResources.Dashboards {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(report, constants.IntrospectionTableReport))
|
||||
}
|
||||
for _, container := range workspaceResources.ReportContainers {
|
||||
for _, container := range workspaceResources.DashboardContainers {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(container, constants.IntrospectionTableContainer))
|
||||
}
|
||||
for _, card := range workspaceResources.ReportCards {
|
||||
for _, card := range workspaceResources.DashboardCards {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(card, constants.IntrospectionTableReportCard))
|
||||
}
|
||||
for _, chart := range workspaceResources.ReportCharts {
|
||||
for _, chart := range workspaceResources.DashboardCharts {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(chart, constants.IntrospectionTableReportChart))
|
||||
}
|
||||
for _, hierarchy := range workspaceResources.ReportHierarchies {
|
||||
for _, hierarchy := range workspaceResources.DashboardHierarchies {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(hierarchy, constants.IntrospectionTableReportHierarchy))
|
||||
}
|
||||
for _, image := range workspaceResources.ReportImages {
|
||||
for _, image := range workspaceResources.DashboardImages {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(image, constants.IntrospectionTableReportImage))
|
||||
}
|
||||
for _, image := range workspaceResources.ReportInputs {
|
||||
for _, image := range workspaceResources.DashboardInputs {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(image, constants.IntrospectionTableReportInput))
|
||||
}
|
||||
for _, table := range workspaceResources.ReportTables {
|
||||
for _, table := range workspaceResources.DashboardTables {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(table, constants.IntrospectionTableReportTable))
|
||||
}
|
||||
for _, text := range workspaceResources.ReportTexts {
|
||||
for _, text := range workspaceResources.DashboardTexts {
|
||||
insertSql = append(insertSql, getTableInsertSqlForResource(text, constants.IntrospectionTableReportText))
|
||||
}
|
||||
for _, reference := range workspaceResources.References {
|
||||
|
||||
@@ -77,7 +77,7 @@ func EnsureLogDir() string {
|
||||
return ensureSteampipeSubDir("logs")
|
||||
}
|
||||
|
||||
func EnsureReportAssetsDir() string {
|
||||
func EnsureDashboardAssetsDir() string {
|
||||
return ensureSteampipeSubDir(filepath.Join(filepath.Join("report", "assets")))
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ func DatabaseVersionFilePath() string {
|
||||
|
||||
// ReportAssetsVersionFilePath returns the report assets version file path
|
||||
func ReportAssetsVersionFilePath() string {
|
||||
return filepath.Join(EnsureReportAssetsDir(), versionFileName)
|
||||
return filepath.Join(EnsureDashboardAssetsDir(), versionFileName)
|
||||
}
|
||||
|
||||
func RunningInfoFilePath() string {
|
||||
|
||||
@@ -33,8 +33,8 @@ func InstallAssets(ctx context.Context, dest string) error {
|
||||
func installAssetsFiles(image *SteampipeImage, tempdir string, dest string) error {
|
||||
fileName := image.Assets.ReportUI
|
||||
sourcePath := filepath.Join(tempdir, fileName)
|
||||
if err := moveFolderWithinPartition(sourcePath, filepaths.EnsureReportAssetsDir()); err != nil {
|
||||
return fmt.Errorf("could not install %s to %s", sourcePath, filepaths.EnsureReportAssetsDir())
|
||||
if err := moveFolderWithinPartition(sourcePath, filepaths.EnsureDashboardAssetsDir()); err != nil {
|
||||
return fmt.Errorf("could not install %s to %s", sourcePath, filepaths.EnsureDashboardAssetsDir())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ContainerComplete struct {
|
||||
Container reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ContainerComplete) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ContainerError struct {
|
||||
Container reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ContainerError) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ExecutionComplete struct {
|
||||
Report reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ExecutionComplete) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ExecutionStarted struct {
|
||||
ReportNode reportinterfaces.ReportNodeRun `json:"report"`
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ExecutionStarted) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type LeafNodeComplete struct {
|
||||
Node reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*LeafNodeComplete) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type LeafNodeError struct {
|
||||
Node reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*LeafNodeError) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type LeafNodeProgress struct {
|
||||
Node reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*LeafNodeProgress) IsReportEvent() {}
|
||||
@@ -1,82 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import (
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
type ReportChanged struct {
|
||||
ChangedReports []*modconfig.ReportTreeItemDiffs
|
||||
ChangedContainers []*modconfig.ReportTreeItemDiffs
|
||||
ChangedControls []*modconfig.ReportTreeItemDiffs
|
||||
ChangedBenchmarks []*modconfig.ReportTreeItemDiffs
|
||||
ChangedCards []*modconfig.ReportTreeItemDiffs
|
||||
ChangedCharts []*modconfig.ReportTreeItemDiffs
|
||||
ChangedHierarchies []*modconfig.ReportTreeItemDiffs
|
||||
ChangedImages []*modconfig.ReportTreeItemDiffs
|
||||
ChangedInputs []*modconfig.ReportTreeItemDiffs
|
||||
ChangedTables []*modconfig.ReportTreeItemDiffs
|
||||
ChangedTexts []*modconfig.ReportTreeItemDiffs
|
||||
|
||||
NewReports []*modconfig.ReportContainer
|
||||
NewContainers []*modconfig.ReportContainer
|
||||
NewControls []*modconfig.Control
|
||||
NewBenchmarks []*modconfig.Benchmark
|
||||
NewCards []*modconfig.ReportCard
|
||||
NewCharts []*modconfig.ReportChart
|
||||
NewHierarchies []*modconfig.ReportHierarchy
|
||||
NewImages []*modconfig.ReportImage
|
||||
NewInputs []*modconfig.ReportInput
|
||||
NewTables []*modconfig.ReportTable
|
||||
NewTexts []*modconfig.ReportText
|
||||
|
||||
DeletedReports []*modconfig.ReportContainer
|
||||
DeletedContainers []*modconfig.ReportContainer
|
||||
DeletedControls []*modconfig.Control
|
||||
DeletedBenchmarks []*modconfig.Benchmark
|
||||
DeletedCards []*modconfig.ReportCard
|
||||
DeletedCharts []*modconfig.ReportChart
|
||||
DeletedHierarchies []*modconfig.ReportHierarchy
|
||||
DeletedImages []*modconfig.ReportImage
|
||||
DeletedInputs []*modconfig.ReportInput
|
||||
DeletedTables []*modconfig.ReportTable
|
||||
DeletedTexts []*modconfig.ReportText
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ReportChanged) IsReportEvent() {}
|
||||
|
||||
func (c *ReportChanged) HasChanges() bool {
|
||||
return len(c.ChangedReports)+
|
||||
len(c.ChangedContainers)+
|
||||
len(c.ChangedBenchmarks)+
|
||||
len(c.ChangedControls)+
|
||||
len(c.ChangedCards)+
|
||||
len(c.ChangedCharts)+
|
||||
len(c.ChangedHierarchies)+
|
||||
len(c.ChangedImages)+
|
||||
len(c.ChangedInputs)+
|
||||
len(c.ChangedTables)+
|
||||
len(c.ChangedTexts)+
|
||||
len(c.NewReports)+
|
||||
len(c.NewContainers)+
|
||||
len(c.NewBenchmarks)+
|
||||
len(c.NewControls)+
|
||||
len(c.NewCards)+
|
||||
len(c.NewCharts)+
|
||||
len(c.NewHierarchies)+
|
||||
len(c.NewImages)+
|
||||
len(c.NewInputs)+
|
||||
len(c.NewTables)+
|
||||
len(c.NewTexts)+
|
||||
len(c.DeletedReports)+
|
||||
len(c.DeletedContainers)+
|
||||
len(c.DeletedBenchmarks)+
|
||||
len(c.DeletedControls)+
|
||||
len(c.DeletedCards)+
|
||||
len(c.DeletedCharts)+
|
||||
len(c.DeletedHierarchies)+
|
||||
len(c.DeletedImages)+
|
||||
len(c.DeletedInputs)+
|
||||
len(c.DeletedTables)+
|
||||
len(c.DeletedTexts) > 0
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ReportComplete struct {
|
||||
Report reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ReportComplete) IsReportEvent() {}
|
||||
@@ -1,10 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
import "github.com/turbot/steampipe/report/reportinterfaces"
|
||||
|
||||
type ReportError struct {
|
||||
Report reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*ReportError) IsReportEvent() {}
|
||||
@@ -1,6 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
type ReportEvent interface {
|
||||
IsReportEvent()
|
||||
}
|
||||
type ReportEventHandler func(ReportEvent)
|
||||
@@ -1,8 +0,0 @@
|
||||
package reportevents
|
||||
|
||||
type WorkspaceError struct {
|
||||
Error error
|
||||
}
|
||||
|
||||
// IsReportEvent implements ReportEvent interface
|
||||
func (*WorkspaceError) IsReportEvent() {}
|
||||
@@ -1,224 +0,0 @@
|
||||
package reportexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/turbot/steampipe/utils"
|
||||
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
// TOTO [reports] split into report and container
|
||||
// update events
|
||||
// ReportContainerRun is a struct representing a container run
|
||||
|
||||
type ReportContainerRun struct {
|
||||
Name string `json:"name"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Width int `json:"width,omitempty"`
|
||||
Height int `json:"height,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
SQL string `json:"sql,omitempty"`
|
||||
Error error `json:"error,omitempty"`
|
||||
Children []reportinterfaces.ReportNodeRun `json:"children,omitempty"`
|
||||
NodeType string `json:"node_type"`
|
||||
Status reportinterfaces.ReportRunStatus `json:"status"`
|
||||
ReportName string `json:"report"`
|
||||
Path []string `json:"-"`
|
||||
reportNode *modconfig.ReportContainer
|
||||
parent reportinterfaces.ReportNodeParent
|
||||
executionTree *ReportExecutionTree
|
||||
childComplete chan reportinterfaces.ReportNodeRun
|
||||
}
|
||||
|
||||
func NewReportContainerRun(container *modconfig.ReportContainer, parent reportinterfaces.ReportNodeParent, executionTree *ReportExecutionTree) (*ReportContainerRun, error) {
|
||||
children := container.GetChildren()
|
||||
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(container.Name())
|
||||
|
||||
r := &ReportContainerRun{
|
||||
Name: name,
|
||||
NodeType: container.HclType,
|
||||
Path: container.Paths[0],
|
||||
ReportName: executionTree.reportName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
reportNode: container,
|
||||
|
||||
// set to complete, optimistically
|
||||
// if any children have SQL we will set this to ReportRunReady instead
|
||||
Status: reportinterfaces.ReportRunComplete,
|
||||
childComplete: make(chan reportinterfaces.ReportNodeRun, len(children)),
|
||||
}
|
||||
if container.Title != nil {
|
||||
r.Title = *container.Title
|
||||
}
|
||||
|
||||
if container.Width != nil {
|
||||
r.Width = *container.Width
|
||||
}
|
||||
|
||||
for _, child := range children {
|
||||
var childRun reportinterfaces.ReportNodeRun
|
||||
var err error
|
||||
switch i := child.(type) {
|
||||
case *modconfig.ReportContainer:
|
||||
childRun, err = NewReportContainerRun(i, r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case *modconfig.Benchmark, *modconfig.Control:
|
||||
childRun, err = NewCheckRun(i.(modconfig.ReportLeafNode), r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
default:
|
||||
// ensure this item is a ReportLeafNode
|
||||
leafNode, ok := i.(modconfig.ReportLeafNode)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("child %s does not implement ReportLeafNode", i.Name())
|
||||
}
|
||||
|
||||
childRun, err = NewLeafRun(leafNode, r, executionTree)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// should never happen - container children must be either container or counter
|
||||
if childRun == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// if our child has not completed, we have not completed
|
||||
if childRun.GetRunStatus() == reportinterfaces.ReportRunReady {
|
||||
r.Status = reportinterfaces.ReportRunReady
|
||||
}
|
||||
r.Children = append(r.Children, childRun)
|
||||
}
|
||||
// add r into execution tree
|
||||
executionTree.runs[r.Name] = r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Execute implements ReportRunNode
|
||||
// execute all children and wait for them to complete
|
||||
func (r *ReportContainerRun) Execute(ctx context.Context) error {
|
||||
|
||||
errChan := make(chan error, len(r.Children))
|
||||
// execute all children asynchronously
|
||||
for _, child := range r.Children {
|
||||
go r.executeChild(ctx, child, errChan)
|
||||
}
|
||||
|
||||
// wait for children to complete
|
||||
var errors []error
|
||||
for !r.ChildrenComplete() {
|
||||
select {
|
||||
case <-r.childComplete:
|
||||
// fall through to recheck ChildrenComplete
|
||||
case err := <-errChan:
|
||||
errors = append(errors, err)
|
||||
// TODO TIMEOUT??
|
||||
}
|
||||
}
|
||||
|
||||
// so all children have completed - check for errors
|
||||
err := utils.CombineErrors(errors...)
|
||||
if err == nil {
|
||||
// set complete status on report - this will raise counter complete event
|
||||
r.SetComplete()
|
||||
} else {
|
||||
r.SetError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *ReportContainerRun) executeChild(ctx context.Context, child reportinterfaces.ReportNodeRun, errChan chan error) {
|
||||
err := child.Execute(ctx)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
}
|
||||
|
||||
// GetName implements ReportNodeRun
|
||||
func (r *ReportContainerRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements ReportNodeRun
|
||||
func (r *ReportContainerRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements ReportNodeRun
|
||||
func (r *ReportContainerRun) GetRunStatus() reportinterfaces.ReportRunStatus {
|
||||
return r.Status
|
||||
}
|
||||
|
||||
// SetError implements ReportNodeRun
|
||||
// tell parent we are done
|
||||
func (r *ReportContainerRun) SetError(err error) {
|
||||
r.Error = err
|
||||
r.Status = reportinterfaces.ReportRunError
|
||||
// raise container error event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.ContainerError{Container: r})
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
|
||||
}
|
||||
|
||||
// SetComplete implements ReportNodeRun
|
||||
func (r *ReportContainerRun) SetComplete() {
|
||||
r.Status = reportinterfaces.ReportRunComplete
|
||||
// raise container complete event
|
||||
r.executionTree.workspace.PublishReportEvent(&reportevents.ContainerComplete{Container: r})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
}
|
||||
|
||||
// RunComplete implements ReportNodeRun
|
||||
func (r *ReportContainerRun) RunComplete() bool {
|
||||
return r.Status == reportinterfaces.ReportRunComplete || r.Status == reportinterfaces.ReportRunError
|
||||
}
|
||||
|
||||
// ChildrenComplete implements ReportNodeRun
|
||||
func (r *ReportContainerRun) ChildrenComplete() bool {
|
||||
for _, child := range r.Children {
|
||||
if !child.RunComplete() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *ReportContainerRun) ChildCompleteChan() chan reportinterfaces.ReportNodeRun {
|
||||
return r.childComplete
|
||||
}
|
||||
|
||||
func (r *ReportContainerRun) GetRuntimeDependency(dependency *modconfig.RuntimeDependency) (*string, error) {
|
||||
// TOTO [reports] LOCK???
|
||||
|
||||
/// TOTO [reports] nasty - split into report and container
|
||||
if !r.reportNode.IsReport() {
|
||||
panic("GetRuntimeDependency called on container")
|
||||
}
|
||||
|
||||
// only inputs supported at present
|
||||
if dependency.PropertyPath.ItemType != modconfig.BlockTypeInput {
|
||||
return nil, fmt.Errorf("invalid runtime dependency type %s", dependency.PropertyPath.ItemType)
|
||||
}
|
||||
|
||||
// find the input corresponding to this dependency
|
||||
input, ok := r.reportNode.GetInput(dependency.PropertyPath.Name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("report %s does not contain input %s", r.reportNode.Name(), dependency.PropertyPath.ItemType)
|
||||
}
|
||||
return input.Value, nil
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package reportexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/statushooks"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
)
|
||||
|
||||
// map of execution trees, keyed by report name
|
||||
var executions = make(map[string]*ReportExecutionTree)
|
||||
|
||||
func ExecuteReportNode(ctx context.Context, reportName string, workspace *workspace.Workspace, client db_common.Client) error {
|
||||
// TODO [reports] if this report is already running - cancel ??? fail???
|
||||
if _, running := executions[reportName]; running {
|
||||
return fmt.Errorf("report %s is already running", reportName)
|
||||
}
|
||||
|
||||
// create context for the report execution
|
||||
// (for now just disable all status messages - replace with event based? )
|
||||
reportCtx := statushooks.DisableStatusHooks(ctx)
|
||||
executionTree, err := NewReportExecutionTree(reportName, client, workspace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
executions[reportName] = executionTree
|
||||
go func() {
|
||||
workspace.PublishReportEvent(&reportevents.ExecutionStarted{ReportNode: executionTree.Root})
|
||||
defer func() {
|
||||
// remove tree from map of executions
|
||||
delete(executions, reportName)
|
||||
// send completed event
|
||||
workspace.PublishReportEvent(&reportevents.ExecutionComplete{Report: executionTree.Root})
|
||||
}()
|
||||
|
||||
if err := executionTree.Execute(reportCtx); err != nil {
|
||||
if executionTree.Root.GetRunStatus() != reportinterfaces.ReportRunError {
|
||||
// set error state on the root node
|
||||
executionTree.Root.SetError(err)
|
||||
}
|
||||
}
|
||||
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package reportexecute
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/report/reportinterfaces"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/workspace"
|
||||
)
|
||||
|
||||
// ReportExecutionTree is a structure representing the control result hierarchy
|
||||
type ReportExecutionTree struct {
|
||||
modconfig.UniqueNameProviderBase
|
||||
|
||||
Root *ReportContainerRun
|
||||
reportName string
|
||||
client db_common.Client
|
||||
runs map[string]reportinterfaces.ReportNodeRun
|
||||
workspace *workspace.Workspace
|
||||
runComplete chan reportinterfaces.ReportNodeRun
|
||||
|
||||
inputLock sync.Mutex
|
||||
inputDataSubscriptions map[string][]chan bool
|
||||
}
|
||||
|
||||
// NewReportExecutionTree creates a result group from a ModTreeItem
|
||||
func NewReportExecutionTree(reportName string, client db_common.Client, workspace *workspace.Workspace) (*ReportExecutionTree, error) {
|
||||
// now populate the ReportExecutionTree
|
||||
reportExecutionTree := &ReportExecutionTree{
|
||||
client: client,
|
||||
runs: make(map[string]reportinterfaces.ReportNodeRun),
|
||||
workspace: workspace,
|
||||
runComplete: make(chan reportinterfaces.ReportNodeRun, 1),
|
||||
inputDataSubscriptions: make(map[string][]chan bool),
|
||||
reportName: reportName,
|
||||
}
|
||||
|
||||
// create the root run node (either a report run or a counter run)
|
||||
root, err := reportExecutionTree.createRootItem(reportName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
reportExecutionTree.Root = root
|
||||
return reportExecutionTree, nil
|
||||
}
|
||||
|
||||
func (e *ReportExecutionTree) createRootItem(reportName string) (*ReportContainerRun, error) {
|
||||
parsedName, err := modconfig.ParseResourceName(reportName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if parsedName.ItemType != modconfig.BlockTypeReport {
|
||||
return nil, fmt.Errorf("reporting type %s cannot be executed directly - only reports may be executed", parsedName.ItemType)
|
||||
}
|
||||
report, ok := e.workspace.Reports[reportName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("report '%s' does not exist in workspace", reportName)
|
||||
}
|
||||
return NewReportContainerRun(report, e, e)
|
||||
|
||||
}
|
||||
|
||||
func (e *ReportExecutionTree) Execute(ctx context.Context) error {
|
||||
log.Println("[TRACE]", "begin ReportExecutionTree.Execute")
|
||||
defer log.Println("[TRACE]", "end ReportExecutionTree.Execute")
|
||||
|
||||
if e.runStatus() == reportinterfaces.ReportRunComplete {
|
||||
// there must be no nodes to execute
|
||||
log.Println("[TRACE]", "execution tree already complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
return e.Root.Execute(ctx)
|
||||
}
|
||||
|
||||
func (e *ReportExecutionTree) runStatus() reportinterfaces.ReportRunStatus {
|
||||
return e.Root.GetRunStatus()
|
||||
}
|
||||
|
||||
// GetName implements ReportNodeParent
|
||||
// use mod chort name - this will be the root name for all child runs
|
||||
func (e *ReportExecutionTree) GetName() string {
|
||||
return e.workspace.Mod.ShortName
|
||||
}
|
||||
|
||||
// ChildCompleteChan implements ReportNodeParent
|
||||
func (e *ReportExecutionTree) ChildCompleteChan() chan reportinterfaces.ReportNodeRun {
|
||||
return e.runComplete
|
||||
}
|
||||
|
||||
func (e *ReportExecutionTree) waitForRuntimeDependency(ctx context.Context, dependency *modconfig.RuntimeDependency) error {
|
||||
depChan := make(chan (bool), 1)
|
||||
// TOTO [reports] for now verify we only bind inputs to args (somewhere)
|
||||
|
||||
e.subscribeToInput(dependency.PropertyPath.Name, depChan)
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-depChan:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e *ReportExecutionTree) subscribeToInput(inputName string, depChan chan bool) {
|
||||
e.inputLock.Lock()
|
||||
defer e.inputLock.Unlock()
|
||||
|
||||
e.inputDataSubscriptions[inputName] = append(e.inputDataSubscriptions[inputName], depChan)
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package reportinterfaces
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
type ReportRunStatus string
|
||||
|
||||
const (
|
||||
ReportRunReady ReportRunStatus = "ready"
|
||||
ReportRunComplete = "complete"
|
||||
ReportRunError = "error"
|
||||
)
|
||||
|
||||
type ReportNodeRun interface {
|
||||
Execute(ctx context.Context) error
|
||||
GetName() string
|
||||
GetPath() modconfig.NodePath
|
||||
GetRunStatus() ReportRunStatus
|
||||
SetError(err error)
|
||||
SetComplete()
|
||||
RunComplete() bool
|
||||
ChildrenComplete() bool
|
||||
}
|
||||
|
||||
type ReportNodeParent interface {
|
||||
GetName() string
|
||||
ChildCompleteChan() chan ReportNodeRun
|
||||
}
|
||||
@@ -451,7 +451,7 @@ func init() {
|
||||
Require: require,
|
||||
Title: toStringPointer("simple report"),
|
||||
Description: toStringPointer("this mod contains a simple report"),
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"simple_report.report.simple_report": {
|
||||
ShortName: "simple_report",
|
||||
FullName: "simple_report.report.simple_report",
|
||||
@@ -459,7 +459,7 @@ func init() {
|
||||
ChildNames: []string{"simple_report.text.anonymous_text", "simple_report.chart.anonymous_chart"},
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"simple_report.chart.anonymous_chart": {
|
||||
FullName: "simple_report.chart.anonymous_chart",
|
||||
ShortName: "anonymous_chart",
|
||||
@@ -468,7 +468,7 @@ func init() {
|
||||
SQL: toStringPointer("select 1"),
|
||||
},
|
||||
},
|
||||
ReportTexts: map[string]*modconfig.ReportText{
|
||||
DashboardTexts: map[string]*modconfig.DashboardText{
|
||||
"simple_report.text.anonymous_text": {
|
||||
FullName: "simple_report.text.anonymous_text",
|
||||
ShortName: "anonymous_text",
|
||||
@@ -486,7 +486,7 @@ func init() {
|
||||
Require: require,
|
||||
Title: toStringPointer("simple report with container"),
|
||||
Description: toStringPointer("this mod contains a simple report with containers"),
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"simple_container_report.report.simple_container_report": {
|
||||
ShortName: "simple_container_report",
|
||||
FullName: "simple_container_report.report.simple_container_report",
|
||||
@@ -495,7 +495,7 @@ func init() {
|
||||
HclType: "report",
|
||||
},
|
||||
},
|
||||
ReportContainers: map[string]*modconfig.ReportContainer{
|
||||
DashboardContainers: map[string]*modconfig.DashboardContainer{
|
||||
"simple_container_report.container.anonymous_container": {
|
||||
ShortName: "anonymous_container",
|
||||
FullName: "simple_container_report.container.anonymous_container",
|
||||
@@ -504,7 +504,7 @@ func init() {
|
||||
HclType: "container",
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"simple_container_report.chart.anonymous_chart": {
|
||||
ShortName: "anonymous_chart",
|
||||
FullName: "simple_container_report.chart.anonymous_chart",
|
||||
@@ -513,7 +513,7 @@ func init() {
|
||||
SQL: toStringPointer("select 1 as container"),
|
||||
},
|
||||
},
|
||||
ReportTexts: map[string]*modconfig.ReportText{
|
||||
DashboardTexts: map[string]*modconfig.DashboardText{
|
||||
"simple_container_report.text.anonymous_text": {
|
||||
ShortName: "anonymous_text",
|
||||
FullName: "simple_container_report.text.anonymous_text",
|
||||
@@ -531,7 +531,7 @@ func init() {
|
||||
Require: require,
|
||||
Title: toStringPointer("report with multiple sibling containers"),
|
||||
Description: toStringPointer("this mod contains a report with multiple sibling containers"),
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"sibling_containers_report.report.sibling_containers_report": {
|
||||
ShortName: "sibling_containers_report",
|
||||
FullName: "sibling_containers_report.report.sibling_containers_report",
|
||||
@@ -540,7 +540,7 @@ func init() {
|
||||
HclType: "report",
|
||||
},
|
||||
},
|
||||
ReportContainers: map[string]*modconfig.ReportContainer{
|
||||
DashboardContainers: map[string]*modconfig.DashboardContainer{
|
||||
"sibling_containers_report.container.anonymous_container": {
|
||||
ShortName: "anonymous_container",
|
||||
FullName: "sibling_containers_report.container.anonymous_container",
|
||||
@@ -562,7 +562,7 @@ func init() {
|
||||
ChildNames: []string{"sibling_containers_report.text.anonymous_text_2", "sibling_containers_report.chart.anonymous_chart_2"},
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"sibling_containers_report.chart.anonymous_chart": {
|
||||
FullName: "sibling_containers_report.chart.anonymous_chart",
|
||||
ShortName: "anonymous_chart",
|
||||
@@ -585,7 +585,7 @@ func init() {
|
||||
SQL: toStringPointer("select 3 as container"),
|
||||
},
|
||||
},
|
||||
ReportTexts: map[string]*modconfig.ReportText{
|
||||
DashboardTexts: map[string]*modconfig.DashboardText{
|
||||
"sibling_containers_report.text.anonymous_text": {
|
||||
FullName: "sibling_containers_report.text.anonymous_text",
|
||||
ShortName: "anonymous_text",
|
||||
@@ -615,7 +615,7 @@ func init() {
|
||||
Require: require,
|
||||
Title: toStringPointer("report with nested containers"),
|
||||
Description: toStringPointer("this mod contains a report with nested containers"),
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"nested_containers_report.report.nested_containers_report": {
|
||||
ShortName: "nested_containers_report",
|
||||
FullName: "nested_containers_report.report.nested_containers_report",
|
||||
@@ -624,7 +624,7 @@ func init() {
|
||||
HclType: "report",
|
||||
},
|
||||
},
|
||||
ReportContainers: map[string]*modconfig.ReportContainer{
|
||||
DashboardContainers: map[string]*modconfig.DashboardContainer{
|
||||
"nested_containers_report.container.anonymous_container_1": {
|
||||
ShortName: "anonymous_container_1",
|
||||
FullName: "nested_containers_report.container.anonymous_container_1",
|
||||
@@ -650,7 +650,7 @@ func init() {
|
||||
ChildNames: []string{"nested_containers_report.text.anonymous_text", "nested_containers_report.container.anonymous_container_1", "nested_containers_report.container.anonymous_container_2"},
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"nested_containers_report.chart.anonymous_chart": {
|
||||
FullName: "nested_containers_report.chart.anonymous_chart",
|
||||
ShortName: "anonymous_chart",
|
||||
@@ -673,7 +673,7 @@ func init() {
|
||||
SQL: toStringPointer("select 1 as child_container, 2 as container"),
|
||||
},
|
||||
},
|
||||
ReportTexts: map[string]*modconfig.ReportText{
|
||||
DashboardTexts: map[string]*modconfig.DashboardText{
|
||||
"nested_containers_report.text.anonymous_text": {
|
||||
FullName: "nested_containers_report.text.anonymous_text",
|
||||
ShortName: "anonymous_text",
|
||||
@@ -709,7 +709,7 @@ func init() {
|
||||
Require: require,
|
||||
Title: toStringPointer("report with axes"),
|
||||
Description: toStringPointer("This mod tests base values overriding functionality"),
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"report_axes.report.override_base_values": {
|
||||
ShortName: "override_base_values",
|
||||
FullName: "report_axes.report.override_base_values",
|
||||
@@ -719,20 +719,20 @@ func init() {
|
||||
HclType: "report",
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"report_axes.chart.aws_bucket_info": {
|
||||
FullName: "report_axes.chart.aws_bucket_info",
|
||||
ShortName: "aws_bucket_info",
|
||||
UnqualifiedName: "chart.aws_bucket_info",
|
||||
Axes: &modconfig.ReportChartAxes{
|
||||
X: &modconfig.ReportChartAxesX{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Axes: &modconfig.DashboardChartAxes{
|
||||
X: &modconfig.DashboardChartAxesX{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
},
|
||||
Y: &modconfig.ReportChartAxesY{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Y: &modconfig.DashboardChartAxesY{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
@@ -740,7 +740,7 @@ func init() {
|
||||
},
|
||||
Grouping: toStringPointer("compare"),
|
||||
Type: toStringPointer("column"),
|
||||
Legend: &modconfig.ReportChartLegend{
|
||||
Legend: &modconfig.DashboardChartLegend{
|
||||
Position: toStringPointer("bottom"),
|
||||
},
|
||||
},
|
||||
@@ -748,15 +748,15 @@ func init() {
|
||||
FullName: "report_axes.chart.anonymous_chart",
|
||||
ShortName: "anonymous_chart",
|
||||
UnqualifiedName: "chart.anonymous_chart",
|
||||
Axes: &modconfig.ReportChartAxes{
|
||||
X: &modconfig.ReportChartAxesX{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Axes: &modconfig.DashboardChartAxes{
|
||||
X: &modconfig.DashboardChartAxesX{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("OVERRIDE"),
|
||||
},
|
||||
},
|
||||
Y: &modconfig.ReportChartAxesY{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Y: &modconfig.DashboardChartAxesY{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("OVERRIDE"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
@@ -764,7 +764,7 @@ func init() {
|
||||
},
|
||||
Grouping: toStringPointer("compare"),
|
||||
Type: toStringPointer("column"),
|
||||
Legend: &modconfig.ReportChartLegend{
|
||||
Legend: &modconfig.DashboardChartLegend{
|
||||
Position: toStringPointer("bottom"),
|
||||
},
|
||||
},
|
||||
@@ -787,7 +787,7 @@ func init() {
|
||||
SQL: toStringPointer("with unencrypted_buckets_by_region as (\n select\n region,\n count(*) as unencrypted\n from\n aws_morales_aaa.aws_s3_bucket\n where\n server_side_encryption_configuration is null\n group by\n region\n),\nnonversioned_buckets_by_region as (\n select\n region,\n count(*) as nonversioned\n from\n aws_morales_aaa.aws_s3_bucket\n where\n not versioning_enabled\n group by\n region\n),\ncompliant_buckets_by_region as (\n select\n region,\n count(*) as \"other\"\n from\n aws_morales_aaa.aws_s3_bucket\n where\n server_side_encryption_configuration is not null\n and versioning_enabled\n group by\n region\n)\nselect\n c.region as \"Region\",\n coalesce(c.other, 0) as \"Compliant\",\n coalesce(u.unencrypted, 0) as \"Unencrypted\",\n coalesce(v.nonversioned, 0) as \"Non-Versioned\"\nfrom\n compliant_buckets_by_region c\n full join unencrypted_buckets_by_region u on c.region = u.region\n full join nonversioned_buckets_by_region v on c.region = v.region;\n"),
|
||||
},
|
||||
},
|
||||
Reports: map[string]*modconfig.ReportContainer{
|
||||
Dashboards: map[string]*modconfig.DashboardContainer{
|
||||
"report_base1.report.inheriting_from_base": {
|
||||
ShortName: "inheriting_from_base",
|
||||
FullName: "report_base1.report.inheriting_from_base",
|
||||
@@ -797,24 +797,24 @@ func init() {
|
||||
HclType: "report",
|
||||
},
|
||||
},
|
||||
ReportCharts: map[string]*modconfig.ReportChart{
|
||||
DashboardCharts: map[string]*modconfig.DashboardChart{
|
||||
"report_base1.chart.aws_bucket_info": {
|
||||
FullName: "report_base1.chart.aws_bucket_info",
|
||||
ShortName: "aws_bucket_info",
|
||||
UnqualifiedName: "chart.aws_bucket_info",
|
||||
Type: toStringPointer("column"),
|
||||
Legend: &modconfig.ReportChartLegend{
|
||||
Legend: &modconfig.DashboardChartLegend{
|
||||
Position: toStringPointer("bottom"),
|
||||
},
|
||||
Axes: &modconfig.ReportChartAxes{
|
||||
X: &modconfig.ReportChartAxesX{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Axes: &modconfig.DashboardChartAxes{
|
||||
X: &modconfig.DashboardChartAxesX{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
},
|
||||
Y: &modconfig.ReportChartAxesY{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Y: &modconfig.DashboardChartAxesY{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
@@ -829,18 +829,18 @@ func init() {
|
||||
UnqualifiedName: "chart.anonymous_chart",
|
||||
Width: toIntegerPointer(8),
|
||||
Type: toStringPointer("column"),
|
||||
Legend: &modconfig.ReportChartLegend{
|
||||
Legend: &modconfig.DashboardChartLegend{
|
||||
Position: toStringPointer("bottom"),
|
||||
},
|
||||
Axes: &modconfig.ReportChartAxes{
|
||||
X: &modconfig.ReportChartAxesX{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Axes: &modconfig.DashboardChartAxes{
|
||||
X: &modconfig.DashboardChartAxesX{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Barz"),
|
||||
},
|
||||
},
|
||||
Y: &modconfig.ReportChartAxesY{
|
||||
Title: &modconfig.ReportChartAxisTitle{
|
||||
Y: &modconfig.DashboardChartAxesY{
|
||||
Title: &modconfig.DashboardChartAxisTitle{
|
||||
Display: toStringPointer("always"),
|
||||
Value: toStringPointer("Foo"),
|
||||
},
|
||||
@@ -930,7 +930,7 @@ func setChildren(mod *modconfig.Mod) error {
|
||||
benchmark.Children = append(benchmark.Children, child.(modconfig.ModTreeItem))
|
||||
}
|
||||
}
|
||||
for _, container := range mod.ReportContainers {
|
||||
for _, container := range mod.DashboardContainers {
|
||||
var children []modconfig.ModTreeItem
|
||||
for _, childName := range container.ChildNames {
|
||||
parsed, _ := modconfig.ParseResourceName(childName)
|
||||
@@ -943,7 +943,7 @@ func setChildren(mod *modconfig.Mod) error {
|
||||
container.SetChildren(children)
|
||||
|
||||
}
|
||||
for _, report := range mod.Reports {
|
||||
for _, report := range mod.Dashboards {
|
||||
var children []modconfig.ModTreeItem
|
||||
for _, childName := range report.ChildNames {
|
||||
parsed, _ := modconfig.ParseResourceName(childName)
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
// Benchmark is a struct representing the Benchmark resource
|
||||
type Benchmark struct {
|
||||
ReportLeafNodeBase
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
ShortName string
|
||||
@@ -37,7 +37,7 @@ type Benchmark struct {
|
||||
DeclRange hcl.Range
|
||||
Paths []NodePath `column:"path,jsonb"`
|
||||
|
||||
// report specific properties
|
||||
// dashboard specific properties
|
||||
Base *Benchmark `hcl:"base" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
|
||||
@@ -213,12 +213,12 @@ func (b *Benchmark) Name() string {
|
||||
return b.FullName
|
||||
}
|
||||
|
||||
// GetSQL implements ReportLeafNode
|
||||
// GetSQL implements DashboardLeafNode
|
||||
func (b *Benchmark) GetSQL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (b *Benchmark) GetWidth() int {
|
||||
if b.Width == nil {
|
||||
return 0
|
||||
@@ -226,13 +226,13 @@ func (b *Benchmark) GetWidth() int {
|
||||
return *b.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (b *Benchmark) GetUnqualifiedName() string {
|
||||
return b.UnqualifiedName
|
||||
}
|
||||
|
||||
func (b *Benchmark) Diff(other *Benchmark) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (b *Benchmark) Diff(other *Benchmark) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: b,
|
||||
Name: b.Name(),
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ const (
|
||||
BlockTypeQuery = "query"
|
||||
BlockTypeControl = "control"
|
||||
BlockTypeBenchmark = "benchmark"
|
||||
BlockTypeReport = "report"
|
||||
BlockTypeDashboard = "dashboard"
|
||||
BlockTypeContainer = "container"
|
||||
BlockTypeChart = "chart"
|
||||
BlockTypeCard = "card"
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
|
||||
// Control is a struct representing the Control resource
|
||||
type Control struct {
|
||||
ReportLeafNodeBase
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
@@ -42,7 +42,7 @@ type Control struct {
|
||||
UnqualifiedName string `json:"-"`
|
||||
Paths []NodePath `json:"-"`
|
||||
|
||||
// report specific properties
|
||||
// dashboard specific properties
|
||||
Base *Control `hcl:"base" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
|
||||
@@ -308,7 +308,7 @@ func (c *Control) GetArgs() *QueryArgs {
|
||||
return c.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (c *Control) GetSQL() string {
|
||||
return typehelpers.SafeString(c.SQL)
|
||||
}
|
||||
@@ -323,7 +323,7 @@ func (c *Control) SetParams(params []*ParamDef) {
|
||||
c.Params = params
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (c *Control) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
@@ -331,13 +331,13 @@ func (c *Control) GetWidth() int {
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (c *Control) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
func (c *Control) Diff(other *Control) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *Control) Diff(other *Control) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
|
||||
+39
-39
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportCard is a struct representing a leaf reporting node
|
||||
type ReportCard struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardCard is a struct representing a leaf dashboard node
|
||||
type DashboardCard struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
FullName string `cty:"name" json:"-"`
|
||||
@@ -32,7 +32,7 @@ type ReportCard struct {
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb" json:"args,omitempty"`
|
||||
Params []*ParamDef `cty:"params" column:"params,jsonb" json:"params,omitempty"`
|
||||
|
||||
Base *ReportCard `hcl:"base" json:"-"`
|
||||
Base *DashboardCard `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
@@ -42,9 +42,9 @@ type ReportCard struct {
|
||||
metadata *ResourceMetadata
|
||||
}
|
||||
|
||||
func NewReportCard(block *hcl.Block, mod *Mod) *ReportCard {
|
||||
func NewDashboardCard(block *hcl.Block, mod *Mod) *DashboardCard {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
c := &ReportCard{
|
||||
c := &DashboardCard{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -57,29 +57,29 @@ func NewReportCard(block *hcl.Block, mod *Mod) *ReportCard {
|
||||
|
||||
}
|
||||
|
||||
func (c *ReportCard) Equals(other *ReportCard) bool {
|
||||
func (c *DashboardCard) Equals(other *DashboardCard) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportCard) CtyValue() (cty.Value, error) {
|
||||
func (c *DashboardCard) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'card.<shortName>'
|
||||
func (c *ReportCard) Name() string {
|
||||
func (c *DashboardCard) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportCard) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardCard) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportCard) setBaseProperties() {
|
||||
func (c *DashboardCard) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -101,51 +101,51 @@ func (c *ReportCard) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportCard) AddReference(*ResourceReference) {}
|
||||
func (c *DashboardCard) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportCard) GetMod() *Mod {
|
||||
func (c *DashboardCard) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportCard) GetDeclRange() *hcl.Range {
|
||||
func (c *DashboardCard) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportCard) AddParent(parent ModTreeItem) error {
|
||||
func (c *DashboardCard) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportCard) GetParents() []ModTreeItem {
|
||||
func (c *DashboardCard) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportCard) GetChildren() []ModTreeItem {
|
||||
func (c *DashboardCard) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportCard) GetTitle() string {
|
||||
func (c *DashboardCard) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportCard) GetDescription() string {
|
||||
func (c *DashboardCard) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportCard) GetTags() map[string]string {
|
||||
func (c *DashboardCard) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportCard) GetPaths() []NodePath {
|
||||
func (c *DashboardCard) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
@@ -155,7 +155,7 @@ func (c *ReportCard) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportCard) SetPaths() {
|
||||
func (c *DashboardCard) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
@@ -164,17 +164,17 @@ func (c *ReportCard) SetPaths() {
|
||||
}
|
||||
|
||||
// GetMetadata implements ResourceWithMetadata
|
||||
func (c *ReportCard) GetMetadata() *ResourceMetadata {
|
||||
func (c *DashboardCard) GetMetadata() *ResourceMetadata {
|
||||
return c.metadata
|
||||
}
|
||||
|
||||
// SetMetadata implements ResourceWithMetadata
|
||||
func (c *ReportCard) SetMetadata(metadata *ResourceMetadata) {
|
||||
func (c *DashboardCard) SetMetadata(metadata *ResourceMetadata) {
|
||||
c.metadata = metadata
|
||||
}
|
||||
|
||||
func (c *ReportCard) Diff(other *ReportCard) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *DashboardCard) Diff(other *DashboardCard) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
@@ -207,41 +207,41 @@ func (c *ReportCard) Diff(other *ReportCard) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (c *ReportCard) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (c *DashboardCard) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode
|
||||
func (c *ReportCard) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode
|
||||
func (c *DashboardCard) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
// GetParams implements QueryProvider
|
||||
func (c *ReportCard) GetParams() []*ParamDef {
|
||||
func (c *DashboardCard) GetParams() []*ParamDef {
|
||||
return c.Params
|
||||
}
|
||||
|
||||
// GetArgs implements QueryProvider
|
||||
func (c *ReportCard) GetArgs() *QueryArgs {
|
||||
func (c *DashboardCard) GetArgs() *QueryArgs {
|
||||
return c.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
func (c *ReportCard) GetSQL() string {
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (c *DashboardCard) GetSQL() string {
|
||||
return typehelpers.SafeString(c.SQL)
|
||||
}
|
||||
|
||||
// GetQuery implements QueryProvider
|
||||
func (c *ReportCard) GetQuery() *Query {
|
||||
func (c *DashboardCard) GetQuery() *Query {
|
||||
return c.Query
|
||||
}
|
||||
|
||||
// GetPreparedStatementName implements QueryProvider
|
||||
func (c *ReportCard) GetPreparedStatementName() string {
|
||||
func (c *DashboardCard) GetPreparedStatementName() string {
|
||||
// lazy load
|
||||
if c.PreparedStatementName == "" {
|
||||
c.PreparedStatementName = preparedStatementName(c)
|
||||
@@ -250,16 +250,16 @@ func (c *ReportCard) GetPreparedStatementName() string {
|
||||
}
|
||||
|
||||
// GetModName implements QueryProvider
|
||||
func (c *ReportCard) GetModName() string {
|
||||
func (c *DashboardCard) GetModName() string {
|
||||
return c.Mod.NameWithVersion()
|
||||
}
|
||||
|
||||
// SetArgs implements QueryProvider
|
||||
func (c *ReportCard) SetArgs(args *QueryArgs) {
|
||||
func (c *DashboardCard) SetArgs(args *QueryArgs) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
// SetParams implements QueryProvider
|
||||
func (c *ReportCard) SetParams(params []*ParamDef) {
|
||||
func (c *DashboardCard) SetParams(params []*ParamDef) {
|
||||
c.Params = params
|
||||
}
|
||||
+46
-46
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportChart is a struct representing a leaf reporting node
|
||||
type ReportChart struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardChart is a struct representing a leaf dashboard node
|
||||
type DashboardChart struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
@@ -25,13 +25,13 @@ type ReportChart struct {
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Legend *ReportChartLegend `cty:"legend" hcl:"legend,block" column:"legend,jsonb" json:"legend"`
|
||||
SeriesList ReportChartSeriesList `cty:"series_list" hcl:"series,block" column:"series,jsonb" json:"-"`
|
||||
Axes *ReportChartAxes `cty:"axes" hcl:"axes,block" column:"axes,jsonb" json:"axes"`
|
||||
Grouping *string `cty:"grouping" hcl:"grouping" json:"grouping,omitempty"`
|
||||
Transform *string `cty:"transform" hcl:"transform" json:"transform,omitempty"`
|
||||
Series map[string]*ReportChartSeries `cty:"series" json:"series,omitempty"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Legend *DashboardChartLegend `cty:"legend" hcl:"legend,block" column:"legend,jsonb" json:"legend"`
|
||||
SeriesList DashboardChartSeriesList `cty:"series_list" hcl:"series,block" column:"series,jsonb" json:"-"`
|
||||
Axes *DashboardChartAxes `cty:"axes" hcl:"axes,block" column:"axes,jsonb" json:"axes"`
|
||||
Grouping *string `cty:"grouping" hcl:"grouping" json:"grouping,omitempty"`
|
||||
Transform *string `cty:"transform" hcl:"transform" json:"transform,omitempty"`
|
||||
Series map[string]*DashboardChartSeries `cty:"series" json:"series,omitempty"`
|
||||
|
||||
// QueryProvider
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
@@ -40,17 +40,17 @@ type ReportChart struct {
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb" json:"args,omitempty"`
|
||||
Params []*ParamDef `cty:"params" column:"params,jsonb" json:"params,omitempty"`
|
||||
|
||||
Base *ReportChart `hcl:"base" json:"-"`
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Base *DashboardChart `hcl:"base" json:"-"`
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
Paths []NodePath `column:"path,jsonb" json:"-"`
|
||||
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportChart(block *hcl.Block, mod *Mod) *ReportChart {
|
||||
func NewDashboardChart(block *hcl.Block, mod *Mod) *DashboardChart {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
c := &ReportChart{
|
||||
c := &DashboardChart{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -62,28 +62,28 @@ func NewReportChart(block *hcl.Block, mod *Mod) *ReportChart {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ReportChart) Equals(other *ReportChart) bool {
|
||||
func (c *DashboardChart) Equals(other *DashboardChart) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportChart) CtyValue() (cty.Value, error) {
|
||||
func (c *DashboardChart) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'chart.<shortName>'
|
||||
func (c *ReportChart) Name() string {
|
||||
func (c *DashboardChart) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportChart) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardChart) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
// populate series map
|
||||
if len(c.SeriesList) > 0 {
|
||||
c.Series = make(map[string]*ReportChartSeries, len(c.SeriesList))
|
||||
c.Series = make(map[string]*DashboardChartSeries, len(c.SeriesList))
|
||||
for _, s := range c.SeriesList {
|
||||
c.Series[s.Name] = s
|
||||
}
|
||||
@@ -91,7 +91,7 @@ func (c *ReportChart) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportChart) setBaseProperties() {
|
||||
func (c *DashboardChart) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -133,51 +133,51 @@ func (c *ReportChart) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportChart) AddReference(*ResourceReference) {}
|
||||
func (c *DashboardChart) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportChart) GetMod() *Mod {
|
||||
func (c *DashboardChart) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportChart) GetDeclRange() *hcl.Range {
|
||||
func (c *DashboardChart) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportChart) AddParent(parent ModTreeItem) error {
|
||||
func (c *DashboardChart) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportChart) GetParents() []ModTreeItem {
|
||||
func (c *DashboardChart) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportChart) GetChildren() []ModTreeItem {
|
||||
func (c *DashboardChart) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportChart) GetTitle() string {
|
||||
func (c *DashboardChart) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportChart) GetDescription() string {
|
||||
func (c *DashboardChart) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportChart) GetTags() map[string]string {
|
||||
func (c *DashboardChart) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportChart) GetPaths() []NodePath {
|
||||
func (c *DashboardChart) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
@@ -187,7 +187,7 @@ func (c *ReportChart) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportChart) SetPaths() {
|
||||
func (c *DashboardChart) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
@@ -195,8 +195,8 @@ func (c *ReportChart) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportChart) Diff(other *ReportChart) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *DashboardChart) Diff(other *DashboardChart) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
@@ -260,41 +260,41 @@ func (c *ReportChart) Diff(other *ReportChart) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (c *ReportChart) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (c *DashboardChart) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (c *ReportChart) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (c *DashboardChart) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
// GetParams implements QueryProvider
|
||||
func (c *ReportChart) GetParams() []*ParamDef {
|
||||
func (c *DashboardChart) GetParams() []*ParamDef {
|
||||
return c.Params
|
||||
}
|
||||
|
||||
// GetArgs implements QueryProvider
|
||||
func (c *ReportChart) GetArgs() *QueryArgs {
|
||||
func (c *DashboardChart) GetArgs() *QueryArgs {
|
||||
return c.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
func (c *ReportChart) GetSQL() string {
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (c *DashboardChart) GetSQL() string {
|
||||
return typehelpers.SafeString(c.SQL)
|
||||
}
|
||||
|
||||
// GetQuery implements QueryProvider
|
||||
func (c *ReportChart) GetQuery() *Query {
|
||||
func (c *DashboardChart) GetQuery() *Query {
|
||||
return c.Query
|
||||
}
|
||||
|
||||
// GetPreparedStatementName implements QueryProvider
|
||||
func (c *ReportChart) GetPreparedStatementName() string {
|
||||
func (c *DashboardChart) GetPreparedStatementName() string {
|
||||
// lazy load
|
||||
if c.PreparedStatementName == "" {
|
||||
c.PreparedStatementName = preparedStatementName(c)
|
||||
@@ -303,16 +303,16 @@ func (c *ReportChart) GetPreparedStatementName() string {
|
||||
}
|
||||
|
||||
// GetModName implements QueryProvider
|
||||
func (c *ReportChart) GetModName() string {
|
||||
func (c *DashboardChart) GetModName() string {
|
||||
return c.Mod.NameWithVersion()
|
||||
}
|
||||
|
||||
// SetArgs implements QueryProvider
|
||||
func (c *ReportChart) SetArgs(args *QueryArgs) {
|
||||
func (c *DashboardChart) SetArgs(args *QueryArgs) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
// SetParams implements QueryProvider
|
||||
func (c *ReportChart) SetParams(params []*ParamDef) {
|
||||
func (c *DashboardChart) SetParams(params []*ParamDef) {
|
||||
c.Params = params
|
||||
}
|
||||
+19
-19
@@ -4,12 +4,12 @@ import (
|
||||
"github.com/turbot/steampipe/utils"
|
||||
)
|
||||
|
||||
type ReportChartAxes struct {
|
||||
X *ReportChartAxesX `cty:"x" hcl:"x,block" json:"x,omitempty"`
|
||||
Y *ReportChartAxesY `cty:"y" hcl:"y,block" json:"y,omitempty"`
|
||||
type DashboardChartAxes struct {
|
||||
X *DashboardChartAxesX `cty:"x" hcl:"x,block" json:"x,omitempty"`
|
||||
Y *DashboardChartAxesY `cty:"y" hcl:"y,block" json:"y,omitempty"`
|
||||
}
|
||||
|
||||
func (a *ReportChartAxes) Equals(other *ReportChartAxes) bool {
|
||||
func (a *DashboardChartAxes) Equals(other *DashboardChartAxes) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -42,7 +42,7 @@ func (a *ReportChartAxes) Equals(other *ReportChartAxes) bool {
|
||||
|
||||
}
|
||||
|
||||
func (a *ReportChartAxes) Merge(other *ReportChartAxes) {
|
||||
func (a *DashboardChartAxes) Merge(other *DashboardChartAxes) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
@@ -58,12 +58,12 @@ func (a *ReportChartAxes) Merge(other *ReportChartAxes) {
|
||||
}
|
||||
}
|
||||
|
||||
type ReportChartAxesX struct {
|
||||
Title *ReportChartAxisTitle `cty:"title" hcl:"title,block" json:"title,omitempty"`
|
||||
Labels *ReportChartLabels `cty:"labels" hcl:"labels,block" json:"labels,omitempty"`
|
||||
type DashboardChartAxesX struct {
|
||||
Title *DashboardChartAxisTitle `cty:"title" hcl:"title,block" json:"title,omitempty"`
|
||||
Labels *DashboardChartLabels `cty:"labels" hcl:"labels,block" json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ReportChartAxesX) Equals(other *ReportChartAxesX) bool {
|
||||
func (x *DashboardChartAxesX) Equals(other *DashboardChartAxesX) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (x *ReportChartAxesX) Equals(other *ReportChartAxesX) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (x *ReportChartAxesX) Merge(other *ReportChartAxesX) {
|
||||
func (x *DashboardChartAxesX) Merge(other *DashboardChartAxesX) {
|
||||
if x.Title == nil {
|
||||
x.Title = other.Title
|
||||
} else {
|
||||
@@ -98,14 +98,14 @@ func (x *ReportChartAxesX) Merge(other *ReportChartAxesX) {
|
||||
}
|
||||
}
|
||||
|
||||
type ReportChartAxesY struct {
|
||||
Title *ReportChartAxisTitle `cty:"title" hcl:"title,block" json:"title,omitempty"`
|
||||
Labels *ReportChartLabels `cty:"labels" hcl:"labels,block" json:"labels,omitempty"`
|
||||
Min *int `cty:"min" hcl:"min" json:"min,omitempty"`
|
||||
type DashboardChartAxesY struct {
|
||||
Title *DashboardChartAxisTitle `cty:"title" hcl:"title,block" json:"title,omitempty"`
|
||||
Labels *DashboardChartLabels `cty:"labels" hcl:"labels,block" json:"labels,omitempty"`
|
||||
Min *int `cty:"min" hcl:"min" json:"min,omitempty"`
|
||||
Max *int `cty:"max" hcl:"max" json:"max,omitempty"`
|
||||
}
|
||||
|
||||
func (y *ReportChartAxesY) Equals(other *ReportChartAxesY) bool {
|
||||
func (y *DashboardChartAxesY) Equals(other *DashboardChartAxesY) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func (y *ReportChartAxesY) Equals(other *ReportChartAxesY) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (y *ReportChartAxesY) Merge(other *ReportChartAxesY) {
|
||||
func (y *DashboardChartAxesY) Merge(other *DashboardChartAxesY) {
|
||||
if y.Title == nil {
|
||||
y.Title = other.Title
|
||||
} else {
|
||||
@@ -150,13 +150,13 @@ func (y *ReportChartAxesY) Merge(other *ReportChartAxesY) {
|
||||
}
|
||||
}
|
||||
|
||||
type ReportChartAxisTitle struct {
|
||||
type DashboardChartAxisTitle struct {
|
||||
Display *string `cty:"display" hcl:"display" json:"display,omitempty"`
|
||||
Align *string `cty:"align" hcl:"align" json:"align,omitempty"`
|
||||
Value *string `cty:"value" hcl:"value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (t *ReportChartAxisTitle) Equals(other *ReportChartAxisTitle) bool {
|
||||
func (t *DashboardChartAxisTitle) Equals(other *DashboardChartAxisTitle) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -170,7 +170,7 @@ func (t *ReportChartAxisTitle) Equals(other *ReportChartAxisTitle) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *ReportChartAxisTitle) Merge(other *ReportChartAxisTitle) {
|
||||
func (t *DashboardChartAxisTitle) Merge(other *DashboardChartAxisTitle) {
|
||||
if t.Display == nil {
|
||||
t.Display = other.Display
|
||||
}
|
||||
+3
-3
@@ -2,12 +2,12 @@ package modconfig
|
||||
|
||||
import "github.com/turbot/steampipe/utils"
|
||||
|
||||
type ReportChartLabels struct {
|
||||
type DashboardChartLabels struct {
|
||||
Display *string `cty:"display" hcl:"display" json:"display,omitempty"`
|
||||
Format *string `cty:"format" hcl:"format" json:"format,omitempty"`
|
||||
}
|
||||
|
||||
func (l *ReportChartLabels) Equals(other *ReportChartLabels) bool {
|
||||
func (l *DashboardChartLabels) Equals(other *DashboardChartLabels) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -16,7 +16,7 @@ func (l *ReportChartLabels) Equals(other *ReportChartLabels) bool {
|
||||
utils.SafeStringsEqual(l.Format, other.Format)
|
||||
}
|
||||
|
||||
func (l *ReportChartLabels) Merge(other *ReportChartLabels) {
|
||||
func (l *DashboardChartLabels) Merge(other *DashboardChartLabels) {
|
||||
if l.Display == nil {
|
||||
l.Display = other.Display
|
||||
}
|
||||
+3
-3
@@ -2,12 +2,12 @@ package modconfig
|
||||
|
||||
import "github.com/turbot/steampipe/utils"
|
||||
|
||||
type ReportChartLegend struct {
|
||||
type DashboardChartLegend struct {
|
||||
Display *string `cty:"display" hcl:"display" json:"display,omitempty"`
|
||||
Position *string `cty:"position" hcl:"position" json:"position,omitempty"`
|
||||
}
|
||||
|
||||
func (l *ReportChartLegend) Equals(other *ReportChartLegend) bool {
|
||||
func (l *DashboardChartLegend) Equals(other *DashboardChartLegend) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
@@ -16,7 +16,7 @@ func (l *ReportChartLegend) Equals(other *ReportChartLegend) bool {
|
||||
utils.SafeStringsEqual(l.Position, other.Position)
|
||||
}
|
||||
|
||||
func (l *ReportChartLegend) Merge(other *ReportChartLegend) {
|
||||
func (l *DashboardChartLegend) Merge(other *DashboardChartLegend) {
|
||||
if l.Display == nil {
|
||||
l.Display = other.Display
|
||||
}
|
||||
+2
-2
@@ -2,13 +2,13 @@ package modconfig
|
||||
|
||||
import "github.com/turbot/steampipe/utils"
|
||||
|
||||
type ReportChartSeries struct {
|
||||
type DashboardChartSeries struct {
|
||||
Name string `hcl:"name,label" json:"name"`
|
||||
Title *string `cty:"title" hcl:"title" json:"title,omitempty"`
|
||||
Color *string `cty:"color" hcl:"color" json:"color,omitempty"`
|
||||
}
|
||||
|
||||
func (s ReportChartSeries) Equals(other *ReportChartSeries) bool {
|
||||
func (s DashboardChartSeries) Equals(other *DashboardChartSeries) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package modconfig
|
||||
|
||||
type ReportChartSeriesList []*ReportChartSeries
|
||||
type DashboardChartSeriesList []*DashboardChartSeries
|
||||
|
||||
func (s *ReportChartSeriesList) Merge(other ReportChartSeriesList) {
|
||||
func (s *DashboardChartSeriesList) Merge(other DashboardChartSeriesList) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
+50
-51
@@ -12,24 +12,24 @@ import (
|
||||
)
|
||||
|
||||
const rootRuntimeDependencyNode = "rootRuntimeDependencyNode"
|
||||
const runtimeDependencyReportScope = "self"
|
||||
const runtimeDependencyDashboardScope = "self"
|
||||
|
||||
// ReportContainer is a struct representing the Report and Container resource
|
||||
type ReportContainer struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardContainer is a struct representing the Dashboard and Container resource
|
||||
type DashboardContainer struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
Remain hcl.Body `hcl:",remain"`
|
||||
|
||||
ShortName string
|
||||
FullName string `cty:"name"`
|
||||
UnqualifiedName string `cty:"unqualified_name"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text"`
|
||||
FullName string `cty:"name"`
|
||||
UnqualifiedName string `cty:"unqualified_name"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text"`
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb"`
|
||||
Base *ReportContainer `hcl:"base"`
|
||||
Inputs []*ReportInput `cty:"inputs"`
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb"`
|
||||
Base *DashboardContainer `hcl:"base"`
|
||||
Inputs []*DashboardInput `cty:"inputs"`
|
||||
|
||||
Mod *Mod `cty:"mod"`
|
||||
DeclRange hcl.Range
|
||||
@@ -37,7 +37,7 @@ type ReportContainer struct {
|
||||
// store children in a way which can be serialised via cty
|
||||
ChildNames []string `cty:"children" column:"children,jsonb"`
|
||||
|
||||
selfInputsMap map[string]*ReportInput
|
||||
selfInputsMap map[string]*DashboardInput
|
||||
// the actual children
|
||||
children []ModTreeItem
|
||||
parents []ModTreeItem
|
||||
@@ -46,10 +46,10 @@ type ReportContainer struct {
|
||||
HclType string
|
||||
}
|
||||
|
||||
func NewReportContainer(block *hcl.Block, mod *Mod) *ReportContainer {
|
||||
// TOTO [reports] think about nested report???
|
||||
func NewDashboardContainer(block *hcl.Block, mod *Mod) *DashboardContainer {
|
||||
// TODO [reports] think about nested report???
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
c := &ReportContainer{
|
||||
c := &DashboardContainer{
|
||||
HclType: block.Type,
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
@@ -63,7 +63,7 @@ func NewReportContainer(block *hcl.Block, mod *Mod) *ReportContainer {
|
||||
}
|
||||
|
||||
//// SetMod implements HclResource
|
||||
//func (c *ReportContainer) SetMod(mod *Mod) {
|
||||
//func (c *DashboardContainer) SetMod(mod *Mod) {
|
||||
// c.Mod = mod
|
||||
//
|
||||
// // if this is a top level resource, and not a child, the resource names will already be set
|
||||
@@ -74,29 +74,28 @@ func NewReportContainer(block *hcl.Block, mod *Mod) *ReportContainer {
|
||||
// }
|
||||
//}
|
||||
|
||||
func (c *ReportContainer) Equals(other *ReportContainer) bool {
|
||||
func (c *DashboardContainer) Equals(other *DashboardContainer) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportContainer) CtyValue() (cty.Value, error) {
|
||||
func (c *DashboardContainer) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'report.<shortName>'
|
||||
func (c *ReportContainer) Name() string {
|
||||
func (c *DashboardContainer) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportContainer) OnDecoded(block *hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardContainer) OnDecoded(block *hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportContainer) setBaseProperties() {
|
||||
func (c *DashboardContainer) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -117,54 +116,54 @@ func (c *ReportContainer) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportContainer) AddReference(*ResourceReference) {
|
||||
func (c *DashboardContainer) AddReference(*ResourceReference) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportContainer) GetMod() *Mod {
|
||||
func (c *DashboardContainer) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportContainer) GetDeclRange() *hcl.Range {
|
||||
func (c *DashboardContainer) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportContainer) AddParent(parent ModTreeItem) error {
|
||||
func (c *DashboardContainer) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportContainer) GetParents() []ModTreeItem {
|
||||
func (c *DashboardContainer) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportContainer) GetChildren() []ModTreeItem {
|
||||
func (c *DashboardContainer) GetChildren() []ModTreeItem {
|
||||
return c.children
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportContainer) GetTitle() string {
|
||||
func (c *DashboardContainer) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportContainer) GetDescription() string {
|
||||
func (c *DashboardContainer) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportContainer) GetTags() map[string]string {
|
||||
func (c *DashboardContainer) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportContainer) GetPaths() []NodePath {
|
||||
func (c *DashboardContainer) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
@@ -173,7 +172,7 @@ func (c *ReportContainer) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportContainer) SetPaths() {
|
||||
func (c *DashboardContainer) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
@@ -181,8 +180,8 @@ func (c *ReportContainer) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportContainer) Diff(other *ReportContainer) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *DashboardContainer) Diff(other *DashboardContainer) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
@@ -203,11 +202,11 @@ func (c *ReportContainer) Diff(other *ReportContainer) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *ReportContainer) IsReport() bool {
|
||||
return c.HclType == "report"
|
||||
func (c *DashboardContainer) IsDashboard() bool {
|
||||
return c.HclType == BlockTypeDashboard
|
||||
}
|
||||
|
||||
func (c *ReportContainer) SetChildren(children []ModTreeItem) {
|
||||
func (c *DashboardContainer) SetChildren(children []ModTreeItem) {
|
||||
c.children = children
|
||||
c.ChildNames = make([]string, len(children))
|
||||
for i, child := range children {
|
||||
@@ -215,12 +214,12 @@ func (c *ReportContainer) SetChildren(children []ModTreeItem) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (c *ReportContainer) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (c *DashboardContainer) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
func (c *ReportContainer) WalkResources(resourceFunc func(resource HclResource) (bool, error)) error {
|
||||
func (c *DashboardContainer) WalkResources(resourceFunc func(resource HclResource) (bool, error)) error {
|
||||
for _, child := range c.children {
|
||||
continueWalking, err := resourceFunc(child.(HclResource))
|
||||
if err != nil {
|
||||
@@ -230,7 +229,7 @@ func (c *ReportContainer) WalkResources(resourceFunc func(resource HclResource)
|
||||
break
|
||||
}
|
||||
|
||||
if childContainer, ok := child.(*ReportContainer); ok {
|
||||
if childContainer, ok := child.(*DashboardContainer); ok {
|
||||
if err := childContainer.WalkResources(resourceFunc); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -239,16 +238,16 @@ func (c *ReportContainer) WalkResources(resourceFunc func(resource HclResource)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportContainer) BuildRuntimeDependencyTree(workspace ResourceMapsProvider) error {
|
||||
if !c.IsReport() {
|
||||
return fmt.Errorf("BuildRuntimeDependencyTree should only be called for reports")
|
||||
func (c *DashboardContainer) BuildRuntimeDependencyTree(workspace ResourceMapsProvider) error {
|
||||
if !c.IsDashboard() {
|
||||
return fmt.Errorf("BuildRuntimeDependencyTree should only be called for dashboards")
|
||||
}
|
||||
c.runtimeDependencyGraph = topsort.NewGraph()
|
||||
// add root node - this will depend on all other nodes
|
||||
c.runtimeDependencyGraph.AddNode(rootRuntimeDependencyNode)
|
||||
|
||||
resourceFunc := func(resource HclResource) (bool, error) {
|
||||
leafNode, ok := resource.(ReportLeafNode)
|
||||
leafNode, ok := resource.(DashboardLeafNode)
|
||||
if !ok {
|
||||
// continue walking
|
||||
return true, nil
|
||||
@@ -296,12 +295,12 @@ func (c *ReportContainer) BuildRuntimeDependencyTree(workspace ResourceMapsProvi
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportContainer) GetInput(name string) (*ReportInput, bool) {
|
||||
func (c *DashboardContainer) GetInput(name string) (*DashboardInput, bool) {
|
||||
input, found := c.selfInputsMap[name]
|
||||
return input, found
|
||||
}
|
||||
|
||||
func (c *ReportContainer) SetInputs(inputs []*ReportInput) error {
|
||||
func (c *DashboardContainer) SetInputs(inputs []*DashboardInput) error {
|
||||
c.Inputs = inputs
|
||||
c.setInputMap()
|
||||
|
||||
@@ -309,7 +308,7 @@ func (c *ReportContainer) SetInputs(inputs []*ReportInput) error {
|
||||
|
||||
var duplicates []string
|
||||
resourceFunc := func(resource HclResource) (bool, error) {
|
||||
if container, ok := resource.(*ReportContainer); ok {
|
||||
if container, ok := resource.(*DashboardContainer); ok {
|
||||
for _, i := range container.Inputs {
|
||||
// check we do not already have this input
|
||||
if _, ok := c.selfInputsMap[i.UnqualifiedName]; ok {
|
||||
@@ -332,13 +331,13 @@ func (c *ReportContainer) SetInputs(inputs []*ReportInput) error {
|
||||
}
|
||||
|
||||
// populate our input map
|
||||
func (c *ReportContainer) setInputMap() {
|
||||
c.selfInputsMap = make(map[string]*ReportInput)
|
||||
func (c *DashboardContainer) setInputMap() {
|
||||
c.selfInputsMap = make(map[string]*DashboardInput)
|
||||
for _, i := range c.Inputs {
|
||||
c.selfInputsMap[i.UnqualifiedName] = i
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportContainer) SetArgs(args *QueryArgs) {
|
||||
func (c *DashboardContainer) SetArgs(args *QueryArgs) {
|
||||
c.Args = args
|
||||
}
|
||||
+40
-40
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportHierarchy is a struct representing a leaf reporting node
|
||||
type ReportHierarchy struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardHierarchy is a struct representing a leaf dashboard node
|
||||
type DashboardHierarchy struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
@@ -25,8 +25,8 @@ type ReportHierarchy struct {
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
CategoryList ReportHierarchyCategoryList `cty:"category_list" hcl:"category,block" column:"category,jsonb" json:"-"`
|
||||
Categories map[string]*ReportHierarchyCategory `cty:"categories" json:"categories"`
|
||||
CategoryList DashboardHierarchyCategoryList `cty:"category_list" hcl:"category,block" column:"category,jsonb" json:"-"`
|
||||
Categories map[string]*DashboardHierarchyCategory `cty:"categories" json:"categories"`
|
||||
|
||||
// QueryProvider
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
@@ -35,7 +35,7 @@ type ReportHierarchy struct {
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb" json:"args"`
|
||||
Params []*ParamDef `cty:"params" column:"params,jsonb" json:"params"`
|
||||
|
||||
Base *ReportHierarchy `hcl:"base" json:"-"`
|
||||
Base *DashboardHierarchy `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
@@ -44,9 +44,9 @@ type ReportHierarchy struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportHierarchy(block *hcl.Block, mod *Mod) *ReportHierarchy {
|
||||
func NewDashboardHierarchy(block *hcl.Block, mod *Mod) *DashboardHierarchy {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
h := &ReportHierarchy{
|
||||
h := &DashboardHierarchy{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -58,28 +58,28 @@ func NewReportHierarchy(block *hcl.Block, mod *Mod) *ReportHierarchy {
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *ReportHierarchy) Equals(other *ReportHierarchy) bool {
|
||||
func (h *DashboardHierarchy) Equals(other *DashboardHierarchy) bool {
|
||||
diff := h.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (h *ReportHierarchy) CtyValue() (cty.Value, error) {
|
||||
func (h *DashboardHierarchy) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(h)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'chart.<shortName>'
|
||||
func (h *ReportHierarchy) Name() string {
|
||||
func (h *DashboardHierarchy) Name() string {
|
||||
return h.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (h *ReportHierarchy) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (h *DashboardHierarchy) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
h.setBaseProperties()
|
||||
// populate categories map
|
||||
if len(h.CategoryList) > 0 {
|
||||
h.Categories = make(map[string]*ReportHierarchyCategory, len(h.CategoryList))
|
||||
h.Categories = make(map[string]*DashboardHierarchyCategory, len(h.CategoryList))
|
||||
for _, c := range h.CategoryList {
|
||||
h.Categories[c.Name] = c
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func (h *ReportHierarchy) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *ReportHierarchy) setBaseProperties() {
|
||||
func (h *DashboardHierarchy) setBaseProperties() {
|
||||
if h.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -113,51 +113,51 @@ func (h *ReportHierarchy) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (h *ReportHierarchy) AddReference(*ResourceReference) {}
|
||||
func (h *DashboardHierarchy) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (h *ReportHierarchy) GetMod() *Mod {
|
||||
func (h *DashboardHierarchy) GetMod() *Mod {
|
||||
return h.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (h *ReportHierarchy) GetDeclRange() *hcl.Range {
|
||||
func (h *DashboardHierarchy) GetDeclRange() *hcl.Range {
|
||||
return &h.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (h *ReportHierarchy) AddParent(parent ModTreeItem) error {
|
||||
func (h *DashboardHierarchy) AddParent(parent ModTreeItem) error {
|
||||
h.parents = append(h.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetParents() []ModTreeItem {
|
||||
func (h *DashboardHierarchy) GetParents() []ModTreeItem {
|
||||
return h.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetChildren() []ModTreeItem {
|
||||
func (h *DashboardHierarchy) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetTitle() string {
|
||||
func (h *DashboardHierarchy) GetTitle() string {
|
||||
return typehelpers.SafeString(h.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetDescription() string {
|
||||
func (h *DashboardHierarchy) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetTags() map[string]string {
|
||||
func (h *DashboardHierarchy) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (h *ReportHierarchy) GetPaths() []NodePath {
|
||||
func (h *DashboardHierarchy) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(h.Paths) == 0 {
|
||||
h.SetPaths()
|
||||
@@ -167,7 +167,7 @@ func (h *ReportHierarchy) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (h *ReportHierarchy) SetPaths() {
|
||||
func (h *DashboardHierarchy) SetPaths() {
|
||||
for _, parent := range h.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
h.Paths = append(h.Paths, append(parentPath, h.Name()))
|
||||
@@ -175,8 +175,8 @@ func (h *ReportHierarchy) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (h *ReportHierarchy) Diff(other *ReportHierarchy) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (h *DashboardHierarchy) Diff(other *DashboardHierarchy) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: h,
|
||||
Name: h.Name(),
|
||||
}
|
||||
@@ -216,41 +216,41 @@ func (h *ReportHierarchy) Diff(other *ReportHierarchy) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (h *ReportHierarchy) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (h *DashboardHierarchy) GetWidth() int {
|
||||
if h.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *h.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (h *ReportHierarchy) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (h *DashboardHierarchy) GetUnqualifiedName() string {
|
||||
return h.UnqualifiedName
|
||||
}
|
||||
|
||||
// GetParams implements QueryProvider
|
||||
func (h *ReportHierarchy) GetParams() []*ParamDef {
|
||||
func (h *DashboardHierarchy) GetParams() []*ParamDef {
|
||||
return h.Params
|
||||
}
|
||||
|
||||
// GetArgs implements QueryProvider
|
||||
func (h *ReportHierarchy) GetArgs() *QueryArgs {
|
||||
func (h *DashboardHierarchy) GetArgs() *QueryArgs {
|
||||
return h.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
func (h *ReportHierarchy) GetSQL() string {
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (h *DashboardHierarchy) GetSQL() string {
|
||||
return typehelpers.SafeString(h.SQL)
|
||||
}
|
||||
|
||||
// GetQuery implements QueryProvider
|
||||
func (h *ReportHierarchy) GetQuery() *Query {
|
||||
func (h *DashboardHierarchy) GetQuery() *Query {
|
||||
return h.Query
|
||||
}
|
||||
|
||||
// GetPreparedStatementName implements QueryProvider
|
||||
func (h *ReportHierarchy) GetPreparedStatementName() string {
|
||||
func (h *DashboardHierarchy) GetPreparedStatementName() string {
|
||||
// lazy load
|
||||
if h.PreparedStatementName == "" {
|
||||
h.PreparedStatementName = preparedStatementName(h)
|
||||
@@ -259,16 +259,16 @@ func (h *ReportHierarchy) GetPreparedStatementName() string {
|
||||
}
|
||||
|
||||
// GetModName implements QueryProvider
|
||||
func (h *ReportHierarchy) GetModName() string {
|
||||
func (h *DashboardHierarchy) GetModName() string {
|
||||
return h.Mod.NameWithVersion()
|
||||
}
|
||||
|
||||
// SetArgs implements QueryProvider
|
||||
func (h *ReportHierarchy) SetArgs(args *QueryArgs) {
|
||||
func (h *DashboardHierarchy) SetArgs(args *QueryArgs) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
// SetParams implements QueryProvider
|
||||
func (h *ReportHierarchy) SetParams(params []*ParamDef) {
|
||||
func (h *DashboardHierarchy) SetParams(params []*ParamDef) {
|
||||
h.Params = params
|
||||
}
|
||||
+2
-2
@@ -2,13 +2,13 @@ package modconfig
|
||||
|
||||
import "github.com/turbot/steampipe/utils"
|
||||
|
||||
type ReportHierarchyCategory struct {
|
||||
type DashboardHierarchyCategory struct {
|
||||
Name string `hcl:"name,label" json:"-"`
|
||||
Title *string `cty:"title" hcl:"title" json:"title,omitempty"`
|
||||
Color *string `cty:"color" hcl:"color" json:"color,omitempty"`
|
||||
}
|
||||
|
||||
func (c ReportHierarchyCategory) Equals(other *ReportHierarchyCategory) bool {
|
||||
func (c DashboardHierarchyCategory) Equals(other *DashboardHierarchyCategory) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package modconfig
|
||||
|
||||
type ReportHierarchyCategoryList []*ReportHierarchyCategory
|
||||
type DashboardHierarchyCategoryList []*DashboardHierarchyCategory
|
||||
|
||||
func (c ReportHierarchyCategoryList) Merge(other ReportHierarchyCategoryList) {
|
||||
func (c DashboardHierarchyCategoryList) Merge(other DashboardHierarchyCategoryList) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
+33
-33
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportImage is a struct representing a leaf reporting node
|
||||
type ReportImage struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardImage is a struct representing a leaf dashboard node
|
||||
type DashboardImage struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
FullName string `cty:"name" json:"-"`
|
||||
@@ -19,12 +19,12 @@ type ReportImage struct {
|
||||
UnqualifiedName string `json:"-"`
|
||||
|
||||
// these properties are JSON serialised by the parent LeafRun
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"-"`
|
||||
Src *string `cty:"src" hcl:"src" column:"src,text" json:"src,omitempty"`
|
||||
Alt *string `cty:"alt" hcl:"alt" column:"alt,text" json:"alt,omitempty"`
|
||||
Base *ReportImage `hcl:"base" json:"-"`
|
||||
Alt *string `cty:"alt" hcl:"alt" column:"alt,text" json:"alt,omitempty"`
|
||||
Base *DashboardImage `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
@@ -33,9 +33,9 @@ type ReportImage struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportImage(block *hcl.Block, mod *Mod) *ReportImage {
|
||||
func NewDashboardImage(block *hcl.Block, mod *Mod) *DashboardImage {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
i := &ReportImage{
|
||||
i := &DashboardImage{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -46,29 +46,29 @@ func NewReportImage(block *hcl.Block, mod *Mod) *ReportImage {
|
||||
return i
|
||||
}
|
||||
|
||||
func (c *ReportImage) Equals(other *ReportImage) bool {
|
||||
func (c *DashboardImage) Equals(other *DashboardImage) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportImage) CtyValue() (cty.Value, error) {
|
||||
func (c *DashboardImage) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'image.<shortName>'
|
||||
func (c *ReportImage) Name() string {
|
||||
func (c *DashboardImage) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportImage) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardImage) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportImage) setBaseProperties() {
|
||||
func (c *DashboardImage) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -90,51 +90,51 @@ func (c *ReportImage) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportImage) AddReference(*ResourceReference) {}
|
||||
func (c *DashboardImage) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportImage) GetMod() *Mod {
|
||||
func (c *DashboardImage) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportImage) GetDeclRange() *hcl.Range {
|
||||
func (c *DashboardImage) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportImage) AddParent(parent ModTreeItem) error {
|
||||
func (c *DashboardImage) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportImage) GetParents() []ModTreeItem {
|
||||
func (c *DashboardImage) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportImage) GetChildren() []ModTreeItem {
|
||||
func (c *DashboardImage) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportImage) GetTitle() string {
|
||||
func (c *DashboardImage) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportImage) GetDescription() string {
|
||||
func (c *DashboardImage) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportImage) GetTags() map[string]string {
|
||||
func (c *DashboardImage) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportImage) GetPaths() []NodePath {
|
||||
func (c *DashboardImage) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
@@ -144,7 +144,7 @@ func (c *ReportImage) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportImage) SetPaths() {
|
||||
func (c *DashboardImage) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
@@ -152,8 +152,8 @@ func (c *ReportImage) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportImage) Diff(other *ReportImage) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *DashboardImage) Diff(other *DashboardImage) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
@@ -186,20 +186,20 @@ func (c *ReportImage) Diff(other *ReportImage) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSQL implements ReportLeafNode
|
||||
func (c *ReportImage) GetSQL() string {
|
||||
// GetSQL implements DashboardLeafNode
|
||||
func (c *DashboardImage) GetSQL() string {
|
||||
return typehelpers.SafeString(c.SQL)
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (c *ReportImage) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (c *DashboardImage) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (c *ReportImage) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (c *DashboardImage) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
+45
-41
@@ -2,6 +2,7 @@ package modconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
typehelpers "github.com/turbot/go-kit/types"
|
||||
@@ -9,9 +10,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportInput is a struct representing a leaf reporting node
|
||||
type ReportInput struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardInput is a struct representing a leaf dashboard node
|
||||
type DashboardInput struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
FullName string `cty:"name" json:"-"`
|
||||
@@ -19,25 +20,25 @@ type ReportInput struct {
|
||||
UnqualifiedName string `cty:"unqualified_name" json:"-"`
|
||||
|
||||
// these properties are JSON serialised by the parent LeafRun
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Style *string `cty:"style" hcl:"style" column:"style,text" json:"style,omitempty"`
|
||||
Value *string `json:"value"`
|
||||
Base *ReportInput `hcl:"base" json:"-"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Style *string `cty:"style" hcl:"style" column:"style,text" json:"style,omitempty"`
|
||||
Value *string `json:"value"`
|
||||
Base *DashboardInput `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
Paths []NodePath `column:"path,jsonb" json:"-"`
|
||||
|
||||
parents []ModTreeItem
|
||||
reportContainer *ReportContainer
|
||||
parents []ModTreeItem
|
||||
dashboardContainer *DashboardContainer
|
||||
}
|
||||
|
||||
func NewReportInput(block *hcl.Block, mod *Mod) *ReportInput {
|
||||
func NewDashboardInput(block *hcl.Block, mod *Mod) *DashboardInput {
|
||||
shortName := block.Labels[0]
|
||||
i := &ReportInput{
|
||||
i := &DashboardInput{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -47,29 +48,29 @@ func NewReportInput(block *hcl.Block, mod *Mod) *ReportInput {
|
||||
return i
|
||||
}
|
||||
|
||||
func (c *ReportInput) Equals(other *ReportInput) bool {
|
||||
func (c *DashboardInput) Equals(other *DashboardInput) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportInput) CtyValue() (cty.Value, error) {
|
||||
func (c *DashboardInput) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'chart.<shortName>'
|
||||
func (c *ReportInput) Name() string {
|
||||
func (c *DashboardInput) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportInput) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardInput) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportInput) setBaseProperties() {
|
||||
func (c *DashboardInput) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -89,51 +90,51 @@ func (c *ReportInput) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportInput) AddReference(*ResourceReference) {}
|
||||
func (c *DashboardInput) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportInput) GetMod() *Mod {
|
||||
func (c *DashboardInput) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportInput) GetDeclRange() *hcl.Range {
|
||||
func (c *DashboardInput) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportInput) AddParent(parent ModTreeItem) error {
|
||||
func (c *DashboardInput) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportInput) GetParents() []ModTreeItem {
|
||||
func (c *DashboardInput) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportInput) GetChildren() []ModTreeItem {
|
||||
func (c *DashboardInput) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportInput) GetTitle() string {
|
||||
func (c *DashboardInput) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportInput) GetDescription() string {
|
||||
func (c *DashboardInput) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportInput) GetTags() map[string]string {
|
||||
func (c *DashboardInput) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportInput) GetPaths() []NodePath {
|
||||
func (c *DashboardInput) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
@@ -143,7 +144,7 @@ func (c *ReportInput) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportInput) SetPaths() {
|
||||
func (c *DashboardInput) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
@@ -151,8 +152,8 @@ func (c *ReportInput) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportInput) Diff(other *ReportInput) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (c *DashboardInput) Diff(other *DashboardInput) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
@@ -182,22 +183,25 @@ func (c *ReportInput) Diff(other *ReportInput) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (c *ReportInput) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (c *DashboardInput) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (c *ReportInput) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (c *DashboardInput) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
// SetReportContainer sets the parent report container
|
||||
func (c *ReportInput) SetReportContainer(reportContainer *ReportContainer) {
|
||||
c.reportContainer = reportContainer
|
||||
// update the full name
|
||||
c.FullName = fmt.Sprintf("%s.%s.%s", c.Mod.ShortName, c.reportContainer.UnqualifiedName, c.UnqualifiedName)
|
||||
// SetDashboardContainer sets the parent dashboard container
|
||||
func (c *DashboardInput) SetDashboardContainer(dashboardContainer *DashboardContainer) {
|
||||
// TODO [reports] also update unqualified name?
|
||||
c.dashboardContainer = dashboardContainer
|
||||
// update the full name with a sanitsed version of the parent dashboard name
|
||||
dashboardName := strings.Replace(c.dashboardContainer.UnqualifiedName, ".", "_", -1)
|
||||
c.FullName = fmt.Sprintf("%s.%s.%s", c.Mod.ShortName, dashboardName, c.UnqualifiedName)
|
||||
c.UnqualifiedName = fmt.Sprintf("%s.%s", dashboardName, c.UnqualifiedName)
|
||||
}
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
package modconfig
|
||||
|
||||
type ReportLeafNodeBase struct {
|
||||
type DashboardLeafNodeBase struct {
|
||||
runtimeDependencies map[string]*RuntimeDependency
|
||||
}
|
||||
|
||||
func (b *ReportLeafNodeBase) AddRuntimeDependencies(dependency *RuntimeDependency) {
|
||||
func (b *DashboardLeafNodeBase) AddRuntimeDependencies(dependency *RuntimeDependency) {
|
||||
if b.runtimeDependencies == nil {
|
||||
b.runtimeDependencies = make(map[string]*RuntimeDependency)
|
||||
}
|
||||
@@ -12,6 +12,6 @@ func (b *ReportLeafNodeBase) AddRuntimeDependencies(dependency *RuntimeDependenc
|
||||
b.runtimeDependencies[dependency.String()] = dependency
|
||||
}
|
||||
|
||||
func (b *ReportLeafNodeBase) GetRuntimeDependencies() map[string]*RuntimeDependency {
|
||||
func (b *DashboardLeafNodeBase) GetRuntimeDependencies() map[string]*RuntimeDependency {
|
||||
return b.runtimeDependencies
|
||||
}
|
||||
+47
-47
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportTable is a struct representing a leaf reporting node
|
||||
type ReportTable struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardTable is a struct representing a leaf dashboard node
|
||||
type DashboardTable struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
@@ -22,11 +22,11 @@ type ReportTable struct {
|
||||
ShortName string `json:"-"`
|
||||
UnqualifiedName string `json:"-"`
|
||||
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
ColumnList ReportTableColumnList `cty:"column_list" hcl:"column,block" column:"columns,jsonb" json:"-"`
|
||||
Columns map[string]*ReportTableColumn `cty:"columns" json:"columns"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
ColumnList DashboardTableColumnList `cty:"column_list" hcl:"column,block" column:"columns,jsonb" json:"-"`
|
||||
Columns map[string]*DashboardTableColumn `cty:"columns" json:"columns"`
|
||||
|
||||
// QueryProvider
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
@@ -35,17 +35,17 @@ type ReportTable struct {
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb" json:"args"`
|
||||
Params []*ParamDef `cty:"params" column:"params,jsonb" json:"params"`
|
||||
|
||||
Base *ReportTable `hcl:"base" json:"-"`
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
Paths []NodePath `column:"path,jsonb" json:"-"`
|
||||
Base *DashboardTable `hcl:"base" json:"-"`
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
Paths []NodePath `column:"path,jsonb" json:"-"`
|
||||
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportTable(block *hcl.Block, mod *Mod) *ReportTable {
|
||||
func NewDashboardTable(block *hcl.Block, mod *Mod) *DashboardTable {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
t := &ReportTable{
|
||||
t := &DashboardTable{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -56,28 +56,28 @@ func NewReportTable(block *hcl.Block, mod *Mod) *ReportTable {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *ReportTable) Equals(other *ReportTable) bool {
|
||||
func (t *DashboardTable) Equals(other *DashboardTable) bool {
|
||||
diff := t.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (t *ReportTable) CtyValue() (cty.Value, error) {
|
||||
func (t *DashboardTable) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(t)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'table.<shortName>'
|
||||
func (t *ReportTable) Name() string {
|
||||
func (t *DashboardTable) Name() string {
|
||||
return t.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (t *ReportTable) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (t *DashboardTable) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
t.setBaseProperties()
|
||||
// populate columns map
|
||||
if len(t.ColumnList) > 0 {
|
||||
t.Columns = make(map[string]*ReportTableColumn, len(t.ColumnList))
|
||||
t.Columns = make(map[string]*DashboardTableColumn, len(t.ColumnList))
|
||||
for _, c := range t.ColumnList {
|
||||
t.Columns[c.Name] = c
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (t *ReportTable) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ReportTable) setBaseProperties() {
|
||||
func (t *DashboardTable) setBaseProperties() {
|
||||
if t.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -112,51 +112,51 @@ func (t *ReportTable) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (t *ReportTable) AddReference(*ResourceReference) {}
|
||||
func (t *DashboardTable) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (t *ReportTable) GetMod() *Mod {
|
||||
func (t *DashboardTable) GetMod() *Mod {
|
||||
return t.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (t *ReportTable) GetDeclRange() *hcl.Range {
|
||||
func (t *DashboardTable) GetDeclRange() *hcl.Range {
|
||||
return &t.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (t *ReportTable) AddParent(parent ModTreeItem) error {
|
||||
func (t *DashboardTable) AddParent(parent ModTreeItem) error {
|
||||
t.parents = append(t.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (t *ReportTable) GetParents() []ModTreeItem {
|
||||
func (t *DashboardTable) GetParents() []ModTreeItem {
|
||||
return t.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (t *ReportTable) GetChildren() []ModTreeItem {
|
||||
func (t *DashboardTable) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem, ReportLeafNode
|
||||
func (t *ReportTable) GetTitle() string {
|
||||
// GetTitle implements ModTreeItem, DashboardLeafNode
|
||||
func (t *DashboardTable) GetTitle() string {
|
||||
return typehelpers.SafeString(t.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (t *ReportTable) GetDescription() string {
|
||||
func (t *DashboardTable) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (t *ReportTable) GetTags() map[string]string {
|
||||
func (t *DashboardTable) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (t *ReportTable) GetPaths() []NodePath {
|
||||
func (t *DashboardTable) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(t.Paths) == 0 {
|
||||
t.SetPaths()
|
||||
@@ -166,7 +166,7 @@ func (t *ReportTable) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (t *ReportTable) SetPaths() {
|
||||
func (t *DashboardTable) SetPaths() {
|
||||
for _, parent := range t.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
t.Paths = append(t.Paths, append(parentPath, t.Name()))
|
||||
@@ -174,8 +174,8 @@ func (t *ReportTable) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *ReportTable) Diff(other *ReportTable) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (t *DashboardTable) Diff(other *DashboardTable) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: t,
|
||||
Name: t.Name(),
|
||||
}
|
||||
@@ -212,41 +212,41 @@ func (t *ReportTable) Diff(other *ReportTable) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (t *ReportTable) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (t *DashboardTable) GetWidth() int {
|
||||
if t.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *t.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (t *ReportTable) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (t *DashboardTable) GetUnqualifiedName() string {
|
||||
return t.UnqualifiedName
|
||||
}
|
||||
|
||||
// GetParams implements QueryProvider
|
||||
func (t *ReportTable) GetParams() []*ParamDef {
|
||||
func (t *DashboardTable) GetParams() []*ParamDef {
|
||||
return t.Params
|
||||
}
|
||||
|
||||
// GetArgs implements QueryProvider
|
||||
func (t *ReportTable) GetArgs() *QueryArgs {
|
||||
func (t *DashboardTable) GetArgs() *QueryArgs {
|
||||
return t.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
func (t *ReportTable) GetSQL() string {
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (t *DashboardTable) GetSQL() string {
|
||||
return typehelpers.SafeString(t.SQL)
|
||||
}
|
||||
|
||||
// GetQuery implements QueryProvider
|
||||
func (t *ReportTable) GetQuery() *Query {
|
||||
func (t *DashboardTable) GetQuery() *Query {
|
||||
return t.Query
|
||||
}
|
||||
|
||||
// GetPreparedStatementName implements QueryProvider
|
||||
func (t *ReportTable) GetPreparedStatementName() string {
|
||||
func (t *DashboardTable) GetPreparedStatementName() string {
|
||||
// lazy load
|
||||
if t.PreparedStatementName == "" {
|
||||
t.PreparedStatementName = preparedStatementName(t)
|
||||
@@ -255,16 +255,16 @@ func (t *ReportTable) GetPreparedStatementName() string {
|
||||
}
|
||||
|
||||
// GetModName implements QueryProvider
|
||||
func (t *ReportTable) GetModName() string {
|
||||
func (t *DashboardTable) GetModName() string {
|
||||
return t.Mod.NameWithVersion()
|
||||
}
|
||||
|
||||
// SetArgs implements QueryProvider
|
||||
func (t *ReportTable) SetArgs(args *QueryArgs) {
|
||||
func (t *DashboardTable) SetArgs(args *QueryArgs) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
// SetParams implements QueryProvider
|
||||
func (t *ReportTable) SetParams(params []*ParamDef) {
|
||||
func (t *DashboardTable) SetParams(params []*ParamDef) {
|
||||
t.Params = params
|
||||
}
|
||||
+2
-2
@@ -2,13 +2,13 @@ package modconfig
|
||||
|
||||
import "github.com/turbot/steampipe/utils"
|
||||
|
||||
type ReportTableColumn struct {
|
||||
type DashboardTableColumn struct {
|
||||
Name string `hcl:"name,label" json:"-"`
|
||||
Display *string `cty:"display" hcl:"display" json:"display,omitempty"`
|
||||
Wrap *string `cty:"wrap" hcl:"wrap" json:"wrap,omitempty"`
|
||||
}
|
||||
|
||||
func (c ReportTableColumn) Equals(other *ReportTableColumn) bool {
|
||||
func (c DashboardTableColumn) Equals(other *DashboardTableColumn) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package modconfig
|
||||
|
||||
type ReportTableColumnList []*ReportTableColumn
|
||||
type DashboardTableColumnList []*DashboardTableColumn
|
||||
|
||||
func (c ReportTableColumnList) Merge(other ReportTableColumnList) {
|
||||
func (c DashboardTableColumnList) Merge(other DashboardTableColumnList) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
+34
-34
@@ -10,9 +10,9 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportText is a struct representing a leaf reporting node
|
||||
type ReportText struct {
|
||||
ReportLeafNodeBase
|
||||
// DashboardText is a struct representing a leaf dashboard node
|
||||
type DashboardText struct {
|
||||
DashboardLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
FullName string `cty:"name" json:"-"`
|
||||
@@ -20,11 +20,11 @@ type ReportText struct {
|
||||
UnqualifiedName string `json:"-"`
|
||||
|
||||
// these properties are JSON serialised by the parent LeafRun
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Value *string `cty:"value" hcl:"value" column:"value,text" json:"value,omitempty"`
|
||||
Base *ReportText `hcl:"base" json:"-"`
|
||||
Value *string `cty:"value" hcl:"value" column:"value,text" json:"value,omitempty"`
|
||||
Base *DashboardText `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
@@ -33,9 +33,9 @@ type ReportText struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportText(block *hcl.Block, mod *Mod) *ReportText {
|
||||
func NewDashboardText(block *hcl.Block, mod *Mod) *DashboardText {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
t := &ReportText{
|
||||
t := &DashboardText{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
@@ -46,29 +46,29 @@ func NewReportText(block *hcl.Block, mod *Mod) *ReportText {
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *ReportText) Equals(other *ReportText) bool {
|
||||
func (t *DashboardText) Equals(other *DashboardText) bool {
|
||||
diff := t.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (t *ReportText) CtyValue() (cty.Value, error) {
|
||||
func (t *DashboardText) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(t)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem, ReportLeafNode
|
||||
// Name implements HclResource, ModTreeItem, DashboardLeafNode
|
||||
// return name in format: 'text.<shortName>'
|
||||
func (t *ReportText) Name() string {
|
||||
func (t *DashboardText) Name() string {
|
||||
return t.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (t *ReportText) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
func (t *DashboardText) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
t.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ReportText) setBaseProperties() {
|
||||
func (t *DashboardText) setBaseProperties() {
|
||||
if t.Base == nil {
|
||||
return
|
||||
}
|
||||
@@ -87,51 +87,51 @@ func (t *ReportText) setBaseProperties() {
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (t *ReportText) AddReference(*ResourceReference) {}
|
||||
func (t *DashboardText) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (t *ReportText) GetMod() *Mod {
|
||||
func (t *DashboardText) GetMod() *Mod {
|
||||
return t.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (t *ReportText) GetDeclRange() *hcl.Range {
|
||||
func (t *DashboardText) GetDeclRange() *hcl.Range {
|
||||
return &t.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (t *ReportText) AddParent(parent ModTreeItem) error {
|
||||
func (t *DashboardText) AddParent(parent ModTreeItem) error {
|
||||
t.parents = append(t.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (t *ReportText) GetParents() []ModTreeItem {
|
||||
func (t *DashboardText) GetParents() []ModTreeItem {
|
||||
return t.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (t *ReportText) GetChildren() []ModTreeItem {
|
||||
func (t *DashboardText) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (t *ReportText) GetTitle() string {
|
||||
func (t *DashboardText) GetTitle() string {
|
||||
return typehelpers.SafeString(t.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (t *ReportText) GetDescription() string {
|
||||
func (t *DashboardText) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (t *ReportText) GetTags() map[string]string {
|
||||
func (t *DashboardText) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (t *ReportText) GetPaths() []NodePath {
|
||||
func (t *DashboardText) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(t.Paths) == 0 {
|
||||
t.SetPaths()
|
||||
@@ -141,7 +141,7 @@ func (t *ReportText) GetPaths() []NodePath {
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (t *ReportText) SetPaths() {
|
||||
func (t *DashboardText) SetPaths() {
|
||||
for _, parent := range t.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
t.Paths = append(t.Paths, append(parentPath, t.Name()))
|
||||
@@ -149,8 +149,8 @@ func (t *ReportText) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *ReportText) Diff(other *ReportText) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (t *DashboardText) Diff(other *DashboardText) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: t,
|
||||
Name: t.Name(),
|
||||
}
|
||||
@@ -180,20 +180,20 @@ func (t *ReportText) Diff(other *ReportText) *ReportTreeItemDiffs {
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSQL implements ReportLeafNode
|
||||
func (t *ReportText) GetSQL() string {
|
||||
// GetSQL implements DashboardLeafNode
|
||||
func (t *DashboardText) GetSQL() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (t *ReportText) GetWidth() int {
|
||||
// GetWidth implements DashboardLeafNode
|
||||
func (t *DashboardText) GetWidth() int {
|
||||
if t.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *t.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (t *ReportText) GetUnqualifiedName() string {
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (t *DashboardText) GetUnqualifiedName() string {
|
||||
return t.UnqualifiedName
|
||||
}
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
package modconfig
|
||||
|
||||
// ReportTreeItemDiffs is a struct representing the differences between 2 ReportTreeItems (of same type)
|
||||
type ReportTreeItemDiffs struct {
|
||||
// DashboardTreeItemDiffs is a struct representing the differences between 2 DashboardTreeItems (of same type)
|
||||
type DashboardTreeItemDiffs struct {
|
||||
Name string
|
||||
Item ModTreeItem
|
||||
ChangedProperties []string
|
||||
@@ -9,19 +9,19 @@ type ReportTreeItemDiffs struct {
|
||||
RemovedItems []string
|
||||
}
|
||||
|
||||
func (d *ReportTreeItemDiffs) AddPropertyDiff(propertyName string) {
|
||||
func (d *DashboardTreeItemDiffs) AddPropertyDiff(propertyName string) {
|
||||
d.ChangedProperties = append(d.ChangedProperties, propertyName)
|
||||
}
|
||||
|
||||
func (d *ReportTreeItemDiffs) AddAddedItem(name string) {
|
||||
func (d *DashboardTreeItemDiffs) AddAddedItem(name string) {
|
||||
d.AddedItems = append(d.AddedItems, name)
|
||||
}
|
||||
|
||||
func (d *ReportTreeItemDiffs) AddRemovedItem(name string) {
|
||||
func (d *DashboardTreeItemDiffs) AddRemovedItem(name string) {
|
||||
d.RemovedItems = append(d.RemovedItems, name)
|
||||
}
|
||||
|
||||
func (d *ReportTreeItemDiffs) populateChildDiffs(old ModTreeItem, new ModTreeItem) {
|
||||
func (d *DashboardTreeItemDiffs) populateChildDiffs(old ModTreeItem, new ModTreeItem) {
|
||||
// build map of child names
|
||||
oldChildMap := make(map[string]bool)
|
||||
newChildMap := make(map[string]bool)
|
||||
@@ -46,7 +46,7 @@ func (d *ReportTreeItemDiffs) populateChildDiffs(old ModTreeItem, new ModTreeIte
|
||||
|
||||
}
|
||||
|
||||
func (d *ReportTreeItemDiffs) HasChanges() bool {
|
||||
func (d *DashboardTreeItemDiffs) HasChanges() bool {
|
||||
return len(d.ChangedProperties)+
|
||||
len(d.AddedItems)+
|
||||
len(d.RemovedItems) > 0
|
||||
@@ -17,7 +17,7 @@ type MappableResource interface {
|
||||
}
|
||||
|
||||
// ModTreeItem must be implemented by elements of the mod resource hierarchy
|
||||
// i.e. Control, Benchmark, Report
|
||||
// i.e. Control, Benchmark, Dashboard
|
||||
type ModTreeItem interface {
|
||||
AddParent(ModTreeItem) error
|
||||
GetChildren() []ModTreeItem
|
||||
@@ -63,21 +63,21 @@ type QueryProvider interface {
|
||||
SetParams(params []*ParamDef)
|
||||
}
|
||||
|
||||
// ParameterisedReportNode must be implemented by resources has params and args
|
||||
type ParameterisedReportNode interface {
|
||||
// ParameterisedDashboardNode must be implemented by resources has params and args
|
||||
type ParameterisedDashboardNode interface {
|
||||
GetParams() []*ParamDef
|
||||
GetArgs() *QueryArgs
|
||||
}
|
||||
|
||||
// ReportLeafNode must be implemented by resources may be a leaf node in the repoort execution tree
|
||||
type ReportLeafNode interface {
|
||||
// DashboardLeafNode must be implemented by resources may be a leaf node in the repoort execution tree
|
||||
type DashboardLeafNode interface {
|
||||
Name() string
|
||||
GetUnqualifiedName() string
|
||||
GetTitle() string
|
||||
GetWidth() int
|
||||
GetPaths() []NodePath
|
||||
GetSQL() string
|
||||
// implemented by ReportLeafNodeBase
|
||||
// implemented by DashboardLeafNodeBase
|
||||
AddRuntimeDependencies(*RuntimeDependency)
|
||||
GetRuntimeDependencies() map[string]*RuntimeDependency
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ func (l *Local) OnDecoded(*hcl.Block) hcl.Diagnostics { return nil }
|
||||
// AddReference implements HclResource
|
||||
func (l *Local) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (l *Local) GetUnqualifiedName() string {
|
||||
return l.UnqualifiedName
|
||||
}
|
||||
@@ -116,8 +116,8 @@ func (l *Local) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Local) Diff(other *Local) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (l *Local) Diff(other *Local) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: l,
|
||||
Name: l.Name(),
|
||||
}
|
||||
|
||||
@@ -57,17 +57,17 @@ type Mod struct {
|
||||
|
||||
Queries map[string]*Query
|
||||
Controls map[string]*Control
|
||||
Benchmarks map[string]*Benchmark
|
||||
Reports map[string]*ReportContainer
|
||||
ReportContainers map[string]*ReportContainer
|
||||
ReportCards map[string]*ReportCard
|
||||
ReportCharts map[string]*ReportChart
|
||||
ReportHierarchies map[string]*ReportHierarchy
|
||||
ReportImages map[string]*ReportImage
|
||||
ReportInputs map[string]*ReportInput
|
||||
ReportTables map[string]*ReportTable
|
||||
ReportTexts map[string]*ReportText
|
||||
Variables map[string]*Variable
|
||||
Benchmarks map[string]*Benchmark
|
||||
Dashboards map[string]*DashboardContainer
|
||||
DashboardContainers map[string]*DashboardContainer
|
||||
DashboardCards map[string]*DashboardCard
|
||||
DashboardCharts map[string]*DashboardChart
|
||||
DashboardHierarchies map[string]*DashboardHierarchy
|
||||
DashboardImages map[string]*DashboardImage
|
||||
DashboardInputs map[string]*DashboardInput
|
||||
DashboardTables map[string]*DashboardTable
|
||||
DashboardTexts map[string]*DashboardText
|
||||
Variables map[string]*Variable
|
||||
Locals map[string]*Local
|
||||
|
||||
// ModPath is the installation location of the mod
|
||||
@@ -86,22 +86,22 @@ func NewMod(shortName, modPath string, defRange hcl.Range) (*Mod, error) {
|
||||
return nil, err
|
||||
}
|
||||
mod := &Mod{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("mod.%s", shortName),
|
||||
Queries: make(map[string]*Query),
|
||||
Controls: make(map[string]*Control),
|
||||
Benchmarks: make(map[string]*Benchmark),
|
||||
Reports: make(map[string]*ReportContainer),
|
||||
ReportContainers: make(map[string]*ReportContainer),
|
||||
ReportCards: make(map[string]*ReportCard),
|
||||
ReportCharts: make(map[string]*ReportChart),
|
||||
ReportHierarchies: make(map[string]*ReportHierarchy),
|
||||
ReportImages: make(map[string]*ReportImage),
|
||||
ReportInputs: make(map[string]*ReportInput),
|
||||
ReportTables: make(map[string]*ReportTable),
|
||||
ReportTexts: make(map[string]*ReportText),
|
||||
Variables: make(map[string]*Variable),
|
||||
Locals: make(map[string]*Local),
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("mod.%s", shortName),
|
||||
Queries: make(map[string]*Query),
|
||||
Controls: make(map[string]*Control),
|
||||
Benchmarks: make(map[string]*Benchmark),
|
||||
Dashboards: make(map[string]*DashboardContainer),
|
||||
DashboardContainers: make(map[string]*DashboardContainer),
|
||||
DashboardCards: make(map[string]*DashboardCard),
|
||||
DashboardCharts: make(map[string]*DashboardChart),
|
||||
DashboardHierarchies: make(map[string]*DashboardHierarchy),
|
||||
DashboardImages: make(map[string]*DashboardImage),
|
||||
DashboardInputs: make(map[string]*DashboardInput),
|
||||
DashboardTables: make(map[string]*DashboardTable),
|
||||
DashboardTexts: make(map[string]*DashboardText),
|
||||
Variables: make(map[string]*Variable),
|
||||
Locals: make(map[string]*Local),
|
||||
|
||||
ModPath: modPath,
|
||||
DeclRange: defRange,
|
||||
|
||||
@@ -121,79 +121,79 @@ func (m *Mod) AddResource(item HclResource) hcl.Diagnostics {
|
||||
}
|
||||
m.Benchmarks[name] = r
|
||||
|
||||
case *ReportContainer:
|
||||
case *DashboardContainer:
|
||||
name := r.Name()
|
||||
// report struct may either be a `report` or a `container`
|
||||
if r.IsReport() {
|
||||
if existing, ok := m.Reports[name]; ok {
|
||||
// DashboardContainer struct may either be a `dashboard` or a `container`
|
||||
if r.IsDashboard() {
|
||||
if existing, ok := m.Dashboards[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.Reports[name] = r
|
||||
m.Dashboards[name] = r
|
||||
|
||||
} else {
|
||||
if existing, ok := m.ReportContainers[name]; ok {
|
||||
if existing, ok := m.DashboardContainers[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportContainers[name] = r
|
||||
m.DashboardContainers[name] = r
|
||||
|
||||
}
|
||||
case *ReportCard:
|
||||
case *DashboardCard:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportCards[name]; ok {
|
||||
if existing, ok := m.DashboardCards[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
} else {
|
||||
m.ReportCards[name] = r
|
||||
m.DashboardCards[name] = r
|
||||
}
|
||||
case *ReportChart:
|
||||
case *DashboardChart:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportCharts[name]; ok {
|
||||
if existing, ok := m.DashboardCharts[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportCharts[name] = r
|
||||
m.DashboardCharts[name] = r
|
||||
|
||||
case *ReportHierarchy:
|
||||
case *DashboardHierarchy:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportHierarchies[name]; ok {
|
||||
if existing, ok := m.DashboardHierarchies[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportHierarchies[name] = r
|
||||
m.DashboardHierarchies[name] = r
|
||||
|
||||
case *ReportImage:
|
||||
case *DashboardImage:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportImages[name]; ok {
|
||||
if existing, ok := m.DashboardImages[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportImages[name] = r
|
||||
m.DashboardImages[name] = r
|
||||
|
||||
case *ReportInput:
|
||||
case *DashboardInput:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportInputs[name]; ok {
|
||||
if existing, ok := m.DashboardInputs[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportInputs[name] = r
|
||||
m.DashboardInputs[name] = r
|
||||
|
||||
case *ReportTable:
|
||||
case *DashboardTable:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportTables[name]; ok {
|
||||
if existing, ok := m.DashboardTables[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportTables[name] = r
|
||||
m.DashboardTables[name] = r
|
||||
|
||||
case *ReportText:
|
||||
case *DashboardText:
|
||||
name := r.Name()
|
||||
if existing, ok := m.ReportTexts[name]; ok {
|
||||
if existing, ok := m.DashboardTexts[name]; ok {
|
||||
diags = append(diags, checkForDuplicate(existing, item)...)
|
||||
break
|
||||
}
|
||||
m.ReportTexts[name] = r
|
||||
m.DashboardTexts[name] = r
|
||||
|
||||
case *Variable:
|
||||
// NOTE: add variable by unqualified name
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package modconfig
|
||||
|
||||
// TOTO [reports] also support error return
|
||||
// TODO [reports] also support error return
|
||||
// WalkResources calls resourceFunc for every resource in the mod
|
||||
// if any resourceFunc returns false, return immediately
|
||||
func (m *Mod) WalkResources(resourceFunc func(item HclResource) bool) {
|
||||
@@ -19,47 +19,47 @@ func (m *Mod) WalkResources(resourceFunc func(item HclResource) bool) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.Reports {
|
||||
for _, r := range m.Dashboards {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportContainers {
|
||||
for _, r := range m.DashboardContainers {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportCards {
|
||||
for _, r := range m.DashboardCards {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportCharts {
|
||||
for _, r := range m.DashboardCharts {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportHierarchies {
|
||||
for _, r := range m.DashboardHierarchies {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportImages {
|
||||
for _, r := range m.DashboardImages {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportInputs {
|
||||
for _, r := range m.DashboardInputs {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportTables {
|
||||
for _, r := range m.DashboardTables {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, r := range m.ReportTexts {
|
||||
for _, r := range m.DashboardTexts {
|
||||
if !resourceFunc(r) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package modconfig
|
||||
|
||||
// NamedItem is a struct used by benchmark, container and report to specify children of different types
|
||||
// NamedItem is a struct used by benchmark, container and dashboard to specify children of different types
|
||||
type NamedItem struct {
|
||||
Name string `cty:"name"`
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func ParseResourcePropertyPath(propertyPath string) (res *ParsedPropertyPath, er
|
||||
}
|
||||
|
||||
// special case handling for runtime dependencies which may have use the "self" qualifier
|
||||
if parts[0] == runtimeDependencyReportScope {
|
||||
if parts[0] == runtimeDependencyDashboardScope {
|
||||
res.Scope = parts[0]
|
||||
parts = parts[1:]
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ func (q *Query) Name() string {
|
||||
return q.FullName
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (q *Query) GetUnqualifiedName() string {
|
||||
return q.UnqualifiedName
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func (q *Query) GetArgs() *QueryArgs {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
// GetSQL implements QueryProvider, DashboardLeafNode
|
||||
func (q *Query) GetSQL() string {
|
||||
return typehelpers.SafeString(q.SQL)
|
||||
}
|
||||
@@ -281,8 +281,8 @@ func (q *Query) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (q *Query) Diff(other *Query) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (q *Query) Diff(other *Query) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: q,
|
||||
Name: q.Name(),
|
||||
}
|
||||
|
||||
@@ -1,256 +0,0 @@
|
||||
package modconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
typehelpers "github.com/turbot/go-kit/types"
|
||||
"github.com/turbot/steampipe/utils"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
)
|
||||
|
||||
// ReportCounter is a struct representing a leaf reporting node
|
||||
type ReportCounter struct {
|
||||
ReportLeafNodeBase
|
||||
ResourceWithMetadataBase
|
||||
|
||||
// required to allow partial decoding
|
||||
Remain hcl.Body `hcl:",remain" json:"-"`
|
||||
|
||||
FullName string `cty:"name" json:"-"`
|
||||
ShortName string `json:"-"`
|
||||
UnqualifiedName string `json:"-"`
|
||||
|
||||
// these properties are JSON serialised by the parent LeafRun
|
||||
Title *string `cty:"title" hcl:"title" column:"title,text" json:"-"`
|
||||
Width *int `cty:"width" hcl:"width" column:"width,text" json:"-"`
|
||||
Type *string `cty:"type" hcl:"type" column:"type,text" json:"type,omitempty"`
|
||||
Style *string `cty:"style" hcl:"style" column:"style,text" json:"style,omitempty"`
|
||||
|
||||
// QueryProvider
|
||||
SQL *string `cty:"sql" hcl:"sql" column:"sql,text" json:"sql"`
|
||||
Query *Query `hcl:"query" json:"-"`
|
||||
PreparedStatementName string `column:"prepared_statement_name,text" json:"-"`
|
||||
Args *QueryArgs `cty:"args" column:"args,jsonb" json:"args,omitempty"`
|
||||
Params []*ParamDef `cty:"params" column:"params,jsonb" json:"params,omitempty"`
|
||||
|
||||
Base *ReportCounter `hcl:"base" json:"-"`
|
||||
|
||||
DeclRange hcl.Range `json:"-"`
|
||||
Mod *Mod `cty:"mod" json:"-"`
|
||||
Paths []NodePath `column:"path,jsonb" json:"-"`
|
||||
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewReportCounter(block *hcl.Block, mod *Mod) *ReportCounter {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
c := &ReportCounter{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
UnqualifiedName: fmt.Sprintf("%s.%s", block.Type, shortName),
|
||||
Mod: mod,
|
||||
DeclRange: block.DefRange,
|
||||
}
|
||||
c.SetAnonymous(block)
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ReportCounter) Equals(other *ReportCounter) bool {
|
||||
diff := c.Diff(other)
|
||||
return !diff.HasChanges()
|
||||
}
|
||||
|
||||
// CtyValue implements HclResource
|
||||
func (c *ReportCounter) CtyValue() (cty.Value, error) {
|
||||
return getCtyValue(c)
|
||||
}
|
||||
|
||||
// Name implements HclResource, ModTreeItem
|
||||
// return name in format: 'counter.<shortName>'
|
||||
func (c *ReportCounter) Name() string {
|
||||
return c.FullName
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *ReportCounter) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.setBaseProperties()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ReportCounter) setBaseProperties() {
|
||||
if c.Base == nil {
|
||||
return
|
||||
}
|
||||
if c.Title == nil {
|
||||
c.Title = c.Base.Title
|
||||
}
|
||||
if c.Type == nil {
|
||||
c.Type = c.Base.Type
|
||||
}
|
||||
if c.Style == nil {
|
||||
c.Style = c.Base.Style
|
||||
}
|
||||
|
||||
if c.Width == nil {
|
||||
c.Width = c.Base.Width
|
||||
}
|
||||
if c.SQL == nil {
|
||||
c.SQL = c.Base.SQL
|
||||
}
|
||||
}
|
||||
|
||||
// AddReference implements HclResource
|
||||
func (c *ReportCounter) AddReference(*ResourceReference) {}
|
||||
|
||||
// GetMod implements HclResource
|
||||
func (c *ReportCounter) GetMod() *Mod {
|
||||
return c.Mod
|
||||
}
|
||||
|
||||
// GetDeclRange implements HclResource
|
||||
func (c *ReportCounter) GetDeclRange() *hcl.Range {
|
||||
return &c.DeclRange
|
||||
}
|
||||
|
||||
// AddParent implements ModTreeItem
|
||||
func (c *ReportCounter) AddParent(parent ModTreeItem) error {
|
||||
c.parents = append(c.parents, parent)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetParents implements ModTreeItem
|
||||
func (c *ReportCounter) GetParents() []ModTreeItem {
|
||||
return c.parents
|
||||
}
|
||||
|
||||
// GetChildren implements ModTreeItem
|
||||
func (c *ReportCounter) GetChildren() []ModTreeItem {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTitle implements ModTreeItem
|
||||
func (c *ReportCounter) GetTitle() string {
|
||||
return typehelpers.SafeString(c.Title)
|
||||
}
|
||||
|
||||
// GetDescription implements ModTreeItem
|
||||
func (c *ReportCounter) GetDescription() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetTags implements ModTreeItem
|
||||
func (c *ReportCounter) GetTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPaths implements ModTreeItem
|
||||
func (c *ReportCounter) GetPaths() []NodePath {
|
||||
// lazy load
|
||||
if len(c.Paths) == 0 {
|
||||
c.SetPaths()
|
||||
}
|
||||
|
||||
return c.Paths
|
||||
}
|
||||
|
||||
// SetPaths implements ModTreeItem
|
||||
func (c *ReportCounter) SetPaths() {
|
||||
for _, parent := range c.parents {
|
||||
for _, parentPath := range parent.GetPaths() {
|
||||
c.Paths = append(c.Paths, append(parentPath, c.Name()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ReportCounter) Diff(other *ReportCounter) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
Item: c,
|
||||
Name: c.Name(),
|
||||
}
|
||||
if !utils.SafeStringsEqual(c.FullName, other.FullName) {
|
||||
res.AddPropertyDiff("Name")
|
||||
}
|
||||
|
||||
if !utils.SafeStringsEqual(c.Title, other.Title) {
|
||||
res.AddPropertyDiff("Title")
|
||||
}
|
||||
|
||||
if !utils.SafeStringsEqual(c.SQL, other.SQL) {
|
||||
res.AddPropertyDiff("SQL")
|
||||
}
|
||||
|
||||
if !utils.SafeIntEqual(c.Width, other.Width) {
|
||||
res.AddPropertyDiff("Width")
|
||||
}
|
||||
|
||||
if !utils.SafeStringsEqual(c.Type, other.Type) {
|
||||
res.AddPropertyDiff("Type")
|
||||
}
|
||||
|
||||
if !utils.SafeStringsEqual(c.Style, other.Style) {
|
||||
res.AddPropertyDiff("Style")
|
||||
}
|
||||
|
||||
res.populateChildDiffs(c, other)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetWidth implements ReportLeafNode
|
||||
func (c *ReportCounter) GetWidth() int {
|
||||
if c.Width == nil {
|
||||
return 0
|
||||
}
|
||||
return *c.Width
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
func (c *ReportCounter) GetUnqualifiedName() string {
|
||||
return c.UnqualifiedName
|
||||
}
|
||||
|
||||
// GetParams implements QueryProvider
|
||||
func (c *ReportCounter) GetParams() []*ParamDef {
|
||||
return c.Params
|
||||
}
|
||||
|
||||
// GetArgs implements QueryProvider
|
||||
func (c *ReportCounter) GetArgs() *QueryArgs {
|
||||
return c.Args
|
||||
}
|
||||
|
||||
// GetSQL implements QueryProvider, ReportLeafNode
|
||||
func (c *ReportCounter) GetSQL() string {
|
||||
return typehelpers.SafeString(c.SQL)
|
||||
}
|
||||
|
||||
// GetQuery implements QueryProvider
|
||||
func (c *ReportCounter) GetQuery() *Query {
|
||||
return c.Query
|
||||
}
|
||||
|
||||
// GetPreparedStatementName implements QueryProvider
|
||||
func (c *ReportCounter) GetPreparedStatementName() string {
|
||||
// lazy load
|
||||
if c.PreparedStatementName == "" {
|
||||
c.PreparedStatementName = preparedStatementName(c)
|
||||
}
|
||||
return c.PreparedStatementName
|
||||
}
|
||||
|
||||
// GetModName implements QueryProvider
|
||||
func (c *ReportCounter) GetModName() string {
|
||||
return c.Mod.NameWithVersion()
|
||||
}
|
||||
|
||||
// SetArgs implements QueryProvider
|
||||
func (c *ReportCounter) SetArgs(args *QueryArgs) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
// SetParams implements QueryProvider
|
||||
func (c *ReportCounter) SetParams(params []*ParamDef) {
|
||||
c.Params = params
|
||||
}
|
||||
@@ -16,18 +16,18 @@ func (d *RuntimeDependency) String() string {
|
||||
return fmt.Sprintf("%s->%s", strings.Join(d.TargetProperties, ","), d.PropertyPath.String())
|
||||
}
|
||||
|
||||
func (d *RuntimeDependency) ResolveSource(resource HclResource, report *ReportContainer, workspace ResourceMapsProvider) error {
|
||||
func (d *RuntimeDependency) ResolveSource(resource HclResource, dashboard *DashboardContainer, workspace ResourceMapsProvider) error {
|
||||
// TODO THINK ABOUT REPORT PREFIX
|
||||
|
||||
resourceName := d.PropertyPath.ToResourceName()
|
||||
var found bool
|
||||
// if this dependency has a 'root' prefix, resolve from the current report container
|
||||
if d.PropertyPath.Scope == runtimeDependencyReportScope {
|
||||
d.SourceResource, found = report.GetInput(resourceName)
|
||||
// if this dependency has a 'root' prefix, resolve from the current dashboard container
|
||||
if d.PropertyPath.Scope == runtimeDependencyDashboardScope {
|
||||
d.SourceResource, found = dashboard.GetInput(resourceName)
|
||||
|
||||
} else {
|
||||
// otherwise, resolve from the workspace
|
||||
d.SourceResource, found = workspace.GetResourceMaps().ReportInputs[resourceName]
|
||||
d.SourceResource, found = workspace.GetResourceMaps().DashboardInputs[resourceName]
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("could not resolve runtime dependency resource %s", d.PropertyPath)
|
||||
|
||||
@@ -15,24 +15,24 @@ func GetResource(provider ResourceMapsProvider, parsedName *ParsedResourceName)
|
||||
resource, found = resourceMaps.Benchmarks[longName]
|
||||
case BlockTypeControl:
|
||||
resource, found = resourceMaps.Controls[longName]
|
||||
case BlockTypeReport:
|
||||
resource, found = resourceMaps.Reports[longName]
|
||||
case BlockTypeDashboard:
|
||||
resource, found = resourceMaps.Dashboards[longName]
|
||||
case BlockTypeContainer:
|
||||
resource, found = resourceMaps.ReportContainers[longName]
|
||||
resource, found = resourceMaps.DashboardContainers[longName]
|
||||
case BlockTypeCard:
|
||||
resource, found = resourceMaps.ReportCards[longName]
|
||||
resource, found = resourceMaps.DashboardCards[longName]
|
||||
case BlockTypeChart:
|
||||
resource, found = resourceMaps.ReportCharts[longName]
|
||||
resource, found = resourceMaps.DashboardCharts[longName]
|
||||
case BlockTypeHierarchy:
|
||||
resource, found = resourceMaps.ReportHierarchies[longName]
|
||||
resource, found = resourceMaps.DashboardHierarchies[longName]
|
||||
case BlockTypeImage:
|
||||
resource, found = resourceMaps.ReportImages[longName]
|
||||
resource, found = resourceMaps.DashboardImages[longName]
|
||||
case BlockTypeInput:
|
||||
resource, found = resourceMaps.ReportInputs[longName]
|
||||
resource, found = resourceMaps.DashboardInputs[longName]
|
||||
case BlockTypeTable:
|
||||
resource, found = resourceMaps.ReportTables[longName]
|
||||
resource, found = resourceMaps.DashboardTables[longName]
|
||||
case BlockTypeText:
|
||||
resource, found = resourceMaps.ReportTexts[longName]
|
||||
resource, found = resourceMaps.DashboardTexts[longName]
|
||||
}
|
||||
return resource, found
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package modconfig
|
||||
|
||||
//
|
||||
//func GetResource(provider ResourceProvider, parsedName *ParsedResourceName, modShortName string) (resource HclResource, found bool) {
|
||||
// longName := fmt.Sprintf("%s.%s.%s", modShortName, parsedName.ItemType, parsedName.Name)
|
||||
//
|
||||
// switch parsedName.ItemType {
|
||||
// case BlockTypeBenchmark:
|
||||
// resource, found = provider.GetBenchmarks()[longName]
|
||||
// case BlockTypeControl:
|
||||
// resource, found = provider.GetControls()[longName]
|
||||
// if !found {
|
||||
// resource, found = provider.GetReportControls()[longName]
|
||||
// }
|
||||
// case BlockTypeReport:
|
||||
// resource, found = provider.GetReports[longName]
|
||||
// case BlockTypeContainer:
|
||||
// resource, found = provider.GetReportContainers[longName]
|
||||
// case BlockTypeCard:
|
||||
// resource, found = provider.GetReportCards[longName]
|
||||
// case BlockTypeChart:
|
||||
// resource, found = provider.GetReportCharts[longName]
|
||||
// case BlockTypeHierarchy:
|
||||
// resource, found = provider.GetReportHierarchies[longName]
|
||||
// case BlockTypeImage:
|
||||
// resource, found = provider.GetReportImages[longName]
|
||||
// case BlockTypeTable:
|
||||
// resource, found = provider.GetReportTables[longName]
|
||||
// case BlockTypeText:
|
||||
// resource, found = provider.GetReportTexts[longName]
|
||||
// }
|
||||
// return resource, found
|
||||
//
|
||||
//}
|
||||
@@ -67,7 +67,7 @@ func (v *Variable) Name() string {
|
||||
return v.FullName
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements ReportLeafNode, ModTreeItem
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
func (v *Variable) GetUnqualifiedName() string {
|
||||
return v.UnqualifiedName
|
||||
}
|
||||
@@ -157,8 +157,8 @@ func (v *Variable) SetPaths() {
|
||||
}
|
||||
}
|
||||
|
||||
func (v *Variable) Diff(other *Variable) *ReportTreeItemDiffs {
|
||||
res := &ReportTreeItemDiffs{
|
||||
func (v *Variable) Diff(other *Variable) *DashboardTreeItemDiffs {
|
||||
res := &DashboardTreeItemDiffs{
|
||||
Item: v,
|
||||
Name: v.Name(),
|
||||
}
|
||||
|
||||
@@ -10,17 +10,17 @@ type WorkspaceResourceMaps struct {
|
||||
Queries map[string]*Query
|
||||
Controls map[string]*Control
|
||||
Benchmarks map[string]*Benchmark
|
||||
Variables map[string]*Variable
|
||||
Reports map[string]*ReportContainer
|
||||
ReportContainers map[string]*ReportContainer
|
||||
ReportCards map[string]*ReportCard
|
||||
ReportCharts map[string]*ReportChart
|
||||
ReportHierarchies map[string]*ReportHierarchy
|
||||
ReportImages map[string]*ReportImage
|
||||
ReportInputs map[string]*ReportInput
|
||||
ReportTables map[string]*ReportTable
|
||||
ReportTexts map[string]*ReportText
|
||||
References map[string]*ResourceReference
|
||||
Variables map[string]*Variable
|
||||
Dashboards map[string]*DashboardContainer
|
||||
DashboardContainers map[string]*DashboardContainer
|
||||
DashboardCards map[string]*DashboardCard
|
||||
DashboardCharts map[string]*DashboardChart
|
||||
DashboardHierarchies map[string]*DashboardHierarchy
|
||||
DashboardImages map[string]*DashboardImage
|
||||
DashboardInputs map[string]*DashboardInput
|
||||
DashboardTables map[string]*DashboardTable
|
||||
DashboardTexts map[string]*DashboardText
|
||||
References map[string]*ResourceReference
|
||||
|
||||
LocalQueries map[string]*Query
|
||||
LocalControls map[string]*Control
|
||||
@@ -29,21 +29,21 @@ type WorkspaceResourceMaps struct {
|
||||
|
||||
func WorkspaceResourceMapFromMod(mod *Mod) *WorkspaceResourceMaps {
|
||||
resourceMaps := &WorkspaceResourceMaps{
|
||||
Mod: mod,
|
||||
Mods: make(map[string]*Mod),
|
||||
Queries: mod.Queries,
|
||||
Controls: mod.Controls,
|
||||
Benchmarks: mod.Benchmarks,
|
||||
Variables: mod.Variables,
|
||||
Reports: mod.Reports,
|
||||
ReportContainers: mod.ReportContainers,
|
||||
ReportCharts: mod.ReportCharts,
|
||||
ReportCards: mod.ReportCards,
|
||||
ReportHierarchies: mod.ReportHierarchies,
|
||||
ReportImages: mod.ReportImages,
|
||||
ReportInputs: mod.ReportInputs,
|
||||
ReportTables: mod.ReportTables,
|
||||
ReportTexts: mod.ReportTexts,
|
||||
Mod: mod,
|
||||
Mods: make(map[string]*Mod),
|
||||
Queries: mod.Queries,
|
||||
Controls: mod.Controls,
|
||||
Benchmarks: mod.Benchmarks,
|
||||
Variables: mod.Variables,
|
||||
Dashboards: mod.Dashboards,
|
||||
DashboardContainers: mod.DashboardContainers,
|
||||
DashboardCharts: mod.DashboardCharts,
|
||||
DashboardCards: mod.DashboardCards,
|
||||
DashboardHierarchies: mod.DashboardHierarchies,
|
||||
DashboardImages: mod.DashboardImages,
|
||||
DashboardInputs: mod.DashboardInputs,
|
||||
DashboardTables: mod.DashboardTables,
|
||||
DashboardTexts: mod.DashboardTexts,
|
||||
}
|
||||
if !mod.IsDefaultMod() {
|
||||
resourceMaps.Mods[mod.Name()] = mod
|
||||
@@ -108,119 +108,119 @@ func (m *WorkspaceResourceMaps) Equals(other *WorkspaceResourceMaps) bool {
|
||||
}
|
||||
}
|
||||
|
||||
for name, report := range m.Reports {
|
||||
if otherReport, ok := other.Reports[name]; !ok {
|
||||
for name, dashboard := range m.Dashboards {
|
||||
if otherDashboard, ok := other.Dashboards[name]; !ok {
|
||||
return false
|
||||
} else if !report.Equals(otherReport) {
|
||||
} else if !dashboard.Equals(otherDashboard) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.Reports {
|
||||
if _, ok := m.Reports[name]; !ok {
|
||||
for name := range other.Dashboards {
|
||||
if _, ok := m.Dashboards[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, container := range m.ReportContainers {
|
||||
if otherReport, ok := other.ReportContainers[name]; !ok {
|
||||
for name, container := range m.DashboardContainers {
|
||||
if otherContainer, ok := other.DashboardContainers[name]; !ok {
|
||||
return false
|
||||
} else if !container.Equals(otherReport) {
|
||||
} else if !container.Equals(otherContainer) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportContainers {
|
||||
if _, ok := m.ReportContainers[name]; !ok {
|
||||
for name := range other.DashboardContainers {
|
||||
if _, ok := m.DashboardContainers[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, cards := range m.ReportCards {
|
||||
if otherReport, ok := other.ReportCards[name]; !ok {
|
||||
for name, cards := range m.DashboardCards {
|
||||
if otherCard, ok := other.DashboardCards[name]; !ok {
|
||||
return false
|
||||
} else if !cards.Equals(otherReport) {
|
||||
} else if !cards.Equals(otherCard) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportCards {
|
||||
if _, ok := m.ReportCards[name]; !ok {
|
||||
for name := range other.DashboardCards {
|
||||
if _, ok := m.DashboardCards[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, charts := range m.ReportCharts {
|
||||
if otherReport, ok := other.ReportCharts[name]; !ok {
|
||||
for name, charts := range m.DashboardCharts {
|
||||
if otherChart, ok := other.DashboardCharts[name]; !ok {
|
||||
return false
|
||||
} else if !charts.Equals(otherReport) {
|
||||
} else if !charts.Equals(otherChart) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportCharts {
|
||||
if _, ok := m.ReportCharts[name]; !ok {
|
||||
for name := range other.DashboardCharts {
|
||||
if _, ok := m.DashboardCharts[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, hierarchies := range m.ReportHierarchies {
|
||||
if otherHierarchy, ok := other.ReportHierarchies[name]; !ok {
|
||||
for name, hierarchies := range m.DashboardHierarchies {
|
||||
if otherHierarchy, ok := other.DashboardHierarchies[name]; !ok {
|
||||
return false
|
||||
} else if !hierarchies.Equals(otherHierarchy) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportHierarchies {
|
||||
if _, ok := m.ReportHierarchies[name]; !ok {
|
||||
for name := range other.DashboardHierarchies {
|
||||
if _, ok := m.DashboardHierarchies[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, images := range m.ReportImages {
|
||||
if otherImage, ok := other.ReportImages[name]; !ok {
|
||||
for name, images := range m.DashboardImages {
|
||||
if otherImage, ok := other.DashboardImages[name]; !ok {
|
||||
return false
|
||||
} else if !images.Equals(otherImage) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportImages {
|
||||
if _, ok := m.ReportImages[name]; !ok {
|
||||
for name := range other.DashboardImages {
|
||||
if _, ok := m.DashboardImages[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, images := range m.ReportInputs {
|
||||
if otherImage, ok := other.ReportInputs[name]; !ok {
|
||||
for name, images := range m.DashboardInputs {
|
||||
if otherImage, ok := other.DashboardInputs[name]; !ok {
|
||||
return false
|
||||
} else if !images.Equals(otherImage) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportInputs {
|
||||
if _, ok := m.ReportInputs[name]; !ok {
|
||||
for name := range other.DashboardInputs {
|
||||
if _, ok := m.DashboardInputs[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, tables := range m.ReportTables {
|
||||
if otherReport, ok := other.ReportTables[name]; !ok {
|
||||
for name, tables := range m.DashboardTables {
|
||||
if otherTable, ok := other.DashboardTables[name]; !ok {
|
||||
return false
|
||||
} else if !tables.Equals(otherReport) {
|
||||
} else if !tables.Equals(otherTable) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportTables {
|
||||
if _, ok := m.ReportTables[name]; !ok {
|
||||
for name := range other.DashboardTables {
|
||||
if _, ok := m.DashboardTables[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for name, texts := range m.ReportTexts {
|
||||
if otherReport, ok := other.ReportTexts[name]; !ok {
|
||||
for name, texts := range m.DashboardTexts {
|
||||
if otherText, ok := other.DashboardTexts[name]; !ok {
|
||||
return false
|
||||
} else if !texts.Equals(otherReport) {
|
||||
} else if !texts.Equals(otherText) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for name := range other.ReportTexts {
|
||||
if _, ok := m.ReportTexts[name]; !ok {
|
||||
for name := range other.DashboardTexts {
|
||||
if _, ok := m.DashboardTexts[name]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -290,14 +290,14 @@ func (m *WorkspaceResourceMaps) Empty() bool {
|
||||
len(m.Controls)+
|
||||
len(m.Benchmarks)+
|
||||
len(m.Variables)+
|
||||
len(m.Reports)+
|
||||
len(m.ReportContainers)+
|
||||
len(m.ReportCards)+
|
||||
len(m.ReportCharts)+
|
||||
len(m.ReportHierarchies)+
|
||||
len(m.ReportImages)+
|
||||
len(m.ReportInputs)+
|
||||
len(m.ReportTables)+
|
||||
len(m.ReportTexts)+
|
||||
len(m.Dashboards)+
|
||||
len(m.DashboardContainers)+
|
||||
len(m.DashboardCards)+
|
||||
len(m.DashboardCharts)+
|
||||
len(m.DashboardHierarchies)+
|
||||
len(m.DashboardImages)+
|
||||
len(m.DashboardInputs)+
|
||||
len(m.DashboardTables)+
|
||||
len(m.DashboardTexts)+
|
||||
len(m.References) == 0
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func decodeBlock(block *hcl.Block, parent modconfig.ModTreeItem, runCtx *RunCont
|
||||
for _, local := range locals {
|
||||
resources = append(resources, local)
|
||||
}
|
||||
case modconfig.BlockTypeContainer, modconfig.BlockTypeReport:
|
||||
case modconfig.BlockTypeContainer, modconfig.BlockTypeDashboard:
|
||||
resource, res = decodeReportContainer(block, runCtx)
|
||||
resources = append(resources, resource)
|
||||
case modconfig.BlockTypeVariable:
|
||||
@@ -166,24 +166,24 @@ func resourceForBlock(block *hcl.Block, runCtx *RunContext) (modconfig.HclResour
|
||||
resource = modconfig.NewControl(block, mod)
|
||||
case modconfig.BlockTypeBenchmark:
|
||||
resource = modconfig.NewBenchmark(block, mod)
|
||||
case modconfig.BlockTypeReport:
|
||||
resource = modconfig.NewReportContainer(block, mod)
|
||||
case modconfig.BlockTypeDashboard:
|
||||
resource = modconfig.NewDashboardContainer(block, mod)
|
||||
case modconfig.BlockTypeContainer:
|
||||
resource = modconfig.NewReportContainer(block, mod)
|
||||
resource = modconfig.NewDashboardContainer(block, mod)
|
||||
case modconfig.BlockTypeChart:
|
||||
resource = modconfig.NewReportChart(block, mod)
|
||||
resource = modconfig.NewDashboardChart(block, mod)
|
||||
case modconfig.BlockTypeCard:
|
||||
resource = modconfig.NewReportCard(block, mod)
|
||||
resource = modconfig.NewDashboardCard(block, mod)
|
||||
case modconfig.BlockTypeHierarchy:
|
||||
resource = modconfig.NewReportHierarchy(block, mod)
|
||||
resource = modconfig.NewDashboardHierarchy(block, mod)
|
||||
case modconfig.BlockTypeImage:
|
||||
resource = modconfig.NewReportImage(block, mod)
|
||||
resource = modconfig.NewDashboardImage(block, mod)
|
||||
case modconfig.BlockTypeInput:
|
||||
resource = modconfig.NewReportInput(block, mod)
|
||||
resource = modconfig.NewDashboardInput(block, mod)
|
||||
case modconfig.BlockTypeTable:
|
||||
resource = modconfig.NewReportTable(block, mod)
|
||||
resource = modconfig.NewDashboardTable(block, mod)
|
||||
case modconfig.BlockTypeText:
|
||||
resource = modconfig.NewReportText(block, mod)
|
||||
resource = modconfig.NewDashboardText(block, mod)
|
||||
default:
|
||||
return nil, hcl.Diagnostics{&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
@@ -392,68 +392,68 @@ func decodeArgs(attr *hcl.Attribute, evalCtx *hcl.EvalContext, controlName strin
|
||||
return args, diags
|
||||
}
|
||||
|
||||
func decodeReportContainer(block *hcl.Block, runCtx *RunContext) (*modconfig.ReportContainer, *decodeResult) {
|
||||
func decodeReportContainer(block *hcl.Block, runCtx *RunContext) (*modconfig.DashboardContainer, *decodeResult) {
|
||||
res := &decodeResult{}
|
||||
reportContainer := modconfig.NewReportContainer(block, runCtx.CurrentMod)
|
||||
dashboardContainer := modconfig.NewDashboardContainer(block, runCtx.CurrentMod)
|
||||
|
||||
// do a partial decode using QueryProviderBlockSchema
|
||||
// this will be used to pull out attributes which need manual decoding
|
||||
content, _, diags := block.Body.PartialContent(ReportContainerBlockSchema)
|
||||
res.handleDecodeDiags(content, reportContainer, diags)
|
||||
res.handleDecodeDiags(content, dashboardContainer, diags)
|
||||
if !res.Success() {
|
||||
return nil, res
|
||||
}
|
||||
|
||||
// decode the body into 'reportContainer' to populate all properties that can be automatically decoded
|
||||
diags = gohcl.DecodeBody(block.Body, runCtx.EvalCtx, reportContainer)
|
||||
// decode the body into 'dashboardContainer' to populate all properties that can be automatically decoded
|
||||
diags = gohcl.DecodeBody(block.Body, runCtx.EvalCtx, dashboardContainer)
|
||||
// handle any resulting diags, which may specify dependencies
|
||||
res.handleDecodeDiags(content, reportContainer, diags)
|
||||
res.handleDecodeDiags(content, dashboardContainer, diags)
|
||||
|
||||
// if this is a container, the base property must not be set
|
||||
if !reportContainer.IsReport() && reportContainer.Base != nil {
|
||||
if !dashboardContainer.IsDashboard() && dashboardContainer.Base != nil {
|
||||
res.addDiags(hcl.Diagnostics{&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Container blocks do not support the 'base' property",
|
||||
Subject: &reportContainer.DeclRange,
|
||||
Subject: &dashboardContainer.DeclRange,
|
||||
}})
|
||||
return nil, res
|
||||
}
|
||||
|
||||
if reportContainer.Base != nil && len(reportContainer.Base.ChildNames) > 0 {
|
||||
if dashboardContainer.Base != nil && len(dashboardContainer.Base.ChildNames) > 0 {
|
||||
supportedChildren := []string{modconfig.BlockTypeContainer, modconfig.BlockTypeChart, modconfig.BlockTypeControl, modconfig.BlockTypeCard, modconfig.BlockTypeHierarchy, modconfig.BlockTypeImage, modconfig.BlockTypeInput, modconfig.BlockTypeTable, modconfig.BlockTypeText}
|
||||
// TODO: we should be passing in the block for the Base resource - but this is only used for diags
|
||||
// and we do not expect to get any (as this function has already succeeded when the base was originally parsed)
|
||||
children, _ := resolveChildrenFromNames(reportContainer.Base.ChildNames, block, supportedChildren, runCtx)
|
||||
reportContainer.Base.SetChildren(children)
|
||||
children, _ := resolveChildrenFromNames(dashboardContainer.Base.ChildNames, block, supportedChildren, runCtx)
|
||||
dashboardContainer.Base.SetChildren(children)
|
||||
}
|
||||
if !res.Success() {
|
||||
return reportContainer, res
|
||||
return dashboardContainer, res
|
||||
}
|
||||
|
||||
// decode args if any
|
||||
if attr, exists := content.Attributes["args"]; exists {
|
||||
if args, diags := decodeArgs(attr, runCtx.EvalCtx, reportContainer.Name()); !diags.HasErrors() {
|
||||
reportContainer.SetArgs(args)
|
||||
if args, diags := decodeArgs(attr, runCtx.EvalCtx, dashboardContainer.Name()); !diags.HasErrors() {
|
||||
dashboardContainer.SetArgs(args)
|
||||
}
|
||||
}
|
||||
|
||||
// now decode child blocks
|
||||
if len(content.Blocks) > 0 {
|
||||
blocksRes := decodeReportContainerBlocks(content, reportContainer, runCtx)
|
||||
blocksRes := decodeReportContainerBlocks(content, dashboardContainer, runCtx)
|
||||
res.Merge(blocksRes)
|
||||
}
|
||||
|
||||
return reportContainer, res
|
||||
return dashboardContainer, res
|
||||
}
|
||||
|
||||
func decodeReportContainerBlocks(content *hcl.BodyContent, reportContainer *modconfig.ReportContainer, runCtx *RunContext) *decodeResult {
|
||||
func decodeReportContainerBlocks(content *hcl.BodyContent, dashboardContainer *modconfig.DashboardContainer, runCtx *RunContext) *decodeResult {
|
||||
var res = &decodeResult{}
|
||||
// if children are declared inline as blocks, add them
|
||||
var children []modconfig.ModTreeItem
|
||||
var inputs []*modconfig.ReportInput
|
||||
var inputs []*modconfig.DashboardInput
|
||||
for _, b := range content.Blocks {
|
||||
// use generic block decoding
|
||||
resources, blockRes := decodeBlock(b, reportContainer, runCtx)
|
||||
resources, blockRes := decodeBlock(b, dashboardContainer, runCtx)
|
||||
res.Merge(blockRes)
|
||||
if !blockRes.Success() {
|
||||
continue
|
||||
@@ -462,11 +462,13 @@ func decodeReportContainerBlocks(content *hcl.BodyContent, reportContainer *modc
|
||||
// we expect either inputs or child report nodes
|
||||
for _, resource := range resources {
|
||||
if b.Type == modconfig.BlockTypeInput {
|
||||
input := resource.(*modconfig.ReportInput)
|
||||
// add report name to input
|
||||
input.SetReportContainer(reportContainer)
|
||||
input := resource.(*modconfig.DashboardInput)
|
||||
// add dashboard name to input
|
||||
input.SetDashboardContainer(dashboardContainer)
|
||||
|
||||
inputs = append(inputs, input)
|
||||
// now we have namespaced the input, add to mod
|
||||
res.addDiags(runCtx.CurrentMod.AddResource(resource))
|
||||
|
||||
} else {
|
||||
// add the resource to the mod
|
||||
@@ -480,15 +482,14 @@ func decodeReportContainerBlocks(content *hcl.BodyContent, reportContainer *modc
|
||||
}
|
||||
}
|
||||
|
||||
reportContainer.SetChildren(children)
|
||||
if err := reportContainer.SetInputs(inputs); err != nil {
|
||||
dashboardContainer.SetChildren(children)
|
||||
if err := dashboardContainer.SetInputs(inputs); err != nil {
|
||||
res.addDiags(hcl.Diagnostics{&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
Summary: "Duplicate input names",
|
||||
Detail: err.Error(),
|
||||
Subject: &reportContainer.DeclRange,
|
||||
Subject: &dashboardContainer.DeclRange,
|
||||
}})
|
||||
|
||||
}
|
||||
|
||||
return res
|
||||
@@ -572,14 +573,6 @@ func handleDecodeResult(resource modconfig.HclResource, res *decodeResult, block
|
||||
if !anonymousResource {
|
||||
moreDiags = runCtx.AddResource(resource)
|
||||
res.addDiags(moreDiags)
|
||||
|
||||
// if resource is NOT a mod, add resource to current mod
|
||||
if _, ok := resource.(*modconfig.Mod); !ok {
|
||||
// - this will fail if the mod already has a resource with the same name
|
||||
// we cannot add anonymous resources at this point - they will be added after their names are set
|
||||
moreDiags = runCtx.CurrentMod.AddResource(resource)
|
||||
res.addDiags(moreDiags)
|
||||
}
|
||||
}
|
||||
|
||||
// if resource supports metadata, save it
|
||||
|
||||
@@ -37,9 +37,9 @@ func (p *decodeResult) handleDecodeDiags(bodyContent *hcl.BodyContent, resource
|
||||
// so it was a dependency error - determine whether this is a RUN TIME dependency
|
||||
// - if so, do not raise a dependency error but instead store in the resources run time dependencies
|
||||
if runtimeDependency := dependency.ToRuntimeDependency(bodyContent); runtimeDependency != nil {
|
||||
// resource must be convertible to a ReportLeafNode
|
||||
// resource must be convertible to a DashboardLeafNode
|
||||
// - these are the only resources to support runtime dependencies
|
||||
leafNode, ok := resource.(modconfig.ReportLeafNode)
|
||||
leafNode, ok := resource.(modconfig.DashboardLeafNode)
|
||||
if !ok {
|
||||
p.addDiags(hcl.Diagnostics{&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
|
||||
@@ -13,7 +13,7 @@ var referenceBlockTypes = []string{
|
||||
modconfig.BlockTypeQuery,
|
||||
modconfig.BlockTypeControl,
|
||||
modconfig.BlockTypeBenchmark,
|
||||
modconfig.BlockTypeReport,
|
||||
modconfig.BlockTypeDashboard,
|
||||
modconfig.BlockTypeContainer,
|
||||
modconfig.BlockTypeCard,
|
||||
modconfig.BlockTypeChart,
|
||||
|
||||
@@ -65,7 +65,7 @@ var ModBlockSchema = &hcl.BodySchema{
|
||||
LabelNames: []string{"name"},
|
||||
},
|
||||
{
|
||||
Type: modconfig.BlockTypeReport,
|
||||
Type: modconfig.BlockTypeDashboard,
|
||||
LabelNames: []string{"name"},
|
||||
},
|
||||
{
|
||||
@@ -124,7 +124,7 @@ var ReportContainerBlockSchema = &hcl.BodySchema{
|
||||
Type: modconfig.BlockTypeContainer,
|
||||
},
|
||||
{
|
||||
Type: modconfig.BlockTypeReport,
|
||||
Type: modconfig.BlockTypeDashboard,
|
||||
LabelNames: []string{"name"},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"m1": {
|
||||
"github.com/turbot/steampipe-mod-aws-compliance": {
|
||||
"Name": "github.com/turbot/steampipe-mod-aws-compliance",
|
||||
"Version": "0.23.0",
|
||||
"Constraint": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
Submodule
+1
Submodule steampipeconfig/testdata/mods/report/.steampipe/mods/github.com/turbot/[email protected] added at 80e8aea516.
+9
-9
@@ -6,7 +6,7 @@ query "q1"{
|
||||
}
|
||||
}
|
||||
|
||||
report "r1"{
|
||||
dashboard "r1"{
|
||||
input "i1"{ }
|
||||
|
||||
chart {
|
||||
@@ -18,11 +18,11 @@ report "r1"{
|
||||
|
||||
}
|
||||
|
||||
report "r2"{
|
||||
report "derived1" {
|
||||
base = report.r1
|
||||
}
|
||||
report "derived2" {
|
||||
base = report.r1
|
||||
}
|
||||
}
|
||||
//dashboard "r2"{
|
||||
// dashboard "derived1" {
|
||||
// base = dashboard.r1
|
||||
// }
|
||||
// dashboard "derived2" {
|
||||
// base = dashboard.r1
|
||||
// }
|
||||
//}
|
||||
+37
-37
@@ -13,9 +13,9 @@ import (
|
||||
"github.com/fsnotify/fsnotify"
|
||||
filehelpers "github.com/turbot/go-kit/files"
|
||||
"github.com/turbot/steampipe/constants"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/filepaths"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/steampipeconfig"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/steampipeconfig/parse"
|
||||
@@ -30,20 +30,20 @@ type Workspace struct {
|
||||
|
||||
// maps of mod resources from this mod and ALL DEPENDENCIES, keyed by long and short names
|
||||
|
||||
Queries map[string]*modconfig.Query
|
||||
Controls map[string]*modconfig.Control
|
||||
Benchmarks map[string]*modconfig.Benchmark
|
||||
Mods map[string]*modconfig.Mod
|
||||
Reports map[string]*modconfig.ReportContainer
|
||||
ReportContainers map[string]*modconfig.ReportContainer
|
||||
ReportCards map[string]*modconfig.ReportCard
|
||||
ReportCharts map[string]*modconfig.ReportChart
|
||||
ReportHierarchies map[string]*modconfig.ReportHierarchy
|
||||
ReportImages map[string]*modconfig.ReportImage
|
||||
ReportInputs map[string]*modconfig.ReportInput
|
||||
ReportTables map[string]*modconfig.ReportTable
|
||||
ReportTexts map[string]*modconfig.ReportText
|
||||
Variables map[string]*modconfig.Variable
|
||||
Queries map[string]*modconfig.Query
|
||||
Controls map[string]*modconfig.Control
|
||||
Benchmarks map[string]*modconfig.Benchmark
|
||||
Mods map[string]*modconfig.Mod
|
||||
Dashboards map[string]*modconfig.DashboardContainer
|
||||
DashboardContainers map[string]*modconfig.DashboardContainer
|
||||
DashboardCards map[string]*modconfig.DashboardCard
|
||||
DashboardCharts map[string]*modconfig.DashboardChart
|
||||
DashboardHierarchies map[string]*modconfig.DashboardHierarchy
|
||||
DashboardImages map[string]*modconfig.DashboardImage
|
||||
DashboardInputs map[string]*modconfig.DashboardInput
|
||||
DashboardTables map[string]*modconfig.DashboardTable
|
||||
DashboardTexts map[string]*modconfig.DashboardText
|
||||
Variables map[string]*modconfig.Variable
|
||||
|
||||
//local resources keyed by unqualified name
|
||||
LocalQueries map[string]*modconfig.Query
|
||||
@@ -58,7 +58,7 @@ type Workspace struct {
|
||||
fileWatcherErrorHandler func(context.Context, error)
|
||||
watcherError error
|
||||
// event handlers
|
||||
reportEventHandlers []reportevents.ReportEventHandler
|
||||
dashboardEventHandlers []dashboardevents.DashboardEventHandler
|
||||
// callback function to reset display after the file watche displays messages
|
||||
onFileWatcherEventMessages func()
|
||||
modFileExists bool
|
||||
@@ -170,15 +170,15 @@ func (w *Workspace) reset() {
|
||||
w.Controls = make(map[string]*modconfig.Control)
|
||||
w.Benchmarks = make(map[string]*modconfig.Benchmark)
|
||||
w.Mods = make(map[string]*modconfig.Mod)
|
||||
w.Reports = make(map[string]*modconfig.ReportContainer)
|
||||
w.ReportContainers = make(map[string]*modconfig.ReportContainer)
|
||||
w.ReportCards = make(map[string]*modconfig.ReportCard)
|
||||
w.ReportCharts = make(map[string]*modconfig.ReportChart)
|
||||
w.ReportHierarchies = make(map[string]*modconfig.ReportHierarchy)
|
||||
w.ReportImages = make(map[string]*modconfig.ReportImage)
|
||||
w.ReportInputs = make(map[string]*modconfig.ReportInput)
|
||||
w.ReportTables = make(map[string]*modconfig.ReportTable)
|
||||
w.ReportTexts = make(map[string]*modconfig.ReportText)
|
||||
w.Dashboards = make(map[string]*modconfig.DashboardContainer)
|
||||
w.DashboardContainers = make(map[string]*modconfig.DashboardContainer)
|
||||
w.DashboardCards = make(map[string]*modconfig.DashboardCard)
|
||||
w.DashboardCharts = make(map[string]*modconfig.DashboardChart)
|
||||
w.DashboardHierarchies = make(map[string]*modconfig.DashboardHierarchy)
|
||||
w.DashboardImages = make(map[string]*modconfig.DashboardImage)
|
||||
w.DashboardInputs = make(map[string]*modconfig.DashboardInput)
|
||||
w.DashboardTables = make(map[string]*modconfig.DashboardTable)
|
||||
w.DashboardTexts = make(map[string]*modconfig.DashboardText)
|
||||
w.LocalQueries = make(map[string]*modconfig.Query)
|
||||
w.LocalControls = make(map[string]*modconfig.Control)
|
||||
w.LocalBenchmarks = make(map[string]*modconfig.Benchmark)
|
||||
@@ -232,15 +232,15 @@ func (w *Workspace) loadWorkspaceMod(ctx context.Context) error {
|
||||
w.Queries, w.LocalQueries = w.buildQueryMap(runCtx.LoadedDependencyMods)
|
||||
w.Controls, w.LocalControls = w.buildControlMap(runCtx.LoadedDependencyMods)
|
||||
w.Benchmarks, w.LocalBenchmarks = w.buildBenchmarkMap(runCtx.LoadedDependencyMods)
|
||||
w.Reports = w.buildReportMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportContainers = w.buildReportContainerMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportCards = w.buildReportCardMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportCharts = w.buildReportChartMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportHierarchies = w.buildReportHierarchyMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportImages = w.buildReportImageMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportInputs = w.buildReportInputMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportTables = w.buildReportTableMap(runCtx.LoadedDependencyMods)
|
||||
w.ReportTexts = w.buildReportTextMap(runCtx.LoadedDependencyMods)
|
||||
w.Dashboards = w.buildDashboardMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardContainers = w.buildDashboardContainerMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardCards = w.buildDashboardCardMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardCharts = w.buildDashboardChartMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardHierarchies = w.buildDashboardHierarchyMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardImages = w.buildDashboardImageMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardInputs = w.buildDashboardInputMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardTables = w.buildDashboardTableMap(runCtx.LoadedDependencyMods)
|
||||
w.DashboardTexts = w.buildDashboardTextMap(runCtx.LoadedDependencyMods)
|
||||
|
||||
// set variables on workspace
|
||||
w.Variables = m.Variables
|
||||
@@ -251,7 +251,7 @@ func (w *Workspace) loadWorkspaceMod(ctx context.Context) error {
|
||||
// populate the workspace resource map
|
||||
w.populateResourceMaps()
|
||||
|
||||
//
|
||||
// verify all runtime dependencies can be resolved
|
||||
return w.verifyResourceRuntimeDependencies()
|
||||
}
|
||||
|
||||
@@ -341,8 +341,8 @@ func (w *Workspace) loadWorkspaceResourceName() (*modconfig.WorkspaceResources,
|
||||
}
|
||||
|
||||
func (w *Workspace) verifyResourceRuntimeDependencies() error {
|
||||
for _, r := range w.Reports {
|
||||
if err := r.BuildRuntimeDependencyTree(w); err != nil {
|
||||
for _, d := range w.Dashboards {
|
||||
if err := d.BuildRuntimeDependencyTree(w); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,26 +7,26 @@ import (
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/turbot/steampipe/db/db_common"
|
||||
"github.com/turbot/steampipe/report/reportevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
"github.com/turbot/steampipe/utils"
|
||||
)
|
||||
|
||||
func (w *Workspace) PublishReportEvent(e reportevents.ReportEvent) {
|
||||
for _, handler := range w.reportEventHandlers {
|
||||
func (w *Workspace) PublishDashboardEvent(e dashboardevents.DashboardEvent) {
|
||||
for _, handler := range w.dashboardEventHandlers {
|
||||
handler(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Workspace) RegisterReportEventHandler(handler reportevents.ReportEventHandler) {
|
||||
w.reportEventHandlers = append(w.reportEventHandlers, handler)
|
||||
func (w *Workspace) RegisterDashboardEventHandler(handler dashboardevents.DashboardEventHandler) {
|
||||
w.dashboardEventHandlers = append(w.dashboardEventHandlers, handler)
|
||||
}
|
||||
|
||||
func (w *Workspace) handleFileWatcherEvent(ctx context.Context, client db_common.Client, _ []fsnotify.Event) {
|
||||
prevResourceMaps, resourceMaps, err := w.reloadResourceMaps(ctx)
|
||||
if err != nil {
|
||||
// publish error event
|
||||
w.PublishReportEvent(&reportevents.WorkspaceError{Error: err})
|
||||
w.PublishDashboardEvent(&dashboardevents.WorkspaceError{Error: err})
|
||||
return
|
||||
}
|
||||
// if resources have changed, update introspection tables and prepared statements
|
||||
@@ -41,7 +41,7 @@ func (w *Workspace) handleFileWatcherEvent(ctx context.Context, client db_common
|
||||
}
|
||||
}
|
||||
}
|
||||
w.raiseReportChangedEvents(resourceMaps, prevResourceMaps)
|
||||
w.raiseDashboardChangedEvents(resourceMaps, prevResourceMaps)
|
||||
}
|
||||
|
||||
func (w *Workspace) reloadResourceMaps(ctx context.Context) (*modconfig.WorkspaceResourceMaps, *modconfig.WorkspaceResourceMaps, error) {
|
||||
@@ -79,22 +79,22 @@ func (w *Workspace) reloadResourceMaps(ctx context.Context) (*modconfig.Workspac
|
||||
|
||||
}
|
||||
|
||||
func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *modconfig.WorkspaceResourceMaps) {
|
||||
event := &reportevents.ReportChanged{}
|
||||
func (w *Workspace) raiseDashboardChangedEvents(resourceMaps, prevResourceMaps *modconfig.WorkspaceResourceMaps) {
|
||||
event := &dashboardevents.DashboardChanged{}
|
||||
|
||||
// first detect changes to existing resources and deletions
|
||||
for name, prev := range prevResourceMaps.Reports {
|
||||
if current, ok := resourceMaps.Reports[name]; ok {
|
||||
for name, prev := range prevResourceMaps.Dashboards {
|
||||
if current, ok := resourceMaps.Dashboards[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedReports = append(event.ChangedReports, diff)
|
||||
event.ChangedDashboards = append(event.ChangedDashboards, diff)
|
||||
}
|
||||
} else {
|
||||
event.DeletedReports = append(event.DeletedReports, prev)
|
||||
event.DeletedDashboards = append(event.DeletedDashboards, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportContainers {
|
||||
if current, ok := resourceMaps.ReportContainers[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardContainers {
|
||||
if current, ok := resourceMaps.DashboardContainers[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedContainers = append(event.ChangedContainers, diff)
|
||||
@@ -103,8 +103,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedContainers = append(event.DeletedContainers, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportCards {
|
||||
if current, ok := resourceMaps.ReportCards[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardCards {
|
||||
if current, ok := resourceMaps.DashboardCards[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedCards = append(event.ChangedCards, diff)
|
||||
@@ -113,8 +113,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedCards = append(event.DeletedCards, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportCharts {
|
||||
if current, ok := resourceMaps.ReportCharts[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardCharts {
|
||||
if current, ok := resourceMaps.DashboardCharts[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedCharts = append(event.ChangedCharts, diff)
|
||||
@@ -143,8 +143,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedControls = append(event.DeletedControls, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportHierarchies {
|
||||
if current, ok := resourceMaps.ReportHierarchies[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardHierarchies {
|
||||
if current, ok := resourceMaps.DashboardHierarchies[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedHierarchies = append(event.ChangedHierarchies, diff)
|
||||
@@ -153,8 +153,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedHierarchies = append(event.DeletedHierarchies, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportImages {
|
||||
if current, ok := resourceMaps.ReportImages[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardImages {
|
||||
if current, ok := resourceMaps.DashboardImages[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedImages = append(event.ChangedImages, diff)
|
||||
@@ -163,8 +163,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedImages = append(event.DeletedImages, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportInputs {
|
||||
if current, ok := resourceMaps.ReportInputs[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardInputs {
|
||||
if current, ok := resourceMaps.DashboardInputs[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedInputs = append(event.ChangedInputs, diff)
|
||||
@@ -173,8 +173,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedInputs = append(event.DeletedInputs, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportTables {
|
||||
if current, ok := resourceMaps.ReportTables[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardTables {
|
||||
if current, ok := resourceMaps.DashboardTables[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedTables = append(event.ChangedTables, diff)
|
||||
@@ -183,8 +183,8 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.DeletedTables = append(event.DeletedTables, prev)
|
||||
}
|
||||
}
|
||||
for name, prev := range prevResourceMaps.ReportTexts {
|
||||
if current, ok := resourceMaps.ReportTexts[name]; ok {
|
||||
for name, prev := range prevResourceMaps.DashboardTexts {
|
||||
if current, ok := resourceMaps.DashboardTexts[name]; ok {
|
||||
diff := prev.Diff(current)
|
||||
if diff.HasChanges() {
|
||||
event.ChangedTexts = append(event.ChangedTexts, diff)
|
||||
@@ -195,23 +195,23 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
}
|
||||
|
||||
// now detect new resources
|
||||
for name, p := range resourceMaps.Reports {
|
||||
if _, ok := prevResourceMaps.Reports[name]; !ok {
|
||||
event.NewReports = append(event.NewReports, p)
|
||||
for name, p := range resourceMaps.Dashboards {
|
||||
if _, ok := prevResourceMaps.Dashboards[name]; !ok {
|
||||
event.NewDashboards = append(event.NewDashboards, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportContainers {
|
||||
if _, ok := prevResourceMaps.ReportContainers[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardContainers {
|
||||
if _, ok := prevResourceMaps.DashboardContainers[name]; !ok {
|
||||
event.NewContainers = append(event.NewContainers, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportCards {
|
||||
if _, ok := prevResourceMaps.ReportCards[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardCards {
|
||||
if _, ok := prevResourceMaps.DashboardCards[name]; !ok {
|
||||
event.NewCards = append(event.NewCards, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportCharts {
|
||||
if _, ok := prevResourceMaps.ReportCharts[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardCharts {
|
||||
if _, ok := prevResourceMaps.DashboardCharts[name]; !ok {
|
||||
event.NewCharts = append(event.NewCharts, p)
|
||||
}
|
||||
}
|
||||
@@ -225,33 +225,33 @@ func (w *Workspace) raiseReportChangedEvents(resourceMaps, prevResourceMaps *mod
|
||||
event.NewControls = append(event.NewControls, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportHierarchies {
|
||||
if _, ok := prevResourceMaps.ReportHierarchies[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardHierarchies {
|
||||
if _, ok := prevResourceMaps.DashboardHierarchies[name]; !ok {
|
||||
event.NewHierarchies = append(event.NewHierarchies, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportImages {
|
||||
if _, ok := prevResourceMaps.ReportImages[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardImages {
|
||||
if _, ok := prevResourceMaps.DashboardImages[name]; !ok {
|
||||
event.NewImages = append(event.NewImages, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportInputs {
|
||||
if _, ok := prevResourceMaps.ReportInputs[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardInputs {
|
||||
if _, ok := prevResourceMaps.DashboardInputs[name]; !ok {
|
||||
event.NewInputs = append(event.NewInputs, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportTables {
|
||||
if _, ok := prevResourceMaps.ReportTables[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardTables {
|
||||
if _, ok := prevResourceMaps.DashboardTables[name]; !ok {
|
||||
event.NewTables = append(event.NewTables, p)
|
||||
}
|
||||
}
|
||||
for name, p := range resourceMaps.ReportTexts {
|
||||
if _, ok := prevResourceMaps.ReportTexts[name]; !ok {
|
||||
for name, p := range resourceMaps.DashboardTexts {
|
||||
if _, ok := prevResourceMaps.DashboardTexts[name]; !ok {
|
||||
event.NewTexts = append(event.NewTexts, p)
|
||||
}
|
||||
}
|
||||
|
||||
if event.HasChanges() {
|
||||
w.PublishReportEvent(event)
|
||||
w.PublishDashboardEvent(event)
|
||||
}
|
||||
}
|
||||
@@ -38,24 +38,24 @@ func (w *Workspace) GetResourceMaps() *modconfig.WorkspaceResourceMaps {
|
||||
|
||||
func (w *Workspace) populateResourceMaps() {
|
||||
w.resourceMaps = &modconfig.WorkspaceResourceMaps{
|
||||
Mod: w.Mod,
|
||||
Mods: make(map[string]*modconfig.Mod),
|
||||
LocalQueries: w.LocalQueries,
|
||||
Queries: w.Queries,
|
||||
Controls: w.Controls,
|
||||
LocalControls: w.LocalControls,
|
||||
Benchmarks: w.Benchmarks,
|
||||
LocalBenchmarks: w.LocalBenchmarks,
|
||||
Variables: w.Variables,
|
||||
Reports: w.Reports,
|
||||
ReportContainers: w.ReportContainers,
|
||||
ReportCards: w.ReportCards,
|
||||
ReportCharts: w.ReportCharts,
|
||||
ReportHierarchies: w.ReportHierarchies,
|
||||
ReportImages: w.ReportImages,
|
||||
ReportInputs: w.ReportInputs,
|
||||
ReportTables: w.ReportTables,
|
||||
ReportTexts: w.ReportTexts,
|
||||
Mod: w.Mod,
|
||||
Mods: make(map[string]*modconfig.Mod),
|
||||
LocalQueries: w.LocalQueries,
|
||||
Queries: w.Queries,
|
||||
Controls: w.Controls,
|
||||
LocalControls: w.LocalControls,
|
||||
Benchmarks: w.Benchmarks,
|
||||
LocalBenchmarks: w.LocalBenchmarks,
|
||||
Variables: w.Variables,
|
||||
Dashboards: w.Dashboards,
|
||||
DashboardContainers: w.DashboardContainers,
|
||||
DashboardCards: w.DashboardCards,
|
||||
DashboardCharts: w.DashboardCharts,
|
||||
DashboardHierarchies: w.DashboardHierarchies,
|
||||
DashboardImages: w.DashboardImages,
|
||||
DashboardInputs: w.DashboardInputs,
|
||||
DashboardTables: w.DashboardTables,
|
||||
DashboardTexts: w.DashboardTexts,
|
||||
}
|
||||
w.resourceMaps.PopulateReferences()
|
||||
|
||||
@@ -129,135 +129,135 @@ func (w *Workspace) buildBenchmarkMap(modMap modconfig.ModMap) (map[string]*modc
|
||||
return benchmarkMap, localBenchmarkMap
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportMap(modMap modconfig.ModMap) map[string]*modconfig.ReportContainer {
|
||||
var res = make(map[string]*modconfig.ReportContainer)
|
||||
func (w *Workspace) buildDashboardMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardContainer {
|
||||
var res = make(map[string]*modconfig.DashboardContainer)
|
||||
|
||||
for _, r := range w.Mod.Reports {
|
||||
for _, r := range w.Mod.Dashboards {
|
||||
res[r.Name()] = r
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, r := range mod.Reports {
|
||||
for _, r := range mod.Dashboards {
|
||||
res[r.Name()] = r
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportContainerMap(modMap modconfig.ModMap) map[string]*modconfig.ReportContainer {
|
||||
var res = make(map[string]*modconfig.ReportContainer)
|
||||
func (w *Workspace) buildDashboardContainerMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardContainer {
|
||||
var res = make(map[string]*modconfig.DashboardContainer)
|
||||
|
||||
for _, c := range w.Mod.ReportContainers {
|
||||
for _, c := range w.Mod.DashboardContainers {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, c := range mod.ReportContainers {
|
||||
for _, c := range mod.DashboardContainers {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportCardMap(modMap modconfig.ModMap) map[string]*modconfig.ReportCard {
|
||||
var res = make(map[string]*modconfig.ReportCard)
|
||||
func (w *Workspace) buildDashboardCardMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardCard {
|
||||
var res = make(map[string]*modconfig.DashboardCard)
|
||||
|
||||
for _, p := range w.Mod.ReportCards {
|
||||
for _, p := range w.Mod.DashboardCards {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, p := range mod.ReportCards {
|
||||
for _, p := range mod.DashboardCards {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportChartMap(modMap modconfig.ModMap) map[string]*modconfig.ReportChart {
|
||||
var res = make(map[string]*modconfig.ReportChart)
|
||||
func (w *Workspace) buildDashboardChartMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardChart {
|
||||
var res = make(map[string]*modconfig.DashboardChart)
|
||||
|
||||
for _, c := range w.Mod.ReportCharts {
|
||||
for _, c := range w.Mod.DashboardCharts {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, c := range mod.ReportCharts {
|
||||
for _, c := range mod.DashboardCharts {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportHierarchyMap(modMap modconfig.ModMap) map[string]*modconfig.ReportHierarchy {
|
||||
var res = make(map[string]*modconfig.ReportHierarchy)
|
||||
func (w *Workspace) buildDashboardHierarchyMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardHierarchy {
|
||||
var res = make(map[string]*modconfig.DashboardHierarchy)
|
||||
|
||||
for _, p := range w.Mod.ReportHierarchies {
|
||||
for _, p := range w.Mod.DashboardHierarchies {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, p := range mod.ReportHierarchies {
|
||||
for _, p := range mod.DashboardHierarchies {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportImageMap(modMap modconfig.ModMap) map[string]*modconfig.ReportImage {
|
||||
var res = make(map[string]*modconfig.ReportImage)
|
||||
func (w *Workspace) buildDashboardImageMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardImage {
|
||||
var res = make(map[string]*modconfig.DashboardImage)
|
||||
|
||||
for _, p := range w.Mod.ReportImages {
|
||||
for _, p := range w.Mod.DashboardImages {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, p := range mod.ReportImages {
|
||||
for _, p := range mod.DashboardImages {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportInputMap(modMap modconfig.ModMap) map[string]*modconfig.ReportInput {
|
||||
var res = make(map[string]*modconfig.ReportInput)
|
||||
func (w *Workspace) buildDashboardInputMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardInput {
|
||||
var res = make(map[string]*modconfig.DashboardInput)
|
||||
|
||||
for _, p := range w.Mod.ReportInputs {
|
||||
for _, p := range w.Mod.DashboardInputs {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, p := range mod.ReportInputs {
|
||||
for _, p := range mod.DashboardInputs {
|
||||
res[p.Name()] = p
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportTableMap(modMap modconfig.ModMap) map[string]*modconfig.ReportTable {
|
||||
var res = make(map[string]*modconfig.ReportTable)
|
||||
func (w *Workspace) buildDashboardTableMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardTable {
|
||||
var res = make(map[string]*modconfig.DashboardTable)
|
||||
|
||||
for _, c := range w.Mod.ReportTables {
|
||||
for _, c := range w.Mod.DashboardTables {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, c := range mod.ReportTables {
|
||||
for _, c := range mod.DashboardTables {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (w *Workspace) buildReportTextMap(modMap modconfig.ModMap) map[string]*modconfig.ReportText {
|
||||
var res = make(map[string]*modconfig.ReportText)
|
||||
func (w *Workspace) buildDashboardTextMap(modMap modconfig.ModMap) map[string]*modconfig.DashboardText {
|
||||
var res = make(map[string]*modconfig.DashboardText)
|
||||
|
||||
for _, c := range w.Mod.ReportTexts {
|
||||
for _, c := range w.Mod.DashboardTexts {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
|
||||
for _, mod := range modMap {
|
||||
for _, c := range mod.ReportTexts {
|
||||
for _, c := range mod.DashboardTexts {
|
||||
res[c.Name()] = c
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user