Skip to content

Commit 90fac60

Browse files
committed
chore: add DOCA driver matrix validation
Signed-off-by: Fred Rolland <[email protected]>
1 parent 74690cd commit 90fac60

File tree

4 files changed

+140
-8
lines changed

4 files changed

+140
-8
lines changed

.github/workflows/checks.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,22 @@ jobs:
7878
uses: actions/checkout@v4
7979
- name: check release-build
8080
run: make check-release-build
81+
check-doca-drivers:
82+
name: check doca-drivers
83+
runs-on: ubuntu-22.04
84+
env:
85+
NGC_CLI_API_KEY: ${{ secrets.NVCR_TOKEN }}
86+
permissions:
87+
contents: read
88+
steps:
89+
- name: Set up Go 1.x
90+
uses: actions/setup-go@v5
91+
with:
92+
go-version: '1.23'
93+
- name: checkout
94+
uses: actions/checkout@v4
95+
- name: check doca-drivers
96+
run: make check-doca-drivers
8197
unit-tests:
8298
name: Unit-tests
8399
runs-on: ubuntu-22.04

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ testbin
3030
test
3131
build
3232
hack/manifests
33+
hack/tmp

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ REPO_PATH=$(ORG_PATH)/$(PACKAGE)
2020
CHART_PATH=$(CURDIR)/deployment/$(PACKAGE)
2121
TOOLSDIR=$(CURDIR)/hack/tools/bin
2222
MANIFESTDIR=$(CURDIR)/hack/manifests
23+
HACKTMPDIR=$(CURDIR)/hack/tmp
2324
BUILDDIR=$(CURDIR)/build/_output
2425
GOFILES=$(shell find . -name "*.go" | grep -vE "(\/vendor\/)|(_test.go)")
2526
TESTPKGS=./...
@@ -37,6 +38,7 @@ BUILD_VERSION := $(strip $(shell [ -d .git ] && git describe --always --tags --d
3738
BUILD_TIMESTAMP := $(shell date -u +"%Y-%m-%dT%H:%M:%S%Z")
3839
VCS_BRANCH := $(strip $(shell git rev-parse --abbrev-ref HEAD))
3940
VCS_REF := $(strip $(shell [ -d .git ] && git rev-parse --short HEAD))
41+
DOCA_DRIVER_RELEASE_URL := https://raw.githubusercontent.com/Mellanox/doca-driver-build/refs/heads/main/release_manifests/
4042

4143
# Docker
4244
IMAGE_BUILDER?=docker
@@ -109,6 +111,9 @@ $(MANIFESTDIR):
109111
$(BUILDDIR): ; $(info Creating build directory...)
110112
mkdir -p $@
111113

114+
$(HACKTMPDIR):
115+
@mkdir -p $@
116+
112117
build: generate $(BUILDDIR)/$(BINARY_NAME) ; $(info Building $(BINARY_NAME)...) @ ## Build executable file
113118
$(info Done!)
114119

@@ -356,6 +361,7 @@ clean: ; $(info Cleaning...) @ ## Cleanup everything
356361
@rm -rf $(BUILDDIR)
357362
@rm -rf $(TOOLSDIR)
358363
@rm -rf $(MANIFESTDIR)
364+
@rm -rf $(HACKTMPDIR)
359365

360366
.PHONY: help
361367
help: ## Show this message
@@ -414,6 +420,12 @@ release-build:
414420
cd hack && $(GO) run release.go --templateDir ./templates/crs/ --outputDir ../example/crs
415421
cd hack && $(GO) run release.go --templateDir ./templates/values/ --outputDir ../deployment/network-operator/
416422

423+
.PHONY: check-doca-drivers
424+
check-doca-drivers: $(HACKTMPDIR)
425+
$(eval DOCAVERSION := $(shell yq '.Mofed.version' hack/release.yaml | cut -d'-' -f1))
426+
wget $(DOCA_DRIVER_RELEASE_URL)$(DOCAVERSION)-TBD.yaml -O $(HACKTMPDIR)/doca-driver-matrix.yaml
427+
cd hack && $(GO) run release.go --doca-driver-check --doca-driver-matrix $(HACKTMPDIR)/doca-driver-matrix.yaml
428+
417429
# dev environment
418430

419431
MINIKUBE_CLUSTER_NAME = net-op-dev

hack/release.go

Lines changed: 111 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import (
3030

3131
"sigs.k8s.io/yaml"
3232

33+
yamlflow "gopkg.in/yaml.v3"
34+
3335
mellanoxv1alpha1 "github.com/Mellanox/network-operator/api/v1alpha1"
3436

3537
"github.com/google/go-containerregistry/pkg/authn"
@@ -80,6 +82,18 @@ type Release struct {
8082
MaintenanceOperator *ReleaseImageSpec
8183
}
8284

85+
type DocaDriverMatrix struct {
86+
Precompiled []struct {
87+
OS string `yaml:"os"`
88+
Arch []string `yaml:"archs,flow"`
89+
Kernels []string `yaml:"kernels,flow"`
90+
} `yaml:"precompiled"`
91+
DynamicallyCompiled []struct {
92+
OS string `yaml:"os,flow"`
93+
Arch []string `yaml:"archs,flow"`
94+
} `yaml:"dynamically_compiled"`
95+
}
96+
8397
func readDefaults(releaseDefaults string) Release {
8498
f, err := os.ReadFile(filepath.Clean(releaseDefaults))
8599
if err != nil {
@@ -136,9 +150,82 @@ func main() {
136150
outputDir := flag.String("outputDir", ".", "Destination directory to render templates to")
137151
releaseDefaults := flag.String("releaseDefaults", "release.yaml", "Destination of the release defaults definition")
138152
retrieveSha := flag.Bool("with-sha256", false, "retrieve SHA256 for container images references")
153+
docaDriverCheck := flag.Bool("doca-driver-check", false, "Verify DOCA Driver tags")
154+
docaDriverMatrix := flag.String("doca-driver-matrix", "tmp/doca-driver-matrix.yaml", "DOCA Driver tags matrix")
139155
flag.Parse()
140156
release := readDefaults(*releaseDefaults)
141157
readEnvironmentVariables(&release)
158+
159+
if !*docaDriverCheck {
160+
renderTemplates(release, templateDir, outputDir, retrieveSha)
161+
} else {
162+
docaDriverTagsCheck(release, docaDriverMatrix)
163+
}
164+
}
165+
166+
func docaDriverTagsCheck(release Release, docaDriverMatrix *string) {
167+
f, err := os.ReadFile(filepath.Clean(*docaDriverMatrix))
168+
if err != nil {
169+
fmt.Printf("Error: %v\n", err)
170+
os.Exit(1)
171+
}
172+
var config DocaDriverMatrix
173+
if err := yamlflow.Unmarshal(f, &config); err != nil {
174+
fmt.Printf("Error: %v\n", err)
175+
os.Exit(1)
176+
}
177+
auth, err := getAuth()
178+
if err != nil {
179+
fmt.Printf("Error: %v\n", err)
180+
os.Exit(1)
181+
}
182+
tags, err := resolveTags(release.Mofed.Repository, release.Mofed.Image, auth)
183+
if err != nil {
184+
fmt.Printf("Error: %v\n", err)
185+
os.Exit(1)
186+
}
187+
if err := validateTags(config, tags, release.Mofed.Version); err != nil {
188+
fmt.Printf("Error: %v\n", err)
189+
os.Exit(1)
190+
}
191+
}
192+
193+
func validateTags(config DocaDriverMatrix, tags []string, version string) error {
194+
// Build expected OS-arch combinations
195+
expectedCombinations := make(map[string]struct{})
196+
for _, entry := range config.DynamicallyCompiled {
197+
for _, arch := range entry.Arch {
198+
key := fmt.Sprintf("%s-%s", entry.OS, arch)
199+
expectedCombinations[key] = struct{}{}
200+
}
201+
}
202+
203+
// Filter tags based on version prefix
204+
filteredTags := []string{}
205+
for _, tag := range tags {
206+
if strings.HasPrefix(tag, version) {
207+
filteredTags = append(filteredTags, tag)
208+
}
209+
}
210+
211+
// Validate if each expected combination exists in the filtered tags
212+
for combo := range expectedCombinations {
213+
found := false
214+
for _, tag := range filteredTags {
215+
if strings.Contains(tag, combo) {
216+
found = true
217+
break
218+
}
219+
}
220+
if !found {
221+
return fmt.Errorf("missing os-arch combination: %s", combo)
222+
}
223+
}
224+
225+
return nil
226+
}
227+
228+
func renderTemplates(release Release, templateDir, outputDir *string, retrieveSha *bool) {
142229
if *retrieveSha {
143230
err := resolveImagesSha(&release)
144231
if err != nil {
@@ -198,15 +285,23 @@ func main() {
198285
}
199286
}
200287

201-
func resolveImagesSha(release *Release) error {
288+
func getAuth() (*authn.Basic, error) {
202289
nvcrToken := os.Getenv("NGC_CLI_API_KEY")
203290
if nvcrToken == "" {
204-
return fmt.Errorf("NGC_CLI_API_KEY is unset")
291+
return nil, fmt.Errorf("NGC_CLI_API_KEY is unset")
205292
}
206293
auth := &authn.Basic{
207294
Username: "$oauthtoken",
208295
Password: nvcrToken,
209296
}
297+
return auth, nil
298+
}
299+
300+
func resolveImagesSha(release *Release) error {
301+
auth, err := getAuth()
302+
if err != nil {
303+
return err
304+
}
210305
v := reflect.ValueOf(*release)
211306
for i := 0; i < v.NumField(); i++ {
212307
field := v.Field(i)
@@ -263,27 +358,35 @@ func resolveImageSha(repo, image, tag string, auth *authn.Basic) (string, error)
263358
return digest.String(), nil
264359
}
265360

266-
func resolveDocaDriversShas(repoName, imageName, ver string, auth *authn.Basic) ([]string, error) {
267-
shaArray := make([]string, 0)
361+
func resolveTags(repoName, imageName string, auth *authn.Basic) ([]string, error) {
362+
tags := make([]string, 0)
268363
image := fmt.Sprintf("%s/%s", repoName, imageName)
269364
repo, err := containerregistryname.NewRepository(image)
270365
if err != nil {
271-
return shaArray, err
366+
return tags, err
272367
}
273-
var tags []string
274368
if strings.Contains(repoName, "nvstaging") {
275369
tags, err = remote.List(repo, remote.WithAuth(auth))
276370
if err != nil {
277-
return shaArray, err
371+
return tags, err
278372
}
279373
} else {
280374
// Container registry might fail if providing unneeded auth
281375
tags, err = remote.List(repo)
282376
if err != nil {
283-
return shaArray, err
377+
return tags, err
284378
}
285379
}
286380
sort.Strings(tags)
381+
return tags, nil
382+
}
383+
384+
func resolveDocaDriversShas(repoName, imageName, ver string, auth *authn.Basic) ([]string, error) {
385+
shaArray := make([]string, 0)
386+
tags, err := resolveTags(repoName, imageName, auth)
387+
if err != nil {
388+
return shaArray, err
389+
}
287390
shaSet := make(map[string]interface{})
288391
for _, tag := range tags {
289392
if strings.Contains(tag, ver) && (strings.Contains(tag, "rhcos") || strings.Contains(tag, "rhel")) {

0 commit comments

Comments
 (0)