Compare commits

...

1 Commits

Author SHA1 Message Date
Julian Sommer a4f3fa6ee2 fix: list Bedrock and Bedrock Runtime operations in the AWS operation coverage inventory
Bedrock and Bedrock Runtime dispatch through REST route tables, so the
gateway inventory never named them and the coverage report left both
services out. Embed their pinned Smithy models, derive their operations
from the route tables, and publish a coverage page for each.

The request generator kept the constraint sites of a map key whose value
could not be generated, so a rejection case targeted a map that was not
in the request. Bedrock's document-valued maps are the first to hit it.
2026-11-02 14:37:28 +10:00
20 changed files with 616 additions and 18 deletions
+4 -2
View File
@@ -17,11 +17,13 @@ tags:
## Overview
The platform serves **392 operations** across the AWS APIs below. Every page names the operations its service implements from the pinned model, generated from the dispatch tables on each build rather than written by hand.
The platform serves **413 operations** across the AWS APIs below. Every page names the operations its service implements from the pinned model, generated from the dispatch tables on each build rather than written by hand.
| Service | Operations |
|---|---:|
| [ACM](/coverage/acm) | 9 |
| [Bedrock](/coverage/bedrock) | 16 |
| [Bedrock Runtime](/coverage/bedrock-runtime) | 5 |
| [EC2](/coverage/ec2) | 127 |
| [ECR](/coverage/ecr) | 23 |
| [ECS](/coverage/ecs) | 31 |
@@ -31,4 +33,4 @@ The platform serves **392 operations** across the AWS APIs below. Every page nam
| [RDS](/coverage/rds) | 27 |
| [S3](/coverage/s3) | 26 |
| [STS](/coverage/sts) | 5 |
| **Total** | **392** |
| **Total** | **413** |
+31
View File
@@ -0,0 +1,31 @@
---
title: "Bedrock Runtime API Coverage"
seoTitle: "Amazon Bedrock Runtime API Coverage — Spinifex Docs"
description: "The Amazon Bedrock Runtime API operations Spinifex implements, covering model invocation, the Converse API, streamed responses and standalone guardrail checks."
category: "Coverage"
sections:
- overview
tags:
- aws
- compatibility
- coverage
- bedrock
- ai
- inference
---
# Bedrock Runtime API Coverage
## Overview
Spinifex implements **5 operations** in the Bedrock Runtime `2023-09-30` API model.
### Operations
| Operation |
|---|
| `ApplyGuardrail` |
| `Converse` |
| `ConverseStream` |
| `InvokeModel` |
| `InvokeModelWithResponseStream` |
+42
View File
@@ -0,0 +1,42 @@
---
title: "Bedrock API Coverage"
seoTitle: "Amazon Bedrock API Coverage on Spinifex — Spinifex Docs"
description: "The Amazon Bedrock control-plane API operations Spinifex implements, covering foundation models, guardrails, provisioned throughput and invocation logging."
category: "Coverage"
sections:
- overview
tags:
- aws
- compatibility
- coverage
- bedrock
- ai
- models
---
# Bedrock API Coverage
## Overview
Spinifex implements **16 operations** in the Bedrock `2023-04-20` API model.
### Operations
| Operation |
|---|
| `CreateGuardrail` |
| `CreateGuardrailVersion` |
| `CreateProvisionedModelThroughput` |
| `DeleteGuardrail` |
| `DeleteModelInvocationLoggingConfiguration` |
| `DeleteProvisionedModelThroughput` |
| `GetFoundationModel` |
| `GetGuardrail` |
| `GetModelInvocationLoggingConfiguration` |
| `GetProvisionedModelThroughput` |
| `ListFoundationModels` |
| `ListGuardrails` |
| `ListProvisionedModelThroughputs` |
| `PutModelInvocationLoggingConfiguration` |
| `UpdateGuardrail` |
| `UpdateProvisionedModelThroughput` |
+297
View File
@@ -114,6 +114,303 @@
"extra": []
}
},
{
"service": "bedrock",
"api_version": "2023-04-20",
"opaque": false,
"note": "",
"operations": {
"modelled": [
"BatchDeleteAdvancedPromptOptimizationJob",
"BatchDeleteEvaluationJob",
"CancelAutomatedReasoningPolicyBuildWorkflow",
"CreateAdvancedPromptOptimizationJob",
"CreateAutomatedReasoningPolicy",
"CreateAutomatedReasoningPolicyTestCase",
"CreateAutomatedReasoningPolicyVersion",
"CreateCustomModel",
"CreateCustomModelDeployment",
"CreateEvaluationJob",
"CreateFoundationModelAgreement",
"CreateGuardrail",
"CreateGuardrailVersion",
"CreateInferenceProfile",
"CreateMarketplaceModelEndpoint",
"CreateModelCopyJob",
"CreateModelCustomizationJob",
"CreateModelImportJob",
"CreateModelInvocationJob",
"CreatePromptRouter",
"CreateProvisionedModelThroughput",
"DeleteAutomatedReasoningPolicy",
"DeleteAutomatedReasoningPolicyBuildWorkflow",
"DeleteAutomatedReasoningPolicyTestCase",
"DeleteCustomModel",
"DeleteCustomModelDeployment",
"DeleteEnforcedGuardrailConfiguration",
"DeleteFoundationModelAgreement",
"DeleteGuardrail",
"DeleteImportedModel",
"DeleteInferenceProfile",
"DeleteMarketplaceModelEndpoint",
"DeleteModelInvocationLoggingConfiguration",
"DeletePromptRouter",
"DeleteProvisionedModelThroughput",
"DeleteResourcePolicy",
"DeregisterMarketplaceModelEndpoint",
"ExportAutomatedReasoningPolicyVersion",
"GetAccountDataRetention",
"GetAdvancedPromptOptimizationJob",
"GetAutomatedReasoningPolicy",
"GetAutomatedReasoningPolicyAnnotations",
"GetAutomatedReasoningPolicyBuildWorkflow",
"GetAutomatedReasoningPolicyBuildWorkflowResultAssets",
"GetAutomatedReasoningPolicyNextScenario",
"GetAutomatedReasoningPolicyTestCase",
"GetAutomatedReasoningPolicyTestResult",
"GetCustomModel",
"GetCustomModelDeployment",
"GetEvaluationJob",
"GetFoundationModel",
"GetFoundationModelAvailability",
"GetGuardrail",
"GetImportedModel",
"GetInferenceProfile",
"GetMarketplaceModelEndpoint",
"GetModelCopyJob",
"GetModelCustomizationJob",
"GetModelImportJob",
"GetModelInvocationJob",
"GetModelInvocationLoggingConfiguration",
"GetPromptRouter",
"GetProvisionedModelThroughput",
"GetResourcePolicy",
"GetUseCaseForModelAccess",
"ListAdvancedPromptOptimizationJobs",
"ListAutomatedReasoningPolicies",
"ListAutomatedReasoningPolicyBuildWorkflows",
"ListAutomatedReasoningPolicyTestCases",
"ListAutomatedReasoningPolicyTestResults",
"ListCustomModelDeployments",
"ListCustomModels",
"ListEnforcedGuardrailsConfiguration",
"ListEvaluationJobs",
"ListFoundationModelAgreementOffers",
"ListFoundationModels",
"ListGuardrails",
"ListImportedModels",
"ListInferenceProfiles",
"ListMarketplaceModelEndpoints",
"ListModelCopyJobs",
"ListModelCustomizationJobs",
"ListModelImportJobs",
"ListModelInvocationJobs",
"ListPromptRouters",
"ListProvisionedModelThroughputs",
"ListTagsForResource",
"PutAccountDataRetention",
"PutEnforcedGuardrailConfiguration",
"PutModelInvocationLoggingConfiguration",
"PutResourcePolicy",
"PutUseCaseForModelAccess",
"RegisterMarketplaceModelEndpoint",
"StartAutomatedReasoningPolicyBuildWorkflow",
"StartAutomatedReasoningPolicyTestWorkflow",
"StopAdvancedPromptOptimizationJob",
"StopEvaluationJob",
"StopModelCustomizationJob",
"StopModelInvocationJob",
"TagResource",
"UntagResource",
"UpdateAutomatedReasoningPolicy",
"UpdateAutomatedReasoningPolicyAnnotations",
"UpdateAutomatedReasoningPolicyTestCase",
"UpdateCustomModelDeployment",
"UpdateGuardrail",
"UpdateMarketplaceModelEndpoint",
"UpdateProvisionedModelThroughput"
],
"registered": [
"CreateGuardrail",
"CreateGuardrailVersion",
"CreateProvisionedModelThroughput",
"DeleteGuardrail",
"DeleteModelInvocationLoggingConfiguration",
"DeleteProvisionedModelThroughput",
"GetFoundationModel",
"GetGuardrail",
"GetModelInvocationLoggingConfiguration",
"GetProvisionedModelThroughput",
"ListFoundationModels",
"ListGuardrails",
"ListProvisionedModelThroughputs",
"PutModelInvocationLoggingConfiguration",
"UpdateGuardrail",
"UpdateProvisionedModelThroughput"
],
"implemented": [
"CreateGuardrail",
"CreateGuardrailVersion",
"CreateProvisionedModelThroughput",
"DeleteGuardrail",
"DeleteModelInvocationLoggingConfiguration",
"DeleteProvisionedModelThroughput",
"GetFoundationModel",
"GetGuardrail",
"GetModelInvocationLoggingConfiguration",
"GetProvisionedModelThroughput",
"ListFoundationModels",
"ListGuardrails",
"ListProvisionedModelThroughputs",
"PutModelInvocationLoggingConfiguration",
"UpdateGuardrail",
"UpdateProvisionedModelThroughput"
],
"stubbed": [],
"unsupported": [],
"missing": [
"BatchDeleteAdvancedPromptOptimizationJob",
"BatchDeleteEvaluationJob",
"CancelAutomatedReasoningPolicyBuildWorkflow",
"CreateAdvancedPromptOptimizationJob",
"CreateAutomatedReasoningPolicy",
"CreateAutomatedReasoningPolicyTestCase",
"CreateAutomatedReasoningPolicyVersion",
"CreateCustomModel",
"CreateCustomModelDeployment",
"CreateEvaluationJob",
"CreateFoundationModelAgreement",
"CreateInferenceProfile",
"CreateMarketplaceModelEndpoint",
"CreateModelCopyJob",
"CreateModelCustomizationJob",
"CreateModelImportJob",
"CreateModelInvocationJob",
"CreatePromptRouter",
"DeleteAutomatedReasoningPolicy",
"DeleteAutomatedReasoningPolicyBuildWorkflow",
"DeleteAutomatedReasoningPolicyTestCase",
"DeleteCustomModel",
"DeleteCustomModelDeployment",
"DeleteEnforcedGuardrailConfiguration",
"DeleteFoundationModelAgreement",
"DeleteImportedModel",
"DeleteInferenceProfile",
"DeleteMarketplaceModelEndpoint",
"DeletePromptRouter",
"DeleteResourcePolicy",
"DeregisterMarketplaceModelEndpoint",
"ExportAutomatedReasoningPolicyVersion",
"GetAccountDataRetention",
"GetAdvancedPromptOptimizationJob",
"GetAutomatedReasoningPolicy",
"GetAutomatedReasoningPolicyAnnotations",
"GetAutomatedReasoningPolicyBuildWorkflow",
"GetAutomatedReasoningPolicyBuildWorkflowResultAssets",
"GetAutomatedReasoningPolicyNextScenario",
"GetAutomatedReasoningPolicyTestCase",
"GetAutomatedReasoningPolicyTestResult",
"GetCustomModel",
"GetCustomModelDeployment",
"GetEvaluationJob",
"GetFoundationModelAvailability",
"GetImportedModel",
"GetInferenceProfile",
"GetMarketplaceModelEndpoint",
"GetModelCopyJob",
"GetModelCustomizationJob",
"GetModelImportJob",
"GetModelInvocationJob",
"GetPromptRouter",
"GetResourcePolicy",
"GetUseCaseForModelAccess",
"ListAdvancedPromptOptimizationJobs",
"ListAutomatedReasoningPolicies",
"ListAutomatedReasoningPolicyBuildWorkflows",
"ListAutomatedReasoningPolicyTestCases",
"ListAutomatedReasoningPolicyTestResults",
"ListCustomModelDeployments",
"ListCustomModels",
"ListEnforcedGuardrailsConfiguration",
"ListEvaluationJobs",
"ListFoundationModelAgreementOffers",
"ListImportedModels",
"ListInferenceProfiles",
"ListMarketplaceModelEndpoints",
"ListModelCopyJobs",
"ListModelCustomizationJobs",
"ListModelImportJobs",
"ListModelInvocationJobs",
"ListPromptRouters",
"ListTagsForResource",
"PutAccountDataRetention",
"PutEnforcedGuardrailConfiguration",
"PutResourcePolicy",
"PutUseCaseForModelAccess",
"RegisterMarketplaceModelEndpoint",
"StartAutomatedReasoningPolicyBuildWorkflow",
"StartAutomatedReasoningPolicyTestWorkflow",
"StopAdvancedPromptOptimizationJob",
"StopEvaluationJob",
"StopModelCustomizationJob",
"StopModelInvocationJob",
"TagResource",
"UntagResource",
"UpdateAutomatedReasoningPolicy",
"UpdateAutomatedReasoningPolicyAnnotations",
"UpdateAutomatedReasoningPolicyTestCase",
"UpdateCustomModelDeployment",
"UpdateMarketplaceModelEndpoint"
],
"extra": []
}
},
{
"service": "bedrockruntime",
"api_version": "2023-09-30",
"opaque": false,
"note": "",
"operations": {
"modelled": [
"ApplyGuardrail",
"Converse",
"ConverseStream",
"CountTokens",
"GetAsyncInvoke",
"InvokeGuardrailChecks",
"InvokeModel",
"InvokeModelWithBidirectionalStream",
"InvokeModelWithResponseStream",
"ListAsyncInvokes",
"StartAsyncInvoke"
],
"registered": [
"ApplyGuardrail",
"Converse",
"ConverseStream",
"InvokeModel",
"InvokeModelWithResponseStream"
],
"implemented": [
"ApplyGuardrail",
"Converse",
"ConverseStream",
"InvokeModel",
"InvokeModelWithResponseStream"
],
"stubbed": [],
"unsupported": [],
"missing": [
"CountTokens",
"GetAsyncInvoke",
"InvokeGuardrailChecks",
"InvokeModelWithBidirectionalStream",
"ListAsyncInvokes",
"StartAsyncInvoke"
],
"extra": []
}
},
{
"service": "ec2",
"api_version": "2016-11-15",
+112
View File
@@ -44,6 +44,118 @@ Pinned model source: `github.com/aws/api-models-aws@9b1a49292744, 2026-09-25`.
- `UpdateAcmeEndpoint`
- `UpdateCertificateOptions`
## bedrock
`2023-04-20` — 16 of 108 modelled operations implemented (14.8%), 0 stubbed, 0 not applicable, 0 registered outside the pinned model.
### Not implemented
- `BatchDeleteAdvancedPromptOptimizationJob`
- `BatchDeleteEvaluationJob`
- `CancelAutomatedReasoningPolicyBuildWorkflow`
- `CreateAdvancedPromptOptimizationJob`
- `CreateAutomatedReasoningPolicy`
- `CreateAutomatedReasoningPolicyTestCase`
- `CreateAutomatedReasoningPolicyVersion`
- `CreateCustomModel`
- `CreateCustomModelDeployment`
- `CreateEvaluationJob`
- `CreateFoundationModelAgreement`
- `CreateInferenceProfile`
- `CreateMarketplaceModelEndpoint`
- `CreateModelCopyJob`
- `CreateModelCustomizationJob`
- `CreateModelImportJob`
- `CreateModelInvocationJob`
- `CreatePromptRouter`
- `DeleteAutomatedReasoningPolicy`
- `DeleteAutomatedReasoningPolicyBuildWorkflow`
- `DeleteAutomatedReasoningPolicyTestCase`
- `DeleteCustomModel`
- `DeleteCustomModelDeployment`
- `DeleteEnforcedGuardrailConfiguration`
- `DeleteFoundationModelAgreement`
- `DeleteImportedModel`
- `DeleteInferenceProfile`
- `DeleteMarketplaceModelEndpoint`
- `DeletePromptRouter`
- `DeleteResourcePolicy`
- `DeregisterMarketplaceModelEndpoint`
- `ExportAutomatedReasoningPolicyVersion`
- `GetAccountDataRetention`
- `GetAdvancedPromptOptimizationJob`
- `GetAutomatedReasoningPolicy`
- `GetAutomatedReasoningPolicyAnnotations`
- `GetAutomatedReasoningPolicyBuildWorkflow`
- `GetAutomatedReasoningPolicyBuildWorkflowResultAssets`
- `GetAutomatedReasoningPolicyNextScenario`
- `GetAutomatedReasoningPolicyTestCase`
- `GetAutomatedReasoningPolicyTestResult`
- `GetCustomModel`
- `GetCustomModelDeployment`
- `GetEvaluationJob`
- `GetFoundationModelAvailability`
- `GetImportedModel`
- `GetInferenceProfile`
- `GetMarketplaceModelEndpoint`
- `GetModelCopyJob`
- `GetModelCustomizationJob`
- `GetModelImportJob`
- `GetModelInvocationJob`
- `GetPromptRouter`
- `GetResourcePolicy`
- `GetUseCaseForModelAccess`
- `ListAdvancedPromptOptimizationJobs`
- `ListAutomatedReasoningPolicies`
- `ListAutomatedReasoningPolicyBuildWorkflows`
- `ListAutomatedReasoningPolicyTestCases`
- `ListAutomatedReasoningPolicyTestResults`
- `ListCustomModelDeployments`
- `ListCustomModels`
- `ListEnforcedGuardrailsConfiguration`
- `ListEvaluationJobs`
- `ListFoundationModelAgreementOffers`
- `ListImportedModels`
- `ListInferenceProfiles`
- `ListMarketplaceModelEndpoints`
- `ListModelCopyJobs`
- `ListModelCustomizationJobs`
- `ListModelImportJobs`
- `ListModelInvocationJobs`
- `ListPromptRouters`
- `ListTagsForResource`
- `PutAccountDataRetention`
- `PutEnforcedGuardrailConfiguration`
- `PutResourcePolicy`
- `PutUseCaseForModelAccess`
- `RegisterMarketplaceModelEndpoint`
- `StartAutomatedReasoningPolicyBuildWorkflow`
- `StartAutomatedReasoningPolicyTestWorkflow`
- `StopAdvancedPromptOptimizationJob`
- `StopEvaluationJob`
- `StopModelCustomizationJob`
- `StopModelInvocationJob`
- `TagResource`
- `UntagResource`
- `UpdateAutomatedReasoningPolicy`
- `UpdateAutomatedReasoningPolicyAnnotations`
- `UpdateAutomatedReasoningPolicyTestCase`
- `UpdateCustomModelDeployment`
- `UpdateMarketplaceModelEndpoint`
## bedrockruntime
`2023-09-30` — 5 of 11 modelled operations implemented (45.5%), 0 stubbed, 0 not applicable, 0 registered outside the pinned model.
### Not implemented
- `CountTokens`
- `GetAsyncInvoke`
- `InvokeGuardrailChecks`
- `InvokeModelWithBidirectionalStream`
- `ListAsyncInvokes`
- `StartAsyncInvoke`
## ec2
`2016-11-15` — 127 of 804 modelled operations implemented (15.8%), 0 stubbed, 39 not applicable, 0 registered outside the pinned model.
+30
View File
@@ -30,6 +30,36 @@
"tls"
]
},
"bedrock": {
"slug": "bedrock",
"name": "Bedrock",
"title": "Bedrock API Coverage",
"seoTitle": "Amazon Bedrock API Coverage on Spinifex — Spinifex Docs",
"description": "The Amazon Bedrock control-plane API operations Spinifex implements, covering foundation models, guardrails, provisioned throughput and invocation logging.",
"tags": [
"aws",
"compatibility",
"coverage",
"bedrock",
"ai",
"models"
]
},
"bedrockruntime": {
"slug": "bedrock-runtime",
"name": "Bedrock Runtime",
"title": "Bedrock Runtime API Coverage",
"seoTitle": "Amazon Bedrock Runtime API Coverage — Spinifex Docs",
"description": "The Amazon Bedrock Runtime API operations Spinifex implements, covering model invocation, the Converse API, streamed responses and standalone guardrail checks.",
"tags": [
"aws",
"compatibility",
"coverage",
"bedrock",
"ai",
"inference"
]
},
"ec2": {
"slug": "ec2",
"name": "EC2",
+2
View File
@@ -10,6 +10,8 @@ var modelFS embed.FS
var modelFiles = map[Service]string{
ACM: "models/acm-2015-12-08.json.gz",
Bedrock: "models/bedrock-2023-04-20.json.gz",
BedrockRuntime: "models/bedrock-runtime-2023-09-30.json.gz",
EC2: "models/ec2-2016-11-15.json.gz",
ECR: "models/ecr-2015-09-21.json.gz",
ECS: "models/ecs-2014-11-13.json.gz",
+2
View File
@@ -27,6 +27,8 @@ type Service string
const (
ACM Service = "acm"
Bedrock Service = "bedrock"
BedrockRuntime Service = "bedrockruntime"
EC2 Service = "ec2"
ECR Service = "ecr"
ECS Service = "ecs"
+3 -1
View File
@@ -8,7 +8,7 @@ import (
)
func TestServices(t *testing.T) {
want := []Service{ACM, EC2, ECR, ECS, EKS, ElasticLoadBalancingV2, IAM, RDS, S3, STS}
want := []Service{ACM, Bedrock, BedrockRuntime, EC2, ECR, ECS, EKS, ElasticLoadBalancingV2, IAM, RDS, S3, STS}
if got := Services(); !reflect.DeepEqual(got, want) {
t.Fatalf("Services() = %v, want %v", got, want)
}
@@ -21,6 +21,8 @@ func TestLoadAllModels(t *testing.T) {
shapes int
}{
ACM: {"2015-12-08", 40, 239},
Bedrock: {"2023-04-20", 108, 881},
BedrockRuntime: {"2023-09-30", 11, 349},
EC2: {"2016-11-15", 804, 4245},
ECR: {"2015-09-21", 58, 404},
ECS: {"2014-11-13", 77, 643},
+1 -1
View File
@@ -1,6 +1,6 @@
# AWS models
The `*.json.gz` files are the Smithy JSON AST service models from [`aws/api-models-aws`](https://github.com/aws/api-models-aws), gzipped and embedded into the binary, so loading them needs no network or Go module cache. All ten come from the one commit recorded in `../model_source.go`.
The `*.json.gz` files are the Smithy JSON AST service models from [`aws/api-models-aws`](https://github.com/aws/api-models-aws), gzipped and embedded into the binary, so loading them needs no network or Go module cache. All of them come from the one commit recorded in `../model_source.go`.
Do not edit them by hand. To move to a newer commit, run `scripts/sync-aws-models.sh <commit-sha>`, then `make generate-aws-model-coverage` and review the regenerated `docs/coverage` and the `awsmodel` test expectations: a newer model can add operations, required members and enum values, and each resulting finding is a real gap to triage rather than a reason to stay on an older commit.
Binary file not shown.
+11 -1
View File
@@ -322,8 +322,18 @@ func (g *requestGenerator) site(path []pathStep, site constraintSite) {
}
// value generates a valid value for ref at path, reporting false when none
// can be generated.
// can be generated. A value that is not generated is left out of the request,
// so the sites recorded beneath it are dropped with it.
func (g *requestGenerator) value(ref ShapeRef, path []pathStep, depth int) (any, bool) {
sites := len(g.sites)
value, ok := g.generate(ref, path, depth)
if !ok {
g.sites = g.sites[:sites]
}
return value, ok
}
func (g *requestGenerator) generate(ref ShapeRef, path []pathStep, depth int) (any, bool) {
shape := g.model.shapes[ref.Shape]
if ref.Streaming {
g.skip(path, "streaming payload")
+11
View File
@@ -299,6 +299,17 @@ func TestGenerateRequestsBreaksMapKeys(t *testing.T) {
require.Equal(t, []Constraint{ConstraintLength, ConstraintLength}, keyRejections, "below min and above max")
}
// A map of documents is left out of the request because document values are
// not generated, so its key must not be broken in a map that is not there.
func TestGenerateRequestsDropsSitesUnderAnUngeneratedValue(t *testing.T) {
plan, err := GenerateRequests(Bedrock, "CreateAdvancedPromptOptimizationJob", testRequestOptions)
require.NoError(t, err)
require.Contains(t, plan.Skipped, Skip{Path: "$.modelConfigurations[0].additionalModelRequestFields.spxa", Reason: "document values are not generated"})
for _, request := range plan.Cases {
require.NotContains(t, request.Path, "additionalModelRequestFields")
}
}
func TestGenerateRequestsRecordsUnbrokenConstraints(t *testing.T) {
plan, err := GenerateRequests(EKS, "DescribeCluster", testRequestOptions)
require.NoError(t, err)
+3 -1
View File
@@ -20,6 +20,8 @@ REPO="https://github.com/aws/api-models-aws.git"
# <api-models-aws sdk-id>/<api version>
MODELS=(
acm/2015-12-08
bedrock/2023-04-20
bedrock-runtime/2023-09-30
ec2/2016-11-15
ecr/2015-09-21
ecs/2014-11-13
@@ -34,7 +36,7 @@ MODELS=(
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
# A blobless shallow fetch pulls only the ten files read below.
# A blobless shallow fetch pulls only the files read below.
git -C "$TMP" init --quiet repo
git -C "$TMP/repo" fetch --quiet --depth=1 --filter=blob:none "$REPO" "$COMMIT"
COMMITTED="$(git -C "$TMP/repo" log -1 --format=%cs "$COMMIT")"
+5
View File
@@ -148,6 +148,11 @@ var bedrockRoutes = []bedrockRoute{
}},
}
// bedrockActionNames returns the distinct actions in bedrockRoutes in stable order.
func bedrockActionNames() []string {
return routeActionNames(bedrockRoutes)
}
// bedrockRouter matches an escaped request path against bedrockRoutes.
var bedrockRouter = rest.NewRouter("bedrock", bedrockRoutes)
+6
View File
@@ -66,6 +66,12 @@ var bedrockRuntimeRoutes = []bedrockRuntimeRoute{
}},
}
// bedrockRuntimeActionNames returns the distinct actions in bedrockRuntimeRoutes
// in stable order.
func bedrockRuntimeActionNames() []string {
return routeActionNames(bedrockRuntimeRoutes)
}
// bedrockRuntimeRouter matches an escaped request path against bedrockRuntimeRoutes.
var bedrockRuntimeRouter = rest.NewRouter("bedrock-runtime", bedrockRuntimeRoutes)
+1 -8
View File
@@ -7,7 +7,6 @@ import (
"github.com/mulgadc/spinifex/spinifex/ingress/aws/rest"
"log/slog"
"net/http"
"slices"
"github.com/mulgadc/bluebottle/pkg/auth"
"github.com/mulgadc/spinifex/spinifex/foundation/aws/arn"
@@ -179,14 +178,8 @@ 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)
return routeActionNames(eksRoutes)
}
// eksRouter matches an escaped request path against eksRoutes.
+19
View File
@@ -7,6 +7,7 @@ import (
gateway_ecs "github.com/mulgadc/spinifex/spinifex/gateway/ecs"
gateway_rds "github.com/mulgadc/spinifex/spinifex/gateway/rds"
"github.com/mulgadc/spinifex/spinifex/ingress/aws/dispatch"
"github.com/mulgadc/spinifex/spinifex/ingress/aws/rest"
)
// ServiceOperationInventory describes the authoritative dispatch state for an
@@ -24,6 +25,12 @@ type ServiceOperationInventory struct {
// operations and delegates that REST surface to Predastore.
func AWSOperationInventory(registered map[string]dispatch.Inventory) map[string]ServiceOperationInventory {
inventory := map[string]ServiceOperationInventory{
"bedrock": {
Registered: bedrockActionNames(),
},
"bedrockruntime": {
Registered: bedrockRuntimeActionNames(),
},
"ec2": {
Registered: mapKeys(ec2Actions),
},
@@ -61,3 +68,15 @@ func AWSOperationInventory(registered map[string]dispatch.Inventory) map[string]
func mapKeys[V any](values map[string]V) []string {
return slices.Sorted(maps.Keys(values))
}
// routeActionNames returns the distinct actions in a REST route table in
// stable order. Deduplicated because an action may be reachable by more than
// one route.
func routeActionNames[H any](routes []rest.Route[H]) []string {
names := make([]string, 0, len(routes))
for _, route := range routes {
names = append(names, route.Action)
}
slices.Sort(names)
return slices.Compact(names)
}
+36 -4
View File
@@ -28,6 +28,11 @@ func TestAWSOperationInventoryClassifiesDispatchers(t *testing.T) {
require.Contains(t, inventory["eks"].Registered, "DescribeCluster")
require.NotContains(t, inventory["eks"].Stubbed, "DescribeCluster")
require.Contains(t, inventory["bedrock"].Registered, "ListFoundationModels")
require.Contains(t, inventory["bedrockruntime"].Registered, "Converse")
// Served by a special case in BedrockRuntime_Request, not a route handler.
require.Contains(t, inventory["bedrockruntime"].Registered, "InvokeModel")
require.Contains(t, inventory["rds"].Registered, "CreateDBInstance")
require.NotContains(t, inventory["rds"].Unsupported, "CreateDBInstance")
require.Contains(t, inventory["rds"].Unsupported, "CreateDBCluster")
@@ -59,11 +64,38 @@ func TestAWSOperationInventoryMeasuresEKSAgainstTheModel(t *testing.T) {
}
}
func TestEKSActionNamesAreSortedAndDistinct(t *testing.T) {
names := eksActionNames()
// Every Bedrock route answers an operation in the pinned model, so nothing
// the gateway serves may be reported as outside it.
func TestAWSOperationInventoryMeasuresBedrockAgainstTheModel(t *testing.T) {
inventory := AWSOperationInventory(ecrRegistrationInventory())
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)
for service, model := range map[string]awsmodel.Service{
"bedrock": awsmodel.Bedrock,
"bedrockruntime": awsmodel.BedrockRuntime,
} {
t.Run(service, func(t *testing.T) {
coverage, err := awsmodel.CompareOperations(model, awsmodel.DispatchInventory{
Registered: inventory[service].Registered,
Stubbed: inventory[service].Stubbed,
Unsupported: inventory[service].Unsupported,
})
require.NoError(t, err)
require.NotEmpty(t, coverage.Implemented)
require.Empty(t, coverage.Extra)
require.ElementsMatch(t, inventory[service].Registered, coverage.Implemented)
})
}
}
func TestRouteActionNamesAreSortedAndDistinct(t *testing.T) {
for name, names := range map[string][]string{
"eks": eksActionNames(),
"bedrock": bedrockActionNames(),
"bedrockruntime": bedrockRuntimeActionNames(),
} {
require.True(t, slices.IsSorted(names), "%s actions are not sorted: %v", name, names)
require.Len(t, slices.Compact(slices.Clone(names)), len(names), "%s actions contain duplicates: %v", name, names)
}
}
func TestAWSOperationInventoryStatusesAreDisjointSubsets(t *testing.T) {