diff --git a/plugin/plugin.go b/plugin/plugin.go index 8b62eb5..b7cf752 100644 --- a/plugin/plugin.go +++ b/plugin/plugin.go @@ -367,7 +367,7 @@ func (p *AwsPlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*p queries := make([]hostSetQuery, len(sets)) for i, set := range sets { - // Validate Id + // Validate Id since we use it in output if set.GetId() == "" { return nil, errors.New("set missing id") } @@ -377,7 +377,7 @@ func (p *AwsPlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*p return nil, errors.New("set missing attributes") } - input, err := buildDescribeInstancesInput(setAttrs, true) + input, err := buildDescribeInstancesInput(setAttrs, false) if err != nil { return nil, fmt.Errorf("error building DescribeInstances parameters for host set id %q: %w", set.GetId(), err) } @@ -411,6 +411,12 @@ func (p *AwsPlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*p return nil, fmt.Errorf("error processing host results for host set id %q: %w", query.Id, err) } + if host == nil { + // Nil result means we don't include the host (instance not + // running, or some other issue). + continue + } + queries[i].OutputHosts = append(queries[i].OutputHosts, host) maxLen++ // Increment maximum counter for allocation later } @@ -422,11 +428,12 @@ func (p *AwsPlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*p seenInstances := make(map[string]struct{}) for _, query := range queries { for _, host := range query.OutputHosts { - if _, ok := seenInstances[host.ExternalId]; !ok { + if _, ok := seenInstances[host.ExternalId]; ok { continue } hostResults = append(hostResults, host) + seenInstances[host.ExternalId] = struct{}{} } } @@ -706,7 +713,12 @@ func buildFilters(in *structpb.Struct) ([]*ec2.Filter, error) { return nil, err } + var foundStateFilter bool for k, v := range m { + if k == "instance-state-code" || k == "instance-state-name" { + foundStateFilter = true + } + w, ok := v.([]interface{}) if !ok { return nil, fmt.Errorf("unexpected type for filter values in %q: want array, got %T", k, v) @@ -728,6 +740,17 @@ func buildFilters(in *structpb.Struct) ([]*ec2.Filter, error) { }) } + if !foundStateFilter { + // if there is no explicit instance state filter, add the + // instance-state-name = ["running"] to the filter set. This + // ensures that we filter on running instances only at the API + // side, saving time when processing results. + filters = append(filters, &ec2.Filter{ + Name: aws.String("instance-state-name"), + Values: aws.StringSlice([]string{ec2.InstanceStateNameRunning}), + }) + } + return filters, nil } diff --git a/plugin/plugin_test.go b/plugin/plugin_test.go index 37f5aea..c3213b6 100644 --- a/plugin/plugin_test.go +++ b/plugin/plugin_test.go @@ -2,6 +2,7 @@ package plugin import ( "context" + "fmt" "os" "sort" "strings" @@ -143,8 +144,10 @@ func TestPlugin(t *testing.T) { cases := [][]string{ {"foo"}, - {"foo", "bar"}, {"bar"}, + {"baz"}, + {"foo", "bar"}, + {"foo", "baz"}, {"bar", "baz"}, {"foo", "bar", "baz"}, } @@ -527,6 +530,7 @@ func testPluginListHosts(ctx context.Context, t *testing.T, p *AwsPlugin, region }) require.NoError(err) sets[i] = &hostsets.HostSet{ + Id: fmt.Sprintf("hostset-%d", i), Attributes: setAttrs, } } @@ -567,7 +571,7 @@ func testPluginListHosts(ctx context.Context, t *testing.T, p *AwsPlugin, region // Compare require.Equal(expectedInstances, actualInstances) // Success - ids := make([]string, len(expectedInstances)) + ids := make([]string, 0, len(expectedInstances)) for k := range expectedInstances { ids = append(ids, k) } diff --git a/plugin/testdata/basic/vpc_ec2.tf b/plugin/testdata/basic/vpc_ec2.tf index dc78526..c612283 100644 --- a/plugin/testdata/basic/vpc_ec2.tf +++ b/plugin/testdata/basic/vpc_ec2.tf @@ -56,6 +56,7 @@ resource "aws_instance" "instances" { count = length(var.instance_tags) ami = data.aws_ami.ubuntu.id instance_type = "t3.nano" + subnet_id = aws_subnet.subnet.id tags = merge(var.instance_tags[count.index], var.project_path_tags) }