Skip to content

Commit a1fdd61

Browse files
committed
Added API functionality + testing to get Firecracker Version
Signed-off-by: David Son <davbson@amazon.com>
1 parent f0a967e commit a1fdd61

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed

firecracker.go

+16
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,22 @@ func NewClient(socketPath string, logger *logrus.Entry, debug bool, opts ...Clie
7575
return c
7676
}
7777

78+
// GetFirecrackerVersionOpt is a functional option to be used for the
79+
// GetFirecrackerVersion API in setting any additional optional fields.
80+
type GetFirecrackerVersionOpt func(*ops.GetFirecrackerVersionParams)
81+
82+
// GetFirecrackerVersion is a wrapper for the swagger generated client to make
83+
// calling of the API easier.
84+
func (f *Client) GetFirecrackerVersion(ctx context.Context, opts ...GetFirecrackerVersionOpt) (*ops.GetFirecrackerVersionOK, error) {
85+
params := ops.NewGetFirecrackerVersionParams()
86+
params.SetContext(ctx)
87+
for _, opt := range opts {
88+
opt(params)
89+
}
90+
91+
return f.client.Operations.GetFirecrackerVersion(params)
92+
}
93+
7894
// PutLoggerOpt is a functional option to be used for the PutLogger API in
7995
// setting any additional optional fields.
8096
type PutLoggerOpt func(*ops.PutLoggerParams)

firecracker_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
2222
"github.com/firecracker-microvm/firecracker-go-sdk/fctesting"
23+
"github.com/stretchr/testify/require"
2324
)
2425

2526
func TestClient(t *testing.T) {
@@ -64,3 +65,38 @@ func TestClient(t *testing.T) {
6465
t.Errorf("unexpected error on PutGuestDriveByID, %v", err)
6566
}
6667
}
68+
69+
func TestGetFirecrackerVersion(t *testing.T) {
70+
if testing.Short() {
71+
t.Skip()
72+
}
73+
74+
ctx := context.Background()
75+
socketpath, cleanup := makeSocketPath(t)
76+
defer cleanup()
77+
78+
cmd := VMCommandBuilder{}.
79+
WithBin(getFirecrackerBinaryPath()).
80+
WithSocketPath(socketpath).
81+
Build(ctx)
82+
83+
if err := cmd.Start(); err != nil {
84+
t.Fatalf("failed to start firecracker vmm: %v", err)
85+
}
86+
87+
defer func() {
88+
if err := cmd.Process.Kill(); err != nil {
89+
t.Errorf("failed to kill process: %v", err)
90+
}
91+
}()
92+
93+
client := NewClient(socketpath, fctesting.NewLogEntry(t), true)
94+
deadlineCtx, deadlineCancel := context.WithTimeout(ctx, 250*time.Millisecond)
95+
defer deadlineCancel()
96+
if err := waitForAliveVMM(deadlineCtx, client); err != nil {
97+
t.Fatal(err)
98+
}
99+
100+
_, err := client.GetFirecrackerVersion(ctx)
101+
require.NoError(t, err, "failed to get firecracker version")
102+
}

machine.go

+12
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,18 @@ func (m *Machine) Wait(ctx context.Context) error {
429429
}
430430
}
431431

432+
// GetFirecrackerVersion gets the machine's firecracker version and returns it
433+
func (m *Machine) GetFirecrackerVersion(ctx context.Context) (string, error) {
434+
resp, err := m.client.GetFirecrackerVersion(ctx)
435+
if err != nil {
436+
m.logger.Errorf("Getting firecracker version: %s", err)
437+
return "", err
438+
}
439+
440+
m.logger.Debug("GetFirecrackerVersion successful")
441+
return *resp.Payload.FirecrackerVersion, nil
442+
}
443+
432444
func (m *Machine) setupNetwork(ctx context.Context) error {
433445
err, cleanupFuncs := m.Cfg.NetworkInterfaces.setupNetwork(ctx, m.Cfg.VMID, m.Cfg.NetNS, m.logger)
434446
m.cleanupFuncs = append(m.cleanupFuncs, cleanupFuncs...)

machine_test.go

+44
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ import (
1818
"context"
1919
"errors"
2020
"flag"
21+
"fmt"
2122
"io"
2223
"io/ioutil"
2324
"net"
2425
"os"
2526
"os/exec"
2627
"os/signal"
2728
"path/filepath"
29+
"regexp"
2830
"strconv"
2931
"strings"
3032
"sync"
@@ -366,6 +368,7 @@ func TestMicroVMExecution(t *testing.T) {
366368
}
367369

368370
t.Run("TestCreateMachine", func(t *testing.T) { testCreateMachine(ctx, t, m) })
371+
t.Run("TestGetFirecrackerVersion", func(t *testing.T) { testGetFirecrackerVersion(ctx, t, m) })
369372
t.Run("TestMachineConfigApplication", func(t *testing.T) { testMachineConfigApplication(ctx, t, m, cfg) })
370373
t.Run("TestCreateBootSource", func(t *testing.T) { testCreateBootSource(ctx, t, m, vmlinuxPath) })
371374
t.Run("TestCreateNetworkInterface", func(t *testing.T) { testCreateNetworkInterfaceByID(ctx, t, m) })
@@ -620,6 +623,47 @@ func testCreateMachine(ctx context.Context, t *testing.T, m *Machine) {
620623
}
621624
}
622625

626+
func parseVersionFromStdout(stdout []byte) (string, error) {
627+
pattern := regexp.MustCompile(`Firecracker v(?P<version>[0-9]\.[0-9]\.[0-9]-?.*)`)
628+
groupNames := pattern.SubexpNames()
629+
matches := pattern.FindStringSubmatch(string(stdout))
630+
631+
for i, name := range groupNames {
632+
if name == "version" {
633+
return matches[i], nil
634+
}
635+
}
636+
637+
return "", fmt.Errorf("Unable to parse firecracker version from stdout (Output: %s)",
638+
stdout)
639+
}
640+
641+
func getFirecrackerVersion() (string, error) {
642+
cmd := exec.Command(getFirecrackerBinaryPath(), "--version")
643+
stdout, err := cmd.Output()
644+
if err != nil {
645+
return "", err
646+
}
647+
return parseVersionFromStdout(stdout)
648+
}
649+
650+
func testGetFirecrackerVersion(ctx context.Context, t *testing.T, m *Machine) {
651+
version, err := m.GetFirecrackerVersion(ctx)
652+
653+
if err != nil {
654+
t.Errorf("GetFirecrackerVersion: %v", err)
655+
}
656+
657+
expectedVersion, err := getFirecrackerVersion()
658+
if err != nil {
659+
t.Errorf("GetFirecrackerVersion: %v", err)
660+
}
661+
662+
assert.Equalf(t, expectedVersion, version,
663+
"GetFirecrackerVersion: Expected version %v, got version %v",
664+
expectedVersion, version)
665+
}
666+
623667
func testMachineConfigApplication(ctx context.Context, t *testing.T, m *Machine, expectedValues Config) {
624668
assert.Equal(t, expectedValues.MachineCfg.VcpuCount,
625669
m.machineConfig.VcpuCount, "CPU count should be equal")

0 commit comments

Comments
 (0)