Skip to content

Commit

Permalink
Add is_primary_key to ConnectorSchemaConfigColumn (#380)
Browse files Browse the repository at this point in the history
* Add is_primary_key to ConnectorSchemaConfigColumn

* Fix mapping

* Fix override

* Fix typo

* Fix tests

* Fix tests

* Fix typo
  • Loading branch information
fivetran-jovanmanojlovic authored Dec 9, 2024
1 parent b0c8ed2 commit b91f2aa
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 61 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased](https://github.com/fivetran/terraform-provider-fivetran/compare/v1.4.1...HEAD)
## [Unreleased](https://github.com/fivetran/terraform-provider-fivetran/compare/v1.4.2...HEAD)

## [1.4.1](https://github.com/fivetran/terraform-provider-fivetran/compare/v1.4.1...v1.4.2)

## Added
- Add `is_primary_key` to connector schema config

## [1.4.1](https://github.com/fivetran/terraform-provider-fivetran/compare/v1.4.0...v1.4.1)

Expand Down
46 changes: 36 additions & 10 deletions fivetran/framework/core/model/connector_schema_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ func (d *ConnectorSchemaResourceModel) ReadFromResponse(response connectors.Conn

func (d *ConnectorSchemaResourceModel) getNullSchema() basetypes.SetValue {
columnAttrTypes := map[string]attr.Type{
"name": types.StringType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"name": types.StringType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"is_primary_key": types.BoolType,
}
tableAttrTypes := map[string]attr.Type{
"name": types.StringType,
Expand All @@ -132,8 +133,9 @@ func (d *ConnectorSchemaResourceModel) getNullSchema() basetypes.SetValue {

func (d *ConnectorSchemaResourceModel) getNullSchemas() basetypes.MapValue {
columnsAttrTypes := map[string]attr.Type{
"enabled": types.BoolType,
"hashed": types.BoolType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"is_primary_key": types.BoolType,
}

tablesAttrTypes := map[string]attr.Type{
Expand Down Expand Up @@ -181,8 +183,9 @@ func (d *ConnectorSchemaResourceModel) getSchemasRawValue(schemas []interface{})

func (d *ConnectorSchemaResourceModel) getSchemasMap(schemas []interface{}) basetypes.MapValue {
columnsAttrTypes := map[string]attr.Type{
"enabled": types.BoolType,
"hashed": types.BoolType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"is_primary_key": types.BoolType,
}

tablesAttrTypes := map[string]attr.Type{
Expand Down Expand Up @@ -259,6 +262,12 @@ func (d *ConnectorSchemaResourceModel) getSchemasMap(schemas []interface{}) base
} else {
columnElements["hashed"] = types.BoolNull()
}

if _, ok := localColumn["is_primary_key"]; ok && columnMap["is_primary_key"] != nil {
columnElements["is_primary_key"] = types.BoolValue(helpers.StrToBool(columnMap["is_primary_key"].(string)))
} else {
columnElements["is_primary_key"] = types.BoolNull()
}
columnValue, _ := types.ObjectValue(columnsAttrTypes, columnElements)
columns[columnName] = columnValue
}
Expand Down Expand Up @@ -310,9 +319,10 @@ func (d *ConnectorSchemaResourceModel) getLegacySchemaItems(schemas []interface{
schemaItems := []attr.Value{}
localSchemas := d.mapLocalSchemas()
columnAttrTypes := map[string]attr.Type{
"name": types.StringType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"name": types.StringType,
"enabled": types.BoolType,
"hashed": types.BoolType,
"is_primary_key": types.BoolType,
}

tableAttrTypes := map[string]attr.Type{
Expand Down Expand Up @@ -371,6 +381,11 @@ func (d *ConnectorSchemaResourceModel) getLegacySchemaItems(schemas []interface{
} else {
columnElements["hashed"] = types.BoolNull()
}
if _, ok := localColumn["is_primary_key"]; ok && columnMap["is_primary_key"] != nil {
columnElements["is_primary_key"] = types.BoolValue(helpers.StrToBool(columnMap["is_primary_key"].(string)))
} else {
columnElements["is_primary_key"] = types.BoolNull()
}
columnValue, _ := types.ObjectValue(columnAttrTypes, columnElements)
columns = append(columns, columnValue)
}
Expand Down Expand Up @@ -436,6 +451,11 @@ func (d *ConnectorSchemaResourceModel) getLegacySchemas() []interface{} {
if !hashedValue.IsUnknown() && !hashedValue.IsNull() {
column["hashed"] = columnElement.Attributes()["hashed"].(basetypes.BoolValue).ValueBool()
}

isPrimaryKey := columnElement.Attributes()["is_primary_key"].(basetypes.BoolValue)
if !isPrimaryKey.IsUnknown() && !isPrimaryKey.IsNull() {
column["is_primary_key"] = columnElement.Attributes()["is_primary_key"].(basetypes.BoolValue).ValueBool()
}
}
columns = append(columns, column)
}
Expand Down Expand Up @@ -509,6 +529,9 @@ func (d *ConnectorSchemaResourceModel) getSchemasRaw() []interface{} {
if h, ok := cMap["hashed"].(bool); ok {
column["hashed"] = h
}
if p, ok := cMap["is_primary_key"].(bool); ok {
column["is_primary_key"] = p
}
columns = append(columns, column)
}
}
Expand Down Expand Up @@ -565,6 +588,9 @@ func (d *ConnectorSchemaResourceModel) getSchemas() []interface{} {
if !columnElement.Attributes()["hashed"].(basetypes.BoolValue).IsUnknown() {
column["hashed"] = columnElement.Attributes()["hashed"].(basetypes.BoolValue).ValueBool()
}
if !columnElement.Attributes()["is_primary_key"].(basetypes.BoolValue).IsUnknown() {
column["is_primary_key"] = columnElement.Attributes()["is_primary_key"].(basetypes.BoolValue).ValueBool()
}
columns = append(columns, column)
}
}
Expand Down
9 changes: 9 additions & 0 deletions fivetran/framework/core/schema/connector_schema_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ The value defines validation method.
Computed: true,
Description: "The boolean value specifying whether a column should be hashed.",
},
"is_primary_key": schema.BoolAttribute{
Optional: true,
Computed: true,
Description: "",
},
},
},
},
Expand Down Expand Up @@ -184,6 +189,10 @@ func getColumnBlock() schema.SetNestedBlock {
Computed: true,
Description: "The boolean value specifying whether a column should be hashed.",
},
"is_primary_key": schema.BoolAttribute{
Optional: true,
Description: "",
},
},
},
}
Expand Down
82 changes: 41 additions & 41 deletions fivetran/tests/mock/resource_connector_schema_config_logic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ func TestUpstreamSchemaWithoutColumns(t *testing.T) {
schema_1response.newTable("table_1", false, nil)
// as table_2 stays enabled on switch to BLOCK_ALL - column settings are fetched from source and saved in config
schema_1response.newTable("table_2", true, nil).
newColumn("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false))
newColumn("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false)
schema_1response.newTable("table_3", false, nil)

schema_2response := responseConfig.newSchema("schema_2", true)
schema_2response.newTable("table_1", false, nil)
// as table_2 stays enabled on switch to BLOCK_ALL - column settings are fetched from source and saved in config
schema_2response.newTable("table_2", true, nil).
newColumn("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false))
newColumn("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false)
schema_2response.newTable("table_3", false, nil)

body := setupOneStepTest(t, upstreamConfig, tfConfig, responseConfig)
Expand Down Expand Up @@ -92,25 +92,25 @@ func TestUpstreamSchemaWithoutColumnsColumnConfigured(t *testing.T) {
// Enable only two tables
tfConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_1", true, nil)
newColumn("column_1", true, nil, true)

responseConfig := schemaConfigTestData{
schemaChangeHandling: "BLOCK_ALL",
}

responseConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_1", true, boolPtr(false)). // column user configured in tf
newColumn("column_2", true, boolPtr(false)) // column present in source, but not saved to standard config before switch to BA mode
newColumn("column_1", true, boolPtr(false), false). // column user configured in tf
newColumn("column_2", true, boolPtr(false), false) // column present in source, but not saved to standard config before switch to BA mode

response2Config := schemaConfigTestData{
schemaChangeHandling: "BLOCK_ALL",
}

response2Config.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_1", true, boolPtr(false)). // column user configured in tf
newColumn("column_2", false, boolPtr(false)) // column set disbled after second patch
newColumn("column_1", true, boolPtr(false), false). // column user configured in tf
newColumn("column_2", false, boolPtr(false), false) // column set disbled after second patch

bodies := setupComplexTestWithColumnsReload(
t, upstreamConfig,
Expand All @@ -119,7 +119,7 @@ func TestUpstreamSchemaWithoutColumnsColumnConfigured(t *testing.T) {
map[string]map[string][]columnsConfigTestData{
"schema_1": map[string][]columnsConfigTestData{
"table_1": []columnsConfigTestData{
newColumnConfigTestData().newColumn("column_1", false, boolPtr(false)).newColumn("column_2", false, boolPtr(false)),
newColumnConfigTestData().newColumn("column_1", false, boolPtr(false), true).newColumn("column_2", false, boolPtr(false), false),
},
},
})
Expand All @@ -142,7 +142,7 @@ func TestUpstreamSchemaWithoutColumnsColumnConfigured(t *testing.T) {

assertEqual(t, len(columns), 1)
column11 := AssertKeyExists(t, columns, "column_1").(map[string]interface{})
assertEqual(t, len(column11), 1)
assertEqual(t, len(column11), 2)
assertKeyExistsAndHasValue(t, column11, "enabled", true)

body2 := bodies[1]
Expand All @@ -160,7 +160,7 @@ func TestUpstreamSchemaWithoutColumnsColumnConfigured(t *testing.T) {
columns = AssertKeyExists(t, table11, "columns").(map[string]interface{})
assertEqual(t, len(columns), 1)
column12 := AssertKeyExists(t, columns, "column_2").(map[string]interface{})
assertEqual(t, len(column12), 1)
assertEqual(t, len(column12), 2)
assertKeyExistsAndHasValue(t, column12, "enabled", false)
}

Expand All @@ -173,14 +173,14 @@ func TestSchemaDoesntTouchColumnsInBlockAllIfNoColumnSettingsMock(t *testing.T)
schema_1 := upstreamConfig.newSchema("schema_1", true)

schema_1.newTable("table_1", true, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

schema_1.newTable("table_2", true, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

// only schema_1.table_1 will stay enabled
// table_2 will be disabled
Expand All @@ -199,15 +199,15 @@ func TestSchemaDoesntTouchColumnsInBlockAllIfNoColumnSettingsMock(t *testing.T)
schema_1response := responseConfig.newSchema("schema_1", true)
// table_1 enabled, existing columns saved settings
schema_1response.newTable("table_1", true, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

// table_2 enabled, existing columns saved settings
schema_1response.newTable("table_2", false, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

// act
body := setupOneStepTest(t, upstreamConfig, tfConfig, responseConfig)
Expand All @@ -231,9 +231,9 @@ func TestSetupSchemaBlockAllMock(t *testing.T) {
schema_1 := upstreamConfig.newSchema("schema_1", true)

schema_1.newTable("table_1", true, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

schema_1.newTableLocked("table_locked", true, nil)

Expand All @@ -243,17 +243,17 @@ func TestSetupSchemaBlockAllMock(t *testing.T) {

tfConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_2", true, nil)
newColumn("column_2", true, nil, true)

responseConfig := schemaConfigTestData{
schemaChangeHandling: "BLOCK_ALL",
}

schema_1response := responseConfig.newSchema("schema_1", true)
schema_1response.newTable("table_1", true, nil).
newColumnLocked("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", false, boolPtr(true))
newColumnLocked("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", false, boolPtr(true), false)
schema_1response.newTableLocked("table_locked", true, nil)

// act
Expand All @@ -272,7 +272,7 @@ func TestSetupSchemaBlockAllMock(t *testing.T) {

assertEqual(t, len(columns), 1)
column3 := assertKeyExists(t, columns, "column_3").(map[string]interface{})
assertEqual(t, len(column3), 1)
assertEqual(t, len(column3), 2)
assertKeyExistsAndHasValue(t, column3, "enabled", false)
}

Expand All @@ -282,26 +282,26 @@ func TestIgnoreNoPatchAllowedColumnsMock(t *testing.T) {
}
upstreamConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_1", true, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", true, boolPtr(true))
newColumn("column_1", true, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", true, boolPtr(true), false)

tfConfig := schemaConfigTestData{
schemaChangeHandling: "BLOCK_ALL",
}

tfConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_2", true, nil)
newColumn("column_2", true, nil, true)

responseConfig := schemaConfigTestData{
schemaChangeHandling: "BLOCK_ALL",
}
responseConfig.newSchema("schema_1", true).
newTable("table_1", true, nil).
newColumn("column_1", false, boolPtr(false)).
newColumn("column_2", true, boolPtr(false)).
newColumn("column_3", false, boolPtr(true))
newColumn("column_1", false, boolPtr(false), true).
newColumn("column_2", true, boolPtr(false), false).
newColumn("column_3", false, boolPtr(true), false)

// act
body := setupOneStepTest(t, upstreamConfig, tfConfig, responseConfig)
Expand All @@ -317,10 +317,10 @@ func TestIgnoreNoPatchAllowedColumnsMock(t *testing.T) {
columns := assertKeyExists(t, table_1, "columns").(map[string]interface{})
assertEqual(t, len(columns), 2)
column_1 := assertKeyExists(t, columns, "column_1").(map[string]interface{})
assertEqual(t, len(column_1), 1)
assertEqual(t, len(column_1), 2)
assertKeyExistsAndHasValue(t, column_1, "enabled", false)
column_3 := assertKeyExists(t, columns, "column_3").(map[string]interface{})
assertEqual(t, len(column_3), 1)
assertEqual(t, len(column_3), 2)
assertKeyExistsAndHasValue(t, column_3, "enabled", false)
}

Expand Down
Loading

0 comments on commit b91f2aa

Please sign in to comment.