Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/java/cloud/dnation/hetznerclient/HetznerApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,26 @@ Call<GetServersBySelectorResponse> getServersBySelector(@Query("label_selector")
@GET("/v1/networks/{id}")
Call<GetNetworkByIdResponse> getNetworkById(@Path("id") long id);

/**
* Get all firewalls matching given label selector.
*
* @param selector label selector used to match firewalls
* @return list of firewalls
* see <a href="https://docs.hetzner.cloud/reference/cloud#firewalls-list-firewalls">API reference</a>
*/
@GET("/v1/firewalls")
Call<GetFirewallsBySelectorResponse> getFirewallsBySelector(@Query("label_selector") String selector);

/**
* Get single firewall by ID.
*
* @param id firewall ID
* @return firewall detail
* see <a href="https://docs.hetzner.cloud/reference/cloud#firewalls-get-a-firewall">API reference</a>
*/
@GET("/v1/firewalls/{id}")
Call<GetFirewallByIdResponse> getFirewallById(@Path("id") long id);

/**
* Get placement groups, optionally filtered using label expression.
*
Expand Down
78 changes: 77 additions & 1 deletion src/main/resources/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ components:
$ref: "#/components/schemas/NetworkDetail"
type: object

GetFirewallsBySelectorResponse:
allOf:
- $ref: "#/components/schemas/AbstractSearchResponse"
properties:
firewalls:
type: array
items:
$ref: "#/components/schemas/FirewallDetail"
type: object

GetServersBySelectorResponse:
allOf:
- $ref: "#/components/schemas/AbstractSearchResponse"
Expand Down Expand Up @@ -205,6 +215,12 @@ components:
$ref: "#/components/schemas/NetworkDetail"
type: object

GetFirewallByIdResponse:
properties:
firewall:
$ref: "#/components/schemas/FirewallDetail"
type: object

GetPlacementGroupByIdResponse:
properties:
placement_group:
Expand Down Expand Up @@ -236,7 +252,10 @@ components:
ssh_key:
$ref: "#/components/schemas/SshKeyDetail"
type: object

CreateServerFirewallsRequest:
properties:
firewall:
$ref: "#/components/schemas/Identifier"
CreateServerRequest:
properties:
automount:
Expand All @@ -247,6 +266,11 @@ components:
not be used together with location)
example: nbg1-dc3
type: string
firewalls:
description: Firewalls which should be applied on the Server's public network interface at creation time.
type: array
items:
$ref: "#/components/schemas/CreateServerFirewallsRequest"
image:
description: ID or name of the Image the Server is created from
example: ubuntu-20.04
Expand Down Expand Up @@ -685,6 +709,58 @@ components:
example: false
type: boolean
type: object
FirewallRule:
properties:
description:
description: Description of the rule.
type: string
direction:
description: Traffic direction in which the rule should be applied to.
type: string
protocol:
description: Network protocol to apply the rule for.
type: string
port:
description: Port or port range to apply the rule for.
type: string
destination_ips:
description: List of permitted IPv4/IPv6 addresses for outgoing traffic.
type: array
items:
type: string
source_ips:
description: List of permitted IPv4/IPv6 addresses for incoming traffic.
type: array
items:
type: string
FirewallAppliedToDetail:
properties:
type:
type: string
FirewallDetail:
allOf:
- $ref: "#/components/schemas/IdentifiableResource"
properties:
created:
description: Point in time when the Resource was created (in
ISO-8601 format)
example: '2016-01-30T23:55:00+00:00'
type: string
name:
type: string
description: Name of the Firewall. Must be unique per Project.
rules:
type: array
items:
$ref: "#/components/schemas/FirewallRule"
applied_to:
type: array
items:
$ref: "#/components/schemas/FirewallAppliedToDetail"
labels:
description: User-defined labels (key-value pairs)
$ref: "#/components/schemas/Labeled"

VolumeDetail:
allOf:
- $ref: "#/components/schemas/IdentifiableResource"
Expand Down
34 changes: 34 additions & 0 deletions src/test/java/cloud/dnation/hetznerclient/BasicTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,38 @@ public void testGetPrimaryIpsBySelector() throws IOException {
assertEquals("1.2.3.4", result.getPrimaryIps().get(0).getIp());
assertNull(result.getPrimaryIps().get(0).getAssigneeId());
}

@Test
public void testGetFirewallBySelector() throws IOException {
ws.enqueue(new MockResponse().setBody(resourceAsString("get-firewalls-by-selector.json")));
final Call<GetFirewallsBySelectorResponse> call = api.getFirewallsBySelector("any");
final GetFirewallsBySelectorResponse result = call.execute().body();
assertEquals(3029857349L, (long) result.getFirewalls().get(0).getId());
assertEquals("::/0", result.getFirewalls().get(0).getRules().get(1).getSourceIps().get(1));
assertEquals("in", result.getFirewalls().get(0).getRules().get(1).getDirection());
assertEquals("22", result.getFirewalls().get(0).getRules().get(0).getPort());
}

@Test
public void testGetFirewallById() throws IOException {
ws.enqueue(new MockResponse().setBody(resourceAsString("get-firewall-by-id.json")));
final Call<GetFirewallByIdResponse> call = api.getFirewallById(345676L);
final GetFirewallByIdResponse result = call.execute().body();
assertEquals(345676, (long) result.getFirewall().getId());
assertEquals("::/0", result.getFirewall().getRules().get(1).getSourceIps().get(1));
assertEquals("in", result.getFirewall().getRules().get(1).getDirection());
assertEquals("22", result.getFirewall().getRules().get(0).getPort());
}


@Test
public void testGetFirewallByIdInvalid() throws IOException {
ws.enqueue(new MockResponse()
.setBody(resourceAsString("get-firewall-by-id-invalid.json"))
.setResponseCode(404)
);
Call<GetNetworkByIdResponse> call = api.getNetworkById(11);
Response<GetNetworkByIdResponse> response = call.execute();
assertEquals(404, response.code());
}
}
7 changes: 7 additions & 0 deletions src/test/resources/get-firewall-by-id-invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"error": {
"message": "firewall with ID XYZ not found",
"code": "not_found",
"details": null
}
}
86 changes: 86 additions & 0 deletions src/test/resources/get-firewall-by-id.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"firewall": {
"id": 345676,
"name": "firewall-worker",
"labels": {},
"created": "2022-11-23T12:36:58+00:00",
"rules": [
{
"direction": "in",
"protocol": "tcp",
"port": "22",
"source_ips": [
"0.0.0.0/0",
"::/0"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "icmp",
"port": null,
"source_ips": [
"0.0.0.0/0",
"::/0"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "tcp",
"port": "80",
"source_ips": [
"0.0.0.0/0",
"::/0"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "tcp",
"port": "9090",
"source_ips": [
"0.0.0.0/0",
"::/0"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "tcp",
"port": "443",
"source_ips": [
"0.0.0.0/0",
"::/0"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "tcp",
"port": "any",
"source_ips": [
"10.1.0.0/16"
],
"destination_ips": [],
"description": null
},
{
"direction": "in",
"protocol": "udp",
"port": "any",
"source_ips": [
"10.1.0.0/16"
],
"destination_ips": [],
"description": null
}
],
"applied_to": []
}
}
Loading