Skip to content

Commit 7336392

Browse files
tas50claude
andcommitted
🐛 Fix Hetzner Cloud missing public IPv4 in cloud.instance
The Hetzner metadata service returns public-ipv4 but the cloud instance resource was not extracting it, leaving publicIpv4 always empty. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a1650e6 commit 7336392

File tree

8 files changed

+152
-1
lines changed

8 files changed

+152
-1
lines changed

providers/os/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
var Config = plugin.Provider{
1414
Name: "os",
1515
ID: "go.mondoo.com/cnquery/v9/providers/os",
16-
Version: "13.6.0",
16+
Version: "13.6.1",
1717
ConnectionTypes: []string{
1818
shared.Type_Local.String(),
1919
shared.Type_SSH.String(),

providers/os/id/hetzner/testdata/instance_linux.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,23 @@ hostname: ubuntu-8gb-hil-1
3636
region: us-west
3737
availability-zone: hil-dc1
3838
local-ipv4: ""
39+
public-ipv4: 5.78.107.208
40+
public-keys:
41+
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwjdTGb2Brk8c99PdqDHgOIjmHBQfE4tT9MGXTsfkss
42+
network-config:
43+
config:
44+
- mac_address: "92:00:06:96:49:21"
45+
name: eth0
46+
subnets:
47+
- ipv4: true
48+
type: dhcp
49+
- address: "2a01:4ff:1f0:4c7b::1/64"
50+
dns_nameservers:
51+
- "2a01:4ff:ff00::add:2"
52+
- "2a01:4ff:ff00::add:1"
53+
gateway: "fe80::1"
54+
ipv6: true
55+
type: static
56+
type: physical
57+
version: 1
3958
"""

providers/os/id/hetznercloud/hetznercloud.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type hetznerMetadata struct {
5050
Region string `yaml:"region"`
5151
AvailabilityZone string `yaml:"availability-zone"`
5252
LocalIPv4 string `yaml:"local-ipv4"`
53+
PublicIPv4 string `yaml:"public-ipv4"`
5354
}
5455

5556
type commandInstanceMetadata struct {

providers/os/id/hetznercloud/hetznercloud_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ func TestRawMetadataLinux(t *testing.T) {
5050
assert.Equal(t, "ubuntu-8gb-hil-1", m["hostname"])
5151
assert.Equal(t, "us-west", m["region"])
5252
assert.Equal(t, "hil-dc1", m["availability-zone"])
53+
assert.Equal(t, "5.78.107.208", m["public-ipv4"])
5354
}

providers/os/id/hetznercloud/testdata/metadata_linux.toml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,23 @@ hostname: ubuntu-8gb-hil-1
1616
region: us-west
1717
availability-zone: hil-dc1
1818
local-ipv4: ""
19+
public-ipv4: 5.78.107.208
20+
public-keys:
21+
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwjdTGb2Brk8c99PdqDHgOIjmHBQfE4tT9MGXTsfkss
22+
network-config:
23+
config:
24+
- mac_address: "92:00:06:96:49:21"
25+
name: eth0
26+
subnets:
27+
- ipv4: true
28+
type: dhcp
29+
- address: "2a01:4ff:1f0:4c7b::1/64"
30+
dns_nameservers:
31+
- "2a01:4ff:ff00::add:2"
32+
- "2a01:4ff:ff00::add:1"
33+
gateway: "fe80::1"
34+
ipv6: true
35+
type: static
36+
type: physical
37+
version: 1
1938
"""

providers/os/resources/cloud/hetzner.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ type hetznerCloud struct {
1818
conn shared.Connection
1919
}
2020

21+
// NewHetznerCloud creates a new Hetzner cloud instance.
22+
func NewHetznerCloud(conn shared.Connection) (OSCloud, error) {
23+
return &hetznerCloud{conn: conn}, nil
24+
}
25+
2126
func (h *hetznerCloud) Provider() Provider {
2227
return HETZNER
2328
}
@@ -57,5 +62,11 @@ func (h *hetznerCloud) Instance() (*InstanceMetadata, error) {
5762
}
5863
}
5964

65+
if value, ok := m["public-ipv4"]; ok {
66+
if publicIP, ok := value.(string); ok && publicIP != "" {
67+
instanceMd.PublicIpv4 = []Ipv4Address{{IP: publicIP}}
68+
}
69+
}
70+
6071
return &instanceMd, nil
6172
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright Mondoo, Inc. 2024, 2026
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
package cloud_test
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
"go.mondoo.com/mql/v13/providers-sdk/v1/inventory"
12+
"go.mondoo.com/mql/v13/providers/os/connection/mock"
13+
"go.mondoo.com/mql/v13/providers/os/detector"
14+
"go.mondoo.com/mql/v13/providers/os/resources/cloud"
15+
)
16+
17+
func newHetznerCloud(t *testing.T, path string) cloud.OSCloud {
18+
t.Helper()
19+
conn, err := mock.New(0, &inventory.Asset{}, mock.WithPath(path))
20+
require.NoError(t, err)
21+
22+
platform, ok := detector.DetectOS(conn)
23+
require.True(t, ok)
24+
conn.Asset().Platform = platform
25+
26+
hc, err := cloud.NewHetznerCloud(conn)
27+
require.NoError(t, err)
28+
return hc
29+
}
30+
31+
func TestHetznerInstance(t *testing.T) {
32+
hc := newHetznerCloud(t, "../../id/hetznercloud/testdata/metadata_linux.toml")
33+
34+
md, err := hc.Instance()
35+
require.NoError(t, err)
36+
37+
assert.Equal(t, "ubuntu-8gb-hil-1", md.PrivateHostname)
38+
assert.Equal(t, "5.78.107.208", md.PublicIP())
39+
40+
require.Len(t, md.PublicIpv4, 1)
41+
assert.Equal(t, "5.78.107.208", md.PublicIpv4[0].IP)
42+
43+
// local-ipv4 is empty in test data, so PrivateIpv4 should be empty
44+
assert.Empty(t, md.PrivateIpv4)
45+
}
46+
47+
func TestHetznerInstanceWithLocalIP(t *testing.T) {
48+
hc := newHetznerCloud(t, "./testdata/hetzner_with_local_ip.toml")
49+
50+
md, err := hc.Instance()
51+
require.NoError(t, err)
52+
53+
assert.Equal(t, "ubuntu-8gb-hil-1", md.PrivateHostname)
54+
assert.Equal(t, "5.78.107.208", md.PublicIP())
55+
assert.Equal(t, "10.0.0.5", md.PrivateIP())
56+
57+
require.Len(t, md.PublicIpv4, 1)
58+
assert.Equal(t, "5.78.107.208", md.PublicIpv4[0].IP)
59+
60+
require.Len(t, md.PrivateIpv4, 1)
61+
assert.Equal(t, "10.0.0.5", md.PrivateIpv4[0].IP)
62+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[commands."uname -s"]
2+
stdout = "Linux"
3+
4+
[commands."uname -m"]
5+
stdout = "x86_64"
6+
7+
[commands."uname -r"]
8+
stdout = "5.15.0-91-generic"
9+
10+
[commands.d4923e3c7f9c8dec0409fddee98da395085699bbb2cc9cfc8c3527e02f746c41]
11+
command = "curl --retry 3 --retry-delay 1 --connect-timeout 1 --retry-max-time 5 --max-time 10 --noproxy '*' http://169.254.169.254/hetzner/v1/metadata"
12+
exit_status = 0
13+
stdout = """
14+
instance-id: 110512417
15+
hostname: ubuntu-8gb-hil-1
16+
region: us-west
17+
availability-zone: hil-dc1
18+
local-ipv4: 10.0.0.5
19+
public-ipv4: 5.78.107.208
20+
public-keys:
21+
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwjdTGb2Brk8c99PdqDHgOIjmHBQfE4tT9MGXTsfkss
22+
network-config:
23+
config:
24+
- mac_address: "92:00:06:96:49:21"
25+
name: eth0
26+
subnets:
27+
- ipv4: true
28+
type: dhcp
29+
- address: "2a01:4ff:1f0:4c7b::1/64"
30+
dns_nameservers:
31+
- "2a01:4ff:ff00::add:2"
32+
- "2a01:4ff:ff00::add:1"
33+
gateway: "fe80::1"
34+
ipv6: true
35+
type: static
36+
type: physical
37+
version: 1
38+
"""

0 commit comments

Comments
 (0)