diff --git a/plugins/source/aws/docs/tables/README.md b/plugins/source/aws/docs/tables/README.md index 6089a74828090d..0c5bbf7de4346c 100644 --- a/plugins/source/aws/docs/tables/README.md +++ b/plugins/source/aws/docs/tables/README.md @@ -161,6 +161,9 @@ - [aws_ec2_reserved_instances](aws_ec2_reserved_instances.md) - [aws_ec2_route_tables](aws_ec2_route_tables.md) - [aws_ec2_security_groups](aws_ec2_security_groups.md) +- [aws_ec2_spot_fleet_requests](aws_ec2_spot_fleet_requests.md) + - [aws_ec2_spot_fleet_instances](aws_ec2_spot_fleet_instances.md) +- [aws_ec2_spot_instance_requests](aws_ec2_spot_instance_requests.md) - [aws_ec2_subnets](aws_ec2_subnets.md) - [aws_ec2_transit_gateways](aws_ec2_transit_gateways.md) - [aws_ec2_transit_gateway_attachments](aws_ec2_transit_gateway_attachments.md) diff --git a/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_instances.md b/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_instances.md new file mode 100644 index 00000000000000..0239365085fa5a --- /dev/null +++ b/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_instances.md @@ -0,0 +1,26 @@ +# Table: aws_ec2_spot_fleet_instances + +https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ActiveInstance.html + +The primary key for this table is **arn**. + +## Relations + +This table depends on [aws_ec2_spot_fleet_requests](aws_ec2_spot_fleet_requests.md). + +## Columns + +| Name | Type | +| ------------- | ------------- | +|_cq_source_name|String| +|_cq_sync_time|Timestamp| +|_cq_id|UUID| +|_cq_parent_id|UUID| +|account_id|String| +|region|String| +|arn (PK)|String| +|spot_fleet_request_id|String| +|instance_health|String| +|instance_id|String| +|instance_type|String| +|spot_instance_request_id|String| \ No newline at end of file diff --git a/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_requests.md b/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_requests.md new file mode 100644 index 00000000000000..01386d77ad6469 --- /dev/null +++ b/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_requests.md @@ -0,0 +1,27 @@ +# Table: aws_ec2_spot_fleet_requests + +https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotFleetRequestConfig.html + +The composite primary key for this table is (**account_id**, **region**, **spot_fleet_request_id**). + +## Relations + +The following tables depend on aws_ec2_spot_fleet_requests: + - [aws_ec2_spot_fleet_instances](aws_ec2_spot_fleet_instances.md) + +## Columns + +| Name | Type | +| ------------- | ------------- | +|_cq_source_name|String| +|_cq_sync_time|Timestamp| +|_cq_id|UUID| +|_cq_parent_id|UUID| +|account_id (PK)|String| +|region (PK)|String| +|tags|JSON| +|activity_status|String| +|create_time|Timestamp| +|spot_fleet_request_config|JSON| +|spot_fleet_request_id (PK)|String| +|spot_fleet_request_state|String| \ No newline at end of file diff --git a/plugins/source/aws/docs/tables/aws_ec2_spot_instance_requests.md b/plugins/source/aws/docs/tables/aws_ec2_spot_instance_requests.md new file mode 100644 index 00000000000000..80bd49def7f5b0 --- /dev/null +++ b/plugins/source/aws/docs/tables/aws_ec2_spot_instance_requests.md @@ -0,0 +1,35 @@ +# Table: aws_ec2_spot_instance_requests + +https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotInstanceRequest.html + +The composite primary key for this table is (**account_id**, **region**, **spot_instance_request_id**). + +## Columns + +| Name | Type | +| ------------- | ------------- | +|_cq_source_name|String| +|_cq_sync_time|Timestamp| +|_cq_id|UUID| +|_cq_parent_id|UUID| +|account_id (PK)|String| +|region (PK)|String| +|tags|JSON| +|actual_block_hourly_price|String| +|availability_zone_group|String| +|block_duration_minutes|Int| +|create_time|Timestamp| +|fault|JSON| +|instance_id|String| +|instance_interruption_behavior|String| +|launch_group|String| +|launch_specification|JSON| +|launched_availability_zone|String| +|product_description|String| +|spot_instance_request_id (PK)|String| +|spot_price|String| +|state|String| +|status|JSON| +|type|String| +|valid_from|Timestamp| +|valid_until|Timestamp| \ No newline at end of file diff --git a/plugins/source/aws/resources/plugin/tables.go b/plugins/source/aws/resources/plugin/tables.go index ebc48fed17a9b6..d89b31b6d3539e 100644 --- a/plugins/source/aws/resources/plugin/tables.go +++ b/plugins/source/aws/resources/plugin/tables.go @@ -205,6 +205,8 @@ func tables() []*schema.Table { ec2.ReservedInstances(), ec2.RouteTables(), ec2.SecurityGroups(), + ec2.SpotFleetRequests(), + ec2.SpotInstanceRequests(), ec2.Subnets(), ec2.TransitGateways(), ec2.VpcEndpoints(), diff --git a/plugins/source/aws/resources/services/ec2/spot_fleet_instances.go b/plugins/source/aws/resources/services/ec2/spot_fleet_instances.go new file mode 100644 index 00000000000000..0d11ee6bb0fd25 --- /dev/null +++ b/plugins/source/aws/resources/services/ec2/spot_fleet_instances.go @@ -0,0 +1,75 @@ +package ec2 + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/cloudquery/cloudquery/plugins/source/aws/client" + "github.com/cloudquery/plugin-sdk/schema" + "github.com/cloudquery/plugin-sdk/transformers" +) + +func spotFleetInstances() *schema.Table { + return &schema.Table{ + Name: "aws_ec2_spot_fleet_instances", + Description: `https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ActiveInstance.html`, + Resolver: fetchEC2SpotFleetInstances, + Multiplex: client.ServiceAccountRegionMultiplexer("ec2"), + Transform: transformers.TransformWithStruct(&types.ActiveInstance{}), + Columns: []schema.Column{ + client.DefaultAccountIDColumn(false), + client.DefaultRegionColumn(false), + { + Name: "arn", + Type: schema.TypeString, + Resolver: resolveActiveInstanceArn, + CreationOptions: schema.ColumnCreationOptions{ + PrimaryKey: true, + }, + }, + { + Name: "spot_fleet_request_id", + Type: schema.TypeString, + Resolver: schema.ParentColumnResolver("spot_fleet_request_id"), + }, + }, + } +} + +func fetchEC2SpotFleetInstances(ctx context.Context, meta schema.ClientMeta, parent *schema.Resource, res chan<- any) error { + p := parent.Item.(types.SpotFleetRequestConfig) + + config := ec2.DescribeSpotFleetInstancesInput{ + SpotFleetRequestId: p.SpotFleetRequestId, + } + c := meta.(*client.Client) + svc := c.Services().Ec2 + for { + output, err := svc.DescribeSpotFleetInstances(ctx, &config) + if err != nil { + return err + } + res <- output.ActiveInstances + if aws.ToString(output.NextToken) == "" { + break + } + config.NextToken = output.NextToken + } + return nil +} + +func resolveActiveInstanceArn(_ context.Context, meta schema.ClientMeta, resource *schema.Resource, c schema.Column) error { + cl := meta.(*client.Client) + item := resource.Item.(types.ActiveInstance) + a := arn.ARN{ + Partition: cl.Partition, + Service: "ec2", + Region: cl.Region, + AccountID: cl.AccountID, + Resource: "instance/" + aws.ToString(item.InstanceId), + } + return resource.Set(c.Name, a.String()) +} diff --git a/plugins/source/aws/resources/services/ec2/spot_fleet_requests.go b/plugins/source/aws/resources/services/ec2/spot_fleet_requests.go new file mode 100644 index 00000000000000..e1b904ff383f83 --- /dev/null +++ b/plugins/source/aws/resources/services/ec2/spot_fleet_requests.go @@ -0,0 +1,47 @@ +package ec2 + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/cloudquery/cloudquery/plugins/source/aws/client" + "github.com/cloudquery/plugin-sdk/schema" + "github.com/cloudquery/plugin-sdk/transformers" +) + +func SpotFleetRequests() *schema.Table { + return &schema.Table{ + Name: "aws_ec2_spot_fleet_requests", + Description: `https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotFleetRequestConfig.html`, + Resolver: fetchEC2SpotFleetRequests, + Multiplex: client.ServiceAccountRegionMultiplexer("ec2"), + Transform: transformers.TransformWithStruct(&types.SpotFleetRequestConfig{}, transformers.WithPrimaryKeys("SpotFleetRequestId")), + Columns: []schema.Column{ + client.DefaultAccountIDColumn(true), + client.DefaultRegionColumn(true), + { + Name: "tags", + Type: schema.TypeJSON, + Resolver: client.ResolveTags, + }, + }, + Relations: []*schema.Table{ + spotFleetInstances(), + }, + } +} + +func fetchEC2SpotFleetRequests(ctx context.Context, meta schema.ClientMeta, parent *schema.Resource, res chan<- any) error { + c := meta.(*client.Client) + svc := c.Services().Ec2 + pag := ec2.NewDescribeSpotFleetRequestsPaginator(svc, &ec2.DescribeSpotFleetRequestsInput{}) + for pag.HasMorePages() { + resp, err := pag.NextPage(ctx) + if err != nil { + return err + } + res <- resp.SpotFleetRequestConfigs + } + return nil +} diff --git a/plugins/source/aws/resources/services/ec2/spot_fleet_requests_mock_test.go b/plugins/source/aws/resources/services/ec2/spot_fleet_requests_mock_test.go new file mode 100644 index 00000000000000..73f17a6e4fd0fb --- /dev/null +++ b/plugins/source/aws/resources/services/ec2/spot_fleet_requests_mock_test.go @@ -0,0 +1,42 @@ +package ec2 + +import ( + "testing" + + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/cloudquery/cloudquery/plugins/source/aws/client" + "github.com/cloudquery/cloudquery/plugins/source/aws/client/mocks" + "github.com/cloudquery/plugin-sdk/faker" + "github.com/golang/mock/gomock" +) + +func buildSpotFleetRequests(t *testing.T, ctrl *gomock.Controller) client.Services { + m := mocks.NewMockEc2Client(ctrl) + item := types.SpotFleetRequestConfig{} + if err := faker.FakeObject(&item); err != nil { + t.Fatal(err) + } + + ins := types.ActiveInstance{} + if err := faker.FakeObject(&ins); err != nil { + t.Fatal(err) + } + + m.EXPECT().DescribeSpotFleetRequests(gomock.Any(), gomock.Any(), gomock.Any()).Return( + &ec2.DescribeSpotFleetRequestsOutput{ + SpotFleetRequestConfigs: []types.SpotFleetRequestConfig{item}, + }, nil) + + m.EXPECT().DescribeSpotFleetInstances(gomock.Any(), gomock.Any(), gomock.Any()).Return( + &ec2.DescribeSpotFleetInstancesOutput{ + ActiveInstances: []types.ActiveInstance{ins}, + }, nil) + return client.Services{ + Ec2: m, + } +} + +func TestSpotFleetRequests(t *testing.T) { + client.AwsMockTestHelper(t, SpotFleetRequests(), buildSpotFleetRequests, client.TestOptions{}) +} diff --git a/plugins/source/aws/resources/services/ec2/spot_instance_requests.go b/plugins/source/aws/resources/services/ec2/spot_instance_requests.go new file mode 100644 index 00000000000000..9c2db81ff179b1 --- /dev/null +++ b/plugins/source/aws/resources/services/ec2/spot_instance_requests.go @@ -0,0 +1,44 @@ +package ec2 + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/cloudquery/cloudquery/plugins/source/aws/client" + "github.com/cloudquery/plugin-sdk/schema" + "github.com/cloudquery/plugin-sdk/transformers" +) + +func SpotInstanceRequests() *schema.Table { + return &schema.Table{ + Name: "aws_ec2_spot_instance_requests", + Description: `https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_SpotInstanceRequest.html`, + Resolver: fetchEC2SpotInstanceRequests, + Multiplex: client.ServiceAccountRegionMultiplexer("ec2"), + Transform: transformers.TransformWithStruct(&types.SpotInstanceRequest{}, transformers.WithPrimaryKeys("SpotInstanceRequestId")), + Columns: []schema.Column{ + client.DefaultAccountIDColumn(true), + client.DefaultRegionColumn(true), + { + Name: "tags", + Type: schema.TypeJSON, + Resolver: client.ResolveTags, + }, + }, + } +} + +func fetchEC2SpotInstanceRequests(ctx context.Context, meta schema.ClientMeta, parent *schema.Resource, res chan<- any) error { + c := meta.(*client.Client) + svc := c.Services().Ec2 + pag := ec2.NewDescribeSpotInstanceRequestsPaginator(svc, &ec2.DescribeSpotInstanceRequestsInput{}) + for pag.HasMorePages() { + resp, err := pag.NextPage(ctx) + if err != nil { + return err + } + res <- resp.SpotInstanceRequests + } + return nil +} diff --git a/plugins/source/aws/resources/services/ec2/spot_instance_requests_mock_test.go b/plugins/source/aws/resources/services/ec2/spot_instance_requests_mock_test.go new file mode 100644 index 00000000000000..3d252fa3303756 --- /dev/null +++ b/plugins/source/aws/resources/services/ec2/spot_instance_requests_mock_test.go @@ -0,0 +1,33 @@ +package ec2 + +import ( + "testing" + + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/cloudquery/cloudquery/plugins/source/aws/client" + "github.com/cloudquery/cloudquery/plugins/source/aws/client/mocks" + "github.com/cloudquery/plugin-sdk/faker" + "github.com/golang/mock/gomock" +) + +func buildSpotInstanceRequests(t *testing.T, ctrl *gomock.Controller) client.Services { + m := mocks.NewMockEc2Client(ctrl) + item := types.SpotInstanceRequest{} + if err := faker.FakeObject(&item); err != nil { + t.Fatal(err) + } + + m.EXPECT().DescribeSpotInstanceRequests(gomock.Any(), gomock.Any(), gomock.Any()).Return( + &ec2.DescribeSpotInstanceRequestsOutput{ + SpotInstanceRequests: []types.SpotInstanceRequest{item}, + }, nil) + + return client.Services{ + Ec2: m, + } +} + +func TestSpotInstanceRequests(t *testing.T) { + client.AwsMockTestHelper(t, SpotInstanceRequests(), buildSpotInstanceRequests, client.TestOptions{}) +} diff --git a/website/pages/docs/plugins/sources/aws/tables.md b/website/pages/docs/plugins/sources/aws/tables.md index 0272ac4a37dc5f..e71bb06f6ef311 100644 --- a/website/pages/docs/plugins/sources/aws/tables.md +++ b/website/pages/docs/plugins/sources/aws/tables.md @@ -161,6 +161,9 @@ - [aws_ec2_reserved_instances](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_reserved_instances.md) - [aws_ec2_route_tables](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_route_tables.md) - [aws_ec2_security_groups](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_security_groups.md) +- [aws_ec2_spot_fleet_requests](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_requests.md) + - [aws_ec2_spot_fleet_instances](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_spot_fleet_instances.md) +- [aws_ec2_spot_instance_requests](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_spot_instance_requests.md) - [aws_ec2_subnets](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_subnets.md) - [aws_ec2_transit_gateways](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_transit_gateways.md) - [aws_ec2_transit_gateway_attachments](https://github.com/cloudquery/cloudquery/blob/main/plugins/source/aws/docs/tables/aws_ec2_transit_gateway_attachments.md)