diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/autoupdate.go | 56 | ||||
-rw-r--r-- | cmd/podman/cliconfig/config.go | 13 | ||||
-rw-r--r-- | cmd/podman/commands.go | 1 | ||||
-rw-r--r-- | cmd/podman/shared/create.go | 59 |
4 files changed, 111 insertions, 18 deletions
diff --git a/cmd/podman/autoupdate.go b/cmd/podman/autoupdate.go new file mode 100644 index 000000000..2cc1ae72e --- /dev/null +++ b/cmd/podman/autoupdate.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + + "github.com/containers/libpod/cmd/podman/cliconfig" + "github.com/containers/libpod/pkg/adapter" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +var ( + autoUpdateCommand cliconfig.AutoUpdateValues + autoUpdateDescription = `Auto update containers according to their auto-update policy. + +Auto-update policies are specified with the "io.containers.autoupdate" label.` + _autoUpdateCommand = &cobra.Command{ + Use: "auto-update [flags]", + Short: "Auto update containers according to their auto-update policy", + Args: noSubArgs, + Long: autoUpdateDescription, + RunE: func(cmd *cobra.Command, args []string) error { + restartCommand.InputArgs = args + restartCommand.GlobalFlags = MainGlobalOpts + return autoUpdateCmd(&restartCommand) + }, + Example: `podman auto-update`, + } +) + +func init() { + autoUpdateCommand.Command = _autoUpdateCommand + autoUpdateCommand.SetHelpTemplate(HelpTemplate()) + autoUpdateCommand.SetUsageTemplate(UsageTemplate()) +} + +func autoUpdateCmd(c *cliconfig.RestartValues) error { + runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) + if err != nil { + return errors.Wrapf(err, "error creating libpod runtime") + } + defer runtime.DeferredShutdown(false) + + units, failures := runtime.AutoUpdate() + for _, unit := range units { + fmt.Println(unit) + } + var finalErr error + if len(failures) > 0 { + finalErr = failures[0] + for _, e := range failures[1:] { + finalErr = errors.Errorf("%v\n%v", finalErr, e) + } + } + return finalErr +} diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 79917946a..94a7b2091 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -54,6 +54,10 @@ type AttachValues struct { SigProxy bool } +type AutoUpdateValues struct { + PodmanCommand +} + type ImagesValues struct { PodmanCommand All bool @@ -470,10 +474,11 @@ type RefreshValues struct { type RestartValues struct { PodmanCommand - All bool - Latest bool - Running bool - Timeout uint + All bool + AutoUpdate bool + Latest bool + Running bool + Timeout uint } type RestoreValues struct { diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index d6018a6f4..dfa04315e 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -11,6 +11,7 @@ const remoteclient = false // Commands that the local client implements func getMainCommands() []*cobra.Command { rootCommands := []*cobra.Command{ + _autoUpdateCommand, _cpCommand, _playCommand, _loginCommand, diff --git a/cmd/podman/shared/create.go b/cmd/podman/shared/create.go index 8968f10e8..cec837af6 100644 --- a/cmd/podman/shared/create.go +++ b/cmd/podman/shared/create.go @@ -18,6 +18,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" ann "github.com/containers/libpod/pkg/annotations" + "github.com/containers/libpod/pkg/autoupdate" envLib "github.com/containers/libpod/pkg/env" "github.com/containers/libpod/pkg/errorhandling" "github.com/containers/libpod/pkg/inspect" @@ -25,6 +26,7 @@ import ( "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/seccomp" cc "github.com/containers/libpod/pkg/spec" + systemdGen "github.com/containers/libpod/pkg/systemd/generate" "github.com/containers/libpod/pkg/util" "github.com/docker/go-connections/nat" "github.com/docker/go-units" @@ -69,6 +71,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } imageName := "" + rawImageName := "" var imageData *inspect.ImageData = nil // Set the storage if there is no rootfs specified @@ -78,9 +81,8 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. writer = os.Stderr } - name := "" if len(c.InputArgs) != 0 { - name = c.InputArgs[0] + rawImageName = c.InputArgs[0] } else { return nil, nil, errors.Errorf("error, image name not provided") } @@ -97,7 +99,7 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. ArchitectureChoice: overrideArch, } - newImage, err := runtime.ImageRuntime().New(ctx, name, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) + newImage, err := runtime.ImageRuntime().New(ctx, rawImageName, rtc.SignaturePolicyPath, c.String("authfile"), writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullType) if err != nil { return nil, nil, err } @@ -174,11 +176,32 @@ func CreateContainer(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } - createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, imageData) + createConfig, err := ParseCreateOpts(ctx, c, runtime, imageName, rawImageName, imageData) if err != nil { return nil, nil, err } + // (VR): Ideally we perform the checks _before_ pulling the image but that + // would require some bigger code refactoring of `ParseCreateOpts` and the + // logic here. But as the creation code will be consolidated in the future + // and given auto updates are experimental, we can live with that for now. + // In the end, the user may only need to correct the policy or the raw image + // name. + autoUpdatePolicy, autoUpdatePolicySpecified := createConfig.Labels[autoupdate.Label] + if autoUpdatePolicySpecified { + if _, err := autoupdate.LookupPolicy(autoUpdatePolicy); err != nil { + return nil, nil, err + } + // Now we need to make sure we're having a fully-qualified image reference. + if rootfs != "" { + return nil, nil, errors.Errorf("auto updates do not work with --rootfs") + } + // Make sure the input image is a docker. + if err := autoupdate.ValidateImageReference(rawImageName); err != nil { + return nil, nil, err + } + } + // Because parseCreateOpts does derive anything from the image, we add health check // at this point. The rest is done by WithOptions. createConfig.HealthCheck = healthCheck @@ -270,7 +293,7 @@ func configurePod(c *GenericCLIResults, runtime *libpod.Runtime, namespaces map[ // Parses CLI options related to container creation into a config which can be // parsed into an OCI runtime spec -func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) { +func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.Runtime, imageName string, rawImageName string, data *inspect.ImageData) (*cc.CreateConfig, error) { var ( inputCommand, command []string memoryLimit, memoryReservation, memorySwap, memoryKernel int64 @@ -481,12 +504,15 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. "container": "podman", } + // First transform the os env into a map. We need it for the labels later in + // any case. + osEnv, err := envLib.ParseSlice(os.Environ()) + if err != nil { + return nil, errors.Wrap(err, "error parsing host environment variables") + } + // Start with env-host if c.Bool("env-host") { - osEnv, err := envLib.ParseSlice(os.Environ()) - if err != nil { - return nil, errors.Wrap(err, "error parsing host environment variables") - } env = envLib.Join(env, osEnv) } @@ -534,6 +560,10 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. } } + if systemdUnit, exists := osEnv[systemdGen.EnvVariable]; exists { + labels[systemdGen.EnvVariable] = systemdUnit + } + // ANNOTATIONS annotations := make(map[string]string) @@ -764,11 +794,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod. Entrypoint: entrypoint, Env: env, // ExposedPorts: ports, - Init: c.Bool("init"), - InitPath: c.String("init-path"), - Image: imageName, - ImageID: imageID, - Interactive: c.Bool("interactive"), + Init: c.Bool("init"), + InitPath: c.String("init-path"), + Image: imageName, + RawImageName: rawImageName, + ImageID: imageID, + Interactive: c.Bool("interactive"), // IP6Address: c.String("ipv6"), // Not implemented yet - needs CNI support for static v6 Labels: labels, // LinkLocalIP: c.StringSlice("link-local-ip"), // Not implemented yet |