mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-15 09:01:31 +00:00
fix: footnotes instead of notes for compatibility
This commit is contained in:
+1
-1011
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **9 of the 15** operations (60.0%) in the ACM `2015-12-08` API model.
|
||||
Spinifex implements **9 of the 15** operations (**60.0%**) in the ACM `2015-12-08` API model.
|
||||
|
||||
### Import and issuance
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ tags:
|
||||
|
||||
Spinifex serves the AWS APIs below. Every page counts the operations in the pinned `aws-sdk-go v1.55.8` `api-2.json` model for its service and reports, operation by operation, whether Spinifex implements it.
|
||||
|
||||
| Service | API version | Implemented | Modelled | Coverage |
|
||||
|---|---|---:|---:|---:|
|
||||
| [ACM](/docs/acm-api-coverage) | 2015-12-08 | 9 | 15 | 60.0% |
|
||||
| [EC2](/docs/ec2-api-coverage) | 2016-11-15 | 121 | 625 | 19.4% |
|
||||
| [ECR](/docs/ecr-api-coverage) | 2015-09-21 | 19 | 47 | 40.4% |
|
||||
| [ECS](/docs/ecs-api-coverage) | 2014-11-13 | 31 | 56 | 55.4% |
|
||||
| [EKS](/docs/eks-api-coverage) | 2017-11-01 | 34 | 56 | 60.7% |
|
||||
| [ELBv2](/docs/elbv2-api-coverage) | 2015-12-01 | 33 | 46 | 71.7% |
|
||||
| [IAM](/docs/iam-api-coverage) | 2010-05-08 | 75 | 159 | 47.2% |
|
||||
| [RDS](/docs/rds-api-coverage) | 2014-10-31 | 26 | 162 | 16.0% |
|
||||
| [STS](/docs/sts-api-coverage) | 2011-06-15 | 4 | 8 | 50.0% |
|
||||
| Service | Implemented | Modelled | Coverage |
|
||||
|---|---:|---:|---:|
|
||||
| [ACM](/docs/acm-api-coverage) | 9 | 15 | 60.0% |
|
||||
| [EC2](/docs/ec2-api-coverage) | 121 | 625 | 19.4% |
|
||||
| [ECR](/docs/ecr-api-coverage) | 19 | 47 | 40.4% |
|
||||
| [ECS](/docs/ecs-api-coverage) | 31 | 56 | 55.4% |
|
||||
| [EKS](/docs/eks-api-coverage) | 34 | 56 | 60.7% |
|
||||
| [ELBv2](/docs/elbv2-api-coverage) | 33 | 46 | 71.7% |
|
||||
| [IAM](/docs/iam-api-coverage) | 75 | 159 | 47.2% |
|
||||
| [RDS](/docs/rds-api-coverage) | 26 | 162 | 16.0% |
|
||||
| [STS](/docs/sts-api-coverage) | 4 | 8 | 50.0% |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **19 of the 47** operations (40.4%) in the ECR `2015-09-21` API model.
|
||||
Spinifex implements **19 of the 47** operations (**40.4%**) in the ECR `2015-09-21` API model.
|
||||
|
||||
### Two endpoints, one registry
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **31 of the 56** operations (55.4%) in the ECS `2014-11-13` API model.
|
||||
Spinifex implements **31 of the 56** operations (**55.4%**) in the ECS `2014-11-13` API model.
|
||||
|
||||
### No Fargate
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **34 of the 56** operations (60.7%) in the EKS `2017-11-01` API model.
|
||||
Spinifex implements **34 of the 56** operations (**60.7%**) in the EKS `2017-11-01` API model.
|
||||
|
||||
### Routing
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **33 of the 46** operations (71.7%) in the ELBv2 `2015-12-01` API model.
|
||||
Spinifex implements **33 of the 46** operations (**71.7%**) in the ELBv2 `2015-12-01` API model.
|
||||
|
||||
### Two data planes
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **75 of the 159** operations (47.2%) in the IAM `2010-05-08` API model.
|
||||
Spinifex implements **75 of the 159** operations (**47.2%**) in the IAM `2010-05-08` API model.
|
||||
|
||||
### Scope
|
||||
|
||||
@@ -26,164 +26,171 @@ All IAM operations are account-scoped. The root user of an account bypasses poli
|
||||
|
||||
### Operations
|
||||
|
||||
| Operation | Status | Notes |
|
||||
|---|---|---|
|
||||
| `AddClientIDToOpenIDConnectProvider` | ❌ Not implemented | |
|
||||
| `AddRoleToInstanceProfile` | ✅ Implemented | |
|
||||
| `AddUserToGroup` | ✅ Implemented | |
|
||||
| `AttachGroupPolicy` | ✅ Implemented | |
|
||||
| `AttachRolePolicy` | ✅ Implemented | |
|
||||
| `AttachUserPolicy` | ✅ Implemented | |
|
||||
| `ChangePassword` | ❌ Not implemented | |
|
||||
| `CreateAccessKey` | ✅ Implemented | |
|
||||
| `CreateAccountAlias` | ❌ Not implemented | |
|
||||
| `CreateGroup` | ✅ Implemented | |
|
||||
| `CreateInstanceProfile` | ✅ Implemented | |
|
||||
| `CreateLoginProfile` | ❌ Not implemented | |
|
||||
| `CreateOpenIDConnectProvider` | ✅ Implemented | |
|
||||
| `CreatePolicy` | ✅ Implemented | |
|
||||
| `CreatePolicyVersion` | ❌ Not implemented | |
|
||||
| `CreateRole` | ✅ Implemented | |
|
||||
| `CreateSAMLProvider` | ❌ Not implemented | |
|
||||
| `CreateServiceLinkedRole` | ⛔ Not applicable | Service-linked roles exist for AWS service principals, which this platform has none of. |
|
||||
| `CreateServiceSpecificCredential` | ⛔ Not applicable | CodeCommit credentials; the service does not exist here. |
|
||||
| `CreateUser` | ✅ Implemented | |
|
||||
| `CreateVirtualMFADevice` | ❌ Not implemented | |
|
||||
| `DeactivateMFADevice` | ❌ Not implemented | |
|
||||
| `DeleteAccessKey` | ✅ Implemented | |
|
||||
| `DeleteAccountAlias` | ❌ Not implemented | |
|
||||
| `DeleteAccountPasswordPolicy` | ❌ Not implemented | |
|
||||
| `DeleteGroup` | ✅ Implemented | |
|
||||
| `DeleteGroupPolicy` | ✅ Implemented | |
|
||||
| `DeleteInstanceProfile` | ✅ Implemented | |
|
||||
| `DeleteLoginProfile` | ❌ Not implemented | |
|
||||
| `DeleteOpenIDConnectProvider` | ✅ Implemented | |
|
||||
| `DeletePolicy` | ✅ Implemented | |
|
||||
| `DeletePolicyVersion` | ❌ Not implemented | |
|
||||
| `DeleteRole` | ✅ Implemented | |
|
||||
| `DeleteRolePermissionsBoundary` | ❌ Not implemented | |
|
||||
| `DeleteRolePolicy` | ✅ Implemented | |
|
||||
| `DeleteSAMLProvider` | ❌ Not implemented | |
|
||||
| `DeleteSSHPublicKey` | ⛔ Not applicable | CodeCommit SSH keys; the service does not exist here. |
|
||||
| `DeleteServerCertificate` | ❌ Not implemented | |
|
||||
| `DeleteServiceLinkedRole` | ⛔ Not applicable | Service-linked roles exist for AWS service principals, which this platform has none of. |
|
||||
| `DeleteServiceSpecificCredential` | ⛔ Not applicable | CodeCommit credentials; the service does not exist here. |
|
||||
| `DeleteSigningCertificate` | ⛔ Not applicable | X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS. |
|
||||
| `DeleteUser` | ✅ Implemented | |
|
||||
| `DeleteUserPermissionsBoundary` | ❌ Not implemented | |
|
||||
| `DeleteUserPolicy` | ✅ Implemented | |
|
||||
| `DeleteVirtualMFADevice` | ❌ Not implemented | |
|
||||
| `DetachGroupPolicy` | ✅ Implemented | |
|
||||
| `DetachRolePolicy` | ✅ Implemented | |
|
||||
| `DetachUserPolicy` | ✅ Implemented | |
|
||||
| `EnableMFADevice` | ❌ Not implemented | |
|
||||
| `GenerateCredentialReport` | ❌ Not implemented | |
|
||||
| `GenerateOrganizationsAccessReport` | ⛔ Not applicable | AWS Organizations is not offered, so there is no organization to report on. |
|
||||
| `GenerateServiceLastAccessedDetails` | ❌ Not implemented | |
|
||||
| `GetAccessKeyLastUsed` | ❌ Not implemented | |
|
||||
| `GetAccountAuthorizationDetails` | ❌ Not implemented | |
|
||||
| `GetAccountPasswordPolicy` | ❌ Not implemented | |
|
||||
| `GetAccountSummary` | ✅ Implemented | |
|
||||
| `GetContextKeysForCustomPolicy` | ❌ Not implemented | |
|
||||
| `GetContextKeysForPrincipalPolicy` | ❌ Not implemented | |
|
||||
| `GetCredentialReport` | ❌ Not implemented | |
|
||||
| `GetGroup` | ✅ Implemented | |
|
||||
| `GetGroupPolicy` | ✅ Implemented | |
|
||||
| `GetInstanceProfile` | ✅ Implemented | |
|
||||
| `GetLoginProfile` | ❌ Not implemented | |
|
||||
| `GetMFADevice` | ❌ Not implemented | |
|
||||
| `GetOpenIDConnectProvider` | ✅ Implemented | |
|
||||
| `GetOrganizationsAccessReport` | ⛔ Not applicable | AWS Organizations is not offered, so there is no organization to report on. |
|
||||
| `GetPolicy` | ✅ Implemented | |
|
||||
| `GetPolicyVersion` | ✅ Implemented | |
|
||||
| `GetRole` | ✅ Implemented | |
|
||||
| `GetRolePolicy` | ✅ Implemented | |
|
||||
| `GetSAMLProvider` | ❌ Not implemented | |
|
||||
| `GetSSHPublicKey` | ⛔ Not applicable | CodeCommit SSH keys; the service does not exist here. |
|
||||
| `GetServerCertificate` | ❌ Not implemented | |
|
||||
| `GetServiceLastAccessedDetails` | ❌ Not implemented | |
|
||||
| `GetServiceLastAccessedDetailsWithEntities` | ❌ Not implemented | |
|
||||
| `GetServiceLinkedRoleDeletionStatus` | ⛔ Not applicable | Service-linked roles exist for AWS service principals, which this platform has none of. |
|
||||
| `GetUser` | ✅ Implemented | |
|
||||
| `GetUserPolicy` | ✅ Implemented | |
|
||||
| `ListAccessKeys` | ✅ Implemented | |
|
||||
| `ListAccountAliases` | ❌ Not implemented | |
|
||||
| `ListAttachedGroupPolicies` | ✅ Implemented | |
|
||||
| `ListAttachedRolePolicies` | ✅ Implemented | |
|
||||
| `ListAttachedUserPolicies` | ✅ Implemented | |
|
||||
| `ListEntitiesForPolicy` | ❌ Not implemented | |
|
||||
| `ListGroupPolicies` | ✅ Implemented | |
|
||||
| `ListGroups` | ✅ Implemented | |
|
||||
| `ListGroupsForUser` | ✅ Implemented | |
|
||||
| `ListInstanceProfileTags` | ✅ Implemented | |
|
||||
| `ListInstanceProfiles` | ✅ Implemented | |
|
||||
| `ListInstanceProfilesForRole` | ✅ Implemented | |
|
||||
| `ListMFADeviceTags` | ❌ Not implemented | |
|
||||
| `ListMFADevices` | ❌ Not implemented | |
|
||||
| `ListOpenIDConnectProviderTags` | ✅ Implemented | |
|
||||
| `ListOpenIDConnectProviders` | ✅ Implemented | |
|
||||
| `ListPolicies` | ✅ Implemented | |
|
||||
| `ListPoliciesGrantingServiceAccess` | ❌ Not implemented | |
|
||||
| `ListPolicyTags` | ✅ Implemented | |
|
||||
| `ListPolicyVersions` | ✅ Implemented | |
|
||||
| `ListRolePolicies` | ✅ Implemented | |
|
||||
| `ListRoleTags` | ✅ Implemented | |
|
||||
| `ListRoles` | ✅ Implemented | |
|
||||
| `ListSAMLProviderTags` | ❌ Not implemented | |
|
||||
| `ListSAMLProviders` | ❌ Not implemented | |
|
||||
| `ListSSHPublicKeys` | ⛔ Not applicable | CodeCommit SSH keys; the service does not exist here. |
|
||||
| `ListServerCertificateTags` | ❌ Not implemented | |
|
||||
| `ListServerCertificates` | ❌ Not implemented | |
|
||||
| `ListServiceSpecificCredentials` | ⛔ Not applicable | CodeCommit credentials; the service does not exist here. |
|
||||
| `ListSigningCertificates` | ⛔ Not applicable | X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS. |
|
||||
| `ListUserPolicies` | ✅ Implemented | |
|
||||
| `ListUserTags` | ✅ Implemented | |
|
||||
| `ListUsers` | ✅ Implemented | |
|
||||
| `ListVirtualMFADevices` | ❌ Not implemented | |
|
||||
| `PutGroupPolicy` | ✅ Implemented | |
|
||||
| `PutRolePermissionsBoundary` | ❌ Not implemented | |
|
||||
| `PutRolePolicy` | ✅ Implemented | |
|
||||
| `PutUserPermissionsBoundary` | ❌ Not implemented | |
|
||||
| `PutUserPolicy` | ✅ Implemented | |
|
||||
| `RemoveClientIDFromOpenIDConnectProvider` | ❌ Not implemented | |
|
||||
| `RemoveRoleFromInstanceProfile` | ✅ Implemented | |
|
||||
| `RemoveUserFromGroup` | ✅ Implemented | |
|
||||
| `ResetServiceSpecificCredential` | ⛔ Not applicable | CodeCommit credentials; the service does not exist here. |
|
||||
| `ResyncMFADevice` | ❌ Not implemented | |
|
||||
| `SetDefaultPolicyVersion` | ❌ Not implemented | |
|
||||
| `SetSecurityTokenServicePreferences` | ❌ Not implemented | |
|
||||
| `SimulateCustomPolicy` | ❌ Not implemented | |
|
||||
| `SimulatePrincipalPolicy` | ❌ Not implemented | |
|
||||
| `TagInstanceProfile` | ✅ Implemented | |
|
||||
| `TagMFADevice` | ❌ Not implemented | |
|
||||
| `TagOpenIDConnectProvider` | ✅ Implemented | |
|
||||
| `TagPolicy` | ✅ Implemented | |
|
||||
| `TagRole` | ✅ Implemented | |
|
||||
| `TagSAMLProvider` | ❌ Not implemented | |
|
||||
| `TagServerCertificate` | ❌ Not implemented | |
|
||||
| `TagUser` | ✅ Implemented | |
|
||||
| `UntagInstanceProfile` | ✅ Implemented | |
|
||||
| `UntagMFADevice` | ❌ Not implemented | |
|
||||
| `UntagOpenIDConnectProvider` | ✅ Implemented | |
|
||||
| `UntagPolicy` | ✅ Implemented | |
|
||||
| `UntagRole` | ✅ Implemented | |
|
||||
| `UntagSAMLProvider` | ❌ Not implemented | |
|
||||
| `UntagServerCertificate` | ❌ Not implemented | |
|
||||
| `UntagUser` | ✅ Implemented | |
|
||||
| `UpdateAccessKey` | ✅ Implemented | |
|
||||
| `UpdateAccountPasswordPolicy` | ❌ Not implemented | |
|
||||
| `UpdateAssumeRolePolicy` | ✅ Implemented | |
|
||||
| `UpdateGroup` | ❌ Not implemented | |
|
||||
| `UpdateLoginProfile` | ❌ Not implemented | |
|
||||
| `UpdateOpenIDConnectProviderThumbprint` | ❌ Not implemented | |
|
||||
| `UpdateRole` | ✅ Implemented | |
|
||||
| `UpdateRoleDescription` | ❌ Not implemented | |
|
||||
| `UpdateSAMLProvider` | ❌ Not implemented | |
|
||||
| `UpdateSSHPublicKey` | ⛔ Not applicable | CodeCommit SSH keys; the service does not exist here. |
|
||||
| `UpdateServerCertificate` | ❌ Not implemented | |
|
||||
| `UpdateServiceSpecificCredential` | ⛔ Not applicable | CodeCommit credentials; the service does not exist here. |
|
||||
| `UpdateSigningCertificate` | ⛔ Not applicable | X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS. |
|
||||
| `UpdateUser` | ❌ Not implemented | |
|
||||
| `UploadSSHPublicKey` | ⛔ Not applicable | CodeCommit SSH keys; the service does not exist here. |
|
||||
| `UploadServerCertificate` | ❌ Not implemented | |
|
||||
| `UploadSigningCertificate` | ⛔ Not applicable | X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS. |
|
||||
| Operation | Status |
|
||||
|---|---|
|
||||
| `AddClientIDToOpenIDConnectProvider` | ❌ Not implemented |
|
||||
| `AddRoleToInstanceProfile` | ✅ Implemented |
|
||||
| `AddUserToGroup` | ✅ Implemented |
|
||||
| `AttachGroupPolicy` | ✅ Implemented |
|
||||
| `AttachRolePolicy` | ✅ Implemented |
|
||||
| `AttachUserPolicy` | ✅ Implemented |
|
||||
| `ChangePassword` | ❌ Not implemented |
|
||||
| `CreateAccessKey` | ✅ Implemented |
|
||||
| `CreateAccountAlias` | ❌ Not implemented |
|
||||
| `CreateGroup` | ✅ Implemented |
|
||||
| `CreateInstanceProfile` | ✅ Implemented |
|
||||
| `CreateLoginProfile` | ❌ Not implemented |
|
||||
| `CreateOpenIDConnectProvider` | ✅ Implemented |
|
||||
| `CreatePolicy` | ✅ Implemented |
|
||||
| `CreatePolicyVersion` | ❌ Not implemented |
|
||||
| `CreateRole` | ✅ Implemented |
|
||||
| `CreateSAMLProvider` | ❌ Not implemented |
|
||||
| `CreateServiceLinkedRole` | ⛔ Not applicable [3](#notes) |
|
||||
| `CreateServiceSpecificCredential` | ⛔ Not applicable [1](#notes) |
|
||||
| `CreateUser` | ✅ Implemented |
|
||||
| `CreateVirtualMFADevice` | ❌ Not implemented |
|
||||
| `DeactivateMFADevice` | ❌ Not implemented |
|
||||
| `DeleteAccessKey` | ✅ Implemented |
|
||||
| `DeleteAccountAlias` | ❌ Not implemented |
|
||||
| `DeleteAccountPasswordPolicy` | ❌ Not implemented |
|
||||
| `DeleteGroup` | ✅ Implemented |
|
||||
| `DeleteGroupPolicy` | ✅ Implemented |
|
||||
| `DeleteInstanceProfile` | ✅ Implemented |
|
||||
| `DeleteLoginProfile` | ❌ Not implemented |
|
||||
| `DeleteOpenIDConnectProvider` | ✅ Implemented |
|
||||
| `DeletePolicy` | ✅ Implemented |
|
||||
| `DeletePolicyVersion` | ❌ Not implemented |
|
||||
| `DeleteRole` | ✅ Implemented |
|
||||
| `DeleteRolePermissionsBoundary` | ❌ Not implemented |
|
||||
| `DeleteRolePolicy` | ✅ Implemented |
|
||||
| `DeleteSAMLProvider` | ❌ Not implemented |
|
||||
| `DeleteSSHPublicKey` | ⛔ Not applicable [1](#notes) |
|
||||
| `DeleteServerCertificate` | ❌ Not implemented |
|
||||
| `DeleteServiceLinkedRole` | ⛔ Not applicable [3](#notes) |
|
||||
| `DeleteServiceSpecificCredential` | ⛔ Not applicable [1](#notes) |
|
||||
| `DeleteSigningCertificate` | ⛔ Not applicable [4](#notes) |
|
||||
| `DeleteUser` | ✅ Implemented |
|
||||
| `DeleteUserPermissionsBoundary` | ❌ Not implemented |
|
||||
| `DeleteUserPolicy` | ✅ Implemented |
|
||||
| `DeleteVirtualMFADevice` | ❌ Not implemented |
|
||||
| `DetachGroupPolicy` | ✅ Implemented |
|
||||
| `DetachRolePolicy` | ✅ Implemented |
|
||||
| `DetachUserPolicy` | ✅ Implemented |
|
||||
| `EnableMFADevice` | ❌ Not implemented |
|
||||
| `GenerateCredentialReport` | ❌ Not implemented |
|
||||
| `GenerateOrganizationsAccessReport` | ⛔ Not applicable [2](#notes) |
|
||||
| `GenerateServiceLastAccessedDetails` | ❌ Not implemented |
|
||||
| `GetAccessKeyLastUsed` | ❌ Not implemented |
|
||||
| `GetAccountAuthorizationDetails` | ❌ Not implemented |
|
||||
| `GetAccountPasswordPolicy` | ❌ Not implemented |
|
||||
| `GetAccountSummary` | ✅ Implemented |
|
||||
| `GetContextKeysForCustomPolicy` | ❌ Not implemented |
|
||||
| `GetContextKeysForPrincipalPolicy` | ❌ Not implemented |
|
||||
| `GetCredentialReport` | ❌ Not implemented |
|
||||
| `GetGroup` | ✅ Implemented |
|
||||
| `GetGroupPolicy` | ✅ Implemented |
|
||||
| `GetInstanceProfile` | ✅ Implemented |
|
||||
| `GetLoginProfile` | ❌ Not implemented |
|
||||
| `GetMFADevice` | ❌ Not implemented |
|
||||
| `GetOpenIDConnectProvider` | ✅ Implemented |
|
||||
| `GetOrganizationsAccessReport` | ⛔ Not applicable [2](#notes) |
|
||||
| `GetPolicy` | ✅ Implemented |
|
||||
| `GetPolicyVersion` | ✅ Implemented |
|
||||
| `GetRole` | ✅ Implemented |
|
||||
| `GetRolePolicy` | ✅ Implemented |
|
||||
| `GetSAMLProvider` | ❌ Not implemented |
|
||||
| `GetSSHPublicKey` | ⛔ Not applicable [1](#notes) |
|
||||
| `GetServerCertificate` | ❌ Not implemented |
|
||||
| `GetServiceLastAccessedDetails` | ❌ Not implemented |
|
||||
| `GetServiceLastAccessedDetailsWithEntities` | ❌ Not implemented |
|
||||
| `GetServiceLinkedRoleDeletionStatus` | ⛔ Not applicable [3](#notes) |
|
||||
| `GetUser` | ✅ Implemented |
|
||||
| `GetUserPolicy` | ✅ Implemented |
|
||||
| `ListAccessKeys` | ✅ Implemented |
|
||||
| `ListAccountAliases` | ❌ Not implemented |
|
||||
| `ListAttachedGroupPolicies` | ✅ Implemented |
|
||||
| `ListAttachedRolePolicies` | ✅ Implemented |
|
||||
| `ListAttachedUserPolicies` | ✅ Implemented |
|
||||
| `ListEntitiesForPolicy` | ❌ Not implemented |
|
||||
| `ListGroupPolicies` | ✅ Implemented |
|
||||
| `ListGroups` | ✅ Implemented |
|
||||
| `ListGroupsForUser` | ✅ Implemented |
|
||||
| `ListInstanceProfileTags` | ✅ Implemented |
|
||||
| `ListInstanceProfiles` | ✅ Implemented |
|
||||
| `ListInstanceProfilesForRole` | ✅ Implemented |
|
||||
| `ListMFADeviceTags` | ❌ Not implemented |
|
||||
| `ListMFADevices` | ❌ Not implemented |
|
||||
| `ListOpenIDConnectProviderTags` | ✅ Implemented |
|
||||
| `ListOpenIDConnectProviders` | ✅ Implemented |
|
||||
| `ListPolicies` | ✅ Implemented |
|
||||
| `ListPoliciesGrantingServiceAccess` | ❌ Not implemented |
|
||||
| `ListPolicyTags` | ✅ Implemented |
|
||||
| `ListPolicyVersions` | ✅ Implemented |
|
||||
| `ListRolePolicies` | ✅ Implemented |
|
||||
| `ListRoleTags` | ✅ Implemented |
|
||||
| `ListRoles` | ✅ Implemented |
|
||||
| `ListSAMLProviderTags` | ❌ Not implemented |
|
||||
| `ListSAMLProviders` | ❌ Not implemented |
|
||||
| `ListSSHPublicKeys` | ⛔ Not applicable [1](#notes) |
|
||||
| `ListServerCertificateTags` | ❌ Not implemented |
|
||||
| `ListServerCertificates` | ❌ Not implemented |
|
||||
| `ListServiceSpecificCredentials` | ⛔ Not applicable [1](#notes) |
|
||||
| `ListSigningCertificates` | ⛔ Not applicable [4](#notes) |
|
||||
| `ListUserPolicies` | ✅ Implemented |
|
||||
| `ListUserTags` | ✅ Implemented |
|
||||
| `ListUsers` | ✅ Implemented |
|
||||
| `ListVirtualMFADevices` | ❌ Not implemented |
|
||||
| `PutGroupPolicy` | ✅ Implemented |
|
||||
| `PutRolePermissionsBoundary` | ❌ Not implemented |
|
||||
| `PutRolePolicy` | ✅ Implemented |
|
||||
| `PutUserPermissionsBoundary` | ❌ Not implemented |
|
||||
| `PutUserPolicy` | ✅ Implemented |
|
||||
| `RemoveClientIDFromOpenIDConnectProvider` | ❌ Not implemented |
|
||||
| `RemoveRoleFromInstanceProfile` | ✅ Implemented |
|
||||
| `RemoveUserFromGroup` | ✅ Implemented |
|
||||
| `ResetServiceSpecificCredential` | ⛔ Not applicable [1](#notes) |
|
||||
| `ResyncMFADevice` | ❌ Not implemented |
|
||||
| `SetDefaultPolicyVersion` | ❌ Not implemented |
|
||||
| `SetSecurityTokenServicePreferences` | ❌ Not implemented |
|
||||
| `SimulateCustomPolicy` | ❌ Not implemented |
|
||||
| `SimulatePrincipalPolicy` | ❌ Not implemented |
|
||||
| `TagInstanceProfile` | ✅ Implemented |
|
||||
| `TagMFADevice` | ❌ Not implemented |
|
||||
| `TagOpenIDConnectProvider` | ✅ Implemented |
|
||||
| `TagPolicy` | ✅ Implemented |
|
||||
| `TagRole` | ✅ Implemented |
|
||||
| `TagSAMLProvider` | ❌ Not implemented |
|
||||
| `TagServerCertificate` | ❌ Not implemented |
|
||||
| `TagUser` | ✅ Implemented |
|
||||
| `UntagInstanceProfile` | ✅ Implemented |
|
||||
| `UntagMFADevice` | ❌ Not implemented |
|
||||
| `UntagOpenIDConnectProvider` | ✅ Implemented |
|
||||
| `UntagPolicy` | ✅ Implemented |
|
||||
| `UntagRole` | ✅ Implemented |
|
||||
| `UntagSAMLProvider` | ❌ Not implemented |
|
||||
| `UntagServerCertificate` | ❌ Not implemented |
|
||||
| `UntagUser` | ✅ Implemented |
|
||||
| `UpdateAccessKey` | ✅ Implemented |
|
||||
| `UpdateAccountPasswordPolicy` | ❌ Not implemented |
|
||||
| `UpdateAssumeRolePolicy` | ✅ Implemented |
|
||||
| `UpdateGroup` | ❌ Not implemented |
|
||||
| `UpdateLoginProfile` | ❌ Not implemented |
|
||||
| `UpdateOpenIDConnectProviderThumbprint` | ❌ Not implemented |
|
||||
| `UpdateRole` | ✅ Implemented |
|
||||
| `UpdateRoleDescription` | ❌ Not implemented |
|
||||
| `UpdateSAMLProvider` | ❌ Not implemented |
|
||||
| `UpdateSSHPublicKey` | ⛔ Not applicable [1](#notes) |
|
||||
| `UpdateServerCertificate` | ❌ Not implemented |
|
||||
| `UpdateServiceSpecificCredential` | ⛔ Not applicable [1](#notes) |
|
||||
| `UpdateSigningCertificate` | ⛔ Not applicable [4](#notes) |
|
||||
| `UpdateUser` | ❌ Not implemented |
|
||||
| `UploadSSHPublicKey` | ⛔ Not applicable [1](#notes) |
|
||||
| `UploadServerCertificate` | ❌ Not implemented |
|
||||
| `UploadSigningCertificate` | ⛔ Not applicable [4](#notes) |
|
||||
|
||||
### Notes
|
||||
|
||||
1. CodeCommit credentials and SSH keys; the service does not exist here.
|
||||
2. AWS Organizations is not offered, so there is no organization to report on.
|
||||
3. Service-linked roles exist for AWS service principals, which this platform has none of.
|
||||
4. X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS.
|
||||
|
||||
@@ -45,7 +45,10 @@
|
||||
"vpc"
|
||||
],
|
||||
"notApplicable": {
|
||||
"DescribeSpotPriceHistory": "On owned hardware there is no spot-to-on-demand price differential, so any figure would be invented."
|
||||
"DescribeSpotPriceHistory": "spot-price"
|
||||
},
|
||||
"notes": {
|
||||
"spot-price": "On owned hardware there is no spot-to-on-demand price differential, so any figure would be invented."
|
||||
}
|
||||
},
|
||||
"ecr": {
|
||||
@@ -123,25 +126,31 @@
|
||||
"policies"
|
||||
],
|
||||
"notApplicable": {
|
||||
"CreateServiceLinkedRole": "Service-linked roles exist for AWS service principals, which this platform has none of.",
|
||||
"CreateServiceSpecificCredential": "CodeCommit credentials; the service does not exist here.",
|
||||
"DeleteSSHPublicKey": "CodeCommit SSH keys; the service does not exist here.",
|
||||
"DeleteServiceLinkedRole": "Service-linked roles exist for AWS service principals, which this platform has none of.",
|
||||
"DeleteServiceSpecificCredential": "CodeCommit credentials; the service does not exist here.",
|
||||
"DeleteSigningCertificate": "X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS.",
|
||||
"GenerateOrganizationsAccessReport": "AWS Organizations is not offered, so there is no organization to report on.",
|
||||
"GetOrganizationsAccessReport": "AWS Organizations is not offered, so there is no organization to report on.",
|
||||
"GetSSHPublicKey": "CodeCommit SSH keys; the service does not exist here.",
|
||||
"GetServiceLinkedRoleDeletionStatus": "Service-linked roles exist for AWS service principals, which this platform has none of.",
|
||||
"ListSSHPublicKeys": "CodeCommit SSH keys; the service does not exist here.",
|
||||
"ListServiceSpecificCredentials": "CodeCommit credentials; the service does not exist here.",
|
||||
"ListSigningCertificates": "X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS.",
|
||||
"ResetServiceSpecificCredential": "CodeCommit credentials; the service does not exist here.",
|
||||
"UpdateSSHPublicKey": "CodeCommit SSH keys; the service does not exist here.",
|
||||
"UpdateServiceSpecificCredential": "CodeCommit credentials; the service does not exist here.",
|
||||
"UpdateSigningCertificate": "X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS.",
|
||||
"UploadSSHPublicKey": "CodeCommit SSH keys; the service does not exist here.",
|
||||
"UploadSigningCertificate": "X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS."
|
||||
"CreateServiceLinkedRole": "service-linked-roles",
|
||||
"CreateServiceSpecificCredential": "codecommit",
|
||||
"DeleteSSHPublicKey": "codecommit",
|
||||
"DeleteServiceLinkedRole": "service-linked-roles",
|
||||
"DeleteServiceSpecificCredential": "codecommit",
|
||||
"DeleteSigningCertificate": "signing-certificates",
|
||||
"GenerateOrganizationsAccessReport": "organizations",
|
||||
"GetOrganizationsAccessReport": "organizations",
|
||||
"GetSSHPublicKey": "codecommit",
|
||||
"GetServiceLinkedRoleDeletionStatus": "service-linked-roles",
|
||||
"ListSSHPublicKeys": "codecommit",
|
||||
"ListServiceSpecificCredentials": "codecommit",
|
||||
"ListSigningCertificates": "signing-certificates",
|
||||
"ResetServiceSpecificCredential": "codecommit",
|
||||
"UpdateSSHPublicKey": "codecommit",
|
||||
"UpdateServiceSpecificCredential": "codecommit",
|
||||
"UpdateSigningCertificate": "signing-certificates",
|
||||
"UploadSSHPublicKey": "codecommit",
|
||||
"UploadSigningCertificate": "signing-certificates"
|
||||
},
|
||||
"notes": {
|
||||
"codecommit": "CodeCommit credentials and SSH keys; the service does not exist here.",
|
||||
"organizations": "AWS Organizations is not offered, so there is no organization to report on.",
|
||||
"service-linked-roles": "Service-linked roles exist for AWS service principals, which this platform has none of.",
|
||||
"signing-certificates": "X.509 signing certificates are an EC2-Classic SOAP credential, retired by AWS."
|
||||
}
|
||||
},
|
||||
"rds": {
|
||||
|
||||
@@ -19,7 +19,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **26 of the 162** operations (16.0%) in the RDS `2014-10-31` API model.
|
||||
Spinifex implements **26 of the 162** operations (**16.0%**) in the RDS `2014-10-31` API model.
|
||||
|
||||
### Engines
|
||||
|
||||
@@ -41,7 +41,34 @@ Enforcement requires that the connection is encrypted, not that the client valid
|
||||
|
||||
### Rejected parameters
|
||||
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected rather than silently dropped — `MultiAZ=true` on a single-AZ platform, `PubliclyAccessible=true` against a private endpoint, `StorageEncrypted=false` where unencrypted storage is not offered. Parameters that are merely inert 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. Parameters that are merely inert — `AutoMinorVersionUpgrade`, `CopyTagsToSnapshot`, `DeleteAutomatedBackups`, Performance Insights and Enhanced Monitoring fields — are accepted as no-ops.
|
||||
|
||||
| Parameter | Why it is rejected |
|
||||
|-----------|--------------------|
|
||||
| `MultiAZ=true` | Single-AZ platform; a standby would not exist |
|
||||
| `PubliclyAccessible=true` | The endpoint is a private VPC address |
|
||||
| `StorageEncrypted=false` | Unencrypted storage is not offered |
|
||||
| `EnableIAMDatabaseAuthentication` | IAM database authentication is not implemented |
|
||||
| `Iops`, `StorageThroughput`, `StorageType` ≠ `gp3` | Provisioned performance classes are not implemented |
|
||||
| `KmsKeyId`, `TdeCredentialArn` | Storage is encrypted with the cluster key, not a customer-managed one |
|
||||
| `AvailabilityZone` | The platform exposes a single zone |
|
||||
| `AvailabilityZoneGroup` (orderable options) | It selects a zone or local-zone group, and naming a zone is already refused |
|
||||
| `DBSecurityGroups` | EC2-Classic security groups — use `VpcSecurityGroupIds` |
|
||||
| `DBClusterIdentifier`, `DBClusterSnapshotIdentifier` | Clustered engines are not offered |
|
||||
| `EnableCloudwatchLogsExports` | Log export is not implemented |
|
||||
| `EngineVersion` other than the engine's pin, `Engine` on modify | No in-place engine or version change |
|
||||
| `Engine=mysql` (and Aurora engines) | Oracle MySQL is not offered; `mariadb` is a distinct engine, not an alias for it |
|
||||
| `NewDBInstanceIdentifier` | The identifier is the DNS label and the KV key |
|
||||
| `DBPortNumber`, `DBSubnetGroupName` on modify | Both would move the endpoint |
|
||||
| `MaxAllocatedStorage` | Storage autoscaling is not implemented |
|
||||
| `ManageMasterUserPassword`, `RotateMasterUserPassword` | Secrets Manager integration is not offered |
|
||||
| `CACertificateIdentifier` | The serving certificate is minted from the cluster CA |
|
||||
| `Domain`, `DomainFqdn` | Active Directory domain join is not offered |
|
||||
| `OptionGroupName` | Option groups are not offered |
|
||||
| `CustomIamInstanceProfile` | The DB VM's instance profile is platform-owned |
|
||||
| `EnableCustomerOwnedIp` | An Outposts feature |
|
||||
| `ForceFailover` (reboot) | No standby to fail over to |
|
||||
| `DBSnapshotIdentifier` (stop) | Snapshot-on-stop is not implemented |
|
||||
|
||||
### Operations
|
||||
|
||||
|
||||
@@ -18,4 +18,31 @@ Enforcement requires that the connection is encrypted, not that the client valid
|
||||
|
||||
### Rejected parameters
|
||||
|
||||
A parameter whose omission would create a false safety, security or availability guarantee is rejected rather than silently dropped — `MultiAZ=true` on a single-AZ platform, `PubliclyAccessible=true` against a private endpoint, `StorageEncrypted=false` where unencrypted storage is not offered. Parameters that are merely inert 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. Parameters that are merely inert — `AutoMinorVersionUpgrade`, `CopyTagsToSnapshot`, `DeleteAutomatedBackups`, Performance Insights and Enhanced Monitoring fields — are accepted as no-ops.
|
||||
|
||||
| Parameter | Why it is rejected |
|
||||
|-----------|--------------------|
|
||||
| `MultiAZ=true` | Single-AZ platform; a standby would not exist |
|
||||
| `PubliclyAccessible=true` | The endpoint is a private VPC address |
|
||||
| `StorageEncrypted=false` | Unencrypted storage is not offered |
|
||||
| `EnableIAMDatabaseAuthentication` | IAM database authentication is not implemented |
|
||||
| `Iops`, `StorageThroughput`, `StorageType` ≠ `gp3` | Provisioned performance classes are not implemented |
|
||||
| `KmsKeyId`, `TdeCredentialArn` | Storage is encrypted with the cluster key, not a customer-managed one |
|
||||
| `AvailabilityZone` | The platform exposes a single zone |
|
||||
| `AvailabilityZoneGroup` (orderable options) | It selects a zone or local-zone group, and naming a zone is already refused |
|
||||
| `DBSecurityGroups` | EC2-Classic security groups — use `VpcSecurityGroupIds` |
|
||||
| `DBClusterIdentifier`, `DBClusterSnapshotIdentifier` | Clustered engines are not offered |
|
||||
| `EnableCloudwatchLogsExports` | Log export is not implemented |
|
||||
| `EngineVersion` other than the engine's pin, `Engine` on modify | No in-place engine or version change |
|
||||
| `Engine=mysql` (and Aurora engines) | Oracle MySQL is not offered; `mariadb` is a distinct engine, not an alias for it |
|
||||
| `NewDBInstanceIdentifier` | The identifier is the DNS label and the KV key |
|
||||
| `DBPortNumber`, `DBSubnetGroupName` on modify | Both would move the endpoint |
|
||||
| `MaxAllocatedStorage` | Storage autoscaling is not implemented |
|
||||
| `ManageMasterUserPassword`, `RotateMasterUserPassword` | Secrets Manager integration is not offered |
|
||||
| `CACertificateIdentifier` | The serving certificate is minted from the cluster CA |
|
||||
| `Domain`, `DomainFqdn` | Active Directory domain join is not offered |
|
||||
| `OptionGroupName` | Option groups are not offered |
|
||||
| `CustomIamInstanceProfile` | The DB VM's instance profile is platform-owned |
|
||||
| `EnableCustomerOwnedIp` | An Outposts feature |
|
||||
| `ForceFailover` (reboot) | No standby to fail over to |
|
||||
| `DBSnapshotIdentifier` (stop) | Snapshot-on-stop is not implemented |
|
||||
|
||||
@@ -18,7 +18,7 @@ tags:
|
||||
|
||||
## Overview
|
||||
|
||||
Spinifex implements **4 of the 8** operations (50.0%) in the STS `2011-06-15` API model.
|
||||
Spinifex implements **4 of the 8** operations (**50.0%**) in the STS `2011-06-15` API model.
|
||||
|
||||
### Trust policies
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ sections:
|
||||
- instructions
|
||||
- troubleshooting
|
||||
resources:
|
||||
- title: "RDS CLI Reference"
|
||||
url: "https://github.com/mulgadc/spinifex/blob/main/docs/COMMANDS.md#rds-postgresql-and-mariadb"
|
||||
- title: "RDS API Coverage"
|
||||
url: "/docs/rds-api-coverage"
|
||||
- title: "Terraform AWS Provider — aws_db_instance"
|
||||
url: "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_instance"
|
||||
- title: "Spinifex Repository"
|
||||
@@ -30,7 +30,7 @@ resources:
|
||||
|
||||
> The smallest end-to-end RDS example on Spinifex: a VPC with a public client subnet and a private DB subnet, a DB subnet group, a parameter group, a PostgreSQL DB instance, and a client VM with `psql` already pointed at the endpoint.
|
||||
|
||||
This workbook is **PostgreSQL throughout** — the engine, the `postgres18` parameter group, port `5432`, the client package and the `~/.pgpass` credential are all PostgreSQL's. Spinifex also serves MariaDB 11.8 under `engine = "mariadb"`; running this workbook against it means changing `engine`, `engine_version`, the parameter-group `family` to `mariadb11.8`, the security-group port to `3306` and the client to `mariadb-client`. See the [RDS command reference](https://github.com/mulgadc/spinifex/blob/main/docs/COMMANDS.md#rds-postgresql-and-mariadb) for both engines' pins, families and limits. Note that `mysql` is not an accepted engine and is not an alias for `mariadb`.
|
||||
This workbook is **PostgreSQL throughout** — the engine, the `postgres18` parameter group, port `5432`, the client package and the `~/.pgpass` credential are all PostgreSQL's. Spinifex also serves MariaDB 11.8 under `engine = "mariadb"`; running this workbook against it means changing `engine`, `engine_version`, the parameter-group `family` to `mariadb11.8`, the security-group port to `3306` and the client to `mariadb-client`. See the [RDS API coverage page](/docs/rds-api-coverage) for both engines' pins, families and limits. Note that `mysql` is not an accepted engine and is not an alias for `mariadb`.
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
+76
-26
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
@@ -31,11 +32,12 @@ const (
|
||||
|
||||
var slugPattern = regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`)
|
||||
|
||||
// OperationStatus is one row of a published coverage table.
|
||||
// OperationStatus is one row of a published coverage table. NoteKey names the
|
||||
// shared explanation behind the row's status, where one is declared.
|
||||
type OperationStatus struct {
|
||||
Operation string
|
||||
Status string
|
||||
Note string
|
||||
NoteKey string
|
||||
}
|
||||
|
||||
// ImplementedPercent is the share of modelled operations bound to a real
|
||||
@@ -51,18 +53,18 @@ func (c OperationCoverage) ImplementedPercent() float64 {
|
||||
// followed by the registered operations the pinned model does not describe.
|
||||
//
|
||||
// notApplicable declares operations the platform will never serve, mapped to
|
||||
// the reason why. A refusing handler is the same fact reached mechanically, so
|
||||
// both publish as StatusNotApplicable; the declaration only adds the reason.
|
||||
// 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) {
|
||||
registered := toSet(c.Registered)
|
||||
stubbed := toSet(c.Stubbed)
|
||||
unsupported := toSet(c.Unsupported)
|
||||
modelled := toSet(c.Modelled)
|
||||
|
||||
for operation, reason := range notApplicable {
|
||||
for operation, noteKey := range notApplicable {
|
||||
switch {
|
||||
case reason == "":
|
||||
return nil, fmt.Errorf("awsmodel: %s operation %q is declared not applicable with no reason", c.Service, operation)
|
||||
case noteKey == "":
|
||||
return nil, fmt.Errorf("awsmodel: %s operation %q is declared not applicable with no note", c.Service, operation)
|
||||
case !modelled[operation]:
|
||||
return nil, fmt.Errorf("awsmodel: %s operation %q is declared not applicable but is not in the pinned model", c.Service, operation)
|
||||
case registered[operation] && !unsupported[operation]:
|
||||
@@ -81,8 +83,8 @@ func (c OperationCoverage) OperationStatuses(notApplicable map[string]string) ([
|
||||
case registered[operation]:
|
||||
status = StatusImplemented
|
||||
}
|
||||
if reason, ok := notApplicable[operation]; ok {
|
||||
statuses = append(statuses, OperationStatus{Operation: operation, Status: StatusNotApplicable, Note: reason})
|
||||
if noteKey, ok := notApplicable[operation]; ok {
|
||||
statuses = append(statuses, OperationStatus{Operation: operation, Status: StatusNotApplicable, NoteKey: noteKey})
|
||||
continue
|
||||
}
|
||||
statuses = append(statuses, OperationStatus{Operation: operation, Status: status})
|
||||
@@ -104,9 +106,14 @@ type PageMetadata struct {
|
||||
Description string `json:"description"`
|
||||
Tags []string `json:"tags"`
|
||||
|
||||
// NotApplicable maps an operation the platform will never serve to the
|
||||
// reason why. Checked against the model and the dispatch tables at render,
|
||||
// so a typo or a later implementation fails the build rather than lying.
|
||||
// Notes are the shared explanations a page footnotes, keyed by a short
|
||||
// name. One note covers every operation that shares a reason.
|
||||
Notes map[string]string `json:"notes,omitempty"`
|
||||
|
||||
// NotApplicable maps an operation the platform will never serve to the key
|
||||
// of the note explaining why. Checked against the model, the notes and the
|
||||
// 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"`
|
||||
}
|
||||
|
||||
@@ -182,6 +189,42 @@ func validatePage(owner string, page PageMetadata, slugs map[string]bool) error
|
||||
return nil
|
||||
}
|
||||
|
||||
// noteOrder returns the note keys in the order they are published. Sorted by
|
||||
// key rather than by first use, so adding an operation cannot renumber a note
|
||||
// that is already published.
|
||||
func noteOrder(notes map[string]string) []string {
|
||||
keys := make([]string, 0, len(notes))
|
||||
for key := range notes {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// numberNotes assigns each note its published footnote number, rejecting a note
|
||||
// nothing references and a reference to a note that does not exist.
|
||||
func numberNotes(page PageMetadata) (map[string]int, error) {
|
||||
referenced := map[string]bool{}
|
||||
for operation, key := range page.NotApplicable {
|
||||
if _, ok := page.Notes[key]; !ok {
|
||||
return nil, fmt.Errorf("awsmodel: coverage page %s: operation %q references undefined note %q", page.Slug, operation, key)
|
||||
}
|
||||
referenced[key] = true
|
||||
}
|
||||
|
||||
numbering := make(map[string]int, len(page.Notes))
|
||||
for index, key := range noteOrder(page.Notes) {
|
||||
if !referenced[key] {
|
||||
return nil, fmt.Errorf("awsmodel: coverage page %s: note %q is never referenced", page.Slug, key)
|
||||
}
|
||||
if page.Notes[key] == "" {
|
||||
return nil, fmt.Errorf("awsmodel: coverage page %s: note %q is empty", page.Slug, key)
|
||||
}
|
||||
numbering[key] = index + 1
|
||||
}
|
||||
return numbering, nil
|
||||
}
|
||||
|
||||
// RenderServicePage renders one publishable coverage page. intro is optional
|
||||
// hand-written prose emitted above the table; it may not open a new page
|
||||
// section, so its headings must be level three or deeper.
|
||||
@@ -203,7 +246,7 @@ func RenderServicePage(coverage OperationCoverage, pages PageSet, intro string)
|
||||
writeFrontmatter(&body, page, pages.Category)
|
||||
fmt.Fprintf(&body, "# %s\n\n## Overview\n\n", page.Title)
|
||||
|
||||
fmt.Fprintf(&body, "Spinifex implements **%d of the %d** operations (%.1f%%) in the %s `%s` API model.\n\n",
|
||||
fmt.Fprintf(&body, "Spinifex implements **%d of the %d** operations (**%.1f%%**) in the %s `%s` API model.\n\n",
|
||||
len(coverage.Implemented), len(coverage.Modelled), coverage.ImplementedPercent(), page.Name, coverage.APIVersion)
|
||||
|
||||
if intro != "" {
|
||||
@@ -214,18 +257,25 @@ func RenderServicePage(coverage OperationCoverage, pages PageSet, intro string)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
body.WriteString("### Operations\n\n")
|
||||
if len(page.NotApplicable) == 0 {
|
||||
body.WriteString("| Operation | Status |\n|---|---|\n")
|
||||
for _, status := range statuses {
|
||||
fmt.Fprintf(&body, "| `%s` | %s |\n", status.Operation, status.Status)
|
||||
}
|
||||
return body.String(), nil
|
||||
numbering, err := numberNotes(page)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
body.WriteString("| Operation | Status | Notes |\n|---|---|---|\n")
|
||||
|
||||
body.WriteString("### Operations\n\n| Operation | Status |\n|---|---|\n")
|
||||
for _, status := range statuses {
|
||||
fmt.Fprintf(&body, "| `%s` | %s | %s |\n", status.Operation, status.Status, status.Note)
|
||||
if number, ok := numbering[status.NoteKey]; ok {
|
||||
fmt.Fprintf(&body, "| `%s` | %s [%d](#notes) |\n", status.Operation, status.Status, number)
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&body, "| `%s` | %s |\n", status.Operation, status.Status)
|
||||
}
|
||||
|
||||
if len(numbering) > 0 {
|
||||
body.WriteString("\n### Notes\n\n")
|
||||
for index, key := range noteOrder(page.Notes) {
|
||||
fmt.Fprintf(&body, "%d. %s\n", index+1, page.Notes[key])
|
||||
}
|
||||
}
|
||||
return body.String(), nil
|
||||
}
|
||||
@@ -240,14 +290,14 @@ func RenderIndexPage(coverages []OperationCoverage, pages PageSet, intro string)
|
||||
writeFrontmatter(&body, pages.Index, pages.Category)
|
||||
fmt.Fprintf(&body, "# %s\n\n## Overview\n\n", pages.Index.Title)
|
||||
fmt.Fprintf(&body, "Spinifex serves the AWS APIs below. Every page counts the operations in the pinned `aws-sdk-go %s` `api-2.json` model for its service and reports, operation by operation, whether Spinifex implements it.\n\n", SourceSDKVersion)
|
||||
body.WriteString("| Service | API version | Implemented | Modelled | Coverage |\n|---|---|---:|---:|---:|\n")
|
||||
body.WriteString("| Service | Implemented | Modelled | Coverage |\n|---|---:|---:|---:|\n")
|
||||
for _, coverage := range sortedCoverages(coverages) {
|
||||
page, ok := pages.Services[coverage.Service]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&body, "| [%s](/docs/%s) | %s | %d | %d | %.1f%% |\n",
|
||||
page.Name, page.Slug, coverage.APIVersion, len(coverage.Implemented), len(coverage.Modelled), coverage.ImplementedPercent())
|
||||
fmt.Fprintf(&body, "| [%s](/docs/%s) | %d | %d | %.1f%% |\n",
|
||||
page.Name, page.Slug, len(coverage.Implemented), len(coverage.Modelled), coverage.ImplementedPercent())
|
||||
}
|
||||
|
||||
if intro != "" {
|
||||
|
||||
@@ -77,7 +77,7 @@ func TestRenderServicePageCarriesEveryStatus(t *testing.T) {
|
||||
`category: "Coverage"`,
|
||||
"sections:\n - overview\n",
|
||||
"# STS API Coverage\n\n## Overview\n",
|
||||
"Spinifex implements **1 of the 8** operations (12.5%) in the STS `2011-06-15` API model.",
|
||||
"Spinifex implements **1 of the 8** operations (**12.5%**) in the STS `2011-06-15` API model.",
|
||||
"### Scope\n\nHand-written prose.",
|
||||
"| `AssumeRole` | " + StatusImplemented + " |",
|
||||
"| `GetSessionToken` | " + StatusStub + " |",
|
||||
@@ -164,13 +164,13 @@ func TestOperationStatusesRejectsStaleNotApplicableClaims(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOperationStatusesPublishesDeclaredReasons(t *testing.T) {
|
||||
func TestOperationStatusesCarriesTheNoteKey(t *testing.T) {
|
||||
coverage, err := CompareOperations(STS, DispatchInventory{Registered: []string{"AssumeRole"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
statuses, err := coverage.OperationStatuses(map[string]string{"GetFederationToken": "No federation broker."})
|
||||
statuses, err := coverage.OperationStatuses(map[string]string{"GetFederationToken": "no-broker"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -178,14 +178,77 @@ func TestOperationStatusesPublishesDeclaredReasons(t *testing.T) {
|
||||
if status.Operation != "GetFederationToken" {
|
||||
continue
|
||||
}
|
||||
if status.Status != StatusNotApplicable || status.Note != "No federation broker." {
|
||||
t.Fatalf("status = %q, note = %q", status.Status, status.Note)
|
||||
if status.Status != StatusNotApplicable || status.NoteKey != "no-broker" {
|
||||
t.Fatalf("status = %q, note key = %q", status.Status, status.NoteKey)
|
||||
}
|
||||
return
|
||||
}
|
||||
t.Fatal("declared operation is missing from the table")
|
||||
}
|
||||
|
||||
// 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) {
|
||||
pages := testPageSet(t)
|
||||
iam := pages.Services[IAM]
|
||||
if len(iam.Notes) == 0 {
|
||||
t.Skip("no notes are declared for IAM")
|
||||
}
|
||||
coverage, err := CompareOperations(IAM, DispatchInventory{Registered: []string{"CreateUser"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
page, err := RenderServicePage(coverage, pages, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(page, "\n### Notes\n\n1. ") {
|
||||
t.Errorf("page has no numbered notes section:\n%s", page)
|
||||
}
|
||||
if !strings.Contains(page, "| `UploadSSHPublicKey` | "+StatusNotApplicable+" [") {
|
||||
t.Errorf("a declared operation carries no footnote reference:\n%s", page)
|
||||
}
|
||||
for _, text := range iam.Notes {
|
||||
if strings.Count(page, text) != 1 {
|
||||
t.Errorf("note %q is not written exactly once", text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderServicePageRejectsBrokenNoteReferences(t *testing.T) {
|
||||
pages := testPageSet(t)
|
||||
coverage, err := CompareOperations(STS, DispatchInventory{Registered: []string{"AssumeRole"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sts := pages.Services[STS]
|
||||
|
||||
for name, mutate := range map[string]func(*PageMetadata){
|
||||
"undefined note": func(p *PageMetadata) {
|
||||
p.NotApplicable = map[string]string{"GetFederationToken": "nonexistent"}
|
||||
},
|
||||
"unreferenced note": func(p *PageMetadata) {
|
||||
p.Notes = map[string]string{"orphan": "Nothing points at this."}
|
||||
},
|
||||
"empty note": func(p *PageMetadata) {
|
||||
p.Notes = map[string]string{"blank": ""}
|
||||
p.NotApplicable = map[string]string{"GetFederationToken": "blank"}
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
broken := sts
|
||||
mutate(&broken)
|
||||
pages.Services[STS] = broken
|
||||
defer func() { pages.Services[STS] = sts }()
|
||||
|
||||
if _, err := RenderServicePage(coverage, pages, ""); err == nil {
|
||||
t.Fatal("RenderServicePage accepted a broken note reference")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// An opaque service has no dispatch table to count, so publishing a page for it
|
||||
// would report 0% where the truth is that the surface is served elsewhere.
|
||||
func TestRenderServicePageRefusesOpaqueCoverage(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user