├── .github ├── dependabot.yml └── workflows │ └── php.yml ├── .gitignore ├── .styleci.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── composer.json ├── docs ├── classes.xhtml ├── classes │ ├── Exception.xhtml │ ├── Exception │ │ ├── __clone.xhtml │ │ ├── __construct.xhtml │ │ ├── __toString.xhtml │ │ ├── getCode.xhtml │ │ ├── getFile.xhtml │ │ ├── getLine.xhtml │ │ ├── getMessage.xhtml │ │ ├── getPrevious.xhtml │ │ ├── getTrace.xhtml │ │ └── getTraceAsString.xhtml │ ├── LKDev_HetznerCloud_APIException.xhtml │ ├── LKDev_HetznerCloud_APIException │ │ ├── __construct.xhtml │ │ └── getApiResponse.xhtml │ ├── LKDev_HetznerCloud_APIResponse.xhtml │ ├── LKDev_HetznerCloud_APIResponse │ │ ├── __get.xhtml │ │ ├── create.xhtml │ │ ├── getHeader.xhtml │ │ ├── getResponse.xhtml │ │ ├── getResponsePart.xhtml │ │ ├── setHeader.xhtml │ │ └── setResponse.xhtml │ ├── LKDev_HetznerCloud_Clients_GuzzleClient.xhtml │ ├── LKDev_HetznerCloud_Clients_GuzzleClient │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_HetznerAPIClient.xhtml │ ├── LKDev_HetznerCloud_HetznerAPIClient │ │ ├── __construct.xhtml │ │ ├── actions.xhtml │ │ ├── datacenters.xhtml │ │ ├── floatingIps.xhtml │ │ ├── getApiToken.xhtml │ │ ├── getBaseUrl.xhtml │ │ ├── getHttpClient.xhtml │ │ ├── getUserAgent.xhtml │ │ ├── hasError.xhtml │ │ ├── httpClient.xhtml │ │ ├── images.xhtml │ │ ├── isos.xhtml │ │ ├── locations.xhtml │ │ ├── networks.xhtml │ │ ├── prices.xhtml │ │ ├── serverTypes.xhtml │ │ ├── servers.xhtml │ │ ├── setBaseUrl.xhtml │ │ ├── setHttpClient.xhtml │ │ ├── setUserAgent.xhtml │ │ ├── sshKeys.xhtml │ │ ├── throwError.xhtml │ │ └── volumes.xhtml │ ├── LKDev_HetznerCloud_Models_Actions_Action.xhtml │ ├── LKDev_HetznerCloud_Models_Actions_Action │ │ ├── __construct.xhtml │ │ ├── delete.xhtml │ │ ├── getById.xhtml │ │ ├── parse.xhtml │ │ ├── refresh.xhtml │ │ ├── reload.xhtml │ │ ├── update.xhtml │ │ └── waitUntilCompleted.xhtml │ ├── LKDev_HetznerCloud_Models_Actions_Actions.xhtml │ ├── LKDev_HetznerCloud_Models_Actions_Actions │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ ├── setAdditionalData.xhtml │ │ └── waitActionCompleted.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_ActionRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_ActionRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_Datacenter.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_Datacenter │ │ ├── __construct.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_DatacenterRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_DatacenterRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_Datacenters.xhtml │ ├── LKDev_HetznerCloud_Models_Datacenters_Datacenters │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIPRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIPRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIp.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIp │ │ ├── __construct.xhtml │ │ ├── assignTo.xhtml │ │ ├── changeDescription.xhtml │ │ ├── changeProtection.xhtml │ │ ├── changeReverseDNS.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ ├── unassign.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIps.xhtml │ ├── LKDev_HetznerCloud_Models_FloatingIps_FloatingIps │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── create.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISO.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISO │ │ ├── __construct.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISORequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISORequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISOs.xhtml │ ├── LKDev_HetznerCloud_Models_ISOs_ISOs │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Images_Image.xhtml │ ├── LKDev_HetznerCloud_Models_Images_Image │ │ ├── __construct.xhtml │ │ ├── changeProtection.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Images_ImageRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Images_ImageRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Images_Images.xhtml │ ├── LKDev_HetznerCloud_Models_Images_Images │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_Location.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_Location │ │ ├── __construct.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_LocationRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_LocationRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_Locations.xhtml │ ├── LKDev_HetznerCloud_Models_Locations_Locations │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Meta.xhtml │ ├── LKDev_HetznerCloud_Models_Meta │ │ ├── __construct.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_Model.xhtml │ ├── LKDev_HetznerCloud_Models_Model │ │ ├── __construct.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Network.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Network │ │ ├── __construct.xhtml │ │ ├── addRoute.xhtml │ │ ├── addSubnet.xhtml │ │ ├── changeIPRange.xhtml │ │ ├── changeProtection.xhtml │ │ ├── delete.xhtml │ │ ├── deleteRoute.xhtml │ │ ├── deleteSubnet.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ ├── setAdditionalData.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_NetworkRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_NetworkRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Networks.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Networks │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── create.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Route.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Route │ │ ├── __construct.xhtml │ │ ├── __toRequestPayload.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Subnet.xhtml │ ├── LKDev_HetznerCloud_Models_Networks_Subnet │ │ ├── __construct.xhtml │ │ ├── __toRequestPayload.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_Pagination.xhtml │ ├── LKDev_HetznerCloud_Models_Pagination │ │ ├── __construct.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_Prices_Prices.xhtml │ ├── LKDev_HetznerCloud_Models_Prices_Prices │ │ └── all.xhtml │ ├── LKDev_HetznerCloud_Models_Protection.xhtml │ ├── LKDev_HetznerCloud_Models_Protection │ │ ├── __construct.xhtml │ │ └── parse.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKey.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKey │ │ ├── __construct.xhtml │ │ ├── changeName.xhtml │ │ ├── delete.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKeyRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKeyRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKeys.xhtml │ ├── LKDev_HetznerCloud_Models_SSHKeys_SSHKeys │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── create.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Server.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Server │ │ ├── __construct.xhtml │ │ ├── attachISO.xhtml │ │ ├── attachToNetwork.xhtml │ │ ├── changeAliasIPs.xhtml │ │ ├── changeProtection.xhtml │ │ ├── changeReverseDNS.xhtml │ │ ├── changeType.xhtml │ │ ├── createImage.xhtml │ │ ├── delete.xhtml │ │ ├── detachFromNetwork.xhtml │ │ ├── detachISO.xhtml │ │ ├── disableBackups.xhtml │ │ ├── disableRescue.xhtml │ │ ├── enableBackups.xhtml │ │ ├── enableRescue.xhtml │ │ ├── get.xhtml │ │ ├── metrics.xhtml │ │ ├── parse.xhtml │ │ ├── powerOff.xhtml │ │ ├── powerOn.xhtml │ │ ├── rebuildFromImage.xhtml │ │ ├── reload.xhtml │ │ ├── replaceServerIdInUri.xhtml │ │ ├── requestConsole.xhtml │ │ ├── reset.xhtml │ │ ├── resetRootPassword.xhtml │ │ ├── setAdditionalData.xhtml │ │ ├── shutdown.xhtml │ │ ├── softReboot.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_ServerRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_ServerRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Servers.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Servers │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── createInDatacenter.xhtml │ │ ├── createInLocation.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerType.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerType │ │ ├── __construct.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerTypes.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerTypes │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerTypesRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Servers_Types_ServerTypesRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_Volume.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_Volume │ │ ├── __construct.xhtml │ │ ├── attach.xhtml │ │ ├── changeProtection.xhtml │ │ ├── delete.xhtml │ │ ├── detach.xhtml │ │ ├── parse.xhtml │ │ ├── reload.xhtml │ │ ├── resize.xhtml │ │ ├── setAdditionalData.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_VolumeRequestOpts.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_VolumeRequestOpts │ │ └── __construct.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_Volumes.xhtml │ ├── LKDev_HetznerCloud_Models_Volumes_Volumes │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── create.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ ├── list.xhtml │ │ ├── parse.xhtml │ │ └── setAdditionalData.xhtml │ ├── LKDev_HetznerCloud_RequestOpts.xhtml │ └── LKDev_HetznerCloud_RequestOpts │ │ ├── __construct.xhtml │ │ └── buildQuery.xhtml ├── css │ ├── SourceSansPro-Regular.ttf │ ├── source.css │ └── style.css ├── index.xhtml ├── interfaces.xhtml ├── interfaces │ ├── LKDev_HetznerCloud_Models_Contracts_Resource.xhtml │ ├── LKDev_HetznerCloud_Models_Contracts_Resource │ │ ├── delete.xhtml │ │ ├── reload.xhtml │ │ └── update.xhtml │ ├── LKDev_HetznerCloud_Models_Contracts_Resources.xhtml │ └── LKDev_HetznerCloud_Models_Contracts_Resources │ │ ├── _getKeys.xhtml │ │ ├── all.xhtml │ │ ├── get.xhtml │ │ ├── getById.xhtml │ │ ├── getByName.xhtml │ │ └── list.xhtml ├── namespaces.xhtml ├── source │ ├── APIException.php.xhtml │ ├── APIResponse.php.xhtml │ ├── Clients │ │ ├── GuzzleClient.php.xhtml │ │ └── index.xhtml │ ├── HetznerAPIClient.php.xhtml │ ├── Models │ │ ├── Actions │ │ │ ├── Action.php.xhtml │ │ │ ├── ActionRequestOpts.php.xhtml │ │ │ ├── Actions.php.xhtml │ │ │ └── index.xhtml │ │ ├── Contracts │ │ │ ├── Resource.php.xhtml │ │ │ ├── Resources.php.xhtml │ │ │ └── index.xhtml │ │ ├── Datacenters │ │ │ ├── Datacenter.php.xhtml │ │ │ ├── DatacenterRequestOpts.php.xhtml │ │ │ ├── Datacenters.php.xhtml │ │ │ └── index.xhtml │ │ ├── FloatingIps │ │ │ ├── FloatingIPRequestOpts.php.xhtml │ │ │ ├── FloatingIp.php.xhtml │ │ │ ├── FloatingIps.php.xhtml │ │ │ └── index.xhtml │ │ ├── ISOs │ │ │ ├── ISO.php.xhtml │ │ │ ├── ISORequestOpts.php.xhtml │ │ │ ├── ISOs.php.xhtml │ │ │ └── index.xhtml │ │ ├── Images │ │ │ ├── Image.php.xhtml │ │ │ ├── ImageRequestOpts.php.xhtml │ │ │ ├── Images.php.xhtml │ │ │ └── index.xhtml │ │ ├── Locations │ │ │ ├── Location.php.xhtml │ │ │ ├── LocationRequestOpts.php.xhtml │ │ │ ├── Locations.php.xhtml │ │ │ └── index.xhtml │ │ ├── Meta.php.xhtml │ │ ├── Model.php.xhtml │ │ ├── Networks │ │ │ ├── Network.php.xhtml │ │ │ ├── NetworkRequestOpts.php.xhtml │ │ │ ├── Networks.php.xhtml │ │ │ ├── Route.php.xhtml │ │ │ ├── Subnet.php.xhtml │ │ │ └── index.xhtml │ │ ├── Pagination.php.xhtml │ │ ├── Prices │ │ │ ├── Prices.php.xhtml │ │ │ └── index.xhtml │ │ ├── Protection.php.xhtml │ │ ├── SSHKeys │ │ │ ├── SSHKey.php.xhtml │ │ │ ├── SSHKeyRequestOpts.php.xhtml │ │ │ ├── SSHKeys.php.xhtml │ │ │ └── index.xhtml │ │ ├── Servers │ │ │ ├── Server.php.xhtml │ │ │ ├── ServerRequestOpts.php.xhtml │ │ │ ├── Servers.php.xhtml │ │ │ ├── Types │ │ │ │ ├── ServerType.php.xhtml │ │ │ │ ├── ServerTypes.php.xhtml │ │ │ │ ├── ServerTypesRequestOpts.php.xhtml │ │ │ │ └── index.xhtml │ │ │ └── index.xhtml │ │ ├── Volumes │ │ │ ├── Volume.php.xhtml │ │ │ ├── VolumeRequestOpts.php.xhtml │ │ │ ├── Volumes.php.xhtml │ │ │ └── index.xhtml │ │ └── index.xhtml │ ├── RequestOpts.php.xhtml │ ├── Traits │ │ ├── GetFunctionTrait.php.xhtml │ │ └── index.xhtml │ └── index.xhtml ├── traits.xhtml └── traits │ ├── LKDev_HetznerCloud_Traits_GetFunctionTrait.xhtml │ └── LKDev_HetznerCloud_Traits_GetFunctionTrait │ ├── _all.xhtml │ └── get.xhtml ├── examples ├── bootstrap.php ├── floating_ip │ └── create_a_floating_ip.php └── servers │ ├── create_a_server.php │ ├── get_a_specifc_server.php │ ├── get_all_server_types.php │ ├── get_all_servers.php │ └── toggle_a_server.php ├── phpdox.phar ├── phpdox.xml ├── phpunit.xml.dist ├── src ├── APIException.php ├── APIResponse.php ├── Clients │ └── GuzzleClient.php ├── HetznerAPIClient.php ├── Models │ ├── Actions │ │ ├── Action.php │ │ ├── ActionRequestOpts.php │ │ └── Actions.php │ ├── Certificates │ │ ├── Certificate.php │ │ ├── CertificateRequestOpts.php │ │ └── Certificates.php │ ├── Contracts │ │ ├── Resource.php │ │ └── Resources.php │ ├── Datacenters │ │ ├── Datacenter.php │ │ ├── DatacenterRequestOpts.php │ │ └── Datacenters.php │ ├── Firewalls │ │ ├── Firewall.php │ │ ├── FirewallRequestOpts.php │ │ ├── FirewallResource.php │ │ ├── FirewallRule.php │ │ └── Firewalls.php │ ├── FloatingIps │ │ ├── FloatingIPRequestOpts.php │ │ ├── FloatingIp.php │ │ └── FloatingIps.php │ ├── ISOs │ │ ├── ISO.php │ │ ├── ISORequestOpts.php │ │ └── ISOs.php │ ├── Images │ │ ├── Image.php │ │ ├── ImageRequestOpts.php │ │ └── Images.php │ ├── LoadBalancerTypes │ │ ├── LoadBalancerType.php │ │ ├── LoadBalancerTypeRequestOpts.php │ │ └── LoadBalancerTypes.php │ ├── LoadBalancers │ │ ├── LoadBalancer.php │ │ ├── LoadBalancerAlgorithm.php │ │ ├── LoadBalancerHealthCheck.php │ │ ├── LoadBalancerHealthCheckHttp.php │ │ ├── LoadBalancerRequestOpts.php │ │ ├── LoadBalancerServiceHttp.php │ │ ├── LoadBalancerTargetIp.php │ │ └── LoadBalancers.php │ ├── Locations │ │ ├── Location.php │ │ ├── LocationRequestOpts.php │ │ └── Locations.php │ ├── Meta.php │ ├── Model.php │ ├── Networks │ │ ├── Network.php │ │ ├── NetworkRequestOpts.php │ │ ├── Networks.php │ │ ├── Route.php │ │ └── Subnet.php │ ├── Pagination.php │ ├── PlacementGroups │ │ ├── PlacementGroup.php │ │ ├── PlacementGroupRequestOpts.php │ │ └── PlacementGroups.php │ ├── Prices │ │ └── Prices.php │ ├── PrimaryIps │ │ ├── PrimaryIPRequestOpts.php │ │ ├── PrimaryIp.php │ │ └── PrimaryIps.php │ ├── Protection.php │ ├── SSHKeys │ │ ├── SSHKey.php │ │ ├── SSHKeyRequestOpts.php │ │ └── SSHKeys.php │ ├── Servers │ │ ├── Server.php │ │ ├── ServerRequestOpts.php │ │ ├── Servers.php │ │ └── Types │ │ │ ├── ServerType.php │ │ │ ├── ServerTypes.php │ │ │ └── ServerTypesRequestOpts.php │ └── Volumes │ │ ├── Volume.php │ │ ├── VolumeRequestOpts.php │ │ └── Volumes.php ├── RequestOpts.php └── Traits │ └── GetFunctionTrait.php └── tests ├── TestCase.php └── Unit ├── ApiResponseTest.php ├── BasicClientTest.php ├── Models ├── Actions │ ├── ActionsTest.php │ └── fixtures │ │ ├── action.json │ │ └── actions.json ├── Certificates │ ├── CertificatesTest.php │ └── fixtures │ │ ├── certificate.json │ │ └── certificates.json ├── Datacenters │ ├── DatacentersTest.php │ └── fixtures │ │ ├── datacenter.json │ │ └── datacenters.json ├── Firewalls │ ├── FirewallTest.php │ ├── FirewallsTest.php │ └── fixtures │ │ ├── firewall.json │ │ ├── firewall_action_apply_to_resources.json │ │ ├── firewall_action_remove_from_resources.json │ │ ├── firewall_action_set_rules.json │ │ ├── firewall_create.json │ │ └── firewalls.json ├── FloatingIPs │ ├── FloatingIPsTest.php │ ├── FloatingIpTest.php │ └── fixtures │ │ ├── floatingIP.json │ │ ├── floatingIP_action_assign_floating_ip.json │ │ ├── floatingIP_action_change_dns_ptr.json │ │ ├── floatingIP_action_change_protection.json │ │ ├── floatingIP_action_unassign_floating_ip.json │ │ ├── floatingIP_create.json │ │ └── floatingIPs.json ├── ISO │ ├── ISOsTest.php │ └── fixtures │ │ ├── iso.json │ │ └── isos.json ├── Images │ ├── ImagesTest.php │ └── fixtures │ │ ├── image.json │ │ ├── image_action_change_protection.json │ │ └── images.json ├── LoadBalancerTypes │ ├── LoadBalancerTypeTest.php │ ├── LoadBalancerTypesTest.php │ └── fixtures │ │ ├── loadBalancerType.json │ │ └── loadBalancerTypes.json ├── LoadBalancers │ ├── LoadBalancerTest.php │ ├── LoadBalancersTest.php │ └── fixtures │ │ ├── loadBalancer.json │ │ ├── loadBalancer_action_add_service.json │ │ ├── loadBalancer_action_add_target.json │ │ ├── loadBalancer_action_attach_loadbalancer_network.json │ │ ├── loadBalancer_action_change_algorithm.json │ │ ├── loadBalancer_action_change_dns_ptr.json │ │ ├── loadBalancer_action_change_load_balancer_type.json │ │ ├── loadBalancer_action_change_protection.json │ │ ├── loadBalancer_action_delete_service.json │ │ ├── loadBalancer_action_detach_from_network.json │ │ ├── loadBalancer_action_disable_public_interface.json │ │ ├── loadBalancer_action_enable_public_interface.json │ │ ├── loadBalancer_action_remove_target.json │ │ ├── loadBalancer_action_update_service.json │ │ └── loadBalancers.json ├── Locations │ ├── LocationsTest.php │ └── fixtures │ │ ├── location.json │ │ └── locations.json ├── Networks │ ├── NetworkTest.php │ ├── NetworksTest.php │ └── fixtures │ │ ├── network.json │ │ ├── network_action_generic.json │ │ └── networks.json ├── PlacementGroups │ ├── PlacementGroupTest.php │ ├── PlacementGroupsTest.php │ └── fixtures │ │ ├── placement_group.json │ │ └── placement_groups.json ├── Pricing │ ├── PricingTest.php │ └── fixtures │ │ └── pricing.json ├── PrimaryIps │ ├── PrimaryIPsTest.php │ ├── PrimaryIpTest.php │ └── fixtures │ │ ├── primaryIP.json │ │ ├── primaryIP_action_assign_primary_ip.json │ │ ├── primaryIP_action_change_dns_ptr.json │ │ ├── primaryIP_action_change_protection.json │ │ ├── primaryIP_action_unassign_primary_ip.json │ │ └── primaryIPs.json ├── SSHKeys │ ├── SSHKeysTest.php │ └── fixtures │ │ ├── ssh_key.json │ │ └── ssh_keys.json ├── ServerTypes │ ├── ServerTypesTest.php │ └── fixtures │ │ ├── server_type.json │ │ └── server_types.json ├── Servers │ ├── ServerTest.php │ ├── ServersTest.php │ └── fixtures │ │ ├── server.json │ │ ├── server_action_create_image.json │ │ ├── server_action_enable_rescue.json │ │ ├── server_action_generic.json │ │ ├── server_action_metrics.json │ │ ├── server_action_request_console.json │ │ ├── server_action_reset_password.json │ │ └── servers.json └── Volumes │ ├── VolumeTest.php │ ├── VolumesTest.php │ └── fixtures │ ├── volume.json │ ├── volume_action_attach.json │ ├── volume_action_change_protection.json │ ├── volume_action_detach.json │ ├── volume_action_resize.json │ ├── volume_create.json │ └── volumes.json └── RequestOptsTest.php /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: composer 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.operating-system }} 8 | strategy: 9 | matrix: 10 | operating-system: [ubuntu-latest] 11 | php-versions: [ '8.1', '8.2', '8.3', '8.4'] 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Setup PHP 15 | uses: shivammathur/setup-php@v2 16 | with: 17 | php-version: ${{ matrix.php-versions }} 18 | - name: Install depdendencies 19 | run: | 20 | composer install 21 | - name: Run phpunit 22 | run: php vendor/bin/phpunit 23 | - name: Run phpstan 24 | run: php vendor/bin/phpstan analyse src --level 1 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | build/ 3 | .idea -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Lukas Kämmerling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest Stable Version](https://poser.pugx.org/lkdevelopment/hetzner-cloud-php-sdk/version)](https://packagist.org/packages/lkdevelopment/hetzner-cloud-php-sdk) 2 | [![License](https://poser.pugx.org/lkdevelopment/hetzner-cloud-php-sdk/license)](https://packagist.org/packages/lkdevelopment/hetzner-cloud-php-sdk) 3 | [![Total Downloads](https://poser.pugx.org/lkdevelopment/hetzner-cloud-php-sdk/downloads)](https://packagist.org/packages/lkdevelopment/hetzner-cloud-php-sdk) 4 | [![Actions Status](https://github.com/lkdevelopment/hetzner-cloud-php-sdk/workflows/CI/badge.svg)](https://github.com/lkdevelopment/hetzner-cloud-php-sdk/actions) 5 | # Hetzner Cloud PHP SDK 6 | A PHP SDK for the Hetzner Cloud API: https://docs.hetzner.cloud/ 7 | ## Installation 8 | 9 | You can install the package via composer: 10 | 11 | ```bash 12 | composer require lkdevelopment/hetzner-cloud-php-sdk 13 | ``` 14 | 15 | ## Usage 16 | 17 | ``` php 18 | $hetznerClient = new \LKDev\HetznerCloud\HetznerAPIClient($apiKey); 19 | foreach ($hetznerClient->servers()->all() as $server) { 20 | echo 'ID: '.$server->id.' Name:'.$server->name.' Status: '.$server->status.PHP_EOL; 21 | } 22 | ``` 23 | ### PHP Support 24 | 25 | We test on all supported PHP Versions. The library can still work on older versions, however it is no longer actively tested. 26 | 27 | ### Old Releases: v1.x 28 | [Version 1.x](https://github.com/LKDevelopment/hetzner-cloud-php-sdk/tree/v1) is abandoned and will not receive any new updates or features. V2 was created with Backward Compatibility in mind. So it should work as a drop-in replacement. Therefor it does not give a "Migration to v2"-Guide. It should just work! 29 | 30 | ### Testing 31 | 32 | You can just run `phpunit`. The whole library is based on unit tests and sample responses from the official Hetzner Cloud documentation. 33 | 34 | ### Changelog 35 | 36 | Please see [CHANGELOG](https://github.com/LKDevelopment/hetzner-cloud-php-sdk/releases) for more information what has changed recently. 37 | 38 | 39 | ### Security 40 | 41 | If you discover any security related issues, please email kontakt@lukas-kaemmerling.de instead of using the issue tracker. 42 | 43 | ## Credits 44 | 45 | - [Lukas Kämmerling](https://github.com/lkaemmerling) 46 | - [All Contributors](../../contributors) 47 | 48 | ## License 49 | 50 | The MIT License (MIT). Please see [License File](LICENSE) for more information. 51 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lkdevelopment/hetzner-cloud-php-sdk", 3 | "description": "An unofficial PHP SDK for the Hetzner Cloud API.", 4 | "type": "library", 5 | "keywords": [ 6 | "hetzner", 7 | "hcloud", 8 | "hetzner cloud", 9 | "cloud php library" 10 | ], 11 | "require": { 12 | "php": "^8.1", 13 | "ext-json": "*", 14 | "guzzlehttp/guzzle": "^6.3|^7.0", 15 | "illuminate/collections": "^5.5|^v6.18|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0" 16 | }, 17 | "require-dev": { 18 | "phpunit/phpunit": "^7.0|^8.5.5|^9.0", 19 | "phpstan/phpstan": "^0.12.43 || ^1.0.0" 20 | }, 21 | "license": "MIT", 22 | "authors": [ 23 | { 24 | "name": "Lukas Kämmerling", 25 | "email": "kontakt@lukas-kaemmerling.de" 26 | } 27 | ], 28 | "autoload": { 29 | "psr-4": { 30 | "LKDev\\HetznerCloud\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "LKDev\\Tests\\": "tests/" 36 | } 37 | }, 38 | "scripts": { 39 | "docs": "php phpDocumentor.phar -d ./src -t ./docs" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/classes/Exception/__clone.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::__clone 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::__clone

68 |

Clone the exception

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/__toString.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::__toString 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::__toString

68 |

String representation of the exception

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getCode.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getCode 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getCode

68 |

Gets the Exception code

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getFile.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getFile 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getFile

68 |

Gets the file in which the exception was created

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getLine.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getLine 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getLine

68 |

Gets the line in which the exception was created

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getMessage.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getMessage 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getMessage

68 |

Gets the Exception message

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getPrevious.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getPrevious 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getPrevious

68 |

Returns previous Exception

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getTrace.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getTrace 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getTrace

68 |

Gets the stack trace

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/Exception/getTraceAsString.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Exception::getTraceAsString 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

Exception::getTraceAsString

68 |

Gets the stack trace as a string

69 |

70 |

82 |
83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_APIResponse/getHeader.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\APIResponse::getHeader 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\APIResponse::getHeader

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function getHeader() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    array
    82 |
    83 |
    84 |

85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_APIResponse/getResponse.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\APIResponse::getResponse 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\APIResponse::getResponse

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function getResponse() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    array
    82 |
    83 |
    84 |

85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_HetznerAPIClient/getApiToken.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\HetznerAPIClient::getApiToken 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\HetznerAPIClient::getApiToken

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function getApiToken() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    string
    82 |
    83 |
    84 |

85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_HetznerAPIClient/getBaseUrl.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\HetznerAPIClient::getBaseUrl 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\HetznerAPIClient::getBaseUrl

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function getBaseUrl() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    string
    82 |
    83 |
    84 |

85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_HetznerAPIClient/images.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\HetznerAPIClient::images 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\HetznerAPIClient::images

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function images() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    Images
    82 |

    83 |
    84 |
    85 |

86 |
87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_HetznerAPIClient/isos.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\HetznerAPIClient::isos 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\HetznerAPIClient::isos

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function isos() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    ISOs
    82 |

    83 |
    84 |
    85 |

86 |
87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/classes/LKDev_HetznerCloud_RequestOpts/buildQuery.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\RequestOpts::buildQuery 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 69 |
70 |

LKDev\HetznerCloud\RequestOpts::buildQuery

71 |

72 |

73 |

    74 |

    Signature

    75 |
    76 | public function buildQuery() 77 | 78 |
    79 |

    Returns

    80 |
    81 |
    string
    82 |
    83 |
    84 |

85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/css/SourceSansPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LKDevelopment/hetzner-cloud-php-sdk/f0b2c33447d929ed49829c3259e2d0006ba26f72/docs/css/SourceSansPro-Regular.ttf -------------------------------------------------------------------------------- /docs/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Overview 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 |

Unofficial Hetzner Cloud PHP SDK

38 |

Software Documentation

39 |

Welcome to the Software Documentation homepage.

40 |
41 |
42 |

Build

43 |

Fri, 24 Jan 2020 11:51:45 +0000

44 |

VCS Info

45 |

46 | tag:
47 | branch:

48 |

Used Enrichers

49 |

build

50 |
51 |
52 |
53 |
54 |

Warning: PHPLoc enrichment not enabled or phploc.xml not found.

55 |
56 |
57 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /docs/interfaces.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | phpDox - Overview 5 | 6 | 7 | 8 | 9 | 34 |
35 |

Interfaces

36 |
37 |

\LKDev\HetznerCloud\Models\Contracts

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 53 | 54 | 55 | 58 | 61 | 62 | 63 |
NameDescription
48 | Resource 49 | 51 | No description available 52 |
56 | Resources 57 | 59 | No description available 60 |
64 |
65 |
66 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /docs/interfaces/LKDev_HetznerCloud_Models_Contracts_Resource/delete.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\Models\Contracts\Resource::delete 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

LKDev\HetznerCloud\Models\Contracts\Resource::delete

68 |

69 |

70 |

Signature

71 |
72 | public function delete() 73 | 74 |
75 |
76 |
77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/interfaces/LKDev_HetznerCloud_Models_Contracts_Resource/reload.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\Models\Contracts\Resource::reload 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

LKDev\HetznerCloud\Models\Contracts\Resource::reload

68 |

69 |

70 |

Signature

71 |
72 | public function reload() 73 | 74 |
75 |
76 |
77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/interfaces/LKDev_HetznerCloud_Models_Contracts_Resources/_getKeys.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - LKDev\HetznerCloud\Models\Contracts\Resources::_getKeys 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 52 |
53 | 66 |
67 |

LKDev\HetznerCloud\Models\Contracts\Resources::_getKeys

68 |

69 |

70 |

Signature

71 |
72 | public function _getKeys() 73 | 74 |
75 |
76 |
77 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /docs/source/Clients/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Overview 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 46 |
47 |

Source of Unofficial Hetzner Cloud PHP SDK

48 |

49 | This project consists of 17 directories, containing 50 | a total of 48 files. 51 |

52 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 70 | 71 | 72 | 73 | 77 | 78 |
NameSizeLast Modified
66 | GuzzleClient.php 67 | 678 Bytes 69 | 2020-01-24T11:45:15+00:00
74 | 75 | Total: 1 files 76 |
79 |
80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/source/Models/Prices/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Overview 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 49 |
50 |

Source of Unofficial Hetzner Cloud PHP SDK

51 |

52 | This project consists of 17 directories, containing 53 | a total of 48 files. 54 |

55 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 74 | 76 | 77 | 78 | 79 | 83 | 84 |
NameSizeLast Modified
72 | Prices.php 73 | 1.0 KB 75 | 2020-01-24T11:45:15+00:00
80 | 81 | Total: 1 files 82 |
85 |
86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/source/Traits/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpDox - Overview 6 | 7 | 8 | 9 | 10 | 35 |
36 |
37 | 46 |
47 |

Source of Unofficial Hetzner Cloud PHP SDK

48 |

49 | This project consists of 17 directories, containing 50 | a total of 48 files. 51 |

52 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 70 | 71 | 72 | 73 | 77 | 78 |
NameSizeLast Modified
66 | GetFunctionTrait.php 67 | 955 Bytes 69 | 2020-01-24T11:45:15+00:00
74 | 75 | Total: 1 files 76 |
79 |
80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /docs/traits.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | phpDox - Overview 5 | 6 | 7 | 8 | 9 | 34 |
35 |

Traits

36 |
37 |

\LKDev\HetznerCloud\Traits

38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 53 | 54 | 55 |
NameDescription
48 | GetFunctionTrait 49 | 51 | No description available 52 |
56 |
57 |
58 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /examples/bootstrap.php: -------------------------------------------------------------------------------- 1 | locations()->getById(1); 6 | 7 | $fip = $hetznerClient->floatingIps()->create('ipv4', null, $location, null, 'my-floatingip', ['key' => 'value']); 8 | echo 'FIP: '.$fip->name.PHP_EOL; 9 | var_dump($fip); 10 | -------------------------------------------------------------------------------- /examples/servers/create_a_server.php: -------------------------------------------------------------------------------- 1 | serverTypes()->get(1); 6 | $location = $hetznerClient->locations()->getByName('fsn1'); 7 | $image = $hetznerClient->images()->getByName('ubuntu-20.04'); 8 | $apiResponse = $hetznerClient->servers()->createInLocation('my-example-server.test', $serverType, $image, $location); 9 | $server = $apiResponse->getResponsePart('server'); 10 | $action = $apiResponse->getResponsePart('action'); 11 | $next_actions = $apiResponse->getResponsePart('next_actions'); 12 | echo 'Server: '.$server->name.PHP_EOL; 13 | echo 'IP: '.$server->publicNet->ipv4->ip.PHP_EOL; 14 | echo 'Password: '.$apiResponse->getResponsePart('root_password').PHP_EOL; 15 | echo 'Now we wait on the success of the server creation!'.PHP_EOL; 16 | echo date('H:i:s').PHP_EOL; 17 | $action->waitUntilCompleted(); 18 | 19 | foreach ($next_actions as $na) { 20 | $na->waitUntilCompleted(); 21 | } 22 | echo date('H:i:s').PHP_EOL; 23 | echo 'Done!'; 24 | -------------------------------------------------------------------------------- /examples/servers/get_a_specifc_server.php: -------------------------------------------------------------------------------- 1 | servers()->get($serverId); 7 | var_dump($server); 8 | -------------------------------------------------------------------------------- /examples/servers/get_all_server_types.php: -------------------------------------------------------------------------------- 1 | serverTypes()->all() as $serverType) { 6 | echo $serverType->name.PHP_EOL; 7 | } 8 | -------------------------------------------------------------------------------- /examples/servers/get_all_servers.php: -------------------------------------------------------------------------------- 1 | servers()->all() as $server) { 6 | echo 'ID: '.$server->id.' Name:'.$server->name.' Status: '.$server->status.PHP_EOL; 7 | } 8 | -------------------------------------------------------------------------------- /examples/servers/toggle_a_server.php: -------------------------------------------------------------------------------- 1 | servers()->get($serverId); 7 | echo 'Server: '.$server->name.PHP_EOL; 8 | echo 'Perform Shutdown now:'.PHP_EOL; 9 | /** 10 | * @var \LKDev\HetznerCloud\Models\Servers\Server 11 | */ 12 | $action = $server->shutdown()->getResponsePart('action'); 13 | 14 | echo 'Reply from API: Action ID: '.$action->id.' '.$action->command.' '.$action->started.PHP_EOL; 15 | 16 | echo 'Wait some seconds that the server could shutdown.'.PHP_EOL; 17 | sleep(5); 18 | echo 'Get the Server from the API:'.PHP_EOL; 19 | $server = $hetznerClient->servers()->get($serverId); 20 | echo 'Server status: '.$server->status.PHP_EOL; 21 | echo "Let's start it again!"; 22 | $server->powerOn(); 23 | echo 'Wait some seconds that the server could startup.'.PHP_EOL; 24 | sleep(5); 25 | echo 'Get the Server from the API:'.PHP_EOL; 26 | $server = $hetznerClient->servers()->get($serverId); 27 | echo 'Server status: '.$server->status.PHP_EOL; 28 | -------------------------------------------------------------------------------- /phpdox.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LKDevelopment/hetzner-cloud-php-sdk/f0b2c33447d929ed49829c3259e2d0006ba26f72/phpdox.phar -------------------------------------------------------------------------------- /phpdox.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/APIException.php: -------------------------------------------------------------------------------- 1 | response = $response; 23 | parent::__construct($message, $code, $previous); 24 | } 25 | 26 | /** 27 | * @return APIResponse 28 | */ 29 | public function getApiResponse() 30 | { 31 | return $this->response; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/APIResponse.php: -------------------------------------------------------------------------------- 1 | response; 34 | } 35 | 36 | /** 37 | * @param string|null $resource 38 | * @return Model|string|bool 39 | */ 40 | public function getResponsePart(?string $resource = null) 41 | { 42 | return (array_key_exists($resource, $this->response)) ? $this->response[$resource] : false; 43 | } 44 | 45 | /** 46 | * @param array $response 47 | */ 48 | public function setResponse(array $response) 49 | { 50 | $this->response = $response; 51 | } 52 | 53 | /** 54 | * @param array $header 55 | */ 56 | public function setHeader(array $header) 57 | { 58 | $this->header = $header; 59 | } 60 | 61 | /** 62 | * @return array 63 | */ 64 | public function getHeader(): array 65 | { 66 | return $this->header; 67 | } 68 | 69 | /** 70 | * @param array $response 71 | * @param array $header 72 | * @return APIResponse 73 | */ 74 | public static function create(array $response, array $header = []) 75 | { 76 | $apiResponse = new self(); 77 | $apiResponse->setResponse($response); 78 | $apiResponse->setHeader($header); 79 | 80 | return $apiResponse; 81 | } 82 | 83 | public function __get($name) 84 | { 85 | return $this->getResponsePart($name); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/Clients/GuzzleClient.php: -------------------------------------------------------------------------------- 1 | $client->getBaseUrl(), 20 | 'headers' => [ 21 | 'Authorization' => 'Bearer '.$client->getApiToken(), 22 | 'Content-Type' => 'application/json', 23 | 'User-Agent' => ((strlen($client->getUserAgent()) > 0) ? $client->getUserAgent().' ' : '').'hcloud-php/'.HetznerAPIClient::VERSION, 24 | ], 25 | ], $additionalGuzzleConfig); 26 | $this->client = new Client($guzzleConfig); 27 | } 28 | 29 | public function __call($name, $arguments) 30 | { 31 | return $this->client->$name(...$arguments); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Models/Actions/ActionRequestOpts.php: -------------------------------------------------------------------------------- 1 | status = $status; 38 | $this->sort = $sort; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Models/Certificates/CertificateRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Models/Contracts/Resource.php: -------------------------------------------------------------------------------- 1 | id = $id; 67 | $this->name = $name; 68 | $this->description = $description; 69 | $this->location = $location; 70 | $this->server_types = $server_types; 71 | $this->serverTypes = $server_types; 72 | parent::__construct(); 73 | } 74 | 75 | /** 76 | * @param $input 77 | * @return \LKDev\HetznerCloud\Models\Datacenters\Datacenter|static 78 | */ 79 | public static function parse($input) 80 | { 81 | if ($input == null) { 82 | return; 83 | } 84 | 85 | return new self($input->id, $input->name, $input->description, Location::parse($input->location), $input->server_types); 86 | } 87 | 88 | public function reload() 89 | { 90 | return HetznerAPIClient::$instance->datacenters()->get($this->id); 91 | } 92 | 93 | public function delete() 94 | { 95 | throw new \BadMethodCallException('delete on datacenter is not possible'); 96 | } 97 | 98 | public function update(array $data) 99 | { 100 | throw new \BadMethodCallException('update on datacenter is not possible'); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Models/Datacenters/DatacenterRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Models/Firewalls/FirewallRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 28 | parent::__construct($perPage, $page, $labelSelector); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Models/Firewalls/FirewallResource.php: -------------------------------------------------------------------------------- 1 | type = $type; 32 | $this->server = $server; 33 | } 34 | 35 | /** 36 | * @return string[] 37 | */ 38 | public function toRequestSchema(): array 39 | { 40 | $s = ['type' => $this->type]; 41 | if ($this->type == self::TYPE_SERVER) { 42 | $s['server'] = ['id' => $this->server->id]; 43 | } 44 | 45 | return $s; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Models/Firewalls/FirewallRule.php: -------------------------------------------------------------------------------- 1 | 25 | */ 26 | public $sourceIPs; 27 | /** 28 | * @var array 29 | */ 30 | public $destinationIPs; 31 | /** 32 | * @var string 33 | */ 34 | public $protocol; 35 | /** 36 | * @var string 37 | */ 38 | public $port; 39 | 40 | /** 41 | * FirewallRule constructor. 42 | * 43 | * @param string $direction 44 | * @param string[] $sourceIPs 45 | * @param string[] $destinationIPs 46 | * @param string $protocol 47 | * @param string $port 48 | */ 49 | public function __construct(string $direction, string $protocol, array $sourceIPs = [], array $destinationIPs = [], ?string $port = '') 50 | { 51 | $this->direction = $direction; 52 | $this->sourceIPs = $sourceIPs; 53 | $this->destinationIPs = $destinationIPs; 54 | $this->protocol = $protocol; 55 | $this->port = $port; 56 | } 57 | 58 | /** 59 | * @return array 60 | */ 61 | public function toRequestSchema(): array 62 | { 63 | $s = [ 64 | 'direction' => $this->direction, 65 | 'source_ips' => $this->sourceIPs, 66 | 'protocol' => $this->protocol, 67 | ]; 68 | if (! empty($this->destinationIPs)) { 69 | $s['destination_ips'] = $this->destinationIPs; 70 | } 71 | if ($this->port != '') { 72 | $s['port'] = $this->port; 73 | } 74 | 75 | return $s; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Models/FloatingIps/FloatingIPRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 29 | parent::__construct($perPage, $page, $labelSelector); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/ISOs/ISO.php: -------------------------------------------------------------------------------- 1 | id = $id; 42 | $this->name = $name; 43 | $this->description = $description; 44 | $this->type = $type; 45 | parent::__construct(); 46 | } 47 | 48 | /** 49 | * @param $input 50 | * @return \LKDev\HetznerCloud\Models\ISOs\ISO|static 51 | */ 52 | public static function parse($input): ?self 53 | { 54 | if ($input == null) { 55 | return null; 56 | } 57 | 58 | return new self($input->id, $input->name, $input->description, $input->type); 59 | } 60 | 61 | public function reload() 62 | { 63 | return HetznerAPIClient::$instance->isos()->get($this->id); 64 | } 65 | 66 | public function delete() 67 | { 68 | throw new \BadMethodCallException('delete on ISOs is not possible'); 69 | } 70 | 71 | public function update(array $data) 72 | { 73 | throw new \BadMethodCallException('update on ISOs is not possible'); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Models/ISOs/ISORequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Models/Images/ImageRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 37 | $this->architecture = $architecture; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Models/LoadBalancerTypes/LoadBalancerTypeRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerAlgorithm.php: -------------------------------------------------------------------------------- 1 | type = $type; 20 | parent::__construct(); 21 | } 22 | 23 | /** 24 | * @param $input 25 | * @return \LKDev\HetznerCloud\Models\LoadBalancers\LoadBalancerAlgorithm|null|static 26 | */ 27 | public static function parse($input) 28 | { 29 | if ($input == null) { 30 | return; 31 | } 32 | 33 | return new self($input->type); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerHealthCheck.php: -------------------------------------------------------------------------------- 1 | http = $http; 50 | $this->interval = $interval; 51 | $this->port = $port; 52 | $this->protocol = $protocol; 53 | $this->retries = $retries; 54 | $this->timeout = $timeout; 55 | parent::__construct(); 56 | } 57 | 58 | /** 59 | * @param $input 60 | * @return \LKDev\HetznerCloud\Models\LoadBalancers\LoadBalancerHealthCheck|null|static 61 | */ 62 | public static function parse($input) 63 | { 64 | if ($input == null) { 65 | return; 66 | } 67 | 68 | return new self(LoadBalancerHealthCheckHttp::parse($input->http), $input->interval, $input->port, $input->protocol, $input->retries, $input->timeout); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerHealthCheckHttp.php: -------------------------------------------------------------------------------- 1 | domain = $domain; 44 | $this->path = $path; 45 | $this->response = $response; 46 | $this->status_codes = $status_codes; 47 | $this->tls = $tls; 48 | parent::__construct(null); 49 | } 50 | 51 | /** 52 | * @param $input 53 | * @return \LKDev\HetznerCloud\Models\LoadBalancers\LoadBalancerHealthCheckHttp|null|static 54 | */ 55 | public static function parse($input) 56 | { 57 | if ($input == null) { 58 | return; 59 | } 60 | 61 | return new self($input->domain, $input->path, $input->response, $input->status_codes, $input->tls); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerServiceHttp.php: -------------------------------------------------------------------------------- 1 | certificates = $certificates; 44 | $this->cookie_lifetime = $cookie_lifetime; 45 | $this->cookie_name = $cookie_name; 46 | $this->redirect_http = $redirect_http; 47 | $this->sticky_sessions = $sticky_sessions; 48 | parent::__construct(); 49 | } 50 | 51 | /** 52 | * @param $input 53 | * @return \LKDev\HetznerCloud\Models\LoadBalancers\LoadBalancerServiceHttp|null|static 54 | */ 55 | public static function parse($input) 56 | { 57 | if ($input == null) { 58 | return; 59 | } 60 | 61 | return new self($input->certificates, $input->cookie_lifetime, $input->cookie_name, $input->redirect_http, $input->sticky_essions); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Models/LoadBalancers/LoadBalancerTargetIp.php: -------------------------------------------------------------------------------- 1 | ip = $ip; 20 | parent::__construct(); 21 | } 22 | 23 | /** 24 | * @param $input 25 | * @return \LKDev\HetznerCloud\Models\LoadBalancers\LoadBalancerTargetIp|null|static 26 | */ 27 | public static function parse($input) 28 | { 29 | if ($input == null) { 30 | return; 31 | } 32 | 33 | return new self($input->ip); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Models/Locations/LocationRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Models/Meta.php: -------------------------------------------------------------------------------- 1 | pagination = $pagination; 25 | parent::__construct(null); 26 | } 27 | 28 | /** 29 | * @param $input 30 | * @return \LKDev\HetznerCloud\Models\Meta|null|static 31 | */ 32 | public static function parse($input) 33 | { 34 | if ($input == null) { 35 | return; 36 | } 37 | 38 | return new self(Pagination::parse($input->pagination)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Models/Model.php: -------------------------------------------------------------------------------- 1 | httpClient = $httpClient == null ? HetznerAPIClient::$instance->getHttpClient() : $httpClient; 23 | } 24 | 25 | /** 26 | * @param $input 27 | * @return static 28 | */ 29 | public static function parse($input) 30 | { 31 | return null; 32 | } 33 | 34 | /** 35 | * Replaces or sets the http client. 36 | * 37 | * @param Client $httpClient 38 | */ 39 | public function setHttpClient(?Client $httpClient = null) 40 | { 41 | $this->httpClient = $httpClient; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Models/Networks/NetworkRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 29 | parent::__construct($perPage, $page, $labelSelector); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/Networks/Route.php: -------------------------------------------------------------------------------- 1 | destination = $destination; 32 | $this->gateway = $gateway; 33 | parent::__construct($client); 34 | } 35 | 36 | /** 37 | * @param $input 38 | * @param Client|null $client 39 | * @return array|Model 40 | */ 41 | public static function parse($input, ?Client $client = null) 42 | { 43 | return collect($input)->map(function ($route) use ($client) { 44 | return new self($route->destination, $route->gateway, $client); 45 | })->toArray(); 46 | } 47 | 48 | /** 49 | * @return array 50 | */ 51 | public function __toRequestPayload() 52 | { 53 | return [ 54 | 'destination' => $this->destination, 55 | 'gateway' => $this->gateway, 56 | ]; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Models/Networks/Subnet.php: -------------------------------------------------------------------------------- 1 | type = $type; 44 | $this->ipRange = $ipRange; 45 | $this->networkZone = $networkZone; 46 | $this->gateway = $gateway; 47 | parent::__construct($client); 48 | } 49 | 50 | /** 51 | * @param $input 52 | * @param Client|null $client 53 | * @return array|Model 54 | */ 55 | public static function parse($input, ?Client $client = null) 56 | { 57 | return collect($input)->map(function ($subnet) use ($client) { 58 | return new self($subnet->type, $subnet->ip_range, $subnet->network_zone, $subnet->gateway, $client); 59 | })->toArray(); 60 | } 61 | 62 | /** 63 | * @return array 64 | */ 65 | public function __toRequestPayload() 66 | { 67 | return [ 68 | 'type' => $this->type, 69 | 'ip_range' => $this->ipRange, 70 | 'network_zone' => $this->networkZone, 71 | ]; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Models/Pagination.php: -------------------------------------------------------------------------------- 1 | page = $page; 48 | $this->per_page = $per_page; 49 | $this->previous_page = $previous_page; 50 | $this->next_page = $next_page; 51 | $this->last_page = $last_page; 52 | $this->total_entries = $total_entries; 53 | // Force getting the default http client 54 | parent::__construct(null); 55 | } 56 | 57 | /** 58 | * @param $input 59 | * @return \LKDev\HetznerCloud\Models\Pagination|null|static 60 | */ 61 | public static function parse($input) 62 | { 63 | if ($input == null) { 64 | return; 65 | } 66 | 67 | return new self($input->page, $input->per_page, $input->previous_page, $input->next_page, $input->last_page, $input->total_entries); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Models/PlacementGroups/PlacementGroupRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 31 | $this->type = $type; 32 | parent::__construct($perPage, $page, $labelSelector); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Models/Prices/Prices.php: -------------------------------------------------------------------------------- 1 | httpClient->get('pricing'.$requestOpts->buildQuery()); 42 | if (! HetznerAPIClient::hasError($response)) { 43 | $this->prices = json_decode((string) $response->getBody())->pricing; 44 | 45 | return $this->prices; 46 | } 47 | 48 | return null; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Models/PrimaryIps/PrimaryIPRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 29 | parent::__construct($perPage, $page, $labelSelector); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/Protection.php: -------------------------------------------------------------------------------- 1 | delete = $delete; 34 | $this->rebuild = $rebuild; 35 | // Force getting the default http client 36 | parent::__construct(null); 37 | } 38 | 39 | /** 40 | * @param $input 41 | * @return \LKDev\HetznerCloud\Models\Protection|null|static 42 | */ 43 | public static function parse($input) 44 | { 45 | if ($input == null) { 46 | return; 47 | } 48 | 49 | return new self($input->delete, property_exists($input, 'rebuild') ? $input->rebuild : null); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Models/SSHKeys/SSHKeyRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 39 | $this->fingerprint = $fingerprint; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Models/Servers/ServerRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 34 | $this->status = $status; 35 | parent::__construct($perPage, $page, $labelSelector); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Models/Servers/Types/ServerType.php: -------------------------------------------------------------------------------- 1 | id = $serverTypeId; 67 | $this->name = $name; 68 | parent::__construct(); 69 | } 70 | 71 | /** 72 | * @param $input 73 | * @return $this 74 | */ 75 | public function setAdditionalData($input) 76 | { 77 | $this->name = $input->name; 78 | $this->description = $input->description; 79 | $this->cores = $input->cores; 80 | $this->memory = $input->memory; 81 | $this->disk = $input->disk; 82 | $this->prices = $input->prices; 83 | $this->storageType = $input->storage_type; 84 | $this->cpuType = $input->cpu_type; 85 | $this->architecture = $input->architecture; 86 | 87 | return $this; 88 | } 89 | 90 | /** 91 | * @param $input 92 | * @return self 93 | */ 94 | public static function parse($input) 95 | { 96 | return (new self($input->id))->setAdditionalData($input); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Models/Servers/Types/ServerTypesRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 29 | parent::__construct($perPage, $page, $labelSelector); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Models/Volumes/VolumeRequestOpts.php: -------------------------------------------------------------------------------- 1 | name = $name; 39 | $this->status = $status; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/RequestOpts.php: -------------------------------------------------------------------------------- 1 | HetznerAPIClient::MAX_ENTITIES_PER_PAGE) { 42 | throw new \InvalidArgumentException('perPage can not be larger than '.HetznerAPIClient::MAX_ENTITIES_PER_PAGE); 43 | } 44 | $this->per_page = $perPage; 45 | $this->page = $page; 46 | $this->label_selector = $labelSelector; 47 | } 48 | 49 | /** 50 | * @return string 51 | */ 52 | public function buildQuery() 53 | { 54 | $values = collect(get_object_vars($this)) 55 | ->filter(function ($var) { 56 | return $var != null; 57 | })->toArray(); 58 | 59 | return count($values) == 0 ? '' : ('?'.http_build_query($values)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Traits/GetFunctionTrait.php: -------------------------------------------------------------------------------- 1 | getById((int) $nameOrId); 14 | } catch (\Exception $e) { 15 | unset($e); 16 | 17 | return $this->getByName($nameOrId); 18 | } 19 | } 20 | 21 | protected function _all(RequestOpts $requestOpts) 22 | { 23 | $entities = []; 24 | $requestOpts->per_page = HetznerAPIClient::MAX_ENTITIES_PER_PAGE; 25 | $max_pages = PHP_INT_MAX; 26 | for ($i = 1; $i < $max_pages; $i++) { 27 | $requestOpts->page = $i; 28 | $_f = $this->list($requestOpts); 29 | $entities = array_merge($entities, $_f->{$this->_getKeys()['many']}); 30 | if ($_f->meta->pagination->page === $_f->meta->pagination->last_page || $_f->meta->pagination->last_page === null) { 31 | $max_pages = 0; 32 | } 33 | } 34 | 35 | return $entities; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | mockHandler = new MockHandler(); 31 | $this->hetznerApi = new HetznerAPIClient('abcdef', 'http://localhost:4000/v1/'); 32 | $this->hetznerApi->setHttpClient(new Client(['handler' => $this->mockHandler])); 33 | } 34 | 35 | public function tearDown(): void 36 | { 37 | $this->mockHandler->reset(); 38 | parent::tearDown(); 39 | } 40 | 41 | public function assertLastRequestEquals($method, $urlFragment) 42 | { 43 | $this->assertEquals($this->mockHandler->getLastRequest()->getMethod(), $method); 44 | $this->assertEquals('/'.$this->mockHandler->getLastRequest()->getUri()->getPath(), $urlFragment); 45 | } 46 | 47 | public function assertLastRequestBodyParametersEqual(array $parameters) 48 | { 49 | $body = (string) $this->mockHandler->getLastRequest()->getBody(); 50 | $bodyParameters = json_decode($body, true); 51 | if (json_last_error() != JSON_ERROR_NONE) { 52 | $this->fail('Invalid json within request: '.json_last_error_msg().':'.$body); 53 | } 54 | foreach ($parameters as $parameter => $value) { 55 | $this->assertArrayHasKey($parameter, $bodyParameters); 56 | $this->assertEquals($bodyParameters[$parameter], $value); 57 | } 58 | } 59 | 60 | public function assertLastRequestBodyIsEmpty() 61 | { 62 | $body = (string) $this->mockHandler->getLastRequest()->getBody(); 63 | $this->assertEmpty($body); 64 | } 65 | 66 | public function assertLastRequestQueryParametersContains(string $key, string $value) 67 | { 68 | $query = $this->mockHandler->getLastRequest()->getUri()->getQuery(); 69 | $this->assertStringContainsString(implode('=', [urlencode($key), urlencode($value)]), $query); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Unit/ApiResponseTest.php: -------------------------------------------------------------------------------- 1 | setResponse(['response1' => '12345', 'response2' => 1234, 'response3' => ['abc', 123, [456, 'efg']]]); 21 | $this->assertCount(3, $apiResponse->getResponse()); 22 | } 23 | 24 | public function testSetHeader() 25 | { 26 | $apiResponse = new APIResponse(); 27 | $apiResponse->setHeader(['header-1' => '12345', 'header-2' => 1234]); 28 | $this->assertCount(2, $apiResponse->getHeader()); 29 | } 30 | 31 | public function testCreate() 32 | { 33 | $apiResponse = APIResponse::create(['response1' => '12345', 'response2' => 1234, 'response3' => ['abc', 123, [456, 'efg']]], ['header-1' => 123, 'header-2' => 123]); 34 | $this->assertCount(3, $apiResponse->getResponse()); 35 | $this->assertCount(2, $apiResponse->getHeader()); 36 | } 37 | 38 | public function testGetResponsePart() 39 | { 40 | $apiResponse = new APIResponse(); 41 | $apiResponse->setResponse(['response1' => '12345', 'response2' => 1234, 'response3' => ['abc', 123, [456, 'efg']]]); 42 | $this->assertEquals('12345', $apiResponse->getResponsePart('response1')); 43 | $this->assertEquals(1234, $apiResponse->getResponsePart('response2')); 44 | $this->assertFalse($apiResponse->getResponsePart('not_there')); 45 | } 46 | 47 | public function testGetMagic() 48 | { 49 | $apiResponse = new APIResponse(); 50 | $apiResponse->setResponse(['response1' => '12345', 'response2' => 1234, 'response3' => ['abc', 123, [456, 'efg']]]); 51 | $this->assertEquals('12345', $apiResponse->response1); 52 | $this->assertEquals(1234, $apiResponse->response2); 53 | $this->assertFalse($apiResponse->not_there); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/Unit/Models/Actions/ActionsTest.php: -------------------------------------------------------------------------------- 1 | actions = new Actions($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/action.json'))); 32 | $datacenter = $this->actions->get(13); 33 | $this->assertEquals($datacenter->id, 13); 34 | $this->assertEquals($datacenter->command, 'start_server'); 35 | $this->assertLastRequestEquals('GET', '/actions/13'); 36 | } 37 | 38 | public function testGetByName() 39 | { 40 | $this->expectException(\BadMethodCallException::class); 41 | $this->actions->getByName('start_server'); 42 | } 43 | 44 | public function testAll() 45 | { 46 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/actions.json'))); 47 | $actions = $this->actions->all(); 48 | 49 | $this->assertEquals(count($actions), 1); 50 | $this->assertEquals($actions[0]->id, 13); 51 | $this->assertEquals($actions[0]->command, 'start_server'); 52 | $this->assertLastRequestEquals('GET', '/actions'); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/Unit/Models/Actions/fixtures/action.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "start_server", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 42, 12 | "type": "server" 13 | } 14 | ], 15 | "error": { 16 | "code": "action_failed", 17 | "message": "Action failed" 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/Actions/fixtures/actions.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "id": 13, 5 | "command": "start_server", 6 | "status": "success", 7 | "progress": 100, 8 | "started": "2016-01-30T23:55:00+00:00", 9 | "finished": "2016-01-30T23:56:00+00:00", 10 | "resources": [ 11 | { 12 | "id": 42, 13 | "type": "server" 14 | } 15 | ], 16 | "error": { 17 | "code": "action_failed", 18 | "message": "Action failed" 19 | } 20 | } 21 | ], 22 | "meta": { 23 | "pagination": { 24 | "page": 1, 25 | "per_page": 25, 26 | "previous_page": null, 27 | "next_page": null, 28 | "last_page": 1, 29 | "total_entries": 1 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/Models/Certificates/fixtures/certificate.json: -------------------------------------------------------------------------------- 1 | { 2 | "certificate": { 3 | "id": 897, 4 | "name": "my website cert", 5 | "labels": {}, 6 | "certificate": "-----BEGIN CERTIFICATE-----\n...", 7 | "created": "2019-01-08T12:10:00+00:00", 8 | "not_valid_before": "2019-01-08T10:00:00+00:00", 9 | "not_valid_after": "2019-07-08T09:59:59+00:00", 10 | "domain_names": [ 11 | "example.com", 12 | "webmail.example.com", 13 | "www.example.com" 14 | ], 15 | "fingerprint": "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f", 16 | "used_by": [ 17 | { 18 | "id": 42, 19 | "type": "server" 20 | } 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tests/Unit/Models/Certificates/fixtures/certificates.json: -------------------------------------------------------------------------------- 1 | { 2 | "certificates": [ 3 | { 4 | "id": 897, 5 | "name": "my website cert", 6 | "labels": {}, 7 | "certificate": "-----BEGIN CERTIFICATE-----\n...", 8 | "created": "2019-01-08T12:10:00+00:00", 9 | "not_valid_before": "2019-01-08T10:00:00+00:00", 10 | "not_valid_after": "2019-07-08T09:59:59+00:00", 11 | "domain_names": [ 12 | "example.com", 13 | "webmail.example.com", 14 | "www.example.com" 15 | ], 16 | "fingerprint": "03:c7:55:9b:2a:d1:04:17:09:f6:d0:7f:18:34:63:d4:3e:5f", 17 | "used_by": [ 18 | { 19 | "id": 42, 20 | "type": "server" 21 | } 22 | ] 23 | } 24 | ], 25 | "meta": { 26 | "pagination": { 27 | "page": 1, 28 | "per_page": 25, 29 | "previous_page": null, 30 | "next_page": null, 31 | "last_page": 1, 32 | "total_entries": 1 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/Unit/Models/Datacenters/DatacentersTest.php: -------------------------------------------------------------------------------- 1 | datacenters = new Datacenters($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/datacenter.json'))); 32 | $datacenter = $this->datacenters->get(1); 33 | $this->assertEquals($datacenter->id, 1); 34 | $this->assertEquals($datacenter->name, 'fsn1-dc8'); 35 | $this->assertLastRequestEquals('GET', '/datacenters/1'); 36 | } 37 | 38 | public function testGetByName() 39 | { 40 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/datacenters.json'))); 41 | $datacenter = $this->datacenters->getByName('fsn1-dc8'); 42 | $this->assertEquals($datacenter->id, 1); 43 | $this->assertEquals($datacenter->name, 'fsn1-dc8'); 44 | $this->assertLastRequestQueryParametersContains('name', 'fsn1-dc8'); 45 | $this->assertLastRequestEquals('GET', '/datacenters'); 46 | } 47 | 48 | public function testAll() 49 | { 50 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/datacenters.json'))); 51 | $datacenters = $this->datacenters->all(); 52 | 53 | $this->assertEquals(count($datacenters), 1); 54 | $this->assertEquals($datacenters[0]->id, 1); 55 | $this->assertEquals($datacenters[0]->name, 'fsn1-dc8'); 56 | $this->assertLastRequestEquals('GET', '/datacenters'); 57 | } 58 | 59 | public function testList() 60 | { 61 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/datacenters.json'))); 62 | $datacenters = $this->datacenters->list()->datacenters; 63 | 64 | $this->assertEquals(count($datacenters), 1); 65 | $this->assertEquals($datacenters[0]->id, 1); 66 | $this->assertEquals($datacenters[0]->name, 'fsn1-dc8'); 67 | $this->assertLastRequestEquals('GET', '/datacenters'); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Unit/Models/Datacenters/fixtures/datacenter.json: -------------------------------------------------------------------------------- 1 | { 2 | "datacenter": { 3 | "id": 1, 4 | "name": "fsn1-dc8", 5 | "description": "Falkenstein DC Park 8", 6 | "location": { 7 | "id": 1, 8 | "name": "fsn1", 9 | "description": "Faleknstein DC Park 1", 10 | "country": "DE", 11 | "city": "Falkenstein", 12 | "latitude": 50.47612, 13 | "longitude": 12.370071, 14 | "network_zone": "eu-central" 15 | }, 16 | "server_types": { 17 | "supported": [ 18 | 1, 19 | 2, 20 | 3 21 | ], 22 | "available": [ 23 | 1, 24 | 2, 25 | 3 26 | ], 27 | "available_for_migration": [ 28 | 1, 29 | 2, 30 | 3 31 | ] 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /tests/Unit/Models/Datacenters/fixtures/datacenters.json: -------------------------------------------------------------------------------- 1 | { 2 | "datacenters": [ 3 | { 4 | "id": 1, 5 | "name": "fsn1-dc8", 6 | "description": "Falkenstein DC Park 8", 7 | "location": { 8 | "id": 1, 9 | "name": "fsn1", 10 | "description": "Faleknstein DC Park 1", 11 | "country": "DE", 12 | "city": "Falkenstein", 13 | "latitude": 50.47612, 14 | "longitude": 12.370071, 15 | "network_zone": "eu-central" 16 | }, 17 | "server_types": { 18 | "supported": [ 19 | 1, 20 | 2, 21 | 3 22 | ], 23 | "available": [ 24 | 1, 25 | 2, 26 | 3 27 | ], 28 | "available_for_migration": [ 29 | 1, 30 | 2, 31 | 3 32 | ] 33 | } 34 | } 35 | ], 36 | "recommendation": 1, 37 | "meta": { 38 | "pagination": { 39 | "page": 1, 40 | "per_page": 25, 41 | "previous_page": null, 42 | "next_page": null, 43 | "last_page": 1, 44 | "total_entries": 1 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewall.json: -------------------------------------------------------------------------------- 1 | { 2 | "firewall": { 3 | "id": 38, 4 | "name": "Corporate Intranet Protection", 5 | "labels": {}, 6 | "created": "2016-01-30T23:50:00+00:00", 7 | "rules": [ 8 | { 9 | "direction": "in", 10 | "source_ips": [ 11 | "28.239.13.1/32", 12 | "28.239.14.0/24", 13 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 14 | ], 15 | "destination_ips": [ 16 | "28.239.13.1/32", 17 | "28.239.14.0/24", 18 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 19 | ], 20 | "protocol": "tcp", 21 | "port": "80" 22 | } 23 | ], 24 | "applied_to": [ 25 | { 26 | "type": "server", 27 | "server": { 28 | "id": 42 29 | } 30 | }, 31 | { 32 | "type": "label_selector", 33 | "label_selector": { 34 | "applied_to_resources": [] 35 | } 36 | } 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewall_action_apply_to_resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "id": 14, 5 | "command": "apply_firewall", 6 | "status": "success", 7 | "progress": 100, 8 | "started": "2016-01-30T23:55:00+00:00", 9 | "finished": "2016-01-30T23:56:00+00:00", 10 | "resources": [ 11 | { 12 | "id": 42, 13 | "type": "server" 14 | }, 15 | { 16 | "id": 38, 17 | "type": "firewall" 18 | } 19 | ], 20 | "error": null 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewall_action_remove_from_resources.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "id": 14, 5 | "command": "remove_firewall", 6 | "status": "success", 7 | "progress": 100, 8 | "started": "2016-01-30T23:55:00+00:00", 9 | "finished": "2016-01-30T23:56:00+00:00", 10 | "resources": [ 11 | { 12 | "id": 42, 13 | "type": "server" 14 | }, 15 | { 16 | "id": 38, 17 | "type": "firewall" 18 | } 19 | ], 20 | "error": null 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewall_action_set_rules.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "id": 13, 5 | "command": "set_firewall_rules", 6 | "status": "success", 7 | "progress": 100, 8 | "started": "2016-01-30T23:55:00+00:00", 9 | "finished": "2016-01-30T23:56:00+00:00", 10 | "resources": [ 11 | { 12 | "id": 38, 13 | "type": "firewall" 14 | } 15 | ], 16 | "error": { 17 | "code": "action_failed", 18 | "message": "Action failed" 19 | } 20 | }, 21 | { 22 | "id": 14, 23 | "command": "apply_firewall", 24 | "status": "success", 25 | "progress": 100, 26 | "started": "2016-01-30T23:55:00+00:00", 27 | "finished": "2016-01-30T23:56:00+00:00", 28 | "resources": [ 29 | { 30 | "id": 38, 31 | "type": "firewall" 32 | }, 33 | { 34 | "id": 42, 35 | "type": "server" 36 | } 37 | ], 38 | "error": { 39 | "code": "action_failed", 40 | "message": "Action failed" 41 | } 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewall_create.json: -------------------------------------------------------------------------------- 1 | { 2 | "firewall": { 3 | "id": 38, 4 | "name": "Corporate Intranet Protection", 5 | "labels": {}, 6 | "created": "2016-01-30T23:50:00+00:00", 7 | "rules": [ 8 | { 9 | "direction": "in", 10 | "source_ips": [ 11 | "28.239.13.1/32", 12 | "28.239.14.0/24", 13 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 14 | ], 15 | "destination_ips": [ 16 | "28.239.13.1/32", 17 | "28.239.14.0/24", 18 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 19 | ], 20 | "protocol": "tcp", 21 | "port": "80" 22 | } 23 | ], 24 | "applied_to": [ 25 | { 26 | "type": "server", 27 | "server": { 28 | "id": 42 29 | } 30 | } 31 | ] 32 | }, 33 | "actions": [ 34 | { 35 | "id": 13, 36 | "command": "set_firewall_rules", 37 | "status": "success", 38 | "progress": 100, 39 | "started": "2016-01-30T23:55:00+00:00", 40 | "finished": "2016-01-30T23:56:00+00:00", 41 | "resources": [ 42 | { 43 | "id": 38, 44 | "type": "firewall" 45 | } 46 | ], 47 | "error": { 48 | "code": "action_failed", 49 | "message": "Action failed" 50 | } 51 | }, 52 | { 53 | "id": 14, 54 | "command": "apply_firewall", 55 | "status": "success", 56 | "progress": 100, 57 | "started": "2016-01-30T23:55:00+00:00", 58 | "finished": "2016-01-30T23:56:00+00:00", 59 | "resources": [ 60 | { 61 | "id": 42, 62 | "type": "server" 63 | }, 64 | { 65 | "id": 38, 66 | "type": "firewall" 67 | } 68 | ], 69 | "error": null 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /tests/Unit/Models/Firewalls/fixtures/firewalls.json: -------------------------------------------------------------------------------- 1 | { 2 | "firewalls": [ 3 | { 4 | "id": 38, 5 | "name": "Corporate Intranet Protection", 6 | "labels": {}, 7 | "created": "2016-01-30T23:50:00+00:00", 8 | "rules": [ 9 | { 10 | "direction": "in", 11 | "source_ips": [ 12 | "28.239.13.1/32", 13 | "28.239.14.0/24", 14 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 15 | ], 16 | "destination_ips": [ 17 | "28.239.13.1/32", 18 | "28.239.14.0/24", 19 | "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" 20 | ], 21 | "protocol": "tcp", 22 | "port": "80" 23 | } 24 | ], 25 | "applied_to": [ 26 | { 27 | "type": "server", 28 | "server": { 29 | "id": 42 30 | } 31 | }, 32 | { 33 | "type": "label_selector", 34 | "label_selector": { 35 | "applied_to_resources": [] 36 | } 37 | } 38 | ] 39 | } 40 | ], 41 | "meta": { 42 | "pagination": { 43 | "page": 1, 44 | "per_page": 25, 45 | "previous_page": null, 46 | "next_page": null, 47 | "last_page": 1, 48 | "total_entries": 1 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP.json: -------------------------------------------------------------------------------- 1 | { 2 | "floating_ip": { 3 | "id": 4711, 4 | "name": "Web Frontend", 5 | "description": "Web Frontend", 6 | "ip": "131.232.99.1", 7 | "type": "ipv4", 8 | "server": 42, 9 | "dns_ptr": [ 10 | { 11 | "ip": "2001:db8::1", 12 | "dns_ptr": "server.example.com" 13 | } 14 | ], 15 | "home_location": { 16 | "id": 1, 17 | "name": "fsn1", 18 | "description": "Falkenstein DC Park 1", 19 | "country": "DE", 20 | "city": "Falkenstein", 21 | "latitude": 50.47612, 22 | "longitude": 12.370071, 23 | "network_zone": "eu-central" 24 | }, 25 | "blocked": false, 26 | "protection": { 27 | "delete": false 28 | }, 29 | "labels": {}, 30 | "created": "2016-01-30T23:50:00+00:00" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP_action_assign_floating_ip.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "assign_floating_ip", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 42, 12 | "type": "server" 13 | }, 14 | { 15 | "id": 4711, 16 | "type": "floating_ip" 17 | } 18 | ], 19 | "error": null 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP_action_change_dns_ptr.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "change_dns_ptr", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 4711, 12 | "type": "floating_ip" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP_action_change_protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "change_protection", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 4711, 12 | "type": "floating_ip" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP_action_unassign_floating_ip.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "unassign_floating_ip", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 42, 12 | "type": "server" 13 | }, 14 | { 15 | "id": 4711, 16 | "type": "floating_ip" 17 | } 18 | ], 19 | "error": null 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIP_create.json: -------------------------------------------------------------------------------- 1 | { 2 | "floating_ip": { 3 | "id": 4711, 4 | "name": "Web Frontend", 5 | "description": "Web Frontend", 6 | "ip": "131.232.99.1", 7 | "type": "ipv4", 8 | "server": 42, 9 | "dns_ptr": [ 10 | { 11 | "ip": "2001:db8::1", 12 | "dns_ptr": "server.example.com" 13 | } 14 | ], 15 | "home_location": { 16 | "id": 1, 17 | "name": "fsn1", 18 | "description": "Falkenstein DC Park 1", 19 | "country": "DE", 20 | "city": "Falkenstein", 21 | "latitude": 50.47612, 22 | "longitude": 12.370071, 23 | "network_zone": "eu-central" 24 | }, 25 | "blocked": false, 26 | "protection": { 27 | "delete": false 28 | }, 29 | "labels": {}, 30 | "created": "2016-01-30T23:50:00+00:00" 31 | }, 32 | "action": { 33 | "id": 13, 34 | "command": "create_floating_ip", 35 | "status": "running", 36 | "progress": 0, 37 | "started": "2016-01-30T23:50:00+00:00", 38 | "finished": null, 39 | "resources": [ 40 | { 41 | "id": 42, 42 | "type": "server" 43 | } 44 | ], 45 | "error": null 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/Unit/Models/FloatingIPs/fixtures/floatingIPs.json: -------------------------------------------------------------------------------- 1 | { 2 | "floating_ips": [ 3 | { 4 | "id": 4711, 5 | "name": "Web Frontend", 6 | "description": "Web Frontend", 7 | "ip": "131.232.99.1", 8 | "type": "ipv4", 9 | "server": 42, 10 | "dns_ptr": [ 11 | { 12 | "ip": "2001:db8::1", 13 | "dns_ptr": "server.example.com" 14 | } 15 | ], 16 | "home_location": { 17 | "id": 1, 18 | "name": "fsn1", 19 | "description": "Falkenstein DC Park 1", 20 | "country": "DE", 21 | "city": "Falkenstein", 22 | "latitude": 50.47612, 23 | "longitude": 12.370071, 24 | "network_zone": "eu-central" 25 | }, 26 | "blocked": false, 27 | "protection": { 28 | "delete": false 29 | }, 30 | "labels": {}, 31 | "created": "2016-01-30T23:50:00+00:00" 32 | } 33 | ], 34 | "meta": { 35 | "pagination": { 36 | "page": 1, 37 | "per_page": 25, 38 | "previous_page": null, 39 | "next_page": null, 40 | "last_page": 1, 41 | "total_entries": 1 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Unit/Models/ISO/ISOsTest.php: -------------------------------------------------------------------------------- 1 | isos = new ISOs($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/iso.json'))); 32 | 33 | $iso = $this->isos->get(4711); 34 | $this->assertEquals($iso->id, 4711); 35 | $this->assertEquals($iso->name, 'FreeBSD-11.0-RELEASE-amd64-dvd1'); 36 | 37 | $this->assertLastRequestEquals('GET', '/isos/4711'); 38 | } 39 | 40 | public function testAll() 41 | { 42 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/isos.json'))); 43 | 44 | $isos = $this->isos->all(); 45 | 46 | $this->assertEquals(count($isos), 1); 47 | $this->assertEquals($isos[0]->id, 4711); 48 | $this->assertEquals($isos[0]->name, 'FreeBSD-11.0-RELEASE-amd64-dvd1'); 49 | 50 | $this->assertLastRequestEquals('GET', '/isos'); 51 | } 52 | 53 | public function testList() 54 | { 55 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/isos.json'))); 56 | $isos = $this->isos->list()->isos; 57 | 58 | $this->assertEquals(count($isos), 1); 59 | $this->assertEquals($isos[0]->id, 4711); 60 | $this->assertEquals($isos[0]->name, 'FreeBSD-11.0-RELEASE-amd64-dvd1'); 61 | 62 | $this->assertLastRequestEquals('GET', '/isos'); 63 | } 64 | 65 | public function testGetByName() 66 | { 67 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/isos.json'))); 68 | $iso = $this->isos->getByName('FreeBSD-11.0-RELEASE-amd64-dvd1'); 69 | $this->assertEquals($iso->id, 4711); 70 | $this->assertEquals($iso->name, 'FreeBSD-11.0-RELEASE-amd64-dvd1'); 71 | $this->assertLastRequestQueryParametersContains('name', 'FreeBSD-11.0-RELEASE-amd64-dvd1'); 72 | $this->assertLastRequestEquals('GET', '/isos'); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/Unit/Models/ISO/fixtures/iso.json: -------------------------------------------------------------------------------- 1 | { 2 | "iso": { 3 | "id": 4711, 4 | "name": "FreeBSD-11.0-RELEASE-amd64-dvd1", 5 | "description": "FreeBSD 11.0 x64", 6 | "type": "public", 7 | "deprecated": "2018-02-28T00:00:00+00:00" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/Unit/Models/ISO/fixtures/isos.json: -------------------------------------------------------------------------------- 1 | { 2 | "isos": [ 3 | { 4 | "id": 4711, 5 | "name": "FreeBSD-11.0-RELEASE-amd64-dvd1", 6 | "description": "FreeBSD 11.0 x64", 7 | "type": "public", 8 | "deprecated": "2018-02-28T00:00:00+00:00" 9 | } 10 | ], 11 | "recommendation": 1, 12 | "meta": { 13 | "pagination": { 14 | "page": 1, 15 | "per_page": 25, 16 | "previous_page": null, 17 | "next_page": null, 18 | "last_page": 1, 19 | "total_entries": 1 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Unit/Models/Images/fixtures/image.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": { 3 | "id": 4711, 4 | "type": "snapshot", 5 | "status": "available", 6 | "architecture": "arm", 7 | "name": "ubuntu-20.04", 8 | "description": "Ubuntu 20.04 Standard 64 bit", 9 | "image_size": 2.3, 10 | "disk_size": 10, 11 | "created": "2016-01-30T23:50:00+00:00", 12 | "created_from": { 13 | "id": 1, 14 | "name": "Server" 15 | }, 16 | "bound_to": null, 17 | "os_flavor": "ubuntu", 18 | "os_version": "20.04", 19 | "rapid_deploy": false, 20 | "protection": { 21 | "delete": false 22 | }, 23 | "deprecated": "2018-02-28T00:00:00+00:00", 24 | "labels": {} 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Models/Images/fixtures/image_action_change_protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "change_protection", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 4711, 12 | "type": "image" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Images/fixtures/images.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "id": 4711, 5 | "type": "snapshot", 6 | "architecture": "arm", 7 | "status": "available", 8 | "name": "ubuntu-20.04", 9 | "description": "Ubuntu 20.04 Standard 64 bit", 10 | "image_size": 2.3, 11 | "disk_size": 10, 12 | "created": "2016-01-30T23:50:00+00:00", 13 | "created_from": { 14 | "id": 1, 15 | "name": "Server" 16 | }, 17 | "bound_to": null, 18 | "os_flavor": "ubuntu", 19 | "os_version": "20.04", 20 | "rapid_deploy": false, 21 | "protection": { 22 | "delete": false 23 | }, 24 | "deprecated": "2018-02-28T00:00:00+00:00", 25 | "labels": {} 26 | } 27 | ], 28 | "meta": { 29 | "pagination": { 30 | "page": 1, 31 | "per_page": 25, 32 | "previous_page": null, 33 | "next_page": null, 34 | "last_page": 1, 35 | "total_entries": 1 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancerTypes/LoadBalancerTypeTest.php: -------------------------------------------------------------------------------- 1 | hetznerApi->getHttpClient()); 25 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancerType.json'))); 26 | $this->load_balancer_type = $tmp->get(4711); 27 | } 28 | 29 | public function testDeleteThrowsException() 30 | { 31 | $this->expectException(BadMethodCallException::class); 32 | $this->load_balancer_type->delete(); 33 | } 34 | 35 | public function testUpdateThrowsException() 36 | { 37 | $this->expectException(BadMethodCallException::class); 38 | $this->load_balancer_type->update([]); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancerTypes/LoadBalancerTypesTest.php: -------------------------------------------------------------------------------- 1 | load_balancer_types = new LoadBalancerTypes($this->hetznerApi->getHttpClient()); 20 | } 21 | 22 | /** 23 | * @throws \LKDev\HetznerCloud\APIException 24 | */ 25 | public function testAll() 26 | { 27 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancerTypes.json'))); 28 | $loadBalancerTypes = $this->load_balancer_types->all(); 29 | 30 | $this->assertCount(2, $loadBalancerTypes); 31 | $this->assertLastRequestEquals('GET', '/load_balancer_types'); 32 | } 33 | 34 | public function testGet() 35 | { 36 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancerType.json'))); 37 | $loadBalancer = $this->load_balancer_types->get(4711); 38 | 39 | $this->assertEquals($loadBalancer->id, 4711); 40 | $this->assertEquals($loadBalancer->name, 'lb11'); 41 | 42 | $this->assertLastRequestEquals('GET', '/load_balancer_types/4711'); 43 | } 44 | 45 | public function testGetByName() 46 | { 47 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancerTypes.json'))); 48 | $loadBalancer = $this->load_balancer_types->getByName('lb11'); 49 | 50 | $this->assertEquals($loadBalancer->id, 4711); 51 | $this->assertEquals($loadBalancer->name, 'lb11'); 52 | $this->assertLastRequestEquals('GET', '/load_balancer_types'); 53 | $this->assertLastRequestQueryParametersContains('name', 'lb11'); 54 | } 55 | 56 | public function testList() 57 | { 58 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancerTypes.json'))); 59 | $loadBalancerTypes = $this->load_balancer_types->list()->load_balancer_types; 60 | 61 | $this->assertEquals(count($loadBalancerTypes), 2); 62 | $this->assertEquals($loadBalancerTypes[0]->id, 4711); 63 | $this->assertEquals($loadBalancerTypes[0]->name, 'lb11'); 64 | $this->assertLastRequestEquals('GET', '/load_balancer_types'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancerTypes/fixtures/loadBalancerType.json: -------------------------------------------------------------------------------- 1 | { 2 | "load_balancer_type": { 3 | "deprecated": "2016-01-30T23:50:00+00:00", 4 | "description": "LB11", 5 | "id": 4711, 6 | "max_assigned_certificates": 10, 7 | "max_connections": 20000, 8 | "max_services": 5, 9 | "max_targets": 25, 10 | "name": "lb11", 11 | "prices": [ 12 | { 13 | "location": "fsn1", 14 | "price_hourly": { 15 | "gross": "1.1900000000000000", 16 | "net": "1.0000000000" 17 | }, 18 | "price_monthly": { 19 | "gross": "1.1900000000000000", 20 | "net": "1.0000000000" 21 | } 22 | } 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancerTypes/fixtures/loadBalancerTypes.json: -------------------------------------------------------------------------------- 1 | { 2 | "load_balancer_types": [ 3 | { 4 | "deprecated": "2016-01-30T23:50:00+00:00", 5 | "description": "LB11", 6 | "id": 4711, 7 | "max_assigned_certificates": 10, 8 | "max_connections": 20000, 9 | "max_services": 5, 10 | "max_targets": 25, 11 | "name": "lb11", 12 | "prices": [ 13 | { 14 | "location": "fsn1", 15 | "price_hourly": { 16 | "gross": "1.1900000000000000", 17 | "net": "1.0000000000" 18 | }, 19 | "price_monthly": { 20 | "gross": "1.1900000000000000", 21 | "net": "1.0000000000" 22 | } 23 | } 24 | ] 25 | }, 26 | { 27 | "deprecated": null, 28 | "description": "LB11", 29 | "id": 1174, 30 | "max_assigned_certificates": 10, 31 | "max_connections": 20000, 32 | "max_services": 15, 33 | "max_targets": 75, 34 | "name": "lb21", 35 | "prices": [ 36 | { 37 | "location": "fsn1", 38 | "price_hourly": { 39 | "gross": "1.1900000000000000", 40 | "net": "1.0000000000" 41 | }, 42 | "price_monthly": { 43 | "gross": "1.1900000000000000", 44 | "net": "1.0000000000" 45 | } 46 | } 47 | ] 48 | } 49 | ], 50 | "meta": { 51 | "pagination": { 52 | "last_page": 1, 53 | "next_page": 1, 54 | "page": 1, 55 | "per_page": 25, 56 | "previous_page": 1, 57 | "total_entries": 100 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/LoadBalancersTest.php: -------------------------------------------------------------------------------- 1 | loadBalancers = new LoadBalancers($this->hetznerApi->getHttpClient()); 20 | } 21 | 22 | /** 23 | * @throws \LKDev\HetznerCloud\APIException 24 | */ 25 | public function testAll() 26 | { 27 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancers.json'))); 28 | $loadBalancers = $this->loadBalancers->all(); 29 | 30 | $this->assertCount(1, $loadBalancers); 31 | $this->assertLastRequestEquals('GET', '/load_balancers'); 32 | } 33 | 34 | public function testGet() 35 | { 36 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancer.json'))); 37 | $loadBalancer = $this->loadBalancers->get(4711); 38 | 39 | $this->assertEquals($loadBalancer->id, 4711); 40 | $this->assertEquals($loadBalancer->name, 'my-resource'); 41 | 42 | $this->assertLastRequestEquals('GET', '/load_balancers/4711'); 43 | } 44 | 45 | public function testGetByName() 46 | { 47 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancers.json'))); 48 | $loadBalancer = $this->loadBalancers->getByName('my-resource'); 49 | 50 | $this->assertEquals($loadBalancer->id, 4711); 51 | $this->assertEquals($loadBalancer->name, 'my-resource'); 52 | $this->assertLastRequestEquals('GET', '/load_balancers'); 53 | $this->assertLastRequestQueryParametersContains('name', 'my-resource'); 54 | } 55 | 56 | public function testList() 57 | { 58 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/loadBalancers.json'))); 59 | $loadBalancers = $this->loadBalancers->list()->load_balancers; 60 | 61 | $this->assertEquals(count($loadBalancers), 1); 62 | $this->assertEquals($loadBalancers[0]->id, 4711); 63 | $this->assertEquals($loadBalancers[0]->name, 'my-resource'); 64 | $this->assertLastRequestEquals('GET', '/load_balancers'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_add_service.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "add_service", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_add_target.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "add_target", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_attach_loadbalancer_network.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "attach_to_network", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_change_algorithm.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_algorithm", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_change_dns_ptr.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_dns_ptr", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:50:00+00:00", 18 | "status": "running" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_change_load_balancer_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_load_balancer_type", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "server" 15 | } 16 | ], 17 | "started": "2016-01-30T23:50:00+00:00", 18 | "status": "running" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_change_protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_protection", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_delete_service.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "delete_service", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_detach_from_network.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "detach_from_network", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | }, 16 | { 17 | "id": 1234, 18 | "type": "network" 19 | } 20 | ], 21 | "started": "2016-01-30T23:50:00+00:00", 22 | "status": "running" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_disable_public_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "disable_public_interface", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | }, 16 | { 17 | "id": 4711, 18 | "type": "network" 19 | } 20 | ], 21 | "started": "2016-01-30T23:50:00+00:00", 22 | "status": "running" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_enable_public_interface.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "enable_public_interface", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | }, 16 | { 17 | "id": 4711, 18 | "type": "network" 19 | } 20 | ], 21 | "started": "2016-01-30T23:50:00+00:00", 22 | "status": "running" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_remove_target.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "remove_target", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/LoadBalancers/fixtures/loadBalancer_action_update_service.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "update_service", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "load_balancer" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/Locations/LocationsTest.php: -------------------------------------------------------------------------------- 1 | locations = new Locations($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/location.json'))); 32 | $location = $this->locations->get(1); 33 | $this->assertEquals($location->id, 1); 34 | $this->assertEquals($location->name, 'fsn1'); 35 | 36 | $this->assertLastRequestEquals('GET', '/locations/1'); 37 | } 38 | 39 | public function testGetByName() 40 | { 41 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/locations.json'))); 42 | $location = $this->locations->getByName('fsn1'); 43 | $this->assertEquals($location->id, 1); 44 | $this->assertEquals($location->name, 'fsn1'); 45 | $this->assertLastRequestEquals('GET', '/locations'); 46 | $this->assertLastRequestQueryParametersContains('name', 'fsn1'); 47 | } 48 | 49 | public function testAll() 50 | { 51 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/locations.json'))); 52 | $locations = $this->locations->all(); 53 | 54 | $this->assertEquals(count($locations), 1); 55 | $this->assertEquals($locations[0]->id, 1); 56 | $this->assertEquals($locations[0]->name, 'fsn1'); 57 | $this->assertLastRequestEquals('GET', '/locations'); 58 | } 59 | 60 | public function testList() 61 | { 62 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/locations.json'))); 63 | $locations = $this->locations->list()->locations; 64 | 65 | $this->assertEquals(count($locations), 1); 66 | $this->assertEquals($locations[0]->id, 1); 67 | $this->assertEquals($locations[0]->name, 'fsn1'); 68 | $this->assertLastRequestEquals('GET', '/locations'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/Unit/Models/Locations/fixtures/location.json: -------------------------------------------------------------------------------- 1 | { 2 | "location": { 3 | "id": 1, 4 | "name": "fsn1", 5 | "description": "Falkenstein DC Park 1", 6 | "country": "DE", 7 | "city": "Falkenstein", 8 | "latitude": 50.47612, 9 | "longitude": 12.370071, 10 | "network_zone": "eu-central" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/Unit/Models/Locations/fixtures/locations.json: -------------------------------------------------------------------------------- 1 | { 2 | "locations": [ 3 | { 4 | "id": 1, 5 | "name": "fsn1", 6 | "description": "Falkenstein DC Park 1", 7 | "country": "DE", 8 | "city": "Falkenstein", 9 | "latitude": 50.47612, 10 | "longitude": 12.370071, 11 | "network_zone": "eu-central" 12 | } 13 | ], 14 | "meta": { 15 | "pagination": { 16 | "page": 1, 17 | "per_page": 25, 18 | "previous_page": null, 19 | "next_page": null, 20 | "last_page": 1, 21 | "total_entries": 1 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/Networks/fixtures/network.json: -------------------------------------------------------------------------------- 1 | { 2 | "network": { 3 | "id": 4711, 4 | "name": "mynet", 5 | "ip_range": "10.0.0.0/16", 6 | "subnets": [ 7 | { 8 | "type": "cloud", 9 | "ip_range": "10.0.1.0/24", 10 | "network_zone": "eu-central", 11 | "gateway": "10.0.0.1" 12 | } 13 | ], 14 | "routes": [ 15 | { 16 | "destination": "10.100.1.0/24", 17 | "gateway": "10.0.1.1" 18 | } 19 | ], 20 | "servers": [ 21 | 42 22 | ], 23 | "load_balancers": [ 24 | 42 25 | ], 26 | "protection": { 27 | "delete": false 28 | }, 29 | "labels": {}, 30 | "created": "2016-01-30T23:50:00+00:00" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/Unit/Models/Networks/fixtures/network_action_generic.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "$command", 5 | "status": "running", 6 | "progress": 0, 7 | "started": "2016-01-30T23:50:00+00:00", 8 | "finished": null, 9 | "resources": [ 10 | { 11 | "id": 4711, 12 | "type": "network" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Networks/fixtures/networks.json: -------------------------------------------------------------------------------- 1 | { 2 | "networks": [ 3 | { 4 | "id": 4711, 5 | "name": "mynet", 6 | "ip_range": "10.0.0.0/16", 7 | "subnets": [ 8 | { 9 | "type": "cloud", 10 | "ip_range": "10.0.1.0/24", 11 | "network_zone": "eu-central", 12 | "gateway": "10.0.0.1" 13 | } 14 | ], 15 | "routes": [ 16 | { 17 | "destination": "10.100.1.0/24", 18 | "gateway": "10.0.1.1" 19 | } 20 | ], 21 | "servers": [ 22 | 42 23 | ], 24 | "load_balancers": [ 25 | 42 26 | ], 27 | "protection": { 28 | "delete": false 29 | }, 30 | "labels": {}, 31 | "created": "2016-01-30T23:50:00+00:00" 32 | } 33 | ], 34 | "meta": { 35 | "pagination": { 36 | "page": 1, 37 | "per_page": 25, 38 | "previous_page": null, 39 | "next_page": null, 40 | "last_page": 1, 41 | "total_entries": 1 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /tests/Unit/Models/PlacementGroups/PlacementGroupTest.php: -------------------------------------------------------------------------------- 1 | hetznerApi->getHttpClient()); 21 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/placement_group.json'))); 22 | $this->placement_group = $tmp->get(4862); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/PlacementGroups/fixtures/placement_group.json: -------------------------------------------------------------------------------- 1 | { 2 | "placement_group": { 3 | "id": 4862, 4 | "name": "my_placemengroup", 5 | "type": "spread", 6 | "servers": [ 7 | 42 8 | ], 9 | "labels": {}, 10 | "created": "2016-01-30T23:50:00+00:00" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/Unit/Models/PlacementGroups/fixtures/placement_groups.json: -------------------------------------------------------------------------------- 1 | { 2 | "placement_groups": [ 3 | { 4 | "id": 4862, 5 | "name": "my_placemengroup", 6 | "type": "spread", 7 | "servers": [ 8 | 42 9 | ], 10 | "labels": {}, 11 | "created": "2016-01-30T23:50:00+00:00" 12 | } 13 | ], 14 | "meta": { 15 | "pagination": { 16 | "page": 1, 17 | "per_page": 25, 18 | "previous_page": null, 19 | "next_page": null, 20 | "last_page": 1, 21 | "total_entries": 1 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/Pricing/PricingTest.php: -------------------------------------------------------------------------------- 1 | prices = new Prices($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testAll() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/pricing.json'))); 32 | $prices = $this->prices->all(); 33 | $this->assertEquals('EUR', $prices->currency); 34 | $this->assertEquals('19.000000', $prices->vat_rate); 35 | $this->assertEquals('1.0000000000', $prices->image->price_per_gb_month->net); 36 | $this->assertIsArray($prices->server_types); 37 | $this->assertLastRequestEquals('GET', '/pricing'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Unit/Models/Pricing/fixtures/pricing.json: -------------------------------------------------------------------------------- 1 | { 2 | "pricing": { 3 | "currency": "EUR", 4 | "vat_rate": "19.000000", 5 | "image": { 6 | "price_per_gb_month": { 7 | "net": "1.0000000000", 8 | "gross": "1.1900000000000000" 9 | } 10 | }, 11 | "floating_ip": { 12 | "price_monthly": { 13 | "net": "1.0000000000", 14 | "gross": "1.1900000000000000" 15 | } 16 | }, 17 | "traffic": { 18 | "price_per_tb": { 19 | "net": "1.0000000000", 20 | "gross": "1.1900000000000000" 21 | } 22 | }, 23 | "server_backup": { 24 | "percentage": "20.0000000000" 25 | }, 26 | "volume": { 27 | "price_per_gb_month": { 28 | "net": "1.0000000000", 29 | "gross": "1.1900000000000000" 30 | } 31 | }, 32 | "server_types": [ 33 | { 34 | "id": 4, 35 | "name": "cx11", 36 | "prices": [ 37 | { 38 | "location": "fsn1", 39 | "price_hourly": { 40 | "net": "1.0000000000", 41 | "gross": "1.1900000000000000" 42 | }, 43 | "price_monthly": { 44 | "net": "1.0000000000", 45 | "gross": "1.1900000000000000" 46 | } 47 | } 48 | ] 49 | } 50 | ], 51 | "load_balancer_types": [ 52 | { 53 | "id": 1, 54 | "name": "lb11", 55 | "prices": [ 56 | { 57 | "location": "fsn1", 58 | "price_hourly": { 59 | "net": "1.0000000000", 60 | "gross": "1.1900000000000000" 61 | }, 62 | "price_monthly": { 63 | "net": "1.0000000000", 64 | "gross": "1.1900000000000000" 65 | } 66 | } 67 | ] 68 | } 69 | ] 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIP.json: -------------------------------------------------------------------------------- 1 | { 2 | "primary_ip": { 3 | "assignee_id": 17, 4 | "assignee_type": "server", 5 | "auto_delete": true, 6 | "blocked": false, 7 | "created": "2016-01-30T23:55:00+00:00", 8 | "datacenter": { 9 | "description": "Falkenstein DC Park 8", 10 | "id": 42, 11 | "location": { 12 | "city": "Falkenstein", 13 | "country": "DE", 14 | "description": "Falkenstein DC Park 1", 15 | "id": 1, 16 | "latitude": 50.47612, 17 | "longitude": 12.370071, 18 | "name": "fsn1", 19 | "network_zone": "eu-central" 20 | }, 21 | "name": "fsn1-dc8", 22 | "server_types": { 23 | "available": [ 24 | 1, 25 | 2, 26 | 3 27 | ], 28 | "available_for_migration": [ 29 | 1, 30 | 2, 31 | 3 32 | ], 33 | "supported": [ 34 | 1, 35 | 2, 36 | 3 37 | ] 38 | } 39 | }, 40 | "dns_ptr": [ 41 | { 42 | "dns_ptr": "server.example.com", 43 | "ip": "131.232.99.1" 44 | } 45 | ], 46 | "id": 4711, 47 | "ip": "131.232.99.1", 48 | "labels": {}, 49 | "name": "my-resource", 50 | "protection": { 51 | "delete": false 52 | }, 53 | "type": "ipv4" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIP_action_assign_primary_ip.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "assign_primary_ip", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | }, 16 | { 17 | "id": 4711, 18 | "type": "primary_ip" 19 | } 20 | ], 21 | "started": "2016-01-30T23:50:00+00:00", 22 | "status": "running" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIP_action_change_dns_ptr.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_dns_ptr", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "primary_ip" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIP_action_change_protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "change_protection", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "id": 13, 10 | "progress": 100, 11 | "resources": [ 12 | { 13 | "id": 4711, 14 | "type": "primary_ip" 15 | } 16 | ], 17 | "started": "2016-01-30T23:55:00+00:00", 18 | "status": "success" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIP_action_unassign_primary_ip.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "command": "unassign_primary_ip", 4 | "error": { 5 | "code": "action_failed", 6 | "message": "Action failed" 7 | }, 8 | "finished": null, 9 | "id": 13, 10 | "progress": 0, 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | }, 16 | { 17 | "id": 4711, 18 | "type": "primary_ip" 19 | } 20 | ], 21 | "started": "2016-01-30T23:50:00+00:00", 22 | "status": "running" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/Unit/Models/PrimaryIps/fixtures/primaryIPs.json: -------------------------------------------------------------------------------- 1 | { 2 | "meta": { 3 | "pagination": { 4 | "last_page": 1, 5 | "next_page": 1, 6 | "page": 1, 7 | "per_page": 25, 8 | "previous_page": 1, 9 | "total_entries": 100 10 | } 11 | }, 12 | "primary_ips": [ 13 | { 14 | "assignee_id": 17, 15 | "assignee_type": "server", 16 | "auto_delete": true, 17 | "blocked": false, 18 | "created": "2016-01-30T23:55:00+00:00", 19 | "datacenter": { 20 | "description": "Falkenstein DC Park 8", 21 | "id": 42, 22 | "location": { 23 | "city": "Falkenstein", 24 | "country": "DE", 25 | "description": "Falkenstein DC Park 1", 26 | "id": 1, 27 | "latitude": 50.47612, 28 | "longitude": 12.370071, 29 | "name": "fsn1", 30 | "network_zone": "eu-central" 31 | }, 32 | "name": "fsn1-dc8", 33 | "server_types": { 34 | "available": [ 35 | 1, 36 | 2, 37 | 3 38 | ], 39 | "available_for_migration": [ 40 | 1, 41 | 2, 42 | 3 43 | ], 44 | "supported": [ 45 | 1, 46 | 2, 47 | 3 48 | ] 49 | } 50 | }, 51 | "dns_ptr": [ 52 | { 53 | "dns_ptr": "server.example.com", 54 | "ip": "131.232.99.1" 55 | } 56 | ], 57 | "id": 4711, 58 | "ip": "131.232.99.1", 59 | "labels": {}, 60 | "name": "my-resource", 61 | "protection": { 62 | "delete": false 63 | }, 64 | "type": "ipv4" 65 | } 66 | ] 67 | } 68 | -------------------------------------------------------------------------------- /tests/Unit/Models/SSHKeys/fixtures/ssh_key.json: -------------------------------------------------------------------------------- 1 | { 2 | "ssh_key": { 3 | "id": 2323, 4 | "name": "My ssh key", 5 | "fingerprint": "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f", 6 | "public_key": "ssh-rsa AAAjjk76kgf...Xt", 7 | "labels": {}, 8 | "created": "2016-01-30T23:50:00+00:00" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/Unit/Models/SSHKeys/fixtures/ssh_keys.json: -------------------------------------------------------------------------------- 1 | { 2 | "ssh_keys": [ 3 | { 4 | "id": 2323, 5 | "name": "My ssh key", 6 | "fingerprint": "b7:2f:30:a0:2f:6c:58:6c:21:04:58:61:ba:06:3b:2f", 7 | "public_key": "ssh-rsa AAAjjk76kgf...Xt", 8 | "labels": {}, 9 | "created": "2016-01-30T23:50:00+00:00" 10 | } 11 | ], 12 | "meta": { 13 | "pagination": { 14 | "page": 1, 15 | "per_page": 25, 16 | "previous_page": null, 17 | "next_page": null, 18 | "last_page": 1, 19 | "total_entries": 1 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tests/Unit/Models/ServerTypes/ServerTypesTest.php: -------------------------------------------------------------------------------- 1 | server_types = new ServerTypes($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/server_type.json'))); 32 | $server_type = $this->server_types->get(1); 33 | $this->assertEquals($server_type->id, 1); 34 | $this->assertEquals($server_type->name, 'cx11'); 35 | $this->assertLastRequestEquals('GET', '/server_types/1'); 36 | } 37 | 38 | public function testGetByName() 39 | { 40 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/server_types.json'))); 41 | $server_type = $this->server_types->getByName('cx11'); 42 | $this->assertEquals($server_type->id, 1); 43 | $this->assertEquals($server_type->name, 'cx11'); 44 | $this->assertLastRequestEquals('GET', '/server_types'); 45 | $this->assertLastRequestQueryParametersContains('name', 'cx11'); 46 | } 47 | 48 | public function testAll() 49 | { 50 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/server_types.json'))); 51 | $server_types = $this->server_types->all(); 52 | 53 | $this->assertEquals(count($server_types), 1); 54 | $this->assertEquals($server_types[0]->id, 1); 55 | $this->assertEquals($server_types[0]->name, 'cx11'); 56 | $this->assertLastRequestEquals('GET', '/server_types'); 57 | } 58 | 59 | public function testList() 60 | { 61 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/server_types.json'))); 62 | $server_types = $this->server_types->list()->server_types; 63 | 64 | $this->assertEquals(count($server_types), 1); 65 | $this->assertEquals($server_types[0]->id, 1); 66 | $this->assertEquals($server_types[0]->name, 'cx11'); 67 | $this->assertLastRequestEquals('GET', '/server_types'); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /tests/Unit/Models/ServerTypes/fixtures/server_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "server_type": { 3 | "id": 1, 4 | "name": "cx11", 5 | "description": "CX11", 6 | "architecture": "arm", 7 | "cores": 1, 8 | "memory": 1, 9 | "disk": 24, 10 | "deprecated": false, 11 | "prices": [ 12 | { 13 | "location": "fsn1", 14 | "price_hourly": { 15 | "net": "1.0000000000", 16 | "gross": "1.1900000000000000" 17 | }, 18 | "price_monthly": { 19 | "net": "1.0000000000", 20 | "gross": "1.1900000000000000" 21 | } 22 | } 23 | ], 24 | "storage_type": "local", 25 | "cpu_type": "shared" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/Unit/Models/ServerTypes/fixtures/server_types.json: -------------------------------------------------------------------------------- 1 | { 2 | "server_types": [ 3 | { 4 | "id": 1, 5 | "name": "cx11", 6 | "description": "CX11", 7 | "architecture": "arm", 8 | "cores": 1, 9 | "memory": 1, 10 | "disk": 24, 11 | "deprecated": false, 12 | "prices": [ 13 | { 14 | "location": "fsn1", 15 | "price_hourly": { 16 | "net": "1.0000000000", 17 | "gross": "1.1900000000000000" 18 | }, 19 | "price_monthly": { 20 | "net": "1.0000000000", 21 | "gross": "1.1900000000000000" 22 | } 23 | } 24 | ], 25 | "storage_type": "local", 26 | "cpu_type": "shared" 27 | } 28 | ], 29 | "meta": { 30 | "pagination": { 31 | "page": 1, 32 | "per_page": 25, 33 | "previous_page": null, 34 | "next_page": null, 35 | "last_page": 1, 36 | "total_entries": 1 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/ServersTest.php: -------------------------------------------------------------------------------- 1 | servers = new Servers($this->hetznerApi->getHttpClient()); 27 | } 28 | 29 | public function testGet() 30 | { 31 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/server.json'))); 32 | $server = $this->servers->get(42); 33 | $this->assertEquals($server->id, 42); 34 | $this->assertEquals($server->name, 'my-server'); 35 | $this->assertEquals($server->status, 'running'); 36 | $this->assertLastRequestEquals('GET', '/servers/42'); 37 | } 38 | 39 | public function testGetByName() 40 | { 41 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/servers.json'))); 42 | $server = $this->servers->getByName('my-server'); 43 | $this->assertEquals($server->id, 42); 44 | $this->assertEquals($server->name, 'my-server'); 45 | $this->assertEquals($server->status, 'running'); 46 | $this->assertLastRequestEquals('GET', '/servers'); 47 | $this->assertLastRequestQueryParametersContains('name', 'my-server'); 48 | } 49 | 50 | public function testAll() 51 | { 52 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/servers.json'))); 53 | $servers = $this->servers->all(); 54 | 55 | $this->assertEquals(count($servers), 1); 56 | $this->assertEquals($servers[0]->id, 42); 57 | $this->assertEquals($servers[0]->name, 'my-server'); 58 | $this->assertLastRequestEquals('GET', '/servers'); 59 | } 60 | 61 | public function testList() 62 | { 63 | $this->mockHandler->append(new Response(200, [], file_get_contents(__DIR__.'/fixtures/servers.json'))); 64 | $servers = $this->servers->list()->servers; 65 | 66 | $this->assertEquals(count($servers), 1); 67 | $this->assertEquals($servers[0]->id, 42); 68 | $this->assertEquals($servers[0]->name, 'my-server'); 69 | $this->assertLastRequestEquals('GET', '/servers'); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_create_image.json: -------------------------------------------------------------------------------- 1 | { 2 | "image": { 3 | "id": 4711, 4 | "type": "snapshot", 5 | "architecture": "arm", 6 | "status": "creating", 7 | "name": null, 8 | "description": "my image", 9 | "image_size": 2.3, 10 | "disk_size": 10, 11 | "created": "2016-01-30T23:50:00+00:00", 12 | "created_from": { 13 | "id": 1, 14 | "name": "Server" 15 | }, 16 | "bound_to": null, 17 | "os_flavor": "ubuntu", 18 | "os_version": "20.04", 19 | "rapid_deploy": false, 20 | "protection": { 21 | "delete": false 22 | }, 23 | "deprecated": "2018-02-28T00:00:00+00:00", 24 | "labels": {} 25 | }, 26 | "action": { 27 | "id": 13, 28 | "command": "create_image", 29 | "status": "success", 30 | "progress": 100, 31 | "started": "2016-01-30T23:55:00+00:00", 32 | "finished": "2016-01-30T23:56:00+00:00", 33 | "resources": [ 34 | { 35 | "id": 42, 36 | "type": "server" 37 | } 38 | ], 39 | "error": null 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_enable_rescue.json: -------------------------------------------------------------------------------- 1 | { 2 | "root_password": "zCWbFhnu950dUTko5f40", 3 | "action": { 4 | "id": 13, 5 | "command": "enable_rescue", 6 | "status": "success", 7 | "progress": 100, 8 | "started": "2016-01-30T23:55:00+00:00", 9 | "finished": "2016-01-30T23:56:00+00:00", 10 | "resources": [ 11 | { 12 | "id": 42, 13 | "type": "server" 14 | } 15 | ], 16 | "error": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_generic.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "$command", 5 | "status": "running", 6 | "progress": 0, 7 | "started": "2016-01-30T23:50:00+00:00", 8 | "finished": null, 9 | "resources": [ 10 | { 11 | "id": 42, 12 | "type": "server" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_metrics.json: -------------------------------------------------------------------------------- 1 | { 2 | "metrics": { 3 | "start": "2017-01-01T00:00:00+00:00", 4 | "end": "2017-01-01T23:00:00+00:00", 5 | "step": 60, 6 | "time_series": { 7 | "name_of_timeseries": { 8 | "values": [ 9 | [ 10 | 1435781470.622, 11 | "42" 12 | ] 13 | ] 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_request_console.json: -------------------------------------------------------------------------------- 1 | { 2 | "wss_url": "wss://console.hetzner.cloud/?server_id=1&token=3db32d15-af2f-459c-8bf8-dee1fd05f49c", 3 | "password": "9MQaTg2VAGI0FIpc10k3UpRXcHj2wQ6x", 4 | "action": { 5 | "id": 13, 6 | "command": "request_console", 7 | "status": "success", 8 | "progress": 100, 9 | "started": "2016-01-30T23:55:00+00:00", 10 | "finished": "2016-01-30T23:56:00+00:00", 11 | "resources": [ 12 | { 13 | "id": 42, 14 | "type": "server" 15 | } 16 | ], 17 | "error": null 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/Unit/Models/Servers/fixtures/server_action_reset_password.json: -------------------------------------------------------------------------------- 1 | { 2 | "root_password": "zCWbFhnu950dUTko5f40", 3 | "action": { 4 | "id": 13, 5 | "command": "reset_password", 6 | "status": "running", 7 | "progress": 0, 8 | "started": "2016-01-30T23:50:00+00:00", 9 | "finished": null, 10 | "resources": [ 11 | { 12 | "id": 42, 13 | "type": "server" 14 | } 15 | ], 16 | "error": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume.json: -------------------------------------------------------------------------------- 1 | { 2 | "volume": { 3 | "id": 4711, 4 | "created": "2016-01-30T23:50:11+00:00", 5 | "name": "database-storage", 6 | "server": 12, 7 | "location": { 8 | "id": 1, 9 | "name": "fsn1", 10 | "description": "Falkenstein DC Park 1", 11 | "country": "DE", 12 | "city": "Falkenstein", 13 | "latitude": 50.47612, 14 | "longitude": 12.370071, 15 | "network_zone": "eu-central" 16 | }, 17 | "size": 42, 18 | "linux_device": "/dev/disk/by-id/scsi-0HC_Volume_4711", 19 | "protection": { 20 | "delete": false 21 | }, 22 | "labels": {}, 23 | "status": "available", 24 | "format": "xfs" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume_action_attach.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "attach_volume", 5 | "status": "running", 6 | "progress": 0, 7 | "started": "2016-01-30T23:50:00+00:00", 8 | "finished": null, 9 | "resources": [ 10 | { 11 | "id": 43, 12 | "type": "server" 13 | }, 14 | { 15 | "id": 554, 16 | "type": "volume" 17 | } 18 | ], 19 | "error": null 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume_action_change_protection.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "change_protection", 5 | "status": "success", 6 | "progress": 100, 7 | "started": "2016-01-30T23:55:00+00:00", 8 | "finished": "2016-01-30T23:56:00+00:00", 9 | "resources": [ 10 | { 11 | "id": 4711, 12 | "type": "volume" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume_action_detach.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "detach_volume", 5 | "status": "running", 6 | "progress": 0, 7 | "started": "2016-01-30T23:50:00+00:00", 8 | "finished": null, 9 | "resources": [ 10 | { 11 | "id": 554, 12 | "type": "volume" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume_action_resize.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": { 3 | "id": 13, 4 | "command": "resize_volume", 5 | "status": "running", 6 | "progress": 0, 7 | "started": "2016-01-30T23:50:00+00:00", 8 | "finished": null, 9 | "resources": [ 10 | { 11 | "id": 42, 12 | "type": "server" 13 | } 14 | ], 15 | "error": null 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volume_create.json: -------------------------------------------------------------------------------- 1 | { 2 | "volume": { 3 | "id": 4711, 4 | "created": "2016-01-30T23:50:11+00:00", 5 | "name": "database-storage", 6 | "server": 12, 7 | "location": { 8 | "id": 1, 9 | "name": "fsn1", 10 | "description": "Falkenstein DC Park 1", 11 | "country": "DE", 12 | "city": "Falkenstein", 13 | "latitude": 50.47612, 14 | "longitude": 12.370071, 15 | "network_zone": "eu-central" 16 | }, 17 | "size": 42, 18 | "linux_device": "/dev/disk/by-id/scsi-0HC_Volume_4711", 19 | "protection": { 20 | "delete": false 21 | }, 22 | "labels": {}, 23 | "status": "available", 24 | "format": "xfs" 25 | }, 26 | "action": { 27 | "id": 13, 28 | "command": "create_volume", 29 | "status": "running", 30 | "progress": 0, 31 | "started": "2016-01-30T23:50:00+00:00", 32 | "finished": null, 33 | "resources": [ 34 | { 35 | "id": 42, 36 | "type": "server" 37 | }, 38 | { 39 | "id": 554, 40 | "type": "volume" 41 | } 42 | ], 43 | "error": null 44 | }, 45 | "next_actions": [ 46 | { 47 | "id": 13, 48 | "command": "attach_volume", 49 | "status": "running", 50 | "progress": 0, 51 | "started": "2016-01-30T23:50:00+00:00", 52 | "finished": null, 53 | "resources": [ 54 | { 55 | "id": 42, 56 | "type": "server" 57 | }, 58 | { 59 | "id": 554, 60 | "type": "volume" 61 | } 62 | ], 63 | "error": null 64 | } 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /tests/Unit/Models/Volumes/fixtures/volumes.json: -------------------------------------------------------------------------------- 1 | { 2 | "volumes": [ 3 | { 4 | "id": 4711, 5 | "created": "2016-01-30T23:50:11+00:00", 6 | "name": "database-storage", 7 | "server": 12, 8 | "location": { 9 | "id": 1, 10 | "name": "fsn1", 11 | "description": "Falkenstein DC Park 1", 12 | "country": "DE", 13 | "city": "Falkenstein", 14 | "latitude": 50.47612, 15 | "longitude": 12.370071, 16 | "network_zone": "eu-central" 17 | }, 18 | "size": 42, 19 | "linux_device": "/dev/disk/by-id/scsi-0HC_Volume_4711", 20 | "protection": { 21 | "delete": false 22 | }, 23 | "labels": {}, 24 | "status": "available", 25 | "format": "xfs" 26 | } 27 | ], 28 | "meta": { 29 | "pagination": { 30 | "page": 1, 31 | "per_page": 25, 32 | "previous_page": null, 33 | "next_page": null, 34 | "last_page": 1, 35 | "total_entries": 1 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/Unit/RequestOptsTest.php: -------------------------------------------------------------------------------- 1 | assertEquals($expectedResult, $r->buildQuery()); 43 | } 44 | 45 | /** 46 | * @test 47 | */ 48 | public function createRequestOptsWithGreaterPerPageThanLimitShouldThrowAnError() 49 | { 50 | $this->expectException(\InvalidArgumentException::class); 51 | new RequestOpts(100); 52 | } 53 | } 54 | --------------------------------------------------------------------------------