Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e31c57
docs: fix scan help string
davidallendj Sep 24, 2025
e778637
docs: added initial set up man pages
davidallendj Sep 24, 2025
4daf414
docs: updated all man pages content and format
davidallendj Sep 25, 2025
b010482
docs: updated all man pages content and format again
davidallendj Sep 25, 2025
97d80ef
docs: fixed syntax formatting for scdoc
davidallendj Sep 26, 2025
9290aaa
refactor: minor changes and fixes
davidallendj Sep 29, 2025
a1a3c90
refactor: added String function to RemoteAsset
davidallendj Sep 29, 2025
c6ac106
chore(man): remove trailing spaces
synackd Sep 29, 2025
4941df4
docs(man): fix scdoc compilation errors
synackd Sep 29, 2025
68b1e1f
docs(man): add .gitignore
synackd Sep 29, 2025
9be903e
docs(man): fix formatting
synackd Sep 29, 2025
740b863
build(Makefile): refactor and add man page targets
synackd Sep 29, 2025
531ad19
docs(man): fix formatting (part 2)
synackd Sep 29, 2025
afca8b5
docs: correct variable for magellen-collect man page
davidallendj Sep 29, 2025
49a78c5
refactor: changed interface{} to any
davidallendj Sep 29, 2025
96f15b8
refactor: address comments in pull request
davidallendj Sep 30, 2025
96795e6
refactor: changed how scan args are printed
davidallendj Sep 30, 2025
31853e8
refactor: removed unused code in cmd/scan
davidallendj Sep 30, 2025
9781a24
refactor: corrected scan params host field
davidallendj Sep 30, 2025
8a96a6d
docs: added deprecation warning message
davidallendj Sep 30, 2025
3b63eaf
docs: added complete description to --insecure flag
davidallendj Sep 30, 2025
267e511
fix: issue with scan not writing to cache db
davidallendj Sep 30, 2025
39b70f9
fix: issue with list not printing output
davidallendj Sep 30, 2025
bad6462
refactor: changed verbose to use zerolog instead
davidallendj Sep 30, 2025
03f091d
docs: updated the example config file
davidallendj Sep 30, 2025
2387f21
docs: updated example in secrets man page
davidallendj Sep 30, 2025
76998ca
docs: updated main man page
davidallendj Sep 30, 2025
3b9208c
docs: further addressed PR comments
davidallendj Oct 1, 2025
54e9b7c
docs: fixed comment in main man page
davidallendj Oct 1, 2025
d9698d0
docs(man): magellan.1: fix newlines and REFERENCES case
synackd Oct 1, 2025
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
280 changes: 203 additions & 77 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,122 +1,248 @@
# 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)
#
# COMMAND CONFIGURATION
#

# Paths to commands
GO ?= $(shell command -v go 2>/dev/null)
GIT ?= $(shell command -v git 2>/dev/null)
# Use HOSTCMD to not conflict with Make's $(HOSTNAME)
HOSTCMD ?= $(shell command -v hostname 2>/dev/null)
INSTALL ?= $(shell command -v install 2>/dev/null)
SCDOC ?= $(shell command -v scdoc 2>/dev/null)
CONTAINER ?= $(shell command -v docker 2>/dev/null)
CONTAINER_ARGS ?= ''
SHELL ?= /bin/sh

# `install` command invocations
INSTALL_PROGRAM ?= $(INSTALL) -Dm755
INSTALL_DATA ?= $(INSTALL) -Dm644

# Check that commands are present
ifeq ($(GIT),)
$(error git command not found.)
endif

ifndef VERSION
$(error VERSION is not set. Please review and copy config.env.default to config.env and try again)
ifeq ($(HOSTCMD),)
$(error hostname command not found.)
endif

ifndef BUILD
$(error BUILD is not set. Please review and copy config.env.default to config.env and try again)
ifeq ($(SHELL),)
$(error '$(SHELL)' undefined.)
endif

LDFLAGS="-s -X=$(GIT)main.commit=$(BUILD) -X=$(GIT)main.version=$(VERSION) -X=$(GIT)main.date=$(shell date +%Y-%m-%d:%H:%M:%S)"
#
# FUNCTIONS
#

SHELL := /bin/bash
GOPATH ?= $(shell echo $${GOPATH:-~/go})
# Recursive wildcard function, obtained from https://stackoverflow.com/a/18258352
#
# Arg 1: Space-separated list of directories to recurse into
# Arg 2: Space-separated list of patterns to match
rwildcard = $(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))

.DEFAULT_GOAL := all
# Print currently running target
define print-target
@printf "Executing target: \033[36m$@\033[0m\n"
endef

#
# BUILD CONFIGURATION
#

NAME ?= magellan
VERSION ?= $(shell git describe --tags --always --dirty --broken --abbrev=0)
BUILD ?= $(shell git rev-parse --short HEAD)
GOPATH ?= $(shell echo $${GOPATH:-~/go})
IMPORT := github.com/OpenCHAMI/magellan/
LDFLAGS := -s \
-X='$(IMPORT)main.commit=$(BUILD)' \
-X='$(IMPORT)main.version=$(VERSION)' \
-X='$(IMPORT)main.date=$(shell date -Iseconds)'
INTERNAL := $(call rwildcard,internal,*.go)
PKG := $(call rwildcard,pkg,*.go)
MANSRC := $(wildcard man/*.sc)
MANBIN := $(subst .sc,,$(MANSRC))
MAN1BIN := $(filter %.1,$(MANBIN))

# Installation paths
prefix ?= /usr/local
exec_prefix ?= $(prefix)
bindir ?= $(exec_prefix)/bin
mandir ?= $(exec_prefix)/man

#
# TARGETS
#

# Default target
.PHONY: all
all: ## build pipeline
all: mod inst build lint test
all: binaries

# Build all program binaries
.PHONY: binaries
binaries: $(NAME)

# CI build pipeline
.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}'

# Remove files created during build pipeline
.PHONY: clean
clean: ## remove files created during build pipeline
clean:
$(call print-target)
ifeq ($(GO),)
$(error go command not found.)
endif
rm -rf dist
rm -f coverage.*
rm -f '"$(shell go env GOCACHE)/../golangci-lint"'
go clean -i -cache -testcache -modcache -fuzzcache -x
$(GO) clean -i -x

# Separate clean target for go modules, cache, etc.
#
# The user may not want their Go module cache cleaned by default, so a separate
# target is provided to do so.
.PHONY: clean-go
clean-go:
$(call print-target)
ifeq ($(GO),)
$(error go command not found.)
endif
$(GO) clean -i -cache -testcache -modcache -fuzzcache -x

.PHONY: mod
mod: ## go mod tidy
.PHONY: clean-man
clean-man:
$(call print-target)
go mod tidy
rm -f $(MANBIN)

.PHONY: inst
inst: ## go install tools
# Build container
.PHONY: container
container:
$(call print-target)
go install github.com/client9/misspell/cmd/misspell@v0.3.4
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.1
go install github.com/goreleaser/goreleaser/v2@v2.3.2
go install github.com/cpuguy83/go-md2man/v2@latest
$(CONTAINER) build . --build-arg REGISTRY_HOST=${REGISTRY_HOST} --no-cache --pull --tag '${NAME}:${VERSION}'

.PHONY: release
release: ## goreleaser build
.PHONY: diff
diff:
$(call print-target)
ifeq ($(GIT),)
$(error git command not found.)
endif
$(GIT) diff --exit-code
RES=$$($(GIT) status --porcelain) ; if [ -n "$$RES" ]; then echo $$RES && exit 1 ; fi

.PHONY: distclean
distclean: clean clean-man

# Generate docs from Go comments
.PHONY: docs
docs:
$(call print-target)
ifeq ($(GO),)
$(error go command not found.)
endif
$(GO) doc github.com/OpenCHAMI/magellan/cmd
$(GO) doc github.com/OpenCHAMI/magellan/internal
$(GO) doc github.com/OpenCHAMI/magellan/pkg/crawler

# Run Redfish emulator
.PHONY: emulator
emulator:
$(call print-target)
./emulator/setup.sh

# Build using Goreleaser
.PHONY: goreleaser
goreleaser:
$(call print-target)
$(GOPATH)/bin/goreleaser build --clean --single-target --snapshot

.PHONY: binaries
binaries: build
.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: build
build: ## go build
go build -v --tags=all -ldflags=$(LDFLAGS) -o $(NAME) main.go
.PHONY: install
install: install-prog install-man

.PHONY: docker
container: ## docker build
container:
.PHONY: install-prog
install-prog: $(NAME)
$(call print-target)
docker build . --build-arg REGISTRY_HOST=${REGISTRY_HOST} --no-cache --pull --tag '${NAME}:${VERSION}'
ifeq ($(INSTALL),)
$(error install command not found.)
endif
$(INSTALL_PROGRAM) $(NAME) $(DESTDIR)$(bindir)/$(NAME)

.PHONY: spell
spell: ## misspell
.PHONY: install-man
install-man: $(MANBIN)
$(call print-target)
$(GOPATH)/bin/misspell -error -locale=US -w **.md
ifeq ($(INSTALL),)
$(error install command not found.)
endif
mkdir -p $(DESTDIR)$(mandir)/man1
$(INSTALL_DATA) $(MAN1BIN) $(DESTDIR)$(mandir)/man1/

# Run golangci-lint to lint Go code
.PHONY: lint
lint: ## golangci-lint
lint:
$(call print-target)
$(GOPATH)/bin/golangci-lint run --fix

.PHONY: test
test: ## go test
.PHONY: man
man: $(MANBIN)

man/%: man/%.sc
ifeq ($(SCDOC),)
$(error scdoc command not found.)
endif
$(SCDOC) < $< > $@

# Download/Prune Go modules
.PHONY: mod
mod:
$(call print-target)
./emulator/setup.sh &
sleep 10
go test -race -covermode=atomic -coverprofile=coverage.out -coverpkg=./... tests/api_test.go tests/compatibility_test.go
go tool cover -html=coverage.out -o coverage.html
go mod tidy

.PHONY: diff
diff: ## git diff
# Prepare by installing necessary Go tools
.PHONY: prepare
prepare:
$(call print-target)
git diff --exit-code
RES=$$(git status --porcelain) ; if [ -n "$$RES" ]; then echo $$RES && exit 1 ; fi
ifeq ($(GO),)
$(error go command not found.)
endif
$(GO) install github.com/client9/misspell/cmd/misspell@v0.3.4
$(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.1
$(GO) install github.com/goreleaser/goreleaser/v2@v2.3.2

.PHONY: docs
docs: ## go docs
# Spellchecking
.PHONY: spell
spell:
$(call print-target)
go doc github.com/OpenCHAMI/magellan/cmd
go doc github.com/OpenCHAMI/magellan/internal
go doc github.com/OpenCHAMI/magellan/pkg/crawler
$(GOPATH)/bin/misspell -error -locale=US -w **.md

.PHONY: emulator
emulator:
# Run Go tests
.PHONY: test
test:
$(call print-target)
./emulator/setup.sh
ifeq ($(GO),)
$(error go command not found.)
endif
./emulator/setup.sh &
sleep 10
$(GO) test -race -covermode=atomic -coverprofile=coverage.out -coverpkg=./... tests/api_test.go tests/compatibility_test.go
$(GO) tool cover -html=coverage.out -o coverage.html

magellan.1: README.md inst
$(GOPATH)/bin/go-md2man -in $< -out $@
.PHONY: uninstall
uninstall: uninstall-prog uninstall-man

.PHONY: man
man:
.PHONY: uninstall-prog
uninstall-prog:
$(call print-target)
$(MAKE) -f $(firstword $(MAKEFILE_LIST)) magellan.1
rm -f $(DESTDIR)$(bindir)/$(NAME)

define print-target
@printf "Executing target: \033[36m$@\033[0m\n"
endef
.PHONY: uninstall-man
uninstall-man:
$(call print-target)
rm -f $(foreach man1page,$(subst man/,,$(MAN1BIN)),$(DESTDIR)$(mandir)/man1/$(man1page))

$(NAME): *.go cmd/*.go $(INTERNAL) $(PKG)
ifeq ($(GO),)
$(error go command not found.)
endif
$(GO) build -v -ldflags="$(LDFLAGS)"
4 changes: 2 additions & 2 deletions cmd/collect.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,12 @@ func init() {
CollectCmd.Flags().StringVarP(&password, "password", "p", "", "Set the master BMC password")
CollectCmd.Flags().StringVar(&secretsFile, "secrets-file", "", "Set path to the node secrets file")
CollectCmd.Flags().StringVar(&protocol, "protocol", "tcp", "Set the protocol used to query")
CollectCmd.Flags().StringVarP(&outputPath, "output-file", "o", "", "Set the path to store collection data using HIVE partitioning")
CollectCmd.Flags().StringVarP(&outputPath, "output-file", "o", "", "Set the path to store collection data in a single file")
CollectCmd.Flags().StringVarP(&outputDir, "output-dir", "O", "", "Set the path to store collection data using HIVE partitioning")
CollectCmd.Flags().BoolVar(&showOutput, "show", false, "Show the output of a collect run")
CollectCmd.Flags().BoolVar(&forceUpdate, "force-update", false, "Set flag to force update data sent to SMD")
CollectCmd.Flags().StringVar(&cacertPath, "cacert", "", "Set the path to CA cert file (defaults to system CAs when blank)")
CollectCmd.Flags().VarP(&collectOutputFormat, "format", "F", "Set the default output data format (json|yaml) can be overridden by file extensions")
CollectCmd.Flags().VarP(&collectOutputFormat, "format", "F", "Set the default output data format (json|yaml; can be overridden by file extensions)")
CollectCmd.Flags().StringVarP(&idMap, "bmc-id-map", "m", "", "Set the BMC ID mapping from raw json data or use @<path> to specify a file path (json or yaml input)")

CollectCmd.MarkFlagsMutuallyExclusive("output-file", "output-dir")
Expand Down
2 changes: 1 addition & 1 deletion cmd/crawl.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func init() {
CrawlCmd.Flags().StringVarP(&password, "password", "p", "", "Set the password for the BMC")
CrawlCmd.Flags().BoolVarP(&insecure, "insecure", "i", false, "Ignore SSL errors")
CrawlCmd.Flags().StringVarP(&secretsFile, "secrets-file", "f", "secrets.json", "Set path to the node secrets file")
CrawlCmd.Flags().BoolVar(&showOutput, "show", false, "Show the output of a collect run")
CrawlCmd.Flags().BoolVar(&showOutput, "show", false, "Show the output of a crawl")
CrawlCmd.Flags().VarP(&crawlOutputFormat, "format", "F", "Set the output format (json|yaml)")

checkRegisterFlagCompletionError(CrawlCmd.RegisterFlagCompletionFunc("format", completionFormatData))
Expand Down
30 changes: 23 additions & 7 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,38 @@ var ListCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
// check if we just want to show cache-related info and exit
if showCache {
fmt.Printf("cache: %s\n", cachePath)
log.Info().Str("cache", cachePath).Send()
return
}

// load the assets found from scan
scannedResults, err := sqlite.GetScannedAssets(cachePath)
if err != nil {
log.Error().Err(err).Msg("failed to get scanned assets")
log.Error().Err(err).Str("path", cachePath).Msg("failed to get scanned assets")
}

output, err := format.MarshalData(scannedResults, listOutputFormat)
if err != nil {
log.Error().Err(err).Msg("failed to marshal data")
return
switch listOutputFormat {
case format.FORMAT_JSON, format.FORMAT_YAML:
output, err := format.MarshalData(scannedResults, listOutputFormat)
if err != nil {
log.Error().Err(err).Msg("failed to marshal data")
return
}
fmt.Print(string(output))
case format.FORMAT_LIST:
fallthrough
default:
var output string
for _, scanned := range scannedResults {
output += fmt.Sprintf("%s %s %v %s\n",
scanned.Host,
scanned.Protocol,
scanned.Timestamp,
scanned.ServiceType,
)
}
fmt.Print(output)
}
log.Printf(string(output))
},
}

Expand Down
Loading
Loading