0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-06-29 18:21:10 +00:00
terraform-provider-proxmox/fwprovider/vm/rng/resource.go
Pavel Boldyrev 3119194292
feat(vm): add RNG device support (#1774)
* feat(vm): add RNG device  support

This commit adds support for configuring the Random Number Generator (RNG) device for virtual machines in both the VM resource and datasource. The implementation includes:

- New schema and model for RNG configuration
- Support for setting RNG source, max_bytes, and period
- Updated documentation for RNG configuration
- Test cases for RNG configuration
- Integration with VM creation, update, and read operations

---------

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
2025-02-16 23:53:40 -05:00

148 lines
3.9 KiB
Go

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package rng
import (
"context"
"reflect"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/bpg/terraform-provider-proxmox/fwprovider/attribute"
"github.com/bpg/terraform-provider-proxmox/proxmox/nodes/vms"
)
// Value represents the type for RNG settings.
type Value = types.Object
// NewValue returns a new Value with the given RNG settings from the PVE API.
func NewValue(ctx context.Context, config *vms.GetResponseData, diags *diag.Diagnostics) Value {
rng := Model{}
if config.RNGDevice != nil {
rng.Source = types.StringValue(config.RNGDevice.Source)
if config.RNGDevice.MaxBytes != nil {
rng.MaxBytes = types.Int64Value(int64(*config.RNGDevice.MaxBytes))
}
if config.RNGDevice.Period != nil {
rng.Period = types.Int64Value(int64(*config.RNGDevice.Period))
}
}
obj, d := types.ObjectValueFrom(ctx, attributeTypes(), rng)
diags.Append(d...)
return obj
}
// createRNGDevice creates a new CustomRNGDevice from the given Model.
func createRNGDevice(model Model, setSource bool) *vms.CustomRNGDevice {
rngDevice := &vms.CustomRNGDevice{}
if setSource && !model.Source.IsUnknown() {
rngDevice.Source = model.Source.ValueString()
}
if !model.MaxBytes.IsUnknown() && model.MaxBytes.ValueInt64() != 0 {
maxBytes := int(model.MaxBytes.ValueInt64())
rngDevice.MaxBytes = &maxBytes
}
if !model.Period.IsUnknown() && model.Period.ValueInt64() != 0 {
period := int(model.Period.ValueInt64())
rngDevice.Period = &period
}
return rngDevice
}
// FillCreateBody fills the CreateRequestBody with the RNG settings from the Value.
//
// In the 'create' context, v is the plan.
func FillCreateBody(ctx context.Context, planValue Value, body *vms.CreateRequestBody, diags *diag.Diagnostics) {
var plan Model
if planValue.IsNull() || planValue.IsUnknown() {
return
}
d := planValue.As(ctx, &plan, basetypes.ObjectAsOptions{})
diags.Append(d...)
if d.HasError() {
return
}
rngDevice := createRNGDevice(plan, true)
if !reflect.DeepEqual(rngDevice, &vms.CustomRNGDevice{}) {
body.RNGDevice = rngDevice
}
}
// FillUpdateBody fills the UpdateRequestBody with the RNG settings from the Value.
//
// In the 'update' context, v is the plan and stateValue is the current state.
func FillUpdateBody(
ctx context.Context,
planValue, stateValue Value,
updateBody *vms.UpdateRequestBody,
isClone bool,
diags *diag.Diagnostics,
) {
var plan, state Model
if planValue.IsNull() || planValue.IsUnknown() || planValue.Equal(stateValue) {
return
}
d := planValue.As(ctx, &plan, basetypes.ObjectAsOptions{})
diags.Append(d...)
d = stateValue.As(ctx, &state, basetypes.ObjectAsOptions{})
diags.Append(d...)
if diags.HasError() {
return
}
rngDevice := createRNGDevice(state, true)
if !plan.Source.Equal(state.Source) {
if attribute.ShouldBeRemoved(plan.Source, state.Source, isClone) {
rngDevice.Source = ""
} else if attribute.IsDefined(plan.Source) {
rngDevice.Source = plan.Source.ValueString()
}
}
if !plan.MaxBytes.Equal(state.MaxBytes) {
if attribute.ShouldBeRemoved(plan.MaxBytes, state.MaxBytes, isClone) {
rngDevice.MaxBytes = nil
} else if attribute.IsDefined(plan.MaxBytes) {
maxBytes := int(plan.MaxBytes.ValueInt64())
rngDevice.MaxBytes = &maxBytes
}
}
if !plan.Period.Equal(state.Period) {
if attribute.ShouldBeRemoved(plan.Period, state.Period, isClone) {
rngDevice.Period = nil
} else if attribute.IsDefined(plan.Period) {
period := int(plan.Period.ValueInt64())
rngDevice.Period = &period
}
}
if !reflect.DeepEqual(rngDevice, &vms.CustomRNGDevice{}) {
updateBody.RNGDevice = rngDevice
}
}