diff --git a/.github/workflows/fmtcheck.yml b/.github/workflows/fmtcheck.yml new file mode 100644 index 00000000..623863a9 --- /dev/null +++ b/.github/workflows/fmtcheck.yml @@ -0,0 +1,30 @@ +name: fmtcheck + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + +jobs: + fmtcheck: + runs-on: ubuntu-latest + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: 1.19 + - name: check fmt + run: 'bash -c "diff -u <(echo -n) <(gofmt -d .)"' diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml deleted file mode 100644 index a300b4ee..00000000 --- a/.github/workflows/go.yml +++ /dev/null @@ -1,159 +0,0 @@ -name: CI tests - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -# see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners -jobs: - # tier 0: system-independent checks - format: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: set up golang - uses: actions/setup-go@v2 - with: - go-version: 1.19 - - - name: format - run: ./hack/check-format.sh - - lint: - runs-on: ubuntu-latest - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Verify - uses: golangci/golangci-lint-action@v2 - with: - version: v1.41.1 - args: --timeout=15m0s --verbose - - # tier-1 - # main development platform, gets features first and it's most tested - build-ubuntu-2204: - runs-on: ubuntu-22.04 - strategy: - matrix: - go: [ '1.19', '1.20'] - steps: - - uses: actions/checkout@v2 - - - name: set up go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: run unit-tests - env: - GHW_TESTING_SKIP_BLOCK: "1" - GHW_TESTING_SKIP_GPU: "1" - run: go test -v ./... - - build-ubuntu-2004: - runs-on: ubuntu-20.04 - strategy: - matrix: - go: [ '1.18', '1.19'] - steps: - - uses: actions/checkout@v2 - - - name: set up go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: run unit-tests - env: - GHW_TESTING_SKIP_BLOCK: "1" - GHW_TESTING_SKIP_GPU: "1" - run: go test -v ./... - - build-windows-2022: - runs-on: windows-2022 - strategy: - matrix: - go: [ '1.19' ] - steps: - - uses: actions/checkout@v2 - - - name: set up go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: run unit-tests - env: - GHW_TESTING_SKIP_BLOCK: "1" - GHW_TESTING_SKIP_GPU: "1" - GHW_TESTING_SKIP_CPU: "1" - GHW_TESTING_SKIP_MEMORY: "1" - GHW_TESTING_SKIP_HOST: "1" - GHW_TESTING_SKIP_NET: "1" - GHW_TESTING_SKIP_PCI: "1" - GHW_TESTING_SKIP_TOPOLOGY: "1" - run: go test -v ./... - - build-windows-2019: - runs-on: windows-2019 - strategy: - matrix: - go: [ '1.18' ] - steps: - - uses: actions/checkout@v2 - - - name: set up go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: run unit-tests - env: - GHW_TESTING_SKIP_BLOCK: "1" - GHW_TESTING_SKIP_CPU: "1" - GHW_TESTING_SKIP_GPU: "1" - GHW_TESTING_SKIP_HOST: "1" - GHW_TESTING_SKIP_MEMORY: "1" - GHW_TESTING_SKIP_NET: "1" - GHW_TESTING_SKIP_PCI: "1" - GHW_TESTING_SKIP_TOPOLOGY: "1" - run: go test -v ./... - - # tier-2 - # best-effort support, limited to most recent platforms (OS+go) - - # NOTE(jaypipes): We currently only support block information on MacOS, and - # the tests have block skipped because we cannot get meaningful information - # about the block devices in the Github Actions Runner virtual machines. So - # this is really just a test of whether the library builds on MacOS 12. - build-macos-12: - runs-on: macos-12 - strategy: - matrix: - go: [ '1.18' ] - steps: - - uses: actions/checkout@v2 - - - name: set up go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: run unit-tests - env: - GHW_TESTING_SKIP_BLOCK: "1" - GHW_TESTING_SKIP_CPU: "1" - GHW_TESTING_SKIP_GPU: "1" - GHW_TESTING_SKIP_HOST: "1" - GHW_TESTING_SKIP_MEMORY: "1" - GHW_TESTING_SKIP_NET: "1" - GHW_TESTING_SKIP_PCI: "1" - GHW_TESTING_SKIP_TOPOLOGY: "1" - run: go test -v ./... diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..e8488e9a --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,38 @@ +name: lint + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + pull-requests: read # needed for only-new-issues option below + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + api.github.com:443 + raw.githubusercontent.com:443 + objects.githubusercontent.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: 1.19 + - name: lint + uses: golangci/golangci-lint-action@639cd343e1d3b897ff35927a75193d57cfcba299 # v3.6.0 + with: + version: v1.53 + args: --timeout=5m0s --verbose + only-new-issues: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..977703ea --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,164 @@ +name: test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +permissions: + contents: read + +# see: https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners +jobs: + # tier-1 + # main development platform, gets features first and it's most tested + ubuntu-latest: + runs-on: ubuntu-latest + strategy: + matrix: + go: [ '1.19', '1.20'] + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: ${{ matrix.go }} + - name: run tests + env: + GHW_TESTING_SKIP_BLOCK: "1" + GHW_TESTING_SKIP_GPU: "1" + run: go test -v ./... + + ubuntu-2004: + runs-on: ubuntu-20.04 + strategy: + matrix: + go: [ '1.18', '1.19'] + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: ${{ matrix.go }} + - name: run tests + env: + GHW_TESTING_SKIP_BLOCK: "1" + GHW_TESTING_SKIP_GPU: "1" + run: go test -v ./... + + windows-2022: + runs-on: windows-2022 + strategy: + matrix: + go: [ '1.19' ] + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: ${{ matrix.go }} + - name: run tests + env: + GHW_TESTING_SKIP_BLOCK: "1" + GHW_TESTING_SKIP_GPU: "1" + GHW_TESTING_SKIP_CPU: "1" + GHW_TESTING_SKIP_MEMORY: "1" + GHW_TESTING_SKIP_HOST: "1" + GHW_TESTING_SKIP_NET: "1" + GHW_TESTING_SKIP_PCI: "1" + GHW_TESTING_SKIP_TOPOLOGY: "1" + run: go test -v ./... + + windows-2019: + runs-on: windows-2019 + strategy: + matrix: + go: [ '1.18' ] + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: ${{ matrix.go }} + - name: run tests + env: + GHW_TESTING_SKIP_BLOCK: "1" + GHW_TESTING_SKIP_GPU: "1" + GHW_TESTING_SKIP_CPU: "1" + GHW_TESTING_SKIP_MEMORY: "1" + GHW_TESTING_SKIP_HOST: "1" + GHW_TESTING_SKIP_NET: "1" + GHW_TESTING_SKIP_PCI: "1" + GHW_TESTING_SKIP_TOPOLOGY: "1" + run: go test -v ./... + + # tier-2 + # best-effort support, limited to most recent platforms (OS+go) + + # NOTE(jaypipes): We currently only support block information on MacOS, and + # the tests have block skipped because we cannot get meaningful information + # about the block devices in the Github Actions Runner virtual machines. So + # this is really just a test of whether the library builds on MacOS 12. + macos-12: + runs-on: macos-12 + strategy: + matrix: + go: [ '1.18' ] + steps: + - name: harden runner + uses: step-security/harden-runner@55d479fb1c5bcad5a4f9099a5d9f37c8857b2845 # v2.4.1 + with: + egress-policy: block + disable-sudo: true + allowed-endpoints: > + github.com:443 + - name: checkout code + uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - name: setup go + uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + with: + go-version: ${{ matrix.go }} + - name: run tests + env: + GHW_TESTING_SKIP_BLOCK: "1" + GHW_TESTING_SKIP_CPU: "1" + GHW_TESTING_SKIP_GPU: "1" + GHW_TESTING_SKIP_HOST: "1" + GHW_TESTING_SKIP_MEMORY: "1" + GHW_TESTING_SKIP_NET: "1" + GHW_TESTING_SKIP_PCI: "1" + GHW_TESTING_SKIP_TOPOLOGY: "1" + run: go test -v ./... diff --git a/Dockerfile b/Dockerfile index cbd587d6..c81352b3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,6 @@ -FROM golang:1.15-buster as builder +FROM golang:1.19-buster as builder WORKDIR /go/src/github.com/jaypipes/ghw -# Force the go compiler to use modules. -ENV GO111MODULE=on ENV GOPROXY=direct # go.mod and go.sum go into their own layers. @@ -16,7 +14,7 @@ COPY . . RUN CGO_ENABLED=0 go build -o ghwc ./cmd/ghwc/ -FROM alpine:3.7 +FROM alpine:3.7@sha256:8421d9a84432575381bfabd248f1eb56f3aa21d9d7cd2511583c68c9b7511d10 RUN apk add --no-cache ethtool WORKDIR /bin diff --git a/Makefile b/Makefile index c7e0db40..75d2bcc8 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,16 @@ -VENDOR := vendor -PKGS := $(shell go list ./... | grep -v /$(VENDOR)/) -SRC = $(shell find . -type f -name '*.go' -not -path "*/$(VENDOR)/*") -BIN_DIR := $(GOPATH)/bin -GOMETALINTER := $(BIN_DIR)/gometalinter - .PHONY: test test: vet - go test $(PKGS) - -$(GOMETALINTER): - go get -u github.com/alecthomas/gometalinter - $(GOMETALINTER) --install &> /dev/null - -.PHONY: lint -lint: $(GOMETALINTER) - $(GOMETALINTER) ./... --vendor + go test -v ./... .PHONY: fmt fmt: @echo "Running gofmt on all sources..." - @gofmt -s -l -w $(SRC) + @gofmt -s -l -w . .PHONY: fmtcheck fmtcheck: - @bash -c "diff -u <(echo -n) <(gofmt -d $(SRC))" + @bash -c "diff -u <(echo -n) <(gofmt -d .)" .PHONY: vet vet: - go vet $(PKGS) - -.PHONY: cover -cover: - $(shell [ -e coverage.out ] && rm coverage.out) - @echo "mode: count" > coverage-all.out - $(foreach pkg,$(PKGS),\ - go test -coverprofile=coverage.out -covermode=count $(pkg);\ - tail -n +2 coverage.out >> coverage-all.out;) - go tool cover -html=coverage-all.out -o=coverage-all.html + go vet ./... diff --git a/README.md b/README.md index 8fc5ccb9..4c64dca0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Go Reference](https://pkg.go.dev/badge/github.com/jaypipes/ghw.svg)](https://pkg.go.dev/github.com/jaypipes/ghw) [![Go Report Card](https://goreportcard.com/badge/github.com/jaypipes/ghw)](https://goreportcard.com/report/github.com/jaypipes/ghw) -[![Build Status](https://github.com/jaypipes/ghw/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/jaypipes/ghw/actions) +[![Build Status](https://github.com/jaypipes/ghw/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/jaypipes/ghw/actions) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md) ![ghw mascot](images/ghw-gopher.png) diff --git a/doc.go b/doc.go index 6722cda7..826ed7b3 100644 --- a/doc.go +++ b/doc.go @@ -5,310 +5,10 @@ // /* -package ghw can determine various hardware-related -information about the host computer: +package ghw discovers hardware-related information about the host computer, +including CPU, memory, block storage, NUMA topology, network devices, PCI, GPU, +and baseboard/BIOS/chassis/product information. -* Memory -* CPU -* Block storage -* Topology -* Network -* PCI -* GPU - -# Memory - -Information about the host computer's memory can be retrieved using the -Memory function which returns a pointer to a MemoryInfo struct. - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - memory, err := ghw.Memory() - if err != nil { - fmt.Printf("Error getting memory info: %v", err) - } - - fmt.Println(memory.String()) - } - -# CPU - -The CPU function returns a CPUInfo struct that contains information about -the CPUs on the host system. - - package main - - import ( - "fmt" - "math" - "strings" - - "github.com/jaypipes/ghw" - ) - - func main() { - cpu, err := ghw.CPU() - if err != nil { - fmt.Printf("Error getting CPU info: %v", err) - } - - fmt.Printf("%v\n", cpu) - - for _, proc := range cpu.Processors { - fmt.Printf(" %v\n", proc) - for _, core := range proc.Cores { - fmt.Printf(" %v\n", core) - } - if len(proc.Capabilities) > 0 { - // pretty-print the (large) block of capability strings into rows - // of 6 capability strings - rows := int(math.Ceil(float64(len(proc.Capabilities)) / float64(6))) - for row := 1; row < rows; row = row + 1 { - rowStart := (row * 6) - 1 - rowEnd := int(math.Min(float64(rowStart+6), float64(len(proc.Capabilities)))) - rowElems := proc.Capabilities[rowStart:rowEnd] - capStr := strings.Join(rowElems, " ") - if row == 1 { - fmt.Printf(" capabilities: [%s\n", capStr) - } else if rowEnd < len(proc.Capabilities) { - fmt.Printf(" %s\n", capStr) - } else { - fmt.Printf(" %s]\n", capStr) - } - } - } - } - } - -# Block storage - -Information about the host computer's local block storage is returned from -the Block function. This function returns a pointer to a BlockInfo struct. - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - block, err := ghw.Block() - if err != nil { - fmt.Printf("Error getting block storage info: %v", err) - } - - fmt.Printf("%v\n", block) - - for _, disk := range block.Disks { - fmt.Printf(" %v\n", disk) - for _, part := range disk.Partitions { - fmt.Printf(" %v\n", part) - } - } - } - -# Topology - -Information about the host computer's architecture (NUMA vs. SMP), the -host's node layout and processor caches can be retrieved from the Topology -function. This function returns a pointer to a TopologyInfo struct. - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - topology, err := ghw.Topology() - if err != nil { - fmt.Printf("Error getting topology info: %v", err) - } - - fmt.Printf("%v\n", topology) - - for _, node := range topology.Nodes { - fmt.Printf(" %v\n", node) - for _, cache := range node.Caches { - fmt.Printf(" %v\n", cache) - } - } - } - -# Network - -Information about the host computer's networking hardware is returned from -the Network function. This function returns a pointer to a NetworkInfo -struct. - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - net, err := ghw.Network() - if err != nil { - fmt.Printf("Error getting network info: %v", err) - } - - fmt.Printf("%v\n", net) - - for _, nic := range net.NICs { - fmt.Printf(" %v\n", nic) - - enabledCaps := make([]int, 0) - for x, cap := range nic.Capabilities { - if cap.IsEnabled { - enabledCaps = append(enabledCaps, x) - } - } - if len(enabledCaps) > 0 { - fmt.Printf(" enabled capabilities:\n") - for _, x := range enabledCaps { - fmt.Printf(" - %s\n", nic.Capabilities[x].Name) - } - } - } - } - -# PCI - -ghw contains a PCI database inspection and querying facility that allows -developers to not only gather information about devices on a local PCI bus -but also query for information about hardware device classes, vendor and -product information. - -**NOTE**: Parsing of the PCI-IDS file database is provided by the separate -http://github.com/jaypipes/pcidb library. You can read that library's -README for more information about the various structs that are exposed on -the PCIInfo struct. - -PCIInfo.ListDevices is used to iterate over a host's PCI devices: - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - pci, err := ghw.PCI() - if err != nil { - fmt.Printf("Error getting PCI info: %v", err) - } - fmt.Printf("host PCI devices:\n") - fmt.Println("====================================================") - devices := pci.ListDevices() - if len(devices) == 0 { - fmt.Printf("error: could not retrieve PCI devices\n") - return - } - - for _, device := range devices { - vendor := device.Vendor - vendorName := vendor.Name - if len(vendor.Name) > 20 { - vendorName = string([]byte(vendorName)[0:17]) + "..." - } - product := device.Product - productName := product.Name - if len(product.Name) > 40 { - productName = string([]byte(productName)[0:37]) + "..." - } - fmt.Printf("%-12s\t%-20s\t%-40s\n", device.Address, vendorName, productName) - } - } - -The following code snippet shows how to call the PCIInfo.GetDevice method -and use its returned PCIDevice struct pointer: - - package main - - import ( - "fmt" - "os" - - "github.com/jaypipes/ghw" - ) - - func main() { - pci, err := ghw.PCI() - if err != nil { - fmt.Printf("Error getting PCI info: %v", err) - } - - addr := "0000:00:00.0" - if len(os.Args) == 2 { - addr = os.Args[1] - } - fmt.Printf("PCI device information for %s\n", addr) - fmt.Println("====================================================") - deviceInfo := pci.GetDevice(addr) - if deviceInfo == nil { - fmt.Printf("could not retrieve PCI device information for %s\n", addr) - return - } - - vendor := deviceInfo.Vendor - fmt.Printf("Vendor: %s [%s]\n", vendor.Name, vendor.ID) - product := deviceInfo.Product - fmt.Printf("Product: %s [%s]\n", product.Name, product.ID) - subsystem := deviceInfo.Subsystem - subvendor := pci.Vendors[subsystem.VendorID] - subvendorName := "UNKNOWN" - if subvendor != nil { - subvendorName = subvendor.Name - } - fmt.Printf("Subsystem: %s [%s] (Subvendor: %s)\n", subsystem.Name, subsystem.ID, subvendorName) - class := deviceInfo.Class - fmt.Printf("Class: %s [%s]\n", class.Name, class.ID) - subclass := deviceInfo.Subclass - fmt.Printf("Subclass: %s [%s]\n", subclass.Name, subclass.ID) - progIface := deviceInfo.ProgrammingInterface - fmt.Printf("Programming Interface: %s [%s]\n", progIface.Name, progIface.ID) - } - -# GPU - -Information about the host computer's graphics hardware is returned from -the GPU function. This function returns a pointer to a GPUInfo struct. - - package main - - import ( - "fmt" - - "github.com/jaypipes/ghw" - ) - - func main() { - gpu, err := ghw.GPU() - if err != nil { - fmt.Printf("Error getting GPU info: %v", err) - } - - fmt.Printf("%v\n", gpu) - - for _, card := range gpu.GraphicsCards { - fmt.Printf(" %v\n", card) - } - } +Please see the extensive README.md document for examples of usage. */ package ghw diff --git a/go.mod b/go.mod index b4074ab7..f315f115 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/jaypipes/ghw -go 1.18 +go 1.19 require ( github.com/StackExchange/wmi v1.2.1 diff --git a/hack/check-format.sh b/hack/check-format.sh deleted file mode 100755 index 42906f0f..00000000 --- a/hack/check-format.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -eu - -DIFF=$( gofmt -s -d . ) -if [ -n "${DIFF}" ]; then - echo "${DIFF}" - exit 1 -fi -exit 0