Skip to content

internal: update GetResourceConfig to use dyn/convert rather than JSON roundtrip - #3646

Merged
denik merged 1 commit into
mainfrom
denik/update-get-resource-config
Sep 26, 2025
Merged

internal: update GetResourceConfig to use dyn/convert rather than JSON roundtrip#3646
denik merged 1 commit into
mainfrom
denik/update-get-resource-config

Conversation

@denik

@denikdenik commented Sep 23, 2025

Copy link
Copy Markdown
Contributor

Why

For direct, we fetch configs as struct instances via GetResourceConfig, which is using json roundtrip between dyn value and struct. That, however, does not work well when there references in the config, see #3645 for details.

This switches to converting dyn.Value with dyn/convert ToTyped function. The function was not used previously because it did not handle ForceSendFields correctly for embedded structs which caused JSON marshaller in Go SDK to return error. This was fixed in #3650 and #3649

Tests

Existing tests.

@denik
denik marked this pull request as ready for review September 23, 2025 12:53
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Sep 23, 2025

Copy link
Copy Markdown
Collaborator

Run: 18036944667

Env✅​pass🔄​flaky🙈​skip
✅​aws linux312531
✅​aws windows313530
✅​aws-ucws linux425428
✅​aws-ucws windows426427
✅​azure linux312530
🔄​azure windows3121529
✅​azure-ucws linux425427
✅​azure-ucws windows426426
✅​gcp linux311532
✅​gcp windows312531
Test Nameazure windows
TestSyncEnsureRemotePathIsUsableIfRepoExists🔄​flaky

@denik
denikforce-pushed the denik/update-get-resource-config branch from 99d95fc to 143be1bCompareSeptember 23, 2025 19:31
@denik
denik changed the base branch from main to denik/dyn-is-zeroSeptember 23, 2025 19:31
@denik
denik marked this pull request as draft September 23, 2025 19:43
github-merge-queueBot pushed a commit that referenced this pull request Sep 24, 2025
## Changes
- Fix IsZero() method for types like int64. This fixes ToConvert for
NumWorkers field in ClusterSpec.
- Do not panic in dyn.V() if other int types are encountered.
- If panic does happen, include type name.
## Why
ToConvert() depends on it and is broken. This unblocks
#3650#3646
## Tests
New unit tests.
Base automatically changed from denik/dyn-is-zero to mainSeptember 24, 2025 10:25
@denik
denikforce-pushed the denik/update-get-resource-config branch from 1c351e3 to 9bac490CompareSeptember 24, 2025 14:43
@denikdenik changed the title internal: update GetResourceConfig to use dyn/convert; fix dyn/convert wrt ForceSendFields+embeddedinternal: update GetResourceConfig to use dyn/convert rather than JSON roundtripSep 24, 2025
@denik
denik marked this pull request as ready for review September 24, 2025 14:45
@denik
denikforce-pushed the denik/update-get-resource-config branch from 9bac490 to f79fdacCompareSeptember 24, 2025 14:52
@denik
denikforce-pushed the denik/update-get-resource-config branch from f79fdac to 57a975bCompareSeptember 25, 2025 12:32
@denik
denikforce-pushed the denik/update-get-resource-config branch from 57a975b to 55ce74fCompareSeptember 25, 2025 15:07
@denikdenik mentioned this pull request Sep 25, 2025
@denik
denikforce-pushed the denik/update-get-resource-config branch from 55ce74f to c9d3f45CompareSeptember 25, 2025 18:43
Comment threadbundle/config/root.go
if err := json.Unmarshal(bytes, typedConfigPtr.Interface()); err != nil {

err = convert.ToTyped(typedConfigPtr.Interface(), v)
if err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC this is the core of the change, on top of #3650. Correct?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right! I updated the base to make it clear.

@denik
denik changed the base branch from main to denik/dyn-convert-fsfSeptember 26, 2025 08:45
@denik
denikforce-pushed the denik/update-get-resource-config branch from c9d3f45 to ce4795bCompareSeptember 26, 2025 10:33
@denik
denikforce-pushed the denik/update-get-resource-config branch from ce4795b to 356e7acCompareSeptember 26, 2025 10:34
@denik
denikforce-pushed the denik/update-get-resource-config branch from 356e7ac to b23495bCompareSeptember 26, 2025 10:38
github-merge-queueBot pushed a commit that referenced this pull request Sep 26, 2025
## Changes
Fix ToTyped / FromTyped wrt ForceSendFields when there are (multiple)
embedded structs.
## Why
Incorrect conversion between typed & dynamic value can result in subtle
bugs. In direct engine it is even more important, as we rely on typed
structs more here. Enables #3646
## Tests
New unit tests.
Base automatically changed from denik/dyn-convert-fsf to mainSeptember 26, 2025 11:50
add test
forcesendfield fix
another test with multiple
updatge and fix
another test
add 3 tests, need clean up
add new test
fix
clean up
clean up
lint fix
add update_single_node test
@denik
denikforce-pushed the denik/update-get-resource-config branch from b23495b to 79b009dCompareSeptember 26, 2025 11:51
@denik
denik enabled auto-merge September 26, 2025 11:51
@denik
denik added this pull request to the merge queueSep 26, 2025
@github-merge-queue
github-merge-queueBot removed this pull request from the merge queue due to failed status checks Sep 26, 2025
@denik
denik added this pull request to the merge queueSep 26, 2025
Merged via the queue into main with commit c02e181Sep 26, 2025
13 checks passed
@denik
denik deleted the denik/update-get-resource-config branch September 26, 2025 12:53
github-merge-queueBot pushed a commit that referenced this pull request Sep 30, 2025
## Changes
The JSON plan (output of “bundle debug plan”) is now input to “bundle
deploy” internally. This means it contains full information about
resources about to be deployed.
The JSON plan stores configs as well as all unresolved fields as map
(path -> reference). There is new module, structvar, that supports
resolving these references. It does it quickly and without copying the
full config for every resolution, like the previous implementation did.
The JSON plan also stores per-field action. This is purely
informational, it gives an idea why a certain action for the resource
was chosen.
During plan and apply, variable resolution is now done in the node that
contains the reference. Previously, it was updated by the node that was
referenced. This results in better error messages when resolution does
not work and it does not fail resources that themselves have no issues
(but have incorrect references pointing to them).
References can now refer to missing field and it works like in terraform
(missing_string_field test).
There is slight simplification in how $resources are resolved. All local
resolutions (from config) are now done in plan phase. All remote
resolutions (from remote state) are now done in apply phase. Previously
we could resolve some remote references in plan stage if action was
“skip”. This might result in slower deploys, so this is a potential perf
regression, to be revisited in the future.
Depends on #3650 &
#3646
Other changes:
- dagrun.Graph now exports its fields. dagrun.OutgoingLabels() is
removed.
- new function structaccess.Set() to set any field in a struct by path
(used by structvar).
- dresources.ClassifyByTriggers([]Change) is replaced by
dresources.ClassifyByTriggers(Change), aggregation logic now lives in
bundle_plan.go
## Why
Having the plan as input to deploy provides a view into deployment that
we did not have before, allowing to see exactly what is going to be
deployed and why.
This is useful for:
- debugging (why is my pipeline being recreated?)
- see diff between deployed infra and config
- deploying exactly what was in the diff and nothing else: "bundle
deploy -readplan plan.json" can be implemented easily after this change.
@denikdenik mentioned this pull request Jan 27, 2026
denik added a commit that referenced this pull request May 20, 2026
## Changes
- Fix IsZero() method for types like int64. This fixes ToConvert for
NumWorkers field in ClusterSpec.
- Do not panic in dyn.V() if other int types are encountered.
- If panic does happen, include type name.
## Why
ToConvert() depends on it and is broken. This unblocks
#3650#3646
## Tests
New unit tests.
denik added a commit that referenced this pull request May 20, 2026
## Changes
Fix ToTyped / FromTyped wrt ForceSendFields when there are (multiple)
embedded structs.
## Why
Incorrect conversion between typed & dynamic value can result in subtle
bugs. In direct engine it is even more important, as we rely on typed
structs more here. Enables #3646
## Tests
New unit tests.
denik added a commit that referenced this pull request May 20, 2026
…N roundtrip (#3646)
## Why
For direct, we fetch configs as struct instances via GetResourceConfig,
which is using json roundtrip between dyn value and struct. That,
however, does not work well when there references in the config, see
#3645 for details.
This switches to converting dyn.Value with dyn/convert ToTyped function.
The function was not used previously because it did not handle
ForceSendFields correctly for embedded structs which caused JSON
marshaller in Go SDK to return error. This was fixed in
#3650 and
#3649
## Tests
Existing tests.
denik added a commit that referenced this pull request May 20, 2026
## Changes
The JSON plan (output of “bundle debug plan”) is now input to “bundle
deploy” internally. This means it contains full information about
resources about to be deployed.
The JSON plan stores configs as well as all unresolved fields as map
(path -> reference). There is new module, structvar, that supports
resolving these references. It does it quickly and without copying the
full config for every resolution, like the previous implementation did.
The JSON plan also stores per-field action. This is purely
informational, it gives an idea why a certain action for the resource
was chosen.
During plan and apply, variable resolution is now done in the node that
contains the reference. Previously, it was updated by the node that was
referenced. This results in better error messages when resolution does
not work and it does not fail resources that themselves have no issues
(but have incorrect references pointing to them).
References can now refer to missing field and it works like in terraform
(missing_string_field test).
There is slight simplification in how $resources are resolved. All local
resolutions (from config) are now done in plan phase. All remote
resolutions (from remote state) are now done in apply phase. Previously
we could resolve some remote references in plan stage if action was
“skip”. This might result in slower deploys, so this is a potential perf
regression, to be revisited in the future.
Depends on #3650 &
#3646
Other changes:
- dagrun.Graph now exports its fields. dagrun.OutgoingLabels() is
removed.
- new function structaccess.Set() to set any field in a struct by path
(used by structvar).
- dresources.ClassifyByTriggers([]Change) is replaced by
dresources.ClassifyByTriggers(Change), aggregation logic now lives in
bundle_plan.go
## Why
Having the plan as input to deploy provides a view into deployment that
we did not have before, allowing to see exactly what is going to be
deployed and why.
This is useful for:
- debugging (why is my pipeline being recreated?)
- see diff between deployed infra and config
- deploying exactly what was in the diff and nothing else: "bundle
deploy -readplan plan.json" can be implemented easily after this change.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@denik@eng-dev-ecosystem-bot@pietern