diff --git a/aws/plugin.go b/aws/plugin.go index 8595308e2..beb794d1c 100644 --- a/aws/plugin.go +++ b/aws/plugin.go @@ -347,9 +347,12 @@ func Plugin(ctx context.Context) *plugin.Plugin { "aws_inspector_exclusion": tableAwsInspectorExclusion(ctx), "aws_inspector_finding": tableAwsInspectorFinding(ctx), "aws_iot_fleet_metric": tableAwsIoTFleetMetric(ctx), + "aws_iot_greengrass_component": tableAwsIotGreengrassComponent(ctx), + "aws_iot_greengrass_core_device": tableAwsIotGreengrassCoreDevice(ctx), + "aws_iot_greengrass_deployment": tableAwsIotGreengrassDeployment(ctx), "aws_iot_thing": tableAwsIoTThing(ctx), "aws_iot_thing_group": tableAwsIoTThingGroup(ctx), - "aws_iot_thing_type": tableAwsIoTThingType(ctx), + "aws_iot_thing_type": tableAwsIoTThingType(ctx), "aws_kinesis_consumer": tableAwsKinesisConsumer(ctx), "aws_kinesis_firehose_delivery_stream": tableAwsKinesisFirehoseDeliveryStream(ctx), "aws_kinesis_stream": tableAwsKinesisStream(ctx), diff --git a/aws/service.go b/aws/service.go index 7bbe039b3..10a3718c4 100644 --- a/aws/service.go +++ b/aws/service.go @@ -74,6 +74,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/glacier" "github.com/aws/aws-sdk-go-v2/service/globalaccelerator" "github.com/aws/aws-sdk-go-v2/service/glue" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2" "github.com/aws/aws-sdk-go-v2/service/guardduty" "github.com/aws/aws-sdk-go-v2/service/health" "github.com/aws/aws-sdk-go-v2/service/iam" @@ -169,6 +170,7 @@ import ( glacierEndpoint "github.com/aws/aws-sdk-go/service/glacier" inspectorEndpoint "github.com/aws/aws-sdk-go/service/inspector" inspector2Endpoint "github.com/aws/aws-sdk-go/service/inspector2" + greengrassEndpoint "github.com/aws/aws-sdk-go/service/greengrassv2" iotEndpoint "github.com/aws/aws-sdk-go/service/iot" kafkaEndpoint "github.com/aws/aws-sdk-go/service/kafka" kinesisanalyticsv2Endpoint "github.com/aws/aws-sdk-go/service/kinesisanalyticsv2" @@ -869,6 +871,17 @@ func Inspector2Client(ctx context.Context, d *plugin.QueryData) (*inspector2.Cli return inspector2.NewFromConfig(*cfg), nil } +func IoTGreengrassClient(ctx context.Context, d *plugin.QueryData) (*greengrassv2.Client, error) { +cfg, err := getClientForQuerySupportedRegion(ctx, d, greengrassEndpoint.EndpointsID) + if err != nil { + return nil, err + } + if cfg == nil { + return nil, nil + } + return greengrassv2.NewFromConfig(*cfg), nil +} + func IoTClient(ctx context.Context, d *plugin.QueryData) (*iot.Client, error) { cfg, err := getClientForQuerySupportedRegion(ctx, d, iotEndpoint.EndpointsID) if err != nil { diff --git a/aws/table_aws_iot_greengrass_component.go b/aws/table_aws_iot_greengrass_component.go new file mode 100644 index 000000000..14fb0a405 --- /dev/null +++ b/aws/table_aws_iot_greengrass_component.go @@ -0,0 +1,197 @@ +package aws + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2/types" + + greengrassv1 "github.com/aws/aws-sdk-go/service/greengrassv2" + + "github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform" +) + +//// TABLE DEFINITION + +func tableAwsIotGreengrassComponent(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "aws_iot_greengrass_component", + Description: "AWS IoT Greengrass Component", + List: &plugin.ListConfig{ + Hydrate: listIoTGreengrassComponents, + Tags: map[string]string{"service": "greengrassv2", "action": "ListComponents"}, + }, + // The `get config` is not included here for several reasons: + // 1. The API only returns the recipe and recipeOutputFormat, without any additional information. + // 2. A specific version is required to make the API call, but we obtain the latest version through the list call. + // 3. Utilizing the GetComponent API as a hydrated call is a more effective approach. + HydrateConfig: []plugin.HydrateConfig{ + { + Func: getIoTGreengrassComponent, + Tags: map[string]string{"service": "greengrassv2", "action": "GetComponent"}, + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + }, + }, + GetMatrixItemFunc: SupportedRegionMatrix(greengrassv1.EndpointsID), + Columns: awsRegionalColumns([]*plugin.Column{ + { + Name: "component_name", + Description: "The name of the component.", + Type: proto.ColumnType_STRING, + }, + { + Name: "arn", + Description: "The ARN of the component.", + Type: proto.ColumnType_STRING, + }, + { + Name: "component_version_arn", + Description: "The ARN of the component version.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("LatestVersion.Arn"), + }, + { + Name: "component_version", + Description: "The version of the component.", + Type: proto.ColumnType_STRING, + Transform: transform.FromField("LatestVersion.ComponentVersion"), + }, + { + Name: "recipe", + Description: "The recipe of the component version.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassComponent, + }, + { + Name: "recipe_output_format", + Description: "The format of the recipe.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassComponent, + }, + + // JSON columns + { + Name: "latest_version", + Description: "The latest version of the component and its details.", + Type: proto.ColumnType_JSON, + }, + + // Steampipe standard columns + { + Name: "title", + Description: resourceInterfaceDescription("title"), + Type: proto.ColumnType_STRING, + Transform: transform.FromField("ComponentName"), + }, + { + Name: "tags", + Description: resourceInterfaceDescription("tags"), + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassComponent, + }, + { + Name: "akas", + Description: resourceInterfaceDescription("akas"), + Type: proto.ColumnType_JSON, + Transform: transform.FromField("Arn").Transform(transform.EnsureStringArray), + }, + }), + } +} + +//// LIST FUNCTION + +func listIoTGreengrassComponents(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + // Create Session + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_component.listIoTGreengrassComponents", "connection_error", err) + return nil, err + } + if svc == nil { + // Unsupported region, return no data + return nil, nil + } + + // Limiting the results + maxLimit := int32(250) + if d.QueryContext.Limit != nil { + limit := int32(*d.QueryContext.Limit) + if limit < maxLimit { + maxLimit = limit + } + } + + input := &greengrassv2.ListComponentsInput{ + MaxResults: aws.Int32(maxLimit), + } + + paginator := greengrassv2.NewListComponentsPaginator(svc, input, func(o *greengrassv2.ListComponentsPaginatorOptions) { + o.Limit = maxLimit + o.StopOnDuplicateToken = true + }) + + // List call + for paginator.HasMorePages() { + // apply rate limiting + d.WaitForListRateLimit(ctx) + + output, err := paginator.NextPage(ctx) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_component.listIoTGreengrassComponents", "api_error", err) + return nil, err + } + + for _, item := range output.Components { + d.StreamListItem(ctx, item) + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + + return nil, err +} + +//// HYDRATE FUNCTIONS + +func getIoTGreengrassComponent(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + arn := "" + componentVersion := "" + if h.Item != nil { + item := h.Item.(types.Component) + arn = *item.Arn + componentVersion = *item.LatestVersion.ComponentVersion + } + + // Empty check + if arn == "" || componentVersion == "" { + return nil, nil + } + + // Create service + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_component.getIoTGreengrassComponent", "connection_error", err) + return nil, err + } + + params := &greengrassv2.GetComponentInput{ + Arn: aws.String(arn + ":versions:" + componentVersion), + } + + resp, err := svc.GetComponent(ctx, params) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_component.getIoTGreengrassComponent", "api_error", err) + return nil, err + } + + return resp, nil +} diff --git a/aws/table_aws_iot_greengrass_core_device.go b/aws/table_aws_iot_greengrass_core_device.go new file mode 100644 index 000000000..a5108ebc7 --- /dev/null +++ b/aws/table_aws_iot_greengrass_core_device.go @@ -0,0 +1,189 @@ +package aws + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2/types" + + greengrassv1 "github.com/aws/aws-sdk-go/service/greengrassv2" + + "github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform" +) + +//// TABLE DEFINITION + +func tableAwsIotGreengrassCoreDevice(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "aws_iot_greengrass_core_device", + Description: "AWS IoT Greengrass Core Device", + Get: &plugin.GetConfig{ + KeyColumns: plugin.SingleColumn("core_device_thing_name"), + Hydrate: getIoTGreengrassCoreDevice, + Tags: map[string]string{"service": "greengrassv2", "action": "GetCoreDevice"}, + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + }, + List: &plugin.ListConfig{ + Hydrate: listIoTGreengrassCoreDevices, + Tags: map[string]string{"service": "greengrassv2", "action": "ListCoreDevices"}, + KeyColumns: plugin.KeyColumnSlice{ + {Name: "status", Require: plugin.Optional}, + }, + }, + HydrateConfig: []plugin.HydrateConfig{ + { + Func: getIoTGreengrassCoreDevice, + Tags: map[string]string{"service": "greengrassv2", "action": "GetCoreDevice"}, + }, + }, + GetMatrixItemFunc: SupportedRegionMatrix(greengrassv1.EndpointsID), + Columns: awsRegionalColumns([]*plugin.Column{ + { + Name: "core_device_thing_name", + Description: "The name of the core device. This is also the name of the IoT thing.", + Type: proto.ColumnType_STRING, + }, + { + Name: "architecture", + Description: "The computer architecture of the core device.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassCoreDevice, + }, + { + Name: "core_version", + Description: "The version of the IoT Greengrass Core software that the core device runs.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassCoreDevice, + }, + { + Name: "platform", + Description: "The operating system platform that the core device runs.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassCoreDevice, + }, + { + Name: "last_status_update_timestamp", + Description: "The time at which the core device's status last updated, expressed in ISO 8601 format.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "status", + Description: "The status of the core device. Core devices can have the following statuses HEALTHY, UNHEALTHY.", + Type: proto.ColumnType_STRING, + }, + + // Steampipe standard columns + { + Name: "title", + Description: resourceInterfaceDescription("title"), + Type: proto.ColumnType_STRING, + Transform: transform.FromField("CoreDeviceThingName"), + }, + { + Name: "tags", + Description: resourceInterfaceDescription("tags"), + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassCoreDevice, + }, + }), + } +} + +//// LIST FUNCTION + +func listIoTGreengrassCoreDevices(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + // Create Session + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_core_device.listIoTGreengrassCoreDevices", "connection_error", err) + return nil, err + } + if svc == nil { + // Unsupported region, return no data + return nil, nil + } + + // Limiting the results + maxLimit := int32(100) + if d.QueryContext.Limit != nil { + limit := int32(*d.QueryContext.Limit) + if limit < maxLimit { + maxLimit = limit + } + } + + input := &greengrassv2.ListCoreDevicesInput{ + MaxResults: aws.Int32(maxLimit), + } + if d.EqualsQualString("status") != "" { + input.Status = types.CoreDeviceStatus(d.EqualsQualString("status")) + } + + paginator := greengrassv2.NewListCoreDevicesPaginator(svc, input, func(o *greengrassv2.ListCoreDevicesPaginatorOptions) { + o.Limit = maxLimit + o.StopOnDuplicateToken = true + }) + + // List call + for paginator.HasMorePages() { + // apply rate limiting + d.WaitForListRateLimit(ctx) + + output, err := paginator.NextPage(ctx) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_core_device.listIoTGreengrassCoreDevices", "api_error", err) + return nil, err + } + + for _, item := range output.CoreDevices { + d.StreamListItem(ctx, item) + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + + return nil, err +} + +//// HYDRATE FUNCTIONS + +func getIoTGreengrassCoreDevice(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + coreDeviceThingName := "" + if h.Item != nil { + t := h.Item.(types.CoreDevice) + coreDeviceThingName = *t.CoreDeviceThingName + } else { + coreDeviceThingName = d.EqualsQualString("core_device_thing_name") + } + + if coreDeviceThingName == "" { + return nil, nil + } + + // Create service + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_core_device.getIoTGreengrassCoreDevice", "connection_error", err) + return nil, err + } + + params := &greengrassv2.GetCoreDeviceInput{ + CoreDeviceThingName: aws.String(coreDeviceThingName), + } + + resp, err := svc.GetCoreDevice(ctx, params) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_core_device.getIoTGreengrassCoreDevice", "api_error", err) + return nil, err + } + + return resp, nil +} diff --git a/aws/table_aws_iot_greengrass_deployment.go b/aws/table_aws_iot_greengrass_deployment.go new file mode 100644 index 000000000..ef8562159 --- /dev/null +++ b/aws/table_aws_iot_greengrass_deployment.go @@ -0,0 +1,232 @@ +package aws + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2" + "github.com/aws/aws-sdk-go-v2/service/greengrassv2/types" + + greengrassv1 "github.com/aws/aws-sdk-go/service/greengrassv2" + + "github.com/turbot/steampipe-plugin-sdk/v5/grpc/proto" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin" + "github.com/turbot/steampipe-plugin-sdk/v5/plugin/transform" +) + +//// TABLE DEFINITION + +func tableAwsIotGreengrassDeployment(_ context.Context) *plugin.Table { + return &plugin.Table{ + Name: "aws_iot_greengrass_deployment", + Description: "AWS IoT Greengrass Deployment", + Get: &plugin.GetConfig{ + KeyColumns: plugin.SingleColumn("deployment_id"), + Hydrate: getIoTGreengrassDeployment, + Tags: map[string]string{"service": "greengrassv2", "action": "GetDeployment"}, + IgnoreConfig: &plugin.IgnoreConfig{ + ShouldIgnoreErrorFunc: shouldIgnoreErrors([]string{"ResourceNotFoundException"}), + }, + }, + List: &plugin.ListConfig{ + Hydrate: listIoTGreengrassDeployments, + Tags: map[string]string{"service": "greengrassv2", "action": "ListDeployments"}, + KeyColumns: plugin.KeyColumnSlice{ + {Name: "parent_target_arn", Require: plugin.Optional}, + {Name: "target_arn", Require: plugin.Optional}, + }, + }, + HydrateConfig: []plugin.HydrateConfig{ + { + Func: getIoTGreengrassDeployment, + Tags: map[string]string{"service": "greengrassv2", "action": "GetDeployment"}, + }, + }, + GetMatrixItemFunc: SupportedRegionMatrix(greengrassv1.EndpointsID), + Columns: awsRegionalColumns([]*plugin.Column{ + { + Name: "deployment_name", + Description: "The name of the deployment.", + Type: proto.ColumnType_STRING, + }, + { + Name: "deployment_id", + Description: "The ID of the deployment.", + Type: proto.ColumnType_STRING, + }, + { + Name: "deployment_status", + Description: "The status of the deployment.", + Type: proto.ColumnType_STRING, + }, + { + Name: "is_latest_for_target", + Description: "Whether or not the deployment is the latest revision for its target.", + Type: proto.ColumnType_BOOL, + }, + { + Name: "creation_timestamp", + Description: "The time at which the deployment was created, expressed in ISO 8601 format.", + Type: proto.ColumnType_TIMESTAMP, + }, + { + Name: "parent_target_arn", + Description: "The parent deployment's target ARN within a subdeployment.", + Type: proto.ColumnType_STRING, + }, + { + Name: "revision_id", + Description: "The revision number of the deployment.", + Type: proto.ColumnType_STRING, + }, + { + Name: "target_arn", + Description: "The ARN of the target IoT thing or thing group. When creating a subdeployment, the targetARN can only be a thing group.", + Type: proto.ColumnType_STRING, + }, + { + Name: "iot_job_arn", + Description: "The ARN of the IoT job that applies the deployment to target devices.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassDeployment, + }, + { + Name: "iot_job_id", + Description: "The ID of the IoT job that applies the deployment to target devices.", + Type: proto.ColumnType_STRING, + Hydrate: getIoTGreengrassDeployment, + }, + + // JSON fields + { + Name: "components", + Description: "The components to deploy. This is a dictionary, where each key is the name of a component, and each key's value is the version and configuration to deploy for that component.", + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassDeployment, + }, + { + Name: "deployment_policies", + Description: "The deployment policies for the deployment. These policies define how the deployment updates components and handles failure.", + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassDeployment, + }, + { + Name: "iot_job_configuration", + Description: " The job configuration for the deployment configuration. The job configuration specifies the rollout, timeout, and stop configurations for the deployment configuration.", + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassDeployment, + }, + + // Steampipe standard columns + { + Name: "title", + Description: resourceInterfaceDescription("title"), + Type: proto.ColumnType_STRING, + Transform: transform.FromField("DeploymentName"), + }, + { + Name: "tags", + Description: resourceInterfaceDescription("tags"), + Type: proto.ColumnType_JSON, + Hydrate: getIoTGreengrassDeployment, + }, + }), + } +} + +//// LIST FUNCTION + +func listIoTGreengrassDeployments(ctx context.Context, d *plugin.QueryData, _ *plugin.HydrateData) (interface{}, error) { + // Create Session + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_deployment.listIoTGreengrassDeployments", "connection_error", err) + return nil, err + } + if svc == nil { + // Unsupported region, return no data + return nil, nil + } + + // Limiting the results + maxLimit := int32(100) + if d.QueryContext.Limit != nil { + limit := int32(*d.QueryContext.Limit) + if limit < maxLimit { + maxLimit = limit + } + } + + input := &greengrassv2.ListDeploymentsInput{ + MaxResults: aws.Int32(maxLimit), + } + if d.EqualsQualString("target_arn") != "" { + input.TargetArn = aws.String(d.EqualsQualString("target_arn")) + } + if d.EqualsQualString("parent_target_arn") != "" { + input.ParentTargetArn = aws.String(d.EqualsQualString("parent_target_arn")) + } + + paginator := greengrassv2.NewListDeploymentsPaginator(svc, input, func(o *greengrassv2.ListDeploymentsPaginatorOptions) { + o.Limit = maxLimit + o.StopOnDuplicateToken = true + }) + + // List call + for paginator.HasMorePages() { + // apply rate limiting + d.WaitForListRateLimit(ctx) + + output, err := paginator.NextPage(ctx) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_deployment.listIoTGreengrassDeployments", "api_error", err) + return nil, err + } + + for _, item := range output.Deployments { + d.StreamListItem(ctx, item) + + // Context can be cancelled due to manual cancellation or the limit has been hit + if d.RowsRemaining(ctx) == 0 { + return nil, nil + } + } + } + + return nil, err +} + +//// HYDRATE FUNCTIONS + +func getIoTGreengrassDeployment(ctx context.Context, d *plugin.QueryData, h *plugin.HydrateData) (interface{}, error) { + deploymentId := "" + if h.Item != nil { + t := h.Item.(types.Deployment) + deploymentId = *t.DeploymentId + } else { + deploymentId = d.EqualsQualString("deployment_id") + } + + if deploymentId == "" { + return nil, nil + } + + // Create service + svc, err := IoTGreengrassClient(ctx, d) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_deployment.getIoTGreengrassDeployment", "connection_error", err) + return nil, err + } + + params := &greengrassv2.GetDeploymentInput{ + DeploymentId: aws.String(deploymentId), + } + + resp, err := svc.GetDeployment(ctx, params) + if err != nil { + plugin.Logger(ctx).Error("aws_iot_greengrass_deployment.getIoTGreengrassDeployment", "api_error", err) + return nil, err + } + + return resp, nil +} diff --git a/docs/tables/aws_iot_greengrass_component.md b/docs/tables/aws_iot_greengrass_component.md new file mode 100644 index 000000000..7b88bbee0 --- /dev/null +++ b/docs/tables/aws_iot_greengrass_component.md @@ -0,0 +1,91 @@ +--- +title: "Steampipe Table: aws_iot_greengrass_component - Query AWS IoT Greengrass Components using SQL" +description: "Allows users to query AWS IoT Greengrass Components. This table provides information about Greengrass Components, which are software modules deployed to Greengrass core devices. Components can represent applications, runtime installers, libraries, or any code that runs on a device. Users can define components with dependencies, and Greengrass deploys only the required software modules when deploying to devices." +--- + +# Table: aws_iot_greengrass_component - Query AWS IoT Greengrass Components using SQL + +AWS IoT Greengrass components are software modules that you deploy to Greengrass core devices. Components can represent applications, runtime installers, libraries, or any code that you would run on a device. You can define components that depend on other components. For example, you might define a component that installs Python, and then define that component as a dependency of your components that run Python applications. When you deploy your components to your fleets of devices, Greengrass deploys only the software modules that your devices require. + +## Table Usage Guide + +The `aws_iot_greengrass_component` table in Steampipe enables users to query information about AWS IoT Greengrass Components. This includes details such as component name, ARN, recipe, and recipe output format. Users can also retrieve the latest version details of components, filter components by tags, and gain insights into component dependencies. + +## Examples + +### Basic info +Retrieve basic information about Greengrass Components, such as their names, ARNs, recipes, and recipe output formats. This query provides an overview of the components in your environment. + +```sql+postgres +select + component_name, + arn, + recipe, + recipe_output_format +from + aws_iot_greengrass_component; +``` + +```sql+sqlite +select + component_name, + arn, + recipe, + recipe_output_format +from + aws_iot_greengrass_component; +``` + +### Get the latest version details of components +Retrieve the latest version details of Greengrass Components, including the ARN, component version, description, creation timestamp, supported platforms, and publisher. This query helps you stay up-to-date with the latest component versions. + +```sql+postgres +select + component_name, + latest_version ->> 'Arn' as latest_version_arn, + latest_version ->> 'ComponentVersion' as component_version, + latest_version ->> 'Description' as description, + latest_version ->> 'CreationTimestamp' as creation_timestamp, + latest_version -> 'Platforms' as platforms, + latest_version ->> 'Publisher' as publisher +from + aws_iot_greengrass_component; +``` + +```sql+sqlite +select + component_name, + json_extract(latest_version, '$.Arn') as latest_version_arn, + json_extract(latest_version, '$.ComponentVersion') as component_version, + json_extract(latest_version, '$.Description') as description, + json_extract(latest_version, '$.CreationTimestamp') as creation_timestamp, + json_extract(latest_version, '$.Platforms') as platforms, + json_extract(latest_version, '$.Publisher') as publisher +from + aws_iot_greengrass_component; +``` + +### Filter the components by tag +Filter Greengrass Components based on their tags. In this example, components with a missing 'owner' tag are retrieved. This query allows you to categorize and manage components effectively. + +```sql+postgres +select + component_name, + arn, + recipe +from + aws_iot_greengrass_component +where + tags -> 'owner' is null; +``` + +```sql+sqlite +select + component_name, + arn, + recipe +from + aws_iot_greengrass_component +where + json_extract(tags, '$.owner') is null; +``` diff --git a/docs/tables/aws_iot_greengrass_core_device.md b/docs/tables/aws_iot_greengrass_core_device.md new file mode 100644 index 000000000..c6628d441 --- /dev/null +++ b/docs/tables/aws_iot_greengrass_core_device.md @@ -0,0 +1,93 @@ +--- +title: "Steampipe Table: aws_iot_greengrass_core_device - Query AWS IoT Greengrass Core Devices using SQL" +description: "Allows users to query AWS IoT Greengrass Core Devices. This table provides information about Greengrass Core Devices within AWS IoT Greengrass, enabling users to gather insights on core devices, including their thing name, architecture, core version, and platform." +--- + +# Table: aws_iot_greengrass_core_device - Query AWS IoT Greengrass Core Devices using SQL + +A Greengrass core device is a fundamental component that runs the AWS IoT Greengrass Core software. This software allows the core device to establish direct communication with AWS IoT Core and the AWS IoT Greengrass service. Each core device possesses its unique device certificate for authentication with AWS IoT Core. Additionally, core devices have a device shadow and are registered in the AWS IoT Core registry. Greengrass core devices operate a local Lambda runtime, deployment agent, and IP address tracker. The IP address tracker sends IP address information to the AWS IoT Greengrass service, enabling client devices to automatically discover their group and core connection information. + +## Table Usage Guide + +The `aws_iot_greengrass_core_device` table in Steampipe provides IoT engineers and DevOps professionals with the ability to query specific details about AWS IoT Greengrass Core Devices. This includes essential information like core device thing name, architecture, core version, and platform. You can use this table to monitor the health and status of Greengrass core devices, identify unhealthy devices, and filter devices by their platform for efficient management. + +## Examples + +### Basic info +Retrieve basic information about Greengrass Core Devices, such as their thing names, architecture, core versions, and platforms. This query provides an overview of the core devices in your environment. + +```sql+postgres +select + core_device_thing_name, + architecture, + core_version, + platform +from + aws_iot_greengrass_core_device; +``` + +```sql+sqlite +select + core_device_thing_name, + architecture, + core_version, + platform +from + aws_iot_greengrass_core_device; +``` + +### List devices that are unhealthy +Identify Greengrass Core Devices that are marked as 'UNHEALTHY' in their status. This helps you monitor and manage devices with potential issues. + +```sql+postgres +select + core_device_thing_name, + architecture, + core_version, + last_status_update_timestamp, + status +from + aws_iot_greengrass_core_device +where + status = 'UNHEALTHY'; +``` + +```sql+sqlite +select + core_device_thing_name, + architecture, + core_version, + last_status_update_timestamp, + status +from + aws_iot_greengrass_core_device +where + status = 'UNHEALTHY'; +``` + +### List devices by platform +Filter Greengrass Core Devices by platform, focusing on devices with a platform that matches 'linux.' This query allows you to group and manage devices based on their platform type. + +```sql+postgres +select + core_device_thing_name, + architecture, + core_version, + platform +from + aws_iot_greengrass_core_device +where + platform ILIKE 'linux'; +``` + +```sql+sqlite +select + core_device_thing_name, + architecture, + core_version, + platform +from + aws_iot_greengrass_core_device +where + platform LIKE 'linux'; +``` diff --git a/docs/tables/aws_iot_greengrass_deployment.md b/docs/tables/aws_iot_greengrass_deployment.md new file mode 100644 index 000000000..87ea18eb8 --- /dev/null +++ b/docs/tables/aws_iot_greengrass_deployment.md @@ -0,0 +1,191 @@ +--- +title: "Steampipe Table: aws_iot_greengrass_deployment - Query AWS IoT Greengrass Deployments using SQL" +description: "Allows users to query AWS IoT Greengrass Deployments. This table provides information about Greengrass Deployments within AWS IoT Greengrass, enabling users to gather insights on deployments such as deployment name, ID, creation timestamp, and more." +--- + +# Table: aws_iot_greengrass_deployment - Query AWS IoT Greengrass Deployments using SQL + +The AWS IoT Greengrass Deployment is a feature within the AWS IoT Greengrass service that manages the deployment of software to IoT devices. Each core device runs the components of the deployments for that device. A new deployment to the same target overwrites the previous deployment to the target. + +When revising a deployment for a target, it replaces the components from the previous revision with the components in the new revision. For instance, if you initially deploy certain components to a group and later create another deployment for the same group with different components, the core devices in that group will run the new set of components. + +## Table Usage Guide + +The `aws_iot_greengrass_deployment` table in Steampipe enables you, as an IoT engineer or DevOps professional, to query deployment-specific details within AWS IoT Greengrass. This includes information like deployment name, ID, whether it's the latest for the target, creation timestamp, and associated target ARNs. You can use this table to monitor and manage deployments, ensuring that your IoT devices are running the desired software configurations and versions. + +## Examples + +### Basic info +Query basic information about Greengrass deployments, such as their names, IDs, and associated target ARNs. This is useful for a quick overview of the deployments in your environment. + +```sql+postgres +select + deployment_name, + deployment_id, + is_latest_for_target, + creation_timestamp, + parent_target_arn, + target_arn +from + aws_iot_greengrass_deployment; +``` + +```sql+sqlite +select + deployment_name, + deployment_id, + is_latest_for_target, + creation_timestamp, + parent_target_arn, + target_arn +from + aws_iot_greengrass_deployment; +``` + +### List deployments created in the last 30 days +Identify recent deployments to manage and monitor new changes in your IoT environment. + +```sql+postgres +select + deployment_name, + deployment_id, + is_latest_for_target, + creation_timestamp, + target_arn +from + aws_iot_greengrass_deployment +where + creation_timestamp >= now() - interval '30' day; +``` + +```sql+sqlite +select + deployment_name, + deployment_id, + is_latest_for_target, + creation_timestamp, + target_arn +from + aws_iot_greengrass_deployment +where + creation_timestamp >= datetime('now', '-30 day'); +``` + +### List deployments that are the latest revision for its target +Focus on the most current deployments for each target to ensure up-to-date configuration and software. + +```sql+postgres +select + deployment_name, + deployment_id, + is_latest_for_target, + revision_id, + iot_job_arn, + iot_job_id +from + aws_iot_greengrass_deployment +where + is_latest_for_target; +``` + +```sql+sqlite +select + deployment_name, + deployment_id, + is_latest_for_target, + revision_id, + iot_job_arn, + iot_job_id +from + aws_iot_greengrass_deployment +where + is_latest_for_target; +``` + +### Get deployment policy details of the deployments +Examine the specific policies associated with each deployment to understand how they are configured and managed. + +```sql+postgres +select + deployment_name, + deployment_policies -> 'ComponentUpdatePolicy' as component_update_policy, + deployment_policies -> 'ConfigurationValidationPolicy' as configuration_validation_policy, + deployment_policies -> 'FailureHandlingPolicy' as failure_handling_policy +from + aws_iot_greengrass_deployment +where + is_latest_for_target; +``` + +```sql+sqlite +select + deployment_name, + json_extract(deployment_policies, '$.ComponentUpdatePolicy') as component_update_policy, + json_extract(deployment_policies, '$.ConfigurationValidationPolicy') as configuration_validation_policy, + json_extract(deployment_policies, '$.FailureHandlingPolicy') as failure_handling_policy +from + aws_iot_greengrass_deployment +where + is_latest_for_target; +``` + +### Get IoT job configuration details of deployments +Review the configurations related to IoT jobs associated with the deployments for detailed insight into their execution and management. + +```sql+postgres +select + deployment_name, + iot_job_configuration -> 'AbortConfig' as abort_config, + iot_job_configuration -> 'JobExecutionsRolloutConfig' as job_executions_rollout_config, + iot_job_configuration -> 'TimeoutConfig' as timeout_config +from + aws_iot_greengrass_deployment +where + is_latest_for_target +``` + +```sql+sqlite +select + deployment_name, + json_extract(iot_job_configuration, '$.AbortConfig') as abort_config, + json_extract(iot_job_configuration, '$.JobExecutionsRolloutConfig') as job_executions_rollout_config, + json_extract(iot_job_configuration, '$.TimeoutConfig') as timeout_config +from + aws_iot_greengrass_deployment +where + is_latest_for_target; +``` + +### Get IoT thing group details of deployments +Link deployments to specific IoT thing groups for a comprehensive understanding of which groups are affected by which deployments. + +```sql+postgres +select + d.deployment_name, + d.target_arn as thing_group_arn, + d.parent_target_arn, + g.group_name, + g.status as thing_group_status, + g.query_string, + g.parent_group_name +from + aws_iot_greengrass_deployment as d, + aws_iot_thing_group as g +where + g.arn = d.target_arn; +``` + +```sql+sqlite +select + d.deployment_name, + d.target_arn as thing_group_arn, + d.parent_target_arn, + g.group_name, + g.status as thing_group_status, + g.query_string, + g.parent_group_name +from + aws_iot_greengrass_deployment as d +join + aws_iot_thing_group as g on g.arn = d.target_arn; +``` diff --git a/go.mod b/go.mod index c2d4528ce..acce8e7ca 100644 --- a/go.mod +++ b/go.mod @@ -143,6 +143,7 @@ require golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.21 // indirect + github.com/aws/aws-sdk-go-v2/service/greengrassv2 v1.31.3 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect diff --git a/go.sum b/go.sum index 75475d0a7..29f450185 100644 --- a/go.sum +++ b/go.sum @@ -353,6 +353,8 @@ github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.23.1 h1:E48tPAIKptyIb8 github.com/aws/aws-sdk-go-v2/service/globalaccelerator v1.23.1/go.mod h1:6morRSCgJD400qAu5DCEtvoaAC1owS5t6oq8ddLLwxw= github.com/aws/aws-sdk-go-v2/service/glue v1.78.0 h1:B7NIez2lCPjP9F/ucgjJSZ9JWHBO9KIeLAxn39G8mLA= github.com/aws/aws-sdk-go-v2/service/glue v1.78.0/go.mod h1:maQT+ebL6UAFXYp8fJlK2Dv/s42LZuggi2l6pVeE2B4= +github.com/aws/aws-sdk-go-v2/service/greengrassv2 v1.31.3 h1:qWI4VrTRdKSmM8mo8tE4mOwRagKeuA1EW0GKnOTt8Cg= +github.com/aws/aws-sdk-go-v2/service/greengrassv2 v1.31.3/go.mod h1:V3fvC4aMH1y21pfystBRewJVaQLUmroX/fQWBG26mqY= github.com/aws/aws-sdk-go-v2/service/guardduty v1.41.1 h1:HbecqrH+phcfa2XVmFlJEjEFM2FXJFhAtqLBq+k0q1I= github.com/aws/aws-sdk-go-v2/service/guardduty v1.41.1/go.mod h1:qXyWkjk60YMVbYEBkQBYqk7d4WJTEPnQzxbWWQ5d6pI= github.com/aws/aws-sdk-go-v2/service/health v1.24.4 h1:5QROeJylnNdBQxxYn4BPpbgoo3nXT+SMG3KvFd71O4s=