fix: refactor package generation
Some checks failed
CI Workflow / Check GoReleaser config (pull_request) Successful in 13s
Publish / Check GoReleaser config (pull_request) Has been skipped
CI Workflow / CI (pull_request) Failing after 32s
CI Workflow / Code coverage report (pull_request) Has been skipped
Publish / Publish provider (pull_request) Has been skipped

This commit is contained in:
Marcel S. Henselin 2026-01-29 16:58:35 +01:00
parent 37ba538a8e
commit bde40bb3d4
1473 changed files with 1443 additions and 296913 deletions

View file

@ -5,7 +5,7 @@ import (
"fmt"
"net/http"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
postgresflexalpha2 "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/datasources_gen"
postgresflexUtils "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"

View file

@ -25,6 +25,58 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
Description: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
},
"connection_info": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"host": schema.StringAttribute{
Computed: true,
Description: "The host of the instance.",
MarkdownDescription: "The host of the instance.",
},
"port": schema.Int64Attribute{
Computed: true,
Description: "The port of the instance.",
MarkdownDescription: "The port of the instance.",
},
},
CustomType: ConnectionInfoType{
ObjectType: types.ObjectType{
AttrTypes: ConnectionInfoValue{}.AttributeTypes(ctx),
},
},
Computed: true,
Description: "The DNS name and port in the instance overview",
MarkdownDescription: "The DNS name and port in the instance overview",
},
"encryption": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"kek_key_id": schema.StringAttribute{
Computed: true,
Description: "The encryption-key key identifier",
MarkdownDescription: "The encryption-key key identifier",
},
"kek_key_ring_id": schema.StringAttribute{
Computed: true,
Description: "The encryption-key keyring identifier",
MarkdownDescription: "The encryption-key keyring identifier",
},
"kek_key_version": schema.StringAttribute{
Computed: true,
Description: "The encryption-key version",
MarkdownDescription: "The encryption-key version",
},
"service_account": schema.StringAttribute{
Computed: true,
},
},
CustomType: EncryptionType{
ObjectType: types.ObjectType{
AttrTypes: EncryptionValue{}.AttributeTypes(ctx),
},
},
Computed: true,
Description: "The configuration for instance's volume and backup storage encryption.\n\n⚠ **Note:** This feature is in private preview. Supplying this object is only permitted for enabled accounts. If your account does not have access, the request will be rejected.\n",
MarkdownDescription: "The configuration for instance's volume and backup storage encryption.\n\n⚠ **Note:** This feature is in private preview. Supplying this object is only permitted for enabled accounts. If your account does not have access, the request will be rejected.\n",
},
"flavor_id": schema.StringAttribute{
Computed: true,
Description: "The id of the instance flavor.",
@ -141,20 +193,890 @@ func InstanceDataSourceSchema(ctx context.Context) schema.Schema {
}
type InstanceModel struct {
BackupSchedule types.String `tfsdk:"backup_schedule"`
FlavorId types.String `tfsdk:"flavor_id"`
Id types.String `tfsdk:"id"`
InstanceId types.String `tfsdk:"instance_id"`
IsDeletable types.Bool `tfsdk:"is_deletable"`
Name types.String `tfsdk:"name"`
Network NetworkValue `tfsdk:"network"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Replicas types.Int64 `tfsdk:"replicas"`
RetentionDays types.Int64 `tfsdk:"retention_days"`
Status types.String `tfsdk:"status"`
Storage StorageValue `tfsdk:"storage"`
Version types.String `tfsdk:"version"`
BackupSchedule types.String `tfsdk:"backup_schedule"`
ConnectionInfo ConnectionInfoValue `tfsdk:"connection_info"`
Encryption EncryptionValue `tfsdk:"encryption"`
FlavorId types.String `tfsdk:"flavor_id"`
Id types.String `tfsdk:"id"`
InstanceId types.String `tfsdk:"instance_id"`
IsDeletable types.Bool `tfsdk:"is_deletable"`
Name types.String `tfsdk:"name"`
Network NetworkValue `tfsdk:"network"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Replicas types.Int64 `tfsdk:"replicas"`
RetentionDays types.Int64 `tfsdk:"retention_days"`
Status types.String `tfsdk:"status"`
Storage StorageValue `tfsdk:"storage"`
Version types.String `tfsdk:"version"`
}
var _ basetypes.ObjectTypable = ConnectionInfoType{}
type ConnectionInfoType struct {
basetypes.ObjectType
}
func (t ConnectionInfoType) Equal(o attr.Type) bool {
other, ok := o.(ConnectionInfoType)
if !ok {
return false
}
return t.ObjectType.Equal(other.ObjectType)
}
func (t ConnectionInfoType) String() string {
return "ConnectionInfoType"
}
func (t ConnectionInfoType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
var diags diag.Diagnostics
attributes := in.Attributes()
hostAttribute, ok := attributes["host"]
if !ok {
diags.AddError(
"Attribute Missing",
`host is missing from object`)
return nil, diags
}
hostVal, ok := hostAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`host expected to be basetypes.StringValue, was: %T`, hostAttribute))
}
portAttribute, ok := attributes["port"]
if !ok {
diags.AddError(
"Attribute Missing",
`port is missing from object`)
return nil, diags
}
portVal, ok := portAttribute.(basetypes.Int64Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`port expected to be basetypes.Int64Value, was: %T`, portAttribute))
}
if diags.HasError() {
return nil, diags
}
return ConnectionInfoValue{
Host: hostVal,
Port: portVal,
state: attr.ValueStateKnown,
}, diags
}
func NewConnectionInfoValueNull() ConnectionInfoValue {
return ConnectionInfoValue{
state: attr.ValueStateNull,
}
}
func NewConnectionInfoValueUnknown() ConnectionInfoValue {
return ConnectionInfoValue{
state: attr.ValueStateUnknown,
}
}
func NewConnectionInfoValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (ConnectionInfoValue, 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 ConnectionInfoValue Attribute Value",
"While creating a ConnectionInfoValue value, a missing attribute value was detected. "+
"A ConnectionInfoValue 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("ConnectionInfoValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
)
continue
}
if !attributeType.Equal(attribute.Type(ctx)) {
diags.AddError(
"Invalid ConnectionInfoValue Attribute Type",
"While creating a ConnectionInfoValue value, an invalid attribute value was detected. "+
"A ConnectionInfoValue 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("ConnectionInfoValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
fmt.Sprintf("ConnectionInfoValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
)
}
}
for name := range attributes {
_, ok := attributeTypes[name]
if !ok {
diags.AddError(
"Extra ConnectionInfoValue Attribute Value",
"While creating a ConnectionInfoValue value, an extra attribute value was detected. "+
"A ConnectionInfoValue 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 ConnectionInfoValue Attribute Name: %s", name),
)
}
}
if diags.HasError() {
return NewConnectionInfoValueUnknown(), diags
}
hostAttribute, ok := attributes["host"]
if !ok {
diags.AddError(
"Attribute Missing",
`host is missing from object`)
return NewConnectionInfoValueUnknown(), diags
}
hostVal, ok := hostAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`host expected to be basetypes.StringValue, was: %T`, hostAttribute))
}
portAttribute, ok := attributes["port"]
if !ok {
diags.AddError(
"Attribute Missing",
`port is missing from object`)
return NewConnectionInfoValueUnknown(), diags
}
portVal, ok := portAttribute.(basetypes.Int64Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`port expected to be basetypes.Int64Value, was: %T`, portAttribute))
}
if diags.HasError() {
return NewConnectionInfoValueUnknown(), diags
}
return ConnectionInfoValue{
Host: hostVal,
Port: portVal,
state: attr.ValueStateKnown,
}, diags
}
func NewConnectionInfoValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) ConnectionInfoValue {
object, diags := NewConnectionInfoValue(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("NewConnectionInfoValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
}
return object
}
func (t ConnectionInfoType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
if in.Type() == nil {
return NewConnectionInfoValueNull(), 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 NewConnectionInfoValueUnknown(), nil
}
if in.IsNull() {
return NewConnectionInfoValueNull(), 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 NewConnectionInfoValueMust(ConnectionInfoValue{}.AttributeTypes(ctx), attributes), nil
}
func (t ConnectionInfoType) ValueType(ctx context.Context) attr.Value {
return ConnectionInfoValue{}
}
var _ basetypes.ObjectValuable = ConnectionInfoValue{}
type ConnectionInfoValue struct {
Host basetypes.StringValue `tfsdk:"host"`
Port basetypes.Int64Value `tfsdk:"port"`
state attr.ValueState
}
func (v ConnectionInfoValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
attrTypes := make(map[string]tftypes.Type, 2)
var val tftypes.Value
var err error
attrTypes["host"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["port"] = basetypes.Int64Type{}.TerraformType(ctx)
objectType := tftypes.Object{AttributeTypes: attrTypes}
switch v.state {
case attr.ValueStateKnown:
vals := make(map[string]tftypes.Value, 2)
val, err = v.Host.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["host"] = val
val, err = v.Port.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["port"] = 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 ConnectionInfoValue) IsNull() bool {
return v.state == attr.ValueStateNull
}
func (v ConnectionInfoValue) IsUnknown() bool {
return v.state == attr.ValueStateUnknown
}
func (v ConnectionInfoValue) String() string {
return "ConnectionInfoValue"
}
func (v ConnectionInfoValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
var diags diag.Diagnostics
attributeTypes := map[string]attr.Type{
"host": basetypes.StringType{},
"port": basetypes.Int64Type{},
}
if v.IsNull() {
return types.ObjectNull(attributeTypes), diags
}
if v.IsUnknown() {
return types.ObjectUnknown(attributeTypes), diags
}
objVal, diags := types.ObjectValue(
attributeTypes,
map[string]attr.Value{
"host": v.Host,
"port": v.Port,
})
return objVal, diags
}
func (v ConnectionInfoValue) Equal(o attr.Value) bool {
other, ok := o.(ConnectionInfoValue)
if !ok {
return false
}
if v.state != other.state {
return false
}
if v.state != attr.ValueStateKnown {
return true
}
if !v.Host.Equal(other.Host) {
return false
}
if !v.Port.Equal(other.Port) {
return false
}
return true
}
func (v ConnectionInfoValue) Type(ctx context.Context) attr.Type {
return ConnectionInfoType{
basetypes.ObjectType{
AttrTypes: v.AttributeTypes(ctx),
},
}
}
func (v ConnectionInfoValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"host": basetypes.StringType{},
"port": basetypes.Int64Type{},
}
}
var _ basetypes.ObjectTypable = EncryptionType{}
type EncryptionType struct {
basetypes.ObjectType
}
func (t EncryptionType) Equal(o attr.Type) bool {
other, ok := o.(EncryptionType)
if !ok {
return false
}
return t.ObjectType.Equal(other.ObjectType)
}
func (t EncryptionType) String() string {
return "EncryptionType"
}
func (t EncryptionType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
var diags diag.Diagnostics
attributes := in.Attributes()
kekKeyIdAttribute, ok := attributes["kek_key_id"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_id is missing from object`)
return nil, diags
}
kekKeyIdVal, ok := kekKeyIdAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_id expected to be basetypes.StringValue, was: %T`, kekKeyIdAttribute))
}
kekKeyRingIdAttribute, ok := attributes["kek_key_ring_id"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_ring_id is missing from object`)
return nil, diags
}
kekKeyRingIdVal, ok := kekKeyRingIdAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_ring_id expected to be basetypes.StringValue, was: %T`, kekKeyRingIdAttribute))
}
kekKeyVersionAttribute, ok := attributes["kek_key_version"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_version is missing from object`)
return nil, diags
}
kekKeyVersionVal, ok := kekKeyVersionAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_version expected to be basetypes.StringValue, was: %T`, kekKeyVersionAttribute))
}
serviceAccountAttribute, ok := attributes["service_account"]
if !ok {
diags.AddError(
"Attribute Missing",
`service_account is missing from object`)
return nil, diags
}
serviceAccountVal, ok := serviceAccountAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`service_account expected to be basetypes.StringValue, was: %T`, serviceAccountAttribute))
}
if diags.HasError() {
return nil, diags
}
return EncryptionValue{
KekKeyId: kekKeyIdVal,
KekKeyRingId: kekKeyRingIdVal,
KekKeyVersion: kekKeyVersionVal,
ServiceAccount: serviceAccountVal,
state: attr.ValueStateKnown,
}, diags
}
func NewEncryptionValueNull() EncryptionValue {
return EncryptionValue{
state: attr.ValueStateNull,
}
}
func NewEncryptionValueUnknown() EncryptionValue {
return EncryptionValue{
state: attr.ValueStateUnknown,
}
}
func NewEncryptionValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (EncryptionValue, 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 EncryptionValue Attribute Value",
"While creating a EncryptionValue value, a missing attribute value was detected. "+
"A EncryptionValue 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("EncryptionValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
)
continue
}
if !attributeType.Equal(attribute.Type(ctx)) {
diags.AddError(
"Invalid EncryptionValue Attribute Type",
"While creating a EncryptionValue value, an invalid attribute value was detected. "+
"A EncryptionValue 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("EncryptionValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
fmt.Sprintf("EncryptionValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
)
}
}
for name := range attributes {
_, ok := attributeTypes[name]
if !ok {
diags.AddError(
"Extra EncryptionValue Attribute Value",
"While creating a EncryptionValue value, an extra attribute value was detected. "+
"A EncryptionValue 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 EncryptionValue Attribute Name: %s", name),
)
}
}
if diags.HasError() {
return NewEncryptionValueUnknown(), diags
}
kekKeyIdAttribute, ok := attributes["kek_key_id"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_id is missing from object`)
return NewEncryptionValueUnknown(), diags
}
kekKeyIdVal, ok := kekKeyIdAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_id expected to be basetypes.StringValue, was: %T`, kekKeyIdAttribute))
}
kekKeyRingIdAttribute, ok := attributes["kek_key_ring_id"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_ring_id is missing from object`)
return NewEncryptionValueUnknown(), diags
}
kekKeyRingIdVal, ok := kekKeyRingIdAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_ring_id expected to be basetypes.StringValue, was: %T`, kekKeyRingIdAttribute))
}
kekKeyVersionAttribute, ok := attributes["kek_key_version"]
if !ok {
diags.AddError(
"Attribute Missing",
`kek_key_version is missing from object`)
return NewEncryptionValueUnknown(), diags
}
kekKeyVersionVal, ok := kekKeyVersionAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`kek_key_version expected to be basetypes.StringValue, was: %T`, kekKeyVersionAttribute))
}
serviceAccountAttribute, ok := attributes["service_account"]
if !ok {
diags.AddError(
"Attribute Missing",
`service_account is missing from object`)
return NewEncryptionValueUnknown(), diags
}
serviceAccountVal, ok := serviceAccountAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`service_account expected to be basetypes.StringValue, was: %T`, serviceAccountAttribute))
}
if diags.HasError() {
return NewEncryptionValueUnknown(), diags
}
return EncryptionValue{
KekKeyId: kekKeyIdVal,
KekKeyRingId: kekKeyRingIdVal,
KekKeyVersion: kekKeyVersionVal,
ServiceAccount: serviceAccountVal,
state: attr.ValueStateKnown,
}, diags
}
func NewEncryptionValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) EncryptionValue {
object, diags := NewEncryptionValue(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("NewEncryptionValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
}
return object
}
func (t EncryptionType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
if in.Type() == nil {
return NewEncryptionValueNull(), 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 NewEncryptionValueUnknown(), nil
}
if in.IsNull() {
return NewEncryptionValueNull(), 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 NewEncryptionValueMust(EncryptionValue{}.AttributeTypes(ctx), attributes), nil
}
func (t EncryptionType) ValueType(ctx context.Context) attr.Value {
return EncryptionValue{}
}
var _ basetypes.ObjectValuable = EncryptionValue{}
type EncryptionValue struct {
KekKeyId basetypes.StringValue `tfsdk:"kek_key_id"`
KekKeyRingId basetypes.StringValue `tfsdk:"kek_key_ring_id"`
KekKeyVersion basetypes.StringValue `tfsdk:"kek_key_version"`
ServiceAccount basetypes.StringValue `tfsdk:"service_account"`
state attr.ValueState
}
func (v EncryptionValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
attrTypes := make(map[string]tftypes.Type, 4)
var val tftypes.Value
var err error
attrTypes["kek_key_id"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["kek_key_ring_id"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["kek_key_version"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["service_account"] = basetypes.StringType{}.TerraformType(ctx)
objectType := tftypes.Object{AttributeTypes: attrTypes}
switch v.state {
case attr.ValueStateKnown:
vals := make(map[string]tftypes.Value, 4)
val, err = v.KekKeyId.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["kek_key_id"] = val
val, err = v.KekKeyRingId.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["kek_key_ring_id"] = val
val, err = v.KekKeyVersion.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["kek_key_version"] = val
val, err = v.ServiceAccount.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["service_account"] = 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 EncryptionValue) IsNull() bool {
return v.state == attr.ValueStateNull
}
func (v EncryptionValue) IsUnknown() bool {
return v.state == attr.ValueStateUnknown
}
func (v EncryptionValue) String() string {
return "EncryptionValue"
}
func (v EncryptionValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
var diags diag.Diagnostics
attributeTypes := map[string]attr.Type{
"kek_key_id": basetypes.StringType{},
"kek_key_ring_id": basetypes.StringType{},
"kek_key_version": basetypes.StringType{},
"service_account": basetypes.StringType{},
}
if v.IsNull() {
return types.ObjectNull(attributeTypes), diags
}
if v.IsUnknown() {
return types.ObjectUnknown(attributeTypes), diags
}
objVal, diags := types.ObjectValue(
attributeTypes,
map[string]attr.Value{
"kek_key_id": v.KekKeyId,
"kek_key_ring_id": v.KekKeyRingId,
"kek_key_version": v.KekKeyVersion,
"service_account": v.ServiceAccount,
})
return objVal, diags
}
func (v EncryptionValue) Equal(o attr.Value) bool {
other, ok := o.(EncryptionValue)
if !ok {
return false
}
if v.state != other.state {
return false
}
if v.state != attr.ValueStateKnown {
return true
}
if !v.KekKeyId.Equal(other.KekKeyId) {
return false
}
if !v.KekKeyRingId.Equal(other.KekKeyRingId) {
return false
}
if !v.KekKeyVersion.Equal(other.KekKeyVersion) {
return false
}
if !v.ServiceAccount.Equal(other.ServiceAccount) {
return false
}
return true
}
func (v EncryptionValue) Type(ctx context.Context) attr.Type {
return EncryptionType{
basetypes.ObjectType{
AttrTypes: v.AttributeTypes(ctx),
},
}
}
func (v EncryptionValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"kek_key_id": basetypes.StringType{},
"kek_key_ring_id": basetypes.StringType{},
"kek_key_version": basetypes.StringType{},
"service_account": basetypes.StringType{},
}
}
var _ basetypes.ObjectTypable = NetworkType{}

View file

@ -8,7 +8,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-log/tflog"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
postgresflexalphadatasource "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/datasources_gen"
postgresflexalpharesource "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/utils"

View file

@ -1,7 +1,7 @@
package postgresflexalpha
import (
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
)

View file

@ -13,7 +13,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource/identityschema"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg_gen/postgresflexalpha"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/core"
postgresflexalpha "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance/resources_gen"

View file

@ -27,6 +27,28 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
Description: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
MarkdownDescription: "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
},
"connection_info": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"host": schema.StringAttribute{
Computed: true,
Description: "The host of the instance.",
MarkdownDescription: "The host of the instance.",
},
"port": schema.Int64Attribute{
Computed: true,
Description: "The port of the instance.",
MarkdownDescription: "The port of the instance.",
},
},
CustomType: ConnectionInfoType{
ObjectType: types.ObjectType{
AttrTypes: ConnectionInfoValue{}.AttributeTypes(ctx),
},
},
Computed: true,
Description: "The DNS name and port in the instance overview",
MarkdownDescription: "The DNS name and port in the instance overview",
},
"encryption": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
"kek_key_id": schema.StringAttribute{
@ -193,21 +215,401 @@ func InstanceResourceSchema(ctx context.Context) schema.Schema {
}
type InstanceModel struct {
BackupSchedule types.String `tfsdk:"backup_schedule"`
Encryption EncryptionValue `tfsdk:"encryption"`
FlavorId types.String `tfsdk:"flavor_id"`
Id types.String `tfsdk:"id"`
InstanceId types.String `tfsdk:"instance_id"`
IsDeletable types.Bool `tfsdk:"is_deletable"`
Name types.String `tfsdk:"name"`
Network NetworkValue `tfsdk:"network"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Replicas types.Int64 `tfsdk:"replicas"`
RetentionDays types.Int64 `tfsdk:"retention_days"`
Status types.String `tfsdk:"status"`
Storage StorageValue `tfsdk:"storage"`
Version types.String `tfsdk:"version"`
BackupSchedule types.String `tfsdk:"backup_schedule"`
ConnectionInfo ConnectionInfoValue `tfsdk:"connection_info"`
Encryption EncryptionValue `tfsdk:"encryption"`
FlavorId types.String `tfsdk:"flavor_id"`
Id types.String `tfsdk:"id"`
InstanceId types.String `tfsdk:"instance_id"`
IsDeletable types.Bool `tfsdk:"is_deletable"`
Name types.String `tfsdk:"name"`
Network NetworkValue `tfsdk:"network"`
ProjectId types.String `tfsdk:"project_id"`
Region types.String `tfsdk:"region"`
Replicas types.Int64 `tfsdk:"replicas"`
RetentionDays types.Int64 `tfsdk:"retention_days"`
Status types.String `tfsdk:"status"`
Storage StorageValue `tfsdk:"storage"`
Version types.String `tfsdk:"version"`
}
var _ basetypes.ObjectTypable = ConnectionInfoType{}
type ConnectionInfoType struct {
basetypes.ObjectType
}
func (t ConnectionInfoType) Equal(o attr.Type) bool {
other, ok := o.(ConnectionInfoType)
if !ok {
return false
}
return t.ObjectType.Equal(other.ObjectType)
}
func (t ConnectionInfoType) String() string {
return "ConnectionInfoType"
}
func (t ConnectionInfoType) ValueFromObject(ctx context.Context, in basetypes.ObjectValue) (basetypes.ObjectValuable, diag.Diagnostics) {
var diags diag.Diagnostics
attributes := in.Attributes()
hostAttribute, ok := attributes["host"]
if !ok {
diags.AddError(
"Attribute Missing",
`host is missing from object`)
return nil, diags
}
hostVal, ok := hostAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`host expected to be basetypes.StringValue, was: %T`, hostAttribute))
}
portAttribute, ok := attributes["port"]
if !ok {
diags.AddError(
"Attribute Missing",
`port is missing from object`)
return nil, diags
}
portVal, ok := portAttribute.(basetypes.Int64Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`port expected to be basetypes.Int64Value, was: %T`, portAttribute))
}
if diags.HasError() {
return nil, diags
}
return ConnectionInfoValue{
Host: hostVal,
Port: portVal,
state: attr.ValueStateKnown,
}, diags
}
func NewConnectionInfoValueNull() ConnectionInfoValue {
return ConnectionInfoValue{
state: attr.ValueStateNull,
}
}
func NewConnectionInfoValueUnknown() ConnectionInfoValue {
return ConnectionInfoValue{
state: attr.ValueStateUnknown,
}
}
func NewConnectionInfoValue(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) (ConnectionInfoValue, 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 ConnectionInfoValue Attribute Value",
"While creating a ConnectionInfoValue value, a missing attribute value was detected. "+
"A ConnectionInfoValue 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("ConnectionInfoValue Attribute Name (%s) Expected Type: %s", name, attributeType.String()),
)
continue
}
if !attributeType.Equal(attribute.Type(ctx)) {
diags.AddError(
"Invalid ConnectionInfoValue Attribute Type",
"While creating a ConnectionInfoValue value, an invalid attribute value was detected. "+
"A ConnectionInfoValue 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("ConnectionInfoValue Attribute Name (%s) Expected Type: %s\n", name, attributeType.String())+
fmt.Sprintf("ConnectionInfoValue Attribute Name (%s) Given Type: %s", name, attribute.Type(ctx)),
)
}
}
for name := range attributes {
_, ok := attributeTypes[name]
if !ok {
diags.AddError(
"Extra ConnectionInfoValue Attribute Value",
"While creating a ConnectionInfoValue value, an extra attribute value was detected. "+
"A ConnectionInfoValue 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 ConnectionInfoValue Attribute Name: %s", name),
)
}
}
if diags.HasError() {
return NewConnectionInfoValueUnknown(), diags
}
hostAttribute, ok := attributes["host"]
if !ok {
diags.AddError(
"Attribute Missing",
`host is missing from object`)
return NewConnectionInfoValueUnknown(), diags
}
hostVal, ok := hostAttribute.(basetypes.StringValue)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`host expected to be basetypes.StringValue, was: %T`, hostAttribute))
}
portAttribute, ok := attributes["port"]
if !ok {
diags.AddError(
"Attribute Missing",
`port is missing from object`)
return NewConnectionInfoValueUnknown(), diags
}
portVal, ok := portAttribute.(basetypes.Int64Value)
if !ok {
diags.AddError(
"Attribute Wrong Type",
fmt.Sprintf(`port expected to be basetypes.Int64Value, was: %T`, portAttribute))
}
if diags.HasError() {
return NewConnectionInfoValueUnknown(), diags
}
return ConnectionInfoValue{
Host: hostVal,
Port: portVal,
state: attr.ValueStateKnown,
}, diags
}
func NewConnectionInfoValueMust(attributeTypes map[string]attr.Type, attributes map[string]attr.Value) ConnectionInfoValue {
object, diags := NewConnectionInfoValue(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("NewConnectionInfoValueMust received error(s): " + strings.Join(diagsStrings, "\n"))
}
return object
}
func (t ConnectionInfoType) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
if in.Type() == nil {
return NewConnectionInfoValueNull(), 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 NewConnectionInfoValueUnknown(), nil
}
if in.IsNull() {
return NewConnectionInfoValueNull(), 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 NewConnectionInfoValueMust(ConnectionInfoValue{}.AttributeTypes(ctx), attributes), nil
}
func (t ConnectionInfoType) ValueType(ctx context.Context) attr.Value {
return ConnectionInfoValue{}
}
var _ basetypes.ObjectValuable = ConnectionInfoValue{}
type ConnectionInfoValue struct {
Host basetypes.StringValue `tfsdk:"host"`
Port basetypes.Int64Value `tfsdk:"port"`
state attr.ValueState
}
func (v ConnectionInfoValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
attrTypes := make(map[string]tftypes.Type, 2)
var val tftypes.Value
var err error
attrTypes["host"] = basetypes.StringType{}.TerraformType(ctx)
attrTypes["port"] = basetypes.Int64Type{}.TerraformType(ctx)
objectType := tftypes.Object{AttributeTypes: attrTypes}
switch v.state {
case attr.ValueStateKnown:
vals := make(map[string]tftypes.Value, 2)
val, err = v.Host.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["host"] = val
val, err = v.Port.ToTerraformValue(ctx)
if err != nil {
return tftypes.NewValue(objectType, tftypes.UnknownValue), err
}
vals["port"] = 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 ConnectionInfoValue) IsNull() bool {
return v.state == attr.ValueStateNull
}
func (v ConnectionInfoValue) IsUnknown() bool {
return v.state == attr.ValueStateUnknown
}
func (v ConnectionInfoValue) String() string {
return "ConnectionInfoValue"
}
func (v ConnectionInfoValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) {
var diags diag.Diagnostics
attributeTypes := map[string]attr.Type{
"host": basetypes.StringType{},
"port": basetypes.Int64Type{},
}
if v.IsNull() {
return types.ObjectNull(attributeTypes), diags
}
if v.IsUnknown() {
return types.ObjectUnknown(attributeTypes), diags
}
objVal, diags := types.ObjectValue(
attributeTypes,
map[string]attr.Value{
"host": v.Host,
"port": v.Port,
})
return objVal, diags
}
func (v ConnectionInfoValue) Equal(o attr.Value) bool {
other, ok := o.(ConnectionInfoValue)
if !ok {
return false
}
if v.state != other.state {
return false
}
if v.state != attr.ValueStateKnown {
return true
}
if !v.Host.Equal(other.Host) {
return false
}
if !v.Port.Equal(other.Port) {
return false
}
return true
}
func (v ConnectionInfoValue) Type(ctx context.Context) attr.Type {
return ConnectionInfoType{
basetypes.ObjectType{
AttrTypes: v.AttributeTypes(ctx),
},
}
}
func (v ConnectionInfoValue) AttributeTypes(ctx context.Context) map[string]attr.Type {
return map[string]attr.Type{
"host": basetypes.StringType{},
"port": basetypes.Int64Type{},
}
}
var _ basetypes.ObjectTypable = EncryptionType{}