feat(ec2-worker): ANYSCAN_EC2_ASSOCIATE_PUBLIC_IP knob for multi-ENI launches#79
Merged
skullcrushercmd merged 1 commit intomainfrom Apr 28, 2026
Merged
Conversation
…launches When the launch payload uses an explicit NetworkInterfaces[] list (ANYSCAN_MAX_ENIS set), AWS does NOT honor the subnet's MapPublicIpOnLaunch — the operator has to opt in by setting AssociatePublicIpAddress=True on the primary ENI explicitly. In anygpt-48 (PR #65 issuecomment-4338158487) this caused the c6in.metal launch to come up unreachable from outside the VPC; the operator had to manually allocate-address + associate-address post-launch as a workaround. Add an opt-in env knob ANYSCAN_EC2_ASSOCIATE_PUBLIC_IP (default off so existing fleets are unchanged). When set, plumb through ManagerConfig to build_network_interfaces, which sets AssociatePublicIpAddress=True on the entry with DeviceIndex=0 NetworkCardIndex=0 only — AWS rejects the field on secondaries.
skullcrushercmd
added a commit
that referenced
this pull request
Apr 28, 2026
…ches (#82) PR #79's ANYSCAN_EC2_ASSOCIATE_PUBLIC_IP=true on a multi-ENI launch is hard-rejected by AWS: InvalidParameterCombination — The associatePublicIPAddress parameter cannot be specified when launching with multiple network interfaces. AWS only honors AssociatePublicIpAddress on NetworkInterfaces[] when exactly one entry is supplied, even if the field appears only on the primary entry of a multi-NIC payload. The entire RunInstances call fails. Reported in PR #65 issuecomment-4339242358 (anygpt-52). Fix: when len(NetworkInterfaces) > 1, suppress the field inline and allocate-address + associate-address on the primary ENI post-launch. The recreate path now also releases the previously-recorded EIP before terminating the old instance so we don't leak Elastic IPs on every recreate. - build_network_interfaces only emits AssociatePublicIpAddress when the resulting payload is single-NIC (target_count == 1). - Ec2WorkerManager._associate_public_ip_post_launch allocates an EIP (Domain=vpc), associates it with the primary ENI (DeviceIndex=0), records AllocationId/AssociationId in self.state. Allocate or associate failures are surfaced in eni_attach.public_ip but do not abort the recreate — the worker is still usable on private IPs. - Ec2WorkerManager._release_recorded_eip disassociates and releases any previously-recorded EIP at the start of recreate_instance. Tests: - New: launch payload free of AssociatePublicIpAddress on multi-ENI; allocate_address + associate_address called post-launch with the primary ENI's NetworkInterfaceId; allocation_id persisted. - New: AllocateAddress failure does not abort recreate. - New: AssociateAddress failure still records AllocationId so the next recreate can release it. - New: previously-recorded EIP is disassociated + released before terminating the old instance on the next recreate. - Updated: prior tests that asserted the broken inline-flag behavior on multi-NIC now assert the field is suppressed everywhere. Co-authored-by: skullcmd <skullcmd@anyvm.tech> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When PR #74's multi-ENI launch path is engaged (
ANYSCAN_MAX_ENISset),RunInstancesis invoked with an explicitNetworkInterfaces[]payload — and in that mode AWS ignores the subnet'sMapPublicIpOnLaunch=true. The launched instance comes up with no public IP and is unreachable from outside the VPC unlessAssociatePublicIpAddress=Trueis set on the primary ENI explicitly.This bit anygpt-48 in PR #65 issuecomment-4338158487:
What changed
ANYSCAN_EC2_ASSOCIATE_PUBLIC_IP(defaultfalse). Truthy values:1,true,yes,on(case-insensitive).ManagerConfig.associate_public_ipfield plumbed throughfrom_env()to the call site inrecreate_instance→build_network_interfaces(associate_public_ip=...).build_network_interfacessetsAssociatePublicIpAddress=Trueon exactly one NIC: the entry withDeviceIndex=0ANDNetworkCardIndex=0(or justDeviceIndex=0on the legacy single-card path). Secondaries are silent on the field — AWS rejectsAssociatePublicIpAddresson non-primary ENIs.Why default off
Existing fleets that rely on
MapPublicIpOnLaunchfor the legacy single-NIC launch path are unaffected — the legacy path sets top-levelSubnetId/SecurityGroupIdswhich DO honor the subnet flag. The knob only matters forANYSCAN_MAX_ENIS-set fleets, and even there an operator may want a private launch (no public IP) so opt-in is correct.Test plan
python3 -m unittest tools.test_ec2_worker_manager -v→ 48 tests pass (40 existing + 8 new)build_network_interfaces: default-off, multi-card primary-only, single-card primary-onlyManagerConfigto RunInstances payloadfrom_envtests: default off, truthy variants, falsy variants🤖 Generated with Claude Code