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

feat: Add more tests & fix issues found by them #1879

Open
wants to merge 38 commits into
base: staging
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
b227542
feat(test): Add tests for 'cloud instance get'
craciunoiuc Sep 5, 2024
b8376b2
feat(test): Add tests for 'cloud instance list'
craciunoiuc Sep 5, 2024
b447662
feat(test): Add tests for 'cloud instance logs'
craciunoiuc Sep 5, 2024
c7d5812
feat(test): Add tests for 'cloud instance remove'
craciunoiuc Sep 5, 2024
5abe51a
feat(test): Add tests for 'cloud instance start'
craciunoiuc Sep 5, 2024
7d0ad35
feat(test): Add tests for 'cloud instance stop'
craciunoiuc Sep 5, 2024
3e50436
feat(test): Rename test suite to 'cloud'
craciunoiuc Sep 5, 2024
a441f08
fix(test): Remove instance after running test
craciunoiuc Sep 5, 2024
2642972
fix(cloud): Allow no arguments to use '--all'
craciunoiuc Sep 5, 2024
ca103b0
fix(cloud): Remove unused flag
craciunoiuc Sep 5, 2024
e4e3161
fix(cloud): Swap flag descriptions
craciunoiuc Sep 5, 2024
125fecf
feat(test): Add tests for 'cloud quotas'
craciunoiuc Sep 13, 2024
45dd5db
feat(test): Add tests for 'cloud metro list'
craciunoiuc Sep 13, 2024
480c09f
feat(test): Add tests for 'cloud volume attach'
craciunoiuc Sep 13, 2024
97c4221
feat(test): Add tests for 'cloud volume detach'
craciunoiuc Sep 13, 2024
4243f3b
feat(test): Add tests for 'cloud volume create'
craciunoiuc Sep 13, 2024
4a6a3f0
feat(test): Add tests for 'cloud volume delete'
craciunoiuc Sep 13, 2024
b40cf45
feat(test): Add tests for 'cloud volume get'
craciunoiuc Sep 13, 2024
18b58bb
feat(test): Add tests for 'cloud volume list'
craciunoiuc Sep 13, 2024
8c6564b
fix(cloud): Allow multiple volume arguments
craciunoiuc Sep 13, 2024
1cc0ef0
fix(cloud): Remove unused flag from volume listing
craciunoiuc Sep 13, 2024
968ee23
fix(test): Increase minimum volume size in tests
craciunoiuc Sep 17, 2024
065b7a3
fix(cloud): Correctly show output depending on log type
craciunoiuc Sep 17, 2024
f13d21b
feat(test): Add tests for 'cloud volume import'
craciunoiuc Sep 17, 2024
8903b43
fix(cloud): Add state check on importing to allow volume detach
craciunoiuc Sep 18, 2024
66001bd
feat(test): Add tests for 'cloud service create'
craciunoiuc Sep 18, 2024
f8c6669
feat(test): Add tests for 'cloud service list'
craciunoiuc Sep 19, 2024
75b0da6
feat(test): Add tests for 'cloud service get'
craciunoiuc Sep 19, 2024
cac3b12
feat(test): Add tests for 'cloud service remove'
craciunoiuc Sep 19, 2024
ac9d5f3
fix(cloud): Remove unused flag from service listing
craciunoiuc Sep 19, 2024
2478d37
fix(cloud): Allow additional arguments to service getting
craciunoiuc Sep 19, 2024
96b1bdb
fix(cloud): Warn instead of failing when removing
craciunoiuc Sep 19, 2024
6e922d2
feat(test): Add tests for 'cloud tunnel'
craciunoiuc Sep 19, 2024
a6d9f94
feat(test): Add tests for 'cloud scale init'
craciunoiuc Sep 20, 2024
613db30
feat(test): Add tests for 'cloud scale add'
craciunoiuc Sep 20, 2024
6755353
feat(test): Add tests for 'cloud scale remove'
craciunoiuc Sep 20, 2024
8fd6011
feat(test): Add tests for 'cloud scale reset'
craciunoiuc Sep 20, 2024
13c68c5
feat(test): Add tests for 'cloud scale get'
craciunoiuc Sep 20, 2024
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
1 change: 0 additions & 1 deletion internal/cli/kraft/cloud/instance/logs/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ type LogOptions struct {
Follow bool `local:"true" long:"follow" short:"f" usage:"Follow the logs of the instance every half second" default:"false"`
Metro string `noattribute:"true"`
NoPrefix bool `long:"no-prefix" usage:"When logging multiple machines, do not prefix each log line with the name"`
Prefix string `local:"true" long:"prefix" short:"p" usage:"Prefix the logs with a given string"`
Tail int `local:"true" long:"tail" short:"n" usage:"Show the last given lines from the logs" default:"-1"`
Token string `noattribute:"true"`
}
Expand Down
2 changes: 1 addition & 1 deletion internal/cli/kraft/cloud/instance/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&StartOptions{}, cobra.Command{
Short: "Start instances",
Use: "start [FLAGS] [UUID|NAME [UUID|NAME]...]",
Args: cobra.MinimumNArgs(1),
Args: cobra.ArbitraryArgs,
Aliases: []string{"str"},
Example: heredoc.Doc(`
# Start an instance by UUID
Expand Down
4 changes: 2 additions & 2 deletions internal/cli/kraft/cloud/instance/stop/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
type StopOptions struct {
Auth *config.AuthConfig `noattribute:"true"`
Client kraftcloud.KraftCloud `noattribute:"true"`
Wait time.Duration `local:"true" long:"wait" short:"w" usage:"Time to wait for the instance to drain all connections before it is stopped (ms/s/m/h)"`
DrainTimeout time.Duration `local:"true" long:"drain-timeout" short:"d" usage:"Timeout for the instance to stop (ms/s/m/h)"`
Wait time.Duration `local:"true" long:"wait" short:"w" usage:"Timeout for the instance to stop (ms/s/m/h)"`
DrainTimeout time.Duration `local:"true" long:"drain-timeout" short:"d" usage:"Time to wait for the instance to drain all connections before it is stopped (ms/s/m/h)"`
All bool `long:"all" short:"a" usage:"Stop all instances"`
Force bool `long:"force" short:"f" usage:"Force stop the instance(s)"`
Metro string `noattribute:"true"`
Expand Down
9 changes: 6 additions & 3 deletions internal/cli/kraft/cloud/service/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&GetOptions{}, cobra.Command{
Short: "Retrieve the state of services",
Use: "get [FLAGS] UUID|NAME",
Args: cobra.ExactArgs(1),
Args: cobra.MinimumNArgs(1),
Aliases: []string{"gt"},
Example: heredoc.Doc(`
# Retrieve information about a kraftcloud service
$ kraft cloud service get fd1684ea-7970-4994-92d6-61dcc7905f2b

# Retrieve information about a kraftcloud service
$ kraft cloud service get my-service

# Retrieve information about two unikraft cloud services
$ kraft cloud service get my-service-1 my-service-2
`),
Annotations: map[string]string{
cmdfactory.AnnotationHelpGroup: "kraftcloud-svc",
Expand Down Expand Up @@ -82,9 +85,9 @@ func (opts *GetOptions) Run(ctx context.Context, args []string) error {
kraftcloud.WithToken(config.GetKraftCloudTokenAuthConfig(*auth)),
)

resp, err := client.WithMetro(opts.metro).Get(ctx, args[0])
resp, err := client.WithMetro(opts.metro).Get(ctx, args...)
if err != nil {
return fmt.Errorf("could not get service %s: %w", args[0], err)
return fmt.Errorf("could not get services: %w", err)
}

return utils.PrintServices(ctx, opts.Output, *resp)
Expand Down
4 changes: 0 additions & 4 deletions internal/cli/kraft/cloud/service/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

type ListOptions struct {
Output string `long:"output" short:"o" usage:"Set output format. Options: table,yaml,json,list" default:"table"`
Watch bool `long:"watch" short:"w" usage:"After listing watch for changes."`

metro string
token string
Expand All @@ -39,9 +38,6 @@ func NewCmd() *cobra.Command {

# List all service in your account in full table format.
$ kraft cloud service list -o full

# List all service in your account and watch for changes.
$ kraft cloud service list -w
`),
Annotations: map[string]string{
cmdfactory.AnnotationHelpGroup: "kraftcloud-svc",
Expand Down
11 changes: 10 additions & 1 deletion internal/cli/kraft/cloud/service/remove/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,17 @@ func Remove(ctx context.Context, opts *RemoveOptions, args ...string) error {
}

args = []string{}
attachedInstances := []string{}
for _, sgItem := range sgList {
args = append(args, sgItem.Name)
if sgItem.Instances != nil && len(sgItem.Instances) > 0 {
attachedInstances = append(attachedInstances, sgItem.Name)
} else {
args = append(args, sgItem.Name)
}
}

if len(attachedInstances) > 0 {
log.G(ctx).Warnf("ignoring %d service(s) as instances are attached: %v", len(attachedInstances), attachedInstances)
}
}

Expand Down
6 changes: 3 additions & 3 deletions internal/cli/kraft/cloud/volume/get/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&GetOptions{}, cobra.Command{
Short: "Retrieve the state of persistent volumes",
Use: "get [FLAGS] UUID|NAME",
Args: cobra.ExactArgs(1),
Args: cobra.MinimumNArgs(1),
Aliases: []string{"gt"},
Example: heredoc.Doc(`
# Retrieve information about a kraftcloud volume by UUID
Expand Down Expand Up @@ -82,9 +82,9 @@ func (opts *GetOptions) Run(ctx context.Context, args []string) error {
kraftcloud.WithToken(config.GetKraftCloudTokenAuthConfig(*auth)),
)

resp, err := client.WithMetro(opts.metro).Get(ctx, args[0])
resp, err := client.WithMetro(opts.metro).Get(ctx, args...)
if err != nil {
return fmt.Errorf("could not get volume %s: %w", args[0], err)
return fmt.Errorf("could not get volume %v: %w", args, err)
}

return utils.PrintVolumes(ctx, opts.Output, *resp)
Expand Down
120 changes: 85 additions & 35 deletions internal/cli/kraft/cloud/volume/import/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ import (
"os"
"strconv"
"strings"
"time"

"github.com/MakeNowJust/heredoc"
"github.com/dustin/go-humanize"
"github.com/spf13/cobra"

kraftcloud "sdk.kraft.cloud"
ukcinstances "sdk.kraft.cloud/instances"

"kraftkit.sh/cmdfactory"
"kraftkit.sh/config"
"kraftkit.sh/internal/cli/kraft/cloud/utils"
"kraftkit.sh/internal/fancymap"
"kraftkit.sh/iostreams"
"kraftkit.sh/log"
"kraftkit.sh/tui"
"kraftkit.sh/tui/paraprogress"
"kraftkit.sh/tui/processtree"
Expand Down Expand Up @@ -151,13 +154,14 @@ func importVolumeData(ctx context.Context, opts *ImportOptions) (retErr error) {

var authStr string
var instFQDN string
var instID string

paramodel, err = processTree(ctx, "Spawning temporary volume data import instance",
func(ctx context.Context) error {
if authStr, err = utils.GenRandAuth(); err != nil {
return fmt.Errorf("generating random authentication string: %w", err)
}
_, instFQDN, err = runVolimport(ctx, icli, opts.VolimportImage, volUUID, authStr, opts.Timeout)
instID, instFQDN, err = runVolimport(ctx, icli, opts.VolimportImage, volUUID, authStr, opts.Timeout)
return err
},
)
Expand All @@ -175,48 +179,94 @@ func importVolumeData(ctx context.Context, opts *ImportOptions) (retErr error) {
var freeSpace uint64
var totalSpace uint64

paraprogress, err := paraProgress(ctx, fmt.Sprintf("Importing data (%s)", humanize.IBytes(uint64(cpioSize))),
func(ctx context.Context, callback func(float64)) (retErr error) {
instAddr := instFQDN + ":" + strconv.FormatUint(uint64(volimportPort), 10)
conn, err := tls.Dial("tcp4", instAddr, nil)
if err != nil {
return fmt.Errorf("connecting to volume data import instance send port: %w", err)
}
defer conn.Close()

ctx, cancel := context.WithCancel(ctx)
defer cancel()
freeSpace, totalSpace, err = copyCPIO(ctx, conn, authStr, cpioPath, opts.Force, uint64(cpioSize), callback)
copyCPIOErr = err
if log.LoggerTypeFromString(config.G[config.KraftKit](ctx).Log.Type) == log.FANCY {
paraprogress, err := paraProgress(ctx, fmt.Sprintf("Importing data (%s)", humanize.IBytes(uint64(cpioSize))),
func(ctx context.Context, callback func(float64)) (retErr error) {
instAddr := instFQDN + ":" + strconv.FormatUint(uint64(volimportPort), 10)
conn, err := tls.Dial("tcp4", instAddr, nil)
if err != nil {
return fmt.Errorf("connecting to volume data import instance send port: %w", err)
}
defer conn.Close()

ctx, cancel := context.WithCancel(ctx)
defer cancel()
freeSpace, totalSpace, err = copyCPIO(ctx, conn, authStr, cpioPath, opts.Force, uint64(cpioSize), callback)
copyCPIOErr = err
return err
},
)
if err != nil {
return err
},
)
if err != nil {
return err
}
if err = paraprogress.Start(); err != nil {
}
if err = paraprogress.Start(); err != nil {
return err
}
} else {
instAddr := instFQDN + ":" + strconv.FormatUint(uint64(volimportPort), 10)
conn, err := tls.Dial("tcp4", instAddr, nil)
if err != nil {
return fmt.Errorf("connecting to volume data import instance send port: %w", err)
}
defer conn.Close()

ctx, cancel := context.WithCancel(ctx)
defer cancel()
freeSpace, totalSpace, err = copyCPIO(ctx, conn, authStr, cpioPath, opts.Force, uint64(cpioSize), func(progress float64) {})
copyCPIOErr = err
return err
}
if copyCPIOErr != nil {
return copyCPIOErr
}

fancymap.PrintFancyMap(iostreams.G(ctx).Out, tui.TextGreen, "Import complete",
fancymap.FancyMapEntry{
Key: "volume",
Value: opts.VolID,
},
fancymap.FancyMapEntry{
Key: "free",
Value: humanize.IBytes(freeSpace),
},
fancymap.FancyMapEntry{
Key: "total",
Value: humanize.IBytes(totalSpace),
},
)
if log.LoggerTypeFromString(config.G[config.KraftKit](ctx).Log.Type) == log.FANCY {
fancymap.PrintFancyMap(iostreams.G(ctx).Out, tui.TextGreen, "Import complete",
fancymap.FancyMapEntry{
Key: "volume",
Value: opts.VolID,
},
fancymap.FancyMapEntry{
Key: "free",
Value: humanize.IBytes(freeSpace),
},
fancymap.FancyMapEntry{
Key: "total",
Value: humanize.IBytes(totalSpace),
},
)
} else {
log.G(ctx).
WithField("volume", opts.VolID).
WithField("free", humanize.IBytes(freeSpace)).
WithField("total", humanize.IBytes(totalSpace)).
Info("Import complete")
}

return nil
// Stopping time can be anywhere between 1-1000ms, so we set a 1100ms timeout
waitResp, err := cli.Instances().WithMetro(opts.Metro).Wait(ctx, ukcinstances.StateStopped, 1100, instID)
if err != nil {
return fmt.Errorf("waiting for volume data import instance to stop: %w", err)
}

if w, err := waitResp.FirstOrErr(); err == nil {
if ukcinstances.State(w.State) == ukcinstances.StateRunning {
return fmt.Errorf("volume data import instance did not stop yet: %s", w.State)
} else {
// Wait a bit for the instance to be deleted
// NOTE(craciunoiuc): this should never be reached, but it's a safety net
time.Sleep(100 * time.Millisecond)
return nil
}
} else {
if strings.Contains(err.Error(), "No instance") {
return nil
} else if strings.Contains(err.Error(), "Operation timed out") {
return fmt.Errorf("timed out waiting for volume data import instance to stop: %w", err)
} else {
return fmt.Errorf("waiting for volume data import instance to stop: %w", err)
}
}
}

// processTree returns a TUI ProcessTree configured to run the given function
Expand Down
1 change: 0 additions & 1 deletion internal/cli/kraft/cloud/volume/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (

type ListOptions struct {
Output string `long:"output" short:"o" usage:"Set output format. Options: table,yaml,json,list" default:"table"`
Watch bool `long:"watch" short:"w" usage:"After listing watch for changes."`

metro string
token string
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/cloud/cloud_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Licensed under the BSD-3-Clause License (the "License").
// You may not use this file except in compliance with the License.

package cli_test
package cloud_test

import (
"testing"
Expand Down
13 changes: 13 additions & 0 deletions test/e2e/cloud/fixtures/import/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2024, Unikraft GmbH and The KraftKit Authors.
# Licensed under the BSD-3-Clause License (the "License").
# You may not use this file except in compliance with the License.

FROM ubuntu:latest AS build

RUN mkdir -p /tmp/build && \
echo "<p>Hello World!</p>" > /tmp/build/hello.txt

FROM scratch AS import

COPY --from=build /tmp/build/hello.txt /index.html
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Hello World!</p>
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-0
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-1
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-2
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-3
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-4
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-5
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-6
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-7
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-8
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio-large/soft-link-9
1 change: 1 addition & 0 deletions test/e2e/cloud/fixtures/import/cpio/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>Hello World!</p>
2 changes: 1 addition & 1 deletion test/e2e/cloud/img_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Licensed under the BSD-3-Clause License (the "License").
// You may not use this file except in compliance with the License.

package cli_test
package cloud_test

import (
"fmt"
Expand Down
24 changes: 23 additions & 1 deletion test/e2e/cloud/instance_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Licensed under the BSD-3-Clause License (the "License").
// You may not use this file except in compliance with the License.

package cli_test
package cloud_test

import (
"crypto/rand"
Expand Down Expand Up @@ -756,6 +756,28 @@ var _ = Describe("kraft cloud instance create", func() {
)
})

AfterEach(func() {
// Remove the instance after the test
cleanCmd := fcmd.NewKraft(stdout, stderr, cfg.Path())
cleanCmd.Args = append(cleanCmd.Args,
"cloud", "instance", "delete",
"--log-level", "info",
"--log-type", "json",
instanceNameFull,
)

err := cleanCmd.Run()
time.Sleep(2 * time.Second)
if err != nil {
fmt.Print(cleanCmd.DumpError(stdout, stderr, err))
}

Expect(err).ToNot(HaveOccurred())
Expect(stderr.String()).To(BeEmpty())
Expect(stdout.String()).ToNot(BeEmpty())
Expect(stdout.String()).To(MatchRegexp(`removing 1 instance\(s\)`))
})

It("should not error out with an API error", func() {
err := cmd.Run()
time.Sleep(2 * time.Second)
Expand Down
Loading
Loading