mirror of
https://github.com/siderolabs/talos.git
synced 2025-12-25 19:31:20 +01:00
feat: support relative voume size
Include percent-based maxSize, e.g. use 50% of available space. Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com> (cherry picked from commit 83f2bdb9ce6c9466716a6ac9c94dc2222e569ee8)
This commit is contained in:
parent
3d997d7421
commit
aebbbaf274
@ -158,6 +158,7 @@ message PartitionSpec {
|
||||
bool grow = 3;
|
||||
string label = 4;
|
||||
string type_uuid = 5;
|
||||
uint64 relative_max_size = 6;
|
||||
}
|
||||
|
||||
// ProvisioningSpec is the spec for volume provisioning.
|
||||
|
||||
@ -536,7 +536,7 @@ func (m *Qemu) initExtraDisks() error {
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(fmt.Sprintf("'%s' in disk.symlinks", m.Provisioner.UserDiskName(diskID+1)), celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningMinSize: block.MustByteSize(volumeSize),
|
||||
ProvisioningMaxSize: block.MustByteSize(volumeSize),
|
||||
ProvisioningMaxSize: block.MustSize(volumeSize),
|
||||
}
|
||||
userVolume.EncryptionSpec = encryptionSpec
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ func CreatePartition(ctx context.Context, logger *zap.Logger, diskPath string, v
|
||||
available := pt.LargestContiguousAllocatable()
|
||||
|
||||
size := volumeCfg.TypedSpec().Provisioning.PartitionSpec.MinSize
|
||||
maxSize := volumeCfg.TypedSpec().Provisioning.PartitionSpec.MaxSize
|
||||
maxSize := volumeCfg.TypedSpec().Provisioning.PartitionSpec.ResolveMaxSize(available)
|
||||
|
||||
if available < size {
|
||||
// should never happen
|
||||
|
||||
@ -113,11 +113,12 @@ func GetEphemeralVolumeTransformer(inContainer bool) volumeConfigTransformer {
|
||||
Match: extraVolumeConfig.Provisioning().DiskSelector().ValueOr(systemDiskMatch()),
|
||||
},
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
MinSize: extraVolumeConfig.Provisioning().MinSize().ValueOr(quirks.New("").PartitionSizes().EphemeralMinSize()),
|
||||
MaxSize: extraVolumeConfig.Provisioning().MaxSize().ValueOr(0),
|
||||
Grow: extraVolumeConfig.Provisioning().Grow().ValueOr(true),
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
MinSize: extraVolumeConfig.Provisioning().MinSize().ValueOr(quirks.New("").PartitionSizes().EphemeralMinSize()),
|
||||
MaxSize: extraVolumeConfig.Provisioning().MaxSize().ValueOrZero(),
|
||||
RelativeMaxSize: extraVolumeConfig.Provisioning().RelativeMaxSize().ValueOrZero(),
|
||||
Grow: extraVolumeConfig.Provisioning().Grow().ValueOr(true),
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
},
|
||||
FilesystemSpec: block.FilesystemSpec{
|
||||
Type: block.FilesystemTypeXFS,
|
||||
|
||||
@ -422,7 +422,7 @@ func TestEphemeralVolumeTransformerWithExtraConfig(t *testing.T) {
|
||||
ephemeralConfig := blockcfg.NewVolumeConfigV1Alpha1()
|
||||
ephemeralConfig.MetaName = constants.EphemeralPartitionLabel
|
||||
ephemeralConfig.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("10GiB")
|
||||
ephemeralConfig.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("100GiB")
|
||||
ephemeralConfig.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("100GiB")
|
||||
|
||||
cfg, err := container.New(
|
||||
baseCfg.DeepCopy(),
|
||||
|
||||
@ -100,11 +100,12 @@ func UserVolumeTransformer(c configconfig.Config) ([]VolumeResource, error) {
|
||||
Match: userVolumeConfig.Provisioning().DiskSelector().ValueOr(noMatch),
|
||||
},
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
MinSize: cmp.Or(userVolumeConfig.Provisioning().MinSize().ValueOrZero(), MinUserVolumeSize),
|
||||
MaxSize: userVolumeConfig.Provisioning().MaxSize().ValueOrZero(),
|
||||
Grow: userVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
MinSize: cmp.Or(userVolumeConfig.Provisioning().MinSize().ValueOrZero(), MinUserVolumeSize),
|
||||
MaxSize: userVolumeConfig.Provisioning().MaxSize().ValueOrZero(),
|
||||
RelativeMaxSize: userVolumeConfig.Provisioning().RelativeMaxSize().ValueOrZero(),
|
||||
Grow: userVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
},
|
||||
FilesystemSpec: block.FilesystemSpec{
|
||||
Type: userVolumeConfig.Filesystem().Type(),
|
||||
@ -157,11 +158,12 @@ func RawVolumeTransformer(c configconfig.Config) ([]VolumeResource, error) {
|
||||
Match: rawVolumeConfig.Provisioning().DiskSelector().ValueOr(noMatch),
|
||||
},
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
MinSize: cmp.Or(rawVolumeConfig.Provisioning().MinSize().ValueOrZero(), MinUserVolumeSize),
|
||||
MaxSize: rawVolumeConfig.Provisioning().MaxSize().ValueOrZero(),
|
||||
Grow: rawVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
MinSize: cmp.Or(rawVolumeConfig.Provisioning().MinSize().ValueOrZero(), MinUserVolumeSize),
|
||||
MaxSize: rawVolumeConfig.Provisioning().MaxSize().ValueOrZero(),
|
||||
RelativeMaxSize: rawVolumeConfig.Provisioning().RelativeMaxSize().ValueOrZero(),
|
||||
Grow: rawVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinuxFilesystemData,
|
||||
},
|
||||
FilesystemSpec: block.FilesystemSpec{
|
||||
Type: block.FilesystemTypeNone,
|
||||
@ -230,10 +232,11 @@ func SwapVolumeTransformer(c configconfig.Config) ([]VolumeResource, error) {
|
||||
Match: swapVolumeConfig.Provisioning().DiskSelector().ValueOr(noMatch),
|
||||
},
|
||||
PartitionSpec: block.PartitionSpec{
|
||||
MaxSize: cmp.Or(swapVolumeConfig.Provisioning().MaxSize().ValueOrZero(), MinUserVolumeSize),
|
||||
Grow: swapVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinkSwap,
|
||||
MaxSize: cmp.Or(swapVolumeConfig.Provisioning().MaxSize().ValueOrZero(), MinUserVolumeSize),
|
||||
RelativeMaxSize: swapVolumeConfig.Provisioning().RelativeMaxSize().ValueOrZero(),
|
||||
Grow: swapVolumeConfig.Provisioning().Grow().ValueOrZero(),
|
||||
Label: volumeID,
|
||||
TypeUUID: partition.LinkSwap,
|
||||
},
|
||||
FilesystemSpec: block.FilesystemSpec{
|
||||
Type: block.FilesystemTypeSwap,
|
||||
|
||||
@ -301,7 +301,7 @@ func (suite *VolumeConfigSuite) TestReconcileExtraEPHEMERALConfig() {
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(`disk.transport == "nvme"`, celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningGrow: pointer.To(false),
|
||||
ProvisioningMaxSize: blockcfg.MustByteSize("2.5TiB"),
|
||||
ProvisioningMaxSize: blockcfg.MustSize("2.5TiB"),
|
||||
},
|
||||
EncryptionSpec: blockcfg.EncryptionSpec{
|
||||
EncryptionProvider: block.EncryptionProviderLUKS2,
|
||||
@ -341,12 +341,12 @@ func (suite *VolumeConfigSuite) TestReconcileUserRawVolumes() {
|
||||
rv1.MetaName = "data1"
|
||||
suite.Require().NoError(rv1.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`system_disk`)))
|
||||
rv1.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("10GiB")
|
||||
rv1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("100GiB")
|
||||
rv1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("100GiB")
|
||||
|
||||
rv2 := blockcfg.NewRawVolumeConfigV1Alpha1()
|
||||
rv2.MetaName = "data2"
|
||||
suite.Require().NoError(rv2.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`!system_disk`)))
|
||||
rv2.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("1TiB")
|
||||
rv2.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("1TiB")
|
||||
rv2.EncryptionSpec = blockcfg.EncryptionSpec{
|
||||
EncryptionProvider: block.EncryptionProviderLUKS2,
|
||||
EncryptionKeys: []blockcfg.EncryptionKey{
|
||||
@ -415,14 +415,14 @@ func (suite *VolumeConfigSuite) TestReconcileUserSwapVolumes() {
|
||||
uvPart1.MetaName = userVolumeNames[0]
|
||||
suite.Require().NoError(uvPart1.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`system_disk`)))
|
||||
uvPart1.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("10GiB")
|
||||
uvPart1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("100GiB")
|
||||
uvPart1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("100GiB")
|
||||
uvPart1.FilesystemSpec.FilesystemType = block.FilesystemTypeXFS
|
||||
|
||||
uvPart2 := blockcfg.NewUserVolumeConfigV1Alpha1()
|
||||
uvPart2.MetaName = userVolumeNames[1]
|
||||
uvPart2.VolumeType = pointer.To(block.VolumeTypePartition)
|
||||
suite.Require().NoError(uvPart2.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`!system_disk`)))
|
||||
uvPart2.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("1TiB")
|
||||
uvPart2.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("1TiB")
|
||||
uvPart2.EncryptionSpec = blockcfg.EncryptionSpec{
|
||||
EncryptionProvider: block.EncryptionProviderLUKS2,
|
||||
EncryptionKeys: []blockcfg.EncryptionKey{
|
||||
@ -461,7 +461,7 @@ func (suite *VolumeConfigSuite) TestReconcileUserSwapVolumes() {
|
||||
sv1 := blockcfg.NewSwapVolumeConfigV1Alpha1()
|
||||
sv1.MetaName = "swap"
|
||||
suite.Require().NoError(sv1.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.transport == "nvme"`)))
|
||||
sv1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("2GiB")
|
||||
sv1.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("2GiB")
|
||||
|
||||
ctr, err := container.New(uvPart1, uvPart2, uvDir1, uvDisk1, sv1)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
@ -240,7 +240,7 @@ func (suite *ImageCacheConfigSuite) TestReconcileWithImageCacheVolume() {
|
||||
|
||||
volumeConfig := blockcfg.NewVolumeConfigV1Alpha1()
|
||||
volumeConfig.MetaName = constants.ImageCachePartitionLabel
|
||||
volumeConfig.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("10GiB")
|
||||
volumeConfig.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("10GiB")
|
||||
|
||||
container, err := container.New(v1alpha1Cfg, volumeConfig)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
@ -512,18 +512,30 @@ func (suite *VolumesSuite) TestUserVolumesPartition() {
|
||||
|
||||
userVolumeIDs := xslices.Map(volumeIDs, func(volumeID string) string { return constants.UserVolumePrefix + volumeID })
|
||||
|
||||
configDocs := xslices.Map(volumeIDs, func(volumeID string) any {
|
||||
configDocs := xslices.Map(volumeIDs[:1], func(volumeID string) any {
|
||||
doc := blockcfg.NewUserVolumeConfigV1Alpha1()
|
||||
doc.MetaName = volumeID
|
||||
doc.ProvisioningSpec.DiskSelectorSpec.Match = cel.MustExpression(
|
||||
cel.ParseBooleanExpression(fmt.Sprintf("'%s' in disk.symlinks", disk.TypedSpec().Symlinks[0]), celenv.DiskLocator()),
|
||||
)
|
||||
doc.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("100MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("1GiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("1GiB")
|
||||
|
||||
return doc
|
||||
})
|
||||
|
||||
configDocs = append(configDocs, xslices.Map(volumeIDs[1:], func(volumeID string) any {
|
||||
doc := blockcfg.NewUserVolumeConfigV1Alpha1()
|
||||
doc.MetaName = volumeID
|
||||
doc.ProvisioningSpec.DiskSelectorSpec.Match = cel.MustExpression(
|
||||
cel.ParseBooleanExpression(fmt.Sprintf("'%s' in disk.symlinks", disk.TypedSpec().Symlinks[0]), celenv.DiskLocator()),
|
||||
)
|
||||
doc.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("100MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("20%")
|
||||
|
||||
return doc
|
||||
})...)
|
||||
|
||||
// create user volumes
|
||||
suite.PatchMachineConfig(ctx, configDocs...)
|
||||
|
||||
@ -979,7 +991,7 @@ func (suite *VolumesSuite) TestRawVolumes() {
|
||||
cel.ParseBooleanExpression(fmt.Sprintf("'%s' in disk.symlinks", disk.TypedSpec().Symlinks[0]), celenv.DiskLocator()),
|
||||
)
|
||||
doc.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("100MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("500MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("500MiB")
|
||||
|
||||
return doc
|
||||
})
|
||||
@ -1104,7 +1116,7 @@ func (suite *VolumesSuite) TestExistingVolumes() {
|
||||
cel.ParseBooleanExpression(fmt.Sprintf("'%s' in disk.symlinks", disk.TypedSpec().Symlinks[0]), celenv.DiskLocator()),
|
||||
)
|
||||
userVolumeDoc.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("100MiB")
|
||||
userVolumeDoc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("1GiB")
|
||||
userVolumeDoc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("1GiB")
|
||||
|
||||
// create user volumes
|
||||
suite.PatchMachineConfig(ctx, userVolumeDoc)
|
||||
@ -1299,7 +1311,7 @@ func (suite *VolumesSuite) TestSwapOnOff() {
|
||||
},
|
||||
}
|
||||
doc.ProvisioningSpec.ProvisioningMinSize = blockcfg.MustByteSize("100MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustByteSize("500MiB")
|
||||
doc.ProvisioningSpec.ProvisioningMaxSize = blockcfg.MustSize("500MiB")
|
||||
|
||||
// create user volumes
|
||||
suite.PatchMachineConfig(ctx, doc)
|
||||
|
||||
@ -1236,14 +1236,15 @@ func (x *MountStatusSpec) GetDetached() bool {
|
||||
|
||||
// PartitionSpec is the spec for volume partitioning.
|
||||
type PartitionSpec struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
MinSize uint64 `protobuf:"varint,1,opt,name=min_size,json=minSize,proto3" json:"min_size,omitempty"`
|
||||
MaxSize uint64 `protobuf:"varint,2,opt,name=max_size,json=maxSize,proto3" json:"max_size,omitempty"`
|
||||
Grow bool `protobuf:"varint,3,opt,name=grow,proto3" json:"grow,omitempty"`
|
||||
Label string `protobuf:"bytes,4,opt,name=label,proto3" json:"label,omitempty"`
|
||||
TypeUuid string `protobuf:"bytes,5,opt,name=type_uuid,json=typeUuid,proto3" json:"type_uuid,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
MinSize uint64 `protobuf:"varint,1,opt,name=min_size,json=minSize,proto3" json:"min_size,omitempty"`
|
||||
MaxSize uint64 `protobuf:"varint,2,opt,name=max_size,json=maxSize,proto3" json:"max_size,omitempty"`
|
||||
Grow bool `protobuf:"varint,3,opt,name=grow,proto3" json:"grow,omitempty"`
|
||||
Label string `protobuf:"bytes,4,opt,name=label,proto3" json:"label,omitempty"`
|
||||
TypeUuid string `protobuf:"bytes,5,opt,name=type_uuid,json=typeUuid,proto3" json:"type_uuid,omitempty"`
|
||||
RelativeMaxSize uint64 `protobuf:"varint,6,opt,name=relative_max_size,json=relativeMaxSize,proto3" json:"relative_max_size,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *PartitionSpec) Reset() {
|
||||
@ -1311,6 +1312,13 @@ func (x *PartitionSpec) GetTypeUuid() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *PartitionSpec) GetRelativeMaxSize() uint64 {
|
||||
if x != nil {
|
||||
return x.RelativeMaxSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ProvisioningSpec is the spec for volume provisioning.
|
||||
type ProvisioningSpec struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
@ -2431,13 +2439,14 @@ const file_resource_definitions_block_block_proto_rawDesc = "" +
|
||||
"\tread_only\x18\x05 \x01(\bR\breadOnly\x122\n" +
|
||||
"\x15project_quota_support\x18\x06 \x01(\bR\x13projectQuotaSupport\x12n\n" +
|
||||
"\x13encryption_provider\x18\a \x01(\x0e2=.talos.resource.definitions.enums.BlockEncryptionProviderTypeR\x12encryptionProvider\x12\x1a\n" +
|
||||
"\bdetached\x18\b \x01(\bR\bdetached\"\x8c\x01\n" +
|
||||
"\bdetached\x18\b \x01(\bR\bdetached\"\xb8\x01\n" +
|
||||
"\rPartitionSpec\x12\x19\n" +
|
||||
"\bmin_size\x18\x01 \x01(\x04R\aminSize\x12\x19\n" +
|
||||
"\bmax_size\x18\x02 \x01(\x04R\amaxSize\x12\x12\n" +
|
||||
"\x04grow\x18\x03 \x01(\bR\x04grow\x12\x14\n" +
|
||||
"\x05label\x18\x04 \x01(\tR\x05label\x12\x1b\n" +
|
||||
"\ttype_uuid\x18\x05 \x01(\tR\btypeUuid\"\xae\x02\n" +
|
||||
"\ttype_uuid\x18\x05 \x01(\tR\btypeUuid\x12*\n" +
|
||||
"\x11relative_max_size\x18\x06 \x01(\x04R\x0frelativeMaxSize\"\xae\x02\n" +
|
||||
"\x10ProvisioningSpec\x12S\n" +
|
||||
"\rdisk_selector\x18\x01 \x01(\v2..talos.resource.definitions.block.DiskSelectorR\fdiskSelector\x12V\n" +
|
||||
"\x0epartition_spec\x18\x02 \x01(\v2/.talos.resource.definitions.block.PartitionSpecR\rpartitionSpec\x12\x12\n" +
|
||||
|
||||
@ -1208,6 +1208,11 @@ func (m *PartitionSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if m.RelativeMaxSize != 0 {
|
||||
i = protohelpers.EncodeVarint(dAtA, i, uint64(m.RelativeMaxSize))
|
||||
i--
|
||||
dAtA[i] = 0x30
|
||||
}
|
||||
if len(m.TypeUuid) > 0 {
|
||||
i -= len(m.TypeUuid)
|
||||
copy(dAtA[i:], m.TypeUuid)
|
||||
@ -2693,6 +2698,9 @@ func (m *PartitionSpec) SizeVT() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + protohelpers.SizeOfVarint(uint64(l))
|
||||
}
|
||||
if m.RelativeMaxSize != 0 {
|
||||
n += 1 + protohelpers.SizeOfVarint(uint64(m.RelativeMaxSize))
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
@ -6421,6 +6429,25 @@ func (m *PartitionSpec) UnmarshalVT(dAtA []byte) error {
|
||||
}
|
||||
m.TypeUuid = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 6:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field RelativeMaxSize", wireType)
|
||||
}
|
||||
m.RelativeMaxSize = 0
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return protohelpers.ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
m.RelativeMaxSize |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := protohelpers.Skip(dAtA[iNdEx:])
|
||||
|
||||
@ -32,6 +32,7 @@ type VolumeProvisioningConfig interface {
|
||||
Grow() optional.Optional[bool]
|
||||
MinSize() optional.Optional[uint64]
|
||||
MaxSize() optional.Optional[uint64]
|
||||
RelativeMaxSize() optional.Optional[uint64]
|
||||
}
|
||||
|
||||
// WrapVolumesConfigList wraps a list of VolumeConfig providing access by name.
|
||||
@ -81,6 +82,14 @@ func (emptyVolumeConfig) MaxSize() optional.Optional[uint64] {
|
||||
return optional.None[uint64]()
|
||||
}
|
||||
|
||||
func (emptyVolumeConfig) RelativeMinSize() optional.Optional[uint64] {
|
||||
return optional.None[uint64]()
|
||||
}
|
||||
|
||||
func (emptyVolumeConfig) RelativeMaxSize() optional.Optional[uint64] {
|
||||
return optional.None[uint64]()
|
||||
}
|
||||
|
||||
// UserVolumeConfig defines the interface to access user volume configuration.
|
||||
type UserVolumeConfig interface {
|
||||
NamedDocument
|
||||
|
||||
@ -313,9 +313,9 @@
|
||||
"maxSize": {
|
||||
"type": "string",
|
||||
"title": "maxSize",
|
||||
"description": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.\n",
|
||||
"markdownDescription": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\u003c/p\u003e\n\n\u003cp\u003eSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.\u003c/p\u003e\n"
|
||||
"description": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.\n",
|
||||
"markdownDescription": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\u003c/p\u003e\n\n\u003cp\u003eSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -666,9 +666,9 @@ func (ProvisioningSpec) Doc() *encoder.Doc {
|
||||
},
|
||||
{
|
||||
Name: "maxSize",
|
||||
Type: "ByteSize",
|
||||
Type: "Size",
|
||||
Note: "",
|
||||
Description: "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.",
|
||||
Description: "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "The maximum size of the volume, if not specified the volume can grow to the size of the" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
@ -676,6 +676,7 @@ func (ProvisioningSpec) Doc() *encoder.Doc {
|
||||
|
||||
doc.Fields[2].AddExample("", "2.5GiB")
|
||||
doc.Fields[3].AddExample("", "50GiB")
|
||||
doc.Fields[3].AddExample("", "80%")
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
@ -29,19 +29,6 @@ type ByteSize struct {
|
||||
raw []byte
|
||||
}
|
||||
|
||||
// MustByteSize returns a new ByteSize with the given value.
|
||||
//
|
||||
// It panics if the value is invalid.
|
||||
func MustByteSize(value string) ByteSize {
|
||||
var bs ByteSize
|
||||
|
||||
if err := bs.UnmarshalText([]byte(value)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
// Value returns the value.
|
||||
func (bs ByteSize) Value() uint64 {
|
||||
return pointer.SafeDeref(bs.value)
|
||||
|
||||
@ -31,13 +31,29 @@ func (o *RawVolumeConfigV1Alpha1) DeepCopy() *RawVolumeConfigV1Alpha1 {
|
||||
cp.ProvisioningSpec.ProvisioningMinSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMinSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMinSize.raw, o.ProvisioningSpec.ProvisioningMinSize.raw)
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.value
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = new(PercentageSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw)
|
||||
}
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.raw)
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = new(ByteSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw)
|
||||
}
|
||||
}
|
||||
if o.EncryptionSpec.EncryptionKeys != nil {
|
||||
cp.EncryptionSpec.EncryptionKeys = make([]EncryptionKey, len(o.EncryptionSpec.EncryptionKeys))
|
||||
@ -99,13 +115,29 @@ func (o *SwapVolumeConfigV1Alpha1) DeepCopy() *SwapVolumeConfigV1Alpha1 {
|
||||
cp.ProvisioningSpec.ProvisioningMinSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMinSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMinSize.raw, o.ProvisioningSpec.ProvisioningMinSize.raw)
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.value
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = new(PercentageSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw)
|
||||
}
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.raw)
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = new(ByteSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw)
|
||||
}
|
||||
}
|
||||
if o.EncryptionSpec.EncryptionKeys != nil {
|
||||
cp.EncryptionSpec.EncryptionKeys = make([]EncryptionKey, len(o.EncryptionSpec.EncryptionKeys))
|
||||
@ -171,13 +203,29 @@ func (o *UserVolumeConfigV1Alpha1) DeepCopy() *UserVolumeConfigV1Alpha1 {
|
||||
cp.ProvisioningSpec.ProvisioningMinSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMinSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMinSize.raw, o.ProvisioningSpec.ProvisioningMinSize.raw)
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.value
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = new(PercentageSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw)
|
||||
}
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.raw)
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = new(ByteSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw)
|
||||
}
|
||||
}
|
||||
if o.FilesystemSpec.ProjectQuotaSupportConfig != nil {
|
||||
cp.FilesystemSpec.ProjectQuotaSupportConfig = new(bool)
|
||||
@ -243,13 +291,29 @@ func (o *VolumeConfigV1Alpha1) DeepCopy() *VolumeConfigV1Alpha1 {
|
||||
cp.ProvisioningSpec.ProvisioningMinSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMinSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMinSize.raw, o.ProvisioningSpec.ProvisioningMinSize.raw)
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.value
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = new(PercentageSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.PercentageSize.raw)
|
||||
}
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.raw)
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = new(ByteSize)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = new(uint64)
|
||||
*cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value = *o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.value
|
||||
}
|
||||
if o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw != nil {
|
||||
cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw = make([]byte, len(o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw))
|
||||
copy(cp.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw, o.ProvisioningSpec.ProvisioningMaxSize.ByteSize.raw)
|
||||
}
|
||||
}
|
||||
if o.EncryptionSpec.EncryptionKeys != nil {
|
||||
cp.EncryptionSpec.EncryptionKeys = make([]EncryptionKey, len(o.EncryptionSpec.EncryptionKeys))
|
||||
|
||||
82
pkg/machinery/config/types/block/percentage_size.go
Normal file
82
pkg/machinery/config/types/block/percentage_size.go
Normal file
@ -0,0 +1,82 @@
|
||||
// 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 http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package block
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
|
||||
"github.com/siderolabs/go-pointer"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Check interfaces.
|
||||
var (
|
||||
_ encoding.TextMarshaler = PercentageSize{}
|
||||
_ encoding.TextUnmarshaler = (*PercentageSize)(nil)
|
||||
_ yaml.IsZeroer = PercentageSize{}
|
||||
)
|
||||
|
||||
// PercentageSize is a size in percents.
|
||||
type PercentageSize struct {
|
||||
value *uint64
|
||||
raw []byte
|
||||
}
|
||||
|
||||
// Value returns the value.
|
||||
func (ps PercentageSize) Value() uint64 {
|
||||
return pointer.SafeDeref(ps.value)
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (ps PercentageSize) MarshalText() ([]byte, error) {
|
||||
if ps.raw != nil {
|
||||
return ps.raw, nil
|
||||
}
|
||||
|
||||
if ps.value != nil {
|
||||
return []byte(strconv.FormatUint(*ps.value, 10)), nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (ps *PercentageSize) UnmarshalText(text []byte) error {
|
||||
if len(text) == 0 {
|
||||
ps.value = nil
|
||||
ps.raw = nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if !bytes.HasSuffix(text, []byte("%")) {
|
||||
return fmt.Errorf("percentage must end with '%%'")
|
||||
}
|
||||
|
||||
numStr := string(text[:len(text)-1])
|
||||
|
||||
value, err := strconv.ParseFloat(numStr, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid percentage value: %w", err)
|
||||
}
|
||||
|
||||
if value < 0 || value > 100 {
|
||||
return fmt.Errorf("percentage must be between 0 and 100, got %v", value)
|
||||
}
|
||||
|
||||
ps.value = pointer.To(uint64(value))
|
||||
ps.raw = slices.Clone(text)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsZero implements yaml.IsZeroer.
|
||||
func (ps PercentageSize) IsZero() bool {
|
||||
return ps.value == nil && ps.raw == nil
|
||||
}
|
||||
@ -90,7 +90,7 @@ func exampleRawVolumeConfigV1Alpha1() *RawVolumeConfigV1Alpha1 {
|
||||
DiskSelectorSpec: DiskSelector{
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(`disk.transport == "nvme"`, celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningMaxSize: MustByteSize("50GiB"),
|
||||
ProvisioningMaxSize: MustSize("50GiB"),
|
||||
}
|
||||
|
||||
return cfg
|
||||
|
||||
@ -39,7 +39,7 @@ func TestRawVolumeConfigMarshalUnmarshal(t *testing.T) {
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.transport == "nvme" && !system_disk`)))
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("100GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("100GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -178,7 +178,7 @@ func TestRawVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("10GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -259,7 +259,7 @@ func TestRawVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
|
||||
return c
|
||||
|
||||
117
pkg/machinery/config/types/block/size.go
Normal file
117
pkg/machinery/config/types/block/size.go
Normal file
@ -0,0 +1,117 @@
|
||||
// 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 http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package block
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Check interfaces.
|
||||
var (
|
||||
_ encoding.TextMarshaler = Size{}
|
||||
_ encoding.TextUnmarshaler = (*PercentageSize)(nil)
|
||||
_ yaml.IsZeroer = Size{}
|
||||
)
|
||||
|
||||
// Size is either a PercentageSize or ByteSize.
|
||||
type Size struct {
|
||||
PercentageSize *PercentageSize
|
||||
ByteSize *ByteSize
|
||||
}
|
||||
|
||||
// MustSize returns a new Size with the given value.
|
||||
//
|
||||
// It panics if the value is invalid.
|
||||
func MustSize(value string) Size {
|
||||
var s Size
|
||||
|
||||
if err := s.UnmarshalText([]byte(value)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// MustByteSize returns a new Size with the given ByteSize value.
|
||||
//
|
||||
// It panics if the value is invalid.
|
||||
func MustByteSize(value string) ByteSize {
|
||||
var bs ByteSize
|
||||
|
||||
if err := bs.UnmarshalText([]byte(value)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return bs
|
||||
}
|
||||
|
||||
// Value returns the value.
|
||||
func (s Size) Value() uint64 {
|
||||
if s.ByteSize != nil {
|
||||
return s.ByteSize.Value()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// RelativeValue returns the relative value.
|
||||
func (s Size) RelativeValue() (uint64, bool) {
|
||||
if s.PercentageSize != nil {
|
||||
return s.PercentageSize.Value(), true
|
||||
}
|
||||
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler.
|
||||
func (s Size) MarshalText() ([]byte, error) {
|
||||
if s.ByteSize != nil {
|
||||
return s.ByteSize.MarshalText()
|
||||
}
|
||||
|
||||
if s.PercentageSize != nil {
|
||||
return s.PercentageSize.MarshalText()
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||
func (s *Size) UnmarshalText(text []byte) error {
|
||||
if string(text) == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.Contains(string(text), "%") {
|
||||
var ps PercentageSize
|
||||
if err := ps.UnmarshalText(text); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.PercentageSize = &ps
|
||||
} else {
|
||||
var bs ByteSize
|
||||
if err := bs.UnmarshalText(text); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.ByteSize = &bs
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsZero implements yaml.IsZeroer.
|
||||
func (s Size) IsZero() bool {
|
||||
return (s.PercentageSize == nil || s.PercentageSize.IsZero()) && (s.ByteSize == nil || s.ByteSize.IsZero())
|
||||
}
|
||||
|
||||
// IsRelative returns if the Size is a relative size.
|
||||
func (s Size) IsRelative() bool {
|
||||
return (s.PercentageSize != nil && !s.PercentageSize.IsZero())
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
package block_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -13,15 +14,17 @@ import (
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/block"
|
||||
)
|
||||
|
||||
func TestByteSizeUnmarshal(t *testing.T) {
|
||||
func TestSizeUnmarshal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
in string
|
||||
|
||||
in string
|
||||
want uint64
|
||||
}{
|
||||
{in: "", want: 0},
|
||||
{in: "100%", want: 100},
|
||||
{in: "33.4%", want: 33},
|
||||
{in: "33.4124%", want: 33},
|
||||
{in: "1048576", want: 1048576},
|
||||
{in: "2.5GiB", want: 2684354560},
|
||||
{in: "2.5GB", want: 2500000000},
|
||||
@ -31,13 +34,25 @@ func TestByteSizeUnmarshal(t *testing.T) {
|
||||
t.Run(test.in, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var bs block.ByteSize
|
||||
var s block.Size
|
||||
|
||||
require.NoError(t, bs.UnmarshalText([]byte(test.in)))
|
||||
require.NoError(t, s.UnmarshalText([]byte(test.in)))
|
||||
|
||||
assert.Equal(t, test.want, bs.Value())
|
||||
if strings.Contains(test.in, "%") {
|
||||
assert.Zero(t, s.Value())
|
||||
|
||||
out, err := bs.MarshalText()
|
||||
val, ok := s.RelativeValue()
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, test.want, val)
|
||||
} else {
|
||||
assert.Equal(t, test.want, s.Value())
|
||||
|
||||
val, ok := s.RelativeValue()
|
||||
assert.False(t, ok)
|
||||
assert.Zero(t, val)
|
||||
}
|
||||
|
||||
out, err := s.MarshalText()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, test.in, string(out))
|
||||
@ -90,7 +90,7 @@ func exampleSwapVolumeConfigV1Alpha1() *SwapVolumeConfigV1Alpha1 {
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(`disk.transport == "nvme"`, celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningMinSize: MustByteSize("3GiB"),
|
||||
ProvisioningMaxSize: MustByteSize("4GiB"),
|
||||
ProvisioningMaxSize: MustSize("4GiB"),
|
||||
}
|
||||
cfg.EncryptionSpec = EncryptionSpec{
|
||||
EncryptionProvider: block.EncryptionProviderLUKS2,
|
||||
|
||||
@ -39,7 +39,7 @@ func TestSwapVolumeConfigMarshalUnmarshal(t *testing.T) {
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.transport == "nvme" && !system_disk`)))
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("100GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("100GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -178,7 +178,7 @@ func TestSwapVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("10GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -259,7 +259,7 @@ func TestSwapVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
|
||||
return c
|
||||
|
||||
@ -113,7 +113,7 @@ func exampleUserVolumeConfigV1Alpha1Partition() *UserVolumeConfigV1Alpha1 {
|
||||
DiskSelectorSpec: DiskSelector{
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(`disk.transport == "nvme"`, celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningMaxSize: MustByteSize("50GiB"),
|
||||
ProvisioningMaxSize: MustSize("50GiB"),
|
||||
}
|
||||
cfg.FilesystemSpec = FilesystemSpec{
|
||||
FilesystemType: block.FilesystemTypeXFS,
|
||||
|
||||
@ -40,7 +40,7 @@ func TestUserVolumeConfigMarshalUnmarshal(t *testing.T) {
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.transport == "nvme" && !system_disk`)))
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("100GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("100GiB")
|
||||
c.FilesystemSpec.FilesystemType = blockres.FilesystemTypeXFS
|
||||
|
||||
return c
|
||||
@ -195,7 +195,7 @@ func TestUserVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("10GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -210,7 +210,7 @@ func TestUserVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.FilesystemSpec.FilesystemType = blockres.FilesystemTypeISO9660
|
||||
|
||||
@ -349,7 +349,7 @@ func TestUserVolumeConfigValidate(t *testing.T) {
|
||||
c.VolumeType = pointer.To(blockres.VolumeTypeDisk)
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.FilesystemSpec.FilesystemType = blockres.FilesystemTypeEXT4
|
||||
|
||||
@ -405,7 +405,7 @@ func TestUserVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.FilesystemSpec.FilesystemType = blockres.FilesystemTypeEXT4
|
||||
|
||||
@ -421,7 +421,7 @@ func TestUserVolumeConfigValidate(t *testing.T) {
|
||||
c.VolumeType = pointer.To(blockres.VolumeTypePartition)
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
c.FilesystemSpec.FilesystemType = blockres.FilesystemTypeEXT4
|
||||
|
||||
|
||||
@ -93,13 +93,15 @@ type ProvisioningSpec struct {
|
||||
// The maximum size of the volume, if not specified the volume can grow to the size of the
|
||||
// disk.
|
||||
//
|
||||
// Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB.
|
||||
// Size is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.
|
||||
// examples:
|
||||
// - value: >
|
||||
// "50GiB"
|
||||
// - value: >
|
||||
// "80%"
|
||||
// schema:
|
||||
// type: string
|
||||
ProvisioningMaxSize ByteSize `yaml:"maxSize,omitempty"`
|
||||
ProvisioningMaxSize Size `yaml:"maxSize,omitempty"`
|
||||
}
|
||||
|
||||
// DiskSelector selects a disk for the volume.
|
||||
@ -135,7 +137,7 @@ func exampleVolumeConfigEphemeralV1Alpha1() *VolumeConfigV1Alpha1 {
|
||||
DiskSelectorSpec: DiskSelector{
|
||||
Match: cel.MustExpression(cel.ParseBooleanExpression(`disk.transport == "nvme"`, celenv.DiskLocator())),
|
||||
},
|
||||
ProvisioningMaxSize: MustByteSize("50GiB"),
|
||||
ProvisioningMaxSize: MustSize("50GiB"),
|
||||
}
|
||||
|
||||
return cfg
|
||||
@ -230,7 +232,7 @@ func (s ProvisioningSpec) Validate(required bool, sizeSupported bool) ([]string,
|
||||
}
|
||||
|
||||
if sizeSupported {
|
||||
if !s.ProvisioningMinSize.IsZero() && !s.ProvisioningMaxSize.IsZero() {
|
||||
if !s.ProvisioningMinSize.IsZero() && !s.ProvisioningMaxSize.IsZero() && !s.ProvisioningMaxSize.IsRelative() {
|
||||
if s.ProvisioningMinSize.Value() > s.ProvisioningMaxSize.Value() {
|
||||
validationErrors = errors.Join(validationErrors, errors.New("min size is greater than max size"))
|
||||
}
|
||||
@ -306,3 +308,17 @@ func (s ProvisioningSpec) MaxSize() optional.Optional[uint64] {
|
||||
|
||||
return optional.Some(s.ProvisioningMaxSize.Value())
|
||||
}
|
||||
|
||||
// RelativeMaxSize implements config.VolumeProvisioningConfig interface.
|
||||
func (s ProvisioningSpec) RelativeMaxSize() optional.Optional[uint64] {
|
||||
if s.ProvisioningMaxSize.IsZero() {
|
||||
return optional.None[uint64]()
|
||||
}
|
||||
|
||||
val, ok := s.ProvisioningMaxSize.RelativeValue()
|
||||
if !ok {
|
||||
return optional.None[uint64]()
|
||||
}
|
||||
|
||||
return optional.Some(val)
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ func TestVolumeConfigMarshalUnmarshal(t *testing.T) {
|
||||
c := block.NewVolumeConfigV1Alpha1()
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
|
||||
return c
|
||||
@ -164,7 +164,7 @@ func TestVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("10GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -179,7 +179,7 @@ func TestVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.StatePartitionLabel
|
||||
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("2.5GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("10GiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("10GiB")
|
||||
|
||||
return c
|
||||
},
|
||||
@ -251,7 +251,7 @@ func TestVolumeConfigValidate(t *testing.T) {
|
||||
c.MetaName = constants.EphemeralPartitionLabel
|
||||
|
||||
require.NoError(t, c.ProvisioningSpec.DiskSelectorSpec.Match.UnmarshalText([]byte(`disk.size > 120u * GiB`)))
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustByteSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMaxSize = block.MustSize("2.5TiB")
|
||||
c.ProvisioningSpec.ProvisioningMinSize = block.MustByteSize("10GiB")
|
||||
|
||||
return c
|
||||
|
||||
@ -92,6 +92,9 @@ type PartitionSpec struct {
|
||||
// Partition maximum size in bytes, if not set, grows to the maximum size.
|
||||
MaxSize uint64 `yaml:"maxSize,omitempty" protobuf:"2"`
|
||||
|
||||
// Partition maximum size (relative), if not set, grows to the maximum size.
|
||||
RelativeMaxSize uint64 `yaml:"relativeMaxSize" protobuf:"6"`
|
||||
|
||||
// Grow the partition automatically to the maximum size.
|
||||
Grow bool `yaml:"grow" protobuf:"3"`
|
||||
|
||||
@ -102,6 +105,15 @@ type PartitionSpec struct {
|
||||
TypeUUID string `yaml:"typeUUID,omitempty" protobuf:"5"`
|
||||
}
|
||||
|
||||
// ResolveMaxSize resolves the maximum size of the partition.
|
||||
func (ps *PartitionSpec) ResolveMaxSize(available uint64) uint64 {
|
||||
if ps.RelativeMaxSize != 0 {
|
||||
return available * ps.RelativeMaxSize / 100
|
||||
}
|
||||
|
||||
return ps.MaxSize
|
||||
}
|
||||
|
||||
// LocatorSpec is the spec for volume locator.
|
||||
//
|
||||
//gotagsrewrite:gen
|
||||
|
||||
@ -5798,6 +5798,7 @@ PartitionSpec is the spec for volume partitioning.
|
||||
| grow | [bool](#bool) | | |
|
||||
| label | [string](#string) | | |
|
||||
| type_uuid | [string](#string) | | |
|
||||
| relative_max_size | [uint64](#uint64) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
@ -81,8 +81,10 @@ ProvisioningSpec describes how the volume is provisioned.
|
||||
|`minSize` |ByteSize |The minimum size of the volume.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
minSize: 2.5GiB
|
||||
{{< /highlight >}}</details> | |
|
||||
|`maxSize` |ByteSize |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
|`maxSize` |Size |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
maxSize: 50GiB
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
maxSize: 80%
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
@ -78,8 +78,10 @@ ProvisioningSpec describes how the volume is provisioned.
|
||||
|`minSize` |ByteSize |The minimum size of the volume.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
minSize: 2.5GiB
|
||||
{{< /highlight >}}</details> | |
|
||||
|`maxSize` |ByteSize |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
|`maxSize` |Size |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
maxSize: 50GiB
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
maxSize: 80%
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
@ -64,6 +64,7 @@ provisioning:
|
||||
|
||||
# # The maximum size of the volume, if not specified the volume can grow to the size of the
|
||||
# maxSize: 50GiB
|
||||
# maxSize: 80%
|
||||
# The filesystem describes how the volume is formatted.
|
||||
filesystem:
|
||||
type: xfs # Filesystem type. Default is `xfs`.
|
||||
@ -176,8 +177,10 @@ ProvisioningSpec describes how the volume is provisioned.
|
||||
|`minSize` |ByteSize |The minimum size of the volume.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
minSize: 2.5GiB
|
||||
{{< /highlight >}}</details> | |
|
||||
|`maxSize` |ByteSize |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
|`maxSize` |Size |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
maxSize: 50GiB
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
maxSize: 80%
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
@ -78,8 +78,10 @@ ProvisioningSpec describes how the volume is provisioned.
|
||||
|`minSize` |ByteSize |The minimum size of the volume.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
minSize: 2.5GiB
|
||||
{{< /highlight >}}</details> | |
|
||||
|`maxSize` |ByteSize |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes, but can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
|`maxSize` |Size |The maximum size of the volume, if not specified the volume can grow to the size of the<br>disk.<br><br>Size is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
maxSize: 50GiB
|
||||
{{< /highlight >}}{{< highlight yaml >}}
|
||||
maxSize: 80%
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
@ -313,9 +313,9 @@
|
||||
"maxSize": {
|
||||
"type": "string",
|
||||
"title": "maxSize",
|
||||
"description": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.\n",
|
||||
"markdownDescription": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\u003c/p\u003e\n\n\u003cp\u003eSize is specified in bytes, but can be expressed in human readable format, e.g. 100MB.\u003c/p\u003e\n"
|
||||
"description": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.\n",
|
||||
"markdownDescription": "The maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\n\nSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe maximum size of the volume, if not specified the volume can grow to the size of the\ndisk.\u003c/p\u003e\n\n\u003cp\u003eSize is specified in bytes or in percents. It can be expressed in human readable format, e.g. 100MB.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user