Skip to content

Commit 67aa255

Browse files
committed
[WINC-1777] Add OTE extension binary skeleton for Windows Containers tests
Add initial OTE (OpenShift Tests Extension) binary following the same pattern as MCO and NTO, with OCP-37362 as a pilot test case. Changes: - cmd/windows-machine-config-operator-tests-ext/main.go: OTE binary with four suites: windows/all, windows/parallel, windows/serial, windows/storage. Suites named parallel/serial (not conformance/*) until tests carry conformance markers and achieve >=99% pass rate. - test/extended/winc.go: OCP-37362 pilot test; uses json.Unmarshal for robust /version parsing with length validation before slice - test/extended/utils/cli.go: minimal oc wrapper; AsAdmin() wired to --as=system:admin in Run() - test/extended/suite_test.go: Ginkgo suite bootstrap - Makefile: add build-tests-ext target with mkdir -p guard - go.mod: add openshift-tests-extension + OpenShift ginkgo fork replace directive (required for OTE; TODO confirm with Mansi re upstream Ginkgo) Verified locally: make build-tests-ext OK ./windows-machine-config-operator-tests-ext list 1 test listed ./windows-machine-config-operator-tests-ext run-test OCP-37362 PASSED (Azure IPI, OCP 4.20, WMCO v10.20.1) Jira: WINC-1777
1 parent f3be5c1 commit 67aa255

File tree

302 files changed

+196479
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

302 files changed

+196479
-6
lines changed

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ build: fmt vet
103103
build-daemon:
104104
env GOOS=windows GOARCH=amd64 go build -o ${OUTPUT_DIR}/bin/windows-instance-config-daemon.exe ./cmd/daemon
105105

106+
# Build the OTE (OpenShift Tests Extension) binary for Windows Containers tests.
107+
# GO_COMPLIANCE_POLICY=exempt_all is required for test binaries per ART compliance policy.
108+
.PHONY: build-tests-ext
109+
build-tests-ext:
110+
mkdir -p ${OUTPUT_DIR}/bin
111+
GO_COMPLIANCE_POLICY="exempt_all" go build -o ${OUTPUT_DIR}/bin/windows-machine-config-operator-tests-ext \
112+
./cmd/windows-machine-config-operator-tests-ext
113+
106114
.PHONY: run
107115
run: manifests generate fmt vet ## Run a controller from your host.
108116
go run cmd/operator/main.go
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// windows-machine-config-operator-tests-ext is the OTE (OpenShift Tests Extension)
2+
// binary for Windows Containers tests. It wraps WINC Ginkgo tests and exposes them
3+
// through the standardized OTE interface (info / list / run-test / run-suite).
4+
//
5+
// References:
6+
// - OTE Integration Guide: https://github.com/openshift-eng/openshift-tests-extension
7+
// - Similar implementation (NTO): https://github.com/openshift/cluster-node-tuning-operator/blob/main/cmd/cluster-node-tuning-operator-test-ext/main.go
8+
// - Similar implementation (MCO): https://github.com/openshift/machine-config-operator/blob/master/cmd/machine-config-tests-ext/main.go
9+
package main
10+
11+
import (
12+
"fmt"
13+
"os"
14+
"strings"
15+
16+
otecmd "github.com/openshift-eng/openshift-tests-extension/pkg/cmd"
17+
e "github.com/openshift-eng/openshift-tests-extension/pkg/extension"
18+
et "github.com/openshift-eng/openshift-tests-extension/pkg/extension/extensiontests"
19+
g "github.com/openshift-eng/openshift-tests-extension/pkg/ginkgo"
20+
"github.com/spf13/cobra"
21+
22+
_ "github.com/openshift/windows-machine-config-operator/test/extended"
23+
// Register WINC Ginkgo tests.
24+
)
25+
26+
func main() {
27+
registry := e.NewRegistry()
28+
ext := e.NewExtension("openshift", "payload", "windows-machine-config-operator")
29+
30+
// All WINC tests - used for full runs and informing jobs.
31+
ext.AddSuite(e.Suite{
32+
Name: "windows/all",
33+
Qualifiers: []string{
34+
`name.contains("[sig-windows]")`,
35+
},
36+
})
37+
38+
// Parallel subset: non-Serial, non-Slow, non-Disruptive tests.
39+
// Renamed from windows/conformance/parallel until tests carry an explicit
40+
// conformance marker and achieve >=99% pass rate, at which point Parents
41+
// pointing to openshift/conformance/parallel will be added.
42+
ext.AddSuite(e.Suite{
43+
Name: "windows/parallel",
44+
Qualifiers: []string{
45+
`name.contains("[sig-windows]") && !name.contains("[Serial]") && !name.contains("[Slow]") && !name.contains("[Disruptive]")`,
46+
},
47+
})
48+
49+
// Serial subset: tests that must run in isolation.
50+
// Renamed from windows/conformance/serial for the same reason as above.
51+
ext.AddSuite(e.Suite{
52+
Name: "windows/serial",
53+
Qualifiers: []string{
54+
`name.contains("[sig-windows]") && name.contains("[Serial]")`,
55+
},
56+
})
57+
58+
// Storage-specific tests.
59+
ext.AddSuite(e.Suite{
60+
Name: "windows/storage",
61+
Qualifiers: []string{
62+
`name.contains("[sig-windows]") && name.contains("storage")`,
63+
},
64+
})
65+
66+
specs, err := g.BuildExtensionTestSpecsFromOpenShiftGinkgoSuite()
67+
if err != nil {
68+
panic(fmt.Sprintf("couldn't build extension test specs from ginkgo: %v", err))
69+
}
70+
71+
applyPlatformFilters(specs)
72+
73+
ext.AddSpecs(specs)
74+
registry.Register(ext)
75+
76+
root := &cobra.Command{
77+
Use: "windows-machine-config-operator-tests-ext",
78+
Short: "OpenShift Windows Containers test extension (OTE)",
79+
Long: "Runs the WINC test suite as an OpenShift Tests Extension binary.",
80+
}
81+
82+
root.AddCommand(otecmd.DefaultExtensionCommands(registry)...)
83+
84+
if err := root.Execute(); err != nil {
85+
os.Exit(1)
86+
}
87+
}
88+
89+
// applyPlatformFilters converts "Platform:<name>" and "NoPlatform:<name>" Ginkgo
90+
// labels into OTE include/exclude constraints so that openshift-tests can filter
91+
// tests before execution rather than relying on g.Skip() inside the test body.
92+
func applyPlatformFilters(specs et.ExtensionTestSpecs) {
93+
specs.Walk(func(spec *et.ExtensionTestSpec) {
94+
for label := range spec.Labels {
95+
if strings.HasPrefix(label, "Platform:") {
96+
platform := strings.TrimPrefix(label, "Platform:")
97+
spec.Include(et.PlatformEquals(platform))
98+
}
99+
if strings.HasPrefix(label, "NoPlatform:") {
100+
platform := strings.TrimPrefix(label, "NoPlatform:")
101+
spec.Exclude(et.PlatformEquals(platform))
102+
}
103+
}
104+
})
105+
}

go.mod

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ replace (
88
// fix CVE-2025-30204 transitive deps still using older v4. Remove once `go mod graph` shows only 4.5.2 or higher
99
github.com/golang-jwt/jwt/v4 => github.com/golang-jwt/jwt/v4 v4.5.2
1010
github.com/golang-jwt/jwt/v5 => github.com/golang-jwt/jwt/v5 v5.2.2
11+
// Required for openshift-tests-extension compatibility (uses OpenShift's ginkgo fork).
12+
// TODO: confirm with Mansi whether this can be avoided with upstream Ginkgo.
13+
github.com/onsi/ginkgo/v2 => github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12
1114
)
1215

1316
require (
@@ -16,6 +19,9 @@ require (
1619
github.com/coreos/ignition/v2 v2.23.0
1720
github.com/go-imports-organizer/goio v1.5.0
1821
github.com/go-logr/logr v1.4.3
22+
github.com/onsi/ginkgo/v2 v2.22.2
23+
github.com/onsi/gomega v1.36.2
24+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818
1925
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3
2026
github.com/openshift/client-go v0.0.0-20260213141500-06efc6dce93b
2127
github.com/openshift/library-go v0.0.0-20260213153706-03f1709971c5
@@ -86,11 +92,13 @@ require (
8692
github.com/go-openapi/swag/stringutils v0.25.4 // indirect
8793
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
8894
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
95+
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
8996
github.com/gogo/protobuf v1.3.2 // indirect
9097
github.com/google/btree v1.1.3 // indirect
9198
github.com/google/cel-go v0.26.0 // indirect
9299
github.com/google/gnostic-models v0.7.1 // indirect
93100
github.com/google/go-cmp v0.7.0 // indirect
101+
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
94102
github.com/google/uuid v1.6.0 // indirect
95103
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
96104
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
@@ -109,9 +117,8 @@ require (
109117
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
110118
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
111119
github.com/onsi/ginkgo v1.16.5 // indirect
112-
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
113-
github.com/onsi/gomega v1.36.2 // indirect
114120
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
121+
github.com/pkg/errors v0.9.1 // indirect
115122
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
116123
github.com/prometheus/client_golang v1.23.2 // indirect
117124
github.com/prometheus/client_model v0.6.2 // indirect
@@ -143,6 +150,7 @@ require (
143150
golang.org/x/term v0.40.0 // indirect
144151
golang.org/x/text v0.34.0 // indirect
145152
golang.org/x/time v0.14.0 // indirect
153+
golang.org/x/tools v0.41.0 // indirect
146154
gomodules.xyz/jsonpatch/v2 v2.5.0 // indirect
147155
google.golang.org/genproto/googleapis/api v0.0.0-20250721164621-a45f3dfb1074 // indirect
148156
google.golang.org/genproto/googleapis/rpc v0.0.0-20250721164621-a45f3dfb1074 // indirect

go.sum

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@ github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85n
275275
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
276276
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
277277
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
278-
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
279278
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
280279
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
281280
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
@@ -505,8 +504,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
505504
github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
506505
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
507506
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
508-
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
509-
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
510507
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
511508
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
512509
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
@@ -515,12 +512,16 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
515512
github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
516513
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
517514
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
515+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818 h1:jJLE/aCAqDf8U4wc3bE1IEKgIxbb0ICjCNVFA49x/8s=
516+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
518517
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3 h1:SZ8+jxtkMvpb4HDTjSAbaOyhFsw5PiWhjBog+XLY7jc=
519518
github.com/openshift/api v0.0.0-20260213204242-d34f11c515b3/go.mod h1:d5uzF0YN2nQQFA0jIEWzzOZ+edmo6wzlGLvx5Fhz4uY=
520519
github.com/openshift/client-go v0.0.0-20260213141500-06efc6dce93b h1:7rTnxq+haKrzUFKQQDylkklyFRtGFox73dlawRlnTA8=
521520
github.com/openshift/client-go v0.0.0-20260213141500-06efc6dce93b/go.mod h1:V3s8weD4bKXGXaN7d9g3V1QS2gmlYBRI2i/lfIwmroM=
522521
github.com/openshift/library-go v0.0.0-20260213153706-03f1709971c5 h1:9Pe6iVOMjt9CdA/vaKBNUSoEIjIe1po5Ha3ABRYXLJI=
523522
github.com/openshift/library-go v0.0.0-20260213153706-03f1709971c5/go.mod h1:K3FoNLgNBFYbFuG+Kr8usAnQxj1w84XogyUp2M8rK8k=
523+
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12 h1:AKx/w1qpS8We43bsRgf8Nll3CGlDHpr/WAXvuedTNZI=
524+
github.com/openshift/onsi-ginkgo/v2 v2.6.1-0.20241205171354-8006f302fd12/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
524525
github.com/operator-framework/api v0.5.2/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY=
525526
github.com/operator-framework/api v0.16.0 h1:swUOhVv7QDszxBTwYM8QAtyeqI4EQHNVAiKMS+xjakY=
526527
github.com/operator-framework/api v0.16.0/go.mod h1:kk8xJahHJR3bKqrA+A+1VIrhOTmyV76k+ARv+iV+u1Q=

test/extended/suite_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package extended
2+
3+
import (
4+
"testing"
5+
6+
g "github.com/onsi/ginkgo/v2"
7+
o "github.com/onsi/gomega"
8+
)
9+
10+
func TestExtended(t *testing.T) {
11+
o.RegisterFailHandler(g.Fail)
12+
g.RunSpecs(t, "Windows Containers Extended Test Suite")
13+
}

test/extended/utils/cli.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package utils
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os"
7+
"os/exec"
8+
"strings"
9+
)
10+
11+
// CLI wraps the oc command-line tool for use in OTE Ginkgo tests.
12+
type CLI struct {
13+
namespace string
14+
asAdmin bool
15+
noNamespace bool
16+
kubeconfig string
17+
}
18+
19+
// NewCLI creates a CLI instance with the given namespace.
20+
func NewCLI(namespace string) *CLI {
21+
return &CLI{
22+
namespace: namespace,
23+
kubeconfig: kubeconfig(),
24+
}
25+
}
26+
27+
// NewCLIWithoutNamespace creates a CLI instance without a namespace (for cluster-scoped resources).
28+
func NewCLIWithoutNamespace() *CLI {
29+
return &CLI{
30+
noNamespace: true,
31+
kubeconfig: kubeconfig(),
32+
}
33+
}
34+
35+
// AsAdmin returns a copy of the CLI that runs as cluster-admin.
36+
func (c *CLI) AsAdmin() *CLI {
37+
copy := *c
38+
copy.asAdmin = true
39+
return &copy
40+
}
41+
42+
// Run executes an oc subcommand with the given arguments and returns stdout, stderr, and any error.
43+
func (c *CLI) Run(verb string, args ...string) (string, string, error) {
44+
cmdArgs := []string{verb}
45+
if c.asAdmin {
46+
cmdArgs = append(cmdArgs, "--as=system:admin")
47+
}
48+
if c.noNamespace {
49+
// no -n flag
50+
} else if c.namespace != "" {
51+
cmdArgs = append(cmdArgs, "-n", c.namespace)
52+
}
53+
cmdArgs = append(cmdArgs, args...)
54+
55+
cmd := exec.Command("oc", cmdArgs...)
56+
if c.kubeconfig != "" {
57+
cmd.Env = append(os.Environ(), "KUBECONFIG="+c.kubeconfig)
58+
}
59+
60+
var stdout, stderr bytes.Buffer
61+
cmd.Stdout = &stdout
62+
cmd.Stderr = &stderr
63+
64+
err := cmd.Run()
65+
return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err
66+
}
67+
68+
// Output is a convenience wrapper that returns stdout or an error combining stderr.
69+
func (c *CLI) Output(verb string, args ...string) (string, error) {
70+
out, errOut, err := c.Run(verb, args...)
71+
if err != nil {
72+
return "", fmt.Errorf("%w\nstderr: %s", err, errOut)
73+
}
74+
return out, nil
75+
}
76+
77+
func kubeconfig() string {
78+
if kc := os.Getenv("KUBECONFIG"); kc != "" {
79+
return kc
80+
}
81+
return os.Getenv("HOME") + "/.kube/config"
82+
}

test/extended/winc.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package extended
2+
3+
import (
4+
"encoding/json"
5+
"strings"
6+
7+
g "github.com/onsi/ginkgo/v2"
8+
o "github.com/onsi/gomega"
9+
10+
"github.com/openshift/windows-machine-config-operator/test/extended/utils"
11+
)
12+
13+
const (
14+
wmcoNamespace = "openshift-windows-machine-config-operator"
15+
)
16+
17+
var _ = g.Describe("[sig-windows] Windows_Containers", func() {
18+
var oc = utils.NewCLIWithoutNamespace()
19+
20+
// author: rrasouli@redhat.com
21+
// OCP-37362 - Pilot case for OTE migration to WMCO
22+
g.It("Author:rrasouli-Smokerun-Medium-37362-[wmco] wmco using correct golang version [OTP]", func() {
23+
g.By("Fetch the correct golang version from cluster")
24+
serverVersion, err := oc.AsAdmin().Output("get", "--raw", "/version")
25+
o.Expect(err).NotTo(o.HaveOccurred())
26+
27+
// Unmarshal the version response to extract goVersion safely.
28+
var versionInfo struct {
29+
GoVersion string `json:"goVersion"`
30+
}
31+
o.Expect(json.Unmarshal([]byte(serverVersion), &versionInfo)).To(o.Succeed(),
32+
"failed to parse /version JSON response")
33+
o.Expect(versionInfo.GoVersion).NotTo(o.BeEmpty(), "goVersion not found in /version response")
34+
35+
// Truncate to major.minor (e.g. "go1.24.6" -> "go1.24")
36+
parts := strings.Split(versionInfo.GoVersion, ".")
37+
o.Expect(len(parts)).To(o.BeNumerically(">=", 2), "unexpected golang version format: %s", versionInfo.GoVersion)
38+
truncated := strings.Join(parts[:2], ".")
39+
g.GinkgoWriter.Printf("Golang version: %s, truncated: %s\n", versionInfo.GoVersion, truncated)
40+
41+
g.By("Compare with golang version in WMCO logs")
42+
logs, err := oc.AsAdmin().Output("logs",
43+
"deployment.apps/windows-machine-config-operator",
44+
"-n", wmcoNamespace,
45+
)
46+
o.Expect(err).NotTo(o.HaveOccurred())
47+
o.Expect(logs).To(o.ContainSubstring(truncated),
48+
"WMCO logs do not contain expected golang version %s", truncated)
49+
})
50+
})

vendor/github.com/go-task/slim-sprig/v3/.editorconfig

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/go-task/slim-sprig/v3/.gitattributes

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/go-task/slim-sprig/v3/.gitignore

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)