Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored create machine tests #345

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ test: manifests generate fmt vet envtest ## Run tests. Some test depend on Linux
integration-tests: ## Run integration tests against code. For dependencies, refer to the integration-test workflow.
go run github.com/onsi/ginkgo/v2/ginkgo run -r --label-filter="integration" -coverprofile cover.out

# .PHONY: integration-tests
Copy link
Contributor

@lukas016 lukas016 Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is duplicity. it can be deleted.

# integration-tests: ## Run integration tests against code. For dependencies, refer to the integration-test workflow.
# go run github.com/onsi/ginkgo/v2/ginkgo run -r --label-filter="integration" -coverprofile cover.out

##@ Documentation

.PHONY: start-docs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var _ = Describe("ListEvents", func() {
Machine: &iri.Machine{
Metadata: &irimeta.ObjectMetadata{
Labels: map[string]string{
"foo": "bar",
"event": "list",
},
},
Spec: &iri.MachineSpec{
Expand Down Expand Up @@ -73,7 +73,7 @@ var _ = Describe("ListEvents", func() {

By("listing the machine events with matching label and time filters")
resp, err = machineClient.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
LabelSelector: map[string]string{"foo": "bar"},
LabelSelector: map[string]string{"event": "list"},
EventsFromTime: time.Now().Add(-5 * time.Second).Unix(),
EventsToTime: time.Now().Unix(),
}})
Expand Down Expand Up @@ -101,7 +101,7 @@ var _ = Describe("ListEvents", func() {

By("listing the machine events with matching label filter and non matching time filter")
resp, err = machineClient.ListEvents(ctx, &iri.ListEventsRequest{Filter: &iri.EventFilter{
LabelSelector: map[string]string{machinepoolletv1alpha1.MachineUIDLabel: "foobar"},
LabelSelector: map[string]string{machinepoolletv1alpha1.MachineUIDLabel: "eventlist"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this correct?

EventsFromTime: time.Now().Add(-10 * time.Minute).Unix(),
EventsToTime: time.Now().Add(-5 * time.Minute).Unix(),
}})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ var (
libvirtConn *libvirt.Libvirt
machineClassesFile *os.File
tempDir string
cephMonitors = os.Getenv("CEPH_MONITORS")
cephImage = os.Getenv("CEPH_IMAGE")
cephUsername = os.Getenv("CEPH_USERNAME")
cephUserkey = os.Getenv("CEPH_USERKEY")
)

func TestServer(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,15 @@ var _ = Describe("Exec", func() {
Expect(createResp).NotTo(BeNil())

DeferCleanup(func(ctx SpecContext) {
Eventually(func(g Gomega) bool {
_, err := machineClient.DeleteMachine(ctx, &iri.DeleteMachineRequest{MachineId: createResp.Machine.Metadata.Id})
g.Expect(err).To(SatisfyAny(
BeNil(),
MatchError(ContainSubstring("NotFound")),
))
_, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(createResp.Machine.Metadata.Id))
return libvirt.IsNotFound(err)
}).Should(BeTrue())
_, err := machineClient.DeleteMachine(ctx, &iri.DeleteMachineRequest{MachineId: createResp.Machine.Metadata.Id})
Expect(err).To(SatisfyAny(
BeNil(),
MatchError(ContainSubstring("NotFound")),
))
})

By("ensuring domain and domain XML is created for machine")
var domain libvirt.Domain
Eventually(func() error {
domain, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(createResp.Machine.Metadata.Id))
return err
}).Should(Succeed())
domainXMLData, err := libvirtConn.DomainGetXMLDesc(domain, 0)
Expect(err).NotTo(HaveOccurred())
Expect(domainXMLData).NotTo(BeEmpty())

By("ensuring domain for machine is in running state")
Eventually(func(g Gomega) libvirt.DomainState {
domainState, _, err := libvirtConn.DomainGetState(domain, 0)
g.Expect(err).NotTo(HaveOccurred())
return libvirt.DomainState(domainState)
}).Should(Equal(libvirt.DomainRunning))
By("ensuring domain and domain XML is created and machine is running")
assertMachineIsRunning(createResp.Machine.Metadata.Id)

By("getting exec-url for the test machine")
execResp, err := machineClient.Exec(ctx, &iri.ExecRequest{MachineId: createResp.Machine.Metadata.Id})
Expand Down
197 changes: 197 additions & 0 deletions tests/integration/exec/server_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and IronCore contributors
// SPDX-License-Identifier: Apache-2.0

package server_test

import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"
"time"

"github.com/digitalocean/go-libvirt"
"github.com/digitalocean/go-libvirt/socket/dialers"
iriv1alpha1 "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1"
"github.com/ironcore-dev/ironcore/iri/remote/machine"
"github.com/ironcore-dev/libvirt-provider/api"
"github.com/ironcore-dev/libvirt-provider/cmd/libvirt-provider/app"
"github.com/ironcore-dev/libvirt-provider/internal/event/machineevent"
libvirtutils "github.com/ironcore-dev/libvirt-provider/internal/libvirt/utils"
"github.com/ironcore-dev/libvirt-provider/internal/networkinterfaceplugin"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)

const (
eventuallyTimeout = 80 * time.Second
pollingInterval = 50 * time.Millisecond
consistentlyDuration = 1 * time.Second
probeEveryInterval = 2 * time.Second

//Test graceful shutdown will be tested separately
resyncGarbageCollectorInterval = 5 * time.Second
resyncVolumeSizeInterval = 1 * time.Minute
baseURL = "http://localhost:20251"
streamingAddress = "127.0.0.1:20251"
healthCheckAddress = "127.0.0.1:20252"
metricsAddress = "" // disable metrics server for integration tests

machineClassx3xlarge = "x3-xlarge"
machineClassx2medium = "x2-medium"
)

var (
machineClient iriv1alpha1.MachineRuntimeClient
libvirtConn *libvirt.Libvirt
machineClassesFile *os.File
tempDir string
)

func TestServer(t *testing.T) {
SetDefaultConsistentlyPollingInterval(pollingInterval)
SetDefaultEventuallyPollingInterval(pollingInterval)
SetDefaultEventuallyTimeout(eventuallyTimeout)
SetDefaultConsistentlyDuration(consistentlyDuration)

RegisterFailHandler(Fail)
RunSpecs(t, "GRPC Server Suite", Label("integration"))
}

var _ = BeforeSuite(func() {
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true)))

By("starting the app")

machineClasses := []iriv1alpha1.MachineClass{
{
Name: machineClassx3xlarge,
Capabilities: &iriv1alpha1.MachineClassCapabilities{
CpuMillis: 4000,
MemoryBytes: 8589934592,
},
},
{
Name: machineClassx2medium,
Capabilities: &iriv1alpha1.MachineClassCapabilities{
CpuMillis: 2000,
MemoryBytes: 2147483648,
},
},
}
machineClassData, err := json.Marshal(machineClasses)
Expect(err).NotTo(HaveOccurred())
machineClassesFile, err = os.CreateTemp(GinkgoT().TempDir(), "machineclasses")
Expect(err).NotTo(HaveOccurred())
Expect(os.WriteFile(machineClassesFile.Name(), machineClassData, 0600)).To(Succeed())
DeferCleanup(machineClassesFile.Close)
DeferCleanup(os.Remove, machineClassesFile.Name())

pluginOpts := networkinterfaceplugin.NewDefaultOptions()
pluginOpts.PluginName = "isolated"

// tempDir = "/home/pcmil/libvirt-provider/temptest"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code from testing

tempDir = GinkgoT().TempDir()
Expect(os.Chmod(tempDir, 0730)).Should(Succeed())

opts := app.Options{
Address: filepath.Join(tempDir, "test.sock"),
BaseURL: baseURL,
PathSupportedMachineClasses: machineClassesFile.Name(),
RootDir: filepath.Join(tempDir, "libvirt-provider"),
StreamingAddress: streamingAddress,
Servers: app.ServersOptions{
Metrics: app.HTTPServerOptions{
Addr: metricsAddress,
},
HealthCheck: app.HTTPServerOptions{
Addr: healthCheckAddress,
},
},
Libvirt: app.LibvirtOptions{
Socket: "/var/run/libvirt/libvirt-sock",
URI: "qemu:///system",
PreferredDomainTypes: []string{"kvm", "qemu"},
PreferredMachineTypes: []string{"pc-q35", "pc-i440fx"},
Qcow2Type: "exec",
},
NicPlugin: pluginOpts,
// GCVMGracefulShutdownTimeout: gracefulShutdownTimeout,
ResyncIntervalGarbageCollector: resyncGarbageCollectorInterval,
ResyncIntervalVolumeSize: resyncVolumeSizeInterval,
GuestAgent: app.GuestAgentOption(api.GuestAgentNone),
MachineEventStore: machineevent.EventStoreOptions{
MachineEventMaxEvents: 5,
MachineEventTTL: 10 * time.Second,
MachineEventResyncInterval: 10 * time.Second,
},
}

srvCtx, cancel := context.WithCancel(context.Background())
DeferCleanup(cancel)

go func() {
defer GinkgoRecover()
Expect(app.Run(srvCtx, opts)).To(Succeed())
}()

Eventually(func() error {
return isSocketAvailable(opts.Address)
}).WithTimeout(30 * time.Second).WithPolling(500 * time.Millisecond).Should(Succeed())

address, err := machine.GetAddressWithTimeout(3*time.Second, fmt.Sprintf("unix://%s", opts.Address))
Expect(err).NotTo(HaveOccurred())

gconn, err := grpc.NewClient(address, grpc.WithTransportCredentials(insecure.NewCredentials()))
Expect(err).NotTo(HaveOccurred())
DeferCleanup(gconn.Close)

machineClient = iriv1alpha1.NewMachineRuntimeClient(gconn)

c := dialers.NewLocal()
libvirtConn = libvirt.NewWithDialer(c)
Expect(libvirtConn.Connect()).To(Succeed())
Expect(libvirtConn.IsConnected(), BeTrue())
DeferCleanup(libvirtConn.ConnectClose)
})

func isSocketAvailable(socketPath string) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is defined multiple times. Probably whole server_suite_test.go were copied. It has to be refactor.

fileInfo, err := os.Stat(socketPath)
if err != nil {
return err
}
if fileInfo.Mode()&os.ModeSocket != 0 {
return nil
}
return fmt.Errorf("socket %s is not available", socketPath)
}

func assertMachineIsRunning(machineID string) libvirt.Domain {
GinkgoHelper()
By("ensuring domain and domain XML is created for machine")
var domain libvirt.Domain

Eventually(func() (err error) {
domain, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(machineID))
return err
}).Should(Succeed())

domainXMLData, err := libvirtConn.DomainGetXMLDesc(domain, 0)
Expect(err).NotTo(HaveOccurred())
Expect(domainXMLData).NotTo(BeEmpty())

By("ensuring domain for machine is in running state")
Eventually(func(g Gomega) libvirt.DomainState {
domainState, _, err := libvirtConn.DomainGetState(domain, 0)
g.Expect(err).NotTo(HaveOccurred())
return libvirt.DomainState(domainState)
}).Should(Equal(libvirt.DomainRunning))

return domain
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
package server_test

import (
"github.com/digitalocean/go-libvirt"
iri "github.com/ironcore-dev/ironcore/iri/apis/machine/v1alpha1"
irimeta "github.com/ironcore-dev/ironcore/iri/apis/meta/v1alpha1"
libvirtutils "github.com/ironcore-dev/libvirt-provider/internal/libvirt/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
Expand All @@ -20,8 +18,7 @@ var _ = Describe("UpdateMachineAnnotations", func() {
Machine: &iri.Machine{
Metadata: &irimeta.ObjectMetadata{
Labels: map[string]string{
"machinepoolletv1alpha1.MachineUIDLabel": "foolabel",
},
"machine": "annotations"},
},
Spec: &iri.MachineSpec{
Power: iri.Power_POWER_ON,
Expand All @@ -35,34 +32,12 @@ var _ = Describe("UpdateMachineAnnotations", func() {
Expect(err).NotTo(HaveOccurred())
Expect(createResp).NotTo(BeNil())

DeferCleanup(func(ctx SpecContext) {
Eventually(func(g Gomega) bool {
_, err := machineClient.DeleteMachine(ctx, &iri.DeleteMachineRequest{MachineId: createResp.Machine.Metadata.Id})
g.Expect(err).To(SatisfyAny(
BeNil(),
MatchError(ContainSubstring("NotFound")),
))
_, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(createResp.Machine.Metadata.Id))
return libvirt.IsNotFound(err)
}).Should(BeTrue())
DeferCleanup(machineClient.DeleteMachine, &iri.DeleteMachineRequest{
MachineId: createResp.Machine.Metadata.Id,
})

By("ensuring domain and domain XML is created for machine")
var domain libvirt.Domain
Eventually(func() error {
domain, err = libvirtConn.DomainLookupByUUID(libvirtutils.UUIDStringToBytes(createResp.Machine.Metadata.Id))
return err
}).Should(Succeed())
domainXMLData, err := libvirtConn.DomainGetXMLDesc(domain, 0)
Expect(err).NotTo(HaveOccurred())
Expect(domainXMLData).NotTo(BeEmpty())

By("ensuring domain for machine is in running state")
Eventually(func(g Gomega) libvirt.DomainState {
domainState, _, err := libvirtConn.DomainGetState(domain, 0)
g.Expect(err).NotTo(HaveOccurred())
return libvirt.DomainState(domainState)
}).Should(Equal(libvirt.DomainRunning))
By("ensuring domain and domain XML is created and machine is running")
assertMachineIsRunning(createResp.Machine.Metadata.Id)

By("updating machine annotations")
_, err = machineClient.UpdateMachineAnnotations(ctx, &iri.UpdateMachineAnnotationsRequest{
Expand Down
Loading
Loading