Merge pull request #5630 from mohamedawnallah/addTestInitOperatorPKGHelpers
operator/pkg: add test helpers
This commit is contained in:
commit
c16e52a3ec
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright 2024 The Karmada Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// TestInterface defines the interface for retrieving test data.
|
||||
type TestInterface interface {
|
||||
// Get returns the data from the test instance.
|
||||
Get() string
|
||||
}
|
||||
|
||||
// MyTestData is a struct that implements the TestInterface.
|
||||
type MyTestData struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
// Get returns the data stored in the MyTestData struct.
|
||||
func (m *MyTestData) Get() string {
|
||||
return m.Data
|
||||
}
|
||||
|
||||
// TestDeInitData contains the configuration and state required to deinitialize Karmada components.
|
||||
type TestDeInitData struct {
|
||||
name string
|
||||
namespace string
|
||||
remoteClient clientset.Interface
|
||||
}
|
||||
|
||||
// Ensure TestDeInitData implements InitData interface at compile time.
|
||||
var _ DeInitData = &TestDeInitData{}
|
||||
|
||||
// GetName returns the name of the current Karmada installation.
|
||||
func (t *TestDeInitData) GetName() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
// GetNamespace returns the namespace of the current Karmada installation.
|
||||
func (t *TestDeInitData) GetNamespace() string {
|
||||
return t.namespace
|
||||
}
|
||||
|
||||
// RemoteClient returns the Kubernetes client for remote interactions.
|
||||
func (t *TestDeInitData) RemoteClient() clientset.Interface {
|
||||
return t.remoteClient
|
||||
}
|
||||
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
Copyright 2024 The Karmada Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
|
||||
operatorv1alpha1 "github.com/karmada-io/karmada/operator/pkg/apis/operator/v1alpha1"
|
||||
"github.com/karmada-io/karmada/operator/pkg/certs"
|
||||
)
|
||||
|
||||
// TestInterface defines the interface for retrieving test data.
|
||||
type TestInterface interface {
|
||||
// Get returns the data from the test instance.
|
||||
Get() string
|
||||
}
|
||||
|
||||
// MyTestData is a struct that implements the TestInterface.
|
||||
type MyTestData struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
// Get returns the data stored in the MyTestData struct.
|
||||
func (m *MyTestData) Get() string {
|
||||
return m.Data
|
||||
}
|
||||
|
||||
// TestInitData contains the configuration and state required to initialize Karmada components.
|
||||
type TestInitData struct {
|
||||
Name string
|
||||
Namespace string
|
||||
ControlplaneConfigREST *rest.Config
|
||||
DataDirectory string
|
||||
CrdTarballArchive operatorv1alpha1.CRDTarball
|
||||
KarmadaVersionRelease string
|
||||
ComponentsUnits *operatorv1alpha1.KarmadaComponents
|
||||
FeatureGatesOptions map[string]bool
|
||||
RemoteClientConnector clientset.Interface
|
||||
KarmadaClientConnector clientset.Interface
|
||||
ControlplaneAddr string
|
||||
Certs []*certs.KarmadaCert
|
||||
}
|
||||
|
||||
// Ensure TestInitData implements InitData interface at compile time.
|
||||
var _ InitData = &TestInitData{}
|
||||
|
||||
// GetName returns the name of the current Karmada installation.
|
||||
func (t *TestInitData) GetName() string {
|
||||
return t.Name
|
||||
}
|
||||
|
||||
// GetNamespace returns the namespace of the current Karmada installation.
|
||||
func (t *TestInitData) GetNamespace() string {
|
||||
return t.Namespace
|
||||
}
|
||||
|
||||
// SetControlplaneConfig sets the control plane configuration for Karmada.
|
||||
func (t *TestInitData) SetControlplaneConfig(config *rest.Config) {
|
||||
t.ControlplaneConfigREST = config
|
||||
}
|
||||
|
||||
// ControlplaneConfig returns the control plane configuration.
|
||||
func (t *TestInitData) ControlplaneConfig() *rest.Config {
|
||||
return t.ControlplaneConfigREST
|
||||
}
|
||||
|
||||
// ControlplaneAddress returns the address of the control plane.
|
||||
func (t *TestInitData) ControlplaneAddress() string {
|
||||
return t.ControlplaneAddr
|
||||
}
|
||||
|
||||
// RemoteClient returns the Kubernetes client for remote interactions.
|
||||
func (t *TestInitData) RemoteClient() clientset.Interface {
|
||||
return t.RemoteClientConnector
|
||||
}
|
||||
|
||||
// KarmadaClient returns the Kubernetes client for interacting with Karmada.
|
||||
func (t *TestInitData) KarmadaClient() clientset.Interface {
|
||||
return t.KarmadaClientConnector
|
||||
}
|
||||
|
||||
// DataDir returns the data directory used by Karmada.
|
||||
func (t *TestInitData) DataDir() string {
|
||||
return t.DataDirectory
|
||||
}
|
||||
|
||||
// CrdTarball returns the CRD tarball used for Karmada installation.
|
||||
func (t *TestInitData) CrdTarball() operatorv1alpha1.CRDTarball {
|
||||
return t.CrdTarballArchive
|
||||
}
|
||||
|
||||
// KarmadaVersion returns the version of Karmada being used.
|
||||
func (t *TestInitData) KarmadaVersion() string {
|
||||
return t.KarmadaVersionRelease
|
||||
}
|
||||
|
||||
// Components returns the Karmada components used in the current installation.
|
||||
func (t *TestInitData) Components() *operatorv1alpha1.KarmadaComponents {
|
||||
return t.ComponentsUnits
|
||||
}
|
||||
|
||||
// FeatureGates returns the feature gates enabled for the current installation.
|
||||
func (t *TestInitData) FeatureGates() map[string]bool {
|
||||
return t.FeatureGatesOptions
|
||||
}
|
||||
|
||||
// AddCert adds a Karmada certificate to the TestInitData.
|
||||
func (t *TestInitData) AddCert(cert *certs.KarmadaCert) {
|
||||
t.Certs = append(t.Certs, cert)
|
||||
}
|
||||
|
||||
// GetCert retrieves a Karmada certificate by its name.
|
||||
func (t *TestInitData) GetCert(name string) *certs.KarmadaCert {
|
||||
for _, cert := range t.Certs {
|
||||
parts := strings.Split(cert.CertName(), ".")
|
||||
if parts[0] == name {
|
||||
return cert
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CertList returns a list of all Karmada certificates stored in TestInitData.
|
||||
func (t *TestInitData) CertList() []*certs.KarmadaCert {
|
||||
return t.Certs
|
||||
}
|
||||
|
||||
// LoadCertFromSecret loads a Karmada certificate from a Kubernetes secret.
|
||||
func (t *TestInitData) LoadCertFromSecret(secret *corev1.Secret) error {
|
||||
if len(secret.Data) == 0 {
|
||||
return fmt.Errorf("cert data is empty")
|
||||
}
|
||||
|
||||
// Dummy implementation: load empty certificate.
|
||||
cert := &certs.KarmadaCert{}
|
||||
t.AddCert(cert)
|
||||
return nil
|
||||
}
|
||||
|
|
@ -29,12 +29,28 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
operatorv1alpha1 "github.com/karmada-io/karmada/operator/pkg/apis/operator/v1alpha1"
|
||||
"github.com/karmada-io/karmada/operator/pkg/workflow"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
)
|
||||
|
||||
var (
|
||||
// ClientFactory creates a new Kubernetes clientset from the provided kubeconfig.
|
||||
ClientFactory = func(kubeconfig *rest.Config) (clientset.Interface, error) {
|
||||
return clientset.NewForConfig(kubeconfig)
|
||||
}
|
||||
|
||||
// BuildClientFromSecretRefFactory constructs a Kubernetes clientset using a LocalSecretReference.
|
||||
BuildClientFromSecretRefFactory = func(client clientset.Interface, ref *operatorv1alpha1.LocalSecretReference) (clientset.Interface, error) {
|
||||
return BuildClientFromSecretRef(client, ref)
|
||||
}
|
||||
)
|
||||
|
||||
// Downloader Download progress
|
||||
type Downloader struct {
|
||||
io.Reader
|
||||
|
|
@ -222,3 +238,51 @@ func ReplaceYamlForReg(path, destResource string, reg *regexp.Regexp) ([]byte, e
|
|||
repl := reg.ReplaceAllString(string(data), destResource)
|
||||
return yaml.YAMLToJSON([]byte(repl))
|
||||
}
|
||||
|
||||
// ContainAllTasks checks if all tasks in the subset are present in the tasks slice.
|
||||
// Returns an error if any subset task is not found; nil otherwise.
|
||||
func ContainAllTasks(tasks, subset []workflow.Task) error {
|
||||
for _, subsetTask := range subset {
|
||||
found := false
|
||||
for _, task := range tasks {
|
||||
found = DeepEqualTasks(task, subsetTask) == nil
|
||||
if found {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("subset task %v not found in tasks", subsetTask)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepEqualTasks checks if two workflow.Task instances are deeply equal.
|
||||
// It returns an error if they differ, or nil if they are equal.
|
||||
// The comparison includes the task name, RunSubTasks flag,
|
||||
// and the length and contents of the Tasks slice.
|
||||
// Function references and behavior are not compared; only the values
|
||||
// of the specified fields are considered. Any differences are detailed
|
||||
// in the returned error.
|
||||
func DeepEqualTasks(t1, t2 workflow.Task) error {
|
||||
if t1.Name != t2.Name {
|
||||
return fmt.Errorf("expected t1 name %s, but got %s", t2.Name, t1.Name)
|
||||
}
|
||||
|
||||
if t1.RunSubTasks != t2.RunSubTasks {
|
||||
return fmt.Errorf("expected t1 RunSubTasks flag %t, but got %t", t2.RunSubTasks, t1.RunSubTasks)
|
||||
}
|
||||
|
||||
if len(t1.Tasks) != len(t2.Tasks) {
|
||||
return fmt.Errorf("expected t1 tasks length %d, but got %d", len(t2.Tasks), len(t1.Tasks))
|
||||
}
|
||||
|
||||
for index := range t1.Tasks {
|
||||
err := DeepEqualTasks(t1.Tasks[index], t2.Tasks[index])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unexpected error; tasks are not equal at index %d: %v", index, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue