Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add linode_database_postgresql_v2 resource #1680

Draft
wants to merge 29 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
module github.com/linode/terraform-provider-linode/v2

go 1.22.0

toolchain go1.22.5
go 1.23.0

require (
github.com/aws/aws-sdk-go-v2 v1.32.5
Expand Down Expand Up @@ -125,3 +123,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace github.com/linode/linodego => github.com/ezilber-akamai/linodego v0.0.0-20241126163514-80c5e9497885
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhF
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/ezilber-akamai/linodego v0.0.0-20241126151916-41d189a2905f h1:o2XBxQZmuzhDBaIfTz9MQ9tchfAfewpKt2H8WwZ+anY=
github.com/ezilber-akamai/linodego v0.0.0-20241126151916-41d189a2905f/go.mod h1:L0nZH3cIKL1Mz5uCTLci2zVDQrPv0MBH0qeSzwUTLcA=
github.com/ezilber-akamai/linodego v0.0.0-20241126163514-80c5e9497885 h1:kH2necFSiNflvEiT8WpKl5bcGkZP68AKGKMSSCRgvLc=
github.com/ezilber-akamai/linodego v0.0.0-20241126163514-80c5e9497885/go.mod h1:L0nZH3cIKL1Mz5uCTLci2zVDQrPv0MBH0qeSzwUTLcA=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
Expand Down Expand Up @@ -189,8 +193,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/linode/linodego v1.43.0 h1:sGeBB3caZt7vKBoPS5p4AVzmlG4JoqQOdigIibx3egk=
github.com/linode/linodego v1.43.0/go.mod h1:n4TMFu1UVNala+icHqrTEFFaicYSF74cSAUG5zkTwfA=
github.com/linode/linodego/k8s v1.25.2 h1:PY6S0sAD3xANVvM9WY38bz9GqMTjIbytC8IJJ9Cv23o=
github.com/linode/linodego/k8s v1.25.2/go.mod h1:DC1XCSRZRGsmaa/ggpDPSDUmOM6aK1bhSIP6+f9Cwhc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
Expand Down
235 changes: 235 additions & 0 deletions linode/databasepostgresqlv2/framework_models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package databasepostgresqlv2

import (
"context"
"fmt"
"strconv"
"strings"

"github.com/hashicorp/terraform-plugin-framework/diag"

"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/linode/linodego"
"github.com/linode/terraform-provider-linode/v2/linode/helper"
)

type ModelFork struct {
Source types.Int64 `tfsdk:"source"`
}

type ModelForkDetails struct {
RestoreTime timetypes.RFC3339 `tfsdk:"restore_time"`
}

type ModelHosts struct {
Primary types.String `tfsdk:"primary"`
Secondary types.String `tfsdk:"secondary"`
}

type ModelUpdates struct {
DayOfWeek types.Int64 `tfsdk:"day_of_week"`
Duration types.Int64 `tfsdk:"duration"`
Frequency types.String `tfsdk:"frequency"`
HourOfDay types.Int64 `tfsdk:"hour_of_day"`
}

func (m ModelUpdates) ToLinodego() (linodego.DatabaseMaintenanceWindow, diag.Diagnostics) {
var d diag.Diagnostics

return linodego.DatabaseMaintenanceWindow{
DayOfWeek: linodego.DatabaseDayOfWeek(helper.FrameworkSafeInt64ToInt(m.DayOfWeek.ValueInt64(), &d)),
Duration: helper.FrameworkSafeInt64ToInt(m.Duration.ValueInt64(), &d),
Frequency: linodego.DatabaseMaintenanceFrequency(m.Frequency.String()),
HourOfDay: helper.FrameworkSafeInt64ToInt(m.HourOfDay.ValueInt64(), &d),
}, d
}

type ModelPendingUpdate struct {
Deadline timetypes.RFC3339 `tfsdk:"deadline"`
Description types.String `tfsdk:"description"`
PlannedFor timetypes.RFC3339 `tfsdk:"planned_for"`
}

type Model struct {
ID types.String `tfsdk:"id"`

Label types.String `tfsdk:"label"`
EngineID types.String `tfsdk:"engine_id"`
Region types.String `tfsdk:"region"`
Type types.String `tfsdk:"type"`

AllowList types.Set `tfsdk:"allow_list"`
ClusterSize types.Int64 `tfsdk:"cluster_size"`
SSLConnection types.Bool `tfsdk:"ssl_connection"`

Created timetypes.RFC3339 `tfsdk:"created"`
Encrypted types.Bool `tfsdk:"encrypted"`
Engine types.String `tfsdk:"engine"`
Members types.Map `tfsdk:"members"`
OldestRestoreTime timetypes.RFC3339 `tfsdk:"oldest_restore_time"`
Platform types.String `tfsdk:"platform"`
Port types.Int64 `tfsdk:"port"`
Status types.String `tfsdk:"status"`
// TotalDiskSizeGB types.Int64 `tfsdk:"total_disk_size_gb"`
Updated timetypes.RFC3339 `tfsdk:"updated"`
// UsedDiskSizeGB types.Int64 `tfsdk:"used_disk_size_gb"`
Version types.String `tfsdk:"version"`

Hosts types.Object `tfsdk:"hosts"`

Fork types.Object `tfsdk:"fork"`
ForkDetails types.Object `tfsdk:"fork_details"`

Updates types.Object `tfsdk:"updates"`
PendingUpdates types.Set `tfsdk:"pending_updates"`
}

func (m *Model) Flatten(ctx context.Context, db *linodego.PostgresDatabase, preserveKnown bool) (d diag.Diagnostics) {
m.ID = helper.KeepOrUpdateString(m.ID, strconv.Itoa(db.ID), preserveKnown)

m.Label = helper.KeepOrUpdateString(m.Label, db.Label, preserveKnown)
m.EngineID = helper.KeepOrUpdateString(m.EngineID, fmt.Sprintf("%s/%s", db.Engine, strings.Split(db.Version, ".")[0]), preserveKnown)
m.Region = helper.KeepOrUpdateString(m.Region, db.Region, preserveKnown)
m.Type = helper.KeepOrUpdateString(m.Type, db.Type, preserveKnown)
m.AllowList = helper.KeepOrUpdateSet(
types.StringType,
m.AllowList,
helper.StringSliceToFrameworkValueSlice(db.AllowList),
preserveKnown,
&d,
)
if d.HasError() {
return
}
m.ClusterSize = helper.KeepOrUpdateInt64(m.ClusterSize, int64(db.ClusterSize), preserveKnown)
m.SSLConnection = helper.KeepOrUpdateBool(m.SSLConnection, db.SSLConnection, preserveKnown)
m.Created = helper.KeepOrUpdateValue(m.Created, timetypes.NewRFC3339TimePointerValue(db.Created), preserveKnown)
m.Encrypted = helper.KeepOrUpdateBool(m.Encrypted, db.Encrypted, preserveKnown)
m.Engine = helper.KeepOrUpdateString(m.Engine, db.Engine, preserveKnown)

membersCasted := helper.MapMap(
db.Members,
func(key string, value linodego.DatabaseMemberType) (string, string) {
return key, string(value)
},
)

m.Members = helper.KeepOrUpdateStringMap(ctx, m.Members, membersCasted, preserveKnown, &d)
if d.HasError() {
return
}

m.OldestRestoreTime = helper.KeepOrUpdateValue(m.OldestRestoreTime, timetypes.NewRFC3339TimePointerValue(db.OldestRestoreTime), preserveKnown)
m.Platform = helper.KeepOrUpdateString(m.Platform, string(db.Platform), preserveKnown)
m.Port = helper.KeepOrUpdateInt64(m.Port, int64(db.Port), preserveKnown)
m.Status = helper.KeepOrUpdateString(m.Status, string(db.Status), preserveKnown)
m.Updated = helper.KeepOrUpdateValue(m.Updated, timetypes.NewRFC3339TimePointerValue(db.Updated), preserveKnown)
m.Version = helper.KeepOrUpdateString(m.Version, db.Version, preserveKnown)

// TODO
// m.TotalDiskSizeGB = helper.KeepOrUpdateInt64(m.TotalDiskSizeGB, 0, preserveKnown)
// m.UsedDiskSizeGB = helper.KeepOrUpdateInt64(m.UsedDiskSizeGB, 0, preserveKnown)

hostsObject, rd := types.ObjectValueFrom(
ctx,
hostsAttributes,
&ModelHosts{
Primary: types.StringValue(db.Hosts.Primary),
Secondary: types.StringValue(db.Hosts.Secondary),
},
)
d.Append(rd...)
m.Hosts = helper.KeepOrUpdateValue(m.Hosts, hostsObject, preserveKnown)

forkObject, rd := types.ObjectValueFrom(
ctx,
forkAttributes,
&ModelFork{
Source: types.Int64Value(int64(db.Fork.Source)),
},
)
d.Append(rd...)
m.Fork = helper.KeepOrUpdateValue(m.Fork, forkObject, preserveKnown)

forkDetailsObject, rd := types.ObjectValueFrom(
ctx,
forkDetailsAttributes,
&ModelForkDetails{
RestoreTime: timetypes.NewRFC3339TimePointerValue(db.Fork.RestoreTime),
},
)
d.Append(rd...)
m.ForkDetails = helper.KeepOrUpdateValue(m.ForkDetails, forkDetailsObject, preserveKnown)

updatesObject, rd := types.ObjectValueFrom(
ctx,
updatesAttributes,
&ModelUpdates{
DayOfWeek: types.Int64Value(int64(db.Updates.DayOfWeek)),
Duration: types.Int64Value(int64(db.Updates.Duration)),
Frequency: types.StringValue(string(db.Updates.Frequency)),
HourOfDay: types.Int64Value(int64(db.Updates.HourOfDay)),
},
)
d.Append(rd...)
m.Updates = helper.KeepOrUpdateValue(m.Updates, updatesObject, preserveKnown)

pendingObjects := helper.MapSlice(
db.Updates.Pending,
func(pending linodego.DatabaseMaintenanceWindowPending) types.Object {
result, rd := types.ObjectValueFrom(
ctx,
pendingUpdateAttributes,
&ModelPendingUpdate{
Deadline: timetypes.NewRFC3339TimePointerValue(pending.Deadline),
Description: types.StringValue(pending.Description),
PlannedFor: timetypes.NewRFC3339TimePointerValue(pending.PlannedFor),
},
)
d.Append(rd...)

return result
},
)

pendingSet, rd := types.SetValueFrom(
ctx,
types.ObjectType{
AttrTypes: pendingUpdateAttributes,
},
pendingObjects,
)
d.Append(rd...)

m.PendingUpdates = helper.KeepOrUpdateValue(m.PendingUpdates, pendingSet, preserveKnown)

return nil
}

func (m *Model) CopyFrom(ctx context.Context, other *Model, preserveKnown bool) {
m.ID = helper.KeepOrUpdateValue(m.ID, other.ID, preserveKnown)
m.Engine = helper.KeepOrUpdateValue(m.Engine, other.Engine, preserveKnown)
m.Label = helper.KeepOrUpdateValue(m.Label, other.Label, preserveKnown)
m.Region = helper.KeepOrUpdateValue(m.Region, other.Region, preserveKnown)
m.Type = helper.KeepOrUpdateValue(m.Type, other.Type, preserveKnown)
m.AllowList = helper.KeepOrUpdateValue(m.AllowList, other.AllowList, preserveKnown)
m.ClusterSize = helper.KeepOrUpdateValue(m.ClusterSize, other.ClusterSize, preserveKnown)
m.SSLConnection = helper.KeepOrUpdateValue(m.SSLConnection, other.SSLConnection, preserveKnown)
m.Created = helper.KeepOrUpdateValue(m.Created, other.Created, preserveKnown)
m.Encrypted = helper.KeepOrUpdateValue(m.Encrypted, other.Encrypted, preserveKnown)
m.Members = helper.KeepOrUpdateValue(m.Members, other.Members, preserveKnown)
m.OldestRestoreTime = helper.KeepOrUpdateValue(m.OldestRestoreTime, other.OldestRestoreTime, preserveKnown)
m.Platform = helper.KeepOrUpdateValue(m.Platform, other.Platform, preserveKnown)
m.Port = helper.KeepOrUpdateValue(m.Port, other.Port, preserveKnown)
m.Status = helper.KeepOrUpdateValue(m.Status, other.Status, preserveKnown)
// m.TotalDiskSizeGB = helper.KeepOrUpdateValue(m.TotalDiskSizeGB, other.TotalDiskSizeGB, preserveKnown)
m.Updated = helper.KeepOrUpdateValue(m.Updated, other.Updated, preserveKnown)
// m.UsedDiskSizeGB = helper.KeepOrUpdateValue(m.UsedDiskSizeGB, other.UsedDiskSizeGB, preserveKnown)
m.Version = helper.KeepOrUpdateValue(m.Version, other.Version, preserveKnown)
m.Hosts = helper.KeepOrUpdateValue(m.Hosts, other.Hosts, preserveKnown)
m.Fork = helper.KeepOrUpdateValue(m.Fork, other.Fork, preserveKnown)
m.ForkDetails = helper.KeepOrUpdateValue(m.ForkDetails, other.ForkDetails, preserveKnown)
m.Updates = helper.KeepOrUpdateValue(m.Updates, other.Updates, preserveKnown)
m.PendingUpdates = helper.KeepOrUpdateValue(m.PendingUpdates, other.PendingUpdates, preserveKnown)
}
120 changes: 120 additions & 0 deletions linode/databasepostgresqlv2/framework_models_unit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//go:build unit

package databasepostgresqlv2_test

import (
"context"
"testing"
"time"

"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"

"github.com/linode/linodego"
"github.com/linode/terraform-provider-linode/v2/linode/databasepostgresqlv2"
"github.com/stretchr/testify/require"
)

var (
currentTime = time.Now()
currentTimeFWValue = timetypes.NewRFC3339TimePointerValue(&currentTime)

testDB = linodego.PostgresDatabase{
ID: 12345,
Status: linodego.DatabaseStatusProvisioning,
Label: "foobar",
Region: "us-mia",
Type: "g6-nanode-1",
Engine: "postgresql",
Version: "16",
Encrypted: true,
AllowList: []string{"0.0.0.0/0", "10.0.0.1/32"},
Port: 1234,
SSLConnection: true,
ClusterSize: 3,
Hosts: linodego.DatabaseHost{
Primary: "1.2.3.4",
Secondary: "4.3.2.1",
},
Updates: linodego.DatabaseMaintenanceWindow{
DayOfWeek: 1,
Duration: 1,
Frequency: linodego.DatabaseMaintenanceFrequencyWeekly,
HourOfDay: 1,
Pending: []linodego.DatabaseMaintenanceWindowPending{
{
Deadline: &currentTime,
Description: "foobar",
PlannedFor: &currentTime,
},
},
},
Created: &currentTime,
Updated: &currentTime,
Fork: linodego.DatabaseFork{
Source: 12345,
RestoreTime: &currentTime,
},
OldestRestoreTime: &currentTime,
}
)

func TestModel_Flatten(t *testing.T) {
var model databasepostgresqlv2.Model
model.Flatten(context.Background(), &testDB, false)

require.Equal(t, "12345", model.ID.ValueString())

require.Equal(t, "provisioning", model.Status.ValueString())
require.Equal(t, "foobar", model.Label.ValueString())
require.Equal(t, "us-mia", model.Region.ValueString())
require.Equal(t, "g6-nanode-1", model.Type.ValueString())
require.Equal(t, "postgresql", model.Engine.ValueString())
require.Equal(t, "16", model.Version.ValueString())
require.Equal(t, true, model.Encrypted.ValueBool())

allowListElements := model.AllowList.Elements()
require.Contains(t, allowListElements, types.StringValue("0.0.0.0/0"))
require.Contains(t, allowListElements, types.StringValue("10.0.0.1/32"))

require.Equal(t, int64(1234), model.Port.ValueInt64())
require.Equal(t, true, model.SSLConnection.ValueBool())
require.Equal(t, "1.2.3.4", model.Hosts.Primary.ValueString())

Check failure on line 83 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Hosts.Primary undefined (type basetypes.ObjectValue has no field or method Primary)

Check failure on line 83 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Hosts.Primary undefined (type basetypes.ObjectValue has no field or method Primary)
require.Equal(t, "4.3.2.1", model.Hosts.Secondary.ValueString())

Check failure on line 84 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Hosts.Secondary undefined (type basetypes.ObjectValue has no field or method Secondary)

Check failure on line 84 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Hosts.Secondary undefined (type basetypes.ObjectValue has no field or method Secondary)

require.Equal(t, int64(1), model.Updates.DayOfWeek.ValueInt64())

Check failure on line 86 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Updates.DayOfWeek undefined (type basetypes.ObjectValue has no field or method DayOfWeek)

Check failure on line 86 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Updates.DayOfWeek undefined (type basetypes.ObjectValue has no field or method DayOfWeek)
require.Equal(t, int64(1), model.Updates.Duration.ValueInt64())

Check failure on line 87 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Updates.Duration undefined (type basetypes.ObjectValue has no field or method Duration)

Check failure on line 87 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Updates.Duration undefined (type basetypes.ObjectValue has no field or method Duration)
require.Equal(t, "weekly", model.Updates.Frequency.ValueString())

Check failure on line 88 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Updates.Frequency undefined (type basetypes.ObjectValue has no field or method Frequency)

Check failure on line 88 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Updates.Frequency undefined (type basetypes.ObjectValue has no field or method Frequency)
require.Equal(t, int64(1), model.Updates.HourOfDay.ValueInt64())

Check failure on line 89 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Updates.HourOfDay undefined (type basetypes.ObjectValue has no field or method HourOfDay)

Check failure on line 89 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Updates.HourOfDay undefined (type basetypes.ObjectValue has no field or method HourOfDay)

expectedPendingElement, d := types.ObjectValue(
map[string]attr.Type{
"deadline": timetypes.RFC3339Type{},
"description": types.StringType,
"planned_for": timetypes.RFC3339Type{},
},
map[string]attr.Value{
"deadline": currentTimeFWValue,
"description": types.StringValue("foobar"),
"planned_for": currentTimeFWValue,
},
)
require.False(t, d.HasError(), d.Errors())

require.True(t, model.Updates.Pending.Elements()[0].Equal(expectedPendingElement))

Check failure on line 105 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Updates.Pending undefined (type basetypes.ObjectValue has no field or method Pending)

Check failure on line 105 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Updates.Pending undefined (type basetypes.ObjectValue has no field or method Pending)

require.Equal(t, int64(12345), model.Fork.Source.ValueInt64())

Check failure on line 107 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Fork.Source undefined (type basetypes.ObjectValue has no field or method Source)

Check failure on line 107 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Fork.Source undefined (type basetypes.ObjectValue has no field or method Source)
require.Equal(t, currentTimeFWValue, model.Fork.RestoreTime)

Check failure on line 108 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / unit_tests

model.Fork.RestoreTime undefined (type basetypes.ObjectValue has no field or method RestoreTime)

Check failure on line 108 in linode/databasepostgresqlv2/framework_models_unit_test.go

View workflow job for this annotation

GitHub Actions / tests

model.Fork.RestoreTime undefined (type basetypes.ObjectValue has no field or method RestoreTime)

require.Equal(t, currentTimeFWValue, model.OldestRestoreTime)
}

func TestModel_Copy(t *testing.T) {
var modelOld, modelNew databasepostgresqlv2.Model
modelOld.Flatten(context.Background(), &testDB, false)

modelNew.CopyFrom(context.Background(), &modelOld, false)

require.Equal(t, modelOld, modelNew)
}
Loading
Loading