func (f *Framework) CreateS3Secret(id, key string) error {
	name := f.S3SecretName()
	f.Logf("Creating RedisClusterBackup secret %s", name)
	secret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: f.Namespace(),
		},
		StringData: map[string]string{
			S3ID:  id,
			S3KEY: key,
		},
		Type: "Opaque",
	}
	result := &corev1.Secret{}
	err := f.Client.Get(context.TODO(), types.NamespacedName{
		Namespace: f.Namespace(),
		Name:      name,
	}, result)
	if errors.IsNotFound(err) {
		return f.Client.Create(context.TODO(), secret)
	}
	return err
}
CreateS3Secret creates a secret for RedisClusterBackup
package e2e
import (
	"context"
	"fmt"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	rbacv1 "k8s.io/api/rbac/v1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/client-go/rest"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/config"
	redisv1alpha1 "github.com/ucloud/redis-cluster-operator/pkg/apis/redis/v1alpha1"
	"github.com/ucloud/redis-cluster-operator/test/testclient"
)
type Framework struct {
	KubeConfig *rest.Config
	Client     client.Client
	nameSpace  string
}
func NewFramework(name string) *Framework {
	namespace := fmt.Sprintf("drce2e-%s-%s", name, RandString(8))
	return &Framework{
		nameSpace: namespace,
	}
}
func (f *Framework) BeforeEach() error {
	cfg, err := config.GetConfig()
	if err != nil {
		f.Failf("get k8s config err: %s", err)
	}
	f.KubeConfig = cfg
	client, err := testclient.NewClient(cfg)
	if err != nil {
		f.Failf("get k8s config err: %s", err)
	}
	f.Client = client
	if err := f.createTestNamespace(); err != nil {
		return err
	}
	if err := f.createRBAC(); err != nil {
		return err
	}
	return nil
}
func (f *Framework) AfterEach() error {
	f.Logf("clear rbac in namespace")
	if err := f.deleteRBAC(); err != nil {
		return err
	}
	if err := f.deleteTestNamespace(); err != nil {
		return err
	}
	f.Logf("test namespace deleted")
	return nil
}
func (f *Framework) Logf(format string, a ...interface{}) {
	l := fmt.Sprintf(format, a...)
	Logf("namespace: %s %s", f.Namespace(), l)
}
func (f *Framework) Failf(format string, a ...interface{}) {
	l := fmt.Sprintf(format, a...)
	Failf("namespace: %s %s", f.Namespace(), l)
}
func (f *Framework) Namespace() string {
	return f.nameSpace
}
func (f *Framework) CreateRedisCluster(instance *redisv1alpha1.DistributedRedisCluster) error {
	f.Logf("Creating DistributedRedisCluster %s", instance.Name)
	result := &redisv1alpha1.DistributedRedisCluster{}
	err := f.Client.Get(context.TODO(), types.NamespacedName{
		Namespace: f.Namespace(),
		Name:      instance.Name,
	}, result)
	if errors.IsNotFound(err) {
		return f.Client.Create(context.TODO(), instance)
	}
	return err
}
func (f *Framework) CreateRedisClusterBackup(instance *redisv1alpha1.RedisClusterBackup) error {
	f.Logf("Creating RedisClusterBackup %s", instance.Name)
	result := &redisv1alpha1.RedisClusterBackup{}
	err := f.Client.Get(context.TODO(), types.NamespacedName{
		Namespace: f.Namespace(),
		Name:      instance.Name,
	}, result)
	if errors.IsNotFound(err) {
		return f.Client.Create(context.TODO(), instance)
	}
	return err
}
func (f *Framework) CreateRedisClusterPassword(name, password string) error {
	f.Logf("Creating DistributedRedisCluster secret %s", name)
	secret := &corev1.Secret{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: f.Namespace(),
		},
		StringData: map[string]string{
			passwordKey: password,
		},
		Type: "Opaque",
	}
	result := &corev1.Secret{}
	err := f.Client.Get(context.TODO(), types.NamespacedName{
		Namespace: f.Namespace(),
		Name:      name,
	}, result)
	if errors.IsNotFound(err) {
		return f.Client.Create(context.TODO(), secret)
	}
	return err
}