mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-21 19:56:33 +00:00
feat: describe-account-attributes (#26)
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
# Hive Development Roadmap
|
||||
|
||||
## Known Bugs
|
||||
|
||||
- **QueryParamsToStruct does not match all AWS query param key formats**: The parser tries the Go field name (e.g. `AttributeNames.1`) and the SDK `locationName` tag (e.g. `attributeName.1`), but the AWS CLI sends PascalCase singular form (e.g. `AttributeName.1`). This causes list filters like `--attribute-names` on `describe-account-attributes` to be silently ignored. Affects any SDK field where the Go name, locationName, and wire format all differ. Fix in `hive/awsec2query/parser.go`.
|
||||
|
||||
## Update Jan 2026
|
||||
|
||||
### Big rocks:
|
||||
@@ -137,6 +141,12 @@ Instance `dmesg`:
|
||||
| `describe-regions` | *(returns configured region, endpoint, opt-in status from config — input params ignored)* | `--region-names`, `--filters`, `--all-regions`, `--dry-run` | None | Return configured region from hive init config with Endpoint and OptInStatus → local-only response, no NATS | 1. List all regions<br>2. Filter by region name<br>3. Verify endpoint URL returned<br>4. Verify OptInStatus returned | **DONE** |
|
||||
| `describe-availability-zones` | *(returns configured AZ, region, zone ID, state, opt-in status from config — input params ignored)* | `--zone-names`, `--filters`, `--all-availability-zones` | None | Return configured AZ from hive init config with zone ID, state, group name, network border group → local-only response, no NATS | 1. List all AZs<br>2. Filter by zone name<br>3. Verify zone state is available<br>4. Verify region name matches config | **DONE** |
|
||||
|
||||
### EC2 - Account Attributes
|
||||
|
||||
| Command | Implemented Flags | Missing Flags | Prerequisites | Basic Logic | Test Cases | Status |
|
||||
|---------|-------------------|---------------|---------------|-------------|------------|--------|
|
||||
| `describe-account-attributes` | *(returns all 6 hardcoded attributes — input filter parsed but not applied due to QueryParamsToStruct bug, see Known Bugs)* | `--attribute-names` (filter not working) | None | Gateway parses input → returns static account attributes: supported-platforms=VPC, default-vpc=none, max-instances=100, vpc-max-security-groups-per-interface=5, max-elastic-ips=5, vpc-max-elastic-ips=20 → local-only response, no NATS | 1. List all account attributes<br>2. Filter by attribute name (blocked by parser bug)<br>3. Verify all 6 attributes returned with correct values | **DONE** |
|
||||
|
||||
### EC2 - VPC Networking (Core)
|
||||
|
||||
Requires Open vSwitch (`apt install openvswitch-switch openvswitch-common`). Single AZ for Hive v1.
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/mulgadc/hive/hive/awsec2query"
|
||||
gateway_ec2_account "github.com/mulgadc/hive/hive/gateway/ec2/account"
|
||||
gateway_ec2_image "github.com/mulgadc/hive/hive/gateway/ec2/image"
|
||||
gateway_ec2_instance "github.com/mulgadc/hive/hive/gateway/ec2/instance"
|
||||
gateway_ec2_key "github.com/mulgadc/hive/hive/gateway/ec2/key"
|
||||
@@ -479,6 +480,28 @@ func (gw *GatewayConfig) EC2_Request(ctx *fiber.Ctx) error {
|
||||
return errors.New("failed to marshal response to XML")
|
||||
}
|
||||
|
||||
case "DescribeAccountAttributes":
|
||||
var input = &ec2.DescribeAccountAttributesInput{}
|
||||
err = awsec2query.QueryParamsToStruct(queryArgs, input)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
output, err := gateway_ec2_account.DescribeAccountAttributes(input)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert to XML
|
||||
payload := utils.GenerateXMLPayload("DescribeAccountAttributesResponse", output)
|
||||
xmlOutput, err = utils.MarshalToXML(payload)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("failed to marshal response to XML")
|
||||
}
|
||||
|
||||
default:
|
||||
err = errors.New("InvalidAction")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package gateway_ec2_account
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
)
|
||||
|
||||
// DescribeAccountAttributes returns static account attributes for the Hive platform
|
||||
func DescribeAccountAttributes(input *ec2.DescribeAccountAttributesInput) (*ec2.DescribeAccountAttributesOutput, error) {
|
||||
slog.Debug("DescribeAccountAttributes called")
|
||||
|
||||
// Build set of requested attribute names for filtering
|
||||
requestedAttrs := make(map[string]bool)
|
||||
for _, name := range input.AttributeNames {
|
||||
if name != nil {
|
||||
requestedAttrs[*name] = true
|
||||
}
|
||||
}
|
||||
|
||||
// If no specific attributes requested, return all
|
||||
returnAll := len(requestedAttrs) == 0
|
||||
|
||||
var accountAttributes []*ec2.AccountAttribute
|
||||
|
||||
// supported-platforms - VPC only (no EC2-Classic)
|
||||
if returnAll || requestedAttrs["supported-platforms"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("supported-platforms"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("VPC")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// default-vpc
|
||||
if returnAll || requestedAttrs["default-vpc"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("default-vpc"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("none")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// max-instances
|
||||
if returnAll || requestedAttrs["max-instances"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("max-instances"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("100")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// vpc-max-security-groups-per-interface
|
||||
if returnAll || requestedAttrs["vpc-max-security-groups-per-interface"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("vpc-max-security-groups-per-interface"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("5")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// max-elastic-ips
|
||||
if returnAll || requestedAttrs["max-elastic-ips"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("max-elastic-ips"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("5")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// vpc-max-elastic-ips
|
||||
if returnAll || requestedAttrs["vpc-max-elastic-ips"] {
|
||||
accountAttributes = append(accountAttributes, &ec2.AccountAttribute{
|
||||
AttributeName: aws.String("vpc-max-elastic-ips"),
|
||||
AttributeValues: []*ec2.AccountAttributeValue{
|
||||
{AttributeValue: aws.String("20")},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
output := &ec2.DescribeAccountAttributesOutput{
|
||||
AccountAttributes: accountAttributes,
|
||||
}
|
||||
|
||||
slog.Info("DescribeAccountAttributes completed", "attributeCount", len(accountAttributes))
|
||||
return output, nil
|
||||
}
|
||||
Reference in New Issue
Block a user