From 3351de48a619946fe29363c8e6e323ac4fe259b0 Mon Sep 17 00:00:00 2001 From: Alex Lovell-Troy Date: Thu, 14 Sep 2023 15:10:08 -0400 Subject: [PATCH] inital release refactor --- .goreleaser.yaml | 40 +++++++++++++++++ Makefile | 87 ++++++++++++++++++++++++++++++++++++ cmd/collect.go | 27 ++++++----- cmd/list.go | 8 ++-- cmd/scan.go | 5 ++- config.env | 5 +++ go.mod | 8 ++-- internal/api/dora/dora.go | 31 ++++++------- internal/api/smd/smd.go | 12 ++--- internal/collect.go | 69 ++++++++++++++-------------- internal/db/sqlite/sqlite.go | 4 +- main.go | 3 +- 12 files changed, 215 insertions(+), 84 deletions(-) create mode 100644 .goreleaser.yaml create mode 100644 Makefile create mode 100644 config.env diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..91e3cbf --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,40 @@ +before: + hooks: + - go mod download +builds: + - env: + - CGO_ENABLED=0 + goos: + - darwin + - linux + - windows + goarch: + - amd64 +archives: + - format_overrides: + - goos: windows + format: zip +dockers: + - image_templates: + - "bikeshack.azurecr.io/magellan:latest" + - "bikeshack.azurecr.io/magellan:{{ .Major }}" + - "bikeshack.azurecr.io/magellan:{{ .Major }}.{{ .Minor }}" + - "bikeshack.azurecr.io/magellan:{{ .Major }}.{{ .Minor }}.{{ .Patch }}" + dockerfile: goreleaser.Dockerfile + build_flag_templates: + - "--pull" + - "--no-cache" + - "--build-arg=REGISTRY_HOST=docker.io/library/" + # OCI annotations: https://github.com/opencontainers/image-spec/blob/main/annotations.md + - "--label=org.opencontainers.image.created={{.Date}}" + - "--label=org.opencontainers.image.name={{.ProjectName}}" + - "--label=org.opencontainers.image.revision={{.FullCommit}}" + - "--label=org.opencontainers.image.version={{.Version}}" + - "--label=org.opencontainers.image.source={{.GitURL}}" +release: + github: + name_template: "{{.Version}}" + prerelease: auto + mode: append +changelog: + skip: true diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dda9c30 --- /dev/null +++ b/Makefile @@ -0,0 +1,87 @@ +# import config. +# You can change the default config with `make cnf="config_special.env" build` +cnf ?= config.env +include $(cnf) +export $(shell sed 's/=.*//' $(cnf)) + +ifndef NAME +$(error NAME is not set. Please review and copy config.env.default to config.env and try again) +endif + +ifndef VERSION +$(error VERSION is not set. Please review and copy config.env.default to config.env and try again) +endif + +SHELL := /bin/bash + +.DEFAULT_GOAL := all +.PHONY: all +all: ## build pipeline +all: mod inst build spell lint test + +.PHONY: ci +ci: ## CI build pipeline +ci: all diff + +.PHONY: help +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: clean +clean: ## remove files created during build pipeline + $(call print-target) + rm -rf dist + rm -f coverage.* + rm -f '"$(shell go env GOCACHE)/../golangci-lint"' + go clean -i -cache -testcache -modcache -fuzzcache -x + +.PHONY: mod +mod: ## go mod tidy + $(call print-target) + go mod tidy + +.PHONY: inst +inst: ## go install tools + $(call print-target) + go install github.com/client9/misspell/cmd/misspell@v0.3.4 + go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2 + go install github.com/goreleaser/goreleaser@v1.18.2 + +.PHONY: build +build: ## goreleaser build +build: + $(call print-target) + goreleaser build --clean --single-target --snapshot + +.PHONY: docker +docker: ## docker build +docker: + $(call print-target) + docker build . --build-arg REGISTRY_HOST=${REGISTRY_HOST} --no-cache --pull --tag '${NAME}:${VERSION}' + +.PHONY: spell +spell: ## misspell + $(call print-target) + misspell -error -locale=US -w **.md + +.PHONY: lint +lint: ## golangci-lint + $(call print-target) + golangci-lint run --fix + +.PHONY: test +test: ## go test + $(call print-target) + go test -race -covermode=atomic -coverprofile=coverage.out -coverpkg=./... ./... + go tool cover -html=coverage.out -o coverage.html + +.PHONY: diff +diff: ## git diff + $(call print-target) + git diff --exit-code + RES=$$(git status --porcelain) ; if [ -n "$$RES" ]; then echo $$RES && exit 1 ; fi + + +define print-target + @printf "Executing target: \033[36m$@\033[0m\n" +endef diff --git a/cmd/collect.go b/cmd/collect.go index 185aa14..3994bb0 100644 --- a/cmd/collect.go +++ b/cmd/collect.go @@ -1,18 +1,17 @@ package cmd import ( - magellan "davidallendj/magellan/internal" - "davidallendj/magellan/internal/api/smd" - "davidallendj/magellan/internal/db/sqlite" + magellan "github.com/bikeshack/magellan/internal" + "github.com/bikeshack/magellan/internal/api/smd" + "github.com/bikeshack/magellan/internal/db/sqlite" "github.com/cznic/mathutil" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) - var collectCmd = &cobra.Command{ - Use: "collect", + Use: "collect", Short: "Query information about BMC", Run: func(cmd *cobra.Command, args []string) { // make application logger @@ -28,13 +27,13 @@ var collectCmd = &cobra.Command{ threads = mathutil.Clamp(len(probeStates), 1, 255) } q := &magellan.QueryParams{ - User: user, - Pass: pass, - Drivers: drivers, - Timeout: timeout, - Threads: threads, - Verbose: verbose, - WithSecureTLS: withSecureTLS, + User: user, + Pass: pass, + Drivers: drivers, + Timeout: timeout, + Threads: threads, + Verbose: verbose, + WithSecureTLS: withSecureTLS, } magellan.CollectInfo(&probeStates, l, q) @@ -46,7 +45,7 @@ var collectCmd = &cobra.Command{ }, } -func init(){ +func init() { collectCmd.PersistentFlags().StringSliceVar(&drivers, "driver", []string{"redfish"}, "set the driver(s) and fallback drivers to use") collectCmd.PersistentFlags().StringVar(&smd.Host, "host", smd.Host, "set the host to the smd API") collectCmd.PersistentFlags().IntVar(&smd.Port, "port", smd.Port, "set the port to the smd API") @@ -58,4 +57,4 @@ func init(){ collectCmd.PersistentFlags().BoolVar(&withSecureTLS, "secure-tls", false, "enable secure TLS") collectCmd.PersistentFlags().StringVar(&certPoolFile, "cert-pool", "", "path to CA cert. (defaults to system CAs; used with --secure-tls=true)") rootCmd.AddCommand(collectCmd) -} \ No newline at end of file +} diff --git a/cmd/list.go b/cmd/list.go index fa69c41..3e344a0 100644 --- a/cmd/list.go +++ b/cmd/list.go @@ -1,16 +1,16 @@ package cmd import ( - "davidallendj/magellan/internal/db/sqlite" "fmt" + "github.com/bikeshack/magellan/internal/db/sqlite" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) - var listCmd = &cobra.Command{ - Use: "list", + Use: "list", Short: "List information from scan", Run: func(cmd *cobra.Command, args []string) { probeResults, err := sqlite.GetProbeResults(dbpath) @@ -25,4 +25,4 @@ var listCmd = &cobra.Command{ func init() { rootCmd.AddCommand(listCmd) -} \ No newline at end of file +} diff --git a/cmd/scan.go b/cmd/scan.go index a5b1a37..8f7f4cf 100644 --- a/cmd/scan.go +++ b/cmd/scan.go @@ -1,10 +1,11 @@ package cmd import ( - magellan "davidallendj/magellan/internal" - "davidallendj/magellan/internal/db/sqlite" "fmt" + magellan "github.com/bikeshack/magellan/internal" + "github.com/bikeshack/magellan/internal/db/sqlite" + "github.com/cznic/mathutil" "github.com/spf13/cobra" ) diff --git a/config.env b/config.env new file mode 100644 index 0000000..e92c519 --- /dev/null +++ b/config.env @@ -0,0 +1,5 @@ +## This configuration is used by the Makefile + +NAME=magellan +VERSION=$(shell git describe --tags --abbrev=0) + diff --git a/go.mod b/go.mod index 482dcf6..11f71c8 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,9 @@ -module davidallendj/magellan +module github.com/bikeshack/magellan go 1.20 -replace github.com/bmc-toolbox/dora => ../../dora - require ( + github.com/Cray-HPE/hms-xname v1.3.0 github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230714152943-a1b87e2ff47f github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 github.com/jacobweinstock/registrar v0.4.7 @@ -13,10 +12,10 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.7.0 github.com/stmcginnis/gofish v0.14.0 + golang.org/x/exp v0.0.0-20230127130021-4ca2cb1a16b7 ) require ( - github.com/Cray-HPE/hms-xname v1.3.0 // indirect github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 // indirect github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 // indirect github.com/bmc-toolbox/common v0.0.0-20230717121556-5eb9915a8a5a // indirect @@ -31,7 +30,6 @@ require ( github.com/satori/go.uuid v1.2.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/testify v1.8.3 // indirect - golang.org/x/exp v0.0.0-20230127130021-4ca2cb1a16b7 // indirect golang.org/x/net v0.14.0 // indirect golang.org/x/sys v0.11.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/internal/api/dora/dora.go b/internal/api/dora/dora.go index b3f2dbd..0e87a92 100644 --- a/internal/api/dora/dora.go +++ b/internal/api/dora/dora.go @@ -1,31 +1,32 @@ package dora import ( - "davidallendj/magellan/internal/api" "encoding/json" "fmt" + "github.com/bikeshack/magellan/internal/api" + "github.com/jmoiron/sqlx" ) const ( - Host = "http://localhost" - DbType = "sqlite3" - DbPath = "../data/assets.db" + Host = "http://localhost" + DbType = "sqlite3" + DbPath = "../data/assets.db" BaseEndpoint = "/v1" - Port = 8000 + Port = 8000 ) type ScannedResult struct { - id string - site any - cidr string - ip string - port int + id string + site any + cidr string + ip string + port int protocol string - scanner string - state string - updated string + scanner string + state string + updated string } func makeEndpointUrl(endpoint string) string { @@ -67,8 +68,8 @@ func LoadScannedPortsFromDB(dbPath string, dbType string) { for rows.Next() { var r ScannedResult rows.Scan( - &r.id, &r.site, &r.cidr, &r.ip, &r.port, &r.protocol, &r.scanner, + &r.id, &r.site, &r.cidr, &r.ip, &r.port, &r.protocol, &r.scanner, &r.state, &r.updated, ) } -} \ No newline at end of file +} diff --git a/internal/api/smd/smd.go b/internal/api/smd/smd.go index 492375d..726df8d 100644 --- a/internal/api/smd/smd.go +++ b/internal/api/smd/smd.go @@ -4,18 +4,18 @@ package smd // https://github.com/Cray-HPE/hms-smd/blob/master/docs/examples.adoc // https://github.com/alexlovelltroy/hms-smd import ( - "davidallendj/magellan/internal/api" "fmt" + + "github.com/bikeshack/magellan/internal/api" // hms "github.com/alexlovelltroy/hms-smd" ) var ( - Host = "http://localhost" + Host = "http://localhost" BaseEndpoint = "/hsm/v2" - Port = 27779 + Port = 27779 ) - func makeEndpointUrl(endpoint string) string { return Host + ":" + fmt.Sprint(Port) + BaseEndpoint + endpoint } @@ -49,7 +49,7 @@ func AddRedfishEndpoint(data []byte, headers map[string]string) error { // var ep hms.RedfishEP // _ = ep - // Add redfish endpoint via POST `/hsm/v2/Inventory/RedfishEndpoints` endpoint + // Add redfish endpoint via POST `/hsm/v2/Inventory/RedfishEndpoints` endpoint url := makeEndpointUrl("/Inventory/RedfishEndpoints") res, body, _ := api.MakeRequest(url, "POST", data, headers) fmt.Println("smd url: ", url) @@ -60,4 +60,4 @@ func AddRedfishEndpoint(data []byte, headers map[string]string) error { func UpdateRedfishEndpoint() { // Update redfish endpoint via PUT `/hsm/v2/Inventory/RedfishEndpoints` endpoint -} \ No newline at end of file +} diff --git a/internal/collect.go b/internal/collect.go index 896bd28..f6b7a1e 100644 --- a/internal/collect.go +++ b/internal/collect.go @@ -3,13 +3,14 @@ package magellan import ( "context" "crypto/x509" - "davidallendj/magellan/internal/api/smd" "encoding/json" "fmt" "os" "sync" "time" + "github.com/bikeshack/magellan/internal/api/smd" + "github.com/Cray-HPE/hms-xname/xnames" bmclib "github.com/bmc-toolbox/bmclib/v2" "github.com/jacobweinstock/registrar" @@ -42,13 +43,13 @@ type QueryParams struct { User string Pass string Drivers []string - Threads int - Preferred string + Threads int + Preferred string Timeout int WithSecureTLS bool CertPoolFile string Verbose bool - IpmitoolPath string + IpmitoolPath string } func NewClient(l *Logger, q *QueryParams) (*bmclib.Client, error) { @@ -120,18 +121,18 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error if len(*probeStates) <= 0 { return fmt.Errorf("no probe states found") } - + // generate custom xnames for bmcs node := xnames.Node{ - Cabinet: 1000, - Chassis: 1, - ComputeModule: 7, - NodeBMC: -1, + Cabinet: 1000, + Chassis: 1, + ComputeModule: 7, + NodeBMC: -1, } - found := make([]string, 0, len(*probeStates)) - done := make(chan struct{}, q.Threads+1) - chanProbeState := make(chan BMCProbeResult, q.Threads+1) + found := make([]string, 0, len(*probeStates)) + done := make(chan struct{}, q.Threads+1) + chanProbeState := make(chan BMCProbeResult, q.Threads+1) // collect bmc information asynchronously var wg sync.WaitGroup @@ -139,7 +140,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error for i := 0; i < q.Threads; i++ { go func() { for { - ps, ok := <- chanProbeState + ps, ok := <-chanProbeState if !ok { wg.Done() return @@ -152,7 +153,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error client, err := NewClient(l, q) if err != nil { l.Log.Errorf("could not make client: %v", err) - continue + continue } // metadata @@ -164,7 +165,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error // inventories inventory, err := QueryInventory(client, l, q) if err != nil { - l.Log.Errorf("could not query inventory: %v", err) + l.Log.Errorf("could not query inventory: %v", err) continue } @@ -181,13 +182,13 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error headers["Content-Type"] = "application/json" data := make(map[string]any) - data["ID"] = fmt.Sprintf("%v", node.String()[:len(node.String())-2]) - data["Type"] = "" - data["Name"] = "" - data["FQDN"] = ps.Host - data["RediscoverOnUpdate"] = false - data["Inventory"] = inventory - data["Chassis"] = chassis + data["ID"] = fmt.Sprintf("%v", node.String()[:len(node.String())-2]) + data["Type"] = "" + data["Name"] = "" + data["FQDN"] = ps.Host + data["RediscoverOnUpdate"] = false + data["Inventory"] = inventory + data["Chassis"] = chassis b, err := json.MarshalIndent(data, "", " ") if err != nil { @@ -228,7 +229,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error for _, ps := range *probeStates { // skip if found info from host foundHost := slices.Index(found, ps.Host) - if !ps.State || foundHost >= 0{ + if !ps.State || foundHost >= 0 { continue } chanProbeState <- ps @@ -394,11 +395,11 @@ func QueryBios(client *bmclib.Client, l *Logger, q *QueryParams) ([]byte, error) func QueryEthernetInterfaces(client *bmclib.Client, l *Logger, q *QueryParams) ([]byte, error) { config := gofish.ClientConfig{ - Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), - Username: q.User, - Password: q.Pass, - Insecure: !q.WithSecureTLS, - TLSHandshakeTimeout: q.Timeout, + Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), + Username: q.User, + Password: q.Pass, + Insecure: !q.WithSecureTLS, + TLSHandshakeTimeout: q.Timeout, } c, err := gofish.Connect(config) if err != nil { @@ -418,12 +419,12 @@ func QueryEthernetInterfaces(client *bmclib.Client, l *Logger, q *QueryParams) ( } func QueryChassis(q *QueryParams) ([]byte, error) { - config := gofish.ClientConfig { - Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), - Username: q.User, - Password: q.Pass, - Insecure: !q.WithSecureTLS, - TLSHandshakeTimeout: q.Timeout, + config := gofish.ClientConfig{ + Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), + Username: q.User, + Password: q.Pass, + Insecure: !q.WithSecureTLS, + TLSHandshakeTimeout: q.Timeout, } c, err := gofish.Connect(config) if err != nil { diff --git a/internal/db/sqlite/sqlite.go b/internal/db/sqlite/sqlite.go index d7c3aeb..39ff33b 100644 --- a/internal/db/sqlite/sqlite.go +++ b/internal/db/sqlite/sqlite.go @@ -3,7 +3,7 @@ package sqlite import ( "fmt" - magellan "davidallendj/magellan/internal" + magellan "github.com/bikeshack/magellan/internal" "github.com/jmoiron/sqlx" ) @@ -58,4 +58,4 @@ func GetProbeResults(path string) ([]magellan.BMCProbeResult, error) { return nil, fmt.Errorf("could not retrieve probes: %v", err) } return results, nil -} \ No newline at end of file +} diff --git a/main.go b/main.go index 03429dc..2cfda3a 100644 --- a/main.go +++ b/main.go @@ -1,8 +1,7 @@ package main import ( - "davidallendj/magellan/cmd" - // smd "github.com/alexlovelltroy/hms-smd/pkg/redfish" + "github.com/bikeshack/magellan/cmd" ) func main() {