Skip to content

Commit

Permalink
Merge pull request #458 from Juniper/feat/457-predefined-dashboards
Browse files Browse the repository at this point in the history
add code to create predefined dashboards
  • Loading branch information
rajagopalans authored Dec 12, 2024
2 parents eb58936 + c688b18 commit 91d102c
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 10 deletions.
71 changes: 61 additions & 10 deletions apstra/api_iba_dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import (
"fmt"
"math/rand"
"net/http"
"strings"
"time"
)

const (
apiUrlIbaDashboards = "/api/blueprints/%s/iba/dashboards"
apiUrlIbaDashboardsPrefix = apiUrlIbaDashboards + apiUrlPathDelim
apiUrlIbaDashboardsById = apiUrlIbaDashboardsPrefix + "%s"
apiUrlIbaDashboards = "/api/blueprints/%s/iba/dashboards"
apiUrlIbaDashboardsPrefix = apiUrlIbaDashboards + apiUrlPathDelim
apiUrlIbaDashboardsById = apiUrlIbaDashboardsPrefix + "%s"
apiUrlIbaPredefinedDashboards = "/api/blueprints/%s/iba/predefined-dashboards"
apiUrlIbaPredefinedDashboardsPrefix = apiUrlIbaPredefinedDashboards + apiUrlPathDelim
apiUrlIbaPredefinedDashboardsById = apiUrlIbaPredefinedDashboardsPrefix + "%s"
)

var _ json.Unmarshaler = (*IbaDashboard)(nil)
Expand Down Expand Up @@ -88,6 +90,49 @@ func (i *IbaDashboardData) MarshalJSON() ([]byte, error) {
})
}

func (o *Client) listAllIbaPredefinedDashboardIds(ctx context.Context, blueprintId ObjectId) ([]ObjectId, error) {
var response struct {
Items []struct {
Name ObjectId `json:"name"`
} `json:"items"`
}

err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodGet,
urlStr: fmt.Sprintf(apiUrlIbaPredefinedDashboards, blueprintId),
apiResponse: &response,
})
if err != nil {
return nil, convertTtaeToAceWherePossible(err)
}

ids := make([]ObjectId, len(response.Items))
for i, r := range response.Items {
ids[i] = r.Name
}

return ids, nil
}

func (o *Client) instantiateIbaPredefinedDashboard(ctx context.Context, blueprintId ObjectId, dashboardId ObjectId, label string) (ObjectId, error) {
var response objectIdResponse
var in struct {
Label string `json:"label"`
}
in.Label = label
err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodPost,
urlStr: fmt.Sprintf(apiUrlIbaPredefinedDashboardsById, blueprintId, dashboardId),
apiInput: &in,
apiResponse: &response,
})
if err != nil {
return "", convertTtaeToAceWherePossible(err)
}

return response.Id, nil
}

func (o *Client) getAllIbaDashboards(ctx context.Context, BlueprintId ObjectId) ([]IbaDashboard, error) {
var response struct {
Items []IbaDashboard `json:"items"`
Expand Down Expand Up @@ -150,11 +195,12 @@ func (o *Client) getIbaDashboardByLabel(ctx context.Context, blueprintId ObjectI

func (o *Client) createIbaDashboard(ctx context.Context, blueprintId ObjectId, in *IbaDashboardData) (ObjectId, error) {
var response objectIdResponse
if strings.TrimSpace(in.UpdatedBy) != "" {
return "", errors.New("UpdatedBy is set by Apstra")
if in.UpdatedBy != "" {
return "", errors.New("attempt to create dashboard with non-empty updated_by value - this value can be set only by the server")
}
if strings.TrimSpace(in.PredefinedDashboard) != "" {
return "", errors.New("predefined Dashboard should not be defined here")
if in.PredefinedDashboard != "" {
return "", errors.New("attempt to create dashboard with non-empty predefined_dashboard value - this value can " +
"be set only by the server, and only when a dashboard is instantiated from a predefined template")
}
err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodPost,
Expand Down Expand Up @@ -206,9 +252,14 @@ func (o *Client) createIbaDashboard(ctx context.Context, blueprintId ObjectId, i
}

func (o *Client) updateIbaDashboard(ctx context.Context, blueprintId ObjectId, id ObjectId, in *IbaDashboardData) error {
if strings.TrimSpace(in.UpdatedBy) != "" {
return errors.New("UpdatedBy is set by Apstra")
if in.UpdatedBy != "" {
return errors.New("attempt to update dashboard with non-empty updated_by value - this value can be set only by the server")
}
if in.PredefinedDashboard != "" {
return errors.New("attempt to update dashboard with non-empty predefined_dashboard value - this value can " +
"be set only by the server, and only when a dashboard is instantiated from a predefined template")
}

err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodPut, urlStr: fmt.Sprintf(apiUrlIbaDashboardsById, blueprintId, id), apiInput: in,
})
Expand Down
35 changes: 35 additions & 0 deletions apstra/api_iba_dashboards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,41 @@ func TestCreateReadUpdateDeleteIbaDashboards(t *testing.T) {
bpClient := testBlueprintA(ctx, t, client.client)
widgetA, widgetB := testWidgetsAB(ctx, t, bpClient)

pds, err := bpClient.ListAllIbaPredefinedDashboardIds(ctx)
require.NoError(t, err)
t.Log(len(pds))

for _, d := range pds {

// Some predefined dashboards cannot be tested
switch d {
case "evpn_vxlan_route_summary": // This one requires the blueprint to be deployed
continue
}

id, err := bpClient.InstantiateIbaPredefinedDashboard(ctx, d, d.String())
require.NoError(t, err)

t.Logf("Name :%s Created Id :%s", d, id)
t.Log("Getting Dashboard")
d1, err := bpClient.GetIbaDashboard(ctx, id)
require.NoError(t, err)

d1.Data.Label = randString(5, "hex")
t.Log("Updating Dashboard")

err = bpClient.UpdateIbaDashboard(ctx, id, d1.Data)
require.NoError(t, err)

d2, err := bpClient.GetIbaDashboard(ctx, id)
require.NoError(t, err)
require.Equalf(t, d1.Data.Label, d2.Data.Label, "Update Seems to have failed. Label should have been %s is %s", d1.Data.Label, d2.Data.Label)

t.Log("Deleting Dashboard")
err = bpClient.DeleteIbaDashboard(ctx, id)
require.NoError(t, err)
}

ds, err := bpClient.GetAllIbaDashboards(ctx)
require.NoError(t, err)
require.Equalf(t, 0, len(ds), "Expected no dashboards, got %d.", len(ds))
Expand Down
16 changes: 16 additions & 0 deletions apstra/two_stage_l3_clos_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,22 @@ func (o *TwoStageL3ClosClient) CreateIbaProbeFromJson(ctx context.Context, probe
return o.client.createIbaProbeFromJson(ctx, o.blueprintId, probeJson)
}

// ListAllIbaPredefinedDashboardIds returns a list of Predefined IBA Dashboards in the blueprint
func (o *TwoStageL3ClosClient) ListAllIbaPredefinedDashboardIds(ctx context.Context) ([]ObjectId, error) {
if !compatibility.IbaDashboardSupported.Check(o.client.apiVersion) {
return nil, fmt.Errorf("this version of the SDK will not support IBA Dashboards with Asptra %s", o.client.apiVersion)
}
return o.client.listAllIbaPredefinedDashboardIds(ctx, o.blueprintId)
}

// InstantiateIbaPredefinedDashboard instantiates a Predefined IBA Dashboard
func (o *TwoStageL3ClosClient) InstantiateIbaPredefinedDashboard(ctx context.Context, dashboardId ObjectId, label string) (ObjectId, error) {
if !compatibility.IbaDashboardSupported.Check(o.client.apiVersion) {
return "", fmt.Errorf("this version of the SDK will not support IBA Dashboards with Asptra %s", o.client.apiVersion)
}
return o.client.instantiateIbaPredefinedDashboard(ctx, o.blueprintId, dashboardId, label)
}

// GetAllIbaDashboards returns a list of IBA Dashboards in the blueprint
func (o *TwoStageL3ClosClient) GetAllIbaDashboards(ctx context.Context) ([]IbaDashboard, error) {
if !compatibility.IbaDashboardSupported.Check(o.client.apiVersion) {
Expand Down

0 comments on commit 91d102c

Please sign in to comment.