Skip to content

Commit c2dc3a7

Browse files
lexxxelbpg
andauthored
fix(lxc): allow container creation/update with correct mountoptions (#2319)
* fix: allow container creation with correct mountoptions Signed-off-by: Alexander Petermann <alex@petermann.dev> * fix: use current rootFS Volume in containerUpdate Signed-off-by: Alexander Petermann <alex@petermann.dev> * add acceptance test Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> * cleanup Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --------- Signed-off-by: Alexander Petermann <alex@petermann.dev> Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
1 parent 51f7979 commit c2dc3a7

File tree

2 files changed

+126
-10
lines changed

2 files changed

+126
-10
lines changed

fwprovider/test/resource_container_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,124 @@ func TestAccResourceContainer(t *testing.T) {
221221
})
222222
}
223223

224+
func TestAccResourceContainerMountOptions(t *testing.T) {
225+
te := InitEnvironment(t)
226+
imageFileName := fmt.Sprintf("%d-alpine-3.22-default_20250617_amd64.tar.xz", time.Now().UnixMicro())
227+
testAccDownloadContainerTemplate(t, te, imageFileName)
228+
229+
accTestContainerID := 100000 + rand.Intn(99999)
230+
231+
te.AddTemplateVars(map[string]interface{}{
232+
"ImageFileName": imageFileName,
233+
"TestContainerID": accTestContainerID,
234+
"TimeoutDelete": 300,
235+
})
236+
237+
resource.ParallelTest(t, resource.TestCase{
238+
ProtoV6ProviderFactories: te.AccProviders,
239+
Steps: []resource.TestStep{
240+
{
241+
Config: te.RenderConfig(`
242+
resource "proxmox_virtual_environment_container" "test_container" {
243+
node_name = "{{.NodeName}}"
244+
vm_id = {{.TestContainerID}}
245+
timeout_delete = {{ .TimeoutDelete }}
246+
unprivileged = true
247+
disk {
248+
datastore_id = "local-lvm"
249+
size = 4
250+
mount_options = ["lazytime"]
251+
}
252+
initialization {
253+
hostname = "test-mount-options"
254+
ip_config {
255+
ipv4 {
256+
address = "dhcp"
257+
}
258+
}
259+
}
260+
network_interface {
261+
name = "vmbr0"
262+
}
263+
operating_system {
264+
template_file_id = "local:vztmpl/{{.ImageFileName}}"
265+
type = "alpine"
266+
}
267+
}`, WithRootUser()),
268+
Check: resource.ComposeTestCheckFunc(
269+
ResourceAttributes(accTestContainerName, map[string]string{
270+
"disk.0.mount_options.#": "1",
271+
"disk.0.mount_options.0": "lazytime",
272+
}),
273+
func(*terraform.State) error {
274+
ct := te.NodeClient().Container(accTestContainerID)
275+
276+
ctInfo, err := ct.GetContainer(t.Context())
277+
require.NoError(te.t, err, "failed to get container")
278+
279+
require.NotNil(te.t, ctInfo.RootFS, "rootfs should not be nil")
280+
require.NotNil(te.t, ctInfo.RootFS.MountOptions, "mount_options should not be nil on initial creation")
281+
require.Len(te.t, *ctInfo.RootFS.MountOptions, 1, "mount_options should have 1 element on initial creation")
282+
require.Equal(te.t, "lazytime", (*ctInfo.RootFS.MountOptions)[0], "mount_options should contain 'lazytime'")
283+
284+
te.t.Logf("Container created with rootFS volume: %s", ctInfo.RootFS.Volume)
285+
286+
return nil
287+
},
288+
),
289+
},
290+
{
291+
Config: te.RenderConfig(`
292+
resource "proxmox_virtual_environment_container" "test_container" {
293+
node_name = "{{.NodeName}}"
294+
vm_id = {{.TestContainerID}}
295+
timeout_delete = {{ .TimeoutDelete }}
296+
unprivileged = true
297+
disk {
298+
datastore_id = "local-lvm"
299+
size = 4
300+
mount_options = ["lazytime", "noatime"]
301+
}
302+
initialization {
303+
hostname = "test-mount-options"
304+
ip_config {
305+
ipv4 {
306+
address = "dhcp"
307+
}
308+
}
309+
}
310+
network_interface {
311+
name = "vmbr0"
312+
}
313+
operating_system {
314+
template_file_id = "local:vztmpl/{{.ImageFileName}}"
315+
type = "alpine"
316+
}
317+
}`, WithRootUser()),
318+
Check: resource.ComposeTestCheckFunc(
319+
ResourceAttributes(accTestContainerName, map[string]string{
320+
"disk.0.mount_options.#": "2",
321+
}),
322+
func(*terraform.State) error {
323+
ct := te.NodeClient().Container(accTestContainerID)
324+
325+
ctInfo, err := ct.GetContainer(t.Context())
326+
require.NoError(te.t, err, "failed to get container")
327+
328+
require.NotNil(te.t, ctInfo.RootFS, "rootfs should not be nil")
329+
require.NotNil(te.t, ctInfo.RootFS.MountOptions, "mount_options should not be nil after update")
330+
require.Len(te.t, *ctInfo.RootFS.MountOptions, 2, "mount_options should have 2 elements after update")
331+
332+
te.t.Logf("After update, rootFS volume: %s", ctInfo.RootFS.Volume)
333+
334+
return nil
335+
},
336+
),
337+
},
338+
},
339+
})
340+
}
341+
224342
func TestAccResourceContainerClone(t *testing.T) {
225343
te := InitEnvironment(t)
226344
accTestContainerID := 100000 + rand.Intn(99999)

proxmoxtf/resource/container/container.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ func containerCreateCustom(ctx context.Context, d *schema.ResourceData, m interf
17651765
}
17661766

17671767
diskSize := diskBlock[mkDiskSize].(int)
1768-
if diskDatastoreID != "" && (diskSize != dvDiskSize || len(mountPoints) > 0) {
1768+
if diskDatastoreID != "" && (diskSize != dvDiskSize || len(mountPoints) > 0 || len(diskMountOptions) > 0) {
17691769
// This is a special case where the rootfs size is set to a non-default value at creation time.
17701770
// see https://pve.proxmox.com/pve-docs/chapter-pct.html#_storage_backed_mount_points
17711771
rootFS = &containers.CustomRootFS{
@@ -2979,11 +2979,13 @@ func containerUpdate(ctx context.Context, d *schema.ResourceData, m interface{})
29792979
}
29802980

29812981
rootFS := &containers.CustomRootFS{}
2982-
// Disk ID for the rootfs is always 0
2983-
diskID := 0
2984-
vmID := d.Get(mkVMID).(int)
2985-
rootFS.Volume = diskBlock[mkDiskDatastoreID].(string)
2986-
rootFS.Volume = getContainerDiskVolume(rootFS.Volume, vmID, diskID)
2982+
2983+
containerConfig, e := containerAPI.GetContainer(ctx)
2984+
if e != nil {
2985+
return diag.FromErr(e)
2986+
}
2987+
2988+
rootFS.Volume = containerConfig.RootFS.Volume
29872989

29882990
acl := types.CustomBool(diskBlock[mkDiskACL].(bool))
29892991
mountOptions := diskBlock[mkDiskMountOptions].([]interface{})
@@ -3534,10 +3536,6 @@ func parseImportIDWithNodeName(id string) (string, string, error) {
35343536
return nodeName, id, nil
35353537
}
35363538

3537-
func getContainerDiskVolume(rawVolume string, vmID int, diskID int) string {
3538-
return fmt.Sprintf("%s:vm-%d-disk-%d", rawVolume, vmID, diskID)
3539-
}
3540-
35413539
func skipDnsDiffIfEmpty(k, oldValue, newValue string, d *schema.ResourceData) bool {
35423540
dnsDataKey := mkInitialization + ".0." + mkInitializationDNS
35433541
if k == dnsDataKey+".#" {

0 commit comments

Comments
 (0)