From 182fbb1fdb0963680dc0daa907356bf8fd53f5fd Mon Sep 17 00:00:00 2001 From: Thibaut Di Prima Date: Tue, 1 Oct 2024 11:57:39 +0000 Subject: [PATCH 1/5] datasource volume(s) --- ovh/data_cloud_project_volume.go | 69 +++ ovh/data_cloud_project_volume_gen.go | 93 +++ ovh/data_cloud_project_volume_test.go | 39 ++ ovh/data_cloud_project_volumes.go | 83 +++ ovh/data_cloud_project_volumes_gen.go | 558 ++++++++++++++++++ ovh/data_cloud_project_volumes_testgo | 38 ++ ovh/provider_new.go | 2 + .../docs/d/cloud_project_volume.html.markdown | 33 ++ .../d/cloud_project_volumes.html.markdown | 32 + 9 files changed, 947 insertions(+) create mode 100644 ovh/data_cloud_project_volume.go create mode 100644 ovh/data_cloud_project_volume_gen.go create mode 100644 ovh/data_cloud_project_volume_test.go create mode 100644 ovh/data_cloud_project_volumes.go create mode 100644 ovh/data_cloud_project_volumes_gen.go create mode 100644 ovh/data_cloud_project_volumes_testgo create mode 100644 website/docs/d/cloud_project_volume.html.markdown create mode 100644 website/docs/d/cloud_project_volumes.html.markdown diff --git a/ovh/data_cloud_project_volume.go b/ovh/data_cloud_project_volume.go new file mode 100644 index 000000000..4ab0ac627 --- /dev/null +++ b/ovh/data_cloud_project_volume.go @@ -0,0 +1,69 @@ +package ovh + +import ( + "context" + "fmt" + "net/url" + + "github.com/hashicorp/terraform-plugin-framework/datasource" +) + +var _ datasource.DataSourceWithConfigure = (*cloudProjectVolumeDataSource)(nil) + +func NewCloudProjectVolumeDataSource() datasource.DataSource { + return &cloudProjectVolumeDataSource{} +} + +type cloudProjectVolumeDataSource struct { + config *Config +} + +func (d *cloudProjectVolumeDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_cloud_project_volume" +} + +func (d *cloudProjectVolumeDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + config, ok := req.ProviderData.(*Config) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + d.config = config +} + +func (d *cloudProjectVolumeDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = CloudProjectVolumeDataSourceSchema(ctx) +} + +func (d *cloudProjectVolumeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data CloudProjectVolumeModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Read API call logic + endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume/" + url.PathEscape(data.VolumeId.ValueString()) + "" + + if err := d.config.OVHClient.Get(endpoint, &data); err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Error calling Get %s", endpoint), + err.Error(), + ) + return + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/ovh/data_cloud_project_volume_gen.go b/ovh/data_cloud_project_volume_gen.go new file mode 100644 index 000000000..46146f2de --- /dev/null +++ b/ovh/data_cloud_project_volume_gen.go @@ -0,0 +1,93 @@ +// Code generated by terraform-plugin-framework-generator DO NOT EDIT. + +package ovh + +import ( + "context" + + ovhtypes "github.com/ovh/terraform-provider-ovh/ovh/types" + + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" +) + +func CloudProjectVolumeDataSourceSchema(ctx context.Context) schema.Schema { + attrs := map[string]schema.Attribute{ + "id": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Description: "Volume ID", + MarkdownDescription: "Volume ID", + }, + "name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Description: "Volume name", + MarkdownDescription: "Volume name", + }, + "region_name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Required: true, + Description: "Region name", + MarkdownDescription: "Region name", + }, + "service_name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Required: true, + Description: "Service name", + MarkdownDescription: "Service name", + }, + "size": schema.Int64Attribute{ + CustomType: ovhtypes.TfInt64Type{}, + Computed: true, + Description: "Volume size", + MarkdownDescription: "Volume size", + }, + "volume_id": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Required: true, + Description: "Volume ID", + MarkdownDescription: "Volume ID", + }, + } + + return schema.Schema{ + Attributes: attrs, + } +} + +type CloudProjectVolumeModel struct { + Id ovhtypes.TfStringValue `tfsdk:"id" json:"id"` + Name ovhtypes.TfStringValue `tfsdk:"name" json:"name"` + RegionName ovhtypes.TfStringValue `tfsdk:"region_name" json:"regionName"` + ServiceName ovhtypes.TfStringValue `tfsdk:"service_name" json:"serviceName"` + Size ovhtypes.TfInt64Value `tfsdk:"size" json:"size"` + VolumeId ovhtypes.TfStringValue `tfsdk:"volume_id" json:"volumeId"` +} + +func (v *CloudProjectVolumeModel) MergeWith(other *CloudProjectVolumeModel) { + + if (v.Id.IsUnknown() || v.Id.IsNull()) && !other.Id.IsUnknown() { + v.Id = other.Id + } + + if (v.Name.IsUnknown() || v.Name.IsNull()) && !other.Name.IsUnknown() { + v.Name = other.Name + } + + if (v.RegionName.IsUnknown() || v.RegionName.IsNull()) && !other.RegionName.IsUnknown() { + v.RegionName = other.RegionName + } + + if (v.ServiceName.IsUnknown() || v.ServiceName.IsNull()) && !other.ServiceName.IsUnknown() { + v.ServiceName = other.ServiceName + } + + if (v.Size.IsUnknown() || v.Size.IsNull()) && !other.Size.IsUnknown() { + v.Size = other.Size + } + + if (v.VolumeId.IsUnknown() || v.VolumeId.IsNull()) && !other.VolumeId.IsUnknown() { + v.VolumeId = other.VolumeId + } + +} diff --git a/ovh/data_cloud_project_volume_test.go b/ovh/data_cloud_project_volume_test.go new file mode 100644 index 000000000..7b24d3af4 --- /dev/null +++ b/ovh/data_cloud_project_volume_test.go @@ -0,0 +1,39 @@ +package ovh + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceCloudProjectVolume_basic(t *testing.T) { + serviceName := os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST") + regionName := os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST") + volumeId := os.Getenv("OVH_CLOUD_PROJECT_VOLUME_ID_TEST") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckCloud(t); testAccCheckCloudProjectExists(t) }, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` + data "ovh_cloud_project_volume" "volume" { + service_name = "%s" + region_name = "%s" + volume_id = "%s" + } + `, + serviceName, + regionName, + volumeId, + ), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.ovh_cloud_project_volume.volume", "region_name", os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST")), + resource.TestCheckResourceAttrSet("data.ovh_cloud_project_volume.volume", "name"), + resource.TestCheckResourceAttrSet("data.ovh_cloud_project_volume.volume", "volume_id"), + ), + }, + }, + }) +} diff --git a/ovh/data_cloud_project_volumes.go b/ovh/data_cloud_project_volumes.go new file mode 100644 index 000000000..df75f052f --- /dev/null +++ b/ovh/data_cloud_project_volumes.go @@ -0,0 +1,83 @@ +package ovh + +import ( + "context" + "fmt" + "net/url" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + ovhtypes "github.com/ovh/terraform-provider-ovh/ovh/types" +) + +var _ datasource.DataSourceWithConfigure = (*cloudProjectVolumesDataSource)(nil) + +func NewCloudProjectVolumesDataSource() datasource.DataSource { + return &cloudProjectVolumesDataSource{} +} + +type cloudProjectVolumesDataSource struct { + config *Config +} + +func (d *cloudProjectVolumesDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_cloud_project_volumes" +} + +func (d *cloudProjectVolumesDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + config, ok := req.ProviderData.(*Config) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + + d.config = config +} + +func (d *cloudProjectVolumesDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = CloudProjectVolumesDataSourceSchema(ctx) +} + +func (d *cloudProjectVolumesDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var data CloudProjectVolumesModel + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Read API call logic + endpoint := "/cloud/project/" + url.PathEscape(data.ServiceName.ValueString()) + "/region/" + url.PathEscape(data.RegionName.ValueString()) + "/volume" + + var arr []CloudProjectVolumesValue + + if err := d.config.OVHClient.Get(endpoint, &arr); err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Error calling Get %s", endpoint), + err.Error(), + ) + return + } + + var b []attr.Value + for _, a := range arr { + b = append(b, a) + } + + data.CloudProjectVolumes = ovhtypes.TfListNestedValue[CloudProjectVolumesValue]{ + ListValue: basetypes.NewListValueMust(CloudProjectVolumesValue{}.Type(ctx), b), + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/ovh/data_cloud_project_volumes_gen.go b/ovh/data_cloud_project_volumes_gen.go new file mode 100644 index 000000000..26663bcc1 --- /dev/null +++ b/ovh/data_cloud_project_volumes_gen.go @@ -0,0 +1,558 @@ +// Code generated by terraform-plugin-framework-generator DO NOT EDIT. + +package ovh + +import ( + "context" + "encoding/json" + "fmt" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-go/tftypes" + ovhtypes "github.com/ovh/terraform-provider-ovh/ovh/types" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" +) + +func CloudProjectVolumesDataSourceSchema(ctx context.Context) schema.Schema { + attrs := map[string]schema.Attribute{ + "cloud_project_volumes": schema.SetNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Description: "Volume ID", + MarkdownDescription: "Volume ID", + }, + "name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Computed: true, + Description: "Volume name", + MarkdownDescription: "Volume name", + }, + "size": schema.Int64Attribute{ + CustomType: ovhtypes.TfInt64Type{}, + Computed: true, + Description: "Volume size", + MarkdownDescription: "Volume size", + }, + }, + CustomType: CloudProjectVolumesType{ + ObjectType: types.ObjectType{ + AttrTypes: CloudProjectVolumesValue{}.AttributeTypes(ctx), + }, + }, + }, + CustomType: ovhtypes.NewTfListNestedType[CloudProjectVolumesValue](ctx), + Computed: true, + }, + "region_name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Required: true, + Description: "Region name", + MarkdownDescription: "Region name", + }, + "service_name": schema.StringAttribute{ + CustomType: ovhtypes.TfStringType{}, + Required: true, + Description: "Service name", + MarkdownDescription: "Service name", + }, + } + + return schema.Schema{ + Attributes: attrs, + } +} + +type CloudProjectVolumesModel struct { + CloudProjectVolumes ovhtypes.TfListNestedValue[CloudProjectVolumesValue] `tfsdk:"cloud_project_volumes" json:"cloudProjectVolumes"` + RegionName ovhtypes.TfStringValue `tfsdk:"region_name" json:"regionName"` + ServiceName ovhtypes.TfStringValue `tfsdk:"service_name" json:"serviceName"` +} + +func (v *CloudProjectVolumesModel) MergeWith(other *CloudProjectVolumesModel) { + + if (v.CloudProjectVolumes.IsUnknown() || v.CloudProjectVolumes.IsNull()) && !other.CloudProjectVolumes.IsUnknown() { + v.CloudProjectVolumes = other.CloudProjectVolumes + } + + if (v.RegionName.IsUnknown() || v.RegionName.IsNull()) && !other.RegionName.IsUnknown() { + v.RegionName = other.RegionName + } + + if (v.ServiceName.IsUnknown() || v.ServiceName.IsNull()) && !other.ServiceName.IsUnknown() { + v.ServiceName = other.ServiceName + } + +} + +var _ basetypes.ObjectTypable = CloudProjectVolumesType{} + +type CloudProjectVolumesType struct { + basetypes.ObjectType +} + +func (t CloudProjectVolumesType) Equal(o attr.Type) bool { + other, ok := o.(CloudProjectVolumesType) + + if !ok { + return false + } + + return t.ObjectType.Equal(other.ObjectType) +} + +func (t CloudProjectVolumesType) String() string { + return "CloudProjectVolumesType" +} + +func (t CloudProjectVolumesType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) { + var diags diag.Diagnostics + + attributes := in.Attributes() + + idAttribute, ok := attributes["id"] + + if !ok { + diags.AddError( + "Attribute Missing", + `id is missing from object`) + + return nil, diags + } + + idVal, ok := idAttribute.(ovhtypes.TfStringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`id expected to be ovhtypes.TfStringValue, was: %T`, idAttribute)) + } + + nameAttribute, ok := attributes["name"] + + if !ok { + diags.AddError( + "Attribute Missing", + `name is missing from object`) + + return nil, diags + } + + nameVal, ok := nameAttribute.(ovhtypes.TfStringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`name expected to be ovhtypes.TfStringValue, was: %T`, nameAttribute)) + } + + sizeAttribute, ok := attributes["size"] + + if !ok { + diags.AddError( + "Attribute Missing", + `size is missing from object`) + + return nil, diags + } + + sizeVal, ok := sizeAttribute.(ovhtypes.TfInt64Value) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`size expected to be ovhtypes.TfInt64Value, was: %T`, sizeAttribute)) + } + + if diags.HasError() { + return nil, diags + } + + return CloudProjectVolumesValue{ + Id: idVal, + Name: nameVal, + Size: sizeVal, + state: attr.ValueStateKnown, + }, diags +} + +func NewCloudProjectVolumesValueNull() CloudProjectVolumesValue { + return CloudProjectVolumesValue{ + state: attr.ValueStateNull, + } +} + +func NewCloudProjectVolumesValueUnknown() CloudProjectVolumesValue { + return CloudProjectVolumesValue{ + state: attr.ValueStateUnknown, + } +} + +func NewCloudProjectVolumesValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (CloudProjectVolumesValue, diag.Diagnostics) { + var diags diag.Diagnostics + + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/521 + ctx := context.Background() + + for name, attributeType := range attributeTypes { + attribute, ok := attributes[name] + + if !ok { + diags.AddError( + "Missing CloudProjectVolumesValue Attribute Value", + "While creating a CloudProjectVolumesValue value, a missing attribute value was detected. "+ + "A CloudProjectVolumesValue must contain values for all attributes, even if null or unknown. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("CloudProjectVolumesValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()), + ) + + continue + } + + if !attributeType.Equal(attribute.Type(ctx)) { + diags.AddError( + "Invalid CloudProjectVolumesValue Attribute Type", + "While creating a CloudProjectVolumesValue value, an invalid attribute value was detected. "+ + "A CloudProjectVolumesValue must use a matching attribute type for the value. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("CloudProjectVolumesValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+ + fmt.Sprintf("CloudProjectVolumesValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)), + ) + } + } + + for name := range attributes { + _, ok := attributeTypes[name] + + if !ok { + diags.AddError( + "Extra CloudProjectVolumesValue Attribute Value", + "While creating a CloudProjectVolumesValue value, an extra attribute value was detected. "+ + "A CloudProjectVolumesValue must not contain values beyond the expected attribute types. "+ + "This is always an issue with the provider and should be reported to the provider developers.\n\n"+ + fmt.Sprintf("Extra CloudProjectVolumesValue Attribute Name: %s", name), + ) + } + } + + if diags.HasError() { + return NewCloudProjectVolumesValueUnknown(), diags + } + + idAttribute, ok := attributes["id"] + + if !ok { + diags.AddError( + "Attribute Missing", + `id is missing from object`) + + return NewCloudProjectVolumesValueUnknown(), diags + } + + idVal, ok := idAttribute.(ovhtypes.TfStringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`id expected to be ovhtypes.TfStringValue, was: %T`, idAttribute)) + } + + nameAttribute, ok := attributes["name"] + + if !ok { + diags.AddError( + "Attribute Missing", + `name is missing from object`) + + return NewCloudProjectVolumesValueUnknown(), diags + } + + nameVal, ok := nameAttribute.(ovhtypes.TfStringValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`name expected to be ovhtypes.TfStringValue, was: %T`, nameAttribute)) + } + + sizeAttribute, ok := attributes["size"] + + if !ok { + diags.AddError( + "Attribute Missing", + `size is missing from object`) + + return NewCloudProjectVolumesValueUnknown(), diags + } + + sizeVal, ok := sizeAttribute.(ovhtypes.TfInt64Value) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`size expected to be ovhtypes.TfInt64Value, was: %T`, sizeAttribute)) + } + + if diags.HasError() { + return NewCloudProjectVolumesValueUnknown(), diags + } + + return CloudProjectVolumesValue{ + Id: idVal, + Name: nameVal, + Size: sizeVal, + state: attr.ValueStateKnown, + }, diags +} + +func NewCloudProjectVolumesValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) CloudProjectVolumesValue { + object, diags := NewCloudProjectVolumesValue(attributeTypes, attributes) + + if diags.HasError() { + // This could potentially be added to the diag package. + diagsStrings := make([]string, 0, len(diags)) + + for _, diagnostic := range diags { + diagsStrings = append(diagsStrings, fmt.Sprintf( + "%s | %s | %s", + diagnostic.Severity(), + diagnostic.Summary(), + diagnostic.Detail())) + } + + panic("NewCloudProjectVolumesValueMust received error(s): " + strings.Join(diagsStrings, "\n")) + } + + return object +} + +func (t CloudProjectVolumesType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) { + if in.Type() == nil { + return NewCloudProjectVolumesValueNull(), nil + } + + if !in.Type().Equal(t.TerraformType(ctx)) { + return nil, fmt.Errorf("expected %s, got %s", t.TerraformType(ctx), in.Type()) + } + + if !in.IsKnown() { + return NewCloudProjectVolumesValueUnknown(), nil + } + + if in.IsNull() { + return NewCloudProjectVolumesValueNull(), nil + } + + attributes := map[string]attr.Value{} + + val := map[string]tftypes.Value{} + + err := in.As(&val) + + if err != nil { + return nil, err + } + + for k, v := range val { + a, err := t.AttrTypes[k].ValueFromTerraform(ctx, v) + + if err != nil { + return nil, err + } + + attributes[k] = a + } + + return NewCloudProjectVolumesValueMust(CloudProjectVolumesValue{}.AttributeTypes(ctx), attributes), nil +} + +func (t CloudProjectVolumesType) ValueType(ctx context.Context) attr.Value { + return CloudProjectVolumesValue{} +} + +var _ basetypes.ObjectValuable = CloudProjectVolumesValue{} + +type CloudProjectVolumesValue struct { + Id ovhtypes.TfStringValue `tfsdk:"id" json:"id"` + Name ovhtypes.TfStringValue `tfsdk:"name" json:"name"` + Size ovhtypes.TfInt64Value `tfsdk:"size" json:"size"` + state attr.ValueState +} + +func (v *CloudProjectVolumesValue) UnmarshalJSON(data []byte) error { + type JsonCloudProjectVolumesValue CloudProjectVolumesValue + + var tmp JsonCloudProjectVolumesValue + if err := json.Unmarshal(data, &tmp); err != nil { + return err + } + v.Id = tmp.Id + v.Name = tmp.Name + v.Size = tmp.Size + + v.state = attr.ValueStateKnown + + return nil +} + +func (v *CloudProjectVolumesValue) MergeWith(other *CloudProjectVolumesValue) { + + if (v.Id.IsUnknown() || v.Id.IsNull()) && !other.Id.IsUnknown() { + v.Id = other.Id + } + + if (v.Name.IsUnknown() || v.Name.IsNull()) && !other.Name.IsUnknown() { + v.Name = other.Name + } + + if (v.Size.IsUnknown() || v.Size.IsNull()) && !other.Size.IsUnknown() { + v.Size = other.Size + } + + if (v.state == attr.ValueStateUnknown || v.state == attr.ValueStateNull) && other.state != attr.ValueStateUnknown { + v.state = other.state + } +} + +func (v CloudProjectVolumesValue) Attributes() map[string]attr.Value { + return map[string]attr.Value{ + "id": v.Id, + "name": v.Name, + "size": v.Size, + } +} +func (v CloudProjectVolumesValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { + attrTypes := make(map[string]tftypes.Type, 3) + + var val tftypes.Value + var err error + + attrTypes["id"] = basetypes.StringType{}.TerraformType(ctx) + attrTypes["name"] = basetypes.StringType{}.TerraformType(ctx) + attrTypes["size"] = basetypes.Int64Type{}.TerraformType(ctx) + + objectType := tftypes.Object{AttributeTypes: attrTypes} + + switch v.state { + case attr.ValueStateKnown: + vals := make(map[string]tftypes.Value, 3) + + val, err = v.Id.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["id"] = val + + val, err = v.Name.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["name"] = val + + val, err = v.Size.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["size"] = val + + if err := tftypes.ValidateValue(objectType, vals); err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + return tftypes.NewValue(objectType, vals), nil + case attr.ValueStateNull: + return tftypes.NewValue(objectType, nil), nil + case attr.ValueStateUnknown: + return tftypes.NewValue(objectType, tftypes.UnknownValue), nil + default: + panic(fmt.Sprintf("unhandled Object state in ToTerraformValue: %s", v.state)) + } +} + +func (v CloudProjectVolumesValue) IsNull() bool { + return v.state == attr.ValueStateNull +} + +func (v CloudProjectVolumesValue) IsUnknown() bool { + return v.state == attr.ValueStateUnknown +} + +func (v CloudProjectVolumesValue) String() string { + return "CloudProjectVolumesValue" +} + +func (v CloudProjectVolumesValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { + var diags diag.Diagnostics + + objVal, diags := types.ObjectValue( + map[string]attr.Type{ + "id": ovhtypes.TfStringType{}, + "name": ovhtypes.TfStringType{}, + "size": ovhtypes.TfInt64Type{}, + }, + map[string]attr.Value{ + "id": v.Id, + "name": v.Name, + "size": v.Size, + }) + + return objVal, diags +} + +func (v CloudProjectVolumesValue) Equal(o attr.Value) bool { + other, ok := o.(CloudProjectVolumesValue) + + if !ok { + return false + } + + if v.state != other.state { + return false + } + + if v.state != attr.ValueStateKnown { + return true + } + + if !v.Id.Equal(other.Id) { + return false + } + + if !v.Name.Equal(other.Name) { + return false + } + + if !v.Size.Equal(other.Size) { + return false + } + + return true +} + +func (v CloudProjectVolumesValue) Type(ctx context.Context) attr.Type { + return CloudProjectVolumesType{ + basetypes.ObjectType{ + AttrTypes: v.AttributeTypes(ctx), + }, + } +} + +func (v CloudProjectVolumesValue) AttributeTypes(ctx context.Context) map[string]attr.Type { + return map[string]attr.Type{ + "id": ovhtypes.TfStringType{}, + "name": ovhtypes.TfStringType{}, + "size": ovhtypes.TfInt64Type{}, + } +} diff --git a/ovh/data_cloud_project_volumes_testgo b/ovh/data_cloud_project_volumes_testgo new file mode 100644 index 000000000..d5a48642b --- /dev/null +++ b/ovh/data_cloud_project_volumes_testgo @@ -0,0 +1,38 @@ +package ovh + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDataSourceCloudProjectVolumes_basic(t *testing.T) { + serviceName := os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST") + regionName := os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST") + volumeId := os.Getenv("OVH_CLOUD_PROJECT_VOLUME_ID_TEST") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheckCloud(t); testAccCheckCloudProjectExists(t) }, + Steps: []resource.TestStep{ + { + Config: fmt.Sprintf(` + data "ovh_cloud_project_volumes" "volume" { + service_name = "%s" + region_name = "%s" + } + `, + serviceName, + regionName, + volumeId, + ), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.ovh_cloud_project_volume.volume", "region_name", os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST")), + resource.TestCheckResourceAttrSet("data.ovh_cloud_project_volume.volume", "volumes.0.name"), + resource.TestCheckResourceAttrSet("data.ovh_cloud_project_volume.volume", "volumes.0.volume_id"), + ), + }, + }, + }) +} diff --git a/ovh/provider_new.go b/ovh/provider_new.go index a8682aa3d..1d764d1e5 100644 --- a/ovh/provider_new.go +++ b/ovh/provider_new.go @@ -196,6 +196,8 @@ func (p *OvhProvider) DataSources(_ context.Context) []func() datasource.DataSou NewCloudProjectNetworkPrivateDataSource, NewCloudProjectNetworkPrivatesDataSource, NewCloudProjectNetworkPrivateSubnetsDataSource, + NewCloudProjectVolumesDataSource, + NewCloudProjectVolumeDataSource, NewCloudProjectDataSource, NewCloudProjectsDataSource, NewDbaasLogsClusterRetentionDataSource, diff --git a/website/docs/d/cloud_project_volume.html.markdown b/website/docs/d/cloud_project_volume.html.markdown new file mode 100644 index 000000000..ea8a4c8d0 --- /dev/null +++ b/website/docs/d/cloud_project_volume.html.markdown @@ -0,0 +1,33 @@ +--- +subcategory : "Cloud Project Volume" +--- + +# ovh_cloud_project_volume + +Get information about a volume in a public cloud project + +## Example Usage + +```hcl +data "ovh_cloud_project_volume" "volume" { + region_name = "xxx" + service_name = "yyy" + volume_id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +} +``` + +## Argument Reference + + +* `service_name` - (Required) The id of the public cloud project. +* `region_name` - (Required) A valid OVHcloud public cloud region name in which the volume is available. Ex.: "GRA11". +* `volume_id` - (Required) Volume id to get the informations + +## Attributes Reference + +* `name` - The name of the volume +E.g.: "GRA", meaning Gravelines, for region "GRA1" +* `region_name` - The region name where volume is available +* `service_name` - The id of the public cloud project. +* `size` - The size of the volume +* `volume_id` - The id of the volume diff --git a/website/docs/d/cloud_project_volumes.html.markdown b/website/docs/d/cloud_project_volumes.html.markdown new file mode 100644 index 000000000..b8c1d1b95 --- /dev/null +++ b/website/docs/d/cloud_project_volumes.html.markdown @@ -0,0 +1,32 @@ +--- +subcategory : "Cloud Project Volume" +--- + +# ovh_cloud_project_volumes + +Get all the volume from a region of a public cloud project + +## Example Usage + +```hcl +data "ovh_cloud_project_volume" "volume" { + region_name = "xxx" + service_name = "yyy" + volume_id = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" +} +``` + +## Argument Reference + + +* `service_name` - (Required) The id of the public cloud project. +* `region_name` - (Required) A valid OVHcloud public cloud region name in which the volume is available. Ex.: "GRA11". +* `volume_id` - (Required) Volume id to get the informations + +## Attributes Reference +* `volumes` - + * `name` - The name of the volume + * `size` - The size of the volume + * `id` - The id of the volume +* `region_name` - The region name where volume is available +* `service_name` - The id of the public cloud project. From 4ab953cbaaa37831cf7d27f411ac1eddff585cc5 Mon Sep 17 00:00:00 2001 From: Thibaut Di Prima Date: Tue, 1 Oct 2024 13:53:22 +0000 Subject: [PATCH 2/5] datasource volume(s) --- ovh/data_cloud_project_volume_test.go | 2 +- ...ct_volumes_testgo => data_cloud_project_volumes_test.go} | 2 -- website/docs/d/cloud_project_volume.html.markdown | 6 ++---- website/docs/d/cloud_project_volumes.html.markdown | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) rename ovh/{data_cloud_project_volumes_testgo => data_cloud_project_volumes_test.go} (93%) diff --git a/ovh/data_cloud_project_volume_test.go b/ovh/data_cloud_project_volume_test.go index 7b24d3af4..5d6a7ff5d 100644 --- a/ovh/data_cloud_project_volume_test.go +++ b/ovh/data_cloud_project_volume_test.go @@ -21,7 +21,7 @@ func TestAccDataSourceCloudProjectVolume_basic(t *testing.T) { data "ovh_cloud_project_volume" "volume" { service_name = "%s" region_name = "%s" - volume_id = "%s" + volume_id = "%s" } `, serviceName, diff --git a/ovh/data_cloud_project_volumes_testgo b/ovh/data_cloud_project_volumes_test.go similarity index 93% rename from ovh/data_cloud_project_volumes_testgo rename to ovh/data_cloud_project_volumes_test.go index d5a48642b..c06de28b7 100644 --- a/ovh/data_cloud_project_volumes_testgo +++ b/ovh/data_cloud_project_volumes_test.go @@ -11,7 +11,6 @@ import ( func TestAccDataSourceCloudProjectVolumes_basic(t *testing.T) { serviceName := os.Getenv("OVH_CLOUD_PROJECT_SERVICE_TEST") regionName := os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST") - volumeId := os.Getenv("OVH_CLOUD_PROJECT_VOLUME_ID_TEST") resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheckCloud(t); testAccCheckCloudProjectExists(t) }, @@ -25,7 +24,6 @@ func TestAccDataSourceCloudProjectVolumes_basic(t *testing.T) { `, serviceName, regionName, - volumeId, ), Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.ovh_cloud_project_volume.volume", "region_name", os.Getenv("OVH_CLOUD_PROJECT_REGION_TEST")), diff --git a/website/docs/d/cloud_project_volume.html.markdown b/website/docs/d/cloud_project_volume.html.markdown index ea8a4c8d0..548a049e8 100644 --- a/website/docs/d/cloud_project_volume.html.markdown +++ b/website/docs/d/cloud_project_volume.html.markdown @@ -1,5 +1,5 @@ --- -subcategory : "Cloud Project Volume" +subcategory : "Cloud Project" --- # ovh_cloud_project_volume @@ -18,15 +18,13 @@ data "ovh_cloud_project_volume" "volume" { ## Argument Reference - * `service_name` - (Required) The id of the public cloud project. * `region_name` - (Required) A valid OVHcloud public cloud region name in which the volume is available. Ex.: "GRA11". * `volume_id` - (Required) Volume id to get the informations ## Attributes Reference -* `name` - The name of the volume -E.g.: "GRA", meaning Gravelines, for region "GRA1" +* `name` - The name of the volume (E.g.: "GRA", meaning Gravelines, for region "GRA1") * `region_name` - The region name where volume is available * `service_name` - The id of the public cloud project. * `size` - The size of the volume diff --git a/website/docs/d/cloud_project_volumes.html.markdown b/website/docs/d/cloud_project_volumes.html.markdown index b8c1d1b95..65269ce32 100644 --- a/website/docs/d/cloud_project_volumes.html.markdown +++ b/website/docs/d/cloud_project_volumes.html.markdown @@ -1,5 +1,5 @@ --- -subcategory : "Cloud Project Volume" +subcategory : "Cloud Project" --- # ovh_cloud_project_volumes From 9a61634627957dd082f77074faff1d3bf35925cc Mon Sep 17 00:00:00 2001 From: Thibaut Di Prima Date: Thu, 3 Oct 2024 07:51:28 +0000 Subject: [PATCH 3/5] datasource volume(s) --- .cds/terraform-provider-ovh.yml | 24 +++++++++++++++++++ .../d/cloud_project_volumes.html.markdown | 1 - 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.cds/terraform-provider-ovh.yml b/.cds/terraform-provider-ovh.yml index 8cbea11ff..7573f5f92 100644 --- a/.cds/terraform-provider-ovh.yml +++ b/.cds/terraform-provider-ovh.yml @@ -375,6 +375,30 @@ workflow: pipeline: terraform-provider-ovh-testacc when: - success + Tests_CloudProjectVolume: + application: terraform-provider-ovh + depends_on: + - terraform-provider-ovh-pre-sweepers + environment: acctests + one_at_a_time: true + parameters: + testargs: -run CloudProjectUser + skipthispipeline: "{{.workflow.terraform-provider-ovh.pip.skipthistest.cloudproject}}" + pipeline: terraform-provider-ovh-testacc + when: + - success + Tests_CloudProjectVolumes: + application: terraform-provider-ovh + depends_on: + - terraform-provider-ovh-pre-sweepers + environment: acctests + one_at_a_time: true + parameters: + testargs: -run CloudProjectUser + skipthispipeline: "{{.workflow.terraform-provider-ovh.pip.skipthistest.cloudproject}}" + pipeline: terraform-provider-ovh-testacc + when: + - success Tests_CloudProjectLoadBalancer: application: terraform-provider-ovh depends_on: diff --git a/website/docs/d/cloud_project_volumes.html.markdown b/website/docs/d/cloud_project_volumes.html.markdown index 65269ce32..baa8285e4 100644 --- a/website/docs/d/cloud_project_volumes.html.markdown +++ b/website/docs/d/cloud_project_volumes.html.markdown @@ -18,7 +18,6 @@ data "ovh_cloud_project_volume" "volume" { ## Argument Reference - * `service_name` - (Required) The id of the public cloud project. * `region_name` - (Required) A valid OVHcloud public cloud region name in which the volume is available. Ex.: "GRA11". * `volume_id` - (Required) Volume id to get the informations From 1bbaf7fd1eb2e6383e823e3f5a6d8a87168d5788 Mon Sep 17 00:00:00 2001 From: Thibaut Di Prima Date: Fri, 11 Oct 2024 13:37:01 +0000 Subject: [PATCH 4/5] datasource volume(s) --- .cds/terraform-provider-ovh.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cds/terraform-provider-ovh.yml b/.cds/terraform-provider-ovh.yml index 7573f5f92..dc3a9fd37 100644 --- a/.cds/terraform-provider-ovh.yml +++ b/.cds/terraform-provider-ovh.yml @@ -382,7 +382,7 @@ workflow: environment: acctests one_at_a_time: true parameters: - testargs: -run CloudProjectUser + testargs: -run CloudProjectVolume skipthispipeline: "{{.workflow.terraform-provider-ovh.pip.skipthistest.cloudproject}}" pipeline: terraform-provider-ovh-testacc when: From 9089a3846f5b175c08e718546acde1f2d6e23e1b Mon Sep 17 00:00:00 2001 From: Arthur Amstutz Date: Fri, 11 Oct 2024 15:38:22 +0000 Subject: [PATCH 5/5] fix: CDS pipeline for Tests_CloudProjectVolume --- .cds/terraform-provider-ovh.yml | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/.cds/terraform-provider-ovh.yml b/.cds/terraform-provider-ovh.yml index dc3a9fd37..c20cc5e43 100644 --- a/.cds/terraform-provider-ovh.yml +++ b/.cds/terraform-provider-ovh.yml @@ -387,18 +387,6 @@ workflow: pipeline: terraform-provider-ovh-testacc when: - success - Tests_CloudProjectVolumes: - application: terraform-provider-ovh - depends_on: - - terraform-provider-ovh-pre-sweepers - environment: acctests - one_at_a_time: true - parameters: - testargs: -run CloudProjectUser - skipthispipeline: "{{.workflow.terraform-provider-ovh.pip.skipthistest.cloudproject}}" - pipeline: terraform-provider-ovh-testacc - when: - - success Tests_CloudProjectLoadBalancer: application: terraform-provider-ovh depends_on: @@ -805,6 +793,7 @@ workflow: - Tests_TestAccCloudProjectRegions - Tests_CloudProjectUser - Tests_CloudProjectLoadBalancer + - Tests_CloudProjectVolume - Tests_DbaasLogs - Tests_DedicatedCeph - Tests_TestAccDedicatedInstallationTemplate