Revision history for WWW-Hetzner

0.102     2026-10-21 18:48:51Z
    - The distribution declares LWP::Protocol::https, without it every
      https target fails
    - Fix: transport failures (connection refused, DNS, TLS, timeout) now
      croak with LWP's reason instead of a bare "Hetzner API error: 500";
      non-JSON error bodies (e.g. a proxy's HTML 502) contribute their status
      and text to the error message
    - Fix: the debug log no longer prints password, private_key and
      user_data values of request bodies
    - New: WWW::Hetzner::Cloud::Costs, $cloud->costs(label_selector => ...,
      price => 'gross'|'net') sums the hourly and monthly cost per resource
      and in total for servers (plus the server backup surcharge when
      backup_window is set), volumes, primary IPs, floating IPs and load
      balancers, priced per location from /pricing. Gross by default; the
      result carries price and vat_rate. Where /pricing has no hourly price
      (volumes, floating IPs) hourly is derived as monthly/624 and flagged
      hourly_derived. Resources without a price warn and stay out of the
      totals
    - CLI: hcloud.pl costs [--label|-l SELECTOR] [--net] [--json]
    - Fix: Server and PrimaryIP read the location object current API responses
      carry instead of the dropped datacenter (datacenter kept as fallback);
      Server gains the backup_window attribute
    - Fix: Servers->create sent start_after_create, automount, enable_ipv4 and
      enable_ipv6 (also inside public_net) as JSON numbers, which the API
      rejected as invalid_input; they are now JSON booleans, as is
      change_type's upgrade_disk. The caller's public_net hash is no longer
      modified
    - Docs: WWW::Hetzner::Cloud::API::Datacenters is deprecated, Hetzner
      removed GET /v1/datacenters (410 deprecated_api_endpoint); use
      Locations. The hcloud.pl datacenter command and the datacenter parameter
      of Servers->create and PrimaryIPs->create are deprecated as well
    - Fix: Volumes->create and Volumes->attach send automount as a JSON
      boolean; a Perl 0 went out as the JSON number 0, which the API rejected
      as invalid_input, and attach turned every value into true
    - CLI: hcloud.pl server list and hcloud.pl primary-ip list show the column
      LOCATION instead of DATACENTER, the API no longer sends the datacenter
      field
    - New: the server type carries its locations, one entry per location with
      the name, the availability the datacenter used to deliver and the
      deprecation flag

0.101     2026-09-22 05:53:00Z
    - New: WWW::Hetzner::Storage, a third API host (api.hetzner.com) for
      Storage Boxes
      - $storage->storage_boxes, ->storage_box_types and ->actions; Storage
        Box objects expose per-box ->subaccounts, ->snapshots and ->actions
      - CLI: hcloud.pl storage-box, 33 subcommands (create/update/delete,
        access settings, protection, snapshot plan, snapshots, subaccounts)
    - New: list_all collects all remaining pages on paginated controllers
      (WWW::Hetzner::Role::Pagination); list keeps its single-page contract.
      CLI lists and local name lookups use complete results; pagination
      failures are reported explicitly
    - New read-only Cloud resources: ISOs, Load Balancer Types and Pricing
      - $cloud->isos (list/get/get_by_name), ->load_balancer_types, and
        ->pricing (a singleton, so get only)
      - New entities WWW::Hetzner::Cloud::ISO, ::LoadBalancerType, ::Pricing
      - CLI: hcloud.pl iso, load-balancer-type and pricing
    - New Robot resources: boot, rdns and failover
      - $robot->boot (rescue system, Linux install, VNC, Windows), with
        enable_*/disable_* methods; returns raw hashrefs, no entity
      - $robot->rdns and $robot->failover, listable per-IP resources with
        entities WWW::Hetzner::Robot::RDNS and ::Failover
      - CLI: hrobot.pl boot (rescue/linux/vnc/windows), rdns, failover
    - BREAKING: mutating Cloud methods now return a WWW::Hetzner::Action object
      instead of a raw decoded-JSON action hashref (66 methods across the API
      controllers and their entity mirrors)
      - Action has status predicates (is_running/is_success/is_error),
        error_message, refresh and a blocking wait(interval => 1, timeout => 120)
      - $cloud->actions looks up any action by id, independent of the resource
        that created it
      - Created entities carry the creating action as ->action plus any
        ->next_actions (WWW::Hetzner::Role::HasAction); Firewall create returns
        plural ->actions
      - Server enable_rescue/rebuild/reset_password/request_console preserve
        their sidecar data (root_password, password, wss_url) on the Action via
        ->result and typed readers
      - Action and its roles live directly under WWW::Hetzner, so the other
        Hetzner APIs can reuse them
      - CLI: mutating hcloud.pl commands wait for a terminal action state by
        default; --no-wait opts out (new injectable Role::HTTP sleeper)
    - BREAKING: server, zone and rrset delete now return an Action; the other
      ten DELETE endpoints answer 204 and are unchanged
      - CLI: hcloud.pl server/zone/record delete wait for the deletion action
        by default; --no-wait opts out
    - Fix: Robot request bodies use application/x-www-form-urlencoded, incl.
      repeated array fields; Cloud and Storage keep JSON encoding
    - Fix: URI-encode query names and values (incl. Unicode); arrayrefs become
      repeated query parameters
    - Fix: CLI table output reads entity accessors, restoring server type,
      datacenter and location values; firewall add-rule preserves existing
      rules
    - Fix: --output json no longer dies on the server, image, datacenter,
      sshkey, location, servertype, zone and record list commands
    - Tests: exercise every Cloud and Robot CLI command through execute with
      MockIO, including action waits and non-action deletes

0.100     2026-02-12 17:13:58Z
    - Pluggable HTTP transport via WWW::Hetzner::Role::IO
      - New: WWW::Hetzner::HTTPRequest, WWW::Hetzner::HTTPResponse
      - New: WWW::Hetzner::Role::IO interface role
      - New: WWW::Hetzner::LWPIO (default sync backend using LWP::UserAgent)
      - Role::HTTP split into _build_request, io->call, _parse_response
      - Enables async HTTP backends (Mojo::UserAgent, Net::Async::HTTP, etc.)
    - Document LWP::ConsoleLogger::Everywhere for HTTP debugging

0.003     2026-01-28 05:56:39Z
    - Add comprehensive POD documentation for all API modules

0.002     2026-01-11 01:22:45Z
    - Refactor POD to use inline PodWeaver commands (=attr, =method)
    - Fix ABSTRACT/VERSION order for PodWeaver compatibility
    - Adapt to new dzil plugin structure

0.001     2026-01-10 01:50:52Z
    - Initial release
    - WWW::Hetzner::Cloud API client:
      - Servers (list, get, create, delete, power_on, power_off, shutdown,
        reboot, reset, rebuild, rescue, enable/disable_backup, attach_iso)
      - SSH Keys (list, get, get_by_name, create, update, delete, ensure)
      - Volumes (list, get, create, delete, attach, detach, resize)
      - Networks (list, get, create, update, delete, add/delete_subnet, add/delete_route)
      - Firewalls (list, get, create, update, delete, set_rules, apply_to/remove_from)
      - Floating IPs (list, get, create, delete, assign, unassign)
      - Primary IPs (list, get, create, delete, assign, unassign)
      - Load Balancers (list, get, create, delete, add_target, add_service)
      - Certificates (list, get, create, delete)
      - Placement Groups (list, get, create, update, delete)
      - Server Types, Images, Locations, Datacenters (list, get, get_by_name)
      - DNS Zones (list, get, create, update, delete, export)
      - DNS RRSets with convenience methods (add_a, add_aaaa, add_cname, add_mx, add_txt)
    - WWW::Hetzner::Robot API client:
      - Servers (list, get, update)
      - SSH Keys (list, get, create, delete)
      - IPs (list, get)
      - Reset (software, hardware, manual)
      - Wake-on-LAN
      - Traffic statistics
    - WWW::Hetzner::Role::HTTP for shared HTTP client logic
    - Entity classes with real attributes and methods (update, delete, etc.)
    - Log::Any integration for flexible logging
    - CLI tools:
      - bin/hcloud.pl - Cloud CLI with all resources and hyphenated subcommands
      - bin/hrobot.pl - Robot CLI for dedicated servers
    - Integration tests for real API testing (HETZNER_TEST_TOKEN)
    - Note: Uses Cloud API for DNS (old dns.hetzner.com API no longer exists)
