Summary
When a formae apply --mode reconcile create partially fails due to a
transient plugin/API error on the Formae side (Cloud Control GetResource
polling timeout), AWS can finish creating the resource successfully while
Formae never records it as managed. For certain resource types (observed:
AWS::EKS::Nodegroup), there is then no supported recovery path back
into Formae's state — not even through the documented
discovery → extract → adopt workflow — because those resource types are
outside the AWS plugin's discovery scan scope.
Environment
- formae:
0.88.0
- AWS plugin:
0.1.16
- Resource type:
AWS::EKS::Nodegroup (also affects AWS::EKS::Cluster)
Steps to reproduce
formae apply --mode reconcile a stack containing an AWS::EKS::Cluster
with 3 AWS::EKS::Nodegroup resources.
- Introduce (or wait for) a transient Cloud Control
GetResource failure
while polling create status for one or more node groups (in our case: a
TLS handshake timeout against AWS Cloud Control). Agent logs:
Plugin operator is missing in action after the timeout.
- AWS finishes creating the node group(s) successfully in the background.
Formae's command terminates Failed and marks those specific resources
as failed creates; they are never added to Formae's managed inventory.
- Confirm directly against AWS: the node group(s) are
ACTIVE and healthy.
- Confirm against Formae:
list_resources/inventory resources for that
stack shows only the node group(s) that finished polling before the
timeout. The others are absent entirely (not listed as managed, not
listed as unmanaged).
- Trigger discovery explicitly (
force_discover / wait for the scheduled
scan). Query managed:false type:AWS::EKS::Nodegroup (or
type:AWS::EKS::Cluster): zero results, even though the resources
are live in the account discovery is configured against.
Root cause (as far as we can tell from the outside)
get_agent_stats shows the AWS plugin's discovery configuration includes an
explicit DiscoveryFilters allow-list:
AWS::EC2::Instance, AWS::EC2::SecurityGroup, AWS::EC2::NetworkInterface,
AWS::EC2::LaunchTemplate, AWS::AutoScaling::AutoScalingGroup,
AWS::EC2::VPCEndpoint, AWS::EC2::RouteTable, AWS::EC2::Subnet,
AWS::EC2::Volume, AWS::EFS::FileSystem, AWS::EFS::MountTarget,
AWS::IAM::Role, AWS::IAM::InstanceProfile,
AWS::ElasticLoadBalancingV2::LoadBalancer,
AWS::ElasticLoadBalancingV2::TargetGroup, AWS::Logs::LogGroup
AWS::EKS::Cluster and AWS::EKS::Nodegroup are not on this list, so the
plugin's List implementation for discovery never surfaces them as
candidates, regardless of how many times discovery runs. This looks like it
was scoped for the "catch out-of-band/foreign resources typically created
by autoscaling or consoles" use case, not for "recover a resource this same
plugin just created but failed to persist."
Impact
This directly undermines the tool's stated core differentiator ("formae
automatically discovers and update resources ... keeps the infrastructure
code automatically in sync with reality") for exactly the failure mode
where it matters most: a partially-successful apply. Once this happens for
an EKS cluster/node group, the operator is left with:
- no way to adopt the orphaned resource back into Formae state through any
documented workflow, and
- a
formae apply --mode reconcile of the original forma that will very
likely attempt to re-create a resource with a name that already exists in
AWS (untested exact error, but the resource identifier is a name that
must be unique per cluster), rather than detecting and adopting it.
Suggested fixes (any of these would help)
- Add
AWS::EKS::Cluster and AWS::EKS::Nodegroup (and likely other
"day-0 declared, not typically out-of-band" resource types) to the AWS
plugin's default discovery filter, so partial-create bookkeeping
failures are always recoverable via the existing discovery/adopt flow.
- Harden the Cloud Control polling path so a transient
network/TLS error while checking create status doesn't mark an
in-flight create Failed outright — e.g. retry/backoff before giving up,
or re-verify actual cloud state via a fresh GetResource/describe call
before recording failure.
- Provide an explicit "resync/repair a specific failed resource" command
or MCP tool that re-checks cloud reality for a named failed resource
from a specific command, independent of the discovery scan scope, and
offers to adopt it if found.
Happy to share more detail (agent logs, command IDs) if useful — trimmed
account-specific identifiers here since this is a public repo.
Summary
When a
formae apply --mode reconcilecreate partially fails due to atransient plugin/API error on the Formae side (Cloud Control
GetResourcepolling timeout), AWS can finish creating the resource successfully while
Formae never records it as managed. For certain resource types (observed:
AWS::EKS::Nodegroup), there is then no supported recovery path backinto Formae's state — not even through the documented
discovery → extract → adopt workflow — because those resource types are
outside the AWS plugin's discovery scan scope.
Environment
0.88.00.1.16AWS::EKS::Nodegroup(also affectsAWS::EKS::Cluster)Steps to reproduce
formae apply --mode reconcilea stack containing anAWS::EKS::Clusterwith 3
AWS::EKS::Nodegroupresources.GetResourcefailurewhile polling create status for one or more node groups (in our case: a
TLS handshake timeout against AWS Cloud Control). Agent logs:
Plugin operator is missing in actionafter the timeout.Formae's command terminates
Failedand marks those specific resourcesas failed creates; they are never added to Formae's managed inventory.
ACTIVEand healthy.list_resources/inventory resourcesfor thatstack shows only the node group(s) that finished polling before the
timeout. The others are absent entirely (not listed as managed, not
listed as unmanaged).
force_discover/ wait for the scheduledscan). Query
managed:false type:AWS::EKS::Nodegroup(ortype:AWS::EKS::Cluster): zero results, even though the resourcesare live in the account discovery is configured against.
Root cause (as far as we can tell from the outside)
get_agent_statsshows the AWS plugin's discovery configuration includes anexplicit
DiscoveryFiltersallow-list:AWS::EKS::ClusterandAWS::EKS::Nodegroupare not on this list, so theplugin's
Listimplementation for discovery never surfaces them ascandidates, regardless of how many times discovery runs. This looks like it
was scoped for the "catch out-of-band/foreign resources typically created
by autoscaling or consoles" use case, not for "recover a resource this same
plugin just created but failed to persist."
Impact
This directly undermines the tool's stated core differentiator ("formae
automatically discovers and update resources ... keeps the infrastructure
code automatically in sync with reality") for exactly the failure mode
where it matters most: a partially-successful apply. Once this happens for
an EKS cluster/node group, the operator is left with:
documented workflow, and
formae apply --mode reconcileof the original forma that will verylikely attempt to re-create a resource with a name that already exists in
AWS (untested exact error, but the resource identifier is a name that
must be unique per cluster), rather than detecting and adopting it.
Suggested fixes (any of these would help)
AWS::EKS::ClusterandAWS::EKS::Nodegroup(and likely other"day-0 declared, not typically out-of-band" resource types) to the AWS
plugin's default discovery filter, so partial-create bookkeeping
failures are always recoverable via the existing discovery/adopt flow.
network/TLS error while checking create status doesn't mark an
in-flight create
Failedoutright — e.g. retry/backoff before giving up,or re-verify actual cloud state via a fresh
GetResource/describe callbefore recording failure.
or MCP tool that re-checks cloud reality for a named failed resource
from a specific command, independent of the discovery scan scope, and
offers to adopt it if found.
Happy to share more detail (agent logs, command IDs) if useful — trimmed
account-specific identifiers here since this is a public repo.