diff --git a/contrib/nydusify/pkg/converter/provider/ported.go b/contrib/nydusify/pkg/converter/provider/ported.go index 652cf5ff838..a934c63d71e 100644 --- a/contrib/nydusify/pkg/converter/provider/ported.go +++ b/contrib/nydusify/pkg/converter/provider/ported.go @@ -6,15 +6,20 @@ package provider import ( "context" + "encoding/json" "fmt" + "io" "strings" "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/images" + "github.com/containerd/containerd/images/archive" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/errdefs" + "github.com/opencontainers/go-digest" // nolint:staticcheck "github.com/containerd/containerd/remotes/docker/schema1" @@ -22,6 +27,18 @@ import ( "golang.org/x/sync/semaphore" ) +type importOpts struct { + indexName string + imageRefT func(string) string + dgstRefT func(digest.Digest) string + skipDgstRef func(string) bool + platformMatcher platforms.MatchComparer + compress bool + discardLayers bool + skipMissing bool + imageLabels map[string]string +} + // Ported from containerd project, copyright The containerd Authors. // github.com/containerd/containerd/blob/main/pull.go func fetch(ctx context.Context, store content.Store, rCtx *containerd.RemoteContext, ref string, limit int) (images.Image, error) { @@ -177,3 +194,108 @@ func push(ctx context.Context, store content.Store, pushCtx *containerd.RemoteCo return remotes.PushContent(ctx, pusher, desc, store, limiter, pushCtx.PlatformMatcher, wrapper) } + +// Ported from containerd project, copyright The containerd Authors. +// github.com/containerd/containerd/blob/main/import.go +func load(ctx context.Context, reader io.Reader, store content.Store, iopts importOpts) ([]images.Image, error) { + var aio []archive.ImportOpt + if iopts.compress { + aio = append(aio, archive.WithImportCompression()) + } + + index, err := archive.ImportIndex(ctx, store, reader, aio...) + if err != nil { + return nil, err + } + + var imgs []images.Image + + if iopts.indexName != "" { + imgs = append(imgs, images.Image{ + Name: iopts.indexName, + Target: index, + }) + } + var platformMatcher = iopts.platformMatcher + + var handler images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + // Only save images at top level + if desc.Digest != index.Digest { + // Don't set labels on missing content. + children, err := images.Children(ctx, store, desc) + if iopts.skipMissing && errdefs.IsNotFound(err) { + return nil, images.ErrSkipDesc + } + return children, err + } + + var idx ocispec.Index + p, err := content.ReadBlob(ctx, store, desc) + if err != nil { + return nil, err + } + if err := json.Unmarshal(p, &idx); err != nil { + return nil, err + } + + for _, m := range idx.Manifests { + name := imageName(m.Annotations, iopts.imageRefT) + if name != "" { + imgs = append(imgs, images.Image{ + Name: name, + Target: m, + }) + } + if iopts.skipDgstRef != nil { + if iopts.skipDgstRef(name) { + continue + } + } + if iopts.dgstRefT != nil { + ref := iopts.dgstRefT(m.Digest) + if ref != "" { + imgs = append(imgs, images.Image{ + Name: ref, + Target: m, + }) + } + } + } + + return idx.Manifests, nil + } + + handler = images.FilterPlatforms(handler, platformMatcher) + if iopts.discardLayers { + handler = images.SetChildrenMappedLabels(store, handler, images.ChildGCLabelsFilterLayers) + } else { + handler = images.SetChildrenLabels(store, handler) + } + if err := images.WalkNotEmpty(ctx, handler, index); err != nil { + return nil, err + } + + for i := range imgs { + fieldsPath := []string{"target"} + if iopts.imageLabels != nil { + fieldsPath = append(fieldsPath, "labels") + imgs[i].Labels = iopts.imageLabels + } + } + + return imgs, nil +} + +func imageName(annotations map[string]string, ociCleanup func(string) string) string { + name := annotations[images.AnnotationImageName] + if name != "" { + return name + } + name = annotations[ocispec.AnnotationRefName] + if name != "" { + if ociCleanup != nil { + name = ociCleanup(name) + } + } + return name +} diff --git a/contrib/nydusify/pkg/converter/provider/provider.go b/contrib/nydusify/pkg/converter/provider/provider.go index 08a7988dba1..3d4b238dc21 100644 --- a/contrib/nydusify/pkg/converter/provider/provider.go +++ b/contrib/nydusify/pkg/converter/provider/provider.go @@ -7,6 +7,7 @@ package provider import ( "context" "crypto/tls" + "io" "net" "net/http" "os" @@ -17,13 +18,16 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/images/archive" "github.com/containerd/containerd/platforms" "github.com/containerd/containerd/remotes" "github.com/containerd/containerd/remotes/docker" "github.com/goharbor/acceleration-service/pkg/cache" accelcontent "github.com/goharbor/acceleration-service/pkg/content" "github.com/goharbor/acceleration-service/pkg/remote" + "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/pkg/errors" ) var LayerConcurrentLimit = 5 @@ -152,6 +156,36 @@ func (pvd *Provider) Push(ctx context.Context, desc ocispec.Descriptor, ref stri return push(ctx, pvd.store, rc, desc, ref) } +func (pvd *Provider) Import(ctx context.Context, reader io.Reader) (string, error) { + iopts := importOpts{ + dgstRefT: func(dgst digest.Digest) string { + return "nydus" + "@" + dgst.String() + }, + skipDgstRef: func(name string) bool { return name != "" }, + platformMatcher: pvd.platformMC, + } + images, err := load(ctx, reader, pvd.store, iopts) + if err != nil { + return "", err + } + + if len(images) != 1 { + return "", errors.New("incorrect tarball format") + } + image := images[0] + + pvd.mutex.Lock() + defer pvd.mutex.Unlock() + pvd.images[image.Name] = &image.Target + + return image.Name, nil +} + +func (pvd *Provider) Export(ctx context.Context, writer io.Writer, img *ocispec.Descriptor, name string) error { + opts := []archive.ExportOpt{archive.WithManifest(*img, name), archive.WithPlatform(pvd.platformMC)} + return archive.Export(ctx, pvd.store, writer, opts...) +} + func (pvd *Provider) Image(_ context.Context, ref string) (*ocispec.Descriptor, error) { pvd.mutex.Lock() defer pvd.mutex.Unlock() diff --git a/contrib/nydusify/pkg/copier/copier.go b/contrib/nydusify/pkg/copier/copier.go index fa3d059035c..b684629558e 100644 --- a/contrib/nydusify/pkg/copier/copier.go +++ b/contrib/nydusify/pkg/copier/copier.go @@ -13,6 +13,7 @@ import ( "path/filepath" "strings" + "github.com/containerd/containerd/archive/compression" "github.com/containerd/containerd/content" containerdErrdefs "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" @@ -246,6 +247,28 @@ func getPlatform(platform *ocispec.Platform) string { return platforms.Format(*platform) } +// getLocalPath checks if the given reference is a local file path and returns its absolute path. +// +// Parameters: +// - ref: A string which may be a docker reference or a local file path prefixed with "file://". +// +// Returns: +// - isLocalPath: A boolean indicating whether the reference is a local file path. +// - absPath: A string containing the absolute path of the local file, if applicable. +// - err: An error object if any error occurs during the process of getting the absolute path. +func getLocalPath(ref string) (isLocalPath bool, absPath string, err error) { + if !strings.HasPrefix(ref, "file://") { + return false, "", nil + } + path := strings.TrimPrefix(ref, "file://") + absPath, err = filepath.Abs(path) + if err != nil { + return true, "", err + } + return true, absPath, nil +} + +// Copy copies an image from the source to the target. func Copy(ctx context.Context, opt Opt) error { // Containerd image fetch requires a namespace context. ctx = namespaces.WithNamespace(ctx, "nydusify") @@ -285,41 +308,86 @@ func Copy(ctx context.Context, opt Opt) error { } defer os.RemoveAll(tmpDir) - sourceNamed, err := docker.ParseDockerRef(opt.Source) + isLocalSource, inputPath, err := getLocalPath(opt.Source) if err != nil { - return errors.Wrap(err, "parse source reference") - } - targetNamed, err := docker.ParseDockerRef(opt.Target) - if err != nil { - return errors.Wrap(err, "parse target reference") + return errors.Wrap(err, "parse source path") } - source := sourceNamed.String() - target := targetNamed.String() + var source string + if isLocalSource { + logrus.Infof("importing source image from %s", inputPath) + + f, err := os.Open(inputPath) + if err != nil { + return err + } + defer f.Close() + + ds, err := compression.DecompressStream(f) + if err != nil { + return err + } + defer ds.Close() - logrus.Infof("pulling source image %s", source) - if err := pvd.Pull(ctx, source); err != nil { - if errdefs.NeedsRetryWithHTTP(err) { - pvd.UsePlainHTTP() - if err := pvd.Pull(ctx, source); err != nil { - return errors.Wrap(err, "try to pull image") + if source, err = pvd.Import(ctx, ds); err != nil { + return errors.Wrap(err, "import source image") + } + logrus.Infof("imported source image %s", source) + } else { + sourceNamed, err := docker.ParseDockerRef(opt.Source) + if err != nil { + return errors.Wrap(err, "parse source reference") + } + source = sourceNamed.String() + + logrus.Infof("pulling source image %s", source) + if err := pvd.Pull(ctx, source); err != nil { + if errdefs.NeedsRetryWithHTTP(err) { + pvd.UsePlainHTTP() + if err := pvd.Pull(ctx, source); err != nil { + return errors.Wrap(err, "try to pull image") + } + } else { + return errors.Wrap(err, "pull source image") } - } else { - return errors.Wrap(err, "pull source image") } + logrus.Infof("pulled source image %s", source) } - logrus.Infof("pulled source image %s", source) sourceImage, err := pvd.Image(ctx, source) if err != nil { return errors.Wrap(err, "find image from store") } + isLocalTarget, outputPath, err := getLocalPath(opt.Target) + if err != nil { + return errors.Wrap(err, "parse target path") + } + if isLocalTarget { + logrus.Infof("exporting source image to %s", outputPath) + f, err := os.OpenFile(outputPath, os.O_CREATE|os.O_WRONLY, 0644) + if err != nil { + return err + } + defer f.Close() + if err := pvd.Export(ctx, f, sourceImage, source); err != nil { + return errors.Wrap(err, "export source image to target tar file") + } + logrus.Infof("exported image %s", source) + return nil + } + sourceDescs, err := utils.GetManifests(ctx, pvd.ContentStore(), *sourceImage, platformMC) if err != nil { return errors.Wrap(err, "get image manifests") } targetDescs := make([]ocispec.Descriptor, len(sourceDescs)) + targetNamed, err := docker.ParseDockerRef(opt.Target) + if err != nil { + return errors.Wrap(err, "parse target reference") + } + target := targetNamed.String() + sem := semaphore.NewWeighted(1) eg := errgroup.Group{} for idx := range sourceDescs { diff --git a/docs/nydusify.md b/docs/nydusify.md index 0da352b0562..361aa6d43ee 100644 --- a/docs/nydusify.md +++ b/docs/nydusify.md @@ -68,7 +68,7 @@ cat /path/to/backend-config.json } ``` -Note: the `endpoint` in the s3 `backend-config.json` **should not** contains the scheme prefix. +Note: the `endpoint` in the s3 `backend-config.json` **should not** contain the scheme prefix. ``` shell nydusify convert \ @@ -178,7 +178,7 @@ nydusify check \ The nydusify mount command can mount a nydus image stored in the backend as a filesystem. Now the supported backend types include Registry (default backend), s3 and oss. -When using Registy as the backend, you don't need specify the `--backend-type` . +When using Registry as the backend, you don't need to specify the `--backend-type` . ``` shell nydusify mount \ @@ -204,6 +204,26 @@ nydusify copy \ It supports copying OCI v1 or Nydus images, use the options `--all-platforms` / `--platform` to copy the images of specific platforms. +## Export to / Import from local tarball + +All you need is to change the `source` or `target` parameter in `nydusify copy` command to a local file path, which must start with `file://`. + +``` shell +# registry repository --> local tarball +nydusify copy \ + --source myregistry/repo:tag-nydus \ + --target file:///home/user/repo-tag-nydus.tar +``` + +Absolute path is also supported. + +``` shell +# local tarball --> registry repository +nydusify copy \ + --source file://./repo-tag-nydus.tar \ + --target myregistry/repo:tag-nydus +``` + ## Commit nydus image from container's changes The nydusify commit command can commit a nydus image from a nydus container, like `nerdctl commit` command. diff --git a/smoke/tests/benchmark_test.go b/smoke/tests/benchmark_test.go index fc7cdf67bff..a3fe12af93b 100644 --- a/smoke/tests/benchmark_test.go +++ b/smoke/tests/benchmark_test.go @@ -18,7 +18,7 @@ import ( // Environment Requirement: Containerd, nerdctl >= 0.22, nydus-snapshotter, nydusd, nydus-image and nydusify. // Prepare: setup nydus for containerd, reference: https://github.com/dragonflyoss/nydus/blob/master/docs/containerd-env-setup.md. -// TestBenchmark will dump json file(benchmark.json) which includes container e2e time, image size, read-amount and read-cout. +// TestBenchmark will dump json file(benchmark.json) which includes container e2e time, image size, read-amount and read-count. // Example: // { // e2e_time: 2747131 @@ -70,18 +70,18 @@ func (b *BenchmarkTestSuite) TestBenchmark(t *testing.T) { } targetImageSize, conversionElapsed := b.prepareImage(b.t, ctx, image) - // run contaienr + // run container b.testContainerName = uuid.NewString() - containerMetic := tool.RunContainer(b.t, b.testImage, b.snapshotter, b.testContainerName) + containerMetric := tool.RunContainer(b.t, b.testImage, b.snapshotter, b.testContainerName) b.metric = tool.ContainerMetrics{ - E2ETime: containerMetic.E2ETime, + E2ETime: containerMetric.E2ETime, ConversionElapsed: time.Duration(conversionElapsed), - ReadCount: containerMetic.ReadCount, - ReadAmountTotal: containerMetic.ReadAmountTotal, + ReadCount: containerMetric.ReadCount, + ReadAmountTotal: containerMetric.ReadAmountTotal, ImageSize: targetImageSize, } - // save metirc + // save metric b.dumpMetric() t.Logf(fmt.Sprintf("Metric: E2ETime %d ConversionElapsed %s ReadCount %d ReadAmount %d ImageSize %d", b.metric.E2ETime, b.metric.ConversionElapsed, b.metric.ReadCount, b.metric.ReadAmountTotal, b.metric.ImageSize)) } @@ -120,18 +120,18 @@ func (b *BenchmarkTestSuite) prepareImage(t *testing.T, ctx *tool.Context, image t.Fatalf("can't read convert metric file") return 0, 0 } - var convertMetirc map[string]int64 - err = json.Unmarshal(metricData, &convertMetirc) + var convertMetric map[string]int64 + err = json.Unmarshal(metricData, &convertMetric) if err != nil { t.Fatalf("can't parsing convert metric file") return 0, 0 } if b.snapshotter == "nydus" { b.testImage = target - return convertMetirc["TargetImageSize"], convertMetirc["ConversionElapsed"] + return convertMetric["TargetImageSize"], convertMetric["ConversionElapsed"] } b.testImage = source - return convertMetirc["SourceImageSize"], 0 + return convertMetric["SourceImageSize"], 0 } func (b *BenchmarkTestSuite) dumpMetric() { diff --git a/smoke/tests/blobcache_test.go b/smoke/tests/blobcache_test.go index 4a701170eb7..ffda24c1b17 100644 --- a/smoke/tests/blobcache_test.go +++ b/smoke/tests/blobcache_test.go @@ -1,3 +1,7 @@ +// Copyright 2023 Nydus Developers. All rights reserved. +// +// SPDX-License-Identifier: Apache-2.0 + package tests import ( diff --git a/smoke/tests/commit_test.go b/smoke/tests/commit_test.go index 9d7579808c0..4f9c16e75cf 100644 --- a/smoke/tests/commit_test.go +++ b/smoke/tests/commit_test.go @@ -42,8 +42,8 @@ func (c *CommitTestSuite) TestCommitContainer() test.Generator { } } -func (c *CommitTestSuite) TestCommitAndCheck(ctx tool.Context, image, commmitedImage string) { - // run nydus contaienr +func (c *CommitTestSuite) TestCommitAndCheck(ctx tool.Context, image, commitedImage string) { + // run nydus container containerName := uuid.NewString() runContainerCmd := fmt.Sprintf("sudo nerdctl --snapshotter nydus run -d -t --insecure-registry --name=%s %s sh", containerName, image) containerID := strings.Trim(tool.RunWithOutput(runContainerCmd), "\n") @@ -60,13 +60,13 @@ func (c *CommitTestSuite) TestCommitAndCheck(ctx tool.Context, image, commmitedI // commit container committedContainerName := fmt.Sprintf("%s-committed", containerName) - commitCmd := fmt.Sprintf("sudo %s commit --container %s --target %s", ctx.Binary.Nydusify, containerID, commmitedImage) + commitCmd := fmt.Sprintf("sudo %s commit --container %s --target %s", ctx.Binary.Nydusify, containerID, commitedImage) tool.RunWithoutOutput(c.t, commitCmd) // run committed container - runCommittedContainerCmd := fmt.Sprintf("sudo nerdctl --snapshotter nydus run -d -t --insecure-registry --name=%s %s sh", committedContainerName, commmitedImage) + runCommittedContainerCmd := fmt.Sprintf("sudo nerdctl --snapshotter nydus run -d -t --insecure-registry --name=%s %s sh", committedContainerName, commitedImage) tool.RunWithOutput(runCommittedContainerCmd) - defer tool.ClearContainer(c.t, commmitedImage, "nydus", committedContainerName) + defer tool.ClearContainer(c.t, commitedImage, "nydus", committedContainerName) // check committed file content checkFileContent(c.t, committedContainerName, "/root/commit", "This is Nydus commit") diff --git a/smoke/tests/hot_upgrade_test.go b/smoke/tests/hot_upgrade_test.go index dbfd141fb95..d785decea4e 100644 --- a/smoke/tests/hot_upgrade_test.go +++ b/smoke/tests/hot_upgrade_test.go @@ -147,7 +147,7 @@ func (c *HotUpgradeTestSuite) TestHotUpgrade(t *testing.T) { err = newNydusd.StartByAPI() require.NoError(t, err) - // Verify filesytem on new nydusd + // Verify filesystem on new nydusd newNydusd.Verify(t, layer.FileTree) } diff --git a/smoke/tests/image_test.go b/smoke/tests/image_test.go index e4f27dc6765..b9c8ef666b8 100644 --- a/smoke/tests/image_test.go +++ b/smoke/tests/image_test.go @@ -6,6 +6,7 @@ package tests import ( "fmt" + "os" "path/filepath" "strings" "testing" @@ -13,6 +14,7 @@ import ( "github.com/dragonflyoss/nydus/smoke/tests/tool" "github.com/dragonflyoss/nydus/smoke/tests/tool/test" "github.com/google/uuid" + "github.com/stretchr/testify/require" ) const ( @@ -45,7 +47,7 @@ func (i *ImageTestSuite) TestConvertImages() test.Generator { } // Zran and Batch can not work together. - // Zran and Encrpt can not work together. + // Zran and Encrypt can not work together. return (param.GetBool(paramZran) && param.GetString(paramBatch) != "0") || (param.GetBool(paramZran) && param.GetBool(paramEncrypt)) }) @@ -121,10 +123,12 @@ func (i *ImageTestSuite) TestConvertAndCopyImage(t *testing.T, ctx tool.Context, ) tool.RunWithoutOutput(t, checkCmd) - if !testCopy { - return + if testCopy { + testNydusifyCopy(t, ctx, source, target, logLevel, nydusifyPath) } +} +func testNydusifyCopy(t *testing.T, ctx tool.Context, source, target, logLevel, nydusifyPath string) { // Copy image targetCopied := fmt.Sprintf("%s_copied", target) copyCmd := fmt.Sprintf( @@ -135,11 +139,38 @@ func (i *ImageTestSuite) TestConvertAndCopyImage(t *testing.T, ctx tool.Context, tool.RunWithoutOutput(t, copyCmd) // Check copied image - checkCmd = fmt.Sprintf( + checkCmd := fmt.Sprintf( "%s %s check --source %s --target %s --nydus-image %s --nydusd %s --work-dir %s", nydusifyPath, logLevel, source, targetCopied, ctx.Binary.Builder, ctx.Binary.Nydusd, filepath.Join(ctx.Env.WorkDir, "check"), ) tool.RunWithoutOutput(t, checkCmd) + + // Save image + targetSaved := fmt.Sprintf("file://%s", filepath.Join(ctx.Env.WorkDir, "saved.tar")) + saveCmd := fmt.Sprintf( + "%s %s copy --source %s --target %s --nydus-image %s --work-dir %s", + ctx.Binary.Nydusify, logLevel, target, targetSaved, ctx.Binary.Builder, filepath.Join(ctx.Env.WorkDir, "save"), + ) + tool.RunWithoutOutput(t, saveCmd) + + // Check saved image + _, err := os.Stat(filepath.Join(ctx.Env.WorkDir, "saved.tar")) + require.NoError(t, err) + + // Load image + targetLoaded := fmt.Sprintf("%s_loaded", target) + loadCmd := fmt.Sprintf( + "%s %s copy --source %s --target %s --nydus-image %s --work-dir %s", + ctx.Binary.Nydusify, logLevel, targetSaved, targetLoaded, ctx.Binary.Builder, filepath.Join(ctx.Env.WorkDir, "load"), + ) + tool.RunWithoutOutput(t, loadCmd) + + // Check loaded image + checkCmd = fmt.Sprintf( + "%s %s check --source %s --target %s --nydus-image %s --nydusd %s --work-dir %s", + nydusifyPath, logLevel, source, targetLoaded, ctx.Binary.Builder, ctx.Binary.Nydusd, filepath.Join(ctx.Env.WorkDir, "check"), + ) + tool.RunWithoutOutput(t, checkCmd) } func (i *ImageTestSuite) TestGenerateChunkdicts() test.Generator { diff --git a/smoke/tests/performance_test.go b/smoke/tests/performance_test.go index ce28ed3c2d6..a6d4b03e96e 100644 --- a/smoke/tests/performance_test.go +++ b/smoke/tests/performance_test.go @@ -53,7 +53,7 @@ func (p *PerformanceTestSuite) TestPerformance(_ *testing.T) { // prepare test image p.prepareTestImage(p.t, ctx, image) - // run Contaienr + // run Container p.testContainerName = uuid.NewString() tool.RunContainerWithBaseline(p.t, p.testImage, p.testContainerName, mode) } diff --git a/smoke/tests/takeover_test.go b/smoke/tests/takeover_test.go index f556be0b930..5c47eee0fa4 100644 --- a/smoke/tests/takeover_test.go +++ b/smoke/tests/takeover_test.go @@ -56,8 +56,8 @@ func (f *TakeoverTestSuit) clear() { tool.RunWithoutOutput(f.t, fmt.Sprintf("sudo nerdctl --snapshotter %s image rm %s", snapshotter, f.testImage)) } -func (f *TakeoverTestSuit) rmContainer(conatinerName string) { - tool.RunWithoutOutput(f.t, fmt.Sprintf("sudo nerdctl --snapshotter %s rm -f %s", snapshotter, conatinerName)) +func (f *TakeoverTestSuit) rmContainer(containerName string) { + tool.RunWithoutOutput(f.t, fmt.Sprintf("sudo nerdctl --snapshotter %s rm -f %s", snapshotter, containerName)) } func (f *TakeoverTestSuit) TestFailover(t *testing.T) { @@ -82,10 +82,10 @@ func (f *TakeoverTestSuit) TestFailover(t *testing.T) { // check the container by requesting its wait url runArgs := tool.GetRunArgs(t, imageName) resp, err := http.Get(runArgs.WaitURL) - require.NoError(t, err, "access to the wait url of the recoverd container") + require.NoError(t, err, "access to the wait url of the recovered container") defer resp.Body.Close() if resp.StatusCode/100 != 2 { - t.Fatalf("Failed to access the wait url of the recoverd container") + t.Fatalf("Failed to access the wait url of the recovered container") } } @@ -120,10 +120,10 @@ func (f *TakeoverTestSuit) TestHotUpgrade(t *testing.T) { // check the container by requesting its wait url runArgs := tool.GetRunArgs(t, imageName) resp, err := http.Get(runArgs.WaitURL) - require.NoError(t, err, "access to the wait url of the recoverd container") + require.NoError(t, err, "access to the wait url of the recovered container") defer resp.Body.Close() if resp.StatusCode/100 != 2 { - t.Fatalf("Failed to access the wait url of the recoverd container") + t.Fatalf("Failed to access the wait url of the recovered container") } } diff --git a/smoke/tests/tool/container.go b/smoke/tests/tool/container.go index 97b9ad170e6..065d0bc1886 100644 --- a/smoke/tests/tool/container.go +++ b/smoke/tests/tool/container.go @@ -169,7 +169,7 @@ func RunContainerWithBaseline(t *testing.T, image string, containerName string, // RunContainer and return container metric func RunContainer(t *testing.T, image string, snapshotter string, containerName string) *ContainerMetrics { - var containerMetic ContainerMetrics + var containerMetric ContainerMetrics startTime := time.Now() // runContainer @@ -182,17 +182,17 @@ func RunContainer(t *testing.T, image string, snapshotter string, containerName defer ClearContainer(t, image, snapshotter, containerName) } - containerMetic.E2ETime = time.Since(startTime) + containerMetric.E2ETime = time.Since(startTime) if snapshotter == "nydus" { backendMetrics, err := getContainerBackendMetrics(t) if err != nil { t.Logf(err.Error()) } - containerMetic.ReadAmountTotal = backendMetrics.ReadAmountTotal - containerMetic.ReadCount = backendMetrics.ReadCount + containerMetric.ReadAmountTotal = backendMetrics.ReadAmountTotal + containerMetric.ReadCount = backendMetrics.ReadCount } - return &containerMetic + return &containerMetric } // RunContainerSimple just runs a container simply diff --git a/smoke/tests/tool/iterator.go b/smoke/tests/tool/iterator.go index 313ddb0dedc..bdd360a5522 100644 --- a/smoke/tests/tool/iterator.go +++ b/smoke/tests/tool/iterator.go @@ -95,7 +95,7 @@ func (d *DescartesItem) GetUInt64(name string) uint64 { // fmt.Println(item.Str()) // } type DescartesIterator struct { - cursores []int + cursors []int valLists [][]interface{} cursorMap map[string]int skip func(item *DescartesItem) bool @@ -118,7 +118,7 @@ func (c *DescartesIterator) Next() *DescartesItem { return nil } - c.cursores = c.nextCursors + c.cursors = c.nextCursors result := c.nextItem c.clearNext() @@ -133,8 +133,8 @@ func (c *DescartesIterator) HasNext() bool { func (c *DescartesIterator) calNext() { - cursors := make([]int, len(c.cursores)) - copy(cursors, c.cursores) + cursors := make([]int, len(c.cursors)) + copy(cursors, c.cursors) item := &DescartesItem{vals: make(map[string]interface{})} for { @@ -186,11 +186,11 @@ func (c *DescartesIterator) Dimension(name string, vals []interface{}) *Descarte c.cursorMap = make(map[string]int) } - c.cursores = append(c.cursores, 0) + c.cursors = append(c.cursors, 0) c.valLists = append(c.valLists, vals) - c.cursorMap[name] = len(c.cursores) - 1 + c.cursorMap[name] = len(c.cursors) - 1 - c.cursores[0] = -1 + c.cursors[0] = -1 return c } diff --git a/smoke/tests/tool/snapshotter.go b/smoke/tests/tool/snapshotter.go index c301e46c2a8..de65f80538e 100644 --- a/smoke/tests/tool/snapshotter.go +++ b/smoke/tests/tool/snapshotter.go @@ -17,7 +17,7 @@ import ( "github.com/pkg/errors" ) -// SnapshotterClient commnicates with nydus-snapshotter via +// SnapshotterClient communicates with nydus-snapshotter via // the system controller endpoint unix socket of nydus-snapshotter. type SnapshotterClient struct { client *http.Client diff --git a/smoke/tests/tool/test/suite.go b/smoke/tests/tool/test/suite.go index 705730ed233..c6b8b9b696d 100644 --- a/smoke/tests/tool/test/suite.go +++ b/smoke/tests/tool/test/suite.go @@ -37,7 +37,7 @@ type Generator func() (name string, testCase Case) // asynchronous/synchronized control is suite-leveled. // // Compared with github.com/onsi/ginkgo, this framework provides simpler way to organize -// cases into suite, which requires less learing of terms and less nested definitions. +// cases into suite, which requires less learning of terms and less nested definitions. // Moreover, the asynchronous run is more golang-natived, which requires no other binary. // // Compared with github.com/stretchr/testify, this framework provides asynchronous mode @@ -161,7 +161,7 @@ type Generator func() (name string, testCase Case) // // `go test -v --parallel 4` // 1. The cases are parallel executed, which leads to random completion. -// 2. The dynamic tests are named automicly in lack of customized name. +// 2. The dynamic tests are named automatically in lack of customized name. // // --- PASS: Test1 (0.00s) // --- PASS: Test1/TestDynamicTest_4 (5.00s)