Skip to content

Commit

Permalink
Merge pull request #453 from Juniper/feat/452-iba-5.0.0
Browse files Browse the repository at this point in the history
add code to update iba for 5.0
  • Loading branch information
rajagopalans authored Nov 23, 2024
2 parents 010ff47 + 57a0603 commit eb58936
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 752 deletions.
161 changes: 81 additions & 80 deletions apstra/api_iba_dashboards.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ package apstra

import (
"context"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net/http"
"strings"
"time"
)

Expand All @@ -19,121 +21,111 @@ const (
apiUrlIbaDashboardsById = apiUrlIbaDashboardsPrefix + "%s"
)

type rawIbaDashboard struct {
Id string `json:"id,omitempty"`
Label string `json:"label"`
Description string `json:"description"`
Default bool `json:"default,omitempty"`
CreatedAt string `json:"created_at,omitempty"`
UpdatedAt string `json:"updated_at,omitempty"`
IbaWidgetGrid [][]ObjectId `json:"grid"`
PredefinedDashboard string `json:"predefined_dashboard,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
}
var _ json.Unmarshaler = (*IbaDashboard)(nil)

type IbaDashboard struct {
Id ObjectId
CreatedAt time.Time
UpdatedAt time.Time
Data *IbaDashboardData
Id ObjectId
Data *IbaDashboardData
}

func (i *IbaDashboard) UnmarshalJSON(bytes []byte) error {
var raw struct {
Id string `json:"id"`
Label string `json:"label"`
Description string `json:"description"`
Default bool `json:"default"`
CreatedAt *string `json:"created_at"`
UpdatedAt *string `json:"updated_at"`
IbaWidgetGrid [][]IbaWidgetData `json:"grid"`
PredefinedDashboard string `json:"predefined_dashboard"`
UpdatedBy string `json:"updated_by"`
}

err := json.Unmarshal(bytes, &raw)
if err != nil {
return err
}

i.Id = ObjectId(raw.Id)
i.Data = &IbaDashboardData{
Description: raw.Description,
Default: raw.Default,
Label: raw.Label,
IbaWidgetGrid: raw.IbaWidgetGrid,
PredefinedDashboard: raw.PredefinedDashboard,
UpdatedBy: raw.UpdatedBy,
}

return nil
}

var _ json.Marshaler = (*IbaDashboardData)(nil)

type IbaDashboardData struct {
Description string
Default bool
Label string
IbaWidgetGrid [][]ObjectId
IbaWidgetGrid [][]IbaWidgetData
PredefinedDashboard string
UpdatedBy string
}

func (o *IbaDashboardData) raw() *rawIbaDashboard {
IbaWidgetGrid := make([][]ObjectId, len(o.IbaWidgetGrid))

for i, g := range o.IbaWidgetGrid {
for _, v := range g {
IbaWidgetGrid[i] = append(IbaWidgetGrid[i], v)
}
}

return &rawIbaDashboard{
Label: o.Label,
Description: o.Description,
Default: o.Default,
IbaWidgetGrid: IbaWidgetGrid,
PredefinedDashboard: o.PredefinedDashboard,
UpdatedBy: o.UpdatedBy,
}
func (i *IbaDashboardData) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Label string `json:"label"`
Description string `json:"description"`
Default bool `json:"default,omitempty"`
IbaWidgetGrid [][]IbaWidgetData `json:"grid"`
PredefinedDashboard string `json:"predefined_dashboard,omitempty"`
UpdatedBy string `json:"updated_by,omitempty"`
}{
Label: i.Label,
Description: i.Description,
Default: i.Default,
IbaWidgetGrid: i.IbaWidgetGrid,
PredefinedDashboard: i.PredefinedDashboard,
UpdatedBy: i.UpdatedBy,
})
}

func (o *rawIbaDashboard) polish() (*IbaDashboard, error) {
var err error

IbaWidgetGrid := make([][]ObjectId, len(o.IbaWidgetGrid))
for i, g := range o.IbaWidgetGrid {
for _, v := range g {
IbaWidgetGrid[i] = append(IbaWidgetGrid[i], ObjectId(v))
}
func (o *Client) getAllIbaDashboards(ctx context.Context, BlueprintId ObjectId) ([]IbaDashboard, error) {
var response struct {
Items []IbaDashboard `json:"items"`
}

created, err := time.Parse("2006-01-02T15:04:05.000000+0000", o.CreatedAt)
if err != nil {
return nil, fmt.Errorf("failure parsing create time %s - %w", o.CreatedAt, err)
}
updated, err := time.Parse("2006-01-02T15:04:05.000000+0000", o.UpdatedAt)
if err != nil {
return nil, fmt.Errorf("failure parsing update time %s - %w", o.UpdatedAt, err)
}
return &IbaDashboard{
Id: ObjectId(o.Id),
CreatedAt: created,
UpdatedAt: updated,
Data: &IbaDashboardData{
Description: o.Description,
Default: o.Default,
Label: o.Label,
IbaWidgetGrid: IbaWidgetGrid,
PredefinedDashboard: o.PredefinedDashboard,
UpdatedBy: o.UpdatedBy,
},
}, nil
}

func (o *Client) getAllIbaDashboards(ctx context.Context, blueprint_id ObjectId) ([]rawIbaDashboard, error) {
response := &struct {
Items []rawIbaDashboard `json:"items"`
}{}

err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodGet, urlStr: fmt.Sprintf(apiUrlIbaDashboards, blueprint_id.String()),
apiResponse: response,
method: http.MethodGet,
urlStr: fmt.Sprintf(apiUrlIbaDashboards, BlueprintId),
apiResponse: &response,
})
if err != nil {
return nil, convertTtaeToAceWherePossible(err)
}
return response.Items, nil
}

func (o *Client) getIbaDashboard(ctx context.Context, blueprintId ObjectId, id ObjectId) (*rawIbaDashboard, error) {
response := &rawIbaDashboard{}
func (o *Client) getIbaDashboard(ctx context.Context, blueprintId ObjectId, id ObjectId) (*IbaDashboard, error) {
var response IbaDashboard
err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodGet, urlStr: fmt.Sprintf(apiUrlIbaDashboardsById, blueprintId, id), apiResponse: response,
method: http.MethodGet,
urlStr: fmt.Sprintf(apiUrlIbaDashboardsById, blueprintId, id),
apiResponse: &response,
})
if err != nil {
return nil, convertTtaeToAceWherePossible(err)
}
return response, nil
return &response, nil
}

func (o *Client) getIbaDashboardByLabel(ctx context.Context, blueprintId ObjectId, label string) (*rawIbaDashboard, error) {
func (o *Client) getIbaDashboardByLabel(ctx context.Context, blueprintId ObjectId, label string) (*IbaDashboard, error) {
dashes, err := o.getAllIbaDashboards(ctx, blueprintId)
if err != nil {
return nil, convertTtaeToAceWherePossible(err)
}

var result []rawIbaDashboard
var result []IbaDashboard
for _, w := range dashes {
if w.Label == label {
if w.Data.Label == label {
result = append(result, w)
}
}
Expand All @@ -156,8 +148,14 @@ func (o *Client) getIbaDashboardByLabel(ctx context.Context, blueprintId ObjectI
return &result[0], nil
}

func (o *Client) createIbaDashboard(ctx context.Context, blueprintId ObjectId, in *rawIbaDashboard) (ObjectId, error) {
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 strings.TrimSpace(in.PredefinedDashboard) != "" {
return "", errors.New("predefined Dashboard should not be defined here")
}
err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodPost,
urlStr: fmt.Sprintf(apiUrlIbaDashboards, blueprintId),
Expand Down Expand Up @@ -207,7 +205,10 @@ func (o *Client) createIbaDashboard(ctx context.Context, blueprintId ObjectId, i
return "", errors.Join(err, fmt.Errorf("reached retry limit %d", retryMax))
}

func (o *Client) updateIbaDashboard(ctx context.Context, blueprintId ObjectId, id ObjectId, in *rawIbaDashboard) error {
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")
}
err := o.talkToApstra(ctx, &talkToApstraIn{
method: http.MethodPut, urlStr: fmt.Sprintf(apiUrlIbaDashboardsById, blueprintId, id), apiInput: in,
})
Expand Down
18 changes: 11 additions & 7 deletions apstra/api_iba_dashboards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ package apstra
import (
"context"
"fmt"
"reflect"
"testing"

"github.com/Juniper/apstra-go-sdk/apstra/compatibility"
Expand All @@ -33,7 +32,7 @@ func TestCreateReadUpdateDeleteIbaDashboards(t *testing.T) {
}

bpClient := testBlueprintA(ctx, t, client.client)
widgetAId, _, widgetBId, _ := testWidgetsAB(ctx, t, bpClient)
widgetA, widgetB := testWidgetsAB(ctx, t, bpClient)

ds, err := bpClient.GetAllIbaDashboards(ctx)
require.NoError(t, err)
Expand All @@ -43,16 +42,19 @@ func TestCreateReadUpdateDeleteIbaDashboards(t *testing.T) {
Description: "Test Dashboard",
Default: false,
Label: "Test Dash",
IbaWidgetGrid: [][]ObjectId{{widgetAId, widgetBId}, {widgetAId, widgetBId}},
IbaWidgetGrid: [][]IbaWidgetData{{widgetA, widgetB}},
}
id, err := bpClient.CreateIbaDashboard(ctx, &req1)
require.NoError(t, err)

widgetA.Label = "label2A"
widgetB.Label = "label2B"

req2 := IbaDashboardData{
Description: "Test Dashboard Backup",
Default: false,
Label: "Test Dash B",
IbaWidgetGrid: [][]ObjectId{{widgetAId, widgetBId}, {widgetAId, widgetBId}},
IbaWidgetGrid: [][]IbaWidgetData{{widgetA, widgetB}},
}
_, err = bpClient.CreateIbaDashboard(ctx, &req2)
require.NoError(t, err)
Expand All @@ -71,19 +73,21 @@ func TestCreateReadUpdateDeleteIbaDashboards(t *testing.T) {

priorValue := req1.UpdatedBy
req1.UpdatedBy = d1.Data.UpdatedBy // this wasn't part of the request
if !reflect.DeepEqual(req1, *d1.Data) {
if !compareDashboards(req1, *d1.Data) {
t.Log(req1)
t.Log(d1.Data)
t.Fatal("Dashboard request doesn't match GetIbaDashboard.Data")
}
req1.UpdatedBy = priorValue // restore prior value

if !reflect.DeepEqual(d1, d2) {
if !compareDashboards(*d1.Data, *d2.Data) {
t.Fatal("GetIbaDashboardByLabel gets different object than GetIbaDashboard")
}
}
checkDashes()

req1.Label = "Test Dash 2"
req1.IbaWidgetGrid = append(req1.IbaWidgetGrid, []ObjectId{widgetAId, widgetBId})
req1.IbaWidgetGrid = append(req1.IbaWidgetGrid, []IbaWidgetData{widgetA, widgetB})
req1.Description = "Test Dashboard 2"
err = bpClient.UpdateIbaDashboard(ctx, id, &req1)
require.NoError(t, err)
Expand Down
47 changes: 1 addition & 46 deletions apstra/api_iba_predefined_probes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ import (
"log"
"testing"

"github.com/Juniper/apstra-go-sdk/apstra/compatibility"

"github.com/Juniper/apstra-go-sdk/apstra/enum"
"github.com/stretchr/testify/require"
)

Expand All @@ -30,11 +27,6 @@ func TestIbaPredefinedProbes(t *testing.T) {
t.Run(fmt.Sprintf("%s_%s", client.client.apiVersion, clientName), func(t *testing.T) {
t.Parallel()

if !compatibility.IbaProbeSupported.Check(client.client.apiVersion) ||
!compatibility.IbaWidgetSupported.Check(client.client.apiVersion) {
t.Skip()
}

log.Printf("testing Predefined Probes against %s %s (%s)", client.clientType, clientName, client.client.ApiVersion())

bpClient := testBlueprintA(ctx, t, client.client)
Expand Down Expand Up @@ -79,49 +71,12 @@ func TestIbaPredefinedProbes(t *testing.T) {
if !expectedToFail[p.Name] {
t.Fatal(err)
} else {
t.Log(err)
t.Logf("%s was expected to fail", p.Name)
continue
}
}

t.Logf("Got back Probe Id %s \n Now Make a Widget with it.", probeId)

widgetId, err := bpClient.CreateIbaWidget(ctx, &IbaWidgetData{
Type: enum.IbaWidgetTypeStage,
ProbeId: probeId,
Label: p.Name,
StageName: p.Name,
})
if err != nil {
t.Fatal(err)
}
t.Logf("Got back Widget Id %s \n Now fetch it.", widgetId)

widget, err := bpClient.GetIbaWidget(ctx, widgetId)
if err != nil {
t.Fatal(err)
}
t.Logf("Widget %s created", widget.Data.Label)

t.Logf("Try to Delete Probe this should fail because a widget is using it")
err = bpClient.DeleteIbaProbe(ctx, probeId)
if err == nil {
t.Fatal("Probe Deletion should have failed")
} else {
t.Log(err)
}

t.Logf("Delete Widget and then the probe this path should succeed")
err = bpClient.DeleteIbaWidget(ctx, widgetId)
if err != nil {
t.Fatal(err)
}
t.Logf("Delete probe")

err = bpClient.DeleteIbaProbe(ctx, probeId)
if err != nil {
t.Fatal(err)
}
}
})
}
Expand Down
7 changes: 0 additions & 7 deletions apstra/api_iba_probes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import (
"log"
"testing"

"github.com/Juniper/apstra-go-sdk/apstra/compatibility"

"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -359,11 +357,6 @@ func TestIbaProbes(t *testing.T) {
t.Run(fmt.Sprintf("%s_%s", client.client.apiVersion, clientName), func(t *testing.T) {
t.Parallel()

if !compatibility.IbaProbeSupported.Check(client.client.apiVersion) ||
!compatibility.IbaWidgetSupported.Check(client.client.apiVersion) {
t.Skip()
}

log.Printf("testing Predefined Probes against %s %s (%s)", client.clientType, clientName, client.client.ApiVersion())

bpClient := testBlueprintA(ctx, t, client.client)
Expand Down
Loading

0 comments on commit eb58936

Please sign in to comment.