Skip to content

Commit 37caff4

Browse files
committed
jianl - First e2e test
1 parent 75c15b5 commit 37caff4

File tree

6 files changed

+261
-23
lines changed

6 files changed

+261
-23
lines changed
Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
package main
22

33
import (
4-
"flag"
4+
"fmt"
5+
"os"
56

67
"github.com/spf13/cobra"
7-
"k8s.io/klog/v2"
8+
9+
"github.com/openshift-eng/openshift-tests-extension/pkg/cmd"
10+
"github.com/openshift-eng/openshift-tests-extension/pkg/extension"
11+
g "github.com/openshift-eng/openshift-tests-extension/pkg/ginkgo"
12+
13+
_ "github.com/openshift/cluster-version-operator/test/cvo"
814
)
915

10-
var (
11-
rootCmd = &cobra.Command{
12-
Use: "cluster-version-operator",
13-
Short: "Run Cluster Version Controller",
14-
Long: "",
16+
func main() {
17+
registry := extension.NewRegistry()
18+
ext := extension.NewExtension("openshift", "payload", "cluster-version-operator")
19+
20+
ext.AddSuite(extension.Suite{
21+
Name: "cluster-version-operator",
22+
})
23+
24+
specs, err := g.BuildExtensionTestSpecsFromOpenShiftGinkgoSuite()
25+
if err != nil {
26+
panic(fmt.Sprintf("couldn't build extension test specs from ginkgo: %+v", err.Error()))
1527
}
16-
)
1728

18-
func init() {
19-
klog.InitFlags(flag.CommandLine)
20-
_ = flag.CommandLine.Set("alsologtostderr", "true")
21-
rootCmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)
22-
}
29+
ext.AddSpecs(specs)
30+
registry.Register(ext)
2331

24-
func main() {
25-
defer klog.Flush()
26-
if err := rootCmd.Execute(); err != nil {
27-
klog.Exitf("Error executing: %v", err)
32+
root := &cobra.Command{
33+
Long: "OpenShift Tests Extension for Cluster Version Operator",
34+
}
35+
root.AddCommand(cmd.DefaultExtensionCommands(registry)...)
36+
37+
if err := func() error {
38+
return root.Execute()
39+
}(); err != nil {
40+
os.Exit(1)
2841
}
2942
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ require (
2424
golang.org/x/net v0.38.0
2525
golang.org/x/time v0.9.0
2626
gopkg.in/fsnotify.v1 v1.4.7
27+
gopkg.in/yaml.v2 v2.4.0
2728
k8s.io/api v0.33.2
2829
k8s.io/apiextensions-apiserver v0.32.1
2930
k8s.io/apimachinery v0.33.2
@@ -78,7 +79,6 @@ require (
7879
google.golang.org/protobuf v1.36.5 // indirect
7980
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
8081
gopkg.in/inf.v0 v0.9.1 // indirect
81-
gopkg.in/yaml.v2 v2.4.0 // indirect
8282
gopkg.in/yaml.v3 v3.0.1 // indirect
8383
k8s.io/apiserver v0.32.1 // indirect
8484
k8s.io/component-base v0.32.1 // indirect

test/cvo/cvo.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
package cvo
22

33
import (
4-
. "github.com/onsi/ginkgo/v2"
5-
. "github.com/onsi/gomega"
4+
"context"
5+
6+
g "github.com/onsi/ginkgo/v2"
7+
o "github.com/onsi/gomega"
8+
"github.com/openshift/cluster-version-operator/test/utilities"
9+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
610
)
711

8-
var _ = Describe("[Jira:Cluster Version Operator] cluster-version-operator-tests", func() {
9-
It("should support passing tests", func() {
10-
Expect(true).To(BeTrue())
12+
var _ = g.Describe("[Jira:Cluster Version Operator] cluster-version-operator-tests", g.Label("cvo"), func() {
13+
defer g.GinkgoRecover()
14+
15+
oc, err := utilities.GetClient()
16+
o.Expect(err).NotTo(o.HaveOccurred())
17+
18+
g.It("Author:jianl-High-42543-the removed resources are not created in a fresh installed cluster", g.Label("High", "42543"), func() {
19+
g.By("Validate resource with 'release.openshift.io/delete: \"true\"' annotation is not installed")
20+
21+
_, err := oc.CoreV1().Services("openshift-cloud-credential-operator").Get(context.TODO(), "controller-manager-service", metav1.GetOptions{})
22+
o.Expect(err).To(o.HaveOccurred(), "Service controller-manager-service was accidentally installed")
23+
24+
_, err = oc.RbacV1().ClusterRoleBindings().Get(context.TODO(), "default-account-openshift-machine-config-operator", metav1.GetOptions{})
25+
o.Expect(err).To(o.HaveOccurred(), "ClusterRoleBinding default-account-openshift-machine-config-operator was accidentally installed")
26+
27+
_, err = oc.BatchV1().CronJobs("openshift-machine-config-operator").Get(context.TODO(), "machine-config-nodes-crd-cleanup", metav1.GetOptions{})
28+
o.Expect(err).To(o.HaveOccurred(), "CronJob machine-config-nodes-crd-cleanup was accidentally installed")
1129
})
1230
})

test/utilities/api_helper.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package utilities
2+
3+
import (
4+
"crypto/tls"
5+
"crypto/x509"
6+
"errors"
7+
"fmt"
8+
"io"
9+
"log"
10+
"net/http"
11+
"net/url"
12+
"os"
13+
"strings"
14+
)
15+
16+
// GetCert
17+
// @Description get certificate for URL request
18+
// @Create jianl Oct 22 2025
19+
// @Param kubeConfigFolder string The certificate folder which contains key.crt, client.crt, ca.ct
20+
// @Return (Instance of http.Transport, error)
21+
func GetCert(kubeConfigFolder string) (*http.Transport, error) {
22+
// 1. Load the client certificate and private key
23+
clientCert, err := tls.LoadX509KeyPair(kubeConfigFolder+"/client.crt", kubeConfigFolder+"/key.crt")
24+
if err != nil {
25+
log.Fatalf("Error loading client certificate and key: %v", err)
26+
return nil, errors.New("Error loading client certificate and key")
27+
}
28+
29+
// 2. Load the CA certificate(s) to trust a custom CA
30+
caCert, err := os.ReadFile(kubeConfigFolder + "/ca.ct")
31+
if err != nil {
32+
log.Fatalf("Error loading CA certificate: %v.", err)
33+
return nil, errors.New("Error loading CA certificate")
34+
}
35+
caCertPool := x509.NewCertPool()
36+
if caCert != nil {
37+
caCertPool.AppendCertsFromPEM(caCert)
38+
}
39+
40+
// 3. Create a tls.Config with the client certificate and trusted CAs
41+
tlsConfig := &tls.Config{
42+
Certificates: []tls.Certificate{clientCert},
43+
RootCAs: caCertPool, // Only needed if you have a custom CA
44+
InsecureSkipVerify: true,
45+
}
46+
47+
transport := &http.Transport{
48+
TLSClientConfig: tlsConfig,
49+
}
50+
return transport, nil
51+
}
52+
53+
// GetResorce
54+
// @Description get resources from an Openshift cluster
55+
// @Create jianl Oct 22 2025
56+
// @Param server string API host
57+
// @Param transport string Instance of http.Transport which used to create http.Client
58+
// @Param api string The api endpoint
59+
// @Return (resource, error)
60+
func GetResorce(server string, transport *http.Transport, api string) (string, error) {
61+
finalUrl, err := url.JoinPath(server, api)
62+
if err != nil {
63+
fmt.Printf("Error failed to concatenate URL for request: %v\n", err)
64+
return "", err
65+
}
66+
67+
// Create a new GET request
68+
client := &http.Client{
69+
Transport: transport,
70+
}
71+
72+
resp, err := client.Get(finalUrl) // Replace with your URL
73+
if err != nil {
74+
fmt.Printf("Error creating request: %v\n", err)
75+
return "", err
76+
}
77+
defer func() {
78+
if err := resp.Body.Close(); err != nil {
79+
log.Printf("Error closing response body: %v", err)
80+
}
81+
}()
82+
83+
// Send the request
84+
body, err := io.ReadAll(resp.Body)
85+
if err != nil {
86+
fmt.Printf("Error reading response body: %v\n", err)
87+
return "", err
88+
}
89+
return string(body), nil
90+
}
91+
92+
// PatchResorce
93+
// @Description Patch update resource
94+
// @Create jianl Oct 22 2025
95+
// @Param server string API host
96+
// @Param transport string Instance of http.Transport which used to create http.Client
97+
// @Param api string The api endpoint
98+
// @Param jsonObject string The part of resources which will be updated
99+
//
100+
// (Now only support json format string, for example: "{\"spec\":{\"capabilities\":{\"baselineCapabilitySet\":\"None\"}}}")
101+
//
102+
// @Return (resource, error)
103+
func PatchResorce(server string, transport *http.Transport, api string, jsonObject string) (string, error) {
104+
finalUrl, err := url.JoinPath(server, api)
105+
if err != nil {
106+
fmt.Printf("Error failed to concatenate URL for request: %v\n", err)
107+
return "", err
108+
}
109+
// Create a new GET request
110+
client := &http.Client{
111+
Transport: transport,
112+
}
113+
114+
req, err := http.NewRequest(http.MethodPatch, finalUrl, strings.NewReader(jsonObject))
115+
if err != nil {
116+
log.Fatal(err)
117+
}
118+
req.Header.Set("Content-Type", "application/merge-patch+json")
119+
resp, err := client.Do(req) // Replace with your URL
120+
if err != nil {
121+
fmt.Printf("Error creating request: %v\n", err)
122+
return "", err
123+
}
124+
defer func() {
125+
if err := resp.Body.Close(); err != nil {
126+
log.Printf("Error closing response body: %v", err)
127+
}
128+
}()
129+
130+
// Send the request
131+
body, err := io.ReadAll(resp.Body)
132+
if err != nil {
133+
fmt.Printf("Error reading response body: %v\n", err)
134+
return "", err
135+
}
136+
return string(body), nil
137+
}

test/utilities/connection.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package utilities
2+
3+
import (
4+
"errors"
5+
"os"
6+
7+
"k8s.io/client-go/kubernetes"
8+
"k8s.io/client-go/tools/clientcmd"
9+
)
10+
11+
// getClient
12+
// @Description create a kubernetes.Clientset object
13+
// @Create jianl Oct 23 2025
14+
// @Return (Instance of kubernetes.Clientset, error)
15+
func GetClient() (*kubernetes.Clientset, error) {
16+
configPath, present := os.LookupEnv("KUBECONFIG")
17+
if present {
18+
config, err := clientcmd.BuildConfigFromFlags("", configPath)
19+
if err != nil {
20+
return nil, err
21+
}
22+
// Create the Clientset
23+
clientset, err := kubernetes.NewForConfig(config)
24+
if err != nil {
25+
return nil, err
26+
}
27+
return clientset, nil
28+
} else {
29+
return nil, errors.New("KUBECONFIG not set")
30+
}
31+
}

test/utilities/yaml_helper.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package utilities
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"gopkg.in/yaml.v2"
8+
)
9+
10+
// ReadYamlFile
11+
// @Description Read yaml file and return the whole yaml object
12+
// @Create jianl Oct 23 2025
13+
// @Param path string file path
14+
// @Return (map[string]any, error)
15+
func ReadYamlFile(path string) (map[string]any, error) {
16+
yamlData, err := os.ReadFile(path)
17+
if err != nil {
18+
fmt.Println("Error reading file:", err)
19+
return nil, err
20+
}
21+
data, err := ReadYamlObject(yamlData)
22+
return data, err
23+
}
24+
25+
// ReadYamlObject
26+
// @Description Read yaml file content and return the whole yaml object
27+
// @Create jianl Oct 23 2025
28+
// @Param path string file path
29+
// @Return (map[string]any, error)
30+
func ReadYamlObject(yamlData []byte) (map[string]any, error) {
31+
32+
var data map[string]interface{}
33+
err := yaml.Unmarshal(yamlData, &data)
34+
if err != nil {
35+
fmt.Println("Error unmarshaling yaml:", err)
36+
return nil, err
37+
}
38+
return data, nil
39+
}

0 commit comments

Comments
 (0)