feat: add eks to aws coverage

This commit is contained in:
Julian Sommer
2026-09-14 11:30:55 +10:00
parent 1eccfded6e
commit 2265aee120
7 changed files with 104 additions and 1 deletions
+50
View File
@@ -10,6 +10,7 @@ Implemented means a modelled operation is registered to a real handler. Stub and
| ec2 | 2016-11-15 | 625 | 121 | 121 | 0 | 0 | 504 | 0 |
| ecr | 2015-09-21 | 47 | 39 | 19 | 13 | 7 | 11 | 3 |
| ecs | 2014-11-13 | 56 | 39 | 31 | 5 | 0 | 20 | 3 |
| eks | 2017-11-01 | 56 | 38 | 34 | 0 | 0 | 22 | 4 |
| elasticloadbalancingv2 | 2015-12-01 | 46 | 37 | 33 | 0 | 0 | 13 | 4 |
| iam | 2010-05-08 | 159 | 75 | 75 | 0 | 0 | 84 | 0 |
| rds | 2014-10-31 | 162 | 43 | 26 | 0 | 12 | 124 | 5 |
@@ -337,6 +338,55 @@ None.
`PollAssignments`, `ProvisionCapacity`, `ReportTaskGPU`
</details>
## eks
Implements **34 of 56** modelled operations (60.7%).
<details><summary>Implemented (34)</summary>
`AssociateAccessPolicy`, `AssociateIdentityProviderConfig`, `CreateAccessEntry`, `CreateAddon`, `CreateCluster`, `CreateNodegroup`, `DeleteAccessEntry`, `DeleteAddon`
`DeleteCluster`, `DeleteNodegroup`, `DescribeAccessEntry`, `DescribeAddon`, `DescribeAddonVersions`, `DescribeCluster`, `DescribeIdentityProviderConfig`, `DescribeNodegroup`
`DisassociateAccessPolicy`, `DisassociateIdentityProviderConfig`, `ListAccessEntries`, `ListAccessPolicies`, `ListAddons`, `ListAssociatedAccessPolicies`, `ListClusters`, `ListIdentityProviderConfigs`
`ListNodegroups`, `ListTagsForResource`, `TagResource`, `UntagResource`, `UpdateAccessEntry`, `UpdateAddon`, `UpdateClusterConfig`, `UpdateClusterVersion`
`UpdateNodegroupConfig`, `UpdateNodegroupVersion`
</details>
<details><summary>Missing from dispatch (22)</summary>
`AssociateEncryptionConfig`, `CreateEksAnywhereSubscription`, `CreateFargateProfile`, `CreatePodIdentityAssociation`, `DeleteEksAnywhereSubscription`, `DeleteFargateProfile`, `DeletePodIdentityAssociation`, `DeregisterCluster`
`DescribeAddonConfiguration`, `DescribeEksAnywhereSubscription`, `DescribeFargateProfile`, `DescribeInsight`, `DescribePodIdentityAssociation`, `DescribeUpdate`, `ListEksAnywhereSubscriptions`, `ListFargateProfiles`
`ListInsights`, `ListPodIdentityAssociations`, `ListUpdates`, `RegisterCluster`, `UpdateEksAnywhereSubscription`, `UpdatePodIdentityAssociation`
</details>
<details><summary>Registered stubs (0)</summary>
None.
</details>
<details><summary>Deliberately unsupported (0)</summary>
None.
</details>
<details><summary>Registered outside the pinned model (4)</summary>
`GetRecoveryDirective`, `ListInternalAddons`, `PublishInternal`, `WebhookTokenReview`
</details>
## elasticloadbalancingv2
+1
View File
@@ -14,6 +14,7 @@ var modelFiles = map[Service]string{
EC2: "models/apis/ec2/2016-11-15/api-2.json",
ECR: "models/apis/ecr/2015-09-21/api-2.json",
ECS: "models/apis/ecs/2014-11-13/api-2.json",
EKS: "models/apis/eks/2017-11-01/api-2.json",
ElasticLoadBalancingV2: "models/apis/elasticloadbalancingv2/2015-12-01/api-2.json",
IAM: "models/apis/iam/2010-05-08/api-2.json",
RDS: "models/apis/rds/2014-10-31/api-2.json",
+1
View File
@@ -28,6 +28,7 @@ const (
EC2 Service = "ec2"
ECR Service = "ecr"
ECS Service = "ecs"
EKS Service = "eks"
ElasticLoadBalancingV2 Service = "elasticloadbalancingv2"
IAM Service = "iam"
RDS Service = "rds"
+2 -1
View File
@@ -8,7 +8,7 @@ import (
)
func TestServices(t *testing.T) {
want := []Service{ACM, EC2, ECR, ECS, ElasticLoadBalancingV2, IAM, RDS, S3, STS}
want := []Service{ACM, EC2, ECR, ECS, EKS, ElasticLoadBalancingV2, IAM, RDS, S3, STS}
if got := Services(); !reflect.DeepEqual(got, want) {
t.Fatalf("Services() = %v, want %v", got, want)
}
@@ -24,6 +24,7 @@ func TestLoadAllModels(t *testing.T) {
EC2: {"2016-11-15", 625, 3198},
ECR: {"2015-09-21", 47, 330},
ECS: {"2014-11-13", 56, 400},
EKS: {"2017-11-01", 56, 298},
ElasticLoadBalancingV2: {"2015-12-01", 46, 357},
IAM: {"2010-05-08", 159, 497},
RDS: {"2014-10-31", 162, 745},
+12
View File
@@ -8,6 +8,7 @@ import (
"net/http"
"net/url"
"regexp"
"slices"
"github.com/mulgadc/bluebottle/pkg/auth"
"github.com/mulgadc/spinifex/spinifex/awserrors"
@@ -216,6 +217,17 @@ var eksRoutes = []eksRoute{
}},
}
// eksActionNames returns the distinct actions in eksRoutes in stable order.
// Deduplicated because an action may be reachable by more than one route.
func eksActionNames() []string {
names := make([]string, 0, len(eksRoutes))
for _, route := range eksRoutes {
names = append(names, route.action)
}
slices.Sort(names)
return slices.Compact(names)
}
// lookupEKSAction matches method+path against eksRoutes, returning the action,
// path params, and handler, or ("", nil, nil, false) on no match.
// path must be r.URL.EscapedPath(): ARNs in path segments are percent-encoded
+3
View File
@@ -41,6 +41,9 @@ func AWSOperationInventory() map[string]ServiceOperationInventory {
Registered: mapKeys(gateway_ecs.Actions),
Stubbed: gateway_ecs.StubbedActionNames(),
},
"eks": {
Registered: eksActionNames(),
},
"elasticloadbalancingv2": {
Registered: mapKeys(elbv2Actions),
},
+35
View File
@@ -1,8 +1,10 @@
package gateway
import (
"slices"
"testing"
"github.com/mulgadc/spinifex/internal/awsmodel"
"github.com/stretchr/testify/require"
)
@@ -23,6 +25,9 @@ func TestAWSOperationInventoryClassifiesDispatchers(t *testing.T) {
require.NotContains(t, inventory["ecr"].Stubbed, "DescribeRepositories")
require.Contains(t, inventory["ecr"].Unsupported, "StartImageScan")
require.Contains(t, inventory["eks"].Registered, "DescribeCluster")
require.NotContains(t, inventory["eks"].Stubbed, "DescribeCluster")
require.Contains(t, inventory["rds"].Registered, "CreateDBInstance")
require.NotContains(t, inventory["rds"].Unsupported, "CreateDBInstance")
require.Contains(t, inventory["rds"].Unsupported, "CreateDBCluster")
@@ -31,6 +36,36 @@ func TestAWSOperationInventoryClassifiesDispatchers(t *testing.T) {
require.False(t, hasS3, "S3 is delegated to Predastore, not dispatched here")
}
func TestAWSOperationInventoryMeasuresEKSAgainstTheModel(t *testing.T) {
inventory := AWSOperationInventory()
eks, err := awsmodel.CompareOperations(awsmodel.EKS, awsmodel.DispatchInventory{
Registered: inventory["eks"].Registered,
Stubbed: inventory["eks"].Stubbed,
Unsupported: inventory["eks"].Unsupported,
})
require.NoError(t, err)
require.Contains(t, eks.Implemented, "DescribeCluster")
// Spinifex-internal control-plane routes have no AWS model entry, so they
// must be reported as registered outside the pinned model.
require.ElementsMatch(t, []string{
"GetRecoveryDirective",
"ListInternalAddons",
"PublishInternal",
"WebhookTokenReview",
}, eks.Extra)
for _, action := range eks.Extra {
require.NotContains(t, eks.Implemented, action)
}
}
func TestEKSActionNamesAreSortedAndDistinct(t *testing.T) {
names := eksActionNames()
require.True(t, slices.IsSorted(names), "actions are not sorted: %v", names)
require.Len(t, slices.Compact(slices.Clone(names)), len(names), "actions contain duplicates: %v", names)
}
func TestAWSOperationInventoryStatusesAreDisjointSubsets(t *testing.T) {
for service, inventory := range AWSOperationInventory() {
t.Run(service, func(t *testing.T) {