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
40 changes: 17 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
# make fmtcheck -- formate check
# make vet -- go vet
# make lint -- go lint
# make deadcode -- deadcode checker
# make test -- run tests
# make clean -- clean
#
Expand All @@ -23,11 +22,12 @@ GOLDFLAGS := -ldflags="-s -w"

DEFAULT_GOPATH := $${GOPATH%%:*}
GO := go
GOFMT := goimports
GOLINT := golint
GO_DEADCODE := deadcode
GOFMT := gofmt
LINT := golangci-lint run
LINTFLAGS ?= --deadline=10m --exclude-use-default=false --print-issued-lines --print-linter-name --out-format=colored-line-number --disable-all --max-same-issues=0 --max-issues-per-linter=0
LINTCONFIG := --config golangci.yml
GOFILES := find . -name '*.go' ! -path './Godeps/*' ! -path './vendor/*'
GOFOLDERS := $(GO) list ./... | sed 's:^github.com/aristanetworks/go-cvprac:.:' | grep -vw -e './vendor'
GOFOLDERS := $(GO) list ./... | sed 's:^github.com/aristanetworks/go-cvprac/v3:.:' | grep -vw -e './vendor'

VERSION_FILE = version.go
GOPKGVERSION := $(shell git describe --tags --always --match "v[0-9]*" --abbrev=7 HEAD)
Expand All @@ -37,35 +37,29 @@ endif

# External Tools
EXTERNAL_TOOLS=\
github.com/golang/lint/golint \
github.com/remyoudompheng/go-misc/deadcode \
golang.org/x/tools/cmd/godoc \
golang.org/x/tools/cmd/goimports

check: fmtcheck vet lint deadcode unittest

deadcode:
@if ! which $(GO_DEADCODE) >/dev/null; then echo Please install $(GO_DEADCODE); exit 1; fi
$(GOFOLDERS) | xargs $(GO_DEADCODE)
check: fmtcheck vet lint unittest

lint:
lint=`$(GOFOLDERS) | xargs -L 1 $(GOLINT)`; if test -n "$$lint"; then echo "$$lint"; exit 1; fi
# The above is ugly, but unfortunately golint doesn't exit 1 when it finds
# lint. See https://github.com/golang/lint/issues/65
$(GOFOLDERS) | xargs $(LINT) $(LINTFLAGS) --disable-all --enable=deadcode --tests=false
$(GOFOLDERS) | xargs $(LINT) $(LINTCONFIG) $(LINTFLAGS)

fmtcheck:
@if ! which $(GOFMT) >/dev/null; then echo Please install $(GOFMT); exit 1; fi
goimports=`$(GOFILES) | xargs $(GOFMT) -l 2>&1`; \
if test -n "$$goimports"; then echo Check the following files for coding style AND USE goimports; echo "$$goimports"; \
if test "$(shell $(GO) version | awk '{ print $$3 }')" != "devel"; then exit 1; fi; \
fi
$(GOFILES) -exec ./check_line_len.awk {} +
goimports=`$(GOFILES) | xargs $(GOFMT) -d 2>&1`; \
if test -n "$$goimports"; then \
echo Check the following files for coding style AND USE goimports; \
echo "$$goimports"; \
exit 1; \
fi

fmt:
$(GO) fmt
$(GOFOLDERS) | xargs $(GO) fmt

vet:
$(GO) vet
$(GOFOLDERS) | xargs $(GO) vet

test:
$(GO) test $(GOTEST_FLAGS)
Expand Down Expand Up @@ -110,5 +104,5 @@ clean:
rm -rf $(COVER_TMPFILE).tmp $(COVER_TMPFILE) $(VERSION_FILE){,-t}
$(GO) clean ./...

.PHONY: all fmtcheck test vet check doc lint deadcode
.PHONY: all fmtcheck test vet check doc lint
.PHONY: clean coverage coverdata version
3 changes: 2 additions & 1 deletion api/configletbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ func (c CvpRestAPI) GenerateAutoConfiglet(devKeyList []string, builderKey string
}

// GenerateConfigletForDevice ...
func (c CvpRestAPI) GenerateConfigletForDevice(dev *NetElement, builder *ConfigletBuilder) (*Configlet, error) {
func (c CvpRestAPI) GenerateConfigletForDevice(dev *NetElement,
builder *ConfigletBuilder) (*Configlet, error) {
if dev == nil {
return nil, errors.Errorf("GenerateConfigletForDevice: dev nil")
}
Expand Down
3 changes: 2 additions & 1 deletion api/cvprac_system_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// +build systest
//go:build systest

//
// Copyright (c) 2016-2017, Arista Networks, Inc. All rights reserved.
//
Expand Down
3 changes: 2 additions & 1 deletion api/export_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// +build systest
//go:build systest

//
// Copyright (c) 2016-2017, Arista Networks, Inc. All rights reserved.
//
Expand Down
3 changes: 2 additions & 1 deletion api/provisioning.go
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,8 @@ func (c CvpRestAPI) ValidateAndApplyConfigletsToDevice(appName string, dev *NetE
}

// Run Validation of new configlets to be applied
validateResp, err := c.ValidateConfigletsForDevice(dev.SystemMacAddress, configletAndBuilders.keys)
validateResp, err := c.ValidateConfigletsForDevice(dev.SystemMacAddress,
configletAndBuilders.keys)
if err != nil {
return nil, errors.Errorf("ApplyConfigletsToDevice: %s", err)
}
Expand Down
9 changes: 6 additions & 3 deletions api/provisioning_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ func Test_checkConfigMapping(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, configletAndBuilders, err := checkConfigMapping(tt.args.applied, tt.args.newconfiglets)
got, configletAndBuilders, err := checkConfigMapping(tt.args.applied,
tt.args.newconfiglets)
if (err != nil) != tt.wantErr {
t.Errorf("checkConfigMapping() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down Expand Up @@ -246,11 +247,13 @@ func Test_checkRemoveConfigMapping(t *testing.T) {
}

if !reflect.DeepEqual(configletAndBuilders, tt.want1) {
t.Errorf("checkRemoveConfigMapping() configletAndBuilders = %v, want %v", configletAndBuilders, tt.want1)
t.Errorf("checkRemoveConfigMapping() configletAndBuilders = %v, want %v",
configletAndBuilders, tt.want1)
}

if !reflect.DeepEqual(rmConfigletAndBuilders, tt.want2) {
t.Errorf("checkRemoveConfigMapping() rmConfigletAndBuilders = %v, want %v", rmConfigletAndBuilders, tt.want2)
t.Errorf("checkRemoveConfigMapping() rmConfigletAndBuilders = %v, want %v",
rmConfigletAndBuilders, tt.want2)
}
})
}
Expand Down
163 changes: 163 additions & 0 deletions api/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//
// Copyright (c) 2016-2023, Arista Networks, Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// * Neither the name of Arista Networks nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARISTA NETWORKS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//

package cvpapi

import (
"bytes"
"encoding/json"
"time"

"github.com/pkg/errors"
)

// Result type for a `Get<x>Rsc` or `Get<x>sRsc` request.
type resultRsc struct {
// Response body.
Result *valueRsc `json:"result"`
// The time that this resource was last modified.
Time *time.Time `json:"time,omitempty"`

resourceGetError
}

// The response body for a `Get<x>Rsc` or `Get<x>sRsc` request.
type valueRsc struct {
// Generic resource type.
Value json.RawMessage `json:"value"`
// Optional time at which this resource was last modified.
Time time.Time `json:"time"`
// Optional type data included with some resources (e.g.,
// change control approvals).
Type string `json:"type"`

resourceGetError
}

// Failure state associated with resource API requests.
type resourceGetError struct {
// Error code supplied if a request fails.
Code *int `json:"code,omitempty"`
// Optional explanation for a request failure.
Message *string `json:"message,omitempty"`
}

// Errors associated with the state of an item from the resource API.
type ResourceError struct {
// An error attached to this item.
//
// The presence of this string does not necessarily mean that *this*
// request failed, e.g., a scheduled execution might expire before its change
// is approved.
Error *string `json:"error,omitempty"`
}

// Wrapper type for a list of strings in Resource API requests
// and responses.
type StringList struct {
Values []string `json:"values"`
}

// Wrapper type for a 2D string array in Resource API requests
// and responses.
type StringMatrix struct {
Values []StringList `json:"values"`
}

// Wrapper type for a string map in Resource API requests
// and responses.
type StringMap struct {
Values map[string]string `json:"values"`
}

// A boolean flag.
type FlagRsc struct {
Value bool `json:"value"`

ModifiedBy
}

// A timestamp flag.
type TimestampFlagRsc struct {
Value *time.Time `json:"value,omitempty"`

ModifiedBy
}

// Modification data for fields of a Resource API value.
type ModifiedBy struct {
// The time this field was updated at.
Time *time.Time `json:"time,omitempty"`
// The user who last updated this field.
User *string `json:"user,omitempty"`
// A comment explaining the last change made to this field.
Notes *string `json:"notes,omitempty"`
}

func (v *resourceGetError) GetError() error {
if v.Code != nil {
err := errors.Errorf("resource API lookup failed [code %d]", v.Code)
if v.Message != nil {
err = errors.Errorf("%s: %s", err, *v.Message)
}
return err
}

return nil
}

// Resource APIs hand us back newline-delimited Json on /all endpoints.
// This converts a call into a list of usable Json objects.
func resultList(data []byte) ([]resultRsc, error) {
out := []resultRsc{}

decoder := json.NewDecoder(bytes.NewReader(data))

for decoder.More() {
el := resultRsc{}

if err := decoder.Decode(&el); err != nil {
return nil, err
}

if err := el.GetError(); err != nil {
return nil, err
}

if el.Result == nil {
return nil, errors.Errorf("missing 'Value' field from ndJson response")
}

out = append(out, el)
}

return out, nil
}
Loading