commands

package
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 20, 2021 License: Apache-2.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ConvertCommand = cli.Command{
	Name:      "convert",
	Usage:     "convert an image",
	ArgsUsage: "[flags] <source_ref> <target_ref>...",
	Description: `Convert an image format.

e.g., 'ctr-remote convert --estargz --oci example.com/foo:orig example.com/foo:esgz'

Use '--platform' to define the output platform.
When '--all-platforms' is given all images in a manifest list must be available.
`,
	Flags: []cli.Flag{

		cli.BoolFlag{
			Name:  "estargz",
			Usage: "convert legacy tar(.gz) layers to eStargz for lazy pulling. Should be used in conjunction with '--oci'",
		},
		cli.StringFlag{
			Name:  "estargz-record-in",
			Usage: "Read 'ctr-remote optimize --record-out=<FILE>' record file",
		},
		cli.IntFlag{
			Name:  "estargz-compression-level",
			Usage: "eStargz compression level",
			Value: gzip.BestCompression,
		},
		cli.IntFlag{
			Name:  "estargz-chunk-size",
			Usage: "eStargz chunk size",
			Value: 0,
		},

		cli.BoolFlag{
			Name:  "uncompress",
			Usage: "convert tar.gz layers to uncompressed tar layers",
		},
		cli.BoolFlag{
			Name:  "oci",
			Usage: "convert Docker media types to OCI media types",
		},

		cli.StringSliceFlag{
			Name:  "platform",
			Usage: "Convert content for a specific platform",
			Value: &cli.StringSlice{},
		},
		cli.BoolFlag{
			Name:  "all-platforms",
			Usage: "Convert content for all platforms",
		},
	},
	Action: func(context *cli.Context) error {
		var (
			convertOpts = []nativeconverter.ConvertOpt{}
		)
		srcRef := context.Args().Get(0)
		targetRef := context.Args().Get(1)
		if srcRef == "" || targetRef == "" {
			return errors.New("src and target image need to be specified")
		}

		if !context.Bool("all-platforms") {
			if pss := context.StringSlice("platform"); len(pss) > 0 {
				var all []ocispec.Platform
				for _, ps := range pss {
					p, err := platforms.Parse(ps)
					if err != nil {
						return errors.Wrapf(err, "invalid platform %q", ps)
					}
					all = append(all, p)
				}
				convertOpts = append(convertOpts, nativeconverter.WithPlatform(platforms.Ordered(all...)))
			} else {
				convertOpts = append(convertOpts, nativeconverter.WithPlatform(platforms.Default()))
			}
		}

		if context.Bool("estargz") {
			esgzOpts, err := getESGZConvertOpts(context)
			if err != nil {
				return err
			}
			convertOpts = append(convertOpts, nativeconverter.WithLayerConvertFunc(estargzconvert.LayerConvertFunc(esgzOpts...)))
			if !context.Bool("oci") {
				logrus.Warn("option --estargz should be used in conjunction with --oci")
			}
			if context.Bool("uncompress") {
				return errors.New("option --estargz conflicts with --uncompress")
			}
		}

		if context.Bool("uncompress") {
			convertOpts = append(convertOpts, nativeconverter.WithLayerConvertFunc(uncompress.LayerConvertFunc))
		}

		if context.Bool("oci") {
			convertOpts = append(convertOpts, nativeconverter.WithDockerToOCI(true))
		}

		client, ctx, cancel, err := commands.NewClient(context)
		if err != nil {
			return err
		}
		defer cancel()

		conv, err := nativeconverter.New(client)
		if err != nil {
			return err
		}
		newImg, err := conv.Convert(ctx, targetRef, srcRef, convertOpts...)
		if err != nil {
			return err
		}
		fmt.Fprintln(context.App.Writer, newImg.Target.Digest.String())
		return nil
	},
}
View Source
var OptimizeCommand = cli.Command{
	Name:      "optimize",
	Usage:     "optimize an image with user-specified workload",
	ArgsUsage: "<input-ref> <output-ref>",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "plain-http",
			Usage: "allow HTTP connections to the registry which has the prefix \"http://\"",
		},
		cli.BoolFlag{
			Name:  "reuse",
			Usage: "reuse eStargz (already optimized) layers without further conversion",
		},
		cli.BoolFlag{
			Name:  "terminal,t",
			Usage: "enable terminal for sample container",
		},
		cli.BoolFlag{
			Name:  "wait-on-signal",
			Usage: "ignore context cancel and keep the container running until it receives signal (Ctrl + C) sent manually",
		},
		cli.IntFlag{
			Name:  "period",
			Usage: "time period to monitor access log",
			Value: defaultPeriod,
		},
		cli.StringFlag{
			Name:  "user",
			Usage: "user name to override image's default config",
		},
		cli.StringFlag{
			Name:  "cwd",
			Usage: "working dir to override image's default config",
		},
		cli.StringFlag{
			Name:  "args",
			Usage: "command arguments to override image's default config(in JSON array)",
		},
		cli.StringFlag{
			Name:  "entrypoint",
			Usage: "entrypoint to override image's default config(in JSON array)",
		},
		cli.StringSliceFlag{
			Name:  "env",
			Usage: "environment valulable to add or override to the image's default config",
		},
		cli.StringSliceFlag{
			Name:  "mount",
			Usage: "additional mounts for the container (e.g. type=foo,source=/path,destination=/target,options=bind)",
		},
		cli.StringFlag{
			Name:  "dns-nameservers",
			Usage: "comma-separated nameservers added to the container's /etc/resolv.conf",
			Value: "8.8.8.8",
		},
		cli.StringFlag{
			Name:  "dns-search-domains",
			Usage: "comma-separated search domains added to the container's /etc/resolv.conf",
		},
		cli.StringFlag{
			Name:  "dns-options",
			Usage: "comma-separated options added to the container's /etc/resolv.conf",
		},
		cli.StringFlag{
			Name:  "add-hosts",
			Usage: "comma-separated hosts configuration (host:IP) added to container's /etc/hosts",
		},
		cli.BoolFlag{
			Name:  "cni",
			Usage: "enable CNI-based networking",
		},
		cli.StringFlag{
			Name:  "cni-plugin-conf-dir",
			Usage: "path to the CNI plugins configuration directory",
		},
		cli.StringFlag{
			Name:  "cni-plugin-dir",
			Usage: "path to the CNI plugins binary directory",
		},
		cli.StringFlag{
			Name:  "platform",
			Usage: "platform specifier of the source image",
		},
		cli.BoolFlag{
			Name:  "all-platforms",
			Usage: "targeting all platform of the source image",
		},
		cli.BoolFlag{
			Name:  "no-optimize",
			Usage: "convert image without optimization",
		},
		cli.StringFlag{
			Name:  "record-out",
			Usage: "record the monitor log to the specified file",
		},
	},
	Action: func(context *cli.Context) error {

		ctx := gocontext.Background()

		reglogs.Warn.SetOutput(log.G(ctx).WriterLevel(logrus.WarnLevel))
		reglogs.Progress.SetOutput(log.G(ctx).WriterLevel(logrus.InfoLevel))

		// Parse arguments
		var (
			src = context.Args().Get(0)
			dst = context.Args().Get(1)
		)
		if src == "" || dst == "" {
			return fmt.Errorf("source and destination of the target image must be specified")
		}
		opts, err := parseArgs(context)
		if err != nil {
			return errors.Wrap(err, "failed to parse args")
		}

		srcIO, err := parseReference(src, context)
		if err != nil {
			return errors.Wrapf(err, "failed to parse source ref %q", src)
		}
		dstIO, err := parseReference(dst, context)
		if err != nil {
			return errors.Wrapf(err, "failed to parse destination ref %q", dst)
		}

		// Parse platform information
		var platform *spec.Platform
		if context.Bool("all-platforms") {
			platform = nil
		} else if pStr := context.String("platform"); pStr != "" {
			p, err := platforms.Parse(pStr)
			if err != nil {
				return errors.Wrapf(err, "failed to parse platform %q", pStr)
			}
			platform = &p
		} else {
			p := platforms.DefaultSpec()
			platform = &p
		}

		tf := tempfiles.NewTempFiles()
		defer func() {
			if err := tf.CleanupAll(); err != nil {
				log.G(ctx).WithError(err).Warn("failed to cleanup layer files")
			}
		}()

		noOptimize := context.Bool("no-optimize")
		optimizerOpts := &optimizer.Opts{
			Reuse:  context.Bool("reuse"),
			Period: time.Duration(context.Int("period")) * time.Second,
		}

		var rec *recorder.Recorder
		if recordOut := context.String("record-out"); recordOut != "" {
			recordWriter, err := os.Create(recordOut)
			if err != nil {
				return err
			}
			defer recordWriter.Close()
			rec = recorder.New(recordWriter)
		}

		srcIndex, err := srcIO.ReadIndex()
		if err != nil {

			log.G(ctx).Warn("index not found; treating as a thin image with ignoring the platform option")
			srcImage, err := srcIO.ReadImage()
			if err != nil {
				return err
			}
			p := platforms.DefaultSpec()
			dstImage, err := converter.ConvertImage(ctx, noOptimize, optimizerOpts, srcImage, &p, tf, rec, opts...)
			if err != nil {
				return err
			}
			return dstIO.WriteImage(dstImage)
		}
		dstIndex, err := converter.ConvertIndex(ctx, noOptimize, optimizerOpts, srcIndex, platform, tf, rec, opts...)
		if err != nil {
			return err
		}
		return dstIO.WriteIndex(dstIndex)
	},
}
View Source
var RpullCommand = cli.Command{
	Name:      "rpull",
	Usage:     "pull an image from a registry levaraging stargz snapshotter",
	ArgsUsage: "[flags] <ref>",
	Description: `Fetch and prepare an image for use in containerd levaraging stargz snapshotter.

After pulling an image, it should be ready to use the same reference in a run
command. 
`,
	Flags: append(commands.RegistryFlags, commands.LabelFlag,
		cli.BoolFlag{
			Name:  skipContentVerifyOpt,
			Usage: "Skip content verification for layers contained in this image.",
		},
	),
	Action: func(context *cli.Context) error {
		var (
			ref    = context.Args().First()
			config = &rPullConfig{}
		)
		if ref == "" {
			return fmt.Errorf("please provide an image reference to pull")
		}

		client, ctx, cancel, err := commands.NewClient(context)
		if err != nil {
			return err
		}
		defer cancel()

		ctx, done, err := client.WithLease(ctx)
		if err != nil {
			return err
		}
		defer done(ctx)

		fc, err := content.NewFetchConfig(ctx, context)
		if err != nil {
			return err
		}
		config.FetchConfig = fc

		if context.Bool(skipContentVerifyOpt) {
			config.skipVerify = true
		}

		if err := pull(ctx, client, ref, config); err != nil {
			return err
		}
		return nil
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL