diff --git a/bundle/permissions/permission_diagnostics.go b/bundle/permissions/permission_diagnostics.go index 3f3aec46..43b8acaa 100644 --- a/bundle/permissions/permission_diagnostics.go +++ b/bundle/permissions/permission_diagnostics.go @@ -8,7 +8,6 @@ import ( "github.com/databricks/cli/bundle" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/dyn" - "github.com/databricks/cli/libs/log" "github.com/databricks/cli/libs/set" ) @@ -106,43 +105,3 @@ func isGroupOfCurrentUser(b *bundle.Bundle, groupName string) bool { } return false } - -// ReportPossiblePermissionDenied generates a diagnostic message when a permission denied error is encountered. -// -// Note that since the workspace API doesn't always distinguish between permission denied and path errors, -// we must treat this as a "possible permission error". See acquire.go for more about this. -func ReportPossiblePermissionDenied(ctx context.Context, b *bundle.Bundle, path string) diag.Diagnostics { - log.Errorf(ctx, "Failed to update, encountered possible permission error: %v", path) - - user := b.Config.Workspace.CurrentUser.DisplayName - if user == "" { - user = b.Config.Workspace.CurrentUser.UserName - } - canManageBundle, assistance := analyzeBundlePermissions(b) - - if !canManageBundle { - return diag.Diagnostics{{ - Summary: fmt.Sprintf("unable to deploy to %s as %s.\n"+ - "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n"+ - "%s\n"+ - "They may need to redeploy the bundle to apply the new permissions.\n"+ - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.", - path, user, assistance), - Severity: diag.Error, - ID: diag.PathPermissionDenied, - }} - } - - // According databricks.yml, the current user has the right permissions. - // But we're still seeing permission errors. So someone else will need - // to redeploy the bundle with the right set of permissions. - return diag.Diagnostics{{ - Summary: fmt.Sprintf("access denied while updating deployment permissions as %s.\n"+ - "%s\n"+ - "They can redeploy the project to apply the latest set of permissions.\n"+ - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.", - user, assistance), - Severity: diag.Error, - ID: diag.CannotChangePathPermissions, - }} -} diff --git a/bundle/permissions/permission_diagnostics_test.go b/bundle/permissions/permission_diagnostics_test.go index a1051484..a13ae171 100644 --- a/bundle/permissions/permission_diagnostics_test.go +++ b/bundle/permissions/permission_diagnostics_test.go @@ -41,72 +41,6 @@ func TestPermissionDiagnosticsApplySuccessWithOwner(t *testing.T) { require.Empty(t, diags) } -func TestPermissionDiagnosticsPermissionDeniedWithGroup(t *testing.T) { - b := mockBundle([]resources.Permission{ - {Level: "CAN_MANAGE", GroupName: "testgroup"}, - }) - - diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") - expected := "EPERM3: access denied while updating deployment permissions as testuser@databricks.com.\n" + - "For assistance, contact the owners of this project.\n" + - "They can redeploy the project to apply the latest set of permissions.\n" + - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." - require.ErrorContains(t, diags.Error(), expected) -} - -func TestPermissionDiagnosticsPermissionDeniedWithOtherGroup(t *testing.T) { - b := mockBundle([]resources.Permission{ - {Level: "CAN_MANAGE", GroupName: "othergroup"}, - }) - - diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") - expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + - "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + - "For assistance, users or groups with appropriate permissions may include: othergroup.\n" + - "They may need to redeploy the bundle to apply the new permissions.\n" + - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." - require.ErrorContains(t, diags.Error(), expected) -} - -func TestPermissionDiagnosticsPermissionDeniedWithoutPermission(t *testing.T) { - b := mockBundle([]resources.Permission{ - {Level: "CAN_VIEW", UserName: "testuser@databricks.com"}, - }) - - diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") - expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + - "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + - "For assistance, contact the owners of this project.\n" + - "They may need to redeploy the bundle to apply the new permissions.\n" + - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." - require.ErrorContains(t, diags.Error(), expected) -} - -func TestPermissionDiagnosticsPermissionDeniedNilPermission(t *testing.T) { - b := mockBundle(nil) - - diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") - expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + - "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + - "For assistance, contact the owners of this project.\n" + - "They may need to redeploy the bundle to apply the new permissions.\n" + - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions" - require.ErrorContains(t, diags.Error(), expected) -} - -func TestPermissionDiagnosticsFindOtherOwners(t *testing.T) { - b := mockBundle([]resources.Permission{ - {Level: "CAN_MANAGE", GroupName: "testgroup"}, - {Level: "CAN_MANAGE", UserName: "alice@databricks.com"}, - }) - - diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") - require.ErrorContains(t, diags.Error(), "EPERM3: access denied while updating deployment permissions as testuser@databricks.com.\n"+ - "For assistance, users or groups with appropriate permissions may include: alice@databricks.com.\n"+ - "They can redeploy the project to apply the latest set of permissions.\n"+ - "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.") -} - func mockBundle(permissions []resources.Permission) *bundle.Bundle { return &bundle.Bundle{ Config: config.Root{ diff --git a/bundle/permissions/permission_report.go b/bundle/permissions/permission_report.go new file mode 100644 index 00000000..c9e4281e --- /dev/null +++ b/bundle/permissions/permission_report.go @@ -0,0 +1,50 @@ +package permissions + +import ( + "context" + "fmt" + + "github.com/databricks/cli/bundle" + "github.com/databricks/cli/libs/diag" + "github.com/databricks/cli/libs/log" +) + +// ReportPossiblePermissionDenied generates a diagnostic message when a permission denied error is encountered. +// +// Note that since the workspace API doesn't always distinguish between permission denied and path errors, +// we must treat this as a "possible permission error". See acquire.go for more about this. +func ReportPossiblePermissionDenied(ctx context.Context, b *bundle.Bundle, path string) diag.Diagnostics { + log.Errorf(ctx, "Failed to update, encountered possible permission error: %v", path) + + user := b.Config.Workspace.CurrentUser.DisplayName + if user == "" { + user = b.Config.Workspace.CurrentUser.UserName + } + canManageBundle, assistance := analyzeBundlePermissions(b) + + if !canManageBundle { + return diag.Diagnostics{{ + Summary: fmt.Sprintf("unable to deploy to %s as %s.\n"+ + "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n"+ + "%s\n"+ + "They may need to redeploy the bundle to apply the new permissions.\n"+ + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.", + path, user, assistance), + Severity: diag.Error, + ID: diag.PathPermissionDenied, + }} + } + + // According databricks.yml, the current user has the right permissions. + // But we're still seeing permission errors. So someone else will need + // to redeploy the bundle with the right set of permissions. + return diag.Diagnostics{{ + Summary: fmt.Sprintf("unable to deploy to %s as %s. Cannot apply local deployment permissions.\n"+ + "%s\n"+ + "They can redeploy the project to apply the latest set of permissions.\n"+ + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.", + path, user, assistance), + Severity: diag.Error, + ID: diag.CannotChangePathPermissions, + }} +} diff --git a/bundle/permissions/permission_report_test.go b/bundle/permissions/permission_report_test.go new file mode 100644 index 00000000..61592f7e --- /dev/null +++ b/bundle/permissions/permission_report_test.go @@ -0,0 +1,76 @@ +package permissions_test + +import ( + "context" + "testing" + + "github.com/databricks/cli/bundle/config/resources" + "github.com/databricks/cli/bundle/permissions" + "github.com/stretchr/testify/require" +) + +func TestPermissionsReportPermissionDeniedWithGroup(t *testing.T) { + b := mockBundle([]resources.Permission{ + {Level: "CAN_MANAGE", GroupName: "testgroup"}, + }) + + diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") + expected := "EPERM3: unable to deploy to testpath as testuser@databricks.com. Cannot apply local deployment permissions.\n" + + "For assistance, contact the owners of this project.\n" + + "They can redeploy the project to apply the latest set of permissions.\n" + + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." + require.ErrorContains(t, diags.Error(), expected) +} + +func TestPermissionsReportPermissionDeniedWithOtherGroup(t *testing.T) { + b := mockBundle([]resources.Permission{ + {Level: "CAN_MANAGE", GroupName: "othergroup"}, + }) + + diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") + expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + + "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + + "For assistance, users or groups with appropriate permissions may include: othergroup.\n" + + "They may need to redeploy the bundle to apply the new permissions.\n" + + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." + require.ErrorContains(t, diags.Error(), expected) +} + +func TestPermissionsReportPermissionDeniedWithoutPermission(t *testing.T) { + b := mockBundle([]resources.Permission{ + {Level: "CAN_VIEW", UserName: "testuser@databricks.com"}, + }) + + diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") + expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + + "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + + "For assistance, contact the owners of this project.\n" + + "They may need to redeploy the bundle to apply the new permissions.\n" + + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions." + require.ErrorContains(t, diags.Error(), expected) +} + +func TestPermissionsReportPermissionDeniedNilPermission(t *testing.T) { + b := mockBundle(nil) + + diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") + expected := "EPERM1: unable to deploy to testpath as testuser@databricks.com.\n" + + "Please make sure the current user or one of their groups is listed under the permissions of this bundle.\n" + + "For assistance, contact the owners of this project.\n" + + "They may need to redeploy the bundle to apply the new permissions.\n" + + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions" + require.ErrorContains(t, diags.Error(), expected) +} + +func TestPermissionsReportFindOtherOwners(t *testing.T) { + b := mockBundle([]resources.Permission{ + {Level: "CAN_MANAGE", GroupName: "testgroup"}, + {Level: "CAN_MANAGE", UserName: "alice@databricks.com"}, + }) + + diags := permissions.ReportPossiblePermissionDenied(context.Background(), b, "testpath") + require.ErrorContains(t, diags.Error(), "EPERM3: unable to deploy to testpath as testuser@databricks.com. Cannot apply local deployment permissions.\n"+ + "For assistance, users or groups with appropriate permissions may include: alice@databricks.com.\n"+ + "They can redeploy the project to apply the latest set of permissions.\n"+ + "Please refer to https://docs.databricks.com/dev-tools/bundles/permissions.html for more on managing permissions.") +}