|
5 | 5 | "errors" |
6 | 6 | "fmt" |
7 | 7 | "slices" |
| 8 | + "strings" |
8 | 9 |
|
9 | 10 | "github.com/databricks/cli/bundle" |
10 | 11 | "github.com/databricks/cli/bundle/config" |
@@ -63,8 +64,19 @@ func (l *load) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { |
63 | 64 | } |
64 | 65 |
|
65 | 66 | // Merge dashboard etags into configuration. |
66 | | - for k, dstate := range state["dashboards"] { |
67 | | - dconfig, ok := b.Config.Resources.Dashboards[k] |
| 67 | + for resourceKey, dstate := range state { |
| 68 | + // Check if this is a dashboard resource key |
| 69 | + if !strings.HasPrefix(resourceKey, "resources.dashboards.") { |
| 70 | + continue |
| 71 | + } |
| 72 | + // Extract dashboard name from "resources.dashboards.name" |
| 73 | + parts := strings.Split(resourceKey, ".") |
| 74 | + if len(parts) != 3 { |
| 75 | + continue |
| 76 | + } |
| 77 | + dashboardName := parts[2] |
| 78 | + |
| 79 | + dconfig, ok := b.Config.Resources.Dashboards[dashboardName] |
68 | 80 |
|
69 | 81 | // Case: A dashboard is defined in state but not in configuration. |
70 | 82 | // In this case the dashboard has been deleted and we do not need to load the etag. |
@@ -98,31 +110,43 @@ func StateToBundle(ctx context.Context, state ExportedResourcesMap, config *conf |
98 | 110 | return v, err |
99 | 111 | } |
100 | 112 |
|
101 | | - for groupName, group := range state { |
| 113 | + for resourceKey, attrs := range state { |
| 114 | + // Parse resource key like "resources.jobs.foo" or "resources.jobs.foo.permissions" |
| 115 | + parts := strings.Split(resourceKey, ".") |
| 116 | + if len(parts) < 3 || parts[0] != "resources" { |
| 117 | + continue // Skip invalid resource keys |
| 118 | + } |
| 119 | + |
| 120 | + groupName := parts[1] |
| 121 | + resourceName := parts[2] |
| 122 | + |
| 123 | + // Skip permissions for now as they are sub-resources |
| 124 | + if len(parts) > 3 { |
| 125 | + continue |
| 126 | + } |
| 127 | + |
102 | 128 | var err error |
103 | 129 | v, err = ensureMap(v, dyn.Path{dyn.Key("resources"), dyn.Key(groupName)}) |
104 | 130 | if err != nil { |
105 | 131 | return v, err |
106 | 132 | } |
107 | 133 |
|
108 | | - for resourceName, attrs := range group { |
109 | | - path := dyn.Path{dyn.Key("resources"), dyn.Key(groupName), dyn.Key(resourceName)} |
110 | | - resource, err := dyn.GetByPath(v, path) |
111 | | - if !resource.IsValid() { |
112 | | - m := dyn.NewMapping() |
113 | | - m.SetLoc("id", nil, dyn.V(attrs.ID)) |
114 | | - m.SetLoc("modified_status", nil, dyn.V(resources.ModifiedStatusDeleted)) |
115 | | - v, err = dyn.SetByPath(v, path, dyn.V(m)) |
116 | | - if err != nil { |
117 | | - return dyn.InvalidValue, err |
118 | | - } |
119 | | - } else if err != nil { |
| 134 | + path := dyn.Path{dyn.Key("resources"), dyn.Key(groupName), dyn.Key(resourceName)} |
| 135 | + resource, err := dyn.GetByPath(v, path) |
| 136 | + if !resource.IsValid() { |
| 137 | + m := dyn.NewMapping() |
| 138 | + m.SetLoc("id", nil, dyn.V(attrs.ID)) |
| 139 | + m.SetLoc("modified_status", nil, dyn.V(resources.ModifiedStatusDeleted)) |
| 140 | + v, err = dyn.SetByPath(v, path, dyn.V(m)) |
| 141 | + if err != nil { |
| 142 | + return dyn.InvalidValue, err |
| 143 | + } |
| 144 | + } else if err != nil { |
| 145 | + return dyn.InvalidValue, err |
| 146 | + } else { |
| 147 | + v, err = dyn.SetByPath(v, dyn.Path{dyn.Key("resources"), dyn.Key(groupName), dyn.Key(resourceName), dyn.Key("id")}, dyn.V(attrs.ID)) |
| 148 | + if err != nil { |
120 | 149 | return dyn.InvalidValue, err |
121 | | - } else { |
122 | | - v, err = dyn.SetByPath(v, dyn.Path{dyn.Key("resources"), dyn.Key(groupName), dyn.Key(resourceName), dyn.Key("id")}, dyn.V(attrs.ID)) |
123 | | - if err != nil { |
124 | | - return dyn.InvalidValue, err |
125 | | - } |
126 | 150 | } |
127 | 151 | } |
128 | 152 | } |
|
0 commit comments