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
25 changes: 25 additions & 0 deletions acceptance/bundle/dms/plan-and-summary/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,21 @@ Target: default
Workspace:
User: [USERNAME]
Path: /Workspace/Users/[USERNAME]/.bundle/plan-summary-test/default
Deployment:
ID: [UUID]
Version: 1
Resources:
Jobs:
test_job:
Name: test-job
URL: [DATABRICKS_URL]/jobs/[NUMID]?w=[NUMID]

>>> [CLI] bundle summary -o json
{
"deployment_id": "[UUID]",
"version_id": "1"
}

>>> print_requests.py --get //bundle ^//workspace-files ^//import-file
{
"method": "POST",
Expand Down Expand Up @@ -103,3 +112,19 @@ Resources:
},
"body": null
}
{
"method": "GET",
"path": "/api/2.0/bundle/deployments/[UUID]"
}
{
"method": "GET",
"path": "/api/2.0/bundle/deployments/[UUID]/resources",
"q": {
"page_size": "1000"
},
"body": null
}
{
"method": "GET",
"path": "/api/2.0/bundle/deployments/[UUID]"
}
3 changes: 3 additions & 0 deletions acceptance/bundle/dms/plan-and-summary/script
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ trace $CLI bundle plan
# Summary should show the deployment ID and read state from DMS.
trace $CLI bundle summary

# Summary in JSON mode exposes the deployment metadata for programmatic use.
trace $CLI bundle summary -o json | jq .deployment

# Print metadata service requests from plan and summary.
# Both should include ListResources calls.
trace print_requests.py --get //bundle ^//workspace-files ^//import-file
Expand Down
25 changes: 24 additions & 1 deletion bundle/render/render_text_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ const resourcesTemplate = `Resources:
{{- end }}
`

const deploymentTemplate = `Deployment:
ID: {{ .DeploymentId | bold }}
{{- if .VersionId }}
Version: {{ .VersionId | bold }}
{{- end }}
`

type ResourceGroup struct {
GroupName string
Resources []ResourceInfo
Expand Down Expand Up @@ -136,14 +143,20 @@ func RenderDiagnosticsSummary(ctx context.Context, out io.Writer, b *bundle.Bund
return nil
}

func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error {
func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle, deploymentID, versionID string) error {
if b == nil {
return nil
}
if err := renderSummaryHeaderTemplate(ctx, out, b); err != nil {
return err
}

if deploymentID != "" {
if err := renderDeploymentTemplate(ctx, out, deploymentID, versionID); err != nil {
return fmt.Errorf("failed to render deployment template: %w", err)
}
}

var resourceGroups []ResourceGroup

for _, group := range b.Config.Resources.AllResources() {
Expand Down Expand Up @@ -171,6 +184,16 @@ func RenderSummary(ctx context.Context, out io.Writer, b *bundle.Bundle) error {
return nil
}

// renderDeploymentTemplate renders the bundle's deployment metadata service
// identifiers (deployment_id and the current version_id).
func renderDeploymentTemplate(ctx context.Context, out io.Writer, deploymentID, versionID string) error {
t := template.Must(template.New("deployment").Funcs(cmdio.RenderFuncMap(ctx)).Parse(deploymentTemplate))
return t.Execute(out, map[string]any{
"DeploymentId": deploymentID,
"VersionId": versionID,
})
}

// Helper function to sort and render resource groups using the template
func renderResourcesTemplate(ctx context.Context, out io.Writer, resourceGroups []ResourceGroup) error {
// Sort everything to ensure consistent output
Expand Down
2 changes: 1 addition & 1 deletion bundle/render/render_text_output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func TestRenderSummary(t *testing.T) {
}

writer := &bytes.Buffer{}
err := RenderSummary(ctx, writer, b)
err := RenderSummary(ctx, writer, b, "", "")
require.NoError(t, err)

expectedSummary := `Name: test-bundle
Expand Down
62 changes: 58 additions & 4 deletions cmd/bundle/summary.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package bundle

import (
"context"
"encoding/json"
"fmt"

"github.com/databricks/cli/bundle"
"github.com/databricks/cli/bundle/render"
"github.com/databricks/cli/cmd/bundle/utils"
"github.com/databricks/cli/cmd/root"
"github.com/databricks/cli/libs/flags"
"github.com/databricks/cli/libs/logdiag"
"github.com/databricks/cli/libs/tmpdms"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -51,11 +56,60 @@ Useful after deployment to see what was created and where to find it.`,
}

func showSummary(cmd *cobra.Command, b *bundle.Bundle) error {
if root.OutputType(cmd) == flags.OutputText {
return render.RenderSummary(cmd.Context(), cmd.OutOrStdout(), b)
ctx := cmd.Context()

// When the deployment metadata service is in use, surface the bundle's
// deployment_id and current version_id so callers (e.g. the workspace UI)
// can link to the deployment metadata. Both are empty otherwise.
versionID, err := currentDeploymentVersion(ctx, b)
if err != nil {
return err
}

switch root.OutputType(cmd) {
case flags.OutputText:
return render.RenderSummary(ctx, cmd.OutOrStdout(), b, b.DeploymentID, versionID)
case flags.OutputJSON:
return renderSummaryJSON(cmd, b, versionID)
}
return nil
}

// currentDeploymentVersion returns the latest version_id recorded for the
// bundle's deployment, or "" when the deployment metadata service is not in use.
func currentDeploymentVersion(ctx context.Context, b *bundle.Bundle) (string, error) {
if b.DeploymentID == "" {
return "", nil
}
svc, err := tmpdms.NewDeploymentMetadataAPI(b.WorkspaceClient(ctx))
if err != nil {
return "", fmt.Errorf("failed to create metadata service client: %w", err)
}
dep, err := svc.GetDeployment(ctx, tmpdms.GetDeploymentRequest{DeploymentID: b.DeploymentID})
if err != nil {
return "", fmt.Errorf("failed to get deployment: %w", err)
}
return dep.LastVersionID, nil
}

// renderSummaryJSON marshals the bundle configuration and, when the deployment
// metadata service is in use, adds a top-level "deployment" object carrying the
// deployment_id and version_id.
func renderSummaryJSON(cmd *cobra.Command, b *bundle.Bundle, versionID string) error {
value := b.Config.Value().AsAny()
if b.DeploymentID != "" {
// The config root is always a mapping for a loaded bundle.
value.(map[string]any)["deployment"] = map[string]string{
"deployment_id": b.DeploymentID,
"version_id": versionID,
}
}
if root.OutputType(cmd) == flags.OutputJSON {
return renderJsonOutput(cmd, b)
buf, err := json.MarshalIndent(value, "", " ")
if err != nil {
return err
}
out := cmd.OutOrStdout()
_, _ = out.Write(buf)
_, _ = out.Write([]byte{'\n'})
return nil
}
Loading