Skip to content

Commit 5c2b02f

Browse files
api-clients-generation-pipeline[bot]ci.datadog-api-spec
andauthored
dashboards - Add DashboardTab schema and tabs property to Dashboard spec (#3712)
Co-authored-by: ci.datadog-api-spec <packages@datadoghq.com>
1 parent 4e75bd2 commit 5c2b02f

4 files changed

Lines changed: 244 additions & 4 deletions

File tree

.generator/schemas/v1/openapi.yaml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,13 @@ components:
13141314
description: A role UUID.
13151315
type: string
13161316
type: array
1317+
tabs:
1318+
description: List of tabs for organizing dashboard widgets into groups.
1319+
items:
1320+
$ref: '#/components/schemas/DashboardTab'
1321+
maxItems: 100
1322+
nullable: true
1323+
type: array
13171324
tags:
13181325
description: List of team names representing ownership of a dashboard.
13191326
items:
@@ -1584,6 +1591,36 @@ components:
15841591
description: URL of the dashboard.
15851592
type: string
15861593
type: object
1594+
DashboardTab:
1595+
description: Dashboard tab for organizing widgets.
1596+
properties:
1597+
id:
1598+
description: UUID of the tab.
1599+
example: ''
1600+
format: uuid
1601+
type: string
1602+
name:
1603+
description: Name of the tab.
1604+
example: L
1605+
maxLength: 100
1606+
minLength: 1
1607+
type: string
1608+
widget_ids:
1609+
description: List of widget IDs belonging to this tab. The backend also
1610+
accepts positional references in @N format (1-indexed) as a convenience
1611+
for Terraform and other declarative tools.
1612+
example:
1613+
- 0
1614+
items:
1615+
description: Widget ID.
1616+
format: int64
1617+
type: integer
1618+
type: array
1619+
required:
1620+
- id
1621+
- name
1622+
- widget_ids
1623+
type: object
15871624
DashboardTemplateVariable:
15881625
description: Template variable.
15891626
properties:

api/datadogV1/model_dashboard.go

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ type Dashboard struct {
4141
ReflowType *DashboardReflowType `json:"reflow_type,omitempty"`
4242
// A list of role identifiers. Only the author and users associated with at least one of these roles can edit this dashboard.
4343
RestrictedRoles []string `json:"restricted_roles,omitempty"`
44+
// List of tabs for organizing dashboard widgets into groups.
45+
Tabs []DashboardTab `json:"tabs,omitempty"`
4446
// List of team names representing ownership of a dashboard.
4547
Tags datadog.NullableList[string] `json:"tags,omitempty"`
4648
// Array of template variables saved views.
@@ -417,6 +419,35 @@ func (o *Dashboard) SetRestrictedRoles(v []string) {
417419
o.RestrictedRoles = v
418420
}
419421

422+
// GetTabs returns the Tabs field value if set, zero value otherwise (both if not set or set to explicit null).
423+
func (o *Dashboard) GetTabs() []DashboardTab {
424+
if o == nil {
425+
var ret []DashboardTab
426+
return ret
427+
}
428+
return o.Tabs
429+
}
430+
431+
// GetTabsOk returns a tuple with the Tabs field value if set, nil otherwise
432+
// and a boolean to check if the value has been set.
433+
// NOTE: If the value is an explicit nil, `nil, true` will be returned.
434+
func (o *Dashboard) GetTabsOk() (*[]DashboardTab, bool) {
435+
if o == nil || o.Tabs == nil {
436+
return nil, false
437+
}
438+
return &o.Tabs, true
439+
}
440+
441+
// HasTabs returns a boolean if a field has been set.
442+
func (o *Dashboard) HasTabs() bool {
443+
return o != nil && o.Tabs != nil
444+
}
445+
446+
// SetTabs gets a reference to the given []DashboardTab and assigns it to the Tabs field.
447+
func (o *Dashboard) SetTabs(v []DashboardTab) {
448+
o.Tabs = v
449+
}
450+
420451
// GetTags returns the Tags field value if set, zero value otherwise (both if not set or set to explicit null).
421452
func (o *Dashboard) GetTags() []string {
422453
if o == nil || o.Tags.Get() == nil {
@@ -633,6 +664,9 @@ func (o Dashboard) MarshalJSON() ([]byte, error) {
633664
if o.RestrictedRoles != nil {
634665
toSerialize["restricted_roles"] = o.RestrictedRoles
635666
}
667+
if o.Tabs != nil {
668+
toSerialize["tabs"] = o.Tabs
669+
}
636670
if o.Tags.IsSet() {
637671
toSerialize["tags"] = o.Tags.Get()
638672
}
@@ -668,6 +702,7 @@ func (o *Dashboard) UnmarshalJSON(bytes []byte) (err error) {
668702
NotifyList datadog.NullableList[string] `json:"notify_list,omitempty"`
669703
ReflowType *DashboardReflowType `json:"reflow_type,omitempty"`
670704
RestrictedRoles []string `json:"restricted_roles,omitempty"`
705+
Tabs []DashboardTab `json:"tabs,omitempty"`
671706
Tags datadog.NullableList[string] `json:"tags,omitempty"`
672707
TemplateVariablePresets []DashboardTemplateVariablePreset `json:"template_variable_presets,omitempty"`
673708
TemplateVariables []DashboardTemplateVariable `json:"template_variables,omitempty"`
@@ -689,7 +724,7 @@ func (o *Dashboard) UnmarshalJSON(bytes []byte) (err error) {
689724
}
690725
additionalProperties := make(map[string]interface{})
691726
if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil {
692-
datadog.DeleteKeys(additionalProperties, &[]string{"author_handle", "author_name", "created_at", "description", "id", "is_read_only", "layout_type", "modified_at", "notify_list", "reflow_type", "restricted_roles", "tags", "template_variable_presets", "template_variables", "title", "url", "widgets"})
727+
datadog.DeleteKeys(additionalProperties, &[]string{"author_handle", "author_name", "created_at", "description", "id", "is_read_only", "layout_type", "modified_at", "notify_list", "reflow_type", "restricted_roles", "tabs", "tags", "template_variable_presets", "template_variables", "title", "url", "widgets"})
693728
} else {
694729
return err
695730
}
@@ -714,6 +749,7 @@ func (o *Dashboard) UnmarshalJSON(bytes []byte) (err error) {
714749
o.ReflowType = all.ReflowType
715750
}
716751
o.RestrictedRoles = all.RestrictedRoles
752+
o.Tabs = all.Tabs
717753
o.Tags = all.Tags
718754
o.TemplateVariablePresets = all.TemplateVariablePresets
719755
o.TemplateVariables = all.TemplateVariables
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License.
2+
// This product includes software developed at Datadog (https://www.datadoghq.com/).
3+
// Copyright 2019-Present Datadog, Inc.
4+
5+
package datadogV1
6+
7+
import (
8+
"fmt"
9+
10+
"github.com/google/uuid"
11+
12+
"github.com/DataDog/datadog-api-client-go/v2/api/datadog"
13+
)
14+
15+
// DashboardTab Dashboard tab for organizing widgets.
16+
type DashboardTab struct {
17+
// UUID of the tab.
18+
Id uuid.UUID `json:"id"`
19+
// Name of the tab.
20+
Name string `json:"name"`
21+
// List of widget IDs belonging to this tab. The backend also accepts positional references in @N format (1-indexed) as a convenience for Terraform and other declarative tools.
22+
WidgetIds []int64 `json:"widget_ids"`
23+
// UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct
24+
UnparsedObject map[string]interface{} `json:"-"`
25+
AdditionalProperties map[string]interface{} `json:"-"`
26+
}
27+
28+
// NewDashboardTab instantiates a new DashboardTab object.
29+
// This constructor will assign default values to properties that have it defined,
30+
// and makes sure properties required by API are set, but the set of arguments
31+
// will change when the set of required properties is changed.
32+
func NewDashboardTab(id uuid.UUID, name string, widgetIds []int64) *DashboardTab {
33+
this := DashboardTab{}
34+
this.Id = id
35+
this.Name = name
36+
this.WidgetIds = widgetIds
37+
return &this
38+
}
39+
40+
// NewDashboardTabWithDefaults instantiates a new DashboardTab object.
41+
// This constructor will only assign default values to properties that have it defined,
42+
// but it doesn't guarantee that properties required by API are set.
43+
func NewDashboardTabWithDefaults() *DashboardTab {
44+
this := DashboardTab{}
45+
return &this
46+
}
47+
48+
// GetId returns the Id field value.
49+
func (o *DashboardTab) GetId() uuid.UUID {
50+
if o == nil {
51+
var ret uuid.UUID
52+
return ret
53+
}
54+
return o.Id
55+
}
56+
57+
// GetIdOk returns a tuple with the Id field value
58+
// and a boolean to check if the value has been set.
59+
func (o *DashboardTab) GetIdOk() (*uuid.UUID, bool) {
60+
if o == nil {
61+
return nil, false
62+
}
63+
return &o.Id, true
64+
}
65+
66+
// SetId sets field value.
67+
func (o *DashboardTab) SetId(v uuid.UUID) {
68+
o.Id = v
69+
}
70+
71+
// GetName returns the Name field value.
72+
func (o *DashboardTab) GetName() string {
73+
if o == nil {
74+
var ret string
75+
return ret
76+
}
77+
return o.Name
78+
}
79+
80+
// GetNameOk returns a tuple with the Name field value
81+
// and a boolean to check if the value has been set.
82+
func (o *DashboardTab) GetNameOk() (*string, bool) {
83+
if o == nil {
84+
return nil, false
85+
}
86+
return &o.Name, true
87+
}
88+
89+
// SetName sets field value.
90+
func (o *DashboardTab) SetName(v string) {
91+
o.Name = v
92+
}
93+
94+
// GetWidgetIds returns the WidgetIds field value.
95+
func (o *DashboardTab) GetWidgetIds() []int64 {
96+
if o == nil {
97+
var ret []int64
98+
return ret
99+
}
100+
return o.WidgetIds
101+
}
102+
103+
// GetWidgetIdsOk returns a tuple with the WidgetIds field value
104+
// and a boolean to check if the value has been set.
105+
func (o *DashboardTab) GetWidgetIdsOk() (*[]int64, bool) {
106+
if o == nil {
107+
return nil, false
108+
}
109+
return &o.WidgetIds, true
110+
}
111+
112+
// SetWidgetIds sets field value.
113+
func (o *DashboardTab) SetWidgetIds(v []int64) {
114+
o.WidgetIds = v
115+
}
116+
117+
// MarshalJSON serializes the struct using spec logic.
118+
func (o DashboardTab) MarshalJSON() ([]byte, error) {
119+
toSerialize := map[string]interface{}{}
120+
if o.UnparsedObject != nil {
121+
return datadog.Marshal(o.UnparsedObject)
122+
}
123+
toSerialize["id"] = o.Id
124+
toSerialize["name"] = o.Name
125+
toSerialize["widget_ids"] = o.WidgetIds
126+
127+
for key, value := range o.AdditionalProperties {
128+
toSerialize[key] = value
129+
}
130+
return datadog.Marshal(toSerialize)
131+
}
132+
133+
// UnmarshalJSON deserializes the given payload.
134+
func (o *DashboardTab) UnmarshalJSON(bytes []byte) (err error) {
135+
all := struct {
136+
Id *uuid.UUID `json:"id"`
137+
Name *string `json:"name"`
138+
WidgetIds *[]int64 `json:"widget_ids"`
139+
}{}
140+
if err = datadog.Unmarshal(bytes, &all); err != nil {
141+
return datadog.Unmarshal(bytes, &o.UnparsedObject)
142+
}
143+
if all.Id == nil {
144+
return fmt.Errorf("required field id missing")
145+
}
146+
if all.Name == nil {
147+
return fmt.Errorf("required field name missing")
148+
}
149+
if all.WidgetIds == nil {
150+
return fmt.Errorf("required field widget_ids missing")
151+
}
152+
additionalProperties := make(map[string]interface{})
153+
if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil {
154+
datadog.DeleteKeys(additionalProperties, &[]string{"id", "name", "widget_ids"})
155+
} else {
156+
return err
157+
}
158+
o.Id = *all.Id
159+
o.Name = *all.Name
160+
o.WidgetIds = *all.WidgetIds
161+
162+
if len(additionalProperties) > 0 {
163+
o.AdditionalProperties = additionalProperties
164+
}
165+
166+
return nil
167+
}

tests/scenarios/features/v1/dashboards.feature

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ Feature: Dashboards
9090
@generated @skip @team:DataDog/dashboards-backend
9191
Scenario: Create a new dashboard returns "Bad Request" response
9292
Given new "CreateDashboard" request
93-
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
93+
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tabs": [{"id": "", "name": "L", "widget_ids": [0]}], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
9494
When the request is sent
9595
Then the response status is 400 Bad Request
9696

@@ -1373,15 +1373,15 @@ Feature: Dashboards
13731373
Scenario: Update a dashboard returns "Bad Request" response
13741374
Given new "UpdateDashboard" request
13751375
And request contains "dashboard_id" parameter from "REPLACE.ME"
1376-
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
1376+
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tabs": [{"id": "", "name": "L", "widget_ids": [0]}], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
13771377
When the request is sent
13781378
Then the response status is 400 Bad Request
13791379

13801380
@generated @skip @team:DataDog/dashboards-backend
13811381
Scenario: Update a dashboard returns "Item Not Found" response
13821382
Given new "UpdateDashboard" request
13831383
And request contains "dashboard_id" parameter from "REPLACE.ME"
1384-
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
1384+
And body with value {"description": null, "is_read_only": false, "layout_type": "ordered", "notify_list": [], "reflow_type": "auto", "restricted_roles": [], "tabs": [{"id": "", "name": "L", "widget_ids": [0]}], "tags": [], "template_variable_presets": [{"template_variables": [{"values": []}]}], "template_variables": [{"available_values": ["my-host", "host1", "host2"], "default": "my-host", "defaults": ["my-host-1", "my-host-2"], "name": "host1", "prefix": "host", "type": "group"}], "title": "", "widgets": [{"definition": {"requests": {"fill": {"q": "avg:system.cpu.user{*}"}}, "type": "hostmap"}}]}
13851385
When the request is sent
13861386
Then the response status is 404 Item Not Found
13871387

0 commit comments

Comments
 (0)