mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
feat: hide internal commands from compatibility page
This commit is contained in:
@@ -20,7 +20,7 @@ tags:
|
||||
|
||||
Spinifex implements **121 of the 625** operations (**19.4%**) in the EC2 `2016-11-15` API model.
|
||||
|
||||
### Spot instances are a mock
|
||||
### Spot Instances Are a Mock
|
||||
|
||||
Spot Instance Requests are a mock over the on-demand `RunInstances` path. A request synchronously launches real VMs on the operator's own compute and is then reported `active` and `fulfilled`. There is no spot market: no bidding, no price rejection, no interruption and no reclamation, and instances are never taken back.
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
### Spot instances are a mock
|
||||
### Spot Instances Are a Mock
|
||||
|
||||
Spot Instance Requests are a mock over the on-demand `RunInstances` path. A request synchronously launches real VMs on the operator's own compute and is then reported `active` and `fulfilled`. There is no spot market: no bidding, no price rejection, no interruption and no reclamation, and instances are never taken back.
|
||||
|
||||
@@ -26,7 +26,7 @@ Repository metadata is served over the AWS API on the gateway endpoint. Image da
|
||||
|
||||
The split explains the largest group of unimplemented operations below. The layer-transfer operations — `BatchCheckLayerAvailability`, `InitiateLayerUpload`, `UploadLayerPart`, `CompleteLayerUpload` and `GetDownloadUrlForLayer` — are registered stubs because the `/v2/` endpoint carries that traffic instead. A client using `docker` or any OCI-compatible tool never calls them.
|
||||
|
||||
Vulnerability scanning is not offered, so the image-scanning operations refuse deliberately rather than pretending to have found nothing. Registry replication is likewise absent: a deployment is a single registry, with no cross-region peer to replicate to.
|
||||
Registry replication is absent as well: a deployment is a single registry, with no cross-region peer to replicate to.
|
||||
|
||||
### Operations
|
||||
|
||||
@@ -35,7 +35,7 @@ Vulnerability scanning is not offered, so the image-scanning operations refuse d
|
||||
| `BatchCheckLayerAvailability` | 🟡 Stub |
|
||||
| `BatchDeleteImage` | ✅ Implemented |
|
||||
| `BatchGetImage` | ✅ Implemented |
|
||||
| `BatchGetRepositoryScanningConfiguration` | ⛔ Not applicable |
|
||||
| `BatchGetRepositoryScanningConfiguration` | ⛔ Not applicable [1](#notes) |
|
||||
| `CompleteLayerUpload` | 🟡 Stub |
|
||||
| `CreatePullThroughCacheRule` | ❌ Not implemented |
|
||||
| `CreateRepository` | ✅ Implemented |
|
||||
@@ -47,7 +47,7 @@ Vulnerability scanning is not offered, so the image-scanning operations refuse d
|
||||
| `DeleteRepositoryCreationTemplate` | ❌ Not implemented |
|
||||
| `DeleteRepositoryPolicy` | ✅ Implemented |
|
||||
| `DescribeImageReplicationStatus` | ❌ Not implemented |
|
||||
| `DescribeImageScanFindings` | ⛔ Not applicable |
|
||||
| `DescribeImageScanFindings` | ⛔ Not applicable [1](#notes) |
|
||||
| `DescribeImages` | ✅ Implemented |
|
||||
| `DescribePullThroughCacheRules` | ❌ Not implemented |
|
||||
| `DescribeRegistry` | 🟡 Stub |
|
||||
@@ -58,20 +58,20 @@ Vulnerability scanning is not offered, so the image-scanning operations refuse d
|
||||
| `GetLifecyclePolicy` | ✅ Implemented |
|
||||
| `GetLifecyclePolicyPreview` | ✅ Implemented |
|
||||
| `GetRegistryPolicy` | 🟡 Stub |
|
||||
| `GetRegistryScanningConfiguration` | ⛔ Not applicable |
|
||||
| `GetRegistryScanningConfiguration` | ⛔ Not applicable [1](#notes) |
|
||||
| `GetRepositoryPolicy` | ✅ Implemented |
|
||||
| `InitiateLayerUpload` | 🟡 Stub |
|
||||
| `ListImages` | ✅ Implemented |
|
||||
| `ListTagsForResource` | ✅ Implemented |
|
||||
| `PutImage` | ✅ Implemented |
|
||||
| `PutImageScanningConfiguration` | ⛔ Not applicable |
|
||||
| `PutImageScanningConfiguration` | ⛔ Not applicable [1](#notes) |
|
||||
| `PutImageTagMutability` | ✅ Implemented |
|
||||
| `PutLifecyclePolicy` | ✅ Implemented |
|
||||
| `PutRegistryPolicy` | 🟡 Stub |
|
||||
| `PutRegistryScanningConfiguration` | ⛔ Not applicable |
|
||||
| `PutRegistryScanningConfiguration` | ⛔ Not applicable [1](#notes) |
|
||||
| `PutReplicationConfiguration` | 🟡 Stub |
|
||||
| `SetRepositoryPolicy` | ✅ Implemented |
|
||||
| `StartImageScan` | ⛔ Not applicable |
|
||||
| `StartImageScan` | ⛔ Not applicable [1](#notes) |
|
||||
| `StartLifecyclePolicyPreview` | ✅ Implemented |
|
||||
| `TagResource` | 🟡 Stub |
|
||||
| `UntagResource` | 🟡 Stub |
|
||||
@@ -82,3 +82,7 @@ Vulnerability scanning is not offered, so the image-scanning operations refuse d
|
||||
| `GetImageScanningConfiguration` | 🔒 Outside the pinned model |
|
||||
| `ListRepositories` | 🔒 Outside the pinned model |
|
||||
| `ReplicateImage` | 🔒 Outside the pinned model |
|
||||
|
||||
### Notes
|
||||
|
||||
1. Image scanning is an AWS-hosted vulnerability service with no equivalent here, so a finding set would always be empty.
|
||||
|
||||
@@ -4,4 +4,4 @@ Repository metadata is served over the AWS API on the gateway endpoint. Image da
|
||||
|
||||
The split explains the largest group of unimplemented operations below. The layer-transfer operations — `BatchCheckLayerAvailability`, `InitiateLayerUpload`, `UploadLayerPart`, `CompleteLayerUpload` and `GetDownloadUrlForLayer` — are registered stubs because the `/v2/` endpoint carries that traffic instead. A client using `docker` or any OCI-compatible tool never calls them.
|
||||
|
||||
Vulnerability scanning is not offered, so the image-scanning operations refuse deliberately rather than pretending to have found nothing. Registry replication is likewise absent: a deployment is a single registry, with no cross-region peer to replicate to.
|
||||
Registry replication is absent as well: a deployment is a single registry, with no cross-region peer to replicate to.
|
||||
|
||||
@@ -84,6 +84,3 @@ Clusters, services and tasks run on EC2 container instances. There is no Fargate
|
||||
| `UpdateServicePrimaryTaskSet` | ❌ Not implemented |
|
||||
| `UpdateTaskProtection` | ❌ Not implemented |
|
||||
| `UpdateTaskSet` | ❌ Not implemented |
|
||||
| `PollAssignments` | 🔒 Outside the pinned model |
|
||||
| `ProvisionCapacity` | 🔒 Outside the pinned model |
|
||||
| `ReportTaskGPU` | 🔒 Outside the pinned model |
|
||||
|
||||
@@ -20,21 +20,6 @@ tags:
|
||||
|
||||
Spinifex implements **34 of the 56** operations (**60.7%**) in the EKS `2017-11-01` API model.
|
||||
|
||||
### Routing
|
||||
|
||||
EKS is REST-JSON, dispatched by HTTP method and path rather than by an action parameter, so the gateway's routing table is the authoritative list of what it serves. Clusters run K3s on control-plane VMs; nodegroups are EC2 instances joined to them.
|
||||
|
||||
### Internal routes
|
||||
|
||||
Four routes on this surface are internal, not AWS actions, and appear in the table below as registered outside the pinned model:
|
||||
|
||||
- `PublishInternal` — the control-plane VM broker, relaying bootstrap and state posts onto the message bus.
|
||||
- `WebhookTokenReview` — the token webhook posting bearer tokens for host-side resolution.
|
||||
- `ListInternalAddons` — the on-VM add-on sync agent fetching its staged manifests.
|
||||
- `GetRecoveryDirective` — the on-VM recovery agent reading its per-member directive at boot.
|
||||
|
||||
None is callable with an ordinary tenant credential. Each names the target account in the path rather than taking it from the credential, so each requires a control-plane instance-role session bound to the named cluster; a broad `eks:*` grant does not reach them.
|
||||
|
||||
### Operations
|
||||
|
||||
| Operation | Status |
|
||||
@@ -95,7 +80,3 @@ None is callable with an ordinary tenant credential. Each names the target accou
|
||||
| `UpdateNodegroupConfig` | ✅ Implemented |
|
||||
| `UpdateNodegroupVersion` | ✅ Implemented |
|
||||
| `UpdatePodIdentityAssociation` | ❌ Not implemented |
|
||||
| `GetRecoveryDirective` | 🔒 Outside the pinned model |
|
||||
| `ListInternalAddons` | 🔒 Outside the pinned model |
|
||||
| `PublishInternal` | 🔒 Outside the pinned model |
|
||||
| `WebhookTokenReview` | 🔒 Outside the pinned model |
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
### Routing
|
||||
|
||||
EKS is REST-JSON, dispatched by HTTP method and path rather than by an action parameter, so the gateway's routing table is the authoritative list of what it serves. Clusters run K3s on control-plane VMs; nodegroups are EC2 instances joined to them.
|
||||
|
||||
### Internal routes
|
||||
|
||||
Four routes on this surface are internal, not AWS actions, and appear in the table below as registered outside the pinned model:
|
||||
|
||||
- `PublishInternal` — the control-plane VM broker, relaying bootstrap and state posts onto the message bus.
|
||||
- `WebhookTokenReview` — the token webhook posting bearer tokens for host-side resolution.
|
||||
- `ListInternalAddons` — the on-VM add-on sync agent fetching its staged manifests.
|
||||
- `GetRecoveryDirective` — the on-VM recovery agent reading its per-member directive at boot.
|
||||
|
||||
None is callable with an ordinary tenant credential. Each names the target account in the path rather than taking it from the credential, so each requires a control-plane instance-role session bound to the named cluster; a broad `eks:*` grant does not reach them.
|
||||
@@ -75,6 +75,4 @@ The data plane is a system-managed load balancer VM, launched automatically duri
|
||||
| `SetSecurityGroups` | ✅ Implemented |
|
||||
| `SetSubnets` | ✅ Implemented |
|
||||
| `DescribeListenerAttributes` | 🔒 Outside the pinned model |
|
||||
| `GetLBConfig` | 🔒 Outside the pinned model |
|
||||
| `LBAgentHeartbeat` | 🔒 Outside the pinned model |
|
||||
| `ModifyListenerAttributes` | 🔒 Outside the pinned model |
|
||||
|
||||
@@ -64,7 +64,18 @@
|
||||
"ecr",
|
||||
"containers",
|
||||
"registry"
|
||||
]
|
||||
],
|
||||
"notApplicable": {
|
||||
"BatchGetRepositoryScanningConfiguration": "image-scanning",
|
||||
"DescribeImageScanFindings": "image-scanning",
|
||||
"GetRegistryScanningConfiguration": "image-scanning",
|
||||
"PutImageScanningConfiguration": "image-scanning",
|
||||
"PutRegistryScanningConfiguration": "image-scanning",
|
||||
"StartImageScan": "image-scanning"
|
||||
},
|
||||
"notes": {
|
||||
"image-scanning": "Image scanning is an AWS-hosted vulnerability service with no equivalent here, so a finding set would always be empty."
|
||||
}
|
||||
},
|
||||
"ecs": {
|
||||
"slug": "ecs-api-coverage",
|
||||
@@ -79,6 +90,11 @@
|
||||
"ecs",
|
||||
"containers",
|
||||
"orchestration"
|
||||
],
|
||||
"internal": [
|
||||
"PollAssignments",
|
||||
"ProvisionCapacity",
|
||||
"ReportTaskGPU"
|
||||
]
|
||||
},
|
||||
"eks": {
|
||||
@@ -94,6 +110,12 @@
|
||||
"eks",
|
||||
"kubernetes",
|
||||
"containers"
|
||||
],
|
||||
"internal": [
|
||||
"GetRecoveryDirective",
|
||||
"ListInternalAddons",
|
||||
"PublishInternal",
|
||||
"WebhookTokenReview"
|
||||
]
|
||||
},
|
||||
"elasticloadbalancingv2": {
|
||||
@@ -109,6 +131,10 @@
|
||||
"elbv2",
|
||||
"load balancing",
|
||||
"networking"
|
||||
],
|
||||
"internal": [
|
||||
"GetLBConfig",
|
||||
"LBAgentHeartbeat"
|
||||
]
|
||||
},
|
||||
"iam": {
|
||||
@@ -167,7 +193,34 @@
|
||||
"databases",
|
||||
"postgresql",
|
||||
"mariadb"
|
||||
]
|
||||
],
|
||||
"internal": [
|
||||
"AcknowledgeDBBootstrap",
|
||||
"GetDBBootstrapConfig",
|
||||
"PollDBCommands",
|
||||
"RegisterDBInstance",
|
||||
"SubmitDBStateChange"
|
||||
],
|
||||
"notApplicable": {
|
||||
"CreateDBCluster": "clusters",
|
||||
"CreateDBInstanceReadReplica": "read-replicas",
|
||||
"CreateOptionGroup": "option-groups",
|
||||
"DeleteDBCluster": "clusters",
|
||||
"DeleteOptionGroup": "option-groups",
|
||||
"DescribeDBClusters": "clusters",
|
||||
"DescribeOptionGroups": "option-groups",
|
||||
"FailoverDBCluster": "clusters",
|
||||
"ModifyDBCluster": "clusters",
|
||||
"ModifyOptionGroup": "option-groups",
|
||||
"PromoteReadReplica": "read-replicas",
|
||||
"RestoreDBInstanceToPointInTime": "point-in-time-restore"
|
||||
},
|
||||
"notes": {
|
||||
"clusters": "Aurora and Multi-AZ clusters are not offered; a DB instance here is a single VM running the engine directly.",
|
||||
"option-groups": "Option groups configure engine add-ons for engines this platform does not offer, such as Oracle and SQL Server.",
|
||||
"point-in-time-restore": "Point-in-time restore needs continuous transaction-log archival, which the backup path does not keep.",
|
||||
"read-replicas": "Replication between instances is not offered, so there is no replica to create or promote."
|
||||
}
|
||||
},
|
||||
"sts": {
|
||||
"slug": "sts-api-coverage",
|
||||
|
||||
@@ -25,7 +25,7 @@ Spinifex implements **26 of the 162** operations (**16.0%**) in the RDS `2014-10
|
||||
|
||||
Spinifex offers PostgreSQL and MariaDB. Each DB instance is one dedicated system-owned VM running the engine directly, launched from a platform AMI and hidden from the customer's EC2 API. `Engine` is fixed at create: there is no in-place engine change, no cross-engine snapshot restore and no migration between the two.
|
||||
|
||||
`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`. Aliasing would report an engine and a version the instance is not running, and the discrepancy would propagate into `DescribeDBInstances`, parameter-group families and snapshot metadata.
|
||||
`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`.
|
||||
|
||||
Engine versions are pinned per engine. An `EngineVersion` naming anything but the pin is rejected, including a narrower minor version, because the AMI makes no promise about which minor it carries.
|
||||
|
||||
@@ -37,11 +37,9 @@ The engine is reached over a customer-account ENI injected into a subnet of the
|
||||
|
||||
Both engines enforce encrypted connections by default: `rds.force_ssl` on PostgreSQL and `require_secure_transport` on MariaDB. For MariaDB this is a deliberate divergence from AWS, which leaves it off. Both are boolean, modifiable and dynamic, so setting either to `0` in a parameter group restores plaintext without a reboot.
|
||||
|
||||
Enforcement requires that the connection is encrypted, not that the client validates the certificate. The engine serves a per-instance certificate signed by the cluster CA carrying both the ENI address and the DNS name, so a client that wants full verification can have it. A deployment holding no cluster CA cannot serve TLS at all, and a parameter group asking for enforcement there is refused rather than quietly ignored.
|
||||
|
||||
### Rejected parameters
|
||||
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected with `InvalidParameterValue` rather than silently dropped. Parameters that are merely inert — `AutoMinorVersionUpgrade`, `CopyTagsToSnapshot`, `DeleteAutomatedBackups`, Performance Insights and Enhanced Monitoring fields — are accepted as no-ops.
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected with `InvalidParameterValue` rather than silently dropped.
|
||||
|
||||
| Parameter | Why it is rejected |
|
||||
|-----------|--------------------|
|
||||
@@ -89,12 +87,12 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `CopyOptionGroup` | ❌ Not implemented |
|
||||
| `CreateBlueGreenDeployment` | ❌ Not implemented |
|
||||
| `CreateCustomDBEngineVersion` | ❌ Not implemented |
|
||||
| `CreateDBCluster` | ⛔ Not applicable |
|
||||
| `CreateDBCluster` | ⛔ Not applicable [1](#notes) |
|
||||
| `CreateDBClusterEndpoint` | ❌ Not implemented |
|
||||
| `CreateDBClusterParameterGroup` | ❌ Not implemented |
|
||||
| `CreateDBClusterSnapshot` | ❌ Not implemented |
|
||||
| `CreateDBInstance` | ✅ Implemented |
|
||||
| `CreateDBInstanceReadReplica` | ⛔ Not applicable |
|
||||
| `CreateDBInstanceReadReplica` | ⛔ Not applicable [4](#notes) |
|
||||
| `CreateDBParameterGroup` | ✅ Implemented |
|
||||
| `CreateDBProxy` | ❌ Not implemented |
|
||||
| `CreateDBProxyEndpoint` | ❌ Not implemented |
|
||||
@@ -105,11 +103,11 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `CreateEventSubscription` | ❌ Not implemented |
|
||||
| `CreateGlobalCluster` | ❌ Not implemented |
|
||||
| `CreateIntegration` | ❌ Not implemented |
|
||||
| `CreateOptionGroup` | ⛔ Not applicable |
|
||||
| `CreateOptionGroup` | ⛔ Not applicable [2](#notes) |
|
||||
| `CreateTenantDatabase` | ❌ Not implemented |
|
||||
| `DeleteBlueGreenDeployment` | ❌ Not implemented |
|
||||
| `DeleteCustomDBEngineVersion` | ❌ Not implemented |
|
||||
| `DeleteDBCluster` | ⛔ Not applicable |
|
||||
| `DeleteDBCluster` | ⛔ Not applicable [1](#notes) |
|
||||
| `DeleteDBClusterAutomatedBackup` | ❌ Not implemented |
|
||||
| `DeleteDBClusterEndpoint` | ❌ Not implemented |
|
||||
| `DeleteDBClusterParameterGroup` | ❌ Not implemented |
|
||||
@@ -126,7 +124,7 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `DeleteEventSubscription` | ❌ Not implemented |
|
||||
| `DeleteGlobalCluster` | ❌ Not implemented |
|
||||
| `DeleteIntegration` | ❌ Not implemented |
|
||||
| `DeleteOptionGroup` | ⛔ Not applicable |
|
||||
| `DeleteOptionGroup` | ⛔ Not applicable [2](#notes) |
|
||||
| `DeleteTenantDatabase` | ❌ Not implemented |
|
||||
| `DeregisterDBProxyTargets` | ❌ Not implemented |
|
||||
| `DescribeAccountAttributes` | ❌ Not implemented |
|
||||
@@ -139,7 +137,7 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `DescribeDBClusterParameters` | ❌ Not implemented |
|
||||
| `DescribeDBClusterSnapshotAttributes` | ❌ Not implemented |
|
||||
| `DescribeDBClusterSnapshots` | ❌ Not implemented |
|
||||
| `DescribeDBClusters` | ⛔ Not applicable |
|
||||
| `DescribeDBClusters` | ⛔ Not applicable [1](#notes) |
|
||||
| `DescribeDBEngineVersions` | ✅ Implemented |
|
||||
| `DescribeDBInstanceAutomatedBackups` | ✅ Implemented |
|
||||
| `DescribeDBInstances` | ✅ Implemented |
|
||||
@@ -166,7 +164,7 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `DescribeGlobalClusters` | ❌ Not implemented |
|
||||
| `DescribeIntegrations` | ❌ Not implemented |
|
||||
| `DescribeOptionGroupOptions` | ❌ Not implemented |
|
||||
| `DescribeOptionGroups` | ⛔ Not applicable |
|
||||
| `DescribeOptionGroups` | ⛔ Not applicable [2](#notes) |
|
||||
| `DescribeOrderableDBInstanceOptions` | ✅ Implemented |
|
||||
| `DescribePendingMaintenanceActions` | ❌ Not implemented |
|
||||
| `DescribeReservedDBInstances` | ❌ Not implemented |
|
||||
@@ -177,14 +175,14 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `DisableHttpEndpoint` | ❌ Not implemented |
|
||||
| `DownloadDBLogFilePortion` | ❌ Not implemented |
|
||||
| `EnableHttpEndpoint` | ❌ Not implemented |
|
||||
| `FailoverDBCluster` | ⛔ Not applicable |
|
||||
| `FailoverDBCluster` | ⛔ Not applicable [1](#notes) |
|
||||
| `FailoverGlobalCluster` | ❌ Not implemented |
|
||||
| `ListTagsForResource` | ✅ Implemented |
|
||||
| `ModifyActivityStream` | ❌ Not implemented |
|
||||
| `ModifyCertificates` | ❌ Not implemented |
|
||||
| `ModifyCurrentDBClusterCapacity` | ❌ Not implemented |
|
||||
| `ModifyCustomDBEngineVersion` | ❌ Not implemented |
|
||||
| `ModifyDBCluster` | ⛔ Not applicable |
|
||||
| `ModifyDBCluster` | ⛔ Not applicable [1](#notes) |
|
||||
| `ModifyDBClusterEndpoint` | ❌ Not implemented |
|
||||
| `ModifyDBClusterParameterGroup` | ❌ Not implemented |
|
||||
| `ModifyDBClusterSnapshotAttribute` | ❌ Not implemented |
|
||||
@@ -201,9 +199,9 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `ModifyEventSubscription` | ❌ Not implemented |
|
||||
| `ModifyGlobalCluster` | ❌ Not implemented |
|
||||
| `ModifyIntegration` | ❌ Not implemented |
|
||||
| `ModifyOptionGroup` | ⛔ Not applicable |
|
||||
| `ModifyOptionGroup` | ⛔ Not applicable [2](#notes) |
|
||||
| `ModifyTenantDatabase` | ❌ Not implemented |
|
||||
| `PromoteReadReplica` | ⛔ Not applicable |
|
||||
| `PromoteReadReplica` | ⛔ Not applicable [4](#notes) |
|
||||
| `PromoteReadReplicaDBCluster` | ❌ Not implemented |
|
||||
| `PurchaseReservedDBInstancesOffering` | ❌ Not implemented |
|
||||
| `RebootDBCluster` | ❌ Not implemented |
|
||||
@@ -222,7 +220,7 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `RestoreDBClusterToPointInTime` | ❌ Not implemented |
|
||||
| `RestoreDBInstanceFromDBSnapshot` | ✅ Implemented |
|
||||
| `RestoreDBInstanceFromS3` | ❌ Not implemented |
|
||||
| `RestoreDBInstanceToPointInTime` | ⛔ Not applicable |
|
||||
| `RestoreDBInstanceToPointInTime` | ⛔ Not applicable [3](#notes) |
|
||||
| `RevokeDBSecurityGroupIngress` | ❌ Not implemented |
|
||||
| `StartActivityStream` | ❌ Not implemented |
|
||||
| `StartDBCluster` | ❌ Not implemented |
|
||||
@@ -236,8 +234,10 @@ A parameter whose omission would create a false safety, security or availability
|
||||
| `SwitchoverBlueGreenDeployment` | ❌ Not implemented |
|
||||
| `SwitchoverGlobalCluster` | ❌ Not implemented |
|
||||
| `SwitchoverReadReplica` | ❌ Not implemented |
|
||||
| `AcknowledgeDBBootstrap` | 🔒 Outside the pinned model |
|
||||
| `GetDBBootstrapConfig` | 🔒 Outside the pinned model |
|
||||
| `PollDBCommands` | 🔒 Outside the pinned model |
|
||||
| `RegisterDBInstance` | 🔒 Outside the pinned model |
|
||||
| `SubmitDBStateChange` | 🔒 Outside the pinned model |
|
||||
|
||||
### Notes
|
||||
|
||||
1. Aurora and Multi-AZ clusters are not offered; a DB instance here is a single VM running the engine directly.
|
||||
2. Option groups configure engine add-ons for engines this platform does not offer, such as Oracle and SQL Server.
|
||||
3. Point-in-time restore needs continuous transaction-log archival, which the backup path does not keep.
|
||||
4. Replication between instances is not offered, so there is no replica to create or promote.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Spinifex offers PostgreSQL and MariaDB. Each DB instance is one dedicated system-owned VM running the engine directly, launched from a platform AMI and hidden from the customer's EC2 API. `Engine` is fixed at create: there is no in-place engine change, no cross-engine snapshot restore and no migration between the two.
|
||||
|
||||
`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`. Aliasing would report an engine and a version the instance is not running, and the discrepancy would propagate into `DescribeDBInstances`, parameter-group families and snapshot metadata.
|
||||
`mysql` is not an accepted engine and is not an alias for `mariadb`. MariaDB is offered under its own AWS engine name, exactly as AWS RDS offers it, so a client — including Terraform's `aws_db_instance` — must set `engine = "mariadb"`.
|
||||
|
||||
Engine versions are pinned per engine. An `EngineVersion` naming anything but the pin is rejected, including a narrower minor version, because the AMI makes no promise about which minor it carries.
|
||||
|
||||
@@ -14,11 +14,9 @@ The engine is reached over a customer-account ENI injected into a subnet of the
|
||||
|
||||
Both engines enforce encrypted connections by default: `rds.force_ssl` on PostgreSQL and `require_secure_transport` on MariaDB. For MariaDB this is a deliberate divergence from AWS, which leaves it off. Both are boolean, modifiable and dynamic, so setting either to `0` in a parameter group restores plaintext without a reboot.
|
||||
|
||||
Enforcement requires that the connection is encrypted, not that the client validates the certificate. The engine serves a per-instance certificate signed by the cluster CA carrying both the ENI address and the DNS name, so a client that wants full verification can have it. A deployment holding no cluster CA cannot serve TLS at all, and a parameter group asking for enforcement there is refused rather than quietly ignored.
|
||||
|
||||
### Rejected parameters
|
||||
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected with `InvalidParameterValue` rather than silently dropped. Parameters that are merely inert — `AutoMinorVersionUpgrade`, `CopyTagsToSnapshot`, `DeleteAutomatedBackups`, Performance Insights and Enhanced Monitoring fields — are accepted as no-ops.
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected with `InvalidParameterValue` rather than silently dropped.
|
||||
|
||||
| Parameter | Why it is rejected |
|
||||
|-----------|--------------------|
|
||||
|
||||
@@ -50,16 +50,19 @@ func (c OperationCoverage) ImplementedPercent() float64 {
|
||||
}
|
||||
|
||||
// OperationStatuses returns every modelled operation with its dispatch state,
|
||||
// followed by the registered operations the pinned model does not describe.
|
||||
// followed by the registered operations the pinned model does not describe,
|
||||
// less the internal routes the page declares.
|
||||
//
|
||||
// notApplicable declares operations the platform will never serve, mapped to
|
||||
// the note key explaining why. A refusing handler is the same fact reached
|
||||
// mechanically, so both publish as StatusNotApplicable.
|
||||
func (c OperationCoverage) OperationStatuses(notApplicable map[string]string) ([]OperationStatus, error) {
|
||||
// The page's NotApplicable declares operations the platform will never serve,
|
||||
// mapped to the note key explaining why. A refusing handler is the same fact
|
||||
// reached mechanically, so both publish as StatusNotApplicable.
|
||||
func (c OperationCoverage) OperationStatuses(page PageMetadata) ([]OperationStatus, error) {
|
||||
registered := toSet(c.Registered)
|
||||
stubbed := toSet(c.Stubbed)
|
||||
unsupported := toSet(c.Unsupported)
|
||||
modelled := toSet(c.Modelled)
|
||||
extra := toSet(c.Extra)
|
||||
notApplicable := page.NotApplicable
|
||||
|
||||
for operation, noteKey := range notApplicable {
|
||||
switch {
|
||||
@@ -72,6 +75,14 @@ func (c OperationCoverage) OperationStatuses(notApplicable map[string]string) ([
|
||||
}
|
||||
}
|
||||
|
||||
internal := map[string]bool{}
|
||||
for _, operation := range page.Internal {
|
||||
if !extra[operation] {
|
||||
return nil, fmt.Errorf("awsmodel: %s route %q is declared internal but is not a registered route outside the pinned model", c.Service, operation)
|
||||
}
|
||||
internal[operation] = true
|
||||
}
|
||||
|
||||
statuses := make([]OperationStatus, 0, len(c.Modelled)+len(c.Extra))
|
||||
for _, operation := range c.Modelled {
|
||||
status := StatusNotImplemented
|
||||
@@ -90,6 +101,9 @@ func (c OperationCoverage) OperationStatuses(notApplicable map[string]string) ([
|
||||
statuses = append(statuses, OperationStatus{Operation: operation, Status: status})
|
||||
}
|
||||
for _, operation := range c.Extra {
|
||||
if internal[operation] {
|
||||
continue
|
||||
}
|
||||
statuses = append(statuses, OperationStatus{Operation: operation, Status: StatusOutsideModel})
|
||||
}
|
||||
return statuses, nil
|
||||
@@ -115,6 +129,12 @@ type PageMetadata struct {
|
||||
// dispatch tables at render, so a typo or a later implementation fails the
|
||||
// build rather than publishing a claim that has quietly become false.
|
||||
NotApplicable map[string]string `json:"notApplicable,omitempty"`
|
||||
|
||||
// Internal names registered routes that carry platform plumbing rather than
|
||||
// a tenant-callable AWS action, which the page leaves out. A route outside
|
||||
// the pinned model that is not declared here is published, so a real AWS
|
||||
// operation newer than the pin surfaces instead of disappearing quietly.
|
||||
Internal []string `json:"internal,omitempty"`
|
||||
}
|
||||
|
||||
// PageSet is the metadata for the index page and every service page.
|
||||
@@ -253,7 +273,7 @@ func RenderServicePage(coverage OperationCoverage, pages PageSet, intro string)
|
||||
body.WriteString(strings.TrimSpace(intro) + "\n\n")
|
||||
}
|
||||
|
||||
statuses, err := coverage.OperationStatuses(page.NotApplicable)
|
||||
statuses, err := coverage.OperationStatuses(page)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package awsmodel_test
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -157,7 +158,7 @@ func TestOperationStatusesRejectsStaleNotApplicableClaims(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if _, err := coverage.OperationStatuses(declared); err == nil {
|
||||
if _, err := coverage.OperationStatuses(PageMetadata{NotApplicable: declared}); err == nil {
|
||||
t.Fatal("OperationStatuses accepted a claim that cannot hold")
|
||||
}
|
||||
})
|
||||
@@ -170,7 +171,9 @@ func TestOperationStatusesCarriesTheNoteKey(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
statuses, err := coverage.OperationStatuses(map[string]string{"GetFederationToken": "no-broker"})
|
||||
statuses, err := coverage.OperationStatuses(PageMetadata{
|
||||
NotApplicable: map[string]string{"GetFederationToken": "no-broker"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -186,6 +189,44 @@ func TestOperationStatusesCarriesTheNoteKey(t *testing.T) {
|
||||
t.Fatal("declared operation is missing from the table")
|
||||
}
|
||||
|
||||
// Platform plumbing is left out of a page about the AWS API, but only where it
|
||||
// is declared: an undeclared route stays visible, so a real AWS operation newer
|
||||
// than the pinned model cannot disappear by being registered.
|
||||
func TestOperationStatusesHidesDeclaredInternalRoutes(t *testing.T) {
|
||||
coverage, err := CompareOperations(STS, DispatchInventory{
|
||||
Registered: []string{"AssumeRole", "PublishInternal", "AheadOfThePin"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
statuses, err := coverage.OperationStatuses(PageMetadata{Internal: []string{"PublishInternal"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, status := range statuses {
|
||||
if status.Operation == "PublishInternal" {
|
||||
t.Error("a declared internal route is published")
|
||||
}
|
||||
}
|
||||
if !slices.ContainsFunc(statuses, func(s OperationStatus) bool {
|
||||
return s.Operation == "AheadOfThePin" && s.Status == StatusOutsideModel
|
||||
}) {
|
||||
t.Error("an undeclared route outside the pinned model is not published")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOperationStatusesRejectsAnInternalRouteThatIsModelled(t *testing.T) {
|
||||
coverage, err := CompareOperations(STS, DispatchInventory{Registered: []string{"AssumeRole"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := coverage.OperationStatuses(PageMetadata{Internal: []string{"AssumeRole"}}); err == nil {
|
||||
t.Fatal("OperationStatuses hid a modelled AWS operation as internal plumbing")
|
||||
}
|
||||
}
|
||||
|
||||
// A footnote reused across operations is written once, and both directions of
|
||||
// the reference are checked so neither side can rot.
|
||||
func TestRenderServicePageFootnotesSharedNotes(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user