From 3a492b5ec5a0dc3c0397eb6cb53dfe22c99522de Mon Sep 17 00:00:00 2001 From: Ujjwal Kumar Date: Tue, 1 Oct 2024 11:04:29 +0530 Subject: [PATCH] Added support for sdp profiles in is_volume --- go.mod | 2 +- go.sum | 4 +- ibm/flex/structures.go | 6 +- ibm/service/vpc/data_source_ibm_is_volume.go | 26 + .../vpc/data_source_ibm_is_volume_profile.go | 528 +++++++++++++++++- .../vpc/data_source_ibm_is_volume_profiles.go | 488 +++++++++++++++- ibm/service/vpc/data_source_ibm_is_volumes.go | 21 + ibm/service/vpc/resource_ibm_is_instance.go | 13 +- ...ource_ibm_is_instance_volume_attachment.go | 41 +- ibm/service/vpc/resource_ibm_is_volume.go | 100 ++-- scripts/build.sh | 5 +- website/docs/d/is_volume.html.markdown | 4 + .../docs/d/is_volume_profile.html.markdown | 9 + .../docs/d/is_volume_profiles.html.markdown | 8 + website/docs/d/is_volumes.html.markdown | 2 + website/docs/r/is_volume.html.markdown | 2 + 16 files changed, 1164 insertions(+), 95 deletions(-) diff --git a/go.mod b/go.mod index f9c9d77238..d4d579cef4 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,7 @@ require ( github.com/IBM/secrets-manager-go-sdk/v2 v2.0.7 github.com/IBM/vmware-go-sdk v0.1.2 github.com/IBM/vpc-beta-go-sdk v0.6.0 - github.com/IBM/vpc-go-sdk v0.58.0 + github.com/IBM/vpc-go-sdk v0.59.0 github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5 github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 github.com/akamai/AkamaiOPEN-edgegrid-golang/v5 v5.0.0 diff --git a/go.sum b/go.sum index 9fd3b8e9e9..5ddf018eb0 100644 --- a/go.sum +++ b/go.sum @@ -194,8 +194,8 @@ github.com/IBM/vmware-go-sdk v0.1.2 h1:5lKWFyInWz9e2hwGsoFTEoLa1jYkD30SReN0fQ10w github.com/IBM/vmware-go-sdk v0.1.2/go.mod h1:2UGPBJju3jiv5VKKBBm9a5L6bzF/aJdKOKAzJ7HaOjA= github.com/IBM/vpc-beta-go-sdk v0.6.0 h1:wfM3AcW3zOM3xsRtZ+EA6+sESlGUjQ6Yf4n5QQyz4uc= github.com/IBM/vpc-beta-go-sdk v0.6.0/go.mod h1:fzHDAQIqH/5yJmYsKodKHLcqxMDT+yfH6vZjdiw8CQA= -github.com/IBM/vpc-go-sdk v0.58.0 h1:Slk1jkcV7tPnf0iECQV2Oja7W8Bom0z7k9M4fMBY4bI= -github.com/IBM/vpc-go-sdk v0.58.0/go.mod h1:swmxiYLT+OfBsBYqJWGeRd6NPmBk4u/het2PZdtzIaw= +github.com/IBM/vpc-go-sdk v0.59.0 h1:1la2LeYy7d2Ea8D5wM9PFFPfqpXn4t2SqJcO27oNA98= +github.com/IBM/vpc-go-sdk v0.59.0/go.mod h1:swmxiYLT+OfBsBYqJWGeRd6NPmBk4u/het2PZdtzIaw= github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E= github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc= github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0= diff --git a/ibm/flex/structures.go b/ibm/flex/structures.go index 1164864179..c1a4deb5f8 100644 --- a/ibm/flex/structures.go +++ b/ibm/flex/structures.go @@ -3023,11 +3023,11 @@ func ResourceVolumeValidate(diff *schema.ResourceDiff) error { } } - if profile != "custom" { + if profile != "custom" && profile != "sdp" { if iops != 0 && diff.NewValueKnown("iops") && diff.HasChange("iops") { - return fmt.Errorf("VolumeError : iops is applicable for only custom volume profiles") + return fmt.Errorf("VolumeError : iops is applicable for only custom/sdp volume profiles") } - } else { + } else if profile != "sdp" { if capacity == 0 { capacity = int64(100) } diff --git a/ibm/service/vpc/data_source_ibm_is_volume.go b/ibm/service/vpc/data_source_ibm_is_volume.go index 95af9adeab..fcf7761b68 100644 --- a/ibm/service/vpc/data_source_ibm_is_volume.go +++ b/ibm/service/vpc/data_source_ibm_is_volume.go @@ -37,6 +37,23 @@ func DataSourceIBMISVolume() *schema.Resource { Computed: true, Description: "Indicates whether a running virtual server instance has an attachment to this volume.", }, + // acadia changes + "adjustable_capacity_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable capacity for this volume.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "adjustable_iops_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable IOPS for this volume.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, isVolumeAttachmentState: { Type: schema.TypeString, Computed: true, @@ -467,6 +484,15 @@ func volumeGet(d *schema.ResourceData, meta interface{}, name string) error { if vol.HealthState != nil { d.Set(isVolumeHealthState, *vol.HealthState) } + + if err = d.Set("adjustable_capacity_states", vol.AdjustableCapacityStates); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting adjustable_capacity_states: %s", err), "(Data) ibm_is_volume", "read", "set-adjustable_capacity_states") + } + + if err = d.Set("adjustable_iops_states", vol.AdjustableIopsStates); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting adjustable_iops_states: %s", err), "(Data) ibm_is_volume", "read", "set-adjustable_iops_states") + } + return nil } diff --git a/ibm/service/vpc/data_source_ibm_is_volume_profile.go b/ibm/service/vpc/data_source_ibm_is_volume_profile.go index 26dab62937..bbc246874a 100644 --- a/ibm/service/vpc/data_source_ibm_is_volume_profile.go +++ b/ibm/service/vpc/data_source_ibm_is_volume_profile.go @@ -4,7 +4,13 @@ package vpc import ( + "context" + "fmt" + "log" + + "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -15,7 +21,7 @@ const ( func DataSourceIBMISVolumeProfile() *schema.Resource { return &schema.Resource{ - Read: dataSourceIBMISVolumeProfileRead, + ReadContext: dataSourceIBMISVolumeProfileRead, Schema: map[string]*schema.Schema{ @@ -24,17 +30,202 @@ func DataSourceIBMISVolumeProfile() *schema.Resource { Required: true, Description: "Volume profile name", }, - - isVolumeProfileFamily: { + "boot_capacity": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "capacity": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "family": &schema.Schema{ Type: schema.TypeString, Computed: true, - Description: "Volume profile family", + Description: "The product family this volume profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this volume profile.", + }, + "iops": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + //acadia changes + "adjustable_capacity_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable capacity for a volume with this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "adjustable_iops_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable IOPS for a volume with this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, }, }, } } -func dataSourceIBMISVolumeProfileRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceIBMISVolumeProfileRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { name := d.Get(isVolumeProfile).(string) @@ -45,21 +236,334 @@ func dataSourceIBMISVolumeProfileRead(d *schema.ResourceData, meta interface{}) return nil } -func volumeProfileGet(d *schema.ResourceData, meta interface{}, name string) error { +func volumeProfileGet(d *schema.ResourceData, meta interface{}, name string) diag.Diagnostics { sess, err := vpcClient(meta) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } getVolumeProfileOptions := &vpcv1.GetVolumeProfileOptions{ Name: &name, } - profile, _, err := sess.GetVolumeProfile(getVolumeProfileOptions) + volumeProfile, _, err := sess.GetVolumeProfile(getVolumeProfileOptions) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("GetVolumeProfileWithContext failed: %s", err.Error()), "(Data) ibm_is_volume_profile", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } // For lack of anything better, compose our id from profile name. - d.SetId(*profile.Name) - d.Set(isVolumeProfile, *profile.Name) - d.Set(isVolumeProfileFamily, *profile.Family) + d.SetId(*volumeProfile.Name) + + bootCapacity := []map[string]interface{}{} + if volumeProfile.BootCapacity != nil { + modelMap, err := DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityToMap(volumeProfile.BootCapacity) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + bootCapacity = append(bootCapacity, modelMap) + } + if err = d.Set("boot_capacity", bootCapacity); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting boot_capacity: %s", err), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + + capacity := []map[string]interface{}{} + if volumeProfile.Capacity != nil { + modelMap, err := DataSourceIBMIsVolumeProfileVolumeProfileCapacityToMap(volumeProfile.Capacity) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + capacity = append(capacity, modelMap) + } + if err = d.Set("capacity", capacity); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting capacity: %s", err), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + + if err = d.Set("family", volumeProfile.Family); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting family: %s", err), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + + if err = d.Set("href", volumeProfile.Href); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting href: %s", err), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + + iops := []map[string]interface{}{} + if volumeProfile.Iops != nil { + modelMap, err := DataSourceIBMIsVolumeProfileVolumeProfileIopsToMap(volumeProfile.Iops) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + iops = append(iops, modelMap) + } + if err = d.Set("iops", iops); err != nil { + tfErr := flex.TerraformErrorf(err, fmt.Sprintf("Error setting iops: %s", err), "(Data) ibm_is_volume_profile", "read") + return tfErr.GetDiag() + } + // acadia changes + + adjustableCapacityStates := []map[string]interface{}{} + if volumeProfile.AdjustableCapacityStates != nil { + modelMap, err := DataSourceIBMIsVolumeProfileVolumeProfileAdjustableCapacityStatesToMap(volumeProfile.AdjustableCapacityStates) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read", "adjustable_capacity_states-to-map").GetDiag() + } + adjustableCapacityStates = append(adjustableCapacityStates, modelMap) + } + if err = d.Set("adjustable_capacity_states", adjustableCapacityStates); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting adjustable_capacity_states: %s", err), "(Data) ibm_is_volume_profile", "read", "set-adjustable_capacity_states").GetDiag() + } + + adjustableIopsStates := []map[string]interface{}{} + if volumeProfile.AdjustableIopsStates != nil { + modelMap, err := DataSourceIBMIsVolumeProfileVolumeProfileAdjustableIopsStatesToMap(volumeProfile.AdjustableIopsStates) + if err != nil { + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profile", "read", "adjustable_iops_states-to-map").GetDiag() + } + adjustableIopsStates = append(adjustableIopsStates, modelMap) + } + if err = d.Set("adjustable_iops_states", adjustableIopsStates); err != nil { + return flex.DiscriminatedTerraformErrorf(err, fmt.Sprintf("Error setting adjustable_iops_states: %s", err), "(Data) ibm_is_volume_profile", "read", "set-adjustable_iops_states").GetDiag() + } + return nil } + +func DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityToMap(model vpcv1.VolumeProfileBootCapacityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileBootCapacityFixed); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityFixedToMap(model.(*vpcv1.VolumeProfileBootCapacityFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityRangeToMap(model.(*vpcv1.VolumeProfileBootCapacityRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityEnum); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityEnumToMap(model.(*vpcv1.VolumeProfileBootCapacityEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityDependentRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityDependentRangeToMap(model.(*vpcv1.VolumeProfileBootCapacityDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileBootCapacity) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileBootCapacityIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityFixedToMap(model *vpcv1.VolumeProfileBootCapacityFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityRangeToMap(model *vpcv1.VolumeProfileBootCapacityRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityEnumToMap(model *vpcv1.VolumeProfileBootCapacityEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileBootCapacityDependentRangeToMap(model *vpcv1.VolumeProfileBootCapacityDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileCapacityToMap(model vpcv1.VolumeProfileCapacityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileCapacityFixed); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileCapacityFixedToMap(model.(*vpcv1.VolumeProfileCapacityFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileCapacityRangeToMap(model.(*vpcv1.VolumeProfileCapacityRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityEnum); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileCapacityEnumToMap(model.(*vpcv1.VolumeProfileCapacityEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityDependentRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileCapacityDependentRangeToMap(model.(*vpcv1.VolumeProfileCapacityDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileCapacity) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileCapacityIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfileVolumeProfileCapacityFixedToMap(model *vpcv1.VolumeProfileCapacityFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileCapacityRangeToMap(model *vpcv1.VolumeProfileCapacityRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileCapacityEnumToMap(model *vpcv1.VolumeProfileCapacityEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileCapacityDependentRangeToMap(model *vpcv1.VolumeProfileCapacityDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileIopsToMap(model vpcv1.VolumeProfileIopsIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileIopsFixed); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileIopsFixedToMap(model.(*vpcv1.VolumeProfileIopsFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileIopsRangeToMap(model.(*vpcv1.VolumeProfileIopsRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsEnum); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileIopsEnumToMap(model.(*vpcv1.VolumeProfileIopsEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsDependentRange); ok { + return DataSourceIBMIsVolumeProfileVolumeProfileIopsDependentRangeToMap(model.(*vpcv1.VolumeProfileIopsDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileIops); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileIops) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileIopsIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfileVolumeProfileIopsFixedToMap(model *vpcv1.VolumeProfileIopsFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileIopsRangeToMap(model *vpcv1.VolumeProfileIopsRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileIopsEnumToMap(model *vpcv1.VolumeProfileIopsEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileIopsDependentRangeToMap(model *vpcv1.VolumeProfileIopsDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileAdjustableCapacityStatesToMap(model *vpcv1.VolumeProfileAdjustableCapacityStates) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfileVolumeProfileAdjustableIopsStatesToMap(model *vpcv1.VolumeProfileAdjustableIopsStates) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} diff --git a/ibm/service/vpc/data_source_ibm_is_volume_profiles.go b/ibm/service/vpc/data_source_ibm_is_volume_profiles.go index 7315e82f3a..4e7c5880d6 100644 --- a/ibm/service/vpc/data_source_ibm_is_volume_profiles.go +++ b/ibm/service/vpc/data_source_ibm_is_volume_profiles.go @@ -4,11 +4,15 @@ package vpc import ( + "context" + "encoding/json" "fmt" + "log" "time" "github.com/IBM-Cloud/terraform-provider-ibm/ibm/flex" "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -18,7 +22,7 @@ const ( func DataSourceIBMISVolumeProfiles() *schema.Resource { return &schema.Resource{ - Read: dataSourceIBMISVolumeProfilesRead, + ReadContext: dataSourceIBMISVolumeProfilesRead, Schema: map[string]*schema.Schema{ @@ -28,13 +32,201 @@ func DataSourceIBMISVolumeProfiles() *schema.Resource { Computed: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, + "boot_capacity": &schema.Schema{ + Type: schema.TypeList, Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, }, - "family": { - Type: schema.TypeString, + "capacity": &schema.Schema{ + Type: schema.TypeList, Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "family": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The product family this volume profile belongs to.The enumerated values for this property may[expand](https://cloud.ibm.com/apidocs/vpc#property-value-expansion) in the future.", + }, + "href": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The URL for this volume profile.", + }, + "iops": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "value": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The value for this profile field.", + }, + "default": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The default value for this profile field.", + }, + "max": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The maximum value for this profile field.", + }, + "min": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The minimum value for this profile field.", + }, + "step": &schema.Schema{ + Type: schema.TypeInt, + Computed: true, + Description: "The increment step value for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The permitted values for this profile field.", + Elem: &schema.Schema{ + Type: schema.TypeInt, + }, + }, + }, + }, + }, + "name": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The globally unique name for this volume profile.", + }, + //acadia changes + "adjustable_capacity_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable capacity for a volume with this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "adjustable_iops_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Description: "The type for this profile field.", + }, + "values": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable IOPS for a volume with this profile.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, }, }, }, @@ -43,11 +235,13 @@ func DataSourceIBMISVolumeProfiles() *schema.Resource { } } -func dataSourceIBMISVolumeProfilesRead(d *schema.ResourceData, meta interface{}) error { +func dataSourceIBMISVolumeProfilesRead(context context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { err := volumeProfilesList(d, meta) if err != nil { - return err + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profiles", "read") + log.Printf("[DEBUG]\n%s", tfErr.GetDebugMessage()) + return tfErr.GetDiag() } return nil } @@ -83,12 +277,12 @@ func volumeProfilesList(d *schema.ResourceData, meta interface{}) error { // } profilesInfo := make([]map[string]interface{}, 0) for _, profile := range allrecs { - - l := map[string]interface{}{ - "name": *profile.Name, - "family": *profile.Family, + modelMap, err := DataSourceIBMIsVolumeProfilesVolumeProfileToMap(&profile) + if err != nil { + tfErr := flex.TerraformErrorf(err, err.Error(), "(Data) ibm_is_volume_profiles", "read") + return tfErr } - profilesInfo = append(profilesInfo, l) + profilesInfo = append(profilesInfo, modelMap) } d.SetId(dataSourceIBMISVolumeProfilesID(d)) d.Set(isVolumeProfiles, profilesInfo) @@ -99,3 +293,273 @@ func volumeProfilesList(d *schema.ResourceData, meta interface{}) error { func dataSourceIBMISVolumeProfilesID(d *schema.ResourceData) string { return time.Now().UTC().String() } + +func DataSourceIBMIsVolumeProfilesVolumeProfileToMap(model *vpcv1.VolumeProfile) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + if model.BootCapacity != nil { + bootCapacityMap, err := DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityToMap(model.BootCapacity) + if err != nil { + return modelMap, err + } + modelMap["boot_capacity"] = []map[string]interface{}{bootCapacityMap} + } + if model.Capacity != nil { + capacityMap, err := DataSourceIBMIsVolumeProfilesVolumeProfileCapacityToMap(model.Capacity) + if err != nil { + return modelMap, err + } + modelMap["capacity"] = []map[string]interface{}{capacityMap} + } + modelMap["family"] = *model.Family + modelMap["href"] = *model.Href + if model.Iops != nil { + iopsMap, err := DataSourceIBMIsVolumeProfilesVolumeProfileIopsToMap(model.Iops) + if err != nil { + return modelMap, err + } + modelMap["iops"] = []map[string]interface{}{iopsMap} + } + modelMap["name"] = *model.Name + if model.AdjustableCapacityStates != nil { + adjustableCapacityStates, err := DataSourceIBMIsVolumeProfileVolumeProfileAdjustableCapacityStatesToMap(model.AdjustableCapacityStates) + if err != nil { + return modelMap, err + } + modelMap["adjustable_capacity_states"] = []map[string]interface{}{adjustableCapacityStates} + } + if model.AdjustableIopsStates != nil { + adjustableIopsStates, err := DataSourceIBMIsVolumeProfileVolumeProfileAdjustableIopsStatesToMap(model.AdjustableIopsStates) + if err != nil { + return modelMap, err + } + modelMap["adjustable_iops_states"] = []map[string]interface{}{adjustableIopsStates} + } + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityToMap(model vpcv1.VolumeProfileBootCapacityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileBootCapacityFixed); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityFixedToMap(model.(*vpcv1.VolumeProfileBootCapacityFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityRangeToMap(model.(*vpcv1.VolumeProfileBootCapacityRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityEnum); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityEnumToMap(model.(*vpcv1.VolumeProfileBootCapacityEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacityDependentRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityDependentRangeToMap(model.(*vpcv1.VolumeProfileBootCapacityDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileBootCapacity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileBootCapacity) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileBootCapacityIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityFixedToMap(model *vpcv1.VolumeProfileBootCapacityFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityRangeToMap(model *vpcv1.VolumeProfileBootCapacityRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityEnumToMap(model *vpcv1.VolumeProfileBootCapacityEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileBootCapacityDependentRangeToMap(model *vpcv1.VolumeProfileBootCapacityDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileCapacityToMap(model vpcv1.VolumeProfileCapacityIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileCapacityFixed); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileCapacityFixedToMap(model.(*vpcv1.VolumeProfileCapacityFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileCapacityRangeToMap(model.(*vpcv1.VolumeProfileCapacityRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityEnum); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileCapacityEnumToMap(model.(*vpcv1.VolumeProfileCapacityEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacityDependentRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileCapacityDependentRangeToMap(model.(*vpcv1.VolumeProfileCapacityDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileCapacity); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileCapacity) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileCapacityIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileCapacityFixedToMap(model *vpcv1.VolumeProfileCapacityFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileCapacityRangeToMap(model *vpcv1.VolumeProfileCapacityRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileCapacityEnumToMap(model *vpcv1.VolumeProfileCapacityEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileCapacityDependentRangeToMap(model *vpcv1.VolumeProfileCapacityDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileIopsToMap(model vpcv1.VolumeProfileIopsIntf) (map[string]interface{}, error) { + if _, ok := model.(*vpcv1.VolumeProfileIopsFixed); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileIopsFixedToMap(model.(*vpcv1.VolumeProfileIopsFixed)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileIopsRangeToMap(model.(*vpcv1.VolumeProfileIopsRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsEnum); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileIopsEnumToMap(model.(*vpcv1.VolumeProfileIopsEnum)) + } else if _, ok := model.(*vpcv1.VolumeProfileIopsDependentRange); ok { + return DataSourceIBMIsVolumeProfilesVolumeProfileIopsDependentRangeToMap(model.(*vpcv1.VolumeProfileIopsDependentRange)) + } else if _, ok := model.(*vpcv1.VolumeProfileIops); ok { + modelMap := make(map[string]interface{}) + model := model.(*vpcv1.VolumeProfileIops) + if model.Type != nil { + modelMap["type"] = *model.Type + } + if model.Value != nil { + modelMap["value"] = flex.IntValue(model.Value) + } + if model.Default != nil { + modelMap["default"] = flex.IntValue(model.Default) + } + if model.Max != nil { + modelMap["max"] = flex.IntValue(model.Max) + } + if model.Min != nil { + modelMap["min"] = flex.IntValue(model.Min) + } + if model.Step != nil { + modelMap["step"] = flex.IntValue(model.Step) + } + if model.Values != nil { + modelMap["values"] = model.Values + } + return modelMap, nil + } else { + return nil, fmt.Errorf("Unrecognized vpcv1.VolumeProfileIopsIntf subtype encountered") + } +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileIopsFixedToMap(model *vpcv1.VolumeProfileIopsFixed) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["type"] = *model.Type + modelMap["value"] = flex.IntValue(model.Value) + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileIopsRangeToMap(model *vpcv1.VolumeProfileIopsRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileIopsEnumToMap(model *vpcv1.VolumeProfileIopsEnum) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["default"] = flex.IntValue(model.Default) + modelMap["type"] = *model.Type + modelMap["values"] = model.Values + return modelMap, nil +} + +func DataSourceIBMIsVolumeProfilesVolumeProfileIopsDependentRangeToMap(model *vpcv1.VolumeProfileIopsDependentRange) (map[string]interface{}, error) { + modelMap := make(map[string]interface{}) + modelMap["max"] = flex.IntValue(model.Max) + modelMap["min"] = flex.IntValue(model.Min) + modelMap["step"] = flex.IntValue(model.Step) + modelMap["type"] = *model.Type + return modelMap, nil +} + +func printfull(response interface{}) string { + output, err := json.MarshalIndent(response, "", " ") + if err == nil { + return fmt.Sprintf("%+v\n", string(output)) + } + return fmt.Sprintf("Error : %#v", response) +} diff --git a/ibm/service/vpc/data_source_ibm_is_volumes.go b/ibm/service/vpc/data_source_ibm_is_volumes.go index 8a8e449da4..861db6b7a6 100644 --- a/ibm/service/vpc/data_source_ibm_is_volumes.go +++ b/ibm/service/vpc/data_source_ibm_is_volumes.go @@ -392,6 +392,25 @@ func DataSourceIBMIsVolumes() *schema.Resource { }, }, }, + + // acadia changes + + "adjustable_capacity_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable capacity for this volume.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "adjustable_iops_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable IOPS for this volume.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, isVolumesStatus: &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -806,6 +825,8 @@ func dataSourceVolumeCollectionVolumesToMap(volumesItem vpcv1.Volume, meta inter } volumesMap[isVolumeHealthReasons] = healthReasonsList } + volumesMap["adjustable_capacity_states"] = volumesItem.AdjustableCapacityStates + volumesMap["adjustable_iops_states"] = volumesItem.AdjustableIopsStates if volumesItem.CatalogOffering != nil { versionCrn := "" if volumesItem.CatalogOffering.Version != nil && volumesItem.CatalogOffering.Version.CRN != nil { diff --git a/ibm/service/vpc/resource_ibm_is_instance.go b/ibm/service/vpc/resource_ibm_is_instance.go index fe23b877e1..d26d20ee26 100644 --- a/ibm/service/vpc/resource_ibm_is_instance.go +++ b/ibm/service/vpc/resource_ibm_is_instance.go @@ -1213,6 +1213,7 @@ func ResourceIBMISInstance() *schema.Resource { }, isInstanceBootProfile: { Type: schema.TypeString, + Optional: true, Computed: true, }, isInstanceBootVolumeTags: { @@ -1765,7 +1766,7 @@ func ResourceIBMISInstanceValidator() *validate.ResourceValidator { return &ibmISInstanceValidator } -func instanceCreateByImage(d *schema.ResourceData, meta interface{}, profile, name, vpcID, zone, image string) error { +func instanceCreateByImage(d *schema.ResourceData, meta interface{}, profile, name, vpcID, zone, image, bootProfile string) error { sess, err := vpcClient(meta) if err != nil { return err @@ -1861,10 +1862,11 @@ func instanceCreateByImage(d *schema.ResourceData, meta interface{}, profile, na CRN: &encstr, } } - - volprof := "general-purpose" + if bootProfile == "" { + bootProfile = "general-purpose" + } volTemplate.Profile = &vpcv1.VolumeProfileIdentity{ - Name: &volprof, + Name: &bootProfile, } var userTags *schema.Set if v, ok := bootvol[isInstanceBootVolumeTags]; ok { @@ -3923,6 +3925,7 @@ func resourceIBMisInstanceCreate(d *schema.ResourceData, meta interface{}) error zone := d.Get(isInstanceZone).(string) image := d.Get(isInstanceImage).(string) snapshot := d.Get("boot_volume.0.snapshot").(string) + bootProfile := d.Get("boot_volume.0.profile").(string) snapshotcrn := d.Get("boot_volume.0.snapshot_crn").(string) volume := d.Get("boot_volume.0.volume_id").(string) template := d.Get(isInstanceSourceTemplate).(string) @@ -3952,7 +3955,7 @@ func resourceIBMisInstanceCreate(d *schema.ResourceData, meta interface{}) error return err } } else { - err := instanceCreateByImage(d, meta, profile, name, vpcID, zone, image) + err := instanceCreateByImage(d, meta, profile, name, vpcID, zone, image, bootProfile) if err != nil { return err } diff --git a/ibm/service/vpc/resource_ibm_is_instance_volume_attachment.go b/ibm/service/vpc/resource_ibm_is_instance_volume_attachment.go index 1e1075549b..e647b0a861 100644 --- a/ibm/service/vpc/resource_ibm_is_instance_volume_attachment.go +++ b/ibm/service/vpc/resource_ibm_is_instance_volume_attachment.go @@ -691,30 +691,31 @@ func instanceVolAttUpdate(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf("[ERROR] Error Getting Volume (%s): %s\n%s", id, err, response) } + if *vol.Profile.Name != "sdp" { + if vol.VolumeAttachments == nil || len(vol.VolumeAttachments) == 0 || *vol.VolumeAttachments[0].Name == "" { + return fmt.Errorf("[ERROR] Error volume capacity can't be updated since volume %s is not attached to any instance for VolumePatch", id) + } - if vol.VolumeAttachments == nil || len(vol.VolumeAttachments) == 0 || *vol.VolumeAttachments[0].Name == "" { - return fmt.Errorf("[ERROR] Error volume capacity can't be updated since volume %s is not attached to any instance for VolumePatch", id) - } - - getinsOptions := &vpcv1.GetInstanceOptions{ - ID: &instanceId, - } - instance, response, err := instanceC.GetInstance(getinsOptions) - if err != nil || instance == nil { - return fmt.Errorf("[ERROR] Error retrieving Instance (%s) : %s\n%s", instanceId, err, response) - } - if instance != nil && *instance.Status != "running" { - actiontype := "start" - createinsactoptions := &vpcv1.CreateInstanceActionOptions{ - InstanceID: &instanceId, - Type: &actiontype, + getinsOptions := &vpcv1.GetInstanceOptions{ + ID: &instanceId, } - _, response, err = instanceC.CreateInstanceAction(createinsactoptions) - if err != nil { + instance, response, err := instanceC.GetInstance(getinsOptions) + if err != nil || instance == nil { + return fmt.Errorf("[ERROR] Error retrieving Instance (%s) : %s\n%s", instanceId, err, response) + } + if instance != nil && *instance.Status != "running" { + actiontype := "start" + createinsactoptions := &vpcv1.CreateInstanceActionOptions{ + InstanceID: &instanceId, + Type: &actiontype, + } + _, response, err = instanceC.CreateInstanceAction(createinsactoptions) + if err != nil { + return fmt.Errorf("[ERROR] Error starting Instance (%s) : %s\n%s", instanceId, err, response) + } + _, err = isWaitForInstanceAvailable(instanceC, instanceId, d.Timeout(schema.TimeoutCreate), d) return fmt.Errorf("[ERROR] Error starting Instance (%s) : %s\n%s", instanceId, err, response) } - _, err = isWaitForInstanceAvailable(instanceC, instanceId, d.Timeout(schema.TimeoutCreate), d) - return fmt.Errorf("[ERROR] Error starting Instance (%s) : %s\n%s", instanceId, err, response) } capacity := int64(d.Get(isVolumeCapacity).(int)) updateVolumeOptions := &vpcv1.UpdateVolumeOptions{ diff --git a/ibm/service/vpc/resource_ibm_is_volume.go b/ibm/service/vpc/resource_ibm_is_volume.go index 0fcf79e00a..23844bf1b8 100644 --- a/ibm/service/vpc/resource_ibm_is_volume.go +++ b/ibm/service/vpc/resource_ibm_is_volume.go @@ -124,12 +124,12 @@ func ResourceIBMISVolume() *schema.Resource { }, isVolumeCapacity: { - Type: schema.TypeInt, - Optional: true, - ForceNew: false, - Computed: true, - ValidateFunc: validate.InvokeValidator("ibm_is_volume", isVolumeCapacity), - Description: "Volume capacity value", + Type: schema.TypeInt, + Optional: true, + ForceNew: false, + Computed: true, + // ValidateFunc: validate.InvokeValidator("ibm_is_volume", isVolumeCapacity), + Description: "Volume capacity value", }, isVolumeSourceSnapshot: { Type: schema.TypeString, @@ -156,11 +156,11 @@ func ResourceIBMISVolume() *schema.Resource { Description: "Resource group name", }, isVolumeIops: { - Type: schema.TypeInt, - Optional: true, - Computed: true, - ValidateFunc: validate.InvokeValidator("ibm_is_volume", isVolumeIops), - Description: "IOPS value for the Volume", + Type: schema.TypeInt, + Optional: true, + Computed: true, + // ValidateFunc: validate.InvokeValidator("ibm_is_volume", isVolumeIops), + Description: "IOPS value for the Volume", }, isVolumeCrn: { Type: schema.TypeString, @@ -231,6 +231,19 @@ func ResourceIBMISVolume() *schema.Resource { }, }, }, + //acadia changes + "adjustable_capacity_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable capacity for this volume.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "adjustable_iops_states": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Description: "The attachment states that support adjustable IOPS for this volume.", + Elem: &schema.Schema{Type: schema.TypeString}, + }, isVolumeHealthReasons: { Type: schema.TypeList, Computed: true, @@ -410,22 +423,20 @@ func ResourceIBMISVolumeValidator() *validate.ResourceValidator { ValidateFunctionIdentifier: validate.ValidateAllowedStringValue, Type: validate.TypeString, Optional: true, - AllowedValues: "general-purpose, 5iops-tier, 10iops-tier, custom", + AllowedValues: "general-purpose, 5iops-tier, 10iops-tier, custom, sdp", }) validateSchema = append(validateSchema, validate.ValidateSchema{ Identifier: isVolumeCapacity, ValidateFunctionIdentifier: validate.IntBetween, Type: validate.TypeInt, - MinValue: "10", - MaxValue: "16000"}) + MinValue: "10"}) validateSchema = append(validateSchema, validate.ValidateSchema{ Identifier: isVolumeIops, ValidateFunctionIdentifier: validate.IntBetween, Type: validate.TypeInt, - MinValue: "100", - MaxValue: "48000"}) + MinValue: "100"}) validateSchema = append(validateSchema, validate.ValidateSchema{ Identifier: "accesstag", @@ -716,6 +727,16 @@ func volGet(d *schema.ResourceData, meta interface{}, id string) error { if err != nil { return err } + //acadia changes + + if err = d.Set("adjustable_capacity_states", vol.AdjustableCapacityStates); err != nil { + err = fmt.Errorf("Error setting adjustable_capacity_states: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_volume", "read", "set-adjustable_capacity_states") + } + if err = d.Set("adjustable_iops_states", vol.AdjustableIopsStates); err != nil { + err = fmt.Errorf("Error setting adjustable_iops_states: %s", err) + return flex.DiscriminatedTerraformErrorf(err, err.Error(), "ibm_is_volume", "read", "set-adjustable_iops_states") + } d.Set(flex.ResourceControllerURL, controller+"/vpc-ext/storage/storageVolumes") d.Set(flex.ResourceName, *vol.Name) d.Set(flex.ResourceCRN, *vol.CRN) @@ -894,32 +915,35 @@ func volUpdate(d *schema.ResourceData, meta interface{}, id, name string, hasNam } return fmt.Errorf("[ERROR] Error Getting Volume (%s): %s\n%s", id, err, response) } - if vol.VolumeAttachments == nil || len(vol.VolumeAttachments) == 0 || *vol.VolumeAttachments[0].ID == "" { - return fmt.Errorf("[ERROR] Error volume capacity can't be updated since volume %s is not attached to any instance for VolumePatch", id) - } - insId := vol.VolumeAttachments[0].Instance.ID - getinsOptions := &vpcv1.GetInstanceOptions{ - ID: insId, - } - instance, response, err := sess.GetInstance(getinsOptions) - if err != nil || instance == nil { - return fmt.Errorf("[ERROR] Error retrieving Instance (%s) : %s\n%s", *insId, err, response) - } - if instance != nil && *instance.Status != "running" { - actiontype := "start" - createinsactoptions := &vpcv1.CreateInstanceActionOptions{ - InstanceID: insId, - Type: &actiontype, + if *vol.Profile.Name != "sdp" { + if vol.VolumeAttachments == nil || len(vol.VolumeAttachments) == 0 || *vol.VolumeAttachments[0].ID == "" { + return fmt.Errorf("[ERROR] Error volume capacity can't be updated since volume %s is not attached to any instance for VolumePatch", id) } - _, response, err = sess.CreateInstanceAction(createinsactoptions) - if err != nil { - return fmt.Errorf("[ERROR] Error starting Instance (%s) : %s\n%s", *insId, err, response) + insId := vol.VolumeAttachments[0].Instance.ID + getinsOptions := &vpcv1.GetInstanceOptions{ + ID: insId, } - _, err = isWaitForInstanceAvailable(sess, *insId, d.Timeout(schema.TimeoutCreate), d) - if err != nil { - return err + instance, response, err := sess.GetInstance(getinsOptions) + if err != nil || instance == nil { + return fmt.Errorf("[ERROR] Error retrieving Instance (%s) : %s\n%s", *insId, err, response) + } + if instance != nil && *instance.Status != "running" { + actiontype := "start" + createinsactoptions := &vpcv1.CreateInstanceActionOptions{ + InstanceID: insId, + Type: &actiontype, + } + _, response, err = sess.CreateInstanceAction(createinsactoptions) + if err != nil { + return fmt.Errorf("[ERROR] Error starting Instance (%s) : %s\n%s", *insId, err, response) + } + _, err = isWaitForInstanceAvailable(sess, *insId, d.Timeout(schema.TimeoutCreate), d) + if err != nil { + return err + } } } + capacity = int64(d.Get(isVolumeCapacity).(int)) volumeCapacityPatchModel := &vpcv1.VolumePatch{} volumeCapacityPatchModel.Capacity = &capacity diff --git a/scripts/build.sh b/scripts/build.sh index 602700a444..d19ae2beb0 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -58,7 +58,7 @@ gox \ -arch="${XC_ARCH}" \ -osarch="${XC_EXCLUDE_OSARCH}" \ -ldflags "${LD_FLAGS}" \ - -output "pkg/{{.OS}}_{{.Arch}}/terraform-provider-ibm" \ + -output "pkg/{{.OS}}_{{.Arch}}/terraform-provider-ibm_${VERSION}_{{.OS}}_{{.Arch}}" \ . # Move all the compiled things to the $GOPATH/bin @@ -92,10 +92,11 @@ if [ "${TF_DEV}x" = "x" ]; then echo "==> Packaging..." for PLATFORM in $(find ./pkg -mindepth 1 -maxdepth 1 -type d); do OSARCH=$(basename ${PLATFORM}) + ZIPNAME="terraform-provider-ibm_${VERSION}_${OSARCH}" echo "--> ${OSARCH}" pushd $PLATFORM >/dev/null 2>&1 - zip ../${OSARCH}.zip ./* + zip ../${ZIPNAME}.zip ./* popd >/dev/null 2>&1 done fi diff --git a/website/docs/d/is_volume.html.markdown b/website/docs/d/is_volume.html.markdown index b5389962ac..1d85cae95b 100644 --- a/website/docs/d/is_volume.html.markdown +++ b/website/docs/d/is_volume.html.markdown @@ -46,6 +46,8 @@ In addition to all argument reference list, you can access the following attribu - `access_tags` - (List) Access management tags associated for the volume. - `active` - (Boolean) Indicates whether a running virtual server instance has an attachment to this volume. - `attachment_state` - (Boolean) The attachment state of the volume +- `adjustable_capacity_states` - (List) The attachment states that support adjustable capacity for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. +- `adjustable_iops_states` - (List) The attachment states that support adjustable IOPS for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. - `bandwidth` - The maximum bandwidth (in megabits per second) for the volume - `busy` - (Boolean) Indicates whether this volume is performing an operation that must be serialized. This must be `false` to perform an operation that is specified to require serialization. - `capacity` - (String) The capacity of the volume in gigabytes. @@ -91,3 +93,5 @@ In addition to all argument reference list, you can access the following attribu - `message` - (String) An explanation of the status reason - `more_info` - (String) Link to documentation about this status reason - `tags` - (String) User Tags associated with the volume. (https://cloud.ibm.com/apidocs/tagging#types-of-tags) +- `unattached_capacity_update_supported` - (Boolean) Indicates whether the capacity for the volume can be changed when not attached to a running virtual server instance. +- `unattached_iops_update_supported` - (Boolean) Indicates whether the IOPS for the volume can be changed when not attached to a running virtual server instance. diff --git a/website/docs/d/is_volume_profile.html.markdown b/website/docs/d/is_volume_profile.html.markdown index 8cdf6c9683..4f098dfcbe 100644 --- a/website/docs/d/is_volume_profile.html.markdown +++ b/website/docs/d/is_volume_profile.html.markdown @@ -38,4 +38,13 @@ Review the argument references that you can specify for your data source. ## Attribute reference In addition to the argument reference list, you can access the following attribute references after your data source is created. +- `adjustable_capacity_states` - (List) + Nested schema for **adjustable_capacity_states**: + - `type` - (String) The type for this profile field. + - `values` - (List) The attachment states that support adjustable capacity for a volume with this profile. Allowable list items are: `attached`, `unattached`, `unusable`. +- `adjustable_iops_states` - (List) + Nested schema for **adjustable_iops_states**: + - `type` - (String) The type for this profile field. + - `values` - (List) The attachment states that support adjustable IOPS for a volume with this profile. Allowable list items are: `attached`, `unattached`, `unusable`. - `family` - (String) The family of the virtual server volume profile. + diff --git a/website/docs/d/is_volume_profiles.html.markdown b/website/docs/d/is_volume_profiles.html.markdown index 77efa299f2..12c6c3e8cf 100644 --- a/website/docs/d/is_volume_profiles.html.markdown +++ b/website/docs/d/is_volume_profiles.html.markdown @@ -35,6 +35,14 @@ You can access the following attribute references after your data source is crea - `profiles` - (List) Lists all server volume profiles in the region. Nested scheme for `profiles`: + - `adjustable_capacity_states` - (List) + Nested schema for **adjustable_capacity_states**: + - `type` - (String) The type for this profile field. + - `values` - (List) The attachment states that support adjustable capacity for a volume with this profile. Allowable list items are: `attached`, `unattached`, `unusable`. + - `adjustable_iops_states` - (List) + Nested schema for **adjustable_iops_states**: + - `type` - (String) The type for this profile field. + - `values` - (List) The attachment states that support adjustable IOPS for a volume with this profile. Allowable list items are: `attached`, `unattached`, `unusable`. - `name` - (String) The name of the virtual server volume profile. - `family` - (String) The family of the virtual server volume profile. diff --git a/website/docs/d/is_volumes.html.markdown b/website/docs/d/is_volumes.html.markdown index 1a8dd26481..609bd268be 100644 --- a/website/docs/d/is_volumes.html.markdown +++ b/website/docs/d/is_volumes.html.markdown @@ -45,6 +45,8 @@ In addition to all argument references listed, you can access the following attr Nested scheme for **volumes**: - `access_tags` - (List) Access management tags associated for the volume. - `active` - (Boolean) Indicates whether a running virtual server instance has an attachment to this volume. + - `adjustable_capacity_states` - (List) The attachment states that support adjustable capacity for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. + - `adjustable_iops_states` - (List) The attachment states that support adjustable IOPS for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. - `attachment_state` - (Boolean) The attachment state of the volume - `bandwidth` - (Integer) The maximum bandwidth (in megabits per second) for the volume. - `busy` - (Boolean) Indicates whether this volume is performing an operation that must be serialized. This must be `false` to perform an operation that is specified to require serialization. diff --git a/website/docs/r/is_volume.html.markdown b/website/docs/r/is_volume.html.markdown index 1b909fe257..cc26dc7eb6 100644 --- a/website/docs/r/is_volume.html.markdown +++ b/website/docs/r/is_volume.html.markdown @@ -71,6 +71,8 @@ Review the argument references that you can specify for your resource. **•** For more information, about creating access tags, see [working with tags](https://cloud.ibm.com/docs/account?topic=account-tag&interface=ui#create-access-console).
**•** You must have the access listed in the [Granting users access to tag resources](https://cloud.ibm.com/docs/account?topic=account-access) for `access_tags`
**•** `access_tags` must be in the format `key:value`. +- `adjustable_capacity_states` - (List) The attachment states that support adjustable capacity for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. +- `adjustable_iops_states` - (List) The attachment states that support adjustable IOPS for this volume. Allowable list items are: `attached`, `unattached`, `unusable`. - `capacity` - (Optional, Integer) (The capacity of the volume in gigabytes. This defaults to `100`, minimum to `10 ` and maximum to `16000`. ~> **NOTE:** Supports only expansion on update (must be attached to a running instance and must not be less than the current volume capacity). Can be updated only if volume is attached to an running virtual server instance. Stopped instance will be started on update of capacity of the volume.If `source_snapshot` is provided `capacity` must be at least the snapshot's minimum_capacity. The maximum value may increase in the future and If unspecified, the capacity will be the source snapshot's minimum_capacity.