mirror of
https://github.com/psviderski/uncloud.git
synced 2026-10-07 05:39:01 +00:00
128 lines
4.4 KiB
Go
128 lines
4.4 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/netip"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/psviderski/uncloud/api/pb"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestValidateMachineName(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
wantErr string
|
|
}{
|
|
{name: "single letter", input: "a"},
|
|
{name: "single digit", input: "1"},
|
|
{name: "two characters", input: "a1"},
|
|
{name: "generated name", input: "machine-ab12"},
|
|
{name: "hyphens and digits", input: "1-worker-2"},
|
|
{name: "maximum length", input: strings.Repeat("a", 63)},
|
|
{name: "maximum length with hyphens", input: "a" + strings.Repeat("-", 61) + "1"},
|
|
{name: "machine namespace label", input: "m"},
|
|
{name: "mode prefix", input: "nearest-worker"},
|
|
{name: "short hexadecimal name", input: strings.Repeat("a", 31)},
|
|
{name: "long hexadecimal name", input: strings.Repeat("a", 33)},
|
|
{name: "non-hexadecimal 32 characters", input: strings.Repeat("g", 32)},
|
|
{name: "empty", wantErr: "must be 1-63 characters"},
|
|
{name: "too long", input: strings.Repeat("a", 64), wantErr: "must be 1-63 characters"},
|
|
{name: "uppercase", input: "VPS1", wantErr: "lowercase letters"},
|
|
{name: "leading hyphen", input: "-worker", wantErr: "starting and ending"},
|
|
{name: "trailing hyphen", input: "worker-", wantErr: "starting and ending"},
|
|
{name: "underscore", input: "worker_1", wantErr: "hyphens only"},
|
|
{name: "dot", input: "worker.example", wantErr: "hyphens only"},
|
|
{name: "space", input: "worker 1", wantErr: "hyphens only"},
|
|
{name: "leading whitespace", input: " worker", wantErr: "hyphens only"},
|
|
{name: "trailing whitespace", input: "worker\t", wantErr: "hyphens only"},
|
|
{name: "non-ASCII", input: "wörker", wantErr: "lowercase letters"},
|
|
{name: "round-robin mode", input: "rr", wantErr: "reserved for internal DNS query modes"},
|
|
{name: "nearest mode", input: "nearest", wantErr: "reserved for internal DNS query modes"},
|
|
{name: "machine ID", input: "c337f00600de51ef4375c9a9a267dba5", wantErr: "machine ID format"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
err := ValidateMachineName(tt.input)
|
|
if tt.wantErr == "" {
|
|
require.NoError(t, err)
|
|
} else {
|
|
require.ErrorContains(t, err, tt.wantErr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMachineMembersList_Info(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
publicKey := []byte{0x01, 0x02, 0x03, 0x04}
|
|
members := MachineMembersList{
|
|
{
|
|
Machine: &pb.MachineInfo{
|
|
Id: "abc123",
|
|
Name: "vm-1",
|
|
Hostname: "vm-1.example.com",
|
|
Arch: "amd64",
|
|
OsPrettyName: "Ubuntu 24.04.4 LTS",
|
|
KernelVersion: "6.8.0-31-generic",
|
|
DockerVersion: "27.1.1",
|
|
DaemonVersion: "0.9.0",
|
|
PublicIp: pb.NewIP(netip.MustParseAddr("203.0.113.5")),
|
|
Network: &pb.NetworkConfig{
|
|
Subnet: pb.NewIPPrefix(netip.MustParsePrefix("10.210.0.0/24")),
|
|
ManagementIp: pb.NewIP(netip.MustParseAddr("10.210.0.1")),
|
|
Endpoints: []*pb.IPPort{
|
|
pb.NewIPPort(netip.MustParseAddrPort("203.0.113.5:51820")),
|
|
},
|
|
PublicKey: publicKey,
|
|
},
|
|
},
|
|
State: pb.MachineMember_UP,
|
|
},
|
|
}
|
|
|
|
infos := members.ToNative()
|
|
require.Len(t, infos, 1)
|
|
|
|
assert.Equal(t, MachineMember{
|
|
ID: "abc123",
|
|
Name: "vm-1",
|
|
State: "Up",
|
|
Hostname: "vm-1.example.com",
|
|
Arch: "amd64",
|
|
OSPrettyName: "Ubuntu 24.04.4 LTS",
|
|
KernelVersion: "6.8.0-31-generic",
|
|
DockerVersion: "27.1.1",
|
|
DaemonVersion: "0.9.0",
|
|
PublicIP: netip.MustParseAddr("203.0.113.5"),
|
|
Network: MachineNetwork{
|
|
Subnet: netip.MustParsePrefix("10.210.0.0/24"),
|
|
ManagementIP: netip.MustParseAddr("10.210.0.1"),
|
|
Endpoints: []netip.AddrPort{netip.MustParseAddrPort("203.0.113.5:51820")},
|
|
PublicKey: publicKey,
|
|
},
|
|
}, infos[0])
|
|
|
|
// The JSON output must use PascalCase keys to stay consistent with `docker inspect` and the
|
|
// rest of Uncloud's JSON output.
|
|
data, err := json.Marshal(infos)
|
|
require.NoError(t, err)
|
|
out := string(data)
|
|
for _, key := range []string{
|
|
`"ID"`, `"Name"`, `"State"`, `"Hostname"`, `"Arch"`, `"OSPrettyName"`, `"KernelVersion"`,
|
|
`"DockerVersion"`, `"DaemonVersion"`, `"PublicIP"`, `"Network"`,
|
|
`"Subnet"`, `"ManagementIP"`, `"Endpoints"`, `"PublicKey"`,
|
|
} {
|
|
assert.Contains(t, out, key)
|
|
}
|
|
assert.Contains(t, out, `"PublicIP":"203.0.113.5"`)
|
|
assert.Contains(t, out, `"Subnet":"10.210.0.0/24"`)
|
|
assert.Contains(t, out, `"Endpoints":["203.0.113.5:51820"]`)
|
|
assert.Contains(t, out, `"PublicKey":"AQIDBA=="`)
|
|
}
|