diff --git a/docs/data-sources/volume.md b/docs/data-sources/volume.md
index ed42ab3d..c7c0d9ce 100644
--- a/docs/data-sources/volume.md
+++ b/docs/data-sources/volume.md
@@ -47,16 +47,16 @@ data "netapp-ontap_volume" "storage_volume" {
- `nas` (Attributes) (see [below for nested schema](#nestedatt--nas))
- `qos_policy_group` (String) Specifies a QoS policy group to be set on volume
- `snaplock` (Attributes) (see [below for nested schema](#nestedatt--snaplock))
+- `snapshot_locking_enabled` (Boolean) Whether or not snapshot copy locking is enabled on the volume.
- `snapshot_policy` (String) The name of the snapshot policy
- `space` (Attributes) (see [below for nested schema](#nestedatt--space))
- `space_guarantee` (String) Space guarantee style for the volume
- `state` (String) Whether the specified volume is online, or not
+- `tags` (Set of String) Set of tags associated with the volume
- `tiering` (Attributes) (see [below for nested schema](#nestedatt--tiering))
- `type` (String) The volume type, either read-write (RW) or data-protection (DP)
-- `snapshot_locking_enabled` (Boolean) Whether or not snapshot copy locking is enabled on the volume
-
### Nested Schema for `aggregates`
Read-Only:
@@ -93,10 +93,11 @@ Read-Only:
Read-Only:
+- `compaction` (String) The system can be enabled/disabled compaction
- `compression` (String) Whether to enable compression for the volume (HDD and Flash Pool aggregates)
-- `policy_name` (String) Allows a storage efficiency policy to be set on volume creation
- `dedupe` (String) The system can be enabled/disabled dedupe
-- `compaction` (String) The system can be enabled/disabled compression
+- `policy_name` (String) Allows a storage efficiency policy to be set on volume creation
+
@@ -146,4 +147,5 @@ Read-Only:
Read-Only:
- `minimum_cooling_days` (Number) Determines how many days must pass before inactive data in a volume using the Auto or Snapshot-Only policy is considered cold and eligible for tiering
+- `object_tags` (Set of String) Object tags are applied to objects in tiered storage
- `policy_name` (String) The tiering policy that is to be associated with the volume
diff --git a/docs/data-sources/volumes.md b/docs/data-sources/volumes.md
index 50065592..79fd96fa 100644
--- a/docs/data-sources/volumes.md
+++ b/docs/data-sources/volumes.md
@@ -50,6 +50,9 @@ Optional:
- `name` (String) StorageVolume name
- `svm_name` (String) StorageVolume svm name
+- `tags` (String) StorageVolume tag value
+- `tiering_object_tags` (String) StorageVolume tiering object tag value
+
@@ -63,7 +66,7 @@ Required:
Read-Only:
-- `aggregates` (Attributes List) Aggregates the volume is on (see [below for nested schema](#nestedatt--aggregates))
+- `aggregates` (Attributes List) List of aggregates that the volume is on (see [below for nested schema](#nestedatt--storage_volumes--aggregates))
- `analytics` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--analytics))
- `autosize` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--autosize))
- `comment` (String) Sets a comment associated with the volume
@@ -74,10 +77,12 @@ Read-Only:
- `nas` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--nas))
- `qos_policy_group` (String) Specifies a QoS policy group to be set on volume
- `snaplock` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--snaplock))
+- `snapshot_locking_enabled` (Boolean) Whether or not snapshot copy locking is enabled on the volume.
- `snapshot_policy` (String) The name of the snapshot policy
- `space` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--space))
- `space_guarantee` (String) Space guarantee style for the volume
- `state` (String) Whether the specified volume is online, or not
+- `tags` (Set of String) Set of tags associated with the volume
- `tiering` (Attributes) (see [below for nested schema](#nestedatt--storage_volumes--tiering))
- `type` (String) The volume type, either read-write (RW) or data-protection (DP)
@@ -97,8 +102,8 @@ Read-Only:
- `state` (String) Set file system analytics state of the volume
-
+
### Nested Schema for `storage_volumes.autosize`
Read-Only:
@@ -107,9 +112,9 @@ Read-Only:
- `maximum` (Number) Maximum size up to which a volume grows automatically. This size cannot be less than the current volume size, or less than or equal to the minimum size of volume.
- `minimum` (Number) Minimum size up to which the volume shrinks automatically. This size cannot be greater than or equal to the maximum size of volume.
- `mode` (String) Autosize mode for the volume.
- grow - Volume automatically grows when the amount of used space is above the 'grow_threshold' value.
- grow_shrink - Volume grows or shrinks in response to the amount of space used.
- off - Autosizing of the volume is disabled.
+ grow - Volume automatically grows when the amount of used space is above the 'grow_threshold' value.
+ grow_shrink - Volume grows or shrinks in response to the amount of space used.
+ off - Autosizing of the volume is disabled.
- `shrink_threshold` (Number) Used space threshold size, in percentage, for the automatic shrinkage of the volume.
- `size_unit` (String) The unit used to interpret the minimum or maximum size parameters.
@@ -119,7 +124,9 @@ Read-Only:
Read-Only:
+- `compaction` (String) The system can be enabled/disabled compaction
- `compression` (String) Whether to enable compression for the volume (HDD and Flash Pool aggregates)
+- `dedupe` (String) The system can be enabled/disabled dedupe
- `policy_name` (String) Allows a storage efficiency policy to be set on volume creation
@@ -172,4 +179,5 @@ Read-Only:
Read-Only:
- `minimum_cooling_days` (Number) Determines how many days must pass before inactive data in a volume using the Auto or Snapshot-Only policy is considered cold and eligible for tiering
+- `object_tags` (Set of String) Object tags are applied to objects in tiered storage
- `policy_name` (String) The tiering policy that is to be associated with the volume
diff --git a/docs/resources/volume.md b/docs/resources/volume.md
index 02aa84f3..f7c80eef 100644
--- a/docs/resources/volume.md
+++ b/docs/resources/volume.md
@@ -78,7 +78,7 @@ resource "netapp-ontap_volume" "example" {
### Required
-- `aggregates` (Attributes List) Aggregates the volume is on (see [below for nested schema](#nestedatt--aggregates))
+- `aggregates` (Attributes Set) List of aggregates to place volume on (see [below for nested schema](#nestedatt--aggregates))
- `cx_profile_name` (String) Connection profile name
- `name` (String) The name of the volume to manage
- `space` (Attributes) (see [below for nested schema](#nestedatt--space))
@@ -95,19 +95,19 @@ resource "netapp-ontap_volume" "example" {
- `nas` (Attributes) (see [below for nested schema](#nestedatt--nas))
- `qos_policy_group` (String) Specifies a QoS policy group to be set on volume
- `snaplock` (Attributes) (see [below for nested schema](#nestedatt--snaplock))
+- `snapshot_locking_enabled` (Boolean) Whether or not snapshot copy locking is enabled on the volume.
- `snapshot_policy` (String) The name of the snapshot policy
- `space_guarantee` (String) Space guarantee style for the volume
- `state` (String) Whether the specified volume is online, or not
+- `tags` (Set of String) Set of tags associated with the volume
- `tiering` (Attributes) (see [below for nested schema](#nestedatt--tiering))
- `type` (String) The volume type, either read-write (RW) or data-protection (DP)
-- `snapshot_locking_enabled` (Boolean) Whether or not snapshot copy locking is enabled on the volume
### Read-Only
- `id` (String) Volume identifier
-
### Nested Schema for `aggregates`
Required:
@@ -167,10 +167,11 @@ Optional:
Optional:
+- `compaction` (String) The system can be enabled/disabled compaction
- `compression` (String) Whether to enable compression for the volume (HDD and Flash Pool aggregates)
-- `policy_name` (String) Allows a storage efficiency policy to be set on volume creation
- `dedupe` (String) The system can be enabled/disabled dedupe
-- `compaction` (String) The system can be enabled/disabled compression
+- `policy_name` (String) Allows a storage efficiency policy to be set on volume creation
+
@@ -200,6 +201,7 @@ Optional:
Optional:
- `minimum_cooling_days` (Number) Determines how many days must pass before inactive data in a volume using the Auto or Snapshot-Only policy is considered cold and eligible for tiering
+- `object_tags` (Set of String) Object tags are applied to objects in tiered storage
- `policy_name` (String) The tiering policy that is to be associated with the volume
## Import
diff --git a/internal/interfaces/storage_volume.go b/internal/interfaces/storage_volume.go
index e31bf675..d2f5997b 100644
--- a/internal/interfaces/storage_volume.go
+++ b/internal/interfaces/storage_volume.go
@@ -14,49 +14,51 @@ import (
// StorageVolumeGetDataModelONTAP describes the GET record data model using go types for mapping.
type StorageVolumeGetDataModelONTAP struct {
- Name string
- SVM svm
- Space Space
- State string
- Type string
- Comment string
- SpaceGuarantee Guarantee `mapstructure:"guarantee"`
- NAS NAS
- QOS QOS
- Encryption Encryption
- Efficiency Efficiency
- SnapshotPolicy SnapshotPolicy `mapstructure:"snapshot_policy,omitempty"`
- TieringPolicy TieringPolicy `mapstructure:"tiering,omitempty"`
- Snaplock Snaplock
- Analytics Analytics
- Language string
- Aggregates []Aggregate
- Autosize Autosize `mapstructure:"autosize,omitempty"`
- UUID string
- SnapshotLockingEnabled *bool `mapstructure:"snapshot_locking_enabled,omitempty"`
+ Name string
+ SVM svm
+ Space Space
+ State string
+ Type string
+ Comment string
+ SpaceGuarantee Guarantee `mapstructure:"guarantee"`
+ NAS NAS
+ QOS QOS
+ Encryption Encryption
+ Efficiency Efficiency
+ SnapshotPolicy SnapshotPolicy `mapstructure:"snapshot_policy,omitempty"`
+ TieringPolicy TieringPolicy `mapstructure:"tiering,omitempty"`
+ Snaplock Snaplock
+ Analytics Analytics
+ Language string
+ Aggregates []Aggregate
+ Autosize Autosize `mapstructure:"autosize,omitempty"`
+ UUID string
+ SnapshotLockingEnabled *bool `mapstructure:"snapshot_locking_enabled,omitempty"`
+ Tags []string `mapstructure:"_tags,omitempty"`
}
// StorageVolumeResourceModel describes the resource data model.
type StorageVolumeResourceModel struct {
- Name string `mapstructure:"name,omitempty"`
- SVM svm `mapstructure:"svm,omitempty"`
- Space Space `mapstructure:"space,omitempty"`
- State string `mapstructure:"state,omitempty"`
- Type string `mapstructure:"type,omitempty"`
- Comment string `mapstructure:"comment,omitempty"`
- SpaceGuarantee Guarantee `mapstructure:"guarantee,omitempty"`
- NAS NAS `mapstructure:"nas,omitempty"`
- QOS QOS `mapstructure:"qos,omitempty"`
- Encryption Encryption `mapstructure:"encryption,omitempty"`
- Efficiency Efficiency `mapstructure:"efficiency,omitempty"`
- SnapshotPolicy SnapshotPolicy `mapstructure:"snapshot_policy,omitempty"`
- TieringPolicy TieringPolicy `mapstructure:"tiering,omitempty"`
- Snaplock Snaplock `mapstructure:"snaplock,omitempty"`
- Analytics Analytics `mapstructure:"analytics,omitempty"`
- Language string `mapstructure:"language,omitempty"`
- Aggregates []map[string]interface{} `mapstructure:"aggregates,omitempty"`
- Autosize Autosize `mapstructure:"autosize,omitempty"`
- SnapshotLockingEnabled *bool `mapstructure:"snapshot_locking_enabled,omitempty"`
+ Name string `mapstructure:"name,omitempty"`
+ SVM svm `mapstructure:"svm,omitempty"`
+ Space Space `mapstructure:"space,omitempty"`
+ State string `mapstructure:"state,omitempty"`
+ Type string `mapstructure:"type,omitempty"`
+ Comment string `mapstructure:"comment,omitempty"`
+ SpaceGuarantee Guarantee `mapstructure:"guarantee,omitempty"`
+ NAS NAS `mapstructure:"nas,omitempty"`
+ QOS QOS `mapstructure:"qos,omitempty"`
+ Encryption Encryption `mapstructure:"encryption,omitempty"`
+ Efficiency Efficiency `mapstructure:"efficiency,omitempty"`
+ SnapshotPolicy SnapshotPolicy `mapstructure:"snapshot_policy,omitempty"`
+ TieringPolicy TieringPolicy `mapstructure:"tiering,omitempty"`
+ Snaplock Snaplock `mapstructure:"snaplock,omitempty"`
+ Analytics Analytics `mapstructure:"analytics,omitempty"`
+ Language string `mapstructure:"language,omitempty"`
+ Aggregates []map[string]interface{} `mapstructure:"aggregates,omitempty"`
+ Autosize Autosize `mapstructure:"autosize,omitempty"`
+ SnapshotLockingEnabled *bool `mapstructure:"snapshot_locking_enabled,omitempty"`
+ Tags []string `mapstructure:"tags,omitempty"`
}
// Aggregate describes the resource data model.
@@ -102,8 +104,9 @@ type Policy struct {
// TieringPolicy describes the resource data model.
type TieringPolicy struct {
- Policy string `mapstructure:"policy,omitempty"`
- MinCoolingDays int `mapstructure:"min_cooling_days,omitempty"`
+ Policy string `mapstructure:"policy,omitempty"`
+ MinCoolingDays int `mapstructure:"min_cooling_days,omitempty"`
+ ObjectTags []string `mapstructure:"object_tags,omitempty"`
}
// Snapshot describes the resource data model.
@@ -190,8 +193,10 @@ var POW2BYTEMAP = map[string]int{
// StorageVolumeDataSourceFilterModel describes the data source data model for queries.
type StorageVolumeDataSourceFilterModel struct {
- Name string `mapstructure:"name"`
- SVMName string `mapstructure:"svm.name"`
+ Name string `mapstructure:"name"`
+ SVMName string `mapstructure:"svm.name"`
+ Tags string `mapstructure:"_tags"`
+ TieringObjectTags string `mapstructure:"tiering.object_tags"`
}
// GetUUIDVolumeByName get a volumes UUID by volume name
@@ -226,7 +231,7 @@ func GetStorageVolume(errorHandler *utils.ErrorHandler, r restclient.RestClient,
query := r.NewQuery()
query.Fields([]string{"name", "svm.name", "aggregates", "space.size", "state", "type", "nas.export_policy.name", "nas.path", "guarantee.type", "space.snapshot.reserve_percent", "efficiency.dedupe", "efficiency.compaction",
"nas.security_style", "encryption.enabled", "efficiency.policy.name", "nas.unix_permissions", "nas.gid", "nas.uid", "snapshot_policy.name", "language", "qos.policy.name", "snapshot_locking_enabled",
- "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize"})
+ "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "tiering.object_tags", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize", "_tags"})
statusCode, response, err := r.GetNilOrOneRecord("storage/volumes/"+uuid, query, nil)
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading volume info", fmt.Sprintf("error on GET storage/volumes: %s", err))
@@ -251,7 +256,7 @@ func GetStorageVolumeByName(errorHandler *utils.ErrorHandler, r restclient.RestC
query.Add("return_records", "true")
query.Fields([]string{"name", "uuid", "svm.name", "aggregates", "space.size", "state", "type", "nas.export_policy.name", "nas.path", "guarantee.type", "space.snapshot.reserve_percent", "efficiency.dedupe", "efficiency.compaction",
"nas.security_style", "encryption.enabled", "efficiency.policy.name", "nas.unix_permissions", "nas.gid", "nas.uid", "snapshot_policy.name", "language", "qos.policy.name", "snapshot_locking_enabled",
- "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize"})
+ "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "tiering.object_tags", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize", "_tags"})
statusCode, response, err := r.GetNilOrOneRecord("storage/volumes", query, nil)
if err != nil {
return nil, errorHandler.MakeAndReportError("error reading volume info by name", fmt.Sprintf("error on GET storage/volumes: %s", err))
@@ -278,7 +283,7 @@ func GetStorageVolumes(errorHandler *utils.ErrorHandler, r restclient.RestClient
query := r.NewQuery()
query.Fields([]string{"name", "svm.name", "aggregates", "space.size", "state", "type", "nas.export_policy.name", "nas.path", "guarantee.type", "space.snapshot.reserve_percent", "efficiency.dedupe", "efficiency.compaction",
"nas.security_style", "encryption.enabled", "efficiency.policy.name", "nas.unix_permissions", "nas.gid", "nas.uid", "snapshot_policy.name", "language", "qos.policy.name", "snapshot_locking_enabled",
- "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize"})
+ "tiering.policy", "comment", "efficiency.compression", "tiering.min_cooling_days", "tiering.object_tags", "space.logical_space.enforcement", "space.logical_space.reporting", "snaplock.type", "analytics.state", "autosize", "_tags"})
if filter != nil {
var filterMap map[string]interface{}
diff --git a/internal/provider/storage/storage_volume_data_source.go b/internal/provider/storage/storage_volume_data_source.go
index 6a673088..6f6d1e8d 100644
--- a/internal/provider/storage/storage_volume_data_source.go
+++ b/internal/provider/storage/storage_volume_data_source.go
@@ -3,7 +3,6 @@ package storage
import (
"context"
"fmt"
-
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -41,27 +40,28 @@ type StorageVolumeDataSource struct {
// StorageVolumeDataSourceModel describes the data source data model.
type StorageVolumeDataSourceModel struct {
- CxProfileName types.String `tfsdk:"cx_profile_name"`
- Name types.String `tfsdk:"name"`
- SVMName types.String `tfsdk:"svm_name"`
- State types.String `tfsdk:"state"`
- Type types.String `tfsdk:"type"`
- SpaceGuarantee types.String `tfsdk:"space_guarantee"`
- Encrypt types.Bool `tfsdk:"encryption"`
- SnapshotPolicy types.String `tfsdk:"snapshot_policy"`
- Language types.String `tfsdk:"language"`
- QOSPolicyGroup types.String `tfsdk:"qos_policy_group"`
- Comment types.String `tfsdk:"comment"`
- Aggregates []StorageVolumeDataSourceAggregates `tfsdk:"aggregates"`
- ID types.String `tfsdk:"id"`
- Space *StorageVolumeDataSourceSpace `tfsdk:"space"`
- Nas *StorageVolumeDataSourceNas `tfsdk:"nas"`
- Tiering *StorageVolumeDataSourceTiering `tfsdk:"tiering"`
- Efficiency *StorageVolumeDataSourceEfficiency `tfsdk:"efficiency"`
- SnapLock *StorageVolumeDataSourceSnapLock `tfsdk:"snaplock"`
- Analytics *StorageVolumeDataSourceAnalytics `tfsdk:"analytics"`
- Autosize *StorageVolumeDataSourceAutosize `tfsdk:"autosize"`
- SnapshotLockingEnabled types.Bool `tfsdk:"snapshot_locking_enabled"`
+ CxProfileName types.String `tfsdk:"cx_profile_name"`
+ Name types.String `tfsdk:"name"`
+ SVMName types.String `tfsdk:"svm_name"`
+ State types.String `tfsdk:"state"`
+ Type types.String `tfsdk:"type"`
+ SpaceGuarantee types.String `tfsdk:"space_guarantee"`
+ Encrypt types.Bool `tfsdk:"encryption"`
+ SnapshotPolicy types.String `tfsdk:"snapshot_policy"`
+ Language types.String `tfsdk:"language"`
+ QOSPolicyGroup types.String `tfsdk:"qos_policy_group"`
+ Comment types.String `tfsdk:"comment"`
+ Aggregates []StorageVolumeDataSourceAggregates `tfsdk:"aggregates"`
+ ID types.String `tfsdk:"id"`
+ Space *StorageVolumeDataSourceSpace `tfsdk:"space"`
+ Nas *StorageVolumeDataSourceNas `tfsdk:"nas"`
+ Tiering *StorageVolumeDataSourceTiering `tfsdk:"tiering"`
+ Efficiency *StorageVolumeDataSourceEfficiency `tfsdk:"efficiency"`
+ SnapLock *StorageVolumeDataSourceSnapLock `tfsdk:"snaplock"`
+ Analytics *StorageVolumeDataSourceAnalytics `tfsdk:"analytics"`
+ Autosize *StorageVolumeDataSourceAutosize `tfsdk:"autosize"`
+ SnapshotLockingEnabled types.Bool `tfsdk:"snapshot_locking_enabled"`
+ Tags types.Set `tfsdk:"tags"`
}
// StorageVolumeDataSourceAggregates describes the analytics model.
@@ -91,6 +91,7 @@ type StorageVolumeDataSourceEfficiency struct {
type StorageVolumeDataSourceTiering struct {
Policy types.String `tfsdk:"policy_name"`
MinimumCoolingDays types.Int64 `tfsdk:"minimum_cooling_days"`
+ ObjectTags types.Set `tfsdk:"object_tags"`
}
// StorageVolumeDataSourceNas describes the Nas model.
@@ -266,6 +267,11 @@ func (d *StorageVolumeDataSource) Schema(ctx context.Context, req datasource.Sch
MarkdownDescription: "Determines how many days must pass before inactive data in a volume using the Auto or Snapshot-Only policy is considered cold and eligible for tiering",
Computed: true,
},
+ "object_tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Object tags are applied to objects in tiered storage",
+ Computed: true,
+ },
},
},
"efficiency": schema.SingleNestedAttribute{
@@ -350,6 +356,11 @@ func (d *StorageVolumeDataSource) Schema(ctx context.Context, req datasource.Sch
MarkdownDescription: "Whether or not snapshot copy locking is enabled on the volume.",
Computed: true,
},
+ "tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Set of tags associated with the volume",
+ Computed: true,
+ },
},
}
}
@@ -417,9 +428,15 @@ func (d *StorageVolumeDataSource) Read(ctx context.Context, req datasource.ReadR
SecurityStyle: types.StringValue(volume.NAS.SecurityStyle),
UnixPermissions: types.Int64Value(int64(volume.NAS.UnixPermissions)),
}
+ objectTagsSet, diags := stringSliceToSet(ctx, volume.TieringPolicy.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
data.Tiering = &StorageVolumeDataSourceTiering{
Policy: types.StringValue(volume.TieringPolicy.Policy),
MinimumCoolingDays: types.Int64Value(int64(volume.TieringPolicy.MinCoolingDays)),
+ ObjectTags: objectTagsSet,
}
data.Efficiency = &StorageVolumeDataSourceEfficiency{
Policy: types.StringValue(volume.Efficiency.Policy.Name),
@@ -446,6 +463,12 @@ func (d *StorageVolumeDataSource) Read(ctx context.Context, req datasource.ReadR
Mode: types.StringValue(volume.Autosize.Mode),
}
tflog.Debug(ctx, fmt.Sprintf("autosize info compiled: %#v", data.Autosize))
+ tagsSet, diags := stringSliceToSet(ctx, volume.Tags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ data.Tags = tagsSet
data.ID = types.StringValue(volume.UUID)
// Write logs using the tflog package
diff --git a/internal/provider/storage/storage_volume_resource.go b/internal/provider/storage/storage_volume_resource.go
index 977a2140..852aace8 100644
--- a/internal/provider/storage/storage_volume_resource.go
+++ b/internal/provider/storage/storage_volume_resource.go
@@ -20,6 +20,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
@@ -54,6 +55,36 @@ func NewStorageVolumeResourceAlias() resource.Resource {
}
}
+// stringSliceToSet converts a slice of strings to a types.Set
+func stringSliceToSet(ctx context.Context, strings []string) (types.Set, diag.Diagnostics) {
+ var diags diag.Diagnostics
+
+ if len(strings) > 0 {
+ stringValues := make([]attr.Value, len(strings))
+ for i, s := range strings {
+ stringValues[i] = types.StringValue(s)
+ }
+ stringsSet, setDiags := types.SetValue(types.StringType, stringValues)
+ diags.Append(setDiags...)
+ return stringsSet, diags
+ }
+
+ return types.SetNull(types.StringType), diags
+}
+
+// setToStringSlice converts a types.Set to a slice of strings
+func setToStringSlice(ctx context.Context, set types.Set) ([]string, diag.Diagnostics) {
+ var diags diag.Diagnostics
+ var stringSlice []string
+
+ if !set.IsUnknown() && !set.IsNull() {
+ setDiags := set.ElementsAs(ctx, &stringSlice, false)
+ diags.Append(setDiags...)
+ }
+
+ return stringSlice, diags
+}
+
// StorageVolumeResource defines the resource implementation.
type StorageVolumeResource struct {
config connection.ResourceOrDataSourceConfig
@@ -61,27 +92,28 @@ type StorageVolumeResource struct {
// StorageVolumeResourceModel describes the resource data model.
type StorageVolumeResourceModel struct {
- CxProfileName types.String `tfsdk:"cx_profile_name"`
- Name types.String `tfsdk:"name"`
- SVMName types.String `tfsdk:"svm_name"`
- State types.String `tfsdk:"state"`
- Type types.String `tfsdk:"type"`
- SpaceGuarantee types.String `tfsdk:"space_guarantee"`
- Encrypt types.Bool `tfsdk:"encryption"`
- SnapshotPolicy types.String `tfsdk:"snapshot_policy"`
- Language types.String `tfsdk:"language"`
- QOSPolicyGroup types.String `tfsdk:"qos_policy_group"`
- Comment types.String `tfsdk:"comment"`
- Aggregates []StorageVolumeResourceAggregates `tfsdk:"aggregates"`
- ID types.String `tfsdk:"id"`
- Space types.Object `tfsdk:"space"`
- Nas types.Object `tfsdk:"nas"`
- Tiering types.Object `tfsdk:"tiering"`
- Efficiency types.Object `tfsdk:"efficiency"`
- SnapLock types.Object `tfsdk:"snaplock"`
- Analytics types.Object `tfsdk:"analytics"`
- Autosize types.Object `tfsdk:"autosize"`
- SnapshotLockingEnabled types.Bool `tfsdk:"snapshot_locking_enabled"`
+ CxProfileName types.String `tfsdk:"cx_profile_name"`
+ Name types.String `tfsdk:"name"`
+ SVMName types.String `tfsdk:"svm_name"`
+ State types.String `tfsdk:"state"`
+ Type types.String `tfsdk:"type"`
+ SpaceGuarantee types.String `tfsdk:"space_guarantee"`
+ Encrypt types.Bool `tfsdk:"encryption"`
+ SnapshotPolicy types.String `tfsdk:"snapshot_policy"`
+ Language types.String `tfsdk:"language"`
+ QOSPolicyGroup types.String `tfsdk:"qos_policy_group"`
+ Comment types.String `tfsdk:"comment"`
+ Aggregates []StorageVolumeResourceAggregates `tfsdk:"aggregates"`
+ ID types.String `tfsdk:"id"`
+ Space types.Object `tfsdk:"space"`
+ Nas types.Object `tfsdk:"nas"`
+ Tiering types.Object `tfsdk:"tiering"`
+ Efficiency types.Object `tfsdk:"efficiency"`
+ SnapLock types.Object `tfsdk:"snaplock"`
+ Analytics types.Object `tfsdk:"analytics"`
+ Autosize types.Object `tfsdk:"autosize"`
+ SnapshotLockingEnabled types.Bool `tfsdk:"snapshot_locking_enabled"`
+ Tags types.Set `tfsdk:"tags"`
}
// StorageVolumeResourceAggregates describes the analytics model.
@@ -111,6 +143,7 @@ type StorageVolumeResourceEfficiency struct {
type StorageVolumeResourceTiering struct {
Policy types.String `tfsdk:"policy_name"`
MinimumCoolingDays types.Int64 `tfsdk:"minimum_cooling_days"`
+ ObjectTags types.Set `tfsdk:"object_tags"`
}
// StorageVolumeResourceNas describes the Nas model.
@@ -381,6 +414,15 @@ func (r *StorageVolumeResource) Schema(ctx context.Context, req resource.SchemaR
int64planmodifier.UseStateForUnknown(),
},
},
+ "object_tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Object tags are applied to objects in tiered storage",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Set{
+ setplanmodifier.UseStateForUnknown(),
+ },
+ },
},
},
"efficiency": schema.SingleNestedAttribute{
@@ -538,6 +580,15 @@ func (r *StorageVolumeResource) Schema(ctx context.Context, req resource.SchemaR
},
},
},
+ "tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Set of tags associated with the volume",
+ Optional: true,
+ Computed: true,
+ PlanModifiers: []planmodifier.Set{
+ setplanmodifier.UseStateForUnknown(),
+ },
+ },
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: "Volume identifier",
@@ -627,7 +678,7 @@ func (r *StorageVolumeResource) Read(ctx context.Context, req resource.ReadReque
data.ID = types.StringValue(response.UUID)
} else {
response, err = interfaces.GetStorageVolume(errorHandler, *client, data.ID.ValueString())
-
+
if err != nil {
return
}
@@ -652,11 +703,11 @@ func (r *StorageVolumeResource) Read(ctx context.Context, req resource.ReadReque
"reporting": types.BoolType,
"enforcement": types.BoolType,
}
- nestedEslements := map[string]attr.Value{
+ nestedElements := map[string]attr.Value{
"reporting": types.BoolValue(response.Space.LogicalSpace.Reporting),
"enforcement": types.BoolValue(response.Space.LogicalSpace.Enforcement),
}
- logicalObjectValue, _ := types.ObjectValue(nestedElementTypes, nestedEslements)
+ logicalObjectValue, _ := types.ObjectValue(nestedElementTypes, nestedElements)
elementTypes := map[string]attr.Type{
"size": types.Int64Type,
"size_unit": types.StringType,
@@ -733,10 +784,16 @@ func (r *StorageVolumeResource) Read(ctx context.Context, req resource.ReadReque
elementTypes = map[string]attr.Type{
"minimum_cooling_days": types.Int64Type,
"policy_name": types.StringType,
+ "object_tags": types.SetType{ElemType: types.StringType},
+ }
+ objectTagsSet, diags := stringSliceToSet(ctx, response.TieringPolicy.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
}
elements = map[string]attr.Value{
"minimum_cooling_days": types.Int64Value(int64(response.TieringPolicy.MinCoolingDays)),
"policy_name": types.StringValue(response.TieringPolicy.Policy),
+ "object_tags": objectTagsSet,
}
objectValue, diags = types.ObjectValue(elementTypes, elements)
if diags.HasError() {
@@ -832,6 +889,14 @@ func (r *StorageVolumeResource) Read(ctx context.Context, req resource.ReadReque
}
data.Autosize = objectValue
+ // Tags
+ tagsSet, diags := stringSliceToSet(ctx, response.Tags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ data.Tags = tagsSet
+
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
@@ -992,6 +1057,12 @@ func (r *StorageVolumeResource) Create(ctx context.Context, req resource.CreateR
if !tiering.MinimumCoolingDays.IsUnknown() {
request.TieringPolicy.MinCoolingDays = int(tiering.MinimumCoolingDays.ValueInt64())
}
+ objectTags, diags := setToStringSlice(ctx, tiering.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ request.TieringPolicy.ObjectTags = objectTags
}
if !data.SnapLock.IsUnknown() {
@@ -1040,6 +1111,15 @@ func (r *StorageVolumeResource) Create(ctx context.Context, req resource.CreateR
}
}
+ if !data.Tags.IsUnknown() && !data.Tags.IsNull() {
+ tags, diags := setToStringSlice(ctx, data.Tags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ request.Tags = tags
+ }
+
if resp.Diagnostics.HasError() {
return
}
@@ -1139,10 +1219,16 @@ func (r *StorageVolumeResource) Create(ctx context.Context, req resource.CreateR
elementTypes = map[string]attr.Type{
"minimum_cooling_days": types.Int64Type,
"policy_name": types.StringType,
+ "object_tags": types.SetType{ElemType: types.StringType},
+ }
+ objectTagsSet, diags := stringSliceToSet(ctx, response.TieringPolicy.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
}
elements = map[string]attr.Value{
"minimum_cooling_days": types.Int64Value(int64(response.TieringPolicy.MinCoolingDays)),
"policy_name": types.StringValue(response.TieringPolicy.Policy),
+ "object_tags": objectTagsSet,
}
objectValue, diags = types.ObjectValue(elementTypes, elements)
if diags.HasError() {
@@ -1371,6 +1457,12 @@ func (r *StorageVolumeResource) Update(ctx context.Context, req resource.UpdateR
}
request.TieringPolicy.Policy = tiering.Policy.ValueString()
request.TieringPolicy.MinCoolingDays = int(tiering.MinimumCoolingDays.ValueInt64())
+ objectTags, diags := setToStringSlice(ctx, tiering.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ request.TieringPolicy.ObjectTags = objectTags
}
if !plan.SnapLock.Equal(state.SnapLock) {
@@ -1408,6 +1500,15 @@ func (r *StorageVolumeResource) Update(ctx context.Context, req resource.UpdateR
request.Autosize.Mode = autosize.Mode.ValueString()
}
+ if !plan.Tags.Equal(state.Tags) {
+ tags, diags := setToStringSlice(ctx, plan.Tags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+ request.Tags = tags
+ }
+
ignoreOptions := []string{}
if ignoreEncrption {
ignoreOptions = append(ignoreOptions, "encryption")
@@ -1600,14 +1701,21 @@ func readVolume(ctx context.Context, client *restclient.RestClient, data *Storag
}
data.Efficiency = objectValue
- //Tiering
+ // Tiering
elementTypes = map[string]attr.Type{
"minimum_cooling_days": types.Int64Type,
"policy_name": types.StringType,
+ "object_tags": types.SetType{ElemType: types.StringType},
+ }
+ // Convert object tags to types.List
+ objectTagsSet, diags := stringSliceToSet(ctx, response.TieringPolicy.ObjectTags)
+ if diags.HasError() {
+ allDiags.Append(diags...)
}
elements = map[string]attr.Value{
"minimum_cooling_days": types.Int64Value(int64(response.TieringPolicy.MinCoolingDays)),
"policy_name": types.StringValue(response.TieringPolicy.Policy),
+ "object_tags": objectTagsSet,
}
objectValue, diags = types.ObjectValue(elementTypes, elements)
if diags.HasError() {
@@ -1685,5 +1793,12 @@ func readVolume(ctx context.Context, client *restclient.RestClient, data *Storag
}
data.Autosize = objectValue
+ tagsSet, diags := stringSliceToSet(ctx, response.Tags)
+ if diags.HasError() {
+ allDiags.Append(diags...)
+ return allDiags
+ }
+ data.Tags = tagsSet
+
return allDiags
}
diff --git a/internal/provider/storage/storage_volumes_data_source.go b/internal/provider/storage/storage_volumes_data_source.go
index 49746a64..3a7c8dbd 100644
--- a/internal/provider/storage/storage_volumes_data_source.go
+++ b/internal/provider/storage/storage_volumes_data_source.go
@@ -48,8 +48,10 @@ type StorageVolumesDataSourceModel struct {
// StorageVolumeDataSourceFilterModel describes the data source data model for queries.
type StorageVolumeDataSourceFilterModel struct {
- Name types.String `tfsdk:"name"`
- SVMName types.String `tfsdk:"svm_name"`
+ Name types.String `tfsdk:"name"`
+ SVMName types.String `tfsdk:"svm_name"`
+ TieringObjectTags types.String `tfsdk:"tiering_object_tags"`
+ Tags types.String `tfsdk:"tags"`
}
// Metadata returns the data source type name.
@@ -78,6 +80,14 @@ func (d *StorageVolumesDataSource) Schema(ctx context.Context, req datasource.Sc
MarkdownDescription: "StorageVolume svm name",
Optional: true,
},
+ "tags": schema.StringAttribute{
+ MarkdownDescription: "StorageVolume tag value",
+ Optional: true,
+ },
+ "tiering_object_tags": schema.StringAttribute{
+ MarkdownDescription: "StorageVolume tiering object tag value",
+ Optional: true,
+ },
},
Optional: true,
},
@@ -211,6 +221,11 @@ func (d *StorageVolumesDataSource) Schema(ctx context.Context, req datasource.Sc
MarkdownDescription: "Determines how many days must pass before inactive data in a volume using the Auto or Snapshot-Only policy is considered cold and eligible for tiering",
Computed: true,
},
+ "object_tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Object tags are applied to objects in tiered storage",
+ Computed: true,
+ },
},
},
"efficiency": schema.SingleNestedAttribute{
@@ -291,6 +306,11 @@ func (d *StorageVolumesDataSource) Schema(ctx context.Context, req datasource.Sc
Computed: true,
MarkdownDescription: "Volume identifier",
},
+ "tags": schema.SetAttribute{
+ ElementType: types.StringType,
+ MarkdownDescription: "Set of tags associated with the volume",
+ Computed: true,
+ },
},
},
Computed: true,
@@ -338,8 +358,10 @@ func (d *StorageVolumesDataSource) Read(ctx context.Context, req datasource.Read
var filter *interfaces.StorageVolumeDataSourceFilterModel = nil
if data.Filter != nil {
filter = &interfaces.StorageVolumeDataSourceFilterModel{
- Name: data.Filter.Name.ValueString(),
- SVMName: data.Filter.SVMName.ValueString(),
+ Name: data.Filter.Name.ValueString(),
+ SVMName: data.Filter.SVMName.ValueString(),
+ Tags: data.Filter.Tags.ValueString(),
+ TieringObjectTags: data.Filter.TieringObjectTags.ValueString(),
}
}
restInfo, err := interfaces.GetStorageVolumes(errorHandler, *client, filter)
@@ -358,6 +380,18 @@ func (d *StorageVolumesDataSource) Read(ctx context.Context, req datasource.Read
aggregates[i].Name = types.StringValue(v.Name)
}
+ objectTagsSet, diags := stringSliceToSet(ctx, record.TieringPolicy.ObjectTags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+
+ tagsSet, diags := stringSliceToSet(ctx, record.Tags)
+ if diags.HasError() {
+ resp.Diagnostics.Append(diags...)
+ return
+ }
+
data.StorageVolumes[index] = StorageVolumeDataSourceModel{
CxProfileName: types.String(data.CxProfileName),
Name: types.StringValue(record.Name),
@@ -391,6 +425,7 @@ func (d *StorageVolumesDataSource) Read(ctx context.Context, req datasource.Read
Tiering: &StorageVolumeDataSourceTiering{
Policy: types.StringValue(record.TieringPolicy.Policy),
MinimumCoolingDays: types.Int64Value(int64(record.TieringPolicy.MinCoolingDays)),
+ ObjectTags: objectTagsSet,
},
Efficiency: &StorageVolumeDataSourceEfficiency{
Policy: types.StringValue(record.Efficiency.Policy.Name),
@@ -412,7 +447,8 @@ func (d *StorageVolumesDataSource) Read(ctx context.Context, req datasource.Read
GrowThreshold: types.Int64Value(int64(record.Autosize.GrowThreshold)),
Mode: types.StringValue(record.Autosize.Mode),
},
- ID: types.StringValue(record.UUID),
+ ID: types.StringValue(record.UUID),
+ Tags: tagsSet,
}
}