diff --git a/.gitlab/ci/.code-quality-ci.yml b/.gitlab/ci/.code-quality-ci.yml index 92e6b501ef628540b527146643029252808c7ac9..acef63a432e83cde3dc89b12693333f78b1c843d 100644 --- a/.gitlab/ci/.code-quality-ci.yml +++ b/.gitlab/ci/.code-quality-ci.yml @@ -1,10 +1,9 @@ code-quality: - image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.42-alpine + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/golangci/golangci-lint:v1.45-alpine stage: analyze script: # writes golangci-lint output to gl-code-quality-report.json - apk add --update make jq - - cd controller/ - make ci-lint artifacts: reports: diff --git a/.gitlab/ci/.golangci-config/.runlint.sh b/.gitlab/ci/.golangci-config/.runlint.sh deleted file mode 100755 index 774573b108c985a07f43d16ed44d0f63c1a7c8ca..0000000000000000000000000000000000000000 --- a/.gitlab/ci/.golangci-config/.runlint.sh +++ /dev/null @@ -1,4 +0,0 @@ -golangci-lint run\ - --config .ci/.golangci.yml\ - --out-format code-climate |\ - jq -r '.[] | "\(.location.path):\(.location.lines.begin) \(.description)"' diff --git a/.gitlab/ci/.golangci-config/.golangci.yml b/.golangci.yml similarity index 80% rename from .gitlab/ci/.golangci-config/.golangci.yml rename to .golangci.yml index 53a29c482a1ee4adbed540965032b06c8c2af5ea..894ea22bf69db911b97f7093798094fdf22ba2d3 100644 --- a/.gitlab/ci/.golangci-config/.golangci.yml +++ b/.golangci.yml @@ -1,13 +1,18 @@ run: + go: 1.18 + concurrency: 4 timeout: 10m issues-exit-code: 1 # directories to be ignored by linters skip-dirs: - - forks - - test + - controller/forks + - controller/test + - controller/mocks skip-dirs-default: true skip-files: - http.go + modules-download-mode: readonly + # output settings -> code-climate for GitLab output: format: code-climate @@ -15,14 +20,16 @@ output: print-linter-name: true uniq-by-line: true path-prefix: "" + # custom settings for linters linters-settings: gocyclo: min-complexity: 15 golint: min-confidence: 0.8 -# enable the specific needed linters + linters: + # enable the specific needed linters disable-all: true enable: - gofmt diff --git a/Makefile b/Makefile index 78fd8cf5d934718340d1a8d2d7a91e36649cb2dd..8b7569837704aa866a6d80de66d4d629e510e6ee 100644 --- a/Makefile +++ b/Makefile @@ -19,12 +19,21 @@ install-tools: @echo Install development tooling mkdir -p $(GOSDN_PRG) go install gotest.tools/gotestsum@v1.7.0 - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42 + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.1 @echo Finished installing development tooling ci-install-tools: go install gotest.tools/gotestsum@v1.7.0 +ci-lint: ci-install-tools + golangci-lint run --config .golangci.yml --out-format code-climate | jq -r '.[] | "\(.location.path):\(.location.lines.begin) \(.description)"' + +lint: install-tools + ./$(TOOLS_DIR)/golangci-lint run --config .golangci.yml | jq + +lint-fix: install-tools + ./$(TOOLS_DIR)/golangci-lint run --config .golangci.yml --fix | jq + build: pre $(GOBUILD) -o $(BUILD_ARTIFACTS_PATH)/gosdn ./controller/cmd/gosdn CGO_ENABLED=0 $(GOBUILD) -o $(BUILD_ARTIFACTS_PATH)/gosdnc ./cli/ @@ -43,7 +52,6 @@ containerlab-stop: containerlab-graph: sudo containerlab graph --topo gosdn.clab.yaml - shell-gosdn: docker exec -it clab-gosdn_csbi_arista_base-gosdn bash shell-orchestrator: diff --git a/cli/adapter/PndAdapter.go b/cli/adapter/PndAdapter.go index b3147df614070d47df5ad72ea4334adb3a46853c..e593d40f47986cb0ac4287f5fbcc6a578b7c7fc2 100644 --- a/cli/adapter/PndAdapter.go +++ b/cli/adapter/PndAdapter.go @@ -23,7 +23,7 @@ type PndAdapter struct { endpoint string } -// NewAdapter creates a PND Adapter. It requires a valid PND UUID and a reachable +// NewPndAdapter creates a PND Adapter. It requires a valid PND UUID and a reachable // goSDN endpoint. func NewPndAdapter(id, endpoint string) (*PndAdapter, error) { pid, err := uuid.Parse(id) @@ -56,6 +56,7 @@ func (p *PndAdapter) AddDevice(name string, opts *tpb.TransportOption, sid uuid. return resp, nil } +// GetSbiSchemaTree requests a sbi schema tree. func (p *PndAdapter) GetSbiSchemaTree(sid uuid.UUID) (map[string]*yang.Entry, error) { resp, err := api.GetSbiSchemaTree(p.Endpoint(), p.ID(), sid) if err != nil { diff --git a/cli/cmd/deviceList.go b/cli/cmd/deviceList.go index 02b0251f96cd86dde2cfdc97a1e27ef1ca57b249..9e73e82eb004be29114a2176b23584fd18777782 100644 --- a/cli/cmd/deviceList.go +++ b/cli/cmd/deviceList.go @@ -43,7 +43,7 @@ var deviceListCmd = &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "list all devices in current PND", - Long: `List all orchestrated network devices within the current PND.`, + Long: "List all orchestrated network devices within the current PND.", RunE: func(cmd *cobra.Command, args []string) error { resp, err := pndAdapter.GetDevices() @@ -60,7 +60,7 @@ var deviceListCmd = &cobra.Command{ if err != nil { return err } - log.Infof(" SchemaTree: ", tree) + log.Infof(" SchemaTree: %v", tree) } return nil }, diff --git a/cli/cmd/prompt.go b/cli/cmd/prompt.go index aa4c341f648583ad76d457b84145cd6efbdcbe0d..f4828889d8ec806ac12891a4a3f62aa91d68385d 100644 --- a/cli/cmd/prompt.go +++ b/cli/cmd/prompt.go @@ -46,19 +46,22 @@ import ( var suggestions []prompt.Suggest -type promptCompleter struct { +// PromptCompleter provides completion for a device +type PromptCompleter struct { //NOTE: not too sure about this but for now it should be sufficient - deviceId uuid.UUID + deviceID uuid.UUID yangSchemaCompleterMap map[uuid.UUID]*completer.YangSchemaCompleter } -func NewPromptCompleter() *promptCompleter { - return &promptCompleter{ +// NewPromptCompleter returns a new promptCompleter +func NewPromptCompleter() *PromptCompleter { + return &PromptCompleter{ yangSchemaCompleterMap: make(map[uuid.UUID]*completer.YangSchemaCompleter), } } -func (pc *promptCompleter) Run() { +// Run starts the interactive completion +func (pc *PromptCompleter) Run() { fmt.Println("Welcome to the interactive mode of gosdnc.") defer fmt.Println("Bye!") @@ -99,7 +102,7 @@ func flagVisitor(f *pflag.Flag) { } } -func (pc *promptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest { +func (pc *PromptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest { // Start with the cobra 'rootCmd' and walk through it // Reference: https://github.com/stromland/cobra-prompt currCmd := rootCmd @@ -109,7 +112,6 @@ func (pc *promptCompleter) cstmCompleter(d prompt.Document) []prompt.Suggest { } return completionBasedOnCmd(pc, currCmd, inputSplit, d) - } func removeFlagsFromInputSlice(input []string) []string { @@ -122,7 +124,7 @@ func removeFlagsFromInputSlice(input []string) []string { return r } -func deviceGetCompletion(c *promptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest { +func deviceGetCompletion(c *PromptCompleter, d prompt.Document, inputSplit []string) []prompt.Suggest { inputLen := len(inputSplit) if inputLen == 2 || inputLen == 3 { if id, err := uuid.Parse(inputSplit[inputLen-1]); err == nil { @@ -143,7 +145,7 @@ func deviceGetCompletion(c *promptCompleter, d prompt.Document, inputSplit []str } c.yangSchemaCompleterMap[id] = completer.NewYangSchemaCompleter(schemaTree["Device"], true) if yc, ok := c.yangSchemaCompleterMap[id]; ok { - c.deviceId = id + c.deviceID = id return yc.Complete(d) } @@ -153,7 +155,7 @@ func deviceGetCompletion(c *promptCompleter, d prompt.Document, inputSplit []str return prompt.FilterHasPrefix(getDevices(), d.GetWordBeforeCursor(), true) } } else { - if yc, ok := c.yangSchemaCompleterMap[c.deviceId]; ok { + if yc, ok := c.yangSchemaCompleterMap[c.deviceID]; ok { return yc.Complete(d) } return []prompt.Suggest{} @@ -177,10 +179,9 @@ func cobraCommandCompletion(currCmd *cobra.Command, d prompt.Document, loaded [] suggestions = append(suggestions, prompt.Suggest{Text: cmd.Name(), Description: cmd.Short}) } return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true) - } -func completionBasedOnCmd(c *promptCompleter, cmd *cobra.Command, inputSplit []string, d prompt.Document) []prompt.Suggest { +func completionBasedOnCmd(c *PromptCompleter, cmd *cobra.Command, inputSplit []string, d prompt.Document) []prompt.Suggest { switch cmd { case pndUseCmd, pndGetCmd: return cobraCommandCompletion(cmd, d, getPnds()) diff --git a/cli/completer/utils.go b/cli/completer/utils.go index ab0f7affa82c659623b89209e2dccc9738396c9f..ab58c30fcf9c33ba2a1ccffbd20fe28bfb58904a 100644 --- a/cli/completer/utils.go +++ b/cli/completer/utils.go @@ -6,6 +6,8 @@ import ( "github.com/c-bata/go-prompt" ) +// SortSuggestionByText sorts the suggestion slice, otherwise the order of the slice will be +// random. func SortSuggestionByText(suggestions []prompt.Suggest) []prompt.Suggest { // sort the suggestion slice, otherwise the order of the slice will be // random. diff --git a/cli/completer/yangSchemaCompleter.go b/cli/completer/yangSchemaCompleter.go index a40cbeab77c1dcbacf4ec2603448557e58852a09..392f17e68783b23de0897c5d74d8500fa9fe4993 100644 --- a/cli/completer/yangSchemaCompleter.go +++ b/cli/completer/yangSchemaCompleter.go @@ -12,13 +12,14 @@ import ( ) var ( + // YangSchemaCompletionSeperator is the seperator for yang schemas YangSchemaCompletionSeperator = string([]byte{' ', '/'}) ) // The idea of path suggestions for a SBI's YANG schema is heavily inspired by // gnmic (https://github.com/karimra/gnmic) -// YgotSchemaPathCompleter +// YangSchemaCompleter represtents the YangSchemaCompleter type YangSchemaCompleter struct { Cache map[string]*yang.Entry Entry *yang.Entry @@ -105,6 +106,7 @@ func promptFromYangEntry(e *yang.Entry) []prompt.Suggest { return []prompt.Suggest{} } +// Complete provides the actual completion func (c *YangSchemaCompleter) Complete(d prompt.Document) []prompt.Suggest { p := d.GetWordBeforeCursor() diff --git a/controller/Makefile b/controller/Makefile index dd0c17b7b4d9d78137faa3365578e3c5ef5f3ddb..1c6cc52a9fee363afbe97b28655a49b2ee42eb8d 100644 --- a/controller/Makefile +++ b/controller/Makefile @@ -15,7 +15,7 @@ install-tools: @echo Install development tooling mkdir -p $(GOSDN_PRG) go install gotest.tools/gotestsum@v1.7.0 - go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42 + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.1 @echo Finished installing development tooling ci-install-tools: diff --git a/controller/api/grpc.go b/controller/api/grpc.go index 26b9dddc042cfcfd1f69b82fcc4c6859708d4b37..f416a259773eac0dc8b0a289713db006793ca7d6 100644 --- a/controller/api/grpc.go +++ b/controller/api/grpc.go @@ -59,6 +59,7 @@ func GetIds(addr string) ([]*ppb.PrincipalNetworkDomain, error) { return resp.Pnd, nil } +// GetAllCore requests all PNDs func GetAllCore(ctx context.Context, addr string) (*pb.GetPndListResponse, error) { coreClient, err := nbi.CoreClient(addr, dialOptions...) if err != nil { @@ -211,6 +212,7 @@ func Confirm(addr, pnd string, cuids ...string) (*ppb.SetChangeListResponse, err return CommitConfirm(addr, pnd, changes) } +// CommitConfirm confirms a commit func CommitConfirm(addr, pnd string, changes []*ppb.SetChange) (*ppb.SetChangeListResponse, error) { ctx := context.Background() client, err := nbi.PndClient(addr, dialOptions...) @@ -280,7 +282,7 @@ func GetDevice(addr, pid string, did ...string) (*ppb.GetOndResponse, error) { return pndClient.GetOnd(ctx, req) } -// GetSbiSchemaTree +// GetSbiSchemaTree gets the sbi tree for a sbi func GetSbiSchemaTree(addr string, pid, sid uuid.UUID) (map[string]*yang.Entry, error) { sbiClient, err := nbi.SbiClient(addr, dialOptions...) if err != nil { @@ -339,6 +341,7 @@ func GetDevices(addr, pid string) (*ppb.GetOndListResponse, error) { return pndClient.GetOndList(ctx, req) } +// GetPath requests a specific path func GetPath(addr, pid, did, path string) (*ppb.GetPathResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { @@ -355,6 +358,7 @@ func GetPath(addr, pid, did, path string) (*ppb.GetPathResponse, error) { return pndClient.GetPath(ctx, req) } +// DeleteDevice deletes a device func DeleteDevice(addr, pid, did string) (*ppb.DeleteOndResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { @@ -370,7 +374,7 @@ func DeleteDevice(addr, pid, did string) (*ppb.DeleteOndResponse, error) { return pndClient.DeleteOnd(ctx, req) } -// change creates a ChangeRequest for the specified OND. ApiOperations are +// ChangeRequest change creates a ChangeRequest for the specified OND. ApiOperations are // used to specify the type of the change (update, replace, delete as specified // in https://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi-specification.md#34-modifying-state) // For delete operations the value field needs to contain an empty string. @@ -384,6 +388,7 @@ func ChangeRequest(addr, did, pid, path, value string, op ppb.ApiOperation) (*pp return SendChangeRequest(addr, pid, req) } +// SendChangeRequest sends a change request func SendChangeRequest(addr, pid string, req *ppb.ChangeRequest) (*ppb.SetPathListResponse, error) { pndClient, err := nbi.PndClient(addr, dialOptions...) if err != nil { diff --git a/controller/nucleus/principalNetworkDomain.go b/controller/nucleus/principalNetworkDomain.go index a4dbf0354200e9b4d2b12fd908d04284b26f1e64..716617f40af3dbff573704a57b0a10f698b81fa2 100644 --- a/controller/nucleus/principalNetworkDomain.go +++ b/controller/nucleus/principalNetworkDomain.go @@ -603,7 +603,7 @@ func (pnd *pndImplementation) requestPlugin(name string, opt *tpb.TransportOptio return sbi, nil } - return nil, fmt.Errorf("requestPlugin: received deployment slice was empty.") + return nil, fmt.Errorf("requestPlugin: received deployment slice was empty") } // GenericGrpcClient allows to distinguish between the different ygot diff --git a/controller/nucleus/southbound.go b/controller/nucleus/southbound.go index e9892a48109a37576e3be3a22010f57b10e923d4..abad487bb5c47b1fda418dde38d49c9743ee7ff6 100644 --- a/controller/nucleus/southbound.go +++ b/controller/nucleus/southbound.go @@ -95,7 +95,7 @@ func (oc *OpenConfig) Schema() *ytypes.Schema { return schema } -// SchemaTree returns the ygot generated SchemaTree compressed as gzip byte +// SchemaTreeGzip returns the ygot generated SchemaTree compressed as gzip byte // slice. func (oc *OpenConfig) SchemaTreeGzip() []byte { return openconfig.SchemaTreeGzip() diff --git a/csbi/cmd/root.go b/csbi/cmd/root.go index 939eb25ced0bb2667c8d77137d4542b27f7a0520..75eef6f39a737ff615850c5eea5e73ca79e6870a 100644 --- a/csbi/cmd/root.go +++ b/csbi/cmd/root.go @@ -77,7 +77,6 @@ func init() { rootCmd.PersistentFlags().StringVar(&accessToken, "access-token", "", "access token for private repositories") rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "", "log level 'debug' or 'trace'") rootCmd.PersistentFlags().StringVar(&repoBasePath, "repository-base-path", "./models", "path to the repository base path (default is ./models)") - } // initConfig reads in config file and ENV variables if set. diff --git a/csbi/run.go b/csbi/run.go index 96373dd0218260a11c8580a230dea5c86749ecf2..469899836c0d998b37cd14a739888127c89ff6bf 100644 --- a/csbi/run.go +++ b/csbi/run.go @@ -64,5 +64,4 @@ func Run(bindAddr string) { o.Shutdown(ctx) }() - } diff --git a/csbi/write.go b/csbi/write.go index 7168431ff88e7decb4d751eed5759b0b8212db5a..b53e6dbb2baa547c1ed83694235b9e2625e1ac42 100644 --- a/csbi/write.go +++ b/csbi/write.go @@ -165,6 +165,7 @@ func writeCode(path string, code *ygen.GeneratedGoCode, t spb.Type) error { return nil } +// Manifest represents a csbi manifest type Manifest struct { Name, Author, Version string }