Skip to content

Commit 0ecbfab

Browse files
committed
postgres: embed spec on Catalog remote type
Apply the same hoist that #5273 does for Branch/Endpoint/Project. Define PostgresCatalogRemote that embeds CatalogCatalogSpec and exposes the identifier and output-only fields at the top level. DoRead returns the new shape so state-side and remote-side paths line up, which is a prerequisite for drift detection on spec fields once the backend echoes spec on GET. Today the embedded fields are auto-classified spec:input_only from the API field behaviors in resources.generated.yml, so drift is correctly suppressed. Prompted by #5265 (comment). Should land after #5273. Co-authored-by: Isaac
1 parent 3ce34dd commit 0ecbfab

3 files changed

Lines changed: 70 additions & 37 deletions

File tree

acceptance/bundle/refschema/out.fields.txt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,20 +2733,16 @@ resources.postgres_branches.*.ttl *duration.Duration INPUT STATE
27332733
resources.postgres_branches.*.uid string REMOTE
27342734
resources.postgres_branches.*.update_time *time.Time REMOTE
27352735
resources.postgres_branches.*.url string INPUT
2736-
resources.postgres_catalogs.*.branch string INPUT STATE
2737-
resources.postgres_catalogs.*.catalog_id string INPUT STATE
2738-
resources.postgres_catalogs.*.create_database_if_missing bool INPUT STATE
2736+
resources.postgres_catalogs.*.branch string ALL
2737+
resources.postgres_catalogs.*.catalog_id string ALL
2738+
resources.postgres_catalogs.*.create_database_if_missing bool ALL
27392739
resources.postgres_catalogs.*.create_time *time.Time REMOTE
27402740
resources.postgres_catalogs.*.id string INPUT
27412741
resources.postgres_catalogs.*.lifecycle resources.Lifecycle INPUT
27422742
resources.postgres_catalogs.*.lifecycle.prevent_destroy bool INPUT
27432743
resources.postgres_catalogs.*.modified_status string INPUT
27442744
resources.postgres_catalogs.*.name string REMOTE
2745-
resources.postgres_catalogs.*.postgres_database string INPUT STATE
2746-
resources.postgres_catalogs.*.spec *postgres.CatalogCatalogSpec REMOTE
2747-
resources.postgres_catalogs.*.spec.branch string REMOTE
2748-
resources.postgres_catalogs.*.spec.create_database_if_missing bool REMOTE
2749-
resources.postgres_catalogs.*.spec.postgres_database string REMOTE
2745+
resources.postgres_catalogs.*.postgres_database string ALL
27502746
resources.postgres_catalogs.*.status *postgres.CatalogCatalogStatus REMOTE
27512747
resources.postgres_catalogs.*.status.branch string REMOTE
27522748
resources.postgres_catalogs.*.status.catalog_id string REMOTE

bundle/direct/dresources/postgres_catalog.go

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,36 @@ import (
55

66
"github.com/databricks/cli/bundle/config/resources"
77
"github.com/databricks/databricks-sdk-go"
8+
sdktime "github.com/databricks/databricks-sdk-go/common/types/time"
9+
"github.com/databricks/databricks-sdk-go/marshal"
810
"github.com/databricks/databricks-sdk-go/service/postgres"
911
)
1012

13+
// PostgresCatalogRemote is the return type for DoRead. It embeds CatalogCatalogSpec so
14+
// that all paths in StateType are valid paths in RemoteType, enabling drift detection
15+
// for spec fields once the backend echoes spec on GET.
16+
type PostgresCatalogRemote struct {
17+
postgres.CatalogCatalogSpec
18+
19+
CatalogId string `json:"catalog_id,omitempty"`
20+
21+
Name string `json:"name,omitempty"`
22+
Status *postgres.CatalogCatalogStatus `json:"status,omitempty"`
23+
Uid string `json:"uid,omitempty"`
24+
CreateTime *sdktime.Time `json:"create_time,omitempty"`
25+
UpdateTime *sdktime.Time `json:"update_time,omitempty"`
26+
}
27+
28+
// Custom marshaler needed because embedded CatalogCatalogSpec has its own MarshalJSON
29+
// which would otherwise take over and ignore the additional fields.
30+
func (s *PostgresCatalogRemote) UnmarshalJSON(b []byte) error {
31+
return marshal.Unmarshal(b, s)
32+
}
33+
34+
func (s PostgresCatalogRemote) MarshalJSON() ([]byte, error) {
35+
return marshal.Marshal(s)
36+
}
37+
1138
type ResourcePostgresCatalog struct {
1239
client *databricks.WorkspaceClient
1340
}
@@ -25,35 +52,50 @@ func (*ResourcePostgresCatalog) PrepareState(input *resources.PostgresCatalog) *
2552
}
2653
}
2754

28-
func (*ResourcePostgresCatalog) RemapState(remote *postgres.Catalog) *PostgresCatalogState {
29-
// Status.CatalogId is the short identifier and matches the user-supplied
30-
// config. Prefer it over parsing remote.Name — semantic contract from the
31-
// API rather than string manipulation on the hierarchical path.
32-
//
33-
// GET does not return the spec today (only status). Return an empty spec
34-
// and rely on the spec:input_only classifications generated from the
35-
// OpenAPI schema to suppress phantom drift until the backend starts
36-
// echoing spec values on GET.
55+
func (*ResourcePostgresCatalog) RemapState(remote *PostgresCatalogRemote) *PostgresCatalogState {
56+
return &PostgresCatalogState{
57+
CatalogId: remote.CatalogId,
58+
CatalogCatalogSpec: remote.CatalogCatalogSpec,
59+
}
60+
}
61+
62+
// makePostgresCatalogRemote converts the SDK Catalog into the embedded remote shape.
63+
// GET does not echo spec today (only status is returned); the embedded spec fields
64+
// stay at their zero values, and resources.yml suppresses phantom drift via
65+
// ignore_remote_changes with reason spec:input_only.
66+
//
67+
// Status.CatalogId is the short identifier and matches the user-supplied config.
68+
// Prefer it over parsing remote.Name — semantic contract from the API rather than
69+
// string manipulation on the hierarchical path.
70+
func makePostgresCatalogRemote(catalog *postgres.Catalog) *PostgresCatalogRemote {
71+
var spec postgres.CatalogCatalogSpec
72+
if catalog.Spec != nil {
73+
spec = *catalog.Spec
74+
}
3775
var catalogId string
38-
if remote.Status != nil {
39-
catalogId = remote.Status.CatalogId
76+
if catalog.Status != nil {
77+
catalogId = catalog.Status.CatalogId
4078
}
41-
return &PostgresCatalogState{
42-
CatalogId: catalogId,
43-
CatalogCatalogSpec: postgres.CatalogCatalogSpec{
44-
Branch: "",
45-
CreateDatabaseIfMissing: false,
46-
PostgresDatabase: "",
47-
ForceSendFields: nil,
48-
},
79+
return &PostgresCatalogRemote{
80+
CatalogCatalogSpec: spec,
81+
CatalogId: catalogId,
82+
Name: catalog.Name,
83+
Status: catalog.Status,
84+
Uid: catalog.Uid,
85+
CreateTime: catalog.CreateTime,
86+
UpdateTime: catalog.UpdateTime,
4987
}
5088
}
5189

52-
func (r *ResourcePostgresCatalog) DoRead(ctx context.Context, id string) (*postgres.Catalog, error) {
53-
return r.client.Postgres.GetCatalog(ctx, postgres.GetCatalogRequest{Name: id})
90+
func (r *ResourcePostgresCatalog) DoRead(ctx context.Context, id string) (*PostgresCatalogRemote, error) {
91+
catalog, err := r.client.Postgres.GetCatalog(ctx, postgres.GetCatalogRequest{Name: id})
92+
if err != nil {
93+
return nil, err
94+
}
95+
return makePostgresCatalogRemote(catalog), nil
5496
}
5597

56-
func (r *ResourcePostgresCatalog) DoCreate(ctx context.Context, config *PostgresCatalogState) (string, *postgres.Catalog, error) {
98+
func (r *ResourcePostgresCatalog) DoCreate(ctx context.Context, config *PostgresCatalogState) (string, *PostgresCatalogRemote, error) {
5799
waiter, err := r.client.Postgres.CreateCatalog(ctx, postgres.CreateCatalogRequest{
58100
CatalogId: config.CatalogId,
59101
Catalog: postgres.Catalog{
@@ -76,7 +118,8 @@ func (r *ResourcePostgresCatalog) DoCreate(ctx context.Context, config *Postgres
76118
if err != nil {
77119
return "", nil, err
78120
}
79-
return result.Name, result, nil
121+
remote := makePostgresCatalogRemote(result)
122+
return remote.Name, remote, nil
80123
}
81124

82125
func (r *ResourcePostgresCatalog) DoDelete(ctx context.Context, id string) error {

bundle/direct/dresources/type_test.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,6 @@ var knownMissingInRemoteType = map[string][]string{
7575
"pg_version",
7676
"project_id",
7777
},
78-
"postgres_catalogs": {
79-
"branch",
80-
"catalog_id",
81-
"create_database_if_missing",
82-
"postgres_database",
83-
},
8478
"vector_search_endpoints": {
8579
"target_qps",
8680
"usage_policy_id",

0 commit comments

Comments
 (0)