github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/spec.md (about) 1 # Mods & Reports 2 3 ## Resource Types 4 5 You can compose reports using a number of resource types. 6 7 | Name | Purpose | Valid children types | Allowed at top-level | 8 | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------- | 9 | `report` | A way to compose resources to meet a reporting requirement. Within the Steampipe reporting UIs, each `report` will be presented as an available item to run. | `chart`<br/>`container`<br/>`control`<br/>`counter`<br/>`hierarchy`<br/>`image`<br/>`input`<br/>`table`<br/>`text` | Yes | 10 | `container` | Conceptually identical to a report, except it will not be presented as an available item to run within the Steampipe reporting UIs. | `chart`<br/>`container`<br/>`control`<br/>`counter`<br/>`hierarchy`<br/>`image`<br/>`input`<br/>`table`<br/>`text` | Yes | 11 | `chart` | Chart SQL data in a number of ways e.g. `bar`, `column`, `line`, `pie` etc. | None | Yes | 12 | `control` | Allow mod controls to be defined or re-used in reports. | None | Yes | 13 | `counter` | Allow anything from a simple value to change in value to be presented in different styles e.g. `plain`, `alert` etc. Supports static values, or derived from SQL. | None | Yes | 14 | `hierarchy` | Visualise hierarchical data using things such as `sankey` or `graph`. | None | Yes | 15 | `image` | Allow embedding of images in reports. Supports static URLs, or can be derived from SQL. | None | Yes | 16 | `input` | Allow dynamic reporting based on user-provided `input`. | None | Yes | 17 | `table` | Show tabular data in a report. | None | Yes | 18 | `text` | Allow GitHub-flavoured markdown to be added to a report. | None | Yes | 19 | more TBD... | | | | 20 21 ## Spec 22 23 ### `report` 24 25 A report is designed to be used by consumers of your mod to answer specific reporting questions, such as "How many public AWS buckets do I have?" or "Show me the number of aging Zendesk tickets by owner". 26 27 Reports can only be declared at the top-level of a mod and can be re-used by using a `container`. 28 29 For layout, a report consists of 12 grid units, where items inside it will consume the full 12 grid units, unless they specific an explicit [width](#width). 30 31 #### Properties 32 33 - `title`: Plain text title used to display in lists, page title etc. When viewing the report in a browser, will be rendered as a h1. 34 35 #### Examples 36 37 ```hcl 38 report hello_world { 39 text { 40 value = "# Hello world!" 41 } 42 } 43 ``` 44 45 ```hcl 46 # Existing report re-used with `base` 47 report compose_other { 48 container { 49 base = report.hello_world 50 } 51 } 52 ``` 53 54 ### `container` 55 56 A container is intended to be used to group/lay-out related items within a report. For example, you may want to group together a number of different charts for a specific AWS service. 57 58 Containers can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using a `container` with `base = <mod>.container.<container_resource_name>`. 59 60 #### Properties 61 62 - `base`: A reference to a named `report` or `container` that this `container` should source its definition from. `title` and `width` can be overridden after sourcing via `base`. 63 - `title`: A container title is a shorthand convenience for adding a `text` block with a h2 Markdown heading and wrapping both items in a container. E.g. a title of `AWS S3 Metrics` would end up as: 64 65 ```hcl 66 container { 67 text { 68 value = "## AWS S3 Metrics" 69 } 70 71 container { 72 # Original container containing the title here... 73 } 74 } 75 ``` 76 77 - `width`: See [width](#width). 78 79 #### Examples 80 81 ```hcl 82 # Simple container with a text markdown panel 83 84 container { 85 text { 86 value = "## AWS S3 Metrics" 87 } 88 } 89 ``` 90 91 ```hcl 92 # Full-width container with 2 side-by-side containers on larger screens. 93 94 container { 95 container { 96 width = 6 97 text { 98 value = "## First text" 99 } 100 } 101 102 container { 103 width = 6 104 text { 105 value = "## Second text" 106 } 107 } 108 } 109 ``` 110 111 ```hcl 112 # Re-use an existing named top-level container and override its width. 113 114 container { 115 base = container.some_other_container 116 width = 6 117 } 118 ``` 119 120 ### `chart` 121 122 A chart will allow visualisation of queries in a variety of charting types such as `bar`, `column`, `donut`, `line` or `pie`. 123 124 The chart types share key things such as shape of the date and common configuration, so by having a single `chart` type, this allows us to be flexible. For example, you could simply change the type of chart from `bar` to `line` and it will just work, or we could allow in the reporting UI for a user to switch the chart type - all made possible by having a consistent data structure and commonality across the charts. 125 126 Chart blocks can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using a `chart` with `base = <mod>.chart.<chart_resource_name>`. 127 128 #### Properties 129 130 - `base`: A reference to a named `chart` resource that this `chart` should source its definition from. `title` and `width` can be overridden after sourcing via `base`. 131 - `title`: As per the title for a `container` or `chart`, except as this is a leaf is rendered as h3. 132 - `type`: The type of the chart. Can be `bar`, `column`, `donut`, `line` or `pie`. 133 - `sql`: Inline SQL or named query. 134 - `width`: See [width](#width). 135 - `legend`: See [legend](#legend). 136 - `series`: A named block matching the name of the series you wish to configure. See `Series`. 137 - `axes`: See [axes](#axes). 138 139 #### Data Format 140 141 | X-Axis | Y-Axis Series 1 | Y-Axis Series 2 | ... | Y-Axis Series N | 142 | ------- | ---------------- | ---------------- | --- | ---------------- | 143 | Label 1 | Value 1 Series 1 | Value 1 Series 2 | ... | Value 1 Series N | 144 | Label 2 | Value 2 Series 1 | Value 2 Series 2 | ... | Value 2 Series N | 145 | ... | ... | ... | ... | ... | 146 | Label N | Value N Series 1 | Value 1 Series 2 | ... | Value N Series N | 147 148 #### Examples 149 150 For the chart examples, we will be referring to the following single and multi-series queries: 151 152 ```hcl 153 query aws_a3_buckets_by_region { 154 sql = <<EOF 155 select 156 region as Region, 157 count(*) as Total 158 from 159 aws_s3_bucket 160 group by 161 region 162 order by 163 Total desc 164 EOF 165 } 166 ``` 167 168 ```hcl 169 query aws_a3_unencrypted_and_nonversioned_buckets_by_region { 170 sql = <<EOF 171 with unencrypted_buckets_by_region as ( 172 select 173 region, 174 count(*) as unencrypted 175 from 176 aws_morales_aaa.aws_s3_bucket 177 where 178 server_side_encryption_configuration is null 179 group by 180 region 181 ), 182 nonversioned_buckets_by_region as ( 183 select 184 region, 185 count(*) as nonversioned 186 from 187 aws_morales_aaa.aws_s3_bucket 188 where 189 not versioning_enabled 190 group by 191 region 192 ), 193 other_buckets_by_region as ( 194 select 195 region, 196 count(*) as "other" 197 from 198 aws_morales_aaa.aws_s3_bucket 199 where 200 server_side_encryption_configuration is not null 201 and versioning_enabled 202 group by 203 region 204 ) 205 select 206 o.region, 207 o.other, 208 u.unencrypted, 209 v.nonversioned 210 from 211 other_buckets_by_region o 212 full join unencrypted_buckets_by_region u on o.region = u.region 213 full join nonversioned_buckets_by_region v on o.region = v.region; 214 EOF 215 } 216 ``` 217 218 ##### Bar 219 220 ```hcl 221 # Single-series bar chart accepting all of the defaults 222 223 chart { 224 type = "bar" 225 sql = query.aws_a3_buckets_by_region.sql 226 title = "AWS S3 Buckets by Region" 227 } 228 ``` 229 230 ```hcl 231 # Multi-series bar chart providing custom properties for a variety of chart features 232 233 chart { 234 type = "bar" 235 sql = query.aws_a3_unencrypted_and_nonversioned_buckets_by_region.sql 236 title = "Unencrypted and Non-Versioned Buckets by Region" 237 legend { 238 display = "auto" 239 position = "top" 240 } 241 series other { 242 title = "Configured Buckets" 243 color = "green" 244 } 245 series unencrypted { 246 title = "Unencrypted Buckets" 247 color = "red" 248 } 249 series nonversioned { 250 title = "Non-Versioned Buckets" 251 color = "orange" 252 } 253 axes { 254 x { 255 title = "Regions" 256 labels { 257 display = "auto" 258 } 259 } 260 y { 261 title = "Totals" 262 labels { 263 display = "show" 264 } 265 min = 0 266 max = 100 267 steps = 10 268 } 269 } 270 } 271 ``` 272 273 ##### Column 274 275 ```hcl 276 # Single-series column chart accepting all of the defaults 277 278 chart { 279 type = "column" 280 sql = query.aws_a3_buckets_by_region.sql 281 title = "AWS S3 Buckets by Region" 282 } 283 ``` 284 285 ##### Donut 286 287 ```hcl 288 # Single-series donut chart accepting all of the defaults 289 290 chart { 291 type = "donut" 292 sql = query.aws_a3_buckets_by_region.sql 293 title = "AWS S3 Buckets by Region" 294 } 295 ``` 296 297 ##### Line 298 299 ```hcl 300 # Single-series line chart accepting all of the defaults 301 302 chart { 303 type = "line" 304 sql = query.aws_a3_buckets_by_region.sql 305 title = "AWS S3 Buckets by Region" 306 } 307 ``` 308 309 ##### Pie 310 311 ```hcl 312 # Single-series pie chart accepting all of the defaults 313 314 chart { 315 type = "pie" 316 sql = query.aws_a3_buckets_by_region.sql 317 title = "AWS S3 Buckets by Region" 318 } 319 ``` 320 321 ### `counter` 322 323 A counter is used to show a value to the user, or some change in value. A counter can also present itself in different styles e.g. show me a count of public S3 buckets and if the value is greater than 0 show as an `alert`, else as `ok`. 324 325 Counters can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using a `counter` with `base = <mod>.counter.<counter_resource_name>`. 326 327 #### Properties 328 329 - `base`: A reference to a named `counter` resource that this `counter` should source its definition from. `label`, `title`, `value`, `style` and `width` can be overridden after sourcing via `base`. 330 - `title`: As per the title for a `container` or `chart`, except as this is a leaf is rendered as h3. 331 - `label`: Inferred from the first column name in simple data format. Else can be set explicitly in HCL, or returned by the query in the `label` column in the formal data format. 332 - `sql`: Inline SQL or named query. 333 - `value`: Inferred from the first column's value in simple data format. 334 - `style`: `plain` (default), `alert`, `info` or `ok`. 335 - `width`: See [width](#width). 336 337 #### Data Structure 338 339 A counter supports 2 data structures. 340 341 1. A simple structure where column 1's name is the counter `label` and column 1's value is the counter `value`. 342 2. A formal data structure where the column names map to properties of the `counter`. 343 344 Simple data structure: 345 346 | \<label> | 347 | -------- | 348 | \<value> | 349 350 Formal data structure: 351 352 | label | value | style | 353 | ------------------- | ----- | ----- | 354 | Unencrypted Buckets | 10 | alert | 355 356 #### Examples 357 358 ```hcl 359 # Hard-code value and style declared in HCL. Useful for mocking report layouts. 360 361 counter { 362 title = "Mock Value" 363 value = 10 364 style = "alert" 365 } 366 ``` 367 368 ```hcl 369 # Using simple data structure as above. Style is static. 370 371 counter { 372 sql = <<EOF 373 select 374 count(*) as "Unencrypted Buckets" 375 from 376 aws_s3_bucket 377 where 378 server_side_encryption_configuration is null; 379 EOF 380 style = "alert" 381 } 382 ``` 383 384 ```hcl 385 # Using formal data structure as above, where the query determines properties of the counter. E.g. style is derived from the `style` column of the query. 386 387 counter { 388 sql = <<EOF 389 select 390 'Unencrypted Buckets' as title, 391 count(*) as value, 392 case 393 when count(*) > 0 then 'alert' 394 else 'ok' 395 end style 396 from 397 aws_s3_bucket 398 where 399 server_side_encryption_configuration is null; 400 EOF 401 } 402 ``` 403 404 ### `image` 405 406 Display images in reports., either from a known publicly-accessible `src` URL, or from a `src` return in a SQL query. 407 408 Image blocks can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using an `image` with `base = <mod>.image.<image_resource_name>`. 409 410 #### Properties 411 412 - `base`: A reference to a named `text` resource that this `text` should source its definition from. `title` and `width` can be overridden after sourcing via `base`. 413 - `title`: As per the title for a `container` or `chart`, except as this is a leaf is rendered as h3. 414 - `src`: Publicly-accessible URL for the image. 415 - `alt`: Alternative text for the image. 416 - `width`: See [width](#width). 417 418 #### Data Structure 419 420 If an image provides a `sql` query, it supports 2 data structures. 421 422 1. A simple structure where column 1's name is the `alt` and column 1's value is the image `src`. 423 2. A formal data structure where the column names map to properties of the `image`. 424 425 Simple data structure: 426 427 | \<alt> | 428 | ------ | 429 | \<src> | 430 431 Formal data structure: 432 433 | src | alt | 434 | ------------------------------------ | -------------- | 435 | https://steampipe.io/images/logo.png | Steampipe Logo | 436 437 #### Examples 438 439 ```hcl 440 # Hard-code src and alt declared in HCL. Useful for known image URLs. 441 442 image { 443 src = "https://steampipe.io/images/logo.png" 444 alt = "Steampipe Logo" 445 } 446 ``` 447 448 ```hcl 449 # Using simple data structure as above. 450 451 image { 452 sql = <<EOF 453 select 454 favicon as "Steampipe Logo" 455 from 456 web 457 where 458 domain = "https://steampipe.io"; 459 EOF 460 } 461 ``` 462 463 ```hcl 464 # Using formal data structure as above, where the query determines properties of the image. E.g. src is derived from the `src` column of the query. 465 466 image { 467 sql = <<EOF 468 select 469 favicon as src, 470 "Steampipe Logo" as alt 471 from 472 web 473 where 474 domain = "https://steampipe.io"; 475 EOF 476 } 477 ``` 478 479 ### `input` 480 481 Allow user input in reports using common form components such as inputs, selects etc. Data can either be static or derived from a SQL query. 482 483 The value of an input is synced with the declared `variable`, which allows the default/initial value to be set by the `variable` and then allows other mod resources to consume this `variable` to enable dynamic behaviour. 484 485 Input blocks can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using an `input` with `base = <mod>.input.<input_resource_name>`. 486 487 #### Properties 488 489 - `base`: A reference to a named `input` resource that this `input` should source its definition from. `title`, `sql`, `type`, `options` and `width` can be overridden after sourcing via `base`. 490 - `title`: As per the title for a `container` or `chart`, except as this is a leaf is rendered as h3. 491 - `sql`: Inline SQL or named query. 492 - `type`: The type of the input. Can be `check`, `input`, `radio` or `select`. 493 - `variable`: A reference to a mod `variable` that backs the input. 494 - `options`: Only applicable for input types that display options e.g. `check`, `radio` or `select` that wish to display a static list of options. Inferred from the data first 2 columns value in simple data format. 495 - `placeholder`: Only applicable for `input` type. 496 - `width`: See [width](#width). 497 498 #### Data Structure 499 500 The data structure for an `input` will depend on the `type`. 501 502 ##### Check / Radio / Select 503 504 | label | value | 505 | ------------------- | --------------------- | 506 | default | vpc-05657e5bef9676266 | 507 | acme @ 10.84.0.0/16 | vpc-03656e5eef967f366 | 508 509 #### Examples 510 511 ```hcl 512 # Select with static options 513 514 input { 515 type = "select" 516 variable = var.selected_vpc 517 options = [ 518 { 519 label = "default" 520 value = "vpc-05657e5bef9676266" 521 } 522 { 523 label = "acme @ 10.84.0.0/16" 524 value = "vpc-03656e5eef967f366" 525 } 526 ] 527 } 528 ``` 529 530 ```hcl 531 # Select with dynamic options 532 533 input { 534 type = "select" 535 variable = var.selected_vpc 536 sql = <<EOF 537 select 538 title as label 539 vpc_id as value, 540 from 541 aws_vpc; 542 EOF 543 } 544 ``` 545 546 ```hcl 547 # Radio with static options 548 549 input { 550 type = "radio" 551 variable = var.selected_vpc 552 options = [ 553 { 554 label = "default" 555 value = "vpc-05657e5bef9676266" 556 } 557 { 558 label = "acme @ 10.84.0.0/16" 559 value = "vpc-03656e5eef967f366" 560 } 561 ] 562 } 563 ``` 564 565 ```hcl 566 # Radio with dynamic options 567 568 input { 569 type = "radio" 570 variable = var.selected_vpc 571 sql = <<EOF 572 select 573 title as label 574 vpc_id as value, 575 from 576 aws_vpc; 577 EOF 578 } 579 ``` 580 581 ```hcl 582 # Check with static options 583 584 input { 585 type = "check" 586 variable = var.selected_vpc 587 options = [ 588 { 589 label = "default" 590 value = "vpc-05657e5bef9676266" 591 } 592 { 593 label = "acme @ 10.84.0.0/16" 594 value = "vpc-03656e5eef967f366" 595 } 596 ] 597 } 598 ``` 599 600 ```hcl 601 # Check with dynamic options 602 603 input { 604 type = "check" 605 variable = var.selected_vpc 606 sql = <<EOF 607 select 608 title as label 609 vpc_id as value, 610 from 611 aws_vpc; 612 EOF 613 } 614 ``` 615 616 ### `text` 617 618 Display either rendered `markdown` ([GitHub Flavored Markdown](https://github.github.com/gfm/)) or `raw` text with no interpretation of markup. # TODO do we want HTML? How can we be sure it's safe before rendering in the browser? 619 620 Text blocks can be declared as named resources at the top level of a mod, or be declared as anonymous blocks inside a `report` or `container`, or be re-used inside a `report` or `container` by using a `text` with `base = <mod>.text.<text_resource_name>`. 621 622 #### Properties 623 624 - `base`: A reference to a named `text` resource that this `text` should source its definition from. `title` and `width` can be overridden after sourcing via `base`. 625 - `title`: As per the title for a `container` or `chart`, except as this is a leaf is rendered as h3. 626 - `type`: `markdown` (default) or `raw`. 627 - `value`: The `markdown` or `html` string to use. Can also be sourced using the HCL `file` function. 628 - `width`: See [width](#width). 629 630 #### Examples 631 632 ```hcl 633 # Render as markdown (default). 634 635 text { 636 value = <<EOF 637 # I am some markdown text. 638 639 Please respect my markdown. 640 EOF 641 } 642 ``` 643 644 ```hcl 645 # Explicitly specify markdown (but is optional as markdown is the default). 646 647 text { 648 type = "markdown" 649 value = <<EOF 650 # I am some markdown text. 651 652 Please respect my markdown. 653 EOF 654 } 655 ``` 656 657 ```hcl 658 # Render raw 659 660 text { 661 type = "raw" 662 value = "<h2>I am a HTML title, but I'll be displayed as-is</h2>" 663 } 664 ``` 665 666 ### Common Properties: 667 668 #### `title` 669 670 Optional `title` for an item. Provided as plain text, but will be rendered as a `text` panel with a `style` of `markdown` using h1 (for `report`), h2 (for `container`) or h3 (for any leaf nodes e.g. `chart`). This `text` block and the item it is titling will be wrapped by a `container`. 671 672 #### `width` 673 674 The number of grid units that this item should consume from its parent. In the browser, this is only used when in a large screen size and up (viewport min-width of 1024px), and will always be 12 for smaller viewports. Provided value must be between `0` and `12` (default). `0` would mean the `container` is hidden and will not consume any space on the report. 675 676 ### Common Chart Properties 677 678 #### `axes` 679 680 Applicable to `bar`, `column`, `line` and `scatter`. 681 682 - `x`: 683 684 | Property | Type | Default | Values | Description | 685 | -------- | ---------------------------- | ------- | ------ | ----------- | 686 | `title` | See [axistitle](#axis-title) | | | | 687 | `labels` | See [labels](#labels) | | | | 688 689 - `y`: 690 691 | Property | Type | Default | Values | Description | 692 | -------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ----------- | 693 | `title` | See [axistitle](#axis-title) | | | | 694 | `labels` | See [labels](#labels) | | | | 695 | `min` | number | Determined by the range of values. For positive ranges, this will be `0`. For negative ranges, this will be scaled to the next appropriate value below the range min. | Any valid number. | | 696 | `max` | number | Determined by the range of values. For positive ranges, this will be scaled to the next appropriate value above the range max `0`. For negative ranges, this will be `0`. | Any valid number. | | 697 698 #### `axis title` 699 700 | Property | Type | Default | Values | Description | 701 | --------- | ------ | -------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | 702 | `display` | string | `none` | `always` or `none` (default). | `always` will ensure the axis title is `always` shown, or `none` will never show it. | 703 | `align` | string | `center` | `start`, `center` (default) or `end`. | By default the chart will align the axis title in the `center` of the chart, but this can be overridden to `start` or `end` if required. | 704 | `value` | string | | Max 50 characters. | | 705 706 #### `labels` 707 708 | Property | Type | Default | Values | Description | 709 | --------- | ------ | ------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 710 | `display` | string | `auto` | `auto` (default), `always` or `none`. | `auto` will display as many labels as possible for the size of the chart. `always` will always show all labels, but will truncate them with an ellipsis as necessary. `none` will never show labels for this axis. | 711 | `format` | TBD | | | | 712 713 #### `legend` 714 715 | Property | Type | Default | Values | Description | 716 | ---------- | ------ | ------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | 717 | `display` | string | `auto` | `auto`, `always` or `none`. | `auto` will display a legend if there are multiple data series. `show` will ensure a legend is `always` shown, or `hide` will never show a legend. | 718 | `position` | string | `top` | `top`, `right`, `bottom` or `left`. | By default the chart will display a legend at the `top` of the chart, but this can be overridden to `right`, `bottom` or `left` if required. | 719 720 #### `series`: 721 722 | Property | Type | Default | Values | Description | 723 | -------- | ------ | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------- | 724 | `title` | string | The column name that the series data resides in. | Max 50 characters | | 725 | `color` | string | The matching color from the default theme for the data series index. | Any valid color from the HTML extended colors (e.g. `gold`), a valid Hex string (e.g. `#0000FF`) or a valid RGB (e.g. `rgb(0, 0, 100)`) | | 726 727 --- 728 729 Inputs mock: 730 731 ```hcl 732 query aws_regions_input { 733 sql = <<-EOT 734 select 735 name as value, 736 title as label 737 from 738 aws_region; 739 EOT 740 } 741 742 query aws_vpcs_for_region_input { 743 sql = <<-EOT 744 select 745 vpc_id as value, 746 title as label 747 from 748 aws_morales_aaa.aws_vpc 749 where 750 region = $1; 751 EOT 752 param region { 753 description = "Region to filter VPCs by." 754 } 755 } 756 757 execute 758 { 759 region = "us-east-1" 760 } 761 762 report inputs_mock { 763 title = "Inputs Mock" 764 765 param "region" { 766 default = var.default_region 767 sql = query.aws_regions_input.sql 768 type = "select" 769 description = "Selected region for the report." 770 } 771 772 param "region" { 773 default = var.default_region 774 description = "Selected region for the report." 775 } 776 777 param "region" { 778 default = var.default_region 779 value = input.region_select.value 780 description = "Selected region for the report." 781 } 782 783 param "vpc_id" { 784 default = input.vpc_select.value 785 description = "Selected VPC for the report." 786 } 787 788 container { 789 input "foo" { 790 base = param.region 791 width = 6 792 } 793 794 input { 795 base = param.region 796 sql = query.aws_regions_input.sql 797 type = "select" 798 width = 6 799 } 800 801 input "region_select" { 802 type = "select" 803 sql = query.aws_regions_input.sql 804 width = 6 805 } 806 807 input { 808 base = param.region 809 type = "select" 810 sql = query.aws_regions_input.sql 811 width = 6 812 } 813 814 input "vpc_select" { 815 type = "select" 816 query = query.aws_vpcs_for_region_input 817 args = { 818 region = param.region 819 } 820 width = 6 821 } 822 } 823 824 container { 825 chart { 826 type = "bar" 827 # sql = query.foo.sql 828 query = query.aws_blah_for_vpc 829 args = { 830 region = param.vpc_id 831 } 832 } 833 } 834 835 text { 836 type = "markdown" 837 value = "## Some text" 838 } 839 } 840 ``` 841 842 ## OLD DOCS - ignore below here 843 844 ### `bar` 845 846 Display a `bar` chart for single or grouped multi-series. Maximum series count is `10`. 847 848 #### Data Format 849 850 | X-Axis | Y-Axis Series 1 | Y-Axis Series 2 | ... | Y-Axis Series N | 851 | ------- | ---------------- | ---------------- | --- | ---------------- | 852 | Label 1 | Value 1 Series 1 | Value 1 Series 2 | ... | Value 1 Series N | 853 | Label 2 | Value 2 Series 1 | Value 2 Series 2 | ... | Value 2 Series N | 854 | ... | ... | ... | ... | ... | 855 | Label N | Value N Series 1 | Value 1 Series 2 | ... | Value N Series N | 856 857 #### Properties 858 859 - `title`: See [title](#title). 860 - `sql`: Inline SQL or named query. 861 - `legend`: See [legend](#legend). 862 - `series`: A named block matching the name of the series you wish to configure. See `Series`. 863 - `axes`: See [axes](#axes). 864 865 ##### Basic 866 867 Accept all defaults. 868 869 ```hcl 870 bar { 871 sql = query.aws_a3_buckets_by_region.sql 872 title = "AWS S3 Buckets by Region" 873 } 874 ``` 875 876 ##### Kitchen Sink 877 878 Specify all options. 879 880 # TODO should blocks assign with =? E.g. `legend { ...` vs `legend = { ...` 881 882 ```hcl 883 bar { 884 sql = query.aws_a3_unencrypted_and_nonversioned_buckets_by_region.sql 885 title = "Unencrypted and Non-Versioned Buckets by Region" 886 legend { 887 display = "auto" 888 position = "top" 889 } 890 series other { 891 title = "Configured Buckets" 892 color = "green" 893 } 894 series unencrypted { 895 title = "Unencrypted Buckets" 896 color = "red" 897 } 898 series nonversioned { 899 title = "Non-Versioned Buckets" 900 color = "orange" 901 } 902 axes { 903 x { 904 title = "Regions" 905 labels { 906 display = "auto" 907 } 908 } 909 y { 910 title = "Totals" 911 labels { 912 display = "show" 913 } 914 min = 0 915 max = 100 916 steps = 10 917 } 918 } 919 } 920 ``` 921 922 ### `column` 923 924 Display a `column` chart for single or grouped multi-series. Maximum series count is 10. 925 926 #### Data Format 927 928 | X-Axis | Y-Axis Series 1 | Y-Axis Series 2 | ... | Y-Axis Series N | 929 | ------- | ---------------- | ---------------- | --- | ---------------- | 930 | Label 1 | Value 1 Series 1 | Value 1 Series 2 | ... | Value 1 Series N | 931 | Label 2 | Value 2 Series 1 | Value 2 Series 2 | ... | Value 2 Series N | 932 | ... | ... | ... | ... | ... | 933 | Label N | Value N Series 1 | Value 1 Series 2 | ... | Value N Series N | 934 935 #### Properties 936 937 - `title`: See [title](#title). 938 - `sql`: Inline SQL or named query. 939 - `legend`: See [legend](#legend). 940 - `series`: A named block matching the name of the series you wish to configure. See `Series`. 941 - `axes`: See [axes](#axes). 942 943 ##### Basic 944 945 Accept all defaults. 946 947 ```hcl 948 column { 949 sql = query.aws_a3_buckets_by_region.sql 950 title = "AWS S3 Buckets by Region" 951 } 952 ``` 953 954 ##### Kitchen Sink 955 956 Specify all options. 957 958 ```hcl 959 column { 960 sql = query.aws_a3_unencrypted_and_nonversioned_buckets_by_region.sql 961 title = "Unencrypted and Non-Versioned Buckets by Region" 962 legend { 963 display = "auto" 964 position = "top" 965 } 966 series other { 967 title = "Configured Buckets" 968 color = "green" 969 } 970 series unencrypted { 971 title = "Unencrypted Buckets" 972 color = "red" 973 } 974 series nonversioned { 975 title = "Non-Versioned Buckets" 976 color = "orange" 977 } 978 axes { 979 x { 980 title = "Regions" 981 labels = "auto" 982 } 983 y { 984 title = "Totals" 985 labels = { 986 display = "show" 987 } 988 min = 0 989 max = 100 990 steps = 10 991 } 992 } 993 } 994 ``` 995 996 ### `line` 997 998 Display a `line` chart for single or multi-series. Maximum series count is 10. 999 1000 #### Data Format 1001 1002 | X-Axis | Y-Axis Series 1 | Y-Axis Series 2 | ... | Y-Axis Series N | 1003 | ------- | ---------------- | ---------------- | --- | ---------------- | 1004 | Label 1 | Value 1 Series 1 | Value 1 Series 2 | ... | Value 1 Series N | 1005 | Label 2 | Value 2 Series 1 | Value 2 Series 2 | ... | Value 2 Series N | 1006 | ... | ... | ... | ... | ... | 1007 | Label N | Value N Series 1 | Value 1 Series 2 | ... | Value N Series N | 1008 1009 #### Properties 1010 1011 - `title`: See [title](#title). 1012 - `sql`: Inline SQL or named query. 1013 - `legend`: See [legend](#legend). 1014 - `series`: A named block matching the name of the series you wish to configure. See `Series`. 1015 - `axes`: See [axes](#axes). 1016 1017 ##### Basic 1018 1019 Accept all defaults. 1020 1021 ```hcl 1022 column { 1023 sql = query.aws_a3_buckets_by_region.sql 1024 title = "AWS S3 Buckets by Region" 1025 } 1026 ``` 1027 1028 ##### Kitchen Sink 1029 1030 Specify all options. 1031 1032 ```hcl 1033 line { 1034 sql = query.aws_a3_unencrypted_and_nonversioned_buckets_by_region.sql 1035 title = "Unencrypted and Non-Versioned Buckets by Region" 1036 legend = { 1037 display = "auto" 1038 position = "top" 1039 } 1040 series other { 1041 title = "Configured Buckets" 1042 color = "green" 1043 } 1044 series unencrypted { 1045 title = "Unencrypted Buckets" 1046 color = "red" 1047 } 1048 series nonversioned { 1049 title = "Non-Versioned Buckets" 1050 color = "orange" 1051 } 1052 axes { 1053 x { 1054 title = "Regions" 1055 labels = "auto" 1056 } 1057 y { 1058 title = "Totals" 1059 labels = { 1060 display = "show" 1061 } 1062 min = 0 1063 max = 100 1064 steps = 10 1065 } 1066 } 1067 } 1068 ``` 1069 1070 ### `pie` 1071 1072 Display a `pie` chart. Maximum 10 categories. Automatically puts the smallest category values into an `Other` category for large category counts. 1073 1074 #### Data Format 1075 1076 # TODO single series like simple charts 1077 1078 | Category | Value | 1079 | ---------- | ------- | 1080 | Category 1 | Value 1 | 1081 | Category 2 | Value 2 | 1082 | ... | ... | 1083 | Category N | Value N | 1084 1085 #### Properties 1086 1087 - `title`: See [title](#title). 1088 - `sql`: Inline SQL or named query. 1089 - `legend`: See [legend](#legend). 1090 - `grouping`: `auto` (default) will automatically group the smallest values into an `Other` category when the number of categories is greater than 10, ensuring a maximum of 10 categories, or `off` will attempt to display the number of categories present. 1091 - `categories`: A named block matching the name of the category you wish to configure. See [categories](#categories). 1092 1093 ##### Basic 1094 1095 Accept all defaults. 1096 1097 ```hcl 1098 pie { 1099 sql = query.aws_a3_buckets_by_region.sql 1100 title = "AWS S3 Buckets by Region" 1101 } 1102 ``` 1103 1104 ##### Kitchen Sink 1105 1106 Specify all options. 1107 1108 ```hcl 1109 pie { 1110 sql = query.aws_a3_unencrypted_and_nonversioned_buckets_by_region.sql 1111 title = "Unencrypted and Non-Versioned Buckets by Region" 1112 legend = { 1113 display = "auto" 1114 position = "top" 1115 } 1116 series other { 1117 title = "Configured Buckets" 1118 color = "green" 1119 } 1120 series unencrypted { 1121 title = "Unencrypted Buckets" 1122 color = "red" 1123 } 1124 series nonversioned { 1125 title = "Non-Versioned Buckets" 1126 color = "orange" 1127 } 1128 axes { 1129 x { 1130 title = "Regions" 1131 labels = "auto" 1132 } 1133 y { 1134 title = "Totals" 1135 labels = { 1136 display = "show" 1137 } 1138 min = 0 1139 max = 100 1140 steps = 10 1141 } 1142 } 1143 } 1144 ``` 1145 1146 --- 1147 1148 ## Old docs 1149 1150 - A `container` is a new layout resource type that composes `panel` and/or `container` blocks. Supports width property: 1151 1152 ```hcl 1153 container s3_layout_panel { 1154 width = 6 1155 1156 panel s3_buckets_by_region { 1157 type = "barchart" 1158 sql = query.aws_s3_buckets_by_region.sql 1159 } 1160 1161 panel ec2_instances_by_region { 1162 type = "barchart" 1163 sql = query.ec2_instances_by_region.sql 1164 } 1165 1166 container layout { 1167 width = 6 1168 1169 panel ec2_instances_by_region { 1170 type = "barchart" 1171 sql = query.ec2_instances_by_region.sql 1172 } 1173 } 1174 } 1175 ``` 1176 1177 - A `report` can contain `panel` and/or `container` blocks. (still supports `title` property): 1178 1179 ```hcl 1180 report my_report { 1181 title = "My Report" 1182 1183 panel s3_buckets_by_region { 1184 type = "barchart" 1185 sql = query.aws_s3_buckets_by_region.sql 1186 } 1187 1188 container layout { 1189 width = 6 1190 1191 panel ec2_instances_by_region { 1192 type = "barchart" 1193 sql = query.ec2_instances_by_region.sql 1194 } 1195 } 1196 } 1197 ``` 1198 1199 - A `panel` cannot compose anything else now. It is a leaf node in the tree: 1200 1201 ```hcl 1202 panel s3_buckets_by_region { 1203 type = "barchart" 1204 sql = query.aws_s3_buckets_by_region.sql 1205 } 1206 ``` 1207 1208 - Only `report` and `panel` can exist at the top-level of a mod. 1209 1210 - To re-use an existing panel, use `base`: 1211 1212 ```hcl 1213 panel s3_buckets_by_region { 1214 type = "barchart" 1215 sql = query.aws_s3_buckets_by_region.sql 1216 } 1217 1218 panel re_use { 1219 base = panel.s3_buckets_by_region 1220 } 1221 ``` 1222 1223 - To re-use and override a property of an existing panel, use `base` + override its property: 1224 1225 ```hcl 1226 panel s3_buckets_by_region { 1227 type = "barchart" 1228 sql = query.aws_s3_buckets_by_region.sql 1229 } 1230 1231 panel re_use { 1232 base = panel.s3_buckets_by_region 1233 type = "linechart" 1234 } 1235 ``` 1236 1237 - To re-use an existing report, use a `panel` with `base`: 1238 1239 ```hcl 1240 report other_report { 1241 panel s3_buckets_by_region { 1242 type = "barchart" 1243 sql = query.aws_s3_buckets_by_region.sql 1244 } 1245 } 1246 1247 report my_report { 1248 panel nested_report { 1249 base = report.other_report 1250 } 1251 } 1252 ``` 1253 1254 - A `container` cannot be re-used unlike `panel` and `report`. 1255 1256 - Panel `source` is now `type` and is not parse-time checked - it's just a (required) string: 1257 1258 ```hcl 1259 panel s3_buckets_by_region { 1260 type = "barchart" 1261 sql = query.aws_s3_buckets_by_region.sql 1262 } 1263 ``` 1264 1265 - "Core" panel properties are `type` (required), `sql` (optional, named or inline query) and `width`. 1266 1267 - Custom/extended properties for a `panel` are declared at the top-level of the block: 1268 1269 ```hcl 1270 panel s3_buckets_by_region { 1271 type = "barchart" 1272 sql = query.aws_s3_buckets_by_region.sql 1273 orientation = "horizontal" 1274 } 1275 ``` 1276 1277 - All internal lists of `container` and `panel` inside a `report` or `container` should be stored as `children` to align with `benchmark`. 1278 1279 ## High-level design decisions 1280 1281 - Mods can define >=0: 1282 - `query` 1283 - A named query that can be used to obtain data 1284 - `panel` 1285 - The building block of a report - effectively a named layout component 1286 - A panel may render a report primitive: 1287 - `report` 1288 - `panel` 1289 - `markdown` 1290 - `table` 1291 - `counter` 1292 - `barchart` // TODO - is this just `chart` with further properties to define, or should be explicit like this? 1293 - `linechart` // TODO - same as above 1294 - `piechart` // TODO - same as above 1295 - tbd... 1296 - A panel can compose other reports and panels, allowing interesting and more complex layouts to be achieved 1297 - A panel can be used in isolation if required, but is typically designed to be composed with other panels into a `report` 1298 - `report` 1299 - Conceptually no different to a `panel` in that it is a named layout component that composes `panel`s and/or `report`s 1300 - The key differentiator is a `report` indicates that it will provide answers to specific reporting issues through composition, whereas a `panel` may only provide a subset of data that may not provide full context if used in isolation 1301 - A mod is expected to provide a `main` report, which is the default report to use 1302 - All reporting primitives must know how to display themselves across a variety of screen sizes and mediums 1303 - The current in-scope mediums are: 1304 - `web` 1305 - Reports and panels will be mapped to a suitable grid system to provide simple, yet powerful layout constructs - spec below 1306 - Ideal state: 1307 - Support a rich and interactive reporting experience on larger devices, with graceful degradation of functionality as we move down through screen sizes 1308 - Panels 1309 - MVP state 1310 - Support display of reports across large and small devices e.g. columns should be full-width on small devices 1311 - `email` 1312 - Spec TBD, but likely to contain images of report primitives - pure html and attachments will ensure maximum compatibility 1313 - `slack` 1314 - Likely to have the most constrained and succinct layout options - spec TBD 1315 - All mod component are public, meaning that anyone using a mod can import any `query`, `panel`, `report` or `action` 1316 - Action spec TBD - but effectively provides a consistent way to take action based on query data or the outcome of a report e.g. email a DG, send a Slack message 1317 - Actions are just named compositions of basic primitives including http request, send slack message, send email etc 1318 - Namespacing: 1319 - Components are namespaced 1320 - `<org>.<component>.<primitive>` 1321 - e.g. `steampipe.panel.markdown` 1322 - Omission of namespace refers to locally-defined components within that mod e.g. 1323 - `panel.header` 1324 - `panel.body` 1325 - `panel.footer` 1326 - `query.aging_aws_iam_access_keys` 1327 - When building reports in custom mods you will always refer to the Steampipe reporting primitives with their full namespace e.g. 1328 - `steampipe.panel.markdown` 1329 - `steampipe.panel.counter` 1330 - etc... 1331 1332 ## Primitives 1333 1334 Reports consist of a number of primitives, which allow various scenarios to be reported on. The following section will outline the available primitives, along with their required and optional parameters. 1335 1336 ### Report 1337 1338 - A report provides a 12-column grid system. It's child panels will consume grid units from left to right, wrapping to the next row when all 12 units have been consumed, or there are insufficient grid units left on that row. 1339 - Properties: 1340 - `title`: (optional) A human-friendly title for the report. This will be preferred over the HCL panel name whenever we need to present a list of reports to the user. 1341 - Example: 1342 1343 ```hcl 1344 report hello_world { 1345 title = "Hello World" 1346 } 1347 ``` 1348 1349 ### Panel 1350 1351 - A panel is the primitive that you will use to lay out your reports and present the various reporting primitives. 1352 - Each panel will consume the full available width of its parent. E.g. if your parent panel is 12 grid units, you will have up to 12 grid unit available, however if your parent panel/report only has 6/12 grid units, your panel will only have up to 6 grid units available. 1353 - Properties: 1354 1355 - `source`: (required) The source type of this panel, which will be one of the following: 1356 1357 - `steampipe.panel.markdown`: A panel for rendering markdown 1358 - `steampipe.panel.counter`: A panel for displaying counter data (e.g. totals) 1359 - `steampipe.panel.table`: A panel for displaying tabular data 1360 - `steampipe.panel.bar_chart`: A panel for displaying tabular data in a bar chart 1361 - `steampipe.panel.line_chart`: A panel for displaying tabular data in a line chart 1362 - `steampipe.panel.pie_chart`: A panel for displaying tabular data in a pie chart 1363 1364 - `steampipe.panel.control_table`: A panel for displaying tabular data that conforms to the Steampipe [control query spec](https://steampipe.io/docs/using-steampipe/writing-controls). 1365 1366 - `width`: (optional) The amount of grid unit that it should consume from its parent. 1367 - If not specified this will default to 12 and the panel will consume the full width of its parent. 1368 - Min: `1` 1369 - Max: `12` 1370 - `height`: (optional) A number of units relative to one grid unit width of itself. 1371 - E.g. if `height` is 4 and the panel is 1200px wide / 12 grid units wide, then 1 grid unit width is 120px, so 4 height units would be 480px. 1372 - If not specified the panel will be as tall as required to render its content 1373 1374 ### Markdown 1375 1376 Allow rendering of markdown content in a report. 1377 1378 - `source: steampipe.panel.markdown` 1379 - Supports [GitHub Flavored Markdown Spec](https://github.github.com/gfm/) 1380 - If a panel `height` is specified and the content height exceeds the calculated height, the panel will scroll vertically. 1381 - Properties: 1382 - `text`: (required) The markdown string 1383 1384 ```hcl 1385 panel markdown { 1386 source = steampipe.panel.markdown 1387 text = <<-EOT 1388 # It's just markdown 1389 So go `wild`. 1390 EOT 1391 } 1392 ``` 1393 1394 ### Counter 1395 1396 Display a counter in a report. 1397 1398 - `steampipe.panel.counter` 1399 - Expects data in format 1400 1401 | \<Title of counter\> | 1402 | -------------------- | 1403 | \<Counter value\> | 1404 1405 e.g. 1406 1407 | AWS IAM Users | 1408 | ------------- | 1409 | 17 | 1410 1411 - First row is expected to be the header with title 1412 - Second row is the counter value itself 1413 1414 ```hcl 1415 panel aws_iam_user_count { 1416 source = steampipe.panel.counter 1417 query = "select count(*) as "AWS IAM Users" from aws_iam_user" 1418 } 1419 ``` 1420 1421 ### Table 1422 1423 Allow rendering of table data in a report. 1424 1425 - `source: steampipe.panel.table` 1426 - Expects data in table (e.g. like CSV/Excel) format. First row assumed to be the header row. Subsequent rows assumed to be the data rows. 1427 - Properties: 1428 - `sql`: Either an inline query, or a named query 1429 1430 Example with inline query: 1431 1432 ```hcl 1433 panel buckets_versioning_disabled { 1434 source = steampipe.panel.table 1435 sql = "select name as Name, region as Region from aws_s3_bucket where versioning = 'disabled'" 1436 } 1437 ``` 1438 1439 Example with named query: 1440 1441 ```hcl 1442 panel buckets_versioning_disabled { 1443 source = steampipe.panel.table 1444 sql = query.buckets_versioning_disabled_query.sql 1445 } 1446 ``` 1447 1448 ### Pie Chart 1449 1450 Allow rendering of data as a pie chart in a report. 1451 1452 - `steampipe.panel.piechart` 1453 - First column will be projected across the X-axis 1454 - Second column will be used as the series data 1455 - Expects data in table format 1456 1457 | Entity | Total | 1458 | -------- | ----- | 1459 | Groups | 2 | 1460 | Policies | 102 | 1461 | ... | ... | 1462 | Users | 10 | 1463 1464 ```hcl 1465 panel buckets_versioning_disabled { 1466 source = steampipe.panel.barchart 1467 title = "AWS IAM Entities" 1468 query = "select entity as Entity, total as Total;" 1469 } 1470 ``` 1471 1472 ### Bar Chart 1473 1474 Allow rendering of data as a bar chart in a report. 1475 1476 - `steampipe.panel.barchart` 1477 - First column will be projected across the X-axis 1478 - Second column will be used as the series data 1479 - Expects data in table format 1480 1481 | Entity | Total | 1482 | -------- | ----- | 1483 | Groups | 2 | 1484 | Policies | 102 | 1485 | ... | ... | 1486 | Users | 10 | 1487 1488 ```hcl 1489 panel buckets_versioning_disabled { 1490 source = steampipe.panel.barchart 1491 title = "AWS IAM Entities" 1492 query = "select entity as Entity, total as Total;" 1493 } 1494 ``` 1495 1496 ### Stacked Bar Chart 1497 1498 Allow rendering of data as a stacked bar chart in a report. 1499 1500 - `steampipe.panel.stackedbarchart` 1501 - First column will be projected across the X-axis 1502 - Each subsequent column will be used as the series data to stack 1503 - Expects data in table format 1504 1505 | Entity | Used | Available | 1506 | -------- | ---- | --------- | 1507 | Groups | 2 | 498 | 1508 | Policies | 102 | 898 | 1509 | ... | ... | ... | 1510 | Users | 10 | 90 | 1511 1512 ```hcl 1513 panel buckets_versioning_disabled { 1514 source = steampipe.panel.stackedbarchart 1515 title = "AWS IAM Entity Quota Usage" 1516 query = "select entity as Entity, total as Used, (total - quota) as Available from aws_iam_account_summary;" 1517 } 1518 ``` 1519 1520 ### Line Chart 1521 1522 Allow rendering of data as a line chart in a report. 1523 1524 - `steampipe.panel.linechart` 1525 - First column will be projected across the X-axis 1526 - Second column will be used as the series data 1527 - Expects data in table format 1528 1529 #### Single Line 1530 1531 | Entity | Total | 1532 | -------- | ----- | 1533 | Groups | 2 | 1534 | Policies | 102 | 1535 | ... | ... | 1536 | Users | 10 | 1537 1538 ```hcl 1539 panel buckets_versioning_disabled { 1540 source = steampipe.panel.linechart 1541 title = "AWS IAM Entities" 1542 query = "select entity as Entity, total as Total;" 1543 } 1544 ``` 1545 1546 #### Multi Line 1547 1548 | Entity | Used | Available | 1549 | -------- | ---- | --------- | 1550 | Groups | 2 | 498 | 1551 | Policies | 102 | 898 | 1552 | ... | ... | ... | 1553 | Users | 10 | 90 | 1554 1555 ```hcl 1556 panel buckets_versioning_disabled { 1557 source = steampipe.panel.linechart 1558 title = "AWS IAM Entity Quota Usage" 1559 query = "select entity as Entity, total as Used, (total - quota) as Available from aws_iam_account_summary;" 1560 } 1561 ``` 1562 1563 ## Examples 1564 1565 ### Report with single markdown panel 1566 1567 - Single full-width panel rendered with a title in markdown 1568 - <!---TODO: text? check this--> 1569 1570 ```hcl 1571 report hello_world { 1572 1573 panel header { 1574 source = steampipe.panel.markdown 1575 text = "# Hello World!" 1576 } 1577 1578 } 1579 ``` 1580 1581 ### 2-column, 1-row layout, single panel in each column 1582 1583 - Top-level panel, but specifying a width of 6 columns each 1584 1585 ```hcl 1586 report two_column_one_row { 1587 1588 panel left { 1589 width = 6 1590 source = steampipe.panel.markdown 1591 text = "# Left Side" 1592 } 1593 1594 panel right { 1595 width = 6 1596 source = steampipe.panel.markdown 1597 text = "# Right Side" 1598 } 1599 1600 } 1601 ``` 1602 1603 ### 1-column, 2-row layout, single panel in each row 1604 1605 - Top-level panel, so implicitly 12 columns wide 1606 - Child panels 1607 - No height specified, so will fill available height 1608 1609 ```hcl 1610 report one_column_two_row { 1611 1612 panel main { 1613 1614 panel first { 1615 source = steampipe.panel.markdown 1616 text = "# First Row" 1617 } 1618 1619 panel second { 1620 source = steampipe.panel.markdown 1621 text = "# Second Row" 1622 } 1623 1624 } 1625 1626 } 1627 ``` 1628 1629 ### Basic report with header, nav, content and footer 1630 1631 ```hcl 1632 report basic { 1633 1634 panel header { 1635 source = steampipe.panel.markdown 1636 text = "# Header" 1637 } 1638 1639 panel main { 1640 1641 panel nav { 1642 width = 3 1643 source = steampipe.panel.markdown 1644 text = "# Nav" 1645 } 1646 1647 panel content { 1648 width = 9 1649 source = steampipe.panel.markdown 1650 text = "# Content" 1651 } 1652 1653 } 1654 1655 panel footer { 1656 source = steampipe.panel.markdown 1657 text = "# Footer" 1658 } 1659 1660 } 1661 ``` 1662 1663 ### 2-column, 1-row layout with nested panels 1664 1665 - Top-level panel, so implicitly 24 columns wide 1666 - No height specified, so will fill available height 1667 1668 ```hcl 1669 panel header_top_row { 1670 1671 panel left { 1672 width = 6 1673 source = steampipe.panel.markdown 1674 text = "# Left" 1675 } 1676 1677 panel right { 1678 width = 6 1679 source = steampipe.panel.markdown 1680 text = "# Right" 1681 } 1682 1683 } 1684 1685 panel main { 1686 1687 panel header { 1688 source = panel.header_top_row 1689 } 1690 1691 } 1692 ``` 1693 1694 ### 2-column, 1-row layout with 2 nested panels each containing 2 columns 1695 1696 - Top-level panel, so implicitly 24 columns wide 1697 - No height specified, so will fill available height 1698 1699 ```hcl 1700 panel content_left { 1701 1702 panel left { 1703 width = 6 1704 source = steampipe.panel.markdown 1705 text = "# One" 1706 } 1707 1708 panel right { 1709 width = 6 1710 source = steampipe.panel.markdown 1711 text = "# Two" 1712 } 1713 1714 } 1715 1716 panel content_right { 1717 1718 panel left { 1719 width = 6 1720 source = steampipe.panel.markdown 1721 text = "# Three" 1722 } 1723 1724 panel right { 1725 width = 6 1726 source = steampipe.panel.markdown 1727 text = "# Four" 1728 } 1729 1730 } 1731 1732 panel main { 1733 1734 panel left { 1735 width = 6 1736 source = panel.content_left 1737 } 1738 1739 panel right { 1740 width = 6 1741 source = panel.content_right 1742 } 1743 1744 } 1745 ``` 1746 1747 ## Primitives 1748 1749 ### Panel 1750 1751 The basic layout construct for reports 1752 1753 ```hcl 1754 panel header { 1755 source = steampipe.panel.markdown 1756 text = "# Render me" 1757 } 1758 ``` 1759 1760 ### Example AWS Report 1761 1762 This example takes a few of the report primitives outlined above and composes them into a simple report 1763 1764 ```hcl 1765 report aws { 1766 1767 panel header { 1768 source = steampipe.panel.markdown 1769 text = <<-EOT 1770 # AWS Report 1771 Overview of a variety of key AWS metrics. 1772 EOT 1773 } 1774 1775 panel iam { 1776 1777 panel iam-header { 1778 source = steampipe.panel.markdown 1779 text = "### IAM" 1780 } 1781 1782 panel iam-count { 1783 width = 3 1784 source = steampipe.panel.counter 1785 query = "select count(*) as "Unused Access Keys" from aws_iam_user" 1786 } 1787 1788 panel iam-entities { 1789 width = 9 1790 source = steampipe.panel.barchart 1791 query = "select groups, groups_quota, policies, policies_quota, roles, roles_quota, users, users_quota from aws_iam_account_summary;" 1792 } 1793 1794 } 1795 1796 panel cost { 1797 width = 8 1798 1799 panel cost-header { 1800 source = steampipe.panel.markdown 1801 text = "### Cost" 1802 } 1803 1804 panel cost-monthly { 1805 source = steampipe.panel.linechart 1806 query = "select period_start as "Period Start", unblended_cost_amount as "Unblended Cost" from aws_cost_by_account where granularity = 'monthly' order by period_start;" 1807 } 1808 1809 } 1810 1811 panel lambda { 1812 width = 4 1813 1814 panel lambda-header { 1815 source = steampipe.panel.markdown 1816 text = "### Lambda" 1817 } 1818 1819 panel lambda-runtimes { 1820 source = steampipe.panel.piechart 1821 query = "select runtime as "Runtime", count(runtime) as "Count" from aws_lambda_function group by runtime order by runtime;" 1822 } 1823 1824 } 1825 1826 panel kms { 1827 1828 panel kms-header { 1829 source = steampipe.panel.markdown 1830 text = "### KMS" 1831 } 1832 1833 panel kms-keys { 1834 source = steampipe.panel.table 1835 query = "select title as "Id", region as "Region", key_rotation_enabled as "Rotation Enabled", description as "Description" from aws_kms_key;" 1836 } 1837 1838 } 1839 1840 } 1841 ```