Skip to content

Commit 735e8a0

Browse files
committed
[ote] Add OTE extension binary skeleton for Windows Containers tests
Add initial OTE (OpenShift Tests Extension) binary using a nested module structure under ote/, isolating OTE dependencies from the operator's go.mod and vendor tree. The binary (wmco-tests-ext) is built via make build-tests-ext using go mod download (no vendor committed for test code). GOFLAGS is explicitly reset to avoid inheriting -mod=vendor from the CI build environment. The binary is compressed and placed in the Prow CI image via Dockerfile.ci. Also adds ote/OWNERS with rrasouli, weinliu, and mansikulkarni96. Jira: WINC-1777
1 parent 282a862 commit 735e8a0

File tree

9 files changed

+301
-0
lines changed

9 files changed

+301
-0
lines changed

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,13 @@ 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+
# The OTE binary lives in the ote/ nested module, isolated from the operator's go.mod.
109+
.PHONY: build-tests-ext
110+
build-tests-ext:
111+
cd ote && GOFLAGS="" go mod download && GOFLAGS="" GO_COMPLIANCE_POLICY="exempt_all" go build -o ../${OUTPUT_DIR}/bin/wmco-tests-ext ./cmd/wmco-tests-ext
112+
106113
.PHONY: run
107114
run: manifests generate fmt vet ## Run a controller from your host.
108115
go run cmd/operator/main.go

build/Dockerfile.ci

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ COPY bundle bundle
9292
COPY hack hack
9393
COPY pkg pkg
9494
COPY test test
95+
COPY ote ote
9596
COPY vendor vendor
9697
COPY version version
9798
COPY go.mod go.mod
@@ -100,6 +101,7 @@ COPY tools.go tools.go
100101
COPY .gitignore .gitignore
101102
RUN make build
102103
RUN make build-daemon
104+
RUN make build-tests-ext && gzip -9 build/_output/bin/wmco-tests-ext
103105

104106
# Build the operator image with following payload structure
105107
# /payload/
@@ -208,6 +210,8 @@ COPY --from=build /build/windows-machine-config-operator .
208210

209211
# install operator binary
210212
COPY --from=build /build/windows-machine-config-operator/build/_output/bin/windows-machine-config-operator ${OPERATOR}
213+
# install OTE test extension binary (gzip compressed for openshift-tests extraction)
214+
COPY --from=build /build/windows-machine-config-operator/build/_output/bin/wmco-tests-ext.gz /usr/bin/wmco-tests-ext.gz
211215
COPY --from=build /build/windows-machine-config-operator/build/bin /usr/local/bin
212216
RUN /usr/local/bin/user_setup
213217

ote/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
vendor/
2+
bin/

ote/OWNERS

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
reviewers:
2+
- rrasouli
3+
- weinliu
4+
- mansikulkarni96
5+
approvers:
6+
- rrasouli
7+
- weinliu
8+
- mansikulkarni96

ote/cmd/wmco-tests-ext/main.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// windows-machine-config-operator-tests-ext is the OTE (OpenShift Tests Extension)
2+
// binary for Windows Containers tests. Tests are registered as plain Go functions
3+
// using upstream Ginkgo, without the OpenShift Ginkgo fork.
4+
//
5+
// References:
6+
// - OTE Integration Guide: https://github.com/openshift-eng/openshift-tests-extension
7+
package main
8+
9+
import (
10+
"context"
11+
"os"
12+
13+
otecmd "github.com/openshift-eng/openshift-tests-extension/pkg/cmd"
14+
e "github.com/openshift-eng/openshift-tests-extension/pkg/extension"
15+
et "github.com/openshift-eng/openshift-tests-extension/pkg/extension/extensiontests"
16+
"github.com/spf13/cobra"
17+
18+
"github.com/openshift/windows-machine-config-operator/ote/test/extended"
19+
"github.com/openshift/windows-machine-config-operator/ote/test/extended/cli"
20+
)
21+
22+
func main() {
23+
registry := e.NewRegistry()
24+
ext := e.NewExtension("openshift", "payload", "windows-machine-config-operator")
25+
26+
// All WINC tests - used for full runs and informing jobs.
27+
// No qualifier needed: all tests in this binary are WINC tests.
28+
ext.AddSuite(e.Suite{
29+
Name: "windows/all",
30+
})
31+
32+
// Parallel subset: non-Serial, non-Slow, non-Disruptive tests.
33+
ext.AddSuite(e.Suite{
34+
Name: "windows/parallel",
35+
Qualifiers: []string{
36+
`!name.contains("[Serial]") && !name.contains("[Slow]") && !name.contains("[Disruptive]")`,
37+
},
38+
})
39+
40+
// Serial subset: tests that must run in isolation.
41+
ext.AddSuite(e.Suite{
42+
Name: "windows/serial",
43+
Qualifiers: []string{
44+
`name.contains("[Serial]")`,
45+
},
46+
})
47+
48+
// Storage-specific tests.
49+
ext.AddSuite(e.Suite{
50+
Name: "windows/storage",
51+
Qualifiers: []string{
52+
`name.contains("storage")`,
53+
},
54+
})
55+
56+
// Register test specs manually — no OpenShift Ginkgo fork required.
57+
specs := et.ExtensionTestSpecs{
58+
{
59+
Name: "[sig-windows] Windows_Containers Author:rrasouli-Smokerun-Medium-37362-[wmco] wmco using correct golang version [OTP]",
60+
Run: func(ctx context.Context) *et.ExtensionTestResult {
61+
if err := extended.CheckWmcoGolangVersion(ctx, cli.NewCLIWithoutNamespace()); err != nil {
62+
return &et.ExtensionTestResult{Result: et.ResultFailed, Output: err.Error()}
63+
}
64+
return &et.ExtensionTestResult{Result: et.ResultPassed}
65+
},
66+
},
67+
}
68+
69+
ext.AddSpecs(specs)
70+
registry.Register(ext)
71+
72+
root := &cobra.Command{
73+
Use: "windows-machine-config-operator-tests-ext",
74+
Short: "OpenShift Windows Containers test extension (OTE)",
75+
Long: "Runs the WINC test suite as an OpenShift Tests Extension binary.",
76+
}
77+
78+
root.AddCommand(otecmd.DefaultExtensionCommands(registry)...)
79+
80+
if err := root.Execute(); err != nil {
81+
os.Exit(1)
82+
}
83+
}

ote/go.mod

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module github.com/openshift/windows-machine-config-operator/ote
2+
3+
go 1.24.0
4+
5+
require (
6+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818
7+
github.com/spf13/cobra v1.10.2
8+
)
9+
10+
require (
11+
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
12+
github.com/google/cel-go v0.17.8 // indirect
13+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
14+
github.com/pkg/errors v0.9.1 // indirect
15+
github.com/spf13/pflag v1.0.9 // indirect
16+
github.com/stoewer/go-strcase v1.2.0 // indirect
17+
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect
18+
golang.org/x/text v0.19.0 // indirect
19+
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
20+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect
21+
google.golang.org/protobuf v1.35.1 // indirect
22+
)

ote/go.sum

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h1:7RFfzj4SSt6nnvCPbCqijJi1nWCd+TqAT3bYCStRC18=
2+
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
3+
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
4+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
6+
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/google/cel-go v0.17.8 h1:j9m730pMZt1Fc4oKhCLUHfjj6527LuhYcYw0Rl8gqto=
8+
github.com/google/cel-go v0.17.8/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
9+
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
10+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
11+
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
12+
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
13+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818 h1:jJLE/aCAqDf8U4wc3bE1IEKgIxbb0ICjCNVFA49x/8s=
14+
github.com/openshift-eng/openshift-tests-extension v0.0.0-20260127124016-0fed2b824818/go.mod h1:6gkP5f2HL0meusT0Aim8icAspcD1cG055xxBZ9yC68M=
15+
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
16+
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
17+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
18+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
19+
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
20+
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
21+
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
22+
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
23+
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
24+
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
25+
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
26+
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
27+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
28+
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
29+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
30+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
31+
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
32+
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU=
33+
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
34+
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
35+
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
36+
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
37+
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
38+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM=
39+
google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
40+
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
41+
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
42+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
43+
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
44+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
45+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

ote/test/extended/cli/cli.go

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

ote/test/extended/cluster.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package extended
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"strings"
8+
9+
"github.com/openshift/windows-machine-config-operator/ote/test/extended/cli"
10+
)
11+
12+
const (
13+
wmcoNamespace = "openshift-windows-machine-config-operator"
14+
)
15+
16+
// CheckWmcoGolangVersion verifies that the golang version reported by the cluster
17+
// matches the version used to build the WMCO binary (OCP-37362).
18+
func CheckWmcoGolangVersion(_ context.Context, oc *cli.CLI) error {
19+
serverVersion, err := oc.AsAdmin().Output("get", "--raw", "/version")
20+
if err != nil {
21+
return fmt.Errorf("failed to get cluster version: %w", err)
22+
}
23+
24+
var versionInfo struct {
25+
GoVersion string `json:"goVersion"`
26+
}
27+
if err := json.Unmarshal([]byte(serverVersion), &versionInfo); err != nil {
28+
return fmt.Errorf("failed to parse /version JSON: %w", err)
29+
}
30+
if versionInfo.GoVersion == "" {
31+
return fmt.Errorf("goVersion not found in /version response")
32+
}
33+
34+
parts := strings.Split(versionInfo.GoVersion, ".")
35+
if len(parts) < 2 {
36+
return fmt.Errorf("unexpected golang version format: %s", versionInfo.GoVersion)
37+
}
38+
truncated := strings.Join(parts[:2], ".")
39+
40+
logs, err := oc.AsAdmin().Output("logs",
41+
"deployment.apps/windows-machine-config-operator",
42+
"-n", wmcoNamespace,
43+
)
44+
if err != nil {
45+
return fmt.Errorf("failed to get WMCO logs: %w", err)
46+
}
47+
48+
if !strings.Contains(logs, truncated) {
49+
return fmt.Errorf("WMCO logs do not contain expected golang version %s (full: %s)",
50+
truncated, versionInfo.GoVersion)
51+
}
52+
return nil
53+
}

0 commit comments

Comments
 (0)