Repository navigation
Network VirtualIPs
Public-IP price discovery and private virtual IP writes for danny.vn/vngcloud/network. See
Network for security groups, VPCs, subnets, and Private DNS,
and Services for the read-only virtual IP list and
its address pairs.
This page assumes cfg, ctx, and client := network.New(cfg) from
Network's Setup, and a subnet's subnetID from
Creating, renaming, and deleting
subnets.
ListNetworkPrices returns three separate account-scoped public-vip
quotes for public, public-vm, and public-mkp. Each row uses IP-month.
Equal amounts do not establish interchangeable products or a price for every
public IP. Floating IP, external-interface, and reservation charges remain
unknown rows with nil prices. Bandwidth tariffs and capacity units remain
unverified and excluded.
prices, err := client.ListNetworkPrices(ctx, &network.ListNetworkPricesInput{
MaxRequests: 4,
AllowPartial: true,
})Nil input uses defaults. MaxRequests defaults to 500 and accepts 1..2000.
Discovery needs three logical quotes plus one project read when resolution is
uncached. The full quote phase must fit before any quote starts. Requests run
serially with at least 500 ms between starts, including retries, and a
ten-minute child deadline. Each response is bounded to 8 MiB. Shared project
or authentication waits can exceed the deadline; cancellation stops work after
acquisition. Catalogs and quotes are cached only within the call, while existing
project and token caches remain shared.
Each row has Kind, Name, Type, Scope, Unit, and Price. Quoted prices
use the returned monthly total, VND, and tax as returned. Optional discounts
retain field presence. Zero without explicit free-entry evidence is rejected.
SDK rows follow stable type order, skipping absent fields. Metadata reports
the configured region, logical request count, UTC completion time, coverage,
failures, and sourced notes. Complete coverage can include unknown costs.
Quotes reserve no price or capacity and place no order.
Without AllowPartial, a failure returns nil output and the original error.
With it, independent quotes continue and failed rows keep nil prices. Output
returns with *pricing.DiscoveryError, which matches
pricing.ErrDiscoveryIncomplete and retains API and context errors. A failure
before any usable quote returns nil output and its cause. Authentication,
exhausted throttling, and cancellation stop remaining quotes.
vngcloud --region hcm-3 --read-only network list-network-prices
vngcloud --region hcm-3 --output json network list-network-prices --allow-partial
vngcloud --region hcm-3 network list-network-prices --sort-by monthly-price --descendingJSON contains Items and Metadata. Table and tab-separated text print nil
amounts as unknown and notes on stderr. --sort-by accepts name or
monthly-price; unit-price sorting is invalid. Numeric sorts use unrounded
values and put unknown prices last in either direction. Sorting precedes
--query. Partial output prints before the error and exits 1, even when a
query hides metadata. See CLI Network for flags.
NAT costs remain excluded. Use network list-nat-zones,
network list-nat-packages, and network quote-create-nat-instance separately,
as described in Network NAT. Source notes distinguish
published rules from account quotes; discovery reads no websites at runtime.
created, err := client.CreateVirtualIPAddress(ctx, &network.CreateVirtualIPAddressInput{
SubnetID: subnetID,
Name: "lb-vip",
Mode: network.VirtualIPModeActivePassive,
})
if err != nil {
log.Fatal(err)
}
log.Println(created.VirtualIPAddress.UUID)
updated, err := client.UpdateVirtualIPAddress(ctx, &network.UpdateVirtualIPAddressInput{
VirtualIPAddressID: created.VirtualIPAddress.UUID,
Description: vngcloud.Ptr("front door failover pair"),
})
if err != nil {
log.Fatal(err)
}
log.Println(updated.VirtualIPAddress.Description)
if _, err := client.DeleteVirtualIPAddress(ctx, &network.DeleteVirtualIPAddressInput{
VirtualIPAddressID: created.VirtualIPAddress.UUID,
}); err != nil {
log.Fatal(err)
}Mode is required on every create; network.VirtualIPModeActiveActive
("Active/Active") and network.VirtualIPModeActivePassive
("Active/Passive") name the documented values, but the SDK sends Mode
as given and does not check it against them, so a value the server adds
later never needs an SDK release. IPAddress, when set, must parse with
net/netip.ParseAddr as an IPv4 address; left empty, the server chooses
it. Whether an address lies in the subnet, and whether it is already in
use, are the server's own checks. CreateVirtualIPAddress never sends
tags, zoneId, or a public type; a public virtual IP has its own create
call, not covered here.
CreateVirtualIPAddress is a POST and is never retried after a failure
that may already have reached the server: list virtual IPs
with ListVirtualIPAddresses and match the name exactly, or the address
if one was given, since the server keeps an address unique within a
subnet, before creating it again. If the create response is not already
"ACTIVE", it then waits; see Waits below.
UpdateVirtualIPAddress changes Name, Description, Mode, or any
combination; at least one must be set, or the call fails with
vngcloud.ErrInvalidInput and sends nothing. The API replaces every field
on each PUT and requires Mode on every call, so the SDK reads the
virtual IP first and resends whichever field the caller left nil
unchanged. The PUT is marked idempotent. Whether the server actually
lets Mode change on an existing virtual IP is not yet confirmed live.
DeleteVirtualIPAddress reads the virtual IP first and sends nothing when
any address pair is still attached, checked both by the read's own
AddressPairIPs and by ListAddressPairsByVirtualIPAddress
(network.ErrInUse): a pair binds the address to a server interface, and
deleting it would move traffic. It also sends nothing for a virtual IP
whose Type is not the recorded lowercase "private"
(vngcloud.ErrInvalidInput), so a public virtual IP, which has its own
delete call and price, is never deleted through this one; an empty Type
is refused the same way. DELETE is idempotent; a retry that finds the
virtual IP already gone returns vngcloud.IsNotFound(err) == true.
Deleting a subnet that still holds a virtual IP is refused; see Creating,
renaming, and deleting
subnets.
CreateVirtualIPAddress skips its wait entirely when the create response
is already "ACTIVE". Otherwise, it polls
GetVirtualIPAddress every 2 seconds for up to 60 seconds of elapsed
time, tolerating a 404, until the virtual IP reaches "ACTIVE". If it
reaches "ERROR" instead, the create returns an error wrapping
network.ErrFailed; once the bound runs out, or a read or the wait's own
sleep fails, it wraps network.ErrNotSettled instead, and the create must
not be repeated. Either way the Output still holds the last virtual IP a
read returned, or, if none did, the one the create response itself
carried.
UpdateVirtualIPAddress takes no wait of its own: it sends the PUT,
then always reads the virtual IP once more and returns that read as the
Output. If that confirm read fails, the write has already succeeded: the
error wraps network.ErrNotSettled, and the Output falls back to the
PUT's own response instead. DeleteVirtualIPAddress takes no wait; the
delete is treated as synchronous.
CreateVirtualIPAddress, UpdateVirtualIPAddress, and
DeleteVirtualIPAddress share network.ErrInUse, network.ErrFailed,
and network.ErrNotSettled with the rest of network's writes; see
Network's Errors. They add no sentinel of their own.
SDK
- Getting Started
- Authentication
- Configuration
- Errors
- Services
- Backup
- Billing and Pricing
- CDN
- Compute
- Compute Servers
- DNS
- Container Registry
- IAM
- Load Balancer
- Monitor
- Monitor Alerts
- Monitor Log Alarms
- Network
- Network Route Tables
- Network ACLs
- Network DHCP Options
- Network Virtual IPs
- Tagging
- Storage
- Storage Workload Access
- Storage Objects
- Storage Object Copy
- Storage: Projects
- Storage: Bucket Policy
- Storage: Bucket Settings
- Security
- Volume
- VKS
- Limitations
CLI