chore: updated files - work save

This commit is contained in:
Marcel S. Henselin 2026-01-21 16:29:22 +01:00
parent 51663cd8d0
commit e91e10e29a
37 changed files with 1121 additions and 118 deletions

View file

@ -29,6 +29,8 @@ builds:
ignore: ignore:
- goos: darwin - goos: darwin
goarch: '386' goarch: '386'
- goos: windows
goarch: 'arm6'
binary: '{{ .ProjectName }}_v{{ .Version }}' binary: '{{ .ProjectName }}_v{{ .Version }}'
archives: archives:
- formats: [ 'zip' ] - formats: [ 'zip' ]

View file

@ -0,0 +1,31 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackitprivatepreview_sqlserverflexalpha_database Data Source - stackitprivatepreview"
subcategory: ""
description: |-
---
# stackitprivatepreview_sqlserverflexalpha_database (Data Source)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `database_name` (String) The name of the database.
- `instance_id` (String) The ID of the instance.
- `project_id` (String) The STACKIT project ID.
- `region` (String) The region which should be addressed
### Read-Only
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
- `compatibility_level` (Number) CompatibilityLevel of the Database.
- `id` (Number) The id of the database.
- `name` (String) The name of the database.
- `owner` (String) The owner of the database.

View file

@ -0,0 +1,36 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackitprivatepreview_sqlserverflexalpha_database Resource - stackitprivatepreview"
subcategory: ""
description: |-
---
# stackitprivatepreview_sqlserverflexalpha_database (Resource)
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `name` (String) The name of the database.
- `owner` (String) The owner of the database.
### Optional
- `collation` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
- `compatibility` (Number) CompatibilityLevel of the Database.
- `database_name` (String) The name of the database.
- `instance_id` (String) The ID of the instance.
- `project_id` (String) The STACKIT project ID.
- `region` (String) The region which should be addressed
### Read-Only
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
- `compatibility_level` (Number) CompatibilityLevel of the Database.
- `id` (Number) The id of the database.

View file

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -82,22 +82,42 @@ type InstanceGetConsumedObjectStorageArgType = string
type InstanceGetConsumedObjectStorageRetType = string type InstanceGetConsumedObjectStorageRetType = string
/* /*
types and functions for created_at types and functions for created
*/ */
// isDateTime // isDateTime
type InstanceGetCreatedAtAttributeType = *time.Time type InstanceGetCreatedAttributeType = *time.Time
type InstanceGetCreatedAtArgType = time.Time type InstanceGetCreatedArgType = time.Time
type InstanceGetCreatedAtRetType = time.Time type InstanceGetCreatedRetType = time.Time
func getInstanceGetCreatedAtAttributeTypeOk(arg InstanceGetCreatedAtAttributeType) (ret InstanceGetCreatedAtRetType, ok bool) { func getInstanceGetCreatedAttributeTypeOk(arg InstanceGetCreatedAttributeType) (ret InstanceGetCreatedRetType, ok bool) {
if arg == nil { if arg == nil {
return ret, false return ret, false
} }
return *arg, true return *arg, true
} }
func setInstanceGetCreatedAtAttributeType(arg *InstanceGetCreatedAtAttributeType, val InstanceGetCreatedAtRetType) { func setInstanceGetCreatedAttributeType(arg *InstanceGetCreatedAttributeType, val InstanceGetCreatedRetType) {
*arg = &val
}
/*
types and functions for feature_toggle
*/
// isModel
type InstanceGetFeatureToggleAttributeType = *FeatureToggle
type InstanceGetFeatureToggleArgType = FeatureToggle
type InstanceGetFeatureToggleRetType = FeatureToggle
func getInstanceGetFeatureToggleAttributeTypeOk(arg InstanceGetFeatureToggleAttributeType) (ret InstanceGetFeatureToggleRetType, ok bool) {
if arg == nil {
return ret, false
}
return *arg, true
}
func setInstanceGetFeatureToggleAttributeType(arg *InstanceGetFeatureToggleAttributeType, val InstanceGetFeatureToggleRetType) {
*arg = &val *arg = &val
} }
@ -351,7 +371,9 @@ type Instance struct {
ConsumedObjectStorage InstanceGetConsumedObjectStorageAttributeType `json:"consumed_object_storage" required:"true"` ConsumedObjectStorage InstanceGetConsumedObjectStorageAttributeType `json:"consumed_object_storage" required:"true"`
// The date and time the creation of the STACKIT Git instance was triggered. // The date and time the creation of the STACKIT Git instance was triggered.
// REQUIRED // REQUIRED
CreatedAt InstanceGetCreatedAtAttributeType `json:"created_at" required:"true"` Created InstanceGetCreatedAttributeType `json:"created" required:"true"`
// REQUIRED
FeatureToggle InstanceGetFeatureToggleAttributeType `json:"feature_toggle" required:"true"`
// Instance flavor. // Instance flavor.
// REQUIRED // REQUIRED
Flavor InstanceGetFlavorAttributeType `json:"flavor" required:"true"` Flavor InstanceGetFlavorAttributeType `json:"flavor" required:"true"`
@ -378,12 +400,13 @@ type _Instance Instance
// This constructor will assign default values to properties that have it defined, // This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments // and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed // will change when the set of required properties is changed
func NewInstance(acl InstanceGetAclArgType, consumedDisk InstanceGetConsumedDiskArgType, consumedObjectStorage InstanceGetConsumedObjectStorageArgType, createdAt InstanceGetCreatedAtArgType, flavor InstanceGetFlavorArgType, id InstanceGetIdArgType, name InstanceGetNameArgType, state InstanceGetStateArgType, url InstanceGetUrlArgType, version InstanceGetVersionArgType) *Instance { func NewInstance(acl InstanceGetAclArgType, consumedDisk InstanceGetConsumedDiskArgType, consumedObjectStorage InstanceGetConsumedObjectStorageArgType, created InstanceGetCreatedArgType, featureToggle InstanceGetFeatureToggleArgType, flavor InstanceGetFlavorArgType, id InstanceGetIdArgType, name InstanceGetNameArgType, state InstanceGetStateArgType, url InstanceGetUrlArgType, version InstanceGetVersionArgType) *Instance {
this := Instance{} this := Instance{}
setInstanceGetAclAttributeType(&this.Acl, acl) setInstanceGetAclAttributeType(&this.Acl, acl)
setInstanceGetConsumedDiskAttributeType(&this.ConsumedDisk, consumedDisk) setInstanceGetConsumedDiskAttributeType(&this.ConsumedDisk, consumedDisk)
setInstanceGetConsumedObjectStorageAttributeType(&this.ConsumedObjectStorage, consumedObjectStorage) setInstanceGetConsumedObjectStorageAttributeType(&this.ConsumedObjectStorage, consumedObjectStorage)
setInstanceGetCreatedAtAttributeType(&this.CreatedAt, createdAt) setInstanceGetCreatedAttributeType(&this.Created, created)
setInstanceGetFeatureToggleAttributeType(&this.FeatureToggle, featureToggle)
setInstanceGetFlavorAttributeType(&this.Flavor, flavor) setInstanceGetFlavorAttributeType(&this.Flavor, flavor)
setInstanceGetIdAttributeType(&this.Id, id) setInstanceGetIdAttributeType(&this.Id, id)
setInstanceGetNameAttributeType(&this.Name, name) setInstanceGetNameAttributeType(&this.Name, name)
@ -452,21 +475,38 @@ func (o *Instance) SetConsumedObjectStorage(v InstanceGetConsumedObjectStorageRe
setInstanceGetConsumedObjectStorageAttributeType(&o.ConsumedObjectStorage, v) setInstanceGetConsumedObjectStorageAttributeType(&o.ConsumedObjectStorage, v)
} }
// GetCreatedAt returns the CreatedAt field value // GetCreated returns the Created field value
func (o *Instance) GetCreatedAt() (ret InstanceGetCreatedAtRetType) { func (o *Instance) GetCreated() (ret InstanceGetCreatedRetType) {
ret, _ = o.GetCreatedAtOk() ret, _ = o.GetCreatedOk()
return ret return ret
} }
// GetCreatedAtOk returns a tuple with the CreatedAt field value // GetCreatedOk returns a tuple with the Created field value
// and a boolean to check if the value has been set. // and a boolean to check if the value has been set.
func (o *Instance) GetCreatedAtOk() (ret InstanceGetCreatedAtRetType, ok bool) { func (o *Instance) GetCreatedOk() (ret InstanceGetCreatedRetType, ok bool) {
return getInstanceGetCreatedAtAttributeTypeOk(o.CreatedAt) return getInstanceGetCreatedAttributeTypeOk(o.Created)
} }
// SetCreatedAt sets field value // SetCreated sets field value
func (o *Instance) SetCreatedAt(v InstanceGetCreatedAtRetType) { func (o *Instance) SetCreated(v InstanceGetCreatedRetType) {
setInstanceGetCreatedAtAttributeType(&o.CreatedAt, v) setInstanceGetCreatedAttributeType(&o.Created, v)
}
// GetFeatureToggle returns the FeatureToggle field value
func (o *Instance) GetFeatureToggle() (ret InstanceGetFeatureToggleRetType) {
ret, _ = o.GetFeatureToggleOk()
return ret
}
// GetFeatureToggleOk returns a tuple with the FeatureToggle field value
// and a boolean to check if the value has been set.
func (o *Instance) GetFeatureToggleOk() (ret InstanceGetFeatureToggleRetType, ok bool) {
return getInstanceGetFeatureToggleAttributeTypeOk(o.FeatureToggle)
}
// SetFeatureToggle sets field value
func (o *Instance) SetFeatureToggle(v InstanceGetFeatureToggleRetType) {
setInstanceGetFeatureToggleAttributeType(&o.FeatureToggle, v)
} }
// GetFlavor returns the Flavor field value // GetFlavor returns the Flavor field value
@ -582,8 +622,11 @@ func (o Instance) ToMap() (map[string]interface{}, error) {
if val, ok := getInstanceGetConsumedObjectStorageAttributeTypeOk(o.ConsumedObjectStorage); ok { if val, ok := getInstanceGetConsumedObjectStorageAttributeTypeOk(o.ConsumedObjectStorage); ok {
toSerialize["ConsumedObjectStorage"] = val toSerialize["ConsumedObjectStorage"] = val
} }
if val, ok := getInstanceGetCreatedAtAttributeTypeOk(o.CreatedAt); ok { if val, ok := getInstanceGetCreatedAttributeTypeOk(o.Created); ok {
toSerialize["CreatedAt"] = val toSerialize["Created"] = val
}
if val, ok := getInstanceGetFeatureToggleAttributeTypeOk(o.FeatureToggle); ok {
toSerialize["FeatureToggle"] = val
} }
if val, ok := getInstanceGetFlavorAttributeTypeOk(o.Flavor); ok { if val, ok := getInstanceGetFlavorAttributeTypeOk(o.Flavor); ok {
toSerialize["Flavor"] = val toSerialize["Flavor"] = val

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -17,6 +17,26 @@ import (
// checks if the CreateInstanceRequestPayload type satisfies the MappedNullable interface at compile time // checks if the CreateInstanceRequestPayload type satisfies the MappedNullable interface at compile time
var _ MappedNullable = &CreateInstanceRequestPayload{} var _ MappedNullable = &CreateInstanceRequestPayload{}
/*
types and functions for acl
*/
// isModel
type CreateInstancePayloadGetAclAttributeType = *[]string
type CreateInstancePayloadGetAclArgType = *[]string
type CreateInstancePayloadGetAclRetType = []string
func getCreateInstancePayloadGetAclAttributeTypeOk(arg CreateInstancePayloadGetAclAttributeType) (ret CreateInstancePayloadGetAclRetType, ok bool) {
if arg == nil {
return ret, false
}
return *arg, true
}
func setCreateInstancePayloadGetAclAttributeType(arg *CreateInstancePayloadGetAclAttributeType, val CreateInstancePayloadGetAclRetType) {
*arg = &val
}
/* /*
types and functions for backupSchedule types and functions for backupSchedule
*/ */
@ -203,6 +223,8 @@ type CreateInstanceRequestPayloadGetVersionRetType = string
// CreateInstanceRequestPayload struct for CreateInstanceRequestPayload // CreateInstanceRequestPayload struct for CreateInstanceRequestPayload
type CreateInstanceRequestPayload struct { type CreateInstanceRequestPayload struct {
// REQUIRED
Acl CreateInstancePayloadGetAclAttributeType `json:"acl" required:"true"`
// The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule. // The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.
// REQUIRED // REQUIRED
BackupSchedule CreateInstanceRequestPayloadGetBackupScheduleAttributeType `json:"backupSchedule" required:"true"` BackupSchedule CreateInstanceRequestPayloadGetBackupScheduleAttributeType `json:"backupSchedule" required:"true"`

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -501,10 +501,7 @@ func addFile(w *multipart.Writer, fieldName, path string) error {
if err != nil { if err != nil {
return err return err
} }
err = file.Close() defer file.Close()
if err != nil {
return err
}
part, err := w.CreateFormFile(fieldName, filepath.Base(path)) part, err := w.CreateFormFile(fieldName, filepath.Base(path))
if err != nil { if err != nil {

View file

@ -51,7 +51,7 @@ resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbuser" {
} }
resource "stackitprivatepreview_postgresflexalpha_database" "example" { resource "stackitprivatepreview_postgresflexalpha_database" "example" {
count = 25 count = 5
depends_on = [stackitprivatepreview_postgresflexalpha_user.ptlsdbadminuser] depends_on = [stackitprivatepreview_postgresflexalpha_user.ptlsdbadminuser]
project_id = var.project_id project_id = var.project_id
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id

View file

@ -3,6 +3,10 @@ provider:
resources: resources:
database: database:
schema:
attributes:
aliases:
id: database_id
create: create:
path: /v3alpha1/projects/{projectId}/regions/{region}/instances/{instanceId}/databases path: /v3alpha1/projects/{projectId}/regions/{region}/instances/{instanceId}/databases
method: POST method: POST
@ -21,6 +25,9 @@ data_sources:
method: GET method: GET
database: database:
attributes:
aliases:
id: database_id
read: read:
path: /v3alpha1/projects/{projectId}/regions/{region}/instances/{instanceId}/databases/{databaseName} path: /v3alpha1/projects/{projectId}/regions/{region}/instances/{instanceId}/databases/{databaseName}
method: GET method: GET

View file

@ -211,7 +211,7 @@ func (r *instanceResource) Create(
func modelToCreateInstancePayload(netAcl []string, model postgresflexalpha.InstanceModel, replVal int32) postgresflex.CreateInstanceRequestPayload { func modelToCreateInstancePayload(netAcl []string, model postgresflexalpha.InstanceModel, replVal int32) postgresflex.CreateInstanceRequestPayload {
payload := postgresflex.CreateInstanceRequestPayload{ payload := postgresflex.CreateInstanceRequestPayload{
// Acl: &netAcl, Acl: &netAcl,
BackupSchedule: model.BackupSchedule.ValueStringPointer(), BackupSchedule: model.BackupSchedule.ValueStringPointer(),
Encryption: &postgresflex.InstanceEncryption{ Encryption: &postgresflex.InstanceEncryption{
KekKeyId: model.Encryption.KekKeyId.ValueStringPointer(), KekKeyId: model.Encryption.KekKeyId.ValueStringPointer(),

View file

@ -0,0 +1,48 @@
package sqlserverflexalpha
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var _ datasource.DataSource = (*backupDataSource)(nil)
func NewBackupDataSource() datasource.DataSource {
return &backupDataSource{}
}
type backupDataSource struct{}
type backupDataSourceModel struct {
Id types.String `tfsdk:"id"`
}
func (d *backupDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "sqlserverflexalpha_backup"
}
func (d *backupDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = sqlserverflexalphaGen.BackupDataSourceSchema(ctx)
}
func (d *backupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data sqlserverflexalphaGen.backupDataSourceModel
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Example data value setting
data.Id = types.StringValue("example-id")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

View file

@ -0,0 +1,48 @@
package sqlserverflexalpha
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var _ datasource.DataSource = (*collationDataSource)(nil)
func NewCollationDataSource() datasource.DataSource {
return &collationDataSource{}
}
type collationDataSource struct{}
type collationDataSourceModel struct {
Id types.String `tfsdk:"id"`
}
func (d *collationDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "sqlserverflexalpha_collation"
}
func (d *collationDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = sqlserverflexalphaGen.CollationDataSourceSchema(ctx)
}
func (d *collationDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data sqlserverflexalphaGen.collationDataSourceModel
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Example data value setting
data.Id = types.StringValue("example-id")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

View file

@ -0,0 +1,49 @@
package sqlserverflexalpha
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/types"
sqlserverflexalphaGen "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/datasources_gen"
)
var _ datasource.DataSource = (*databaseDataSource)(nil)
func NewDatabaseDataSource() datasource.DataSource {
return &databaseDataSource{}
}
type databaseDataSource struct{}
type databaseDataSourceModel struct {
Id types.String `tfsdk:"id"`
}
func (d *databaseDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_sqlserverflexalpha_database"
}
func (d *databaseDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = sqlserverflexalphaGen.DatabaseDataSourceSchema(ctx)
}
func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data sqlserverflexalphaGen.DatabaseModel
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Example data value setting
// data.Id = types.StringValue("example-id")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

View file

@ -0,0 +1,217 @@
package sqlserverflexalpha
import (
"context"
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/sqlserverflexalpha"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/core"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/utils"
sqlserverflexalphaGen "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database/resources_gen"
)
var (
_ resource.Resource = &databaseResource{}
_ resource.ResourceWithConfigure = &databaseResource{}
_ resource.ResourceWithImportState = &databaseResource{}
_ resource.ResourceWithModifyPlan = &databaseResource{}
)
func NewDatabaseResource() resource.Resource {
return &databaseResource{}
}
type databaseResource struct {
client *sqlserverflexalpha.APIClient
providerData core.ProviderData
}
func (r *databaseResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_sqlserverflexalpha_database"
}
func (r *databaseResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = sqlserverflexalphaGen.DatabaseResourceSchema(ctx)
}
// Configure adds the provider configured client to the resource.
func (r *databaseResource) Configure(
ctx context.Context,
req resource.ConfigureRequest,
resp *resource.ConfigureResponse,
) {
var ok bool
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
if !ok {
return
}
apiClientConfigOptions := []config.ConfigurationOption{
config.WithCustomAuth(r.providerData.RoundTripper),
utils.UserAgentConfigOption(r.providerData.Version),
}
if r.providerData.PostgresFlexCustomEndpoint != "" {
apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(r.providerData.PostgresFlexCustomEndpoint))
} else {
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(r.providerData.GetRegion()))
}
apiClient, err := sqlserverflexalpha.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError(
"Error configuring API client",
fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err),
)
return
}
r.client = apiClient
tflog.Info(ctx, "sqlserverflexalpha.Database client configured")
}
func (r *databaseResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data sqlserverflexalphaGen.DatabaseModel
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// TODO: Create API call logic
// Example data value setting
//data.DatabaseId = types.StringValue("id-from-response")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "sqlserverflexalpha.Database created")
}
func (r *databaseResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data sqlserverflexalphaGen.DatabaseModel
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "sqlserverflexalpha.Database read")
}
func (r *databaseResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data sqlserverflexalphaGen.DatabaseModel
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Update API call logic
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "sqlserverflexalpha.Database updated")
}
func (r *databaseResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data sqlserverflexalphaGen.DatabaseModel
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Delete API call logic
tflog.Info(ctx, "sqlserverflexalpha.Database deleted")
}
// ModifyPlan implements resource.ResourceWithModifyPlan.
// Use the modifier to set the effective region in the current plan.
func (r *databaseResource) ModifyPlan(
ctx context.Context,
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
var configModel sqlserverflexalphaGen.DatabaseModel
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return
}
resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...)
if resp.Diagnostics.HasError() {
return
}
var planModel sqlserverflexalphaGen.DatabaseModel
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
if resp.Diagnostics.HasError() {
return
}
utils.AdaptRegion(ctx, configModel.Region, &planModel.Region, r.providerData.GetRegion(), resp)
if resp.Diagnostics.HasError() {
return
}
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
if resp.Diagnostics.HasError() {
return
}
}
// ImportState imports a resource into the Terraform state on success.
// The expected format of the resource import identifier is: project_id,zone_id,record_set_id
func (r *databaseResource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
idParts := strings.Split(req.ID, core.Separator)
// Todo: Import logic
if len(idParts) < 2 || idParts[0] == "" || idParts[1] == "" {
core.LogAndAddError(
ctx, &resp.Diagnostics,
"Error importing database",
fmt.Sprintf(
"Expected import identifier with format [project_id],[region],..., got %q",
req.ID,
),
)
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("region"), idParts[1])...)
// ... more ...
core.LogAndAddWarning(
ctx,
&resp.Diagnostics,
"Sqlserverflexalpha database imported with empty password",
"The database password is not imported as it is only available upon creation of a new database. The password field will be empty.",
)
tflog.Info(ctx, "Sqlserverflexalpha database state imported")
}

View file

@ -0,0 +1,48 @@
package sqlserverflexalpha
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
)
var _ datasource.DataSource = (*versionDataSource)(nil)
func NewVersionDataSource() datasource.DataSource {
return &versionDataSource{}
}
type versionDataSource struct{}
type versionDataSourceModel struct {
Id types.String `tfsdk:"id"`
}
func (d *versionDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "sqlserverflexalpha_version"
}
func (d *versionDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = sqlserverflexalphaGen.VersionDataSourceSchema(ctx)
}
func (d *versionDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data sqlserverflexalphaGen.versionDataSourceModel
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Example data value setting
data.Id = types.StringValue("example-id")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

View file

@ -22,6 +22,7 @@ import (
postgresFlexAlphaFlavor "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor" postgresFlexAlphaFlavor "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/flavor"
postgresFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance" postgresFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/instance"
postgresFlexAlphaUser "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user" postgresFlexAlphaUser "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/user"
sqlserverflexalpha "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/database"
sqlserverFlexAlphaFlavor "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavor" sqlserverFlexAlphaFlavor "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/flavor"
sqlServerFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance" sqlServerFlexAlphaInstance "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/instance"
sqlserverFlexAlphaUser "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user" sqlserverFlexAlphaUser "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexalpha/user"
@ -499,6 +500,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
sqlserverFlexAlphaFlavor.NewFlavorDataSource, sqlserverFlexAlphaFlavor.NewFlavorDataSource,
sqlServerFlexAlphaInstance.NewInstanceDataSource, sqlServerFlexAlphaInstance.NewInstanceDataSource,
sqlserverFlexAlphaUser.NewUserDataSource, sqlserverFlexAlphaUser.NewUserDataSource,
sqlserverflexalpha.NewDatabaseDataSource,
} }
} }
@ -510,6 +512,7 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
postgresFlexAlphaUser.NewUserResource, postgresFlexAlphaUser.NewUserResource,
sqlServerFlexAlphaInstance.NewInstanceResource, sqlServerFlexAlphaInstance.NewInstanceResource,
sqlserverFlexAlphaUser.NewUserResource, sqlserverFlexAlphaUser.NewUserResource,
sqlserverflexalpha.NewDatabaseResource,
} }
return resources return resources
} }

53
tools/formats.go Normal file
View file

@ -0,0 +1,53 @@
package tools
import (
"regexp"
"strings"
"unicode"
"unicode/utf8"
)
// snakeLetters will match to the first letter and an underscore followed by a letter
var snakeLetters = regexp.MustCompile("(^[a-z])|_[a-z0-9]")
func ToPascalCase(in string) string {
inputSplit := strings.Split(in, ".")
var ucName string
for _, v := range inputSplit {
if len(v) < 1 {
continue
}
firstChar := v[0:1]
ucFirstChar := strings.ToUpper(firstChar)
if len(v) < 2 {
ucName += ucFirstChar
continue
}
ucName += ucFirstChar + v[1:]
}
return snakeLetters.ReplaceAllStringFunc(ucName, func(s string) string {
return strings.ToUpper(strings.Replace(s, "_", "", -1))
})
}
func ToCamelCase(in string) string {
pascal := ToPascalCase(in)
// Grab first rune and lower case it
firstLetter, size := utf8.DecodeRuneInString(pascal)
if firstLetter == utf8.RuneError && size <= 1 {
return pascal
}
return string(unicode.ToLower(firstLetter)) + pascal[size:]
}
func ValidateSnakeCase(in string) bool {
return snakeLetters.MatchString(string(in))
}

View file

@ -14,7 +14,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"time" "text/template"
"github.com/ldez/go-git-cmd-wrapper/v2/clone" "github.com/ldez/go-git-cmd-wrapper/v2/clone"
"github.com/ldez/go-git-cmd-wrapper/v2/git" "github.com/ldez/go-git-cmd-wrapper/v2/git"
@ -50,6 +50,12 @@ func Build() error {
return err return err
} }
slog.Info("Cleaning up old packages directory")
err = os.RemoveAll(path.Join(*root, "pkg"))
if err != nil {
return err
}
slog.Info("Creating generator dir", "dir", fmt.Sprintf("%s/%s", *root, GEN_REPO_NAME)) slog.Info("Creating generator dir", "dir", fmt.Sprintf("%s/%s", *root, GEN_REPO_NAME))
genDir, err := createGeneratorDir(*root, GEN_REPO, GEN_REPO_NAME) genDir, err := createGeneratorDir(*root, GEN_REPO, GEN_REPO_NAME)
if err != nil { if err != nil {
@ -162,6 +168,10 @@ func Build() error {
} }
slog.Info("Rearranging package directories") slog.Info("Rearranging package directories")
err = os.MkdirAll(path.Join(*root, "pkg"), 0755)
if err != nil {
return err
}
srcDir := path.Join(genDir, "sdk-repo-updated", "services") srcDir := path.Join(genDir, "sdk-repo-updated", "services")
items, err := os.ReadDir(srcDir) items, err := os.ReadDir(srcDir)
if err != nil { if err != nil {
@ -171,27 +181,30 @@ func Build() error {
if item.IsDir() { if item.IsDir() {
slog.Info(" -> package", "name", item.Name()) slog.Info(" -> package", "name", item.Name())
tgtDir := path.Join(*root, "pkg", item.Name()) tgtDir := path.Join(*root, "pkg", item.Name())
bakName := fmt.Sprintf("%s.%s", item.Name(), time.Now().Format("20060102-150405")) // no backup needed as we generate new
if _, err = os.Stat(tgtDir); !os.IsNotExist(err) { //bakName := fmt.Sprintf("%s.%s", item.Name(), time.Now().Format("20060102-150405"))
err = os.Rename( //if _, err = os.Stat(tgtDir); !os.IsNotExist(err) {
tgtDir, // err = os.Rename(
path.Join(*root, "pkg", bakName), // tgtDir,
) // path.Join(*root, "pkg", bakName),
if err != nil { // )
return err // if err != nil {
} // return err
} // }
//}
err = os.Rename(path.Join(srcDir, item.Name()), tgtDir) err = os.Rename(path.Join(srcDir, item.Name()), tgtDir)
if err != nil { if err != nil {
return err return err
} }
if _, err = os.Stat(path.Join(*root, "pkg", bakName, "wait")); !os.IsNotExist(err) {
slog.Info(" Copying wait subfolder") // wait is placed outside now
err = os.Rename(path.Join(*root, "pkg", bakName, "wait"), path.Join(tgtDir, "wait")) //if _, err = os.Stat(path.Join(*root, "pkg", bakName, "wait")); !os.IsNotExist(err) {
if err != nil { // slog.Info(" Copying wait subfolder")
return err // err = os.Rename(path.Join(*root, "pkg", bakName, "wait"), path.Join(tgtDir, "wait"))
} // if err != nil {
} // return err
// }
//}
} }
} }
@ -216,19 +229,17 @@ func Build() error {
return err return err
} }
// TODO err = createBoilerplate(*root, path.Join(*root, "stackit", "internal", "services"))
for _, testDir := range []string{ if err != nil {
path.Join(*root, "stackit", "internal", "services"), return err
} {
fmt.Println(testDir)
} }
slog.Info("Finally removing temporary files and directories") slog.Info("Finally removing temporary files and directories")
err = os.RemoveAll(path.Join(*root, "generated")) //err = os.RemoveAll(path.Join(*root, "generated"))
if err != nil { //if err != nil {
slog.Error("RemoveAll", "dir", path.Join(*root, "generated"), "err", err) // slog.Error("RemoveAll", "dir", path.Join(*root, "generated"), "err", err)
return err // return err
} //}
err = os.RemoveAll(path.Join(*root, GEN_REPO_NAME)) err = os.RemoveAll(path.Join(*root, GEN_REPO_NAME))
if err != nil { if err != nil {
@ -240,6 +251,146 @@ func Build() error {
return nil return nil
} }
type templateData struct {
PackageName string
NameCamel string
NamePascal string
NameSnake string
}
func fileExists(path string) bool {
_, err := os.Stat(path)
if os.IsNotExist(err) {
return false
}
if err != nil {
panic(err)
}
return true
}
func createBoilerplate(rootFolder, folder string) error {
services, err := os.ReadDir(folder)
if err != nil {
return err
}
for _, svc := range services {
if !svc.IsDir() {
continue
}
resources, err := os.ReadDir(path.Join(folder, svc.Name()))
if err != nil {
return err
}
handleDS := false
handleRes := false
foundDS := false
foundRes := false
for _, res := range resources {
if !res.IsDir() {
continue
}
resourceName := res.Name()
dsFile := path.Join(folder, svc.Name(), res.Name(), "datasources_gen", fmt.Sprintf("%s_data_source_gen.go", res.Name()))
handleDS = fileExists(dsFile)
resFile := path.Join(folder, svc.Name(), res.Name(), "resources_gen", fmt.Sprintf("%s_resource_gen.go", res.Name()))
handleRes = fileExists(resFile)
dsGoFile := path.Join(folder, svc.Name(), res.Name(), "datasource.go")
foundDS = fileExists(dsGoFile)
resGoFile := path.Join(folder, svc.Name(), res.Name(), "resource.go")
foundRes = fileExists(resGoFile)
if handleDS && !foundDS {
slog.Info("Creating missing datasource.go", "service", svc.Name(), "resource", resourceName)
if !ValidateSnakeCase(resourceName) {
return errors.New("resource name is invalid")
}
tplName := "data_source_scaffold.gotmpl"
err = writeTemplateToFile(
tplName,
path.Join(rootFolder, "tools", "templates", tplName),
path.Join(folder, svc.Name(), res.Name(), "datasource.go"),
&templateData{
PackageName: svc.Name(),
NameCamel: ToCamelCase(resourceName),
NamePascal: ToPascalCase(resourceName),
NameSnake: resourceName,
},
)
if err != nil {
panic(err)
}
}
if handleRes && !foundRes {
slog.Info("Creating missing resource.go", "service", svc.Name(), "resource", resourceName)
if !ValidateSnakeCase(resourceName) {
return errors.New("resource name is invalid")
}
tplName := "resource_scaffold.gotmpl"
err = writeTemplateToFile(
tplName,
path.Join(rootFolder, "tools", "templates", tplName),
path.Join(folder, svc.Name(), res.Name(), "resource.go"),
&templateData{
PackageName: svc.Name(),
NameCamel: ToCamelCase(resourceName),
NamePascal: ToPascalCase(resourceName),
NameSnake: resourceName,
},
)
if err != nil {
return err
}
}
}
}
return nil
}
func ucfirst(s string) string {
if len(s) == 0 {
return ""
}
return strings.ToUpper(s[:1]) + s[1:]
}
func writeTemplateToFile(tplName, tplFile, outFile string, data *templateData) error {
fn := template.FuncMap{
"ucfirst": ucfirst,
}
tmpl, err := template.New(tplName).Funcs(fn).ParseFiles(tplFile)
if err != nil {
return err
}
var f *os.File
f, err = os.Create(outFile)
if err != nil {
return err
}
err = tmpl.Execute(f, *data)
if err != nil {
return err
}
err = f.Close()
if err != nil {
return err
}
return nil
}
func generateServiceFiles(rootDir, generatorDir string) error { func generateServiceFiles(rootDir, generatorDir string) error {
// slog.Info("Generating specs folder") // slog.Info("Generating specs folder")
err := os.MkdirAll(path.Join(rootDir, "generated", "specs"), 0755) err := os.MkdirAll(path.Join(rootDir, "generated", "specs"), 0755)

View file

@ -0,0 +1,49 @@
package {{.PackageName}}
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
{{.PackageName}}Gen "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/{{.PackageName}}/{{.NameSnake}}/datasources_gen"
)
var _ datasource.DataSource = (*{{.NameCamel}}DataSource)(nil)
func New{{.NamePascal}}DataSource() datasource.DataSource {
return &{{.NameCamel}}DataSource{}
}
type {{.NameCamel}}DataSource struct{
client *{{.PackageName}}.APIClient
providerData core.ProviderData
}
func (d *{{.NameCamel}}DataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_{{.PackageName}}_{{.NameSnake}}"
}
func (d *{{.NameCamel}}DataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = {{.PackageName}}Gen.{{.NamePascal}}DataSourceSchema(ctx)
}
func (d *{{.NameCamel}}DataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data {{.PackageName}}Gen.{{.NameCamel}}Model
// Read Terraform configuration data into the model
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Example data value setting
// data.Id = types.StringValue("example-id")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

View file

@ -0,0 +1,39 @@
package {{.PackageName}}
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/provider"
"github.com/hashicorp/terraform-plugin-framework/resource"
)
var _ provider.Provider = (*{{.NameCamel}}Provider)(nil)
func New() func() provider.Provider {
return func() provider.Provider {
return &{{.NameCamel}}Provider{}
}
}
type {{.NameCamel}}Provider struct{}
func (p *{{.NameCamel}}Provider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) {
}
func (p *{{.NameCamel}}Provider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {
}
func (p *{{.NameCamel}}Provider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "{{.NameSnake}}"
}
func (p *{{.NameCamel}}Provider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{}
}
func (p *{{.NameCamel}}Provider) Resources(ctx context.Context) []func() resource.Resource {
return []func() resource.Resource{}
}

View file

@ -0,0 +1,208 @@
package {{.PackageName}}
import (
"context"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/core"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/utils"
{{.PackageName}}Gen "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/{{.PackageName}}/{{.NameSnake}}/resources_gen"
)
var (
_ resource.Resource = &{{.NameCamel}}Resource{}
_ resource.ResourceWithConfigure = &{{.NameCamel}}Resource{}
_ resource.ResourceWithImportState = &{{.NameCamel}}Resource{}
_ resource.ResourceWithModifyPlan = &{{.NameCamel}}Resource{}
)
func New{{.NamePascal}}Resource() resource.Resource {
return &{{.NameCamel}}Resource{}
}
type {{.NameCamel}}Resource struct{
client *{{.PackageName}}.APIClient
providerData core.ProviderData
}
func (r *{{.NameCamel}}Resource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_{{.PackageName}}_{{.NameSnake}}"
}
func (r *{{.NameCamel}}Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = {{.PackageName}}Gen.{{.NamePascal}}ResourceSchema(ctx)
}
// Configure adds the provider configured client to the resource.
func (r *{{.NameCamel}}Resource) Configure(
ctx context.Context,
req resource.ConfigureRequest,
resp *resource.ConfigureResponse,
) {
var ok bool
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
if !ok {
return
}
apiClientConfigOptions := []config.ConfigurationOption{
config.WithCustomAuth(r.providerData.RoundTripper),
utils.UserAgentConfigOption(r.providerData.Version),
}
if r.providerData.PostgresFlexCustomEndpoint != "" {
apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(r.providerData.PostgresFlexCustomEndpoint))
} else {
apiClientConfigOptions = append(apiClientConfigOptions, config.WithRegion(r.providerData.GetRegion()))
}
apiClient, err := {{.PackageName}}.NewAPIClient(apiClientConfigOptions...)
if err != nil {
resp.Diagnostics.AddError( "Error configuring API client", fmt.Sprintf("Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration", err))
return
}
r.client = apiClient
tflog.Info(ctx, "{{.PackageName}}.{{.NamePascal}} client configured")
}
func (r *{{.NameCamel}}Resource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
var data {{.PackageName}}Gen.{{.NamePascal}}Model
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// TODO: Create API call logic
// Example data value setting
data.{{.NameCamel | ucfirst}}Id = types.StringValue("id-from-response")
// Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "{{.PackageName}}.{{.NamePascal}} created")
}
func (r *{{.NameCamel}}Resource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data {{.PackageName}}Gen.{{.NamePascal}}Model
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Read API call logic
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "{{.PackageName}}.{{.NamePascal}} read")
}
func (r *{{.NameCamel}}Resource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
var data {{.PackageName}}Gen.{{.NamePascal}}Model
// Read Terraform plan data into the model
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Update API call logic
// Save updated data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
tflog.Info(ctx, "{{.PackageName}}.{{.NamePascal}} updated")
}
func (r *{{.NameCamel}}Resource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data {{.PackageName}}Gen.{{.NamePascal}}Model
// Read Terraform prior state data into the model
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
// Todo: Delete API call logic
tflog.Info(ctx, "{{.PackageName}}.{{.NamePascal}} deleted")
}
// ModifyPlan implements resource.ResourceWithModifyPlan.
// Use the modifier to set the effective region in the current plan.
func (r *{{.NameCamel}}Resource) ModifyPlan(
ctx context.Context,
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
var configModel {{.PackageName}}Gen.{{.NamePascal}}Model
// skip initial empty configuration to avoid follow-up errors
if req.Config.Raw.IsNull() {
return
}
resp.Diagnostics.Append(req.Config.Get(ctx, &configModel)...)
if resp.Diagnostics.HasError() {
return
}
var planModel {{.PackageName}}Gen.{{.NamePascal}}Model
resp.Diagnostics.Append(req.Plan.Get(ctx, &planModel)...)
if resp.Diagnostics.HasError() {
return
}
utils.AdaptRegion(ctx, configModel.Region, &planModel.Region, r.providerData.GetRegion(), resp)
if resp.Diagnostics.HasError() {
return
}
resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
if resp.Diagnostics.HasError() {
return
}
}
// ImportState imports a resource into the Terraform state on success.
// The expected format of the resource import identifier is: project_id,zone_id,record_set_id
func (r *{{.NameCamel}}Resource) ImportState(
ctx context.Context,
req resource.ImportStateRequest,
resp *resource.ImportStateResponse,
) {
idParts := strings.Split(req.ID, core.Separator)
// Todo: Import logic
if len(idParts) < 2 || idParts[0] == "" || idParts[1] == "" {
core.LogAndAddError(
ctx, &resp.Diagnostics,
"Error importing database",
fmt.Sprintf(
"Expected import identifier with format [project_id],[region],..., got %q",
req.ID,
),
)
return
}
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), idParts[0])...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("region"), idParts[1])...)
// ... more ...
core.LogAndAddWarning(
ctx,
&resp.Diagnostics,
"{{.PackageName | ucfirst}} database imported with empty password",
"The database password is not imported as it is only available upon creation of a new database. The password field will be empty.",
)
tflog.Info(ctx, "{{.PackageName | ucfirst}} {{.NameCamel}} state imported")
}