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
4 changes: 2 additions & 2 deletions acceptance/bundle/resources/apps/lifecycle-started/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Deployment complete!
"description": "MY_APP_DESCRIPTION_2",
"name": "[UNIQUE_NAME]"
},
"update_mask": "description"
"update_mask": "description,budget_policy_id,usage_policy_id,resources,user_api_scopes,compute_size,git_repository,telemetry_export_destinations"
}
}

Expand Down Expand Up @@ -112,7 +112,7 @@ Deployment complete!
"description": "MY_APP_DESCRIPTION_3",
"name": "[UNIQUE_NAME]"
},
"update_mask": "description"
"update_mask": "description,budget_policy_id,usage_policy_id,resources,user_api_scopes,compute_size,git_repository,telemetry_export_destinations"
}
}
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"description": "MY_APP_DESCRIPTION",
"name": "myappname"
},
"update_mask": "description"
"update_mask": "description,budget_policy_id,usage_policy_id,resources,user_api_scopes,compute_size,git_repository,telemetry_export_destinations"
},
"method": "POST",
"path": "/api/2.0/apps/myappname/update"
Expand Down
23 changes: 13 additions & 10 deletions bundle/direct/dresources/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"slices"
"strings"
"time"

Expand Down Expand Up @@ -163,19 +162,23 @@ func (r *ResourceApp) DoCreate(ctx context.Context, config *AppState) (string, *
return app.Name, nil, nil
}

var UpdateMaskFields = []string{
Comment thread
andrewnester marked this conversation as resolved.
"description",
"budget_policy_id",
"usage_policy_id",
"resources",
"user_api_scopes",
"compute_size",
"git_repository",
"telemetry_export_destinations",
}

var updateMask = strings.Join(UpdateMaskFields, ",")

func (r *ResourceApp) DoUpdate(ctx context.Context, id string, config *AppState, entry *PlanEntry) (*AppRemote, error) {
// Deploy-only fields (source_code_path, config,
// git_source, lifecycle) are not part of apps.App and thus excluded from the request body.
if hasAppChanges(entry) {
fieldPaths := collectUpdatePathsWithPrefix(entry.Changes, "")
slices.Sort(fieldPaths)
for i, fieldPath := range fieldPaths {
fieldPaths[i] = truncateAtIndex(fieldPath)
}
fieldPaths = slices.DeleteFunc(fieldPaths, func(p string) bool {
return deployOnlyFields[p]
})
updateMask := strings.Join(fieldPaths, ",")
request := apps.AsyncUpdateAppRequest{
App: &config.App,
AppName: id,
Expand Down
47 changes: 47 additions & 0 deletions bundle/direct/dresources/app_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dresources

import (
"reflect"
"slices"
"strings"
"testing"

"github.com/databricks/cli/libs/testserver"
Expand Down Expand Up @@ -120,3 +123,47 @@ func TestAppDoCreate_RetriesWhenGetReturnsNotFound(t *testing.T) {
assert.Equal(t, 2, createCallCount, "expected Create to be called twice")
assert.Equal(t, 1, getCallCount, "expected Get to be called once to check app state")
}

func TestAppDoUpdate_UpdateMaskHasAllFields(t *testing.T) {
Comment thread
andrewnester marked this conversation as resolved.
// iterate over all apps.App fields using reflection and ensure that UpdateMaskFields contains all of them.
config := GetGeneratedResourceConfig("apps")
require.NotNil(t, config)
var nonUpdatableFields []string
for _, field := range config.IgnoreRemoteChanges {
nonUpdatableFields = append(nonUpdatableFields, field.Field.String())
}

for _, field := range config.RecreateOnChanges {
nonUpdatableFields = append(nonUpdatableFields, field.Field.String())
}

config = GetResourceConfig("apps")
require.NotNil(t, config)
for _, field := range config.IgnoreRemoteChanges {
nonUpdatableFields = append(nonUpdatableFields, field.Field.String())
}

for _, field := range config.RecreateOnChanges {
nonUpdatableFields = append(nonUpdatableFields, field.Field.String())
}

app := apps.App{}
fields := reflect.TypeOf(app)
var allFields []string
for i := range fields.NumField() {
field := fields.Field(i)
jsonTag := field.Tag.Get("json")
if jsonTag == "" || jsonTag == "-" {
continue
}
jsonTag = strings.TrimSuffix(jsonTag, ",omitempty")
allFields = append(allFields, jsonTag)
if !slices.Contains(nonUpdatableFields, jsonTag) {
assert.Contains(t, UpdateMaskFields, jsonTag, "field %s is not in UpdateMaskFields and not marked as non-updatable", jsonTag)
}
}

for _, field := range UpdateMaskFields {
assert.Contains(t, allFields, field, "field %s is in UpdateMaskFields but not in apps.App struct", field)
}
}
3 changes: 3 additions & 0 deletions bundle/direct/dresources/resources.yml
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,9 @@ resources:
# drift detection applies (e.g. detecting out-of-band stop).
- field: lifecycle
- field: lifecycle.started
ignore_remote_changes:
- field: space # This field is not yet supported by Update APIs but exposed in the API spec. TODO: fix when update APIs supports it.
reason: managed

secret_scopes:
backend_defaults:
Expand Down
Loading