Skip to content

Commit

Permalink
Added API functionality + testing to get Firecracker Version
Browse files Browse the repository at this point in the history
Signed-off-by: David Son <[email protected]>
  • Loading branch information
sondavidb committed Jun 17, 2022
1 parent f0a967e commit a1fdd61
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
16 changes: 16 additions & 0 deletions firecracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ func NewClient(socketPath string, logger *logrus.Entry, debug bool, opts ...Clie
return c
}

// GetFirecrackerVersionOpt is a functional option to be used for the
// GetFirecrackerVersion API in setting any additional optional fields.
type GetFirecrackerVersionOpt func(*ops.GetFirecrackerVersionParams)

// GetFirecrackerVersion is a wrapper for the swagger generated client to make
// calling of the API easier.
func (f *Client) GetFirecrackerVersion(ctx context.Context, opts ...GetFirecrackerVersionOpt) (*ops.GetFirecrackerVersionOK, error) {
params := ops.NewGetFirecrackerVersionParams()
params.SetContext(ctx)
for _, opt := range opts {
opt(params)
}

return f.client.Operations.GetFirecrackerVersion(params)
}

// PutLoggerOpt is a functional option to be used for the PutLogger API in
// setting any additional optional fields.
type PutLoggerOpt func(*ops.PutLoggerParams)
Expand Down
36 changes: 36 additions & 0 deletions firecracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
"github.com/firecracker-microvm/firecracker-go-sdk/fctesting"
"github.com/stretchr/testify/require"
)

func TestClient(t *testing.T) {
Expand Down Expand Up @@ -64,3 +65,38 @@ func TestClient(t *testing.T) {
t.Errorf("unexpected error on PutGuestDriveByID, %v", err)
}
}

func TestGetFirecrackerVersion(t *testing.T) {
if testing.Short() {
t.Skip()
}

ctx := context.Background()
socketpath, cleanup := makeSocketPath(t)
defer cleanup()

cmd := VMCommandBuilder{}.
WithBin(getFirecrackerBinaryPath()).
WithSocketPath(socketpath).
Build(ctx)

if err := cmd.Start(); err != nil {
t.Fatalf("failed to start firecracker vmm: %v", err)
}

defer func() {
if err := cmd.Process.Kill(); err != nil {
t.Errorf("failed to kill process: %v", err)
}
}()

client := NewClient(socketpath, fctesting.NewLogEntry(t), true)
deadlineCtx, deadlineCancel := context.WithTimeout(ctx, 250*time.Millisecond)
defer deadlineCancel()
if err := waitForAliveVMM(deadlineCtx, client); err != nil {
t.Fatal(err)
}

_, err := client.GetFirecrackerVersion(ctx)
require.NoError(t, err, "failed to get firecracker version")
}
12 changes: 12 additions & 0 deletions machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,18 @@ func (m *Machine) Wait(ctx context.Context) error {
}
}

// GetFirecrackerVersion gets the machine's firecracker version and returns it
func (m *Machine) GetFirecrackerVersion(ctx context.Context) (string, error) {
resp, err := m.client.GetFirecrackerVersion(ctx)
if err != nil {
m.logger.Errorf("Getting firecracker version: %s", err)
return "", err
}

m.logger.Debug("GetFirecrackerVersion successful")
return *resp.Payload.FirecrackerVersion, nil
}

func (m *Machine) setupNetwork(ctx context.Context) error {
err, cleanupFuncs := m.Cfg.NetworkInterfaces.setupNetwork(ctx, m.Cfg.VMID, m.Cfg.NetNS, m.logger)
m.cleanupFuncs = append(m.cleanupFuncs, cleanupFuncs...)
Expand Down
44 changes: 44 additions & 0 deletions machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
"context"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"os/exec"
"os/signal"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -366,6 +368,7 @@ func TestMicroVMExecution(t *testing.T) {
}

t.Run("TestCreateMachine", func(t *testing.T) { testCreateMachine(ctx, t, m) })
t.Run("TestGetFirecrackerVersion", func(t *testing.T) { testGetFirecrackerVersion(ctx, t, m) })
t.Run("TestMachineConfigApplication", func(t *testing.T) { testMachineConfigApplication(ctx, t, m, cfg) })
t.Run("TestCreateBootSource", func(t *testing.T) { testCreateBootSource(ctx, t, m, vmlinuxPath) })
t.Run("TestCreateNetworkInterface", func(t *testing.T) { testCreateNetworkInterfaceByID(ctx, t, m) })
Expand Down Expand Up @@ -620,6 +623,47 @@ func testCreateMachine(ctx context.Context, t *testing.T, m *Machine) {
}
}

func parseVersionFromStdout(stdout []byte) (string, error) {
pattern := regexp.MustCompile(`Firecracker v(?P<version>[0-9]\.[0-9]\.[0-9]-?.*)`)
groupNames := pattern.SubexpNames()
matches := pattern.FindStringSubmatch(string(stdout))

for i, name := range groupNames {
if name == "version" {
return matches[i], nil
}
}

return "", fmt.Errorf("Unable to parse firecracker version from stdout (Output: %s)",
stdout)
}

func getFirecrackerVersion() (string, error) {
cmd := exec.Command(getFirecrackerBinaryPath(), "--version")
stdout, err := cmd.Output()
if err != nil {
return "", err
}
return parseVersionFromStdout(stdout)
}

func testGetFirecrackerVersion(ctx context.Context, t *testing.T, m *Machine) {
version, err := m.GetFirecrackerVersion(ctx)

if err != nil {
t.Errorf("GetFirecrackerVersion: %v", err)
}

expectedVersion, err := getFirecrackerVersion()
if err != nil {
t.Errorf("GetFirecrackerVersion: %v", err)
}

assert.Equalf(t, expectedVersion, version,
"GetFirecrackerVersion: Expected version %v, got version %v",
expectedVersion, version)
}

func testMachineConfigApplication(ctx context.Context, t *testing.T, m *Machine, expectedValues Config) {
assert.Equal(t, expectedValues.MachineCfg.VcpuCount,
m.machineConfig.VcpuCount, "CPU count should be equal")
Expand Down

0 comments on commit a1fdd61

Please sign in to comment.