Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
bundle:
name: test-bundle-$UNIQUE_NAME

variables:
notebook_root:
default: /Users/{{workspace_user_name}}

resources:
jobs:
"job with spaces":
name: spaced-job
tasks:
- task_key: main
timeout_seconds: 60
notebook_task:
notebook_path: ${var.notebook_root}/notebook
"job's\"quotes":
name: quoted-job
tasks:
- task_key: main
timeout_seconds: 60
notebook_task:
notebook_path: ${var.notebook_root}/notebook

targets:
default:
mode: development
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Cloud = false
GOOS.windows = false
EnvMatrix.DMS = ["", "true"]
110 changes: 110 additions & 0 deletions acceptance/bundle/config-remote-sync/resource_keys/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@

>>> [CLI] bundle deploy -qq

=== Edit job with spaces remotely
=== Sync only job with spaces
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB WITH SPACES_ID] --save
Detected changes in 1 resource(s):

Resource: resources.jobs.job with spaces
description: add
tasks[task_key='main'].notebook_task.notebook_path: replace
tasks[task_key='main'].timeout_seconds: replace



>>> diff.py databricks.yml.backup databricks.yml
--- databricks.yml.backup
+++ databricks.yml
@@ -12,7 +12,8 @@
tasks:
- task_key: main
- timeout_seconds: 60
+ timeout_seconds: 900
notebook_task:
- notebook_path: ${var.notebook_root}/notebook
+ notebook_path: ${var.notebook_root}/notebook_updated
+ description: Remote description
"job's\"quotes":
name: quoted-job

=== Syncing job with spaces again is idempotent
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB WITH SPACES_ID] --save
No changes detected.


=== Add a sibling task in job with spaces
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB WITH SPACES_ID] --save
Detected changes in 1 resource(s):

Resource: resources.jobs.job with spaces
tasks[task_key='added']: add



>>> diff.py databricks.yml.backup databricks.yml
--- databricks.yml.backup
+++ databricks.yml
@@ -15,4 +15,7 @@
notebook_task:
notebook_path: ${var.notebook_root}/notebook_updated
+ - notebook_task:
+ notebook_path: ${var.notebook_root}/notebook_updated_sibling
+ task_key: added
description: Remote description
"job's\"quotes":

=== Edit job's"quotes remotely
=== Sync only job's"quotes
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB'S\"QUOTES_ID] --save
Detected changes in 1 resource(s):

Resource: resources.jobs.job's"quotes
description: add
tasks[task_key='main'].notebook_task.notebook_path: replace
tasks[task_key='main'].timeout_seconds: replace



>>> diff.py databricks.yml.backup databricks.yml
--- databricks.yml.backup
+++ databricks.yml
@@ -23,7 +23,8 @@
tasks:
- task_key: main
- timeout_seconds: 60
+ timeout_seconds: 900
notebook_task:
- notebook_path: ${var.notebook_root}/notebook
+ notebook_path: ${var.notebook_root}/notebook_updated
+ description: Remote description

targets:

=== Syncing job's"quotes again is idempotent
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB'S\"QUOTES_ID] --save
No changes detected.


=== Add a sibling task in job's"quotes
>>> [CLI] bundle config-remote-sync --select-ids jobs:[JOB'S\"QUOTES_ID] --save
Detected changes in 1 resource(s):

Resource: resources.jobs.job's"quotes
tasks[task_key='added']: add



>>> diff.py databricks.yml.backup databricks.yml
--- databricks.yml.backup
+++ databricks.yml
@@ -26,4 +26,7 @@
notebook_task:
notebook_path: ${var.notebook_root}/notebook_updated
+ - notebook_task:
+ notebook_path: ${var.notebook_root}/notebook_updated_sibling
+ task_key: added
description: Remote description


>>> [CLI] bundle destroy --auto-approve -qq
45 changes: 45 additions & 0 deletions acceptance/bundle/config-remote-sync/resource_keys/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/bash

envsubst < databricks.yml.tmpl > databricks.yml

cleanup() {
trace $CLI bundle destroy --auto-approve -qq
}
trap cleanup EXIT

trace $CLI bundle deploy -qq

for key in 'job with spaces' "job's\"quotes"; do
job_id="$(read_id.py "$key")"

title "Edit $key remotely"
edit_resource.py jobs "$job_id" <<'PYEDIT'
r["tasks"][0]["timeout_seconds"] = 900
r["tasks"][0]["notebook_task"]["notebook_path"] += "_updated"
r["description"] = "Remote description"
PYEDIT

title "Sync only $key"
cp databricks.yml databricks.yml.backup
trace $CLI bundle config-remote-sync --select-ids "jobs:$job_id" --save
trace diff.py databricks.yml.backup databricks.yml
rm databricks.yml.backup

title "Syncing $key again is idempotent"
trace $CLI bundle config-remote-sync --select-ids "jobs:$job_id" --save | contains.py "No changes detected."

title "Add a sibling task in $key"
edit_resource.py jobs "$job_id" <<'PYEDIT'
r["tasks"].append({
"task_key": "added",
"notebook_task": {
"notebook_path": r["tasks"][0]["notebook_task"]["notebook_path"] + "_sibling"
},
})
PYEDIT

cp databricks.yml databricks.yml.backup
trace $CLI bundle config-remote-sync --select-ids "jobs:$job_id" --save
trace diff.py databricks.yml.backup databricks.yml
rm databricks.yml.backup
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
RecordRequests = false
Ignore = [".databricks", "databricks.yml", "databricks.yml.backup"]

Env.DATABRICKS_BUNDLE_ENABLE_EXPERIMENTAL_YAML_SYNC = "true"
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ bundle:

resources:
jobs:
sample_job:
"sample job's\"quotes":
tasks:
- task_key: new_task
notebook_task:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle-[UNIQUE_NAME]/default/files...
Created jobs.sample_job
Created jobs.sample job's"quotes
Files: 2 uploaded, 0 deleted
Resources: 1 created, 0 changed, 0 deleted, 0 unchanged

Expand All @@ -8,7 +8,7 @@ Resources: 1 created, 0 changed, 0 deleted, 0 unchanged
=== Sync the rename into config (no redeploy)
Detected changes in 1 resource(s):

Resource: resources.jobs.sample_job
Resource: resources.jobs.sample job's"quotes
tasks[task_key='new_task']: remove
tasks[task_key='new_task_2']: add

Expand All @@ -18,7 +18,7 @@ Resource: resources.jobs.sample_job
--- databricks.yml.backup
+++ databricks.yml
@@ -6,5 +6,5 @@
sample_job:
"sample job's\"quotes":
tasks:
- - task_key: new_task
+ - task_key: new_task_2
Expand All @@ -30,7 +30,7 @@ Resource: resources.jobs.sample_job
=== Sync the revert into config
Detected changes in 1 resource(s):

Resource: resources.jobs.sample_job
Resource: resources.jobs.sample job's"quotes
tasks[task_key='new_task']: add
tasks[task_key='new_task_2']: remove

Expand All @@ -40,7 +40,7 @@ Resource: resources.jobs.sample_job
--- databricks.yml.backup
+++ databricks.yml
@@ -6,5 +6,5 @@
sample_job:
"sample job's\"quotes":
tasks:
- - task_key: new_task_2
+ - task_key: new_task
Expand All @@ -49,7 +49,7 @@ Resource: resources.jobs.sample_job

>>> [CLI] bundle destroy --auto-approve
The following resources will be deleted:
delete resources.jobs.sample_job
delete resources.jobs.sample job's"quotes

All files and directories at the following location will be deleted: /Workspace/Users/[USERNAME]/.bundle/test-bundle-[UNIQUE_NAME]/default

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ cleanup() {
trap cleanup EXIT

$CLI bundle deploy
job_id="$(read_id.py sample_job)"
job_id="$(read_id.py "sample job's\"quotes")"

title "Rename task to new_task_2 remotely"
echo
Expand Down
5 changes: 3 additions & 2 deletions bundle/configsync/patch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestApplyChangesToYAML_PreserveFormatting(t *testing.T) {
yamlContent := `# Comment at top
resources:
jobs:
test_job:
"test.job":
name: "Test Job"

# Comment before timeout
Expand All @@ -42,7 +42,7 @@ resources:
mutator.DefaultMutators(ctx, b)

changes := Changes{
"resources.jobs.test_job": ResourceChanges{
"resources.jobs.test.job": ResourceChanges{
"timeout_seconds": &ConfigChangeDesc{
Operation: OperationReplace,
Value: 7200,
Expand All @@ -61,6 +61,7 @@ resources:
modified := fileChanges[0].ModifiedContent

assert.Contains(t, modified, "# Comment at top")
assert.Contains(t, modified, `"test.job":`)
assert.Contains(t, modified, "# Comment before timeout")
assert.Contains(t, modified, "timeout_seconds: 7200")
assert.Equal(t, 2, strings.Count(modified, "\n\n"), "both blank lines should be preserved")
Expand Down
11 changes: 8 additions & 3 deletions bundle/configsync/resolve.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ func ResolveChanges(ctx context.Context, b *bundle.Bundle, configChanges Changes

for _, resourceKey := range resourceKeys {
resourceChanges := configChanges[resourceKey]
// Plan keys are unquoted; only the first two dots separate resource components.
var resourcePath *structpath.PathNode
for _, key := range strings.SplitN(resourceKey, ".", 3) {
resourcePath = structpath.NewStringKey(resourcePath, key)
}

fieldPaths := make([]string, 0, len(resourceChanges))
fieldPathsDepths := map[string]int{}
Expand Down Expand Up @@ -244,13 +249,13 @@ func ResolveChanges(ctx context.Context, b *bundle.Bundle, configChanges Changes
// add of the new one, with nothing linking them. Pairing them back up lets a
// rename be written as a key rewrite in every block that defines the element,
// which keeps a split element split instead of collapsing it into one scope.
renames := matchRenamingPairs(b, blocks, resourceKey, resourceChanges)
renames := matchRenamingPairs(b, blocks, resourcePath.String(), resourceChanges)

indices := newIndexTracker()

for _, fieldPath := range fieldPaths {
configChange := resourceChanges[fieldPath]
fullPath := resourceKey + "." + fieldPath
fullPath := resourcePath.String() + "." + fieldPath

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.

seems you can have ther same issue with fieldPath? you can do structpath.StringKey(resourcePath, fieldPath).String() for reliable representation.


// The add half of a rename carries no source location of its own; the
// pair is written from the remove half, which does.
Expand Down Expand Up @@ -360,7 +365,7 @@ func ResolveChanges(ctx context.Context, b *bundle.Bundle, configChanges Changes
// on it belongs in that same block.
filePath = block.file
} else {
resourceLocation := b.Config.GetLocation(resourceKey)
resourceLocation := b.Config.GetLocationOf(resourcePath)
filePath = resourceLocation.File
}
if filePath == "" {
Expand Down
14 changes: 7 additions & 7 deletions bundle/configsync/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,10 +556,14 @@ func parseTemplateSegments(template string, resolved dyn.Value) []templateSegmen
// preResolvedValueAt returns the pre-resolved dyn.Value at the field path,
// if the field exists in the merged pre-resolved config.
func preResolvedValueAt(preResolved dyn.Value, fieldPath string) (dyn.Value, bool) {
p, err := dyn.NewPathFromString(fieldPath)
node, err := structpath.ParsePath(fieldPath)
if err != nil {
return dyn.InvalidValue, false
}
p, ok := dyn.FromStructPath(node)
if !ok {
return dyn.InvalidValue, false
}
v, err := dyn.GetByPath(preResolved, p)
if err != nil {
return dyn.InvalidValue, false
Expand Down Expand Up @@ -603,12 +607,8 @@ func sequenceSiblings(preResolved dyn.Value, fieldPath string) ([]dyn.Value, boo
if !hasIndex && !node.BracketStar() {
return nil, false
}
p, err := dyn.NewPathFromString(node.Parent().String())
if err != nil {
return nil, false
}
parentValue, err := dyn.GetByPath(preResolved, p)
if err != nil {
parentValue, ok := preResolvedValueAt(preResolved, node.Parent().String())
if !ok {
return nil, false
}
seq, ok := parentValue.AsSequence()
Expand Down
Loading