mirror of
https://github.com/turbot/steampipe.git
synced 2026-05-07 15:01:56 -04:00
Update naming of anonymous resources to ensure consistent names. Closes #1489
This commit is contained in:
@@ -3,8 +3,8 @@ package dashboardevents
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type ExecutionStarted struct {
|
||||
DashboardNode dashboardinterfaces.DashboardNodeRun `json:"dashboard"`
|
||||
Session string
|
||||
Dashboard dashboardinterfaces.DashboardNodeRun `json:"dashboard"`
|
||||
Session string
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
|
||||
@@ -3,8 +3,8 @@ package dashboardevents
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeComplete struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
LeafNode dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
|
||||
@@ -3,8 +3,9 @@ package dashboardevents
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeError struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
LeafNode dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
Error error
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
|
||||
@@ -3,8 +3,8 @@ package dashboardevents
|
||||
import "github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
|
||||
type LeafNodeProgress struct {
|
||||
Node dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
LeafNode dashboardinterfaces.DashboardNodeRun
|
||||
Session string
|
||||
}
|
||||
|
||||
// IsDashboardEvent implements DashboardEvent interface
|
||||
|
||||
@@ -22,21 +22,22 @@ type CheckRun struct {
|
||||
ControlExecutionTree *controlexecute.ExecutionTree `json:"execution_tree"`
|
||||
DashboardName string `json:"dashboard"`
|
||||
DashboardNode modconfig.DashboardLeafNode `json:"-"`
|
||||
Path []string `json:"-"`
|
||||
parent dashboardinterfaces.DashboardNodeParent
|
||||
runStatus dashboardinterfaces.DashboardRunStatus
|
||||
executionTree *DashboardExecutionTree
|
||||
}
|
||||
|
||||
func NewCheckRun(resource modconfig.DashboardLeafNode, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*CheckRun, error) {
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(resource.Name())
|
||||
|
||||
// NOTE: for now we MUST declare container/dashboard children inline - therefore we cannot share children between runs in the tree
|
||||
// (if we supported the children property then we could reuse resources)
|
||||
// so FOR NOW it is safe to use the node name directly as the run name
|
||||
name := resource.Name()
|
||||
|
||||
r := &CheckRun{
|
||||
Name: name,
|
||||
Title: resource.GetTitle(),
|
||||
Width: resource.GetWidth(),
|
||||
Path: resource.GetPaths()[0],
|
||||
DashboardNode: resource,
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
@@ -88,11 +89,6 @@ func (r *CheckRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *CheckRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *CheckRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.runStatus
|
||||
@@ -104,8 +100,9 @@ func (r *CheckRun) SetError(err error) {
|
||||
r.runStatus = dashboardinterfaces.DashboardRunError
|
||||
// raise dashboard error event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeError{
|
||||
Node: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
LeafNode: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
Error: err,
|
||||
})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
@@ -117,8 +114,8 @@ func (r *CheckRun) SetComplete() {
|
||||
r.runStatus = dashboardinterfaces.DashboardRunComplete
|
||||
// raise counter complete event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeComplete{
|
||||
Node: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
LeafNode: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
|
||||
@@ -24,7 +24,6 @@ type DashboardContainerRun struct {
|
||||
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
|
||||
@@ -34,13 +33,14 @@ type DashboardContainerRun struct {
|
||||
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())
|
||||
// NOTE: for now we MUST declare children inline - therefore we cannot share children between runs in the tree
|
||||
// (if we supported the children property then we could reuse resources)
|
||||
// so FOR NOW it is safe to use the container name directly as the run name
|
||||
name := container.Name()
|
||||
|
||||
r := &DashboardContainerRun{
|
||||
Name: name,
|
||||
NodeType: modconfig.BlockTypeContainer,
|
||||
Path: container.Paths[0],
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
@@ -153,11 +153,6 @@ 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
|
||||
|
||||
@@ -23,7 +23,7 @@ func (c *ControlEventHooks) OnStart(ctx context.Context, _ *controlhooks.Control
|
||||
}
|
||||
|
||||
func (c *ControlEventHooks) OnControlEvent(ctx context.Context, _ *controlhooks.ControlProgress) {
|
||||
event := &dashboardevents.LeafNodeProgress{Node: c.CheckRun}
|
||||
event := &dashboardevents.LeafNodeProgress{LeafNode: c.CheckRun}
|
||||
c.CheckRun.executionTree.workspace.PublishDashboardEvent(event)
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ import (
|
||||
|
||||
// DashboardExecutionTree is a structure representing the control result hierarchy
|
||||
type DashboardExecutionTree struct {
|
||||
modconfig.UniqueNameProviderBase
|
||||
|
||||
Root *DashboardRun
|
||||
|
||||
dashboardName string
|
||||
@@ -80,8 +78,8 @@ func (e *DashboardExecutionTree) Execute(ctx context.Context) error {
|
||||
e.cancel = cancel
|
||||
workspace := e.workspace
|
||||
workspace.PublishDashboardEvent(&dashboardevents.ExecutionStarted{
|
||||
DashboardNode: e.Root,
|
||||
Session: e.sessionId,
|
||||
Dashboard: e.Root,
|
||||
Session: e.sessionId,
|
||||
})
|
||||
defer workspace.PublishDashboardEvent(&dashboardevents.ExecutionComplete{
|
||||
Dashboard: e.Root,
|
||||
|
||||
@@ -27,7 +27,6 @@ type DashboardRun struct {
|
||||
NodeType string `json:"node_type"`
|
||||
Status dashboardinterfaces.DashboardRunStatus `json:"status"`
|
||||
DashboardName string `json:"dashboard"`
|
||||
Path []string `json:"-"`
|
||||
dashboardNode *modconfig.Dashboard
|
||||
parent dashboardinterfaces.DashboardNodeParent
|
||||
executionTree *DashboardExecutionTree
|
||||
@@ -37,13 +36,14 @@ type DashboardRun struct {
|
||||
func NewDashboardRun(dashboard *modconfig.Dashboard, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*DashboardRun, error) {
|
||||
children := dashboard.GetChildren()
|
||||
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(dashboard.Name())
|
||||
// NOTE: for now we MUST declare container/dashboard children inline - therefore we cannot share children between runs in the tree
|
||||
// (if we supported the children property then we could reuse resources)
|
||||
// so FOR NOW it is safe to use the dashboard name directly as the run name
|
||||
name := dashboard.Name()
|
||||
|
||||
r := &DashboardRun{
|
||||
Name: name,
|
||||
NodeType: modconfig.BlockTypeDashboard,
|
||||
Path: dashboard.Paths[0],
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
parent: parent,
|
||||
@@ -162,11 +162,6 @@ func (r *DashboardRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *DashboardRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *DashboardRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.Status
|
||||
|
||||
@@ -3,6 +3,7 @@ package dashboardexecute
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/turbot/steampipe/dashboard/dashboardevents"
|
||||
"github.com/turbot/steampipe/dashboard/dashboardinterfaces"
|
||||
@@ -21,7 +22,6 @@ type LeafRun struct {
|
||||
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
|
||||
@@ -29,14 +29,16 @@ type LeafRun struct {
|
||||
}
|
||||
|
||||
func NewLeafRun(resource modconfig.DashboardLeafNode, parent dashboardinterfaces.DashboardNodeParent, executionTree *DashboardExecutionTree) (*LeafRun, error) {
|
||||
// ensure the tree node name is unique
|
||||
name := executionTree.GetUniqueName(resource.Name())
|
||||
|
||||
// NOTE: for now we MUST declare container/dashboard children inline - therefore we cannot share children between runs in the tree
|
||||
// (if we supported the children property then we could reuse resources)
|
||||
// so FOR NOW it is safe to use the node name directly as the run name
|
||||
name := resource.Name()
|
||||
|
||||
r := &LeafRun{
|
||||
Name: name,
|
||||
Title: resource.GetTitle(),
|
||||
Width: resource.GetWidth(),
|
||||
Path: resource.GetPaths()[0],
|
||||
DashboardNode: resource,
|
||||
DashboardName: executionTree.dashboardName,
|
||||
executionTree: executionTree,
|
||||
@@ -65,7 +67,6 @@ func NewLeafRun(resource modconfig.DashboardLeafNode, parent dashboardinterfaces
|
||||
for name, dep := range runtimeDependencies {
|
||||
r.runtimeDependencies[name] = NewResolvedRuntimeDependency(dep, executionTree)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add r into execution tree
|
||||
@@ -80,12 +81,14 @@ func (r *LeafRun) Execute(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] LeafRun '%s' Execute()", r.DashboardNode.Name())
|
||||
|
||||
// if there are any unresolved runtime dependencies, wait for them
|
||||
if err := r.waitForRuntimeDependencies(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// ok now we have runtime depdencies, we can resolve the query
|
||||
// ok now we have runtime dependencies, we can resolve the query
|
||||
queryProvider := r.DashboardNode.(modconfig.QueryProvider)
|
||||
sql, err := r.executionTree.workspace.ResolveQueryFromQueryProvider(queryProvider, nil)
|
||||
if err != nil {
|
||||
@@ -93,13 +96,18 @@ func (r *LeafRun) Execute(ctx context.Context) error {
|
||||
}
|
||||
r.SQL = sql
|
||||
|
||||
log.Printf("[TRACE] LeafRun '%s' SQL resolved, executing", r.DashboardNode.Name())
|
||||
|
||||
queryResult, err := r.executionTree.client.ExecuteSync(ctx, r.SQL)
|
||||
if err != nil {
|
||||
log.Printf("[TRACE] LeafRun '%s' query failed: %s", r.DashboardNode.Name(), err.Error())
|
||||
// set the error status on the counter - this will raise counter error event
|
||||
r.SetError(err)
|
||||
return err
|
||||
|
||||
}
|
||||
log.Printf("[TRACE] LeafRun '%s' complete", r.DashboardNode.Name())
|
||||
|
||||
r.Data = NewLeafData(queryResult)
|
||||
// set complete status on counter - this will raise counter complete event
|
||||
r.SetComplete()
|
||||
@@ -111,11 +119,6 @@ func (r *LeafRun) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// GetPath implements DashboardNodeRun
|
||||
func (r *LeafRun) GetPath() modconfig.NodePath {
|
||||
return r.Path
|
||||
}
|
||||
|
||||
// GetRunStatus implements DashboardNodeRun
|
||||
func (r *LeafRun) GetRunStatus() dashboardinterfaces.DashboardRunStatus {
|
||||
return r.runStatus
|
||||
@@ -127,8 +130,8 @@ func (r *LeafRun) SetError(err error) {
|
||||
r.runStatus = dashboardinterfaces.DashboardRunError
|
||||
// raise counter error event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeError{
|
||||
Node: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
LeafNode: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
@@ -140,8 +143,8 @@ func (r *LeafRun) SetComplete() {
|
||||
r.runStatus = dashboardinterfaces.DashboardRunComplete
|
||||
// raise counter complete event
|
||||
r.executionTree.workspace.PublishDashboardEvent(&dashboardevents.LeafNodeComplete{
|
||||
Node: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
LeafNode: r,
|
||||
Session: r.executionTree.sessionId,
|
||||
})
|
||||
// tell parent we are done
|
||||
r.parent.ChildCompleteChan() <- r
|
||||
@@ -158,19 +161,27 @@ func (r *LeafRun) ChildrenComplete() bool {
|
||||
}
|
||||
|
||||
func (r *LeafRun) waitForRuntimeDependencies(ctx context.Context) error {
|
||||
log.Printf("[TRACE] LeafRun '%s' waitForRuntimeDependencies", r.DashboardNode.Name())
|
||||
for _, resolvedDependency := range r.runtimeDependencies {
|
||||
// check with the top level dashboard whether the dependency is available
|
||||
if !resolvedDependency.Resolve() {
|
||||
log.Printf("[TRACE] waitForRuntimeDependency %s", resolvedDependency.dependency.String())
|
||||
if err := r.executionTree.waitForRuntimeDependency(ctx, resolvedDependency.dependency); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[TRACE] dependency %s should be available", resolvedDependency.dependency.String())
|
||||
// now again resolve the dependency value - this sets the arg to have the runtime dependency value
|
||||
if !resolvedDependency.Resolve() {
|
||||
log.Printf("[TRACE] dependency %s not resolved after waitForRuntimeDependency returned", resolvedDependency.dependency.String())
|
||||
// should now be resolved`
|
||||
return fmt.Errorf("dependency not resolved after waitForRuntimeDependency returned")
|
||||
return fmt.Errorf("dependency %s not resolved after waitForRuntimeDependency returned", resolvedDependency.dependency.String())
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.runtimeDependencies) > 0 {
|
||||
log.Printf("[TRACE] LeafRun '%s' all runtime dependencies ready", r.DashboardNode.Name())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package dashboardinterfaces
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/turbot/steampipe/steampipeconfig/modconfig"
|
||||
)
|
||||
|
||||
type DashboardRunStatus string
|
||||
@@ -19,7 +17,6 @@ const (
|
||||
type DashboardNodeRun interface {
|
||||
Execute(ctx context.Context) error
|
||||
GetName() string
|
||||
GetPath() modconfig.NodePath
|
||||
GetRunStatus() DashboardRunStatus
|
||||
SetError(err error)
|
||||
SetComplete()
|
||||
|
||||
@@ -157,7 +157,7 @@ func buildWorkspaceErrorPayload(e *dashboardevents.WorkspaceError) ([]byte, erro
|
||||
func buildLeafNodeProgressPayload(event *dashboardevents.LeafNodeProgress) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "leaf_node_progress",
|
||||
DashboardNode: event.Node,
|
||||
DashboardNode: event.LeafNode,
|
||||
}
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func buildLeafNodeProgressPayload(event *dashboardevents.LeafNodeProgress) ([]by
|
||||
func buildLeafNodeCompletePayload(event *dashboardevents.LeafNodeComplete) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "leaf_node_complete",
|
||||
DashboardNode: event.Node,
|
||||
DashboardNode: event.LeafNode,
|
||||
}
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
@@ -173,11 +173,8 @@ func buildLeafNodeCompletePayload(event *dashboardevents.LeafNodeComplete) ([]by
|
||||
func buildExecutionStartedPayload(event *dashboardevents.ExecutionStarted) ([]byte, error) {
|
||||
payload := ExecutionPayload{
|
||||
Action: "execution_started",
|
||||
DashboardNode: event.DashboardNode,
|
||||
DashboardNode: event.Dashboard,
|
||||
}
|
||||
a, _ := json.MarshalIndent(payload, "", " ")
|
||||
b := string(a)
|
||||
fmt.Println(b)
|
||||
return json.Marshal(payload)
|
||||
}
|
||||
|
||||
@@ -252,7 +249,7 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
switch e := event.(type) {
|
||||
|
||||
case *dashboardevents.WorkspaceError:
|
||||
log.Println("[TRACE] Got workspace error event", *e)
|
||||
log.Printf("[TRACE] WorkspaceError event: %s", e.Error)
|
||||
payload, payloadError = buildWorkspaceErrorPayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
@@ -261,7 +258,7 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
outputError(s.context, e.Error)
|
||||
|
||||
case *dashboardevents.ExecutionStarted:
|
||||
log.Println("[TRACE] Got execution started event", *e)
|
||||
log.Printf("[TRACE] ExecutionStarted event session %s, dashboard %s", e.Session, e.Dashboard.GetName())
|
||||
payload, payloadError = buildExecutionStartedPayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
@@ -269,13 +266,13 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
s.mutex.Lock()
|
||||
s.writePayloadToSession(e.Session, payload)
|
||||
s.mutex.Unlock()
|
||||
outputWait(s.context, fmt.Sprintf("Dashboard execution started: %s", e.DashboardNode.GetName()))
|
||||
outputWait(s.context, fmt.Sprintf("Dashboard execution started: %s", e.Dashboard.GetName()))
|
||||
|
||||
case *dashboardevents.LeafNodeError:
|
||||
log.Println("[TRACE] Got leaf node error event", *e)
|
||||
log.Printf("[TRACE] LeafNodeError event session %s, node %s, error %s", e.Session, e.LeafNode.GetName(), e.Error)
|
||||
|
||||
case *dashboardevents.LeafNodeProgress:
|
||||
log.Println("[TRACE] Got leaf node complete event", *e)
|
||||
log.Printf("[TRACE] LeafNodeProgress event session %s, node %s", e.Session, e.LeafNode.GetName())
|
||||
payload, payloadError = buildLeafNodeProgressPayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
@@ -285,7 +282,7 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
s.mutex.Unlock()
|
||||
|
||||
case *dashboardevents.LeafNodeComplete:
|
||||
log.Println("[TRACE] Got leaf node complete event", *e)
|
||||
log.Printf("[TRACE] LeafNodeComplete event session %s, node %s", e.Session, e.LeafNode.GetName())
|
||||
payload, payloadError = buildLeafNodeCompletePayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
@@ -295,7 +292,7 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
s.mutex.Unlock()
|
||||
|
||||
case *dashboardevents.DashboardChanged:
|
||||
log.Println("[TRACE] Got dashboard changed event", *e)
|
||||
log.Println("[TRACE] DashboardChanged event", *e)
|
||||
deletedDashboards := e.DeletedDashboards
|
||||
newDashboards := e.NewDashboards
|
||||
|
||||
@@ -408,13 +405,13 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
}
|
||||
|
||||
case *dashboardevents.DashboardError:
|
||||
log.Println("[TRACE] Got dashboard error event", *e)
|
||||
log.Println("[TRACE] dashboard error event", *e)
|
||||
|
||||
case *dashboardevents.DashboardComplete:
|
||||
log.Println("[TRACE] Got dashboard complete event", *e)
|
||||
log.Println("[TRACE] dashboard complete event", *e)
|
||||
|
||||
case *dashboardevents.ExecutionComplete:
|
||||
log.Println("[TRACE] Got execution complete event", *e)
|
||||
log.Println("[TRACE] execution complete event", *e)
|
||||
payload, payloadError = buildExecutionCompletePayload(e)
|
||||
if payloadError != nil {
|
||||
return
|
||||
@@ -430,12 +427,12 @@ func (s *Server) HandleWorkspaceUpdate(event dashboardevents.DashboardEvent) {
|
||||
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")
|
||||
log.Println("[TRACE] client connected")
|
||||
s.addSession(session)
|
||||
})
|
||||
|
||||
s.webSocket.HandleDisconnect(func(session *melody.Session) {
|
||||
log.Println("[TRACE] Client disconnected")
|
||||
log.Println("[TRACE] client disconnected")
|
||||
s.clearSession(ctx, session)
|
||||
})
|
||||
|
||||
@@ -445,7 +442,6 @@ func (s *Server) Init(ctx context.Context) {
|
||||
|
||||
func (s *Server) handleMessageFunc(ctx context.Context) func(session *melody.Session, msg []byte) {
|
||||
return func(session *melody.Session, msg []byte) {
|
||||
log.Println("[TRACE] Got message", string(msg))
|
||||
|
||||
// TODO TEMP GET SESSION ID
|
||||
sessionId := s.getSessionId(session)
|
||||
@@ -453,6 +449,11 @@ func (s *Server) handleMessageFunc(ctx context.Context) func(session *melody.Ses
|
||||
var request ClientRequest
|
||||
// if we could not decode message - ignore
|
||||
if err := json.Unmarshal(msg, &request); err == nil {
|
||||
|
||||
if request.Action != "keep_alive" {
|
||||
log.Println("[TRACE] message", string(msg))
|
||||
}
|
||||
|
||||
switch request.Action {
|
||||
case "get_dashboard_metadata":
|
||||
payload, err := buildDashboardMetadataPayload(s.workspace.GetResourceMaps())
|
||||
|
||||
@@ -76,6 +76,8 @@ func LoadMod(modPath string, parentRunCtx *parse.RunContext) (mod *modconfig.Mod
|
||||
}
|
||||
// now we have loaded dependencies, set the current mod on the run context
|
||||
runCtx.CurrentMod = mod
|
||||
runCtx.PushParent(mod)
|
||||
defer runCtx.PopParent()
|
||||
|
||||
// if flag is set, create pseudo resources by mapping files
|
||||
var pseudoResources []modconfig.MappableResource
|
||||
|
||||
@@ -2,18 +2,39 @@ package modconfig
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/hcl/v2"
|
||||
)
|
||||
|
||||
func GetAnonymousResourceShortName(block *hcl.Block, mod *Mod) string {
|
||||
func GetAnonymousResourceShortName(block *hcl.Block, parent ModTreeItem) string {
|
||||
var shortName string
|
||||
|
||||
anonymous := len(block.Labels) == 0
|
||||
if anonymous {
|
||||
shortName = mod.GetUniqueName(fmt.Sprintf("anonymous_%s", block.Type))
|
||||
shortName = GetUniqueName(block.Type, parent)
|
||||
} else {
|
||||
shortName = block.Labels[0]
|
||||
}
|
||||
return shortName
|
||||
}
|
||||
|
||||
// GetUniqueName returns a name unique within the scope of this execution tree
|
||||
func GetUniqueName(blockType string, parent ModTreeItem) string {
|
||||
|
||||
// count how many children of this block type the parent has
|
||||
childCount := 0
|
||||
|
||||
for _, child := range parent.GetChildren() {
|
||||
parsedName, err := ParseResourceName(child.Name())
|
||||
if err != nil {
|
||||
// we do not expect this
|
||||
continue
|
||||
}
|
||||
if parsedName.ItemType == blockType {
|
||||
childCount++
|
||||
}
|
||||
}
|
||||
sanitisedParentName := strings.Replace(parent.GetUnqualifiedName(), ".", "_", -1)
|
||||
return fmt.Sprintf("%s_anonymous_%s_%d", sanitisedParentName, blockType, childCount)
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ type Benchmark struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewBenchmark(block *hcl.Block, mod *Mod) *Benchmark {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewBenchmark(block *hcl.Block, mod *Mod, parent ModTreeItem) *Benchmark {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
benchmark := &Benchmark{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.benchmark.%s", mod.ShortName, shortName),
|
||||
|
||||
@@ -50,8 +50,8 @@ type Control struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewControl(block *hcl.Block, mod *Mod) *Control {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewControl(block *hcl.Block, mod *Mod, parent ModTreeItem) *Control {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
control := &Control{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.control.%s", mod.ShortName, shortName),
|
||||
|
||||
@@ -49,9 +49,9 @@ type Dashboard struct {
|
||||
HclType string
|
||||
}
|
||||
|
||||
func NewDashboard(block *hcl.Block, mod *Mod) *Dashboard {
|
||||
func NewDashboard(block *hcl.Block, mod *Mod, parent ModTreeItem) *Dashboard {
|
||||
// TODO [reports] think about nested report???
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
c := &Dashboard{
|
||||
HclType: block.Type,
|
||||
ShortName: shortName,
|
||||
@@ -83,6 +83,11 @@ func (d *Dashboard) Name() string {
|
||||
// OnDecoded implements HclResource
|
||||
func (d *Dashboard) OnDecoded(block *hcl.Block) hcl.Diagnostics {
|
||||
d.setBaseProperties()
|
||||
|
||||
d.ChildNames = make([]string, len(d.children))
|
||||
for i, child := range d.children {
|
||||
d.ChildNames[i] = child.Name()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -200,10 +205,10 @@ func (d *Dashboard) Diff(other *Dashboard) *DashboardTreeItemDiffs {
|
||||
|
||||
func (d *Dashboard) SetChildren(children []ModTreeItem) {
|
||||
d.children = children
|
||||
d.ChildNames = make([]string, len(children))
|
||||
for i, child := range children {
|
||||
d.ChildNames[i] = child.Name()
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dashboard) AddChild(child ModTreeItem) {
|
||||
d.children = append(d.children, child)
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
|
||||
@@ -46,8 +46,8 @@ type DashboardCard struct {
|
||||
metadata *ResourceMetadata
|
||||
}
|
||||
|
||||
func NewDashboardCard(block *hcl.Block, mod *Mod) *DashboardCard {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardCard(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardCard {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
c := &DashboardCard{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -52,8 +52,8 @@ type DashboardChart struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewDashboardChart(block *hcl.Block, mod *Mod) *DashboardChart {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardChart(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardChart {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
c := &DashboardChart{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -37,8 +37,8 @@ type DashboardContainer struct {
|
||||
runtimeDependencyGraph *topsort.Graph
|
||||
}
|
||||
|
||||
func NewDashboardContainer(block *hcl.Block, mod *Mod) *DashboardContainer {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardContainer(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardContainer {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
c := &DashboardContainer{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
@@ -67,7 +67,11 @@ func (c *DashboardContainer) Name() string {
|
||||
}
|
||||
|
||||
// OnDecoded implements HclResource
|
||||
func (c *DashboardContainer) OnDecoded(block *hcl.Block) hcl.Diagnostics {
|
||||
func (c *DashboardContainer) OnDecoded(*hcl.Block) hcl.Diagnostics {
|
||||
c.ChildNames = make([]string, len(c.children))
|
||||
for i, child := range c.children {
|
||||
c.ChildNames[i] = child.Name()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -160,10 +164,10 @@ func (c *DashboardContainer) Diff(other *DashboardContainer) *DashboardTreeItemD
|
||||
|
||||
func (c *DashboardContainer) SetChildren(children []ModTreeItem) {
|
||||
c.children = children
|
||||
c.ChildNames = make([]string, len(children))
|
||||
for i, child := range children {
|
||||
c.ChildNames[i] = child.Name()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DashboardContainer) AddChild(child ModTreeItem) {
|
||||
c.children = append(c.children, child)
|
||||
}
|
||||
|
||||
// GetUnqualifiedName implements DashboardLeafNode, ModTreeItem
|
||||
|
||||
@@ -48,8 +48,8 @@ type DashboardHierarchy struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewDashboardHierarchy(block *hcl.Block, mod *Mod) *DashboardHierarchy {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardHierarchy(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardHierarchy {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
h := &DashboardHierarchy{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -44,8 +44,8 @@ type DashboardImage struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewDashboardImage(block *hcl.Block, mod *Mod) *DashboardImage {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardImage(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardImage {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
i := &DashboardImage{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -72,7 +72,7 @@ func (i *DashboardInput) Clone() *DashboardInput {
|
||||
|
||||
}
|
||||
|
||||
func NewDashboardInput(block *hcl.Block, mod *Mod) *DashboardInput {
|
||||
func NewDashboardInput(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardInput {
|
||||
// input cannot be anonymous
|
||||
shortName := block.Labels[0]
|
||||
i := &DashboardInput{
|
||||
|
||||
@@ -47,8 +47,8 @@ type DashboardTable struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewDashboardTable(block *hcl.Block, mod *Mod) *DashboardTable {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardTable(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardTable {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
t := &DashboardTable{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -34,8 +34,8 @@ type DashboardText struct {
|
||||
parents []ModTreeItem
|
||||
}
|
||||
|
||||
func NewDashboardText(block *hcl.Block, mod *Mod) *DashboardText {
|
||||
shortName := GetAnonymousResourceShortName(block, mod)
|
||||
func NewDashboardText(block *hcl.Block, mod *Mod, parent ModTreeItem) *DashboardText {
|
||||
shortName := GetAnonymousResourceShortName(block, parent)
|
||||
t := &DashboardText{
|
||||
ShortName: shortName,
|
||||
FullName: fmt.Sprintf("%s.%s.%s", mod.ShortName, block.Type, shortName),
|
||||
|
||||
@@ -82,7 +82,3 @@ type DashboardLeafNode interface {
|
||||
type ResourceMapsProvider interface {
|
||||
GetResourceMaps() *WorkspaceResourceMaps
|
||||
}
|
||||
|
||||
type UniqueNameProvider interface {
|
||||
GetUniqueName(string) string
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ const defaultModName = "local"
|
||||
// Mod is a struct representing a Mod resource
|
||||
type Mod struct {
|
||||
ResourceWithMetadataBase
|
||||
UniqueNameProviderBase
|
||||
|
||||
// ShortName is the mod name, e.g. azure_thrifty
|
||||
ShortName string `cty:"short_name" hcl:"name,label"`
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package modconfig
|
||||
|
||||
import "fmt"
|
||||
|
||||
type UniqueNameProviderBase struct {
|
||||
nameMap map[string]struct{}
|
||||
}
|
||||
|
||||
// GetUniqueName returns a name unique within the scope of this execution tree
|
||||
func (p *UniqueNameProviderBase) GetUniqueName(name string) string {
|
||||
if p.nameMap == nil {
|
||||
p.nameMap = make(map[string]struct{})
|
||||
}
|
||||
// keep adding a suffix until we get a unique name
|
||||
uniqueName := name
|
||||
suffix := 0
|
||||
for {
|
||||
if _, ok := p.nameMap[uniqueName]; !ok {
|
||||
p.nameMap[uniqueName] = struct{}{}
|
||||
return uniqueName
|
||||
}
|
||||
suffix++
|
||||
uniqueName = fmt.Sprintf("%s_%d", name, suffix)
|
||||
}
|
||||
return uniqueName
|
||||
}
|
||||
@@ -40,6 +40,7 @@ func decode(runCtx *RunContext) hcl.Diagnostics {
|
||||
Summary: "failed to determine required dependency order",
|
||||
Detail: err.Error()})
|
||||
}
|
||||
|
||||
for _, block := range blocks {
|
||||
resources, res := decodeBlock(block, runCtx)
|
||||
if !res.Success() {
|
||||
@@ -162,33 +163,34 @@ func resourceForBlock(block *hcl.Block, runCtx *RunContext) (modconfig.HclResour
|
||||
var resource modconfig.HclResource
|
||||
// runCtx already contains the current mod
|
||||
mod := runCtx.CurrentMod
|
||||
parent := runCtx.PeekParent()
|
||||
switch block.Type {
|
||||
case modconfig.BlockTypeMod:
|
||||
resource = mod
|
||||
case modconfig.BlockTypeQuery:
|
||||
resource = modconfig.NewQuery(block, mod)
|
||||
case modconfig.BlockTypeControl:
|
||||
resource = modconfig.NewControl(block, mod)
|
||||
resource = modconfig.NewControl(block, mod, parent)
|
||||
case modconfig.BlockTypeBenchmark:
|
||||
resource = modconfig.NewBenchmark(block, mod)
|
||||
resource = modconfig.NewBenchmark(block, mod, parent)
|
||||
case modconfig.BlockTypeDashboard:
|
||||
resource = modconfig.NewDashboard(block, mod)
|
||||
resource = modconfig.NewDashboard(block, mod, parent)
|
||||
case modconfig.BlockTypeContainer:
|
||||
resource = modconfig.NewDashboardContainer(block, mod)
|
||||
resource = modconfig.NewDashboardContainer(block, mod, parent)
|
||||
case modconfig.BlockTypeChart:
|
||||
resource = modconfig.NewDashboardChart(block, mod)
|
||||
resource = modconfig.NewDashboardChart(block, mod, parent)
|
||||
case modconfig.BlockTypeCard:
|
||||
resource = modconfig.NewDashboardCard(block, mod)
|
||||
resource = modconfig.NewDashboardCard(block, mod, parent)
|
||||
case modconfig.BlockTypeHierarchy:
|
||||
resource = modconfig.NewDashboardHierarchy(block, mod)
|
||||
resource = modconfig.NewDashboardHierarchy(block, mod, parent)
|
||||
case modconfig.BlockTypeImage:
|
||||
resource = modconfig.NewDashboardImage(block, mod)
|
||||
resource = modconfig.NewDashboardImage(block, mod, parent)
|
||||
case modconfig.BlockTypeInput:
|
||||
resource = modconfig.NewDashboardInput(block, mod)
|
||||
resource = modconfig.NewDashboardInput(block, mod, parent)
|
||||
case modconfig.BlockTypeTable:
|
||||
resource = modconfig.NewDashboardTable(block, mod)
|
||||
resource = modconfig.NewDashboardTable(block, mod, parent)
|
||||
case modconfig.BlockTypeText:
|
||||
resource = modconfig.NewDashboardText(block, mod)
|
||||
resource = modconfig.NewDashboardText(block, mod, parent)
|
||||
default:
|
||||
return nil, hcl.Diagnostics{&hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
@@ -373,7 +375,7 @@ func invalidParamDiags(resource modconfig.HclResource, block *hcl.Block) *hcl.Di
|
||||
|
||||
func decodeDashboard(block *hcl.Block, runCtx *RunContext) (*modconfig.Dashboard, *decodeResult) {
|
||||
res := &decodeResult{}
|
||||
dashboard := modconfig.NewDashboard(block, runCtx.CurrentMod)
|
||||
dashboard := modconfig.NewDashboard(block, runCtx.CurrentMod, runCtx.PeekParent())
|
||||
|
||||
// do a partial decode using QueryProviderBlockSchema
|
||||
// this will be used to pull out attributes which need manual decoding
|
||||
@@ -410,11 +412,16 @@ func decodeDashboard(block *hcl.Block, runCtx *RunContext) (*modconfig.Dashboard
|
||||
|
||||
func decodeDashboardBlocks(content *hcl.BodyContent, dashboard *modconfig.Dashboard, runCtx *RunContext) *decodeResult {
|
||||
var res = &decodeResult{}
|
||||
// if children are declared inline as blocks, add them
|
||||
var children []modconfig.ModTreeItem
|
||||
var inputs []*modconfig.DashboardInput
|
||||
|
||||
// set dashboard as parent on the run context - this is used when generating names for anonymous blocks
|
||||
runCtx.PushParent(dashboard)
|
||||
defer func() {
|
||||
runCtx.PopParent()
|
||||
}()
|
||||
|
||||
for _, b := range content.Blocks {
|
||||
// use generic block decoding
|
||||
// decode block
|
||||
resources, blockRes := decodeBlock(b, runCtx)
|
||||
res.Merge(blockRes)
|
||||
if !blockRes.Success() {
|
||||
@@ -434,16 +441,14 @@ func decodeDashboardBlocks(content *hcl.BodyContent, dashboard *modconfig.Dashbo
|
||||
|
||||
// add the resource to the mod
|
||||
addResourcesToMod(runCtx, resource)
|
||||
// add to children
|
||||
// (we expect this cast to always succeed
|
||||
// add to the dashboard children
|
||||
// (we expect this cast to always succeed)
|
||||
if child, ok := resource.(modconfig.ModTreeItem); ok {
|
||||
children = append(children, child)
|
||||
dashboard.AddChild(child)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dashboard.SetChildren(children)
|
||||
err := dashboard.SetInputs(inputs)
|
||||
if err != nil {
|
||||
res.addDiags(hcl.Diagnostics{&hcl.Diagnostic{
|
||||
@@ -459,7 +464,7 @@ func decodeDashboardBlocks(content *hcl.BodyContent, dashboard *modconfig.Dashbo
|
||||
|
||||
func decodeDashboardContainer(block *hcl.Block, runCtx *RunContext) (*modconfig.DashboardContainer, *decodeResult) {
|
||||
res := &decodeResult{}
|
||||
container := modconfig.NewDashboardContainer(block, runCtx.CurrentMod)
|
||||
container := modconfig.NewDashboardContainer(block, runCtx.CurrentMod, runCtx.PeekParent())
|
||||
|
||||
// do a partial decode using QueryProviderBlockSchema
|
||||
// this will be used to pull out attributes which need manual decoding
|
||||
@@ -485,8 +490,12 @@ func decodeDashboardContainer(block *hcl.Block, runCtx *RunContext) (*modconfig.
|
||||
|
||||
func decodeDashboardContainerBlocks(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
|
||||
// set container as parent on the run context - this is used when generating names for anonymous blocks
|
||||
runCtx.PushParent(dashboardContainer)
|
||||
defer func() {
|
||||
runCtx.PopParent()
|
||||
}()
|
||||
|
||||
for _, b := range content.Blocks {
|
||||
// use generic block decoding
|
||||
resources, blockRes := decodeBlock(b, runCtx)
|
||||
@@ -501,21 +510,18 @@ func decodeDashboardContainerBlocks(content *hcl.BodyContent, dashboardContainer
|
||||
addResourcesToMod(runCtx, resource)
|
||||
|
||||
if child, ok := resource.(modconfig.ModTreeItem); ok {
|
||||
children = append(children, child)
|
||||
dashboardContainer.AddChild(child)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dashboardContainer.SetChildren(children)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func decodeBenchmark(block *hcl.Block, runCtx *RunContext) (*modconfig.Benchmark, *decodeResult) {
|
||||
res := &decodeResult{}
|
||||
|
||||
benchmark := modconfig.NewBenchmark(block, runCtx.CurrentMod)
|
||||
benchmark := modconfig.NewBenchmark(block, runCtx.CurrentMod, runCtx.PeekParent())
|
||||
content, diags := block.Body.Content(BenchmarkBlockSchema)
|
||||
res.handleDecodeDiags(content, benchmark, diags)
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ type RunContext struct {
|
||||
BlockTypeExclusions []string
|
||||
Variables map[string]*modconfig.Variable
|
||||
|
||||
// stack of parent resources for the currently parsed block
|
||||
parents []modconfig.ModTreeItem
|
||||
dependencyGraph *topsort.Graph
|
||||
// map of ReferenceTypeValueMaps keyed by mod
|
||||
// NOTE: all values from root mod are keyed with "local"
|
||||
@@ -89,6 +91,21 @@ func (r *RunContext) EnsureWorkspaceLock(mod *modconfig.Mod) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *RunContext) PushParent(parent modconfig.ModTreeItem) {
|
||||
r.parents = append(r.parents, parent)
|
||||
}
|
||||
|
||||
func (r *RunContext) PopParent() modconfig.ModTreeItem {
|
||||
n := len(r.parents) - 1
|
||||
res := r.parents[n]
|
||||
r.parents = r.parents[:n]
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *RunContext) PeekParent() modconfig.ModTreeItem {
|
||||
return r.parents[len(r.parents)-1]
|
||||
}
|
||||
|
||||
// VariableValueMap converts a map of variables to a map of the underlying cty value
|
||||
func VariableValueMap(variables map[string]*modconfig.Variable) map[string]cty.Value {
|
||||
ret := make(map[string]cty.Value, len(variables))
|
||||
|
||||
@@ -1,110 +1,21 @@
|
||||
query "aws_region_input" {
|
||||
sql = <<EOQ
|
||||
select
|
||||
title as label,
|
||||
region as value
|
||||
from
|
||||
aws_region
|
||||
where
|
||||
account_id = '876515858155'
|
||||
order by
|
||||
title;
|
||||
EOQ
|
||||
}
|
||||
query "aws_s3_buckets_by_versioning_enabled" {
|
||||
sql = <<-EOQ
|
||||
with versioning as (
|
||||
select
|
||||
case when versioning_enabled then 'Enabled' else 'Disabled' end as versioning_status,
|
||||
region
|
||||
from
|
||||
aws_s3_bucket
|
||||
)
|
||||
select
|
||||
versioning_status,
|
||||
count(versioning_status) as "Total"
|
||||
from
|
||||
versioning
|
||||
where
|
||||
region = $1
|
||||
group by
|
||||
versioning_status
|
||||
EOQ
|
||||
param "region" {
|
||||
default = "us-east-1"
|
||||
}
|
||||
}
|
||||
|
||||
dashboard "inputs" {
|
||||
title = "Inputs Test"
|
||||
chart "top_level1"{}
|
||||
chart "top_level2"{}
|
||||
|
||||
input "region" {
|
||||
sql = query.aws_region_input.sql
|
||||
width = 3
|
||||
dashboard "anonymous_naming" {
|
||||
|
||||
chart{}
|
||||
|
||||
container {
|
||||
chart {}
|
||||
chart {}
|
||||
table{}
|
||||
}
|
||||
|
||||
container {
|
||||
chart {
|
||||
type = "donut"
|
||||
width = 3
|
||||
query = query.aws_s3_buckets_by_versioning_enabled
|
||||
args = {
|
||||
"region" = self.input.region.value
|
||||
}
|
||||
title = "AWS IAM Users MFA Status"
|
||||
|
||||
series "Total" {
|
||||
point "Disabled" {
|
||||
color = "red"
|
||||
}
|
||||
|
||||
point "Enabled" {
|
||||
color = "green"
|
||||
}
|
||||
}
|
||||
}
|
||||
chart {}
|
||||
chart {}
|
||||
table{}
|
||||
table{}
|
||||
}
|
||||
}
|
||||
//
|
||||
//query "q1"{
|
||||
// sql = "select {1}"
|
||||
// param "p1"{
|
||||
// default = "1"
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//dashboard "r1"{
|
||||
// input "i1"{
|
||||
// query = query.q1
|
||||
// args = {
|
||||
// "p1" = "FOO"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// chart {
|
||||
// query = query.q1
|
||||
// args = {
|
||||
// "p1" = self.input.i1.value
|
||||
// "p2" = "foo"
|
||||
// "p3" = self.input.i1.value
|
||||
// }
|
||||
// }
|
||||
|
||||
// control {
|
||||
// query = query.q1
|
||||
// args = [ self.input.i1.value, "foo", self.input.i1.value]
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
//dashboard "r2"{
|
||||
// dashboard "derived1" {
|
||||
// base = dashboard.r1
|
||||
// }
|
||||
// dashboard "derived2" {
|
||||
// base = dashboard.r1
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user