feat(LXC): add networks; closes #2
This commit is contained in:
50
lxc.go
50
lxc.go
@@ -13,6 +13,8 @@ import (
|
|||||||
"github.com/platform-engineering-labs/formae/pkg/plugin/resource"
|
"github.com/platform-engineering-labs/formae/pkg/plugin/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const MAX_NETWORK_COUNT = 10
|
||||||
|
|
||||||
func parseLXCProperties(data json.RawMessage) (*LXCProperties, error) {
|
func parseLXCProperties(data json.RawMessage) (*LXCProperties, error) {
|
||||||
var props LXCProperties
|
var props LXCProperties
|
||||||
if err := json.Unmarshal(data, &props); err != nil {
|
if err := json.Unmarshal(data, &props); err != nil {
|
||||||
@@ -83,6 +85,10 @@ func (p *Plugin) CreateLXC(ctx context.Context, req *resource.CreateRequest) (*r
|
|||||||
urlparams.Add("onboot", strconv.Itoa(props.OnBoot))
|
urlparams.Add("onboot", strconv.Itoa(props.OnBoot))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i := range min(MAX_NETWORK_COUNT, len(props.Networks)) {
|
||||||
|
urlparams.Add(fmt.Sprintf("net%d", i), props.Networks[i])
|
||||||
|
}
|
||||||
|
|
||||||
data, err := authenticatedRequest(http.MethodPost, config.URL+"/api2/json/nodes/"+config.NODE+"/lxc", createAuthorizationString(username, token), urlparams)
|
data, err := authenticatedRequest(http.MethodPost, config.URL+"/api2/json/nodes/"+config.NODE+"/lxc", createAuthorizationString(username, token), urlparams)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -158,6 +164,39 @@ func (p *Plugin) ReadLXC(ctx context.Context, req *resource.ReadRequest) (*resou
|
|||||||
|
|
||||||
lxcdata := props.Data
|
lxcdata := props.Data
|
||||||
|
|
||||||
|
networks := []string{}
|
||||||
|
|
||||||
|
if len(lxcdata.Net0) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net0)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net1) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net1)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net2) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net2)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net3) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net3)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net4) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net4)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net5) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net5)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net6) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net6)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net7) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net7)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net8) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net8)
|
||||||
|
}
|
||||||
|
if len(lxcdata.Net9) > 0 {
|
||||||
|
networks = append(networks, lxcdata.Net9)
|
||||||
|
}
|
||||||
|
|
||||||
properties := LXCProperties{
|
properties := LXCProperties{
|
||||||
VMID: req.NativeID,
|
VMID: req.NativeID,
|
||||||
Hostname: lxcdata.Hostname,
|
Hostname: lxcdata.Hostname,
|
||||||
@@ -165,6 +204,7 @@ func (p *Plugin) ReadLXC(ctx context.Context, req *resource.ReadRequest) (*resou
|
|||||||
Cores: lxcdata.Cores,
|
Cores: lxcdata.Cores,
|
||||||
Memory: lxcdata.Memory,
|
Memory: lxcdata.Memory,
|
||||||
OnBoot: lxcdata.OnBoot,
|
OnBoot: lxcdata.OnBoot,
|
||||||
|
Networks: networks,
|
||||||
}
|
}
|
||||||
|
|
||||||
propsJSON, err := json.Marshal(properties)
|
propsJSON, err := json.Marshal(properties)
|
||||||
@@ -264,6 +304,16 @@ func (p *Plugin) UpdateLXC(ctx context.Context, req *resource.UpdateRequest) (*r
|
|||||||
urlparams.Add("onboot", strconv.Itoa(desir.OnBoot))
|
urlparams.Add("onboot", strconv.Itoa(desir.OnBoot))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toDelete := []string{}
|
||||||
|
for i := range min(MAX_NETWORK_COUNT, len(desir.Networks)) {
|
||||||
|
if i < len(desir.Networks) {
|
||||||
|
urlparams.Add(fmt.Sprintf("net%d", i), desir.Networks[i])
|
||||||
|
} else {
|
||||||
|
toDelete = append(toDelete, fmt.Sprintf("net%d", i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
urlparams.Add("delete", strings.Join(toDelete, ","))
|
||||||
|
|
||||||
_, err = authenticatedRequest("PUT", config.URL+"/api2/json/nodes/"+config.NODE+"/lxc/"+desir.VMID+"/config", createAuthorizationString(username, token), urlparams)
|
_, err = authenticatedRequest("PUT", config.URL+"/api2/json/nodes/"+config.NODE+"/lxc/"+desir.VMID+"/config", createAuthorizationString(username, token), urlparams)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ func TestCreate(t *testing.T) {
|
|||||||
"password": "password",
|
"password": "password",
|
||||||
"cores": 1,
|
"cores": 1,
|
||||||
"memory": 512,
|
"memory": 512,
|
||||||
|
"networks": []string{"name=test,hwaddr=BC:24:11:FD:90:BF,bridge=internal,firewall=1"},
|
||||||
}
|
}
|
||||||
|
|
||||||
propertiesJSON, err := json.Marshal(properties)
|
propertiesJSON, err := json.Marshal(properties)
|
||||||
@@ -103,6 +104,7 @@ func TestRead(t *testing.T) {
|
|||||||
require.Equal(t, mem_num, props["memory"], "memory should match")
|
require.Equal(t, mem_num, props["memory"], "memory should match")
|
||||||
const onboot float64 = 0
|
const onboot float64 = 0
|
||||||
require.Equal(t, onboot, props["onboot"], "memory should match")
|
require.Equal(t, onboot, props["onboot"], "memory should match")
|
||||||
|
require.NotEqual(t, nil, props["networks"], "network should be defined")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUpdate(t *testing.T) {
|
func TestUpdate(t *testing.T) {
|
||||||
@@ -116,6 +118,7 @@ func TestUpdate(t *testing.T) {
|
|||||||
"ostemplate": "local:vztmpl/alpine-3.22-default_20250617_amd64.tar.xz",
|
"ostemplate": "local:vztmpl/alpine-3.22-default_20250617_amd64.tar.xz",
|
||||||
"cores": 1,
|
"cores": 1,
|
||||||
"memory": 512,
|
"memory": 512,
|
||||||
|
"networks": []string{"name=test,hwaddr=BC:24:11:FD:90:BF,bridge=internal,firewall=1"},
|
||||||
})
|
})
|
||||||
|
|
||||||
desiredProperties, _ := json.Marshal(map[string]any{
|
desiredProperties, _ := json.Marshal(map[string]any{
|
||||||
@@ -126,6 +129,7 @@ func TestUpdate(t *testing.T) {
|
|||||||
"cores": 2,
|
"cores": 2,
|
||||||
"memory": 1024,
|
"memory": 1024,
|
||||||
"onboot": 1,
|
"onboot": 1,
|
||||||
|
"networks": []string{"name=test1,hwaddr=BC:24:11:FD:90:BF,bridge=internal,firewall=1"},
|
||||||
})
|
})
|
||||||
|
|
||||||
req := &resource.UpdateRequest{
|
req := &resource.UpdateRequest{
|
||||||
|
|||||||
@@ -49,4 +49,7 @@ class LXC extends formae.Resource {
|
|||||||
@formae.FieldHint {}
|
@formae.FieldHint {}
|
||||||
sshkeys: Listing<String>?
|
sshkeys: Listing<String>?
|
||||||
|
|
||||||
|
@formae.FieldHint {}
|
||||||
|
networks: Listing<String>?
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
3
testdata/resource-update.pkl
vendored
3
testdata/resource-update.pkl
vendored
@@ -34,5 +34,8 @@ forma {
|
|||||||
cores = 2
|
cores = 2
|
||||||
memory = 1024
|
memory = 1024
|
||||||
onboot = 1
|
onboot = 1
|
||||||
|
networks = new Listing<String> {
|
||||||
|
"name=first,hwaddr=BC:24:11:FD:90:BF,bridge=internal"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
testdata/resource.pkl
vendored
4
testdata/resource.pkl
vendored
@@ -36,5 +36,9 @@ forma {
|
|||||||
password = "abcd"
|
password = "abcd"
|
||||||
cores = 1
|
cores = 1
|
||||||
memory = 512
|
memory = 512
|
||||||
|
networks = new Listing<String> {
|
||||||
|
"name=first,hwaddr=BC:24:11:FD:90:BF,bridge=internal"
|
||||||
|
"name=second,hwaddr=BC:24:11:FD:90:BF,bridge=internal"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
types.go
11
types.go
@@ -17,6 +17,7 @@ type LXCProperties struct {
|
|||||||
Memory int `json:"memory"`
|
Memory int `json:"memory"`
|
||||||
OnBoot int `json:"onboot"`
|
OnBoot int `json:"onboot"`
|
||||||
SSHKeys []string `json:"sshkeys"`
|
SSHKeys []string `json:"sshkeys"`
|
||||||
|
Networks []string `json:"networks"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReadRequest struct {
|
type ReadRequest struct {
|
||||||
@@ -75,6 +76,16 @@ type StatusLXCConfig struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Digest string `json:"digest"`
|
Digest string `json:"digest"`
|
||||||
OnBoot int `json:"onboot"`
|
OnBoot int `json:"onboot"`
|
||||||
|
Net0 string `json:"net0,omitempty"`
|
||||||
|
Net1 string `json:"net1,omitempty"`
|
||||||
|
Net2 string `json:"net2,omitempty"`
|
||||||
|
Net3 string `json:"net3,omitempty"`
|
||||||
|
Net4 string `json:"net4,omitempty"`
|
||||||
|
Net5 string `json:"net5,omitempty"`
|
||||||
|
Net6 string `json:"net6,omitempty"`
|
||||||
|
Net7 string `json:"net7,omitempty"`
|
||||||
|
Net8 string `json:"net8,omitempty"`
|
||||||
|
Net9 string `json:"net9,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type StatusLXCConfigResponse struct {
|
type StatusLXCConfigResponse struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user