Skip to content

Commit 95d6c06

Browse files
authored
Merge pull request #1963 from rackerlabs/feat/ironic-hardware-exporter-states
feat(ironic): Add node state metrics from versioned notifications
2 parents 4318eef + 3ab4a72 commit 95d6c06

41 files changed

Lines changed: 2690 additions & 309 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
name: build-ironic-hardware-exporter-images
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
version:
8+
description: 'Release version (X.Y.Z, without the v prefix)'
9+
required: true
10+
type: string
11+
push:
12+
tags:
13+
- "ironic-hardware-exporter/v*"
14+
paths:
15+
- "go/ironic-hardware-exporter/**"
16+
17+
jobs:
18+
build-ironic-hardware-exporter:
19+
runs-on: ubuntu-latest
20+
permissions:
21+
packages: write
22+
contents: write
23+
id-token: write
24+
outputs:
25+
version: ${{ steps.extract_tag.outputs.tag }}
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
29+
with:
30+
fetch-depth: 0
31+
32+
- name: Install Go
33+
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
34+
with:
35+
go-version: '1.25'
36+
cache: true
37+
cache-dependency-path: 'go/ironic-hardware-exporter/go.sum'
38+
39+
- name: Install syft
40+
uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0.23.1
41+
42+
- name: Install Cosign
43+
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
44+
45+
- name: Set up QEMU
46+
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4
47+
48+
- name: Set up Docker Buildx
49+
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
50+
51+
- name: Login to ghcr.io
52+
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
53+
with:
54+
registry: "ghcr.io"
55+
username: ${{ github.actor }}
56+
password: ${{ secrets.GITHUB_TOKEN }}
57+
58+
- name: Validate tag format
59+
if: github.event_name != 'workflow_dispatch'
60+
run: |
61+
if [[ ! "$GITHUB_REF" =~ ^refs/tags/ironic-hardware-exporter/v[0-9]+\.[0-9]+\.[0-9]+ ]]; then
62+
echo "Invalid tag: $GITHUB_REF — expected refs/tags/ironic-hardware-exporter/vX.Y.Z"
63+
exit 1
64+
fi
65+
66+
- name: Validate version input
67+
if: github.event_name == 'workflow_dispatch'
68+
run: |
69+
if [[ ! "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
70+
echo "Invalid version: ${{ inputs.version }} — expected X.Y.Z"
71+
exit 1
72+
fi
73+
74+
- name: Extract release version
75+
id: extract_tag
76+
run: |
77+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
78+
echo "tag=${{ inputs.version }}" >> $GITHUB_OUTPUT
79+
else
80+
echo "tag=${GITHUB_REF_NAME#ironic-hardware-exporter/v}" >> $GITHUB_OUTPUT
81+
fi
82+
83+
- name: Run GoReleaser
84+
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6
85+
with:
86+
distribution: goreleaser
87+
version: "~> v2"
88+
args: release --clean --skip=validate
89+
workdir: go/ironic-hardware-exporter
90+
env:
91+
GIT_REPO: ${{ github.repository }}
92+
RELEASE_VERSION: ${{ steps.extract_tag.outputs.tag }}
93+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
94+
95+
chart:
96+
runs-on: ubuntu-latest
97+
needs:
98+
- build-ironic-hardware-exporter
99+
steps:
100+
- name: Checkout repository
101+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
102+
- name: Log in to ghcr.io
103+
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4
104+
with:
105+
registry: ghcr.io
106+
username: '${{ github.actor }}'
107+
password: '${{ secrets.GITHUB_TOKEN }}'
108+
- name: Package and push Helm chart
109+
working-directory: go/ironic-hardware-exporter
110+
env:
111+
PKG_VER: '${{ needs.build-ironic-hardware-exporter.outputs.version }}'
112+
run: |
113+
yq -i ".version = \"${PKG_VER}\"" helm/Chart.yaml
114+
yq -i ".appVersion = \"${PKG_VER}\"" helm/Chart.yaml
115+
yq helm/Chart.yaml
116+
helm package -u -d ${{ github.workspace }} helm
117+
helm push ${{ github.workspace }}/ironic-hardware-exporter-${PKG_VER}.tgz \
118+
oci://ghcr.io/${GITHUB_REPOSITORY_OWNER}/charts
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# compiled binary
2+
/ironic-hardware-exporter
3+
bin/
4+
dist/
5+
6+
# test output
7+
*.test
8+
*.out
9+
10+
# local dev harness
11+
local/
12+
13+
# docs
14+
*.md
15+
ARCHITECTURE.md
16+
17+
# editor and IDE
18+
.idea/
19+
.vscode/
20+
*.swp
21+
*.swo
22+
*~
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# compiled binary
2+
/ironic-hardware-exporter
3+
4+
# test and coverage output
5+
*.test
6+
*.out
7+
cover.out
8+
9+
# build artifacts
10+
bin/
11+
dist/
12+
13+
# Go workspace
14+
go.work
15+
vendor/
16+
17+
# editor and IDE
18+
.idea/
19+
.vscode/
20+
*.swp
21+
*.swo
22+
*~
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM gcr.io/distroless/base-debian12:nonroot
2+
COPY --chmod=555 ironic-hardware-exporter /usr/local/bin/ironic-hardware-exporter
3+
USER 65532:65532
4+
ENTRYPOINT ["/usr/local/bin/ironic-hardware-exporter"]
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
project_name: "ironic-hardware-exporter"
2+
version: 2
3+
4+
before:
5+
hooks:
6+
- go mod tidy
7+
8+
env:
9+
- RELEASE_VERSION={{ .Env.RELEASE_VERSION }}
10+
- GIT_REPO={{ .Env.GIT_REPO }}
11+
12+
release:
13+
name_template: "ironic-hardware-exporter v{{ .Env.RELEASE_VERSION }}"
14+
15+
builds:
16+
- main: main.go
17+
dir: ./cmd
18+
binary: ironic-hardware-exporter
19+
goos: ["linux"]
20+
goarch: ["amd64", "arm64"]
21+
flags:
22+
- -trimpath
23+
ldflags:
24+
- -s
25+
- -w
26+
- -X main.version={{.Version}}
27+
- -X main.commit={{.ShortCommit}}
28+
env:
29+
- CGO_ENABLED=0
30+
31+
changelog:
32+
disable: true
33+
34+
dockers:
35+
- skip_push: false
36+
use: buildx
37+
dockerfile: .goreleaser.Dockerfile
38+
image_templates:
39+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-amd64
40+
build_flag_templates:
41+
- --platform=linux/amd64
42+
- --label=org.opencontainers.image.version={{ .Env.RELEASE_VERSION }}
43+
- --label=org.opencontainers.image.revision={{ .Commit }}
44+
- --label=org.opencontainers.image.title={{ .ProjectName }}
45+
- --label=org.opencontainers.image.created={{ .Date }}
46+
- --label=org.opencontainers.image.description=Prometheus exporter for Ironic bare-metal hardware metrics
47+
- --label=org.opencontainers.image.vendor=rackspace
48+
- --label=org.opencontainers.image.licenses=Apache License 2.0
49+
- --label=org.opencontainers.image.source=https://rackspace.com/
50+
- --label=org.opencontainers.image.authors=Rackspace
51+
- skip_push: false
52+
goarch: arm64
53+
use: buildx
54+
dockerfile: .goreleaser.Dockerfile
55+
image_templates:
56+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-arm64
57+
build_flag_templates:
58+
- --platform=linux/arm64
59+
- --label=org.opencontainers.image.version={{ .Env.RELEASE_VERSION }}
60+
- --label=org.opencontainers.image.revision={{ .Commit }}
61+
- --label=org.opencontainers.image.title={{ .ProjectName }}
62+
- --label=org.opencontainers.image.created={{ .Date }}
63+
- --label=org.opencontainers.image.description=Prometheus exporter for Ironic bare-metal hardware metrics
64+
- --label=org.opencontainers.image.vendor=rackspace
65+
- --label=org.opencontainers.image.licenses=Apache License 2.0
66+
- --label=org.opencontainers.image.source=https://rackspace.com/
67+
- --label=org.opencontainers.image.authors=Rackspace
68+
69+
docker_manifests:
70+
- name_template: ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}
71+
image_templates:
72+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-amd64
73+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-arm64
74+
- name_template: ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:latest
75+
image_templates:
76+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-amd64
77+
- ghcr.io/{{ .Env.GIT_REPO }}/{{ .ProjectName }}:{{ .Env.RELEASE_VERSION }}-arm64
78+
79+
signs:
80+
- cmd: cosign
81+
signature: "${artifact}.sigstore.json"
82+
output: true
83+
artifacts: checksum
84+
args:
85+
- sign-blob
86+
- "--bundle=${signature}"
87+
- "${artifact}"
88+
- --yes
89+
90+
docker_signs:
91+
- cmd: cosign
92+
artifacts: manifests
93+
output: true
94+
args:
95+
- "sign"
96+
- "--oidc-provider=github-actions"
97+
- "${artifact}@${digest}"
98+
- --yes
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM golang:1.25 AS builder
2+
ARG TARGETOS
3+
ARG TARGETARCH
4+
5+
WORKDIR /workspace
6+
COPY go.mod go.mod
7+
COPY go.sum go.sum
8+
RUN go mod download
9+
10+
COPY cmd/ cmd/
11+
COPY internal/ internal/
12+
13+
# the GOARCH has not a default value to allow the binary be built according to the host where the command
14+
# was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO
15+
# the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore,
16+
# by leaving it empty we can ensure that the container and binary shipped on it will have the same platform.
17+
RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o ironic-hardware-exporter cmd/main.go
18+
19+
FROM gcr.io/distroless/static:nonroot
20+
WORKDIR /
21+
COPY --from=builder /workspace/ironic-hardware-exporter .
22+
USER 65532:65532
23+
24+
ENTRYPOINT ["/ironic-hardware-exporter"]
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
BINARY := ironic-hardware-exporter
2+
CMD := ./cmd
3+
IMG ?= ironic-hardware-exporter:dev
4+
5+
CONTAINER_TOOL ?= docker
6+
GOLANGCI_LINT ?= golangci-lint
7+
8+
.PHONY: all
9+
all: build
10+
11+
.PHONY: help
12+
help: ## Display this help.
13+
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
14+
15+
##@ Development
16+
17+
.PHONY: fmt
18+
fmt: ## Run go fmt against code.
19+
go fmt ./...
20+
21+
.PHONY: vet
22+
vet: ## Run go vet against code.
23+
go vet ./...
24+
25+
.PHONY: test
26+
test: fmt vet ## Run tests.
27+
GOCACHE=/tmp/gocache go test ./...
28+
29+
.PHONY: test-race
30+
test-race: ## Run tests with the race detector.
31+
go test -race ./...
32+
33+
.PHONY: lint
34+
lint: ## Run golangci-lint.
35+
$(GOLANGCI_LINT) run ./...
36+
37+
.PHONY: lint-fix
38+
lint-fix: ## Run golangci-lint and apply fixes.
39+
$(GOLANGCI_LINT) run --fix ./...
40+
41+
##@ Build
42+
43+
.PHONY: build
44+
build: fmt vet ## Build the binary.
45+
go build -o $(BINARY) $(CMD)
46+
47+
.PHONY: run
48+
run: fmt vet ## Run the service locally (requires RABBITMQ_PASSWORD).
49+
go run $(CMD)/main.go
50+
51+
.PHONY: docker-build
52+
docker-build: ## Build the container image.
53+
$(CONTAINER_TOOL) build -t $(IMG) .
54+
55+
.PHONY: docker-push
56+
docker-push: ## Push the container image.
57+
$(CONTAINER_TOOL) push $(IMG)

0 commit comments

Comments
 (0)