Skip to content
Open
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
1 change: 1 addition & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

### CLI
* Skip non-exportable objects (e.g., `MLFLOW_EXPERIMENT`) during `workspace export-dir` instead of failing ([#4081](https://github.com/databricks/cli/issues/4081))
* Allow domain_friendly_name to be used in name_prefix in development mode ([#4173](https://github.com/databricks/cli/pull/4173))

### Bundles

Expand Down
17 changes: 16 additions & 1 deletion bundle/config/mutator/resourcemutator/validate_target_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func validateDevelopmentMode(b *bundle.Bundle) diag.Diagnostics {
diags = diags.Extend(diag.Errorf("%s must start with '~/' or contain the current username to ensure uniqueness when using 'mode: development'", path))
}
}
if p.NamePrefix != "" && !strings.Contains(p.NamePrefix, u.ShortName) && !strings.Contains(p.NamePrefix, u.UserName) {
if p.NamePrefix != "" && !namePrefixContainsUserIdentifier(p.NamePrefix, u) {
// Resources such as pipelines require a unique name, e.g. '[dev steve] my_pipeline'.
// For this reason we require the name prefix to contain the current username;
// it's a pitfall for users if they don't include it and later find out that
Expand All @@ -83,6 +83,21 @@ func validateDevelopmentMode(b *bundle.Bundle) diag.Diagnostics {
return diags
}

// namePrefixContainsUserIdentifier checks if the name prefix contains any user identifier
// (username, short name, or domain friendly name) to ensure uniqueness.
func namePrefixContainsUserIdentifier(prefix string, u *config.User) bool {
if strings.Contains(prefix, u.UserName) {
return true
}
if strings.Contains(prefix, u.ShortName) {
return true
}
if u.DomainFriendlyName != "" && strings.Contains(prefix, u.DomainFriendlyName) {
return true
}
return false
}

// findNonUserPath finds the first workspace path such as root_path that doesn't
// contain the current username or current user's shortname.
func findNonUserPath(b *bundle.Bundle) string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,23 @@ func TestValidateDevelopmentMode(t *testing.T) {
b.Config.Workspace.ResourcePath = "/Users/lennart@company.com/.bundle/x/y/resources"
diags = validateDevelopmentMode(b)
require.NoError(t, diags.Error())

// Test with a bundle that has a prefix containing the domain_friendly_name
b = mockBundle(config.Development)
b.Config.Workspace.CurrentUser.DomainFriendlyName = "lennartfriendly"
b.Config.Presets.NamePrefix = "[dev-lennartfriendly]"
diags = validateDevelopmentMode(b)
require.NoError(t, diags.Error())

// Test with a bundle that has a prefix containing the short_name
b = mockBundle(config.Development)
b.Config.Presets.NamePrefix = "[dev-lennart]"
diags = validateDevelopmentMode(b)
require.NoError(t, diags.Error())

// Test with a bundle that has a prefix containing the username
b = mockBundle(config.Development)
b.Config.Presets.NamePrefix = "[dev-lennart@company.com]"
diags = validateDevelopmentMode(b)
require.NoError(t, diags.Error())
}