182 lines
7.1 KiB
Go
182 lines
7.1 KiB
Go
package basic
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
v1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/util/intstr"
|
|
|
|
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
|
|
|
|
. "github.com/vmware-tanzu/velero/test/e2e"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/test"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/k8s"
|
|
. "github.com/vmware-tanzu/velero/test/e2e/util/velero"
|
|
)
|
|
|
|
type NodePort struct {
|
|
TestCase
|
|
replica int32
|
|
labels map[string]string
|
|
containers *[]v1.Container
|
|
serviceName string
|
|
serviceSpec *v1.ServiceSpec
|
|
nodePort int32
|
|
namespaceToCollision string
|
|
namespace string
|
|
}
|
|
|
|
const NodeportBaseName string = "nodeport-"
|
|
|
|
var NodePortTest func() = TestFunc(&NodePort{namespace: NodeportBaseName + "1", TestCase: TestCase{NSBaseName: NodeportBaseName}})
|
|
|
|
func (n *NodePort) Init() error {
|
|
n.VeleroCfg = VeleroCfg
|
|
n.Client = *n.VeleroCfg.ClientToInstallVelero
|
|
n.NSBaseName = NodeportBaseName
|
|
n.TestMsg = &TestMSG{
|
|
Desc: fmt.Sprintf("Nodeport preservation"),
|
|
FailedMSG: "Failed to restore with nodeport preservation",
|
|
Text: fmt.Sprintf("Nodeport can be preserved or omit during restore"),
|
|
}
|
|
n.BackupName = "backup-nodeport-" + UUIDgen.String()
|
|
n.RestoreName = "restore-" + UUIDgen.String()
|
|
n.serviceName = "nginx-service-" + UUIDgen.String()
|
|
n.labels = map[string]string{"app": "nginx"}
|
|
return nil
|
|
}
|
|
|
|
func (n *NodePort) StartRun() error {
|
|
n.BackupArgs = []string{
|
|
"create", "--namespace", VeleroCfg.VeleroNamespace, "backup", n.BackupName,
|
|
"--include-namespaces", n.namespace, "--wait",
|
|
}
|
|
n.RestoreArgs = []string{
|
|
"create", "--namespace", VeleroCfg.VeleroNamespace, "restore",
|
|
"--from-backup", n.BackupName,
|
|
"--wait",
|
|
}
|
|
return nil
|
|
}
|
|
func (n *NodePort) CreateResources() error {
|
|
n.Ctx, _ = context.WithTimeout(context.Background(), 60*time.Minute)
|
|
|
|
By(fmt.Sprintf("Creating service %s in namespaces %s ......\n", n.serviceName, n.namespace), func() {
|
|
Expect(CreateNamespace(n.Ctx, n.Client, n.namespace)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", n.namespace))
|
|
Expect(createServiceWithNodeport(n.Ctx, n.Client, n.namespace, n.serviceName, n.labels, 0)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
|
|
service, err := GetService(n.Ctx, n.Client, n.namespace, n.serviceName)
|
|
Expect(err).To(Succeed())
|
|
Expect(len(service.Spec.Ports)).To(Equal(1))
|
|
n.nodePort = service.Spec.Ports[0].NodePort
|
|
_, err = GetAllService(n.Ctx)
|
|
Expect(err).To(Succeed(), "fail to get service")
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (n *NodePort) Destroy() error {
|
|
By(fmt.Sprintf("Start to destroy namespace %s......", n.NSBaseName), func() {
|
|
Expect(CleanupNamespacesWithPoll(n.Ctx, n.Client, NodeportBaseName)).To(Succeed(),
|
|
fmt.Sprintf("Failed to delete namespace %s", n.NSBaseName))
|
|
Expect(WaitForServiceDelete(n.Client, n.namespace, n.serviceName, false)).To(Succeed(), "fail to delete service")
|
|
_, err := GetAllService(n.Ctx)
|
|
Expect(err).To(Succeed(), "fail to get service")
|
|
})
|
|
|
|
n.namespaceToCollision = NodeportBaseName + "tmp"
|
|
By(fmt.Sprintf("Creating a new service which has the same nodeport as backed up service has in a new namespaces for nodeport collision ...%s\n", n.namespaceToCollision), func() {
|
|
Expect(CreateNamespace(n.Ctx, n.Client, n.namespaceToCollision)).To(Succeed(), fmt.Sprintf("Failed to create namespace %s", n.namespaceToCollision))
|
|
Expect(createServiceWithNodeport(n.Ctx, n.Client, n.namespaceToCollision, n.serviceName, n.labels, n.nodePort)).To(Succeed(), fmt.Sprintf("Failed to create service %s", n.serviceName))
|
|
_, err := GetAllService(n.Ctx)
|
|
Expect(err).To(Succeed(), "fail to get service")
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (n *NodePort) Restore() error {
|
|
index := 4
|
|
restoreName1 := n.RestoreName + "-1"
|
|
restoreName2 := restoreName1 + "-1"
|
|
|
|
args := n.RestoreArgs
|
|
args = append(args[:index], append([]string{n.RestoreName}, args[index:]...)...)
|
|
args = append(args, "--preserve-nodeports=true")
|
|
By(fmt.Sprintf("Start to restore %s with nodeports preservation when port %d is already occupied by other service", n.RestoreName, n.nodePort), func() {
|
|
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI,
|
|
n.VeleroCfg.VeleroNamespace, n.RestoreName,
|
|
args, velerov1api.RestorePhasePartiallyFailed)).To(
|
|
Succeed(),
|
|
func() string {
|
|
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI,
|
|
n.VeleroCfg.VeleroNamespace, "", n.RestoreName)
|
|
return "Fail to restore workload"
|
|
})
|
|
})
|
|
|
|
args = n.RestoreArgs
|
|
args = append(args[:index], append([]string{restoreName1}, args[index:]...)...)
|
|
args = append(args, "--preserve-nodeports=false")
|
|
By(fmt.Sprintf("Start to restore %s without nodeports preservation ......", restoreName1), func() {
|
|
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
|
|
restoreName1, args, velerov1api.RestorePhaseCompleted)).To(Succeed(), func() string {
|
|
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace, "", restoreName1)
|
|
return "Fail to restore workload"
|
|
})
|
|
})
|
|
|
|
By(fmt.Sprintf("Delete service %s by deleting namespace %s", n.serviceName, n.namespace), func() {
|
|
service, err := GetService(n.Ctx, n.Client, n.namespace, n.serviceName)
|
|
Expect(err).To(Succeed())
|
|
Expect(len(service.Spec.Ports)).To(Equal(1))
|
|
fmt.Println(service.Spec.Ports)
|
|
Expect(DeleteNamespace(n.Ctx, n.Client, n.namespace, true)).To(Succeed())
|
|
})
|
|
|
|
By(fmt.Sprintf("Start to delete service %s in namespace %s ......", n.serviceName, n.namespaceToCollision), func() {
|
|
Expect(WaitForServiceDelete(n.Client, n.namespaceToCollision, n.serviceName, true)).To(Succeed(), "fail to delete service")
|
|
_, err := GetAllService(n.Ctx)
|
|
Expect(err).To(Succeed(), "fail to get service")
|
|
})
|
|
|
|
args = n.RestoreArgs
|
|
args = append(args[:index], append([]string{restoreName2}, args[index:]...)...)
|
|
args = append(args, "--preserve-nodeports=true")
|
|
By(fmt.Sprintf("Start to restore %s with nodeports preservation ......", restoreName2), func() {
|
|
Expect(VeleroRestoreExec(n.Ctx, n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace,
|
|
restoreName2, args, velerov1api.RestorePhaseCompleted)).To(Succeed(), func() string {
|
|
RunDebug(context.Background(), n.VeleroCfg.VeleroCLI, n.VeleroCfg.VeleroNamespace, "", restoreName2)
|
|
return "Fail to restore workload"
|
|
})
|
|
})
|
|
|
|
By(fmt.Sprintf("Verify service %s was restore successfully with the origin nodeport.", n.namespace), func() {
|
|
service, err := GetService(n.Ctx, n.Client, n.namespace, n.serviceName)
|
|
Expect(err).To(Succeed())
|
|
Expect(len(service.Spec.Ports)).To(Equal(1))
|
|
Expect(service.Spec.Ports[0].NodePort).To(Equal(n.nodePort))
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func createServiceWithNodeport(ctx context.Context, client TestClient, namespace string,
|
|
service string, labels map[string]string, nodePort int32) error {
|
|
serviceSpec := &v1.ServiceSpec{
|
|
Ports: []v1.ServicePort{
|
|
{
|
|
Port: 80,
|
|
TargetPort: intstr.IntOrString{IntVal: 80},
|
|
NodePort: nodePort,
|
|
},
|
|
},
|
|
Selector: nil,
|
|
Type: v1.ServiceTypeLoadBalancer,
|
|
}
|
|
return CreateService(ctx, client, namespace, service, labels, serviceSpec)
|
|
}
|