inital release refactor

This commit is contained in:
Alex Lovell-Troy 2023-09-14 15:10:08 -04:00
parent 34367f830a
commit 3351de48a6
12 changed files with 215 additions and 84 deletions

40
.goreleaser.yaml Normal file
View file

@ -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

87
Makefile Normal file
View file

@ -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

View file

@ -1,18 +1,17 @@
package cmd package cmd
import ( import (
magellan "davidallendj/magellan/internal" magellan "github.com/bikeshack/magellan/internal"
"davidallendj/magellan/internal/api/smd" "github.com/bikeshack/magellan/internal/api/smd"
"davidallendj/magellan/internal/db/sqlite" "github.com/bikeshack/magellan/internal/db/sqlite"
"github.com/cznic/mathutil" "github.com/cznic/mathutil"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var collectCmd = &cobra.Command{ var collectCmd = &cobra.Command{
Use: "collect", Use: "collect",
Short: "Query information about BMC", Short: "Query information about BMC",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// make application logger // make application logger
@ -28,13 +27,13 @@ var collectCmd = &cobra.Command{
threads = mathutil.Clamp(len(probeStates), 1, 255) threads = mathutil.Clamp(len(probeStates), 1, 255)
} }
q := &magellan.QueryParams{ q := &magellan.QueryParams{
User: user, User: user,
Pass: pass, Pass: pass,
Drivers: drivers, Drivers: drivers,
Timeout: timeout, Timeout: timeout,
Threads: threads, Threads: threads,
Verbose: verbose, Verbose: verbose,
WithSecureTLS: withSecureTLS, WithSecureTLS: withSecureTLS,
} }
magellan.CollectInfo(&probeStates, l, q) 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().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().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") collectCmd.PersistentFlags().IntVar(&smd.Port, "port", smd.Port, "set the port to the smd API")

View file

@ -1,16 +1,16 @@
package cmd package cmd
import ( import (
"davidallendj/magellan/internal/db/sqlite"
"fmt" "fmt"
"github.com/bikeshack/magellan/internal/db/sqlite"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var listCmd = &cobra.Command{ var listCmd = &cobra.Command{
Use: "list", Use: "list",
Short: "List information from scan", Short: "List information from scan",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
probeResults, err := sqlite.GetProbeResults(dbpath) probeResults, err := sqlite.GetProbeResults(dbpath)

View file

@ -1,10 +1,11 @@
package cmd package cmd
import ( import (
magellan "davidallendj/magellan/internal"
"davidallendj/magellan/internal/db/sqlite"
"fmt" "fmt"
magellan "github.com/bikeshack/magellan/internal"
"github.com/bikeshack/magellan/internal/db/sqlite"
"github.com/cznic/mathutil" "github.com/cznic/mathutil"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )

5
config.env Normal file
View file

@ -0,0 +1,5 @@
## This configuration is used by the Makefile
NAME=magellan
VERSION=$(shell git describe --tags --abbrev=0)

8
go.mod
View file

@ -1,10 +1,9 @@
module davidallendj/magellan module github.com/bikeshack/magellan
go 1.20 go 1.20
replace github.com/bmc-toolbox/dora => ../../dora
require ( require (
github.com/Cray-HPE/hms-xname v1.3.0
github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230714152943-a1b87e2ff47f github.com/bmc-toolbox/bmclib/v2 v2.0.1-0.20230714152943-a1b87e2ff47f
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548
github.com/jacobweinstock/registrar v0.4.7 github.com/jacobweinstock/registrar v0.4.7
@ -13,10 +12,10 @@ require (
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0 github.com/spf13/cobra v1.7.0
github.com/stmcginnis/gofish v0.14.0 github.com/stmcginnis/gofish v0.14.0
golang.org/x/exp v0.0.0-20230127130021-4ca2cb1a16b7
) )
require ( require (
github.com/Cray-HPE/hms-xname v1.3.0 // indirect
github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 // indirect github.com/VictorLowther/simplexml v0.0.0-20180716164440-0bff93621230 // indirect
github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 // indirect github.com/VictorLowther/soap v0.0.0-20150314151524-8e36fca84b22 // indirect
github.com/bmc-toolbox/common v0.0.0-20230717121556-5eb9915a8a5a // 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/satori/go.uuid v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.3 // 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/net v0.14.0 // indirect
golang.org/x/sys v0.11.0 // indirect golang.org/x/sys v0.11.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect

View file

@ -1,31 +1,32 @@
package dora package dora
import ( import (
"davidallendj/magellan/internal/api"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/bikeshack/magellan/internal/api"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )
const ( const (
Host = "http://localhost" Host = "http://localhost"
DbType = "sqlite3" DbType = "sqlite3"
DbPath = "../data/assets.db" DbPath = "../data/assets.db"
BaseEndpoint = "/v1" BaseEndpoint = "/v1"
Port = 8000 Port = 8000
) )
type ScannedResult struct { type ScannedResult struct {
id string id string
site any site any
cidr string cidr string
ip string ip string
port int port int
protocol string protocol string
scanner string scanner string
state string state string
updated string updated string
} }
func makeEndpointUrl(endpoint string) string { func makeEndpointUrl(endpoint string) string {

View file

@ -4,18 +4,18 @@ package smd
// https://github.com/Cray-HPE/hms-smd/blob/master/docs/examples.adoc // https://github.com/Cray-HPE/hms-smd/blob/master/docs/examples.adoc
// https://github.com/alexlovelltroy/hms-smd // https://github.com/alexlovelltroy/hms-smd
import ( import (
"davidallendj/magellan/internal/api"
"fmt" "fmt"
"github.com/bikeshack/magellan/internal/api"
// hms "github.com/alexlovelltroy/hms-smd" // hms "github.com/alexlovelltroy/hms-smd"
) )
var ( var (
Host = "http://localhost" Host = "http://localhost"
BaseEndpoint = "/hsm/v2" BaseEndpoint = "/hsm/v2"
Port = 27779 Port = 27779
) )
func makeEndpointUrl(endpoint string) string { func makeEndpointUrl(endpoint string) string {
return Host + ":" + fmt.Sprint(Port) + BaseEndpoint + endpoint return Host + ":" + fmt.Sprint(Port) + BaseEndpoint + endpoint
} }

View file

@ -3,13 +3,14 @@ package magellan
import ( import (
"context" "context"
"crypto/x509" "crypto/x509"
"davidallendj/magellan/internal/api/smd"
"encoding/json" "encoding/json"
"fmt" "fmt"
"os" "os"
"sync" "sync"
"time" "time"
"github.com/bikeshack/magellan/internal/api/smd"
"github.com/Cray-HPE/hms-xname/xnames" "github.com/Cray-HPE/hms-xname/xnames"
bmclib "github.com/bmc-toolbox/bmclib/v2" bmclib "github.com/bmc-toolbox/bmclib/v2"
"github.com/jacobweinstock/registrar" "github.com/jacobweinstock/registrar"
@ -42,13 +43,13 @@ type QueryParams struct {
User string User string
Pass string Pass string
Drivers []string Drivers []string
Threads int Threads int
Preferred string Preferred string
Timeout int Timeout int
WithSecureTLS bool WithSecureTLS bool
CertPoolFile string CertPoolFile string
Verbose bool Verbose bool
IpmitoolPath string IpmitoolPath string
} }
func NewClient(l *Logger, q *QueryParams) (*bmclib.Client, error) { func NewClient(l *Logger, q *QueryParams) (*bmclib.Client, error) {
@ -123,15 +124,15 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error
// generate custom xnames for bmcs // generate custom xnames for bmcs
node := xnames.Node{ node := xnames.Node{
Cabinet: 1000, Cabinet: 1000,
Chassis: 1, Chassis: 1,
ComputeModule: 7, ComputeModule: 7,
NodeBMC: -1, NodeBMC: -1,
} }
found := make([]string, 0, len(*probeStates)) found := make([]string, 0, len(*probeStates))
done := make(chan struct{}, q.Threads+1) done := make(chan struct{}, q.Threads+1)
chanProbeState := make(chan BMCProbeResult, q.Threads+1) chanProbeState := make(chan BMCProbeResult, q.Threads+1)
// collect bmc information asynchronously // collect bmc information asynchronously
var wg sync.WaitGroup var wg sync.WaitGroup
@ -139,7 +140,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error
for i := 0; i < q.Threads; i++ { for i := 0; i < q.Threads; i++ {
go func() { go func() {
for { for {
ps, ok := <- chanProbeState ps, ok := <-chanProbeState
if !ok { if !ok {
wg.Done() wg.Done()
return return
@ -181,13 +182,13 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
data := make(map[string]any) data := make(map[string]any)
data["ID"] = fmt.Sprintf("%v", node.String()[:len(node.String())-2]) data["ID"] = fmt.Sprintf("%v", node.String()[:len(node.String())-2])
data["Type"] = "" data["Type"] = ""
data["Name"] = "" data["Name"] = ""
data["FQDN"] = ps.Host data["FQDN"] = ps.Host
data["RediscoverOnUpdate"] = false data["RediscoverOnUpdate"] = false
data["Inventory"] = inventory data["Inventory"] = inventory
data["Chassis"] = chassis data["Chassis"] = chassis
b, err := json.MarshalIndent(data, "", " ") b, err := json.MarshalIndent(data, "", " ")
if err != nil { if err != nil {
@ -228,7 +229,7 @@ func CollectInfo(probeStates *[]BMCProbeResult, l *Logger, q *QueryParams) error
for _, ps := range *probeStates { for _, ps := range *probeStates {
// skip if found info from host // skip if found info from host
foundHost := slices.Index(found, ps.Host) foundHost := slices.Index(found, ps.Host)
if !ps.State || foundHost >= 0{ if !ps.State || foundHost >= 0 {
continue continue
} }
chanProbeState <- ps 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) { func QueryEthernetInterfaces(client *bmclib.Client, l *Logger, q *QueryParams) ([]byte, error) {
config := gofish.ClientConfig{ config := gofish.ClientConfig{
Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port),
Username: q.User, Username: q.User,
Password: q.Pass, Password: q.Pass,
Insecure: !q.WithSecureTLS, Insecure: !q.WithSecureTLS,
TLSHandshakeTimeout: q.Timeout, TLSHandshakeTimeout: q.Timeout,
} }
c, err := gofish.Connect(config) c, err := gofish.Connect(config)
if err != nil { if err != nil {
@ -418,12 +419,12 @@ func QueryEthernetInterfaces(client *bmclib.Client, l *Logger, q *QueryParams) (
} }
func QueryChassis(q *QueryParams) ([]byte, error) { func QueryChassis(q *QueryParams) ([]byte, error) {
config := gofish.ClientConfig { config := gofish.ClientConfig{
Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port), Endpoint: fmt.Sprintf("https://%s:%d", q.Host, q.Port),
Username: q.User, Username: q.User,
Password: q.Pass, Password: q.Pass,
Insecure: !q.WithSecureTLS, Insecure: !q.WithSecureTLS,
TLSHandshakeTimeout: q.Timeout, TLSHandshakeTimeout: q.Timeout,
} }
c, err := gofish.Connect(config) c, err := gofish.Connect(config)
if err != nil { if err != nil {

View file

@ -3,7 +3,7 @@ package sqlite
import ( import (
"fmt" "fmt"
magellan "davidallendj/magellan/internal" magellan "github.com/bikeshack/magellan/internal"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
) )

View file

@ -1,8 +1,7 @@
package main package main
import ( import (
"davidallendj/magellan/cmd" "github.com/bikeshack/magellan/cmd"
// smd "github.com/alexlovelltroy/hms-smd/pkg/redfish"
) )
func main() { func main() {