package pods import ( "encoding/json" "fmt" "os" "path/filepath" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) var ( files bool format string systemdTimeout uint systemdOptions = entities.GenerateSystemdOptions{} systemdDescription = `Generate systemd units for a pod or container. The generated units can later be controlled via systemctl(1).` systemdCmd = &cobra.Command{ Use: "systemd [flags] CTR|POD", Short: "Generate systemd units.", Long: systemdDescription, RunE: systemd, Args: cobra.ExactArgs(1), Example: `podman generate systemd CTR podman generate systemd --new --time 10 CTR podman generate systemd --files --name POD`, } ) func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: systemdCmd, Parent: generateCmd, }) flags := systemdCmd.Flags() flags.BoolVarP(&systemdOptions.Name, "name", "n", false, "Use container/pod names instead of IDs") flags.BoolVarP(&files, "files", "f", false, "Generate .service files instead of printing to stdout") flags.UintVarP(&systemdTimeout, "time", "t", containerConfig.Engine.StopTimeout, "Stop timeout override") flags.StringVar(&systemdOptions.RestartPolicy, "restart-policy", "on-failure", "Systemd restart-policy") flags.BoolVarP(&systemdOptions.New, "new", "", false, "Create a new container instead of starting an existing one") flags.StringVar(&systemdOptions.ContainerPrefix, "container-prefix", "container", "Systemd unit name prefix for containers") flags.StringVar(&systemdOptions.PodPrefix, "pod-prefix", "pod", "Systemd unit name prefix for pods") flags.StringVar(&systemdOptions.Separator, "separator", "-", "Systemd unit name separator between name/id and prefix") flags.StringVar(&format, "format", "", "Print the created units in specified format (json)") flags.SetNormalizeFunc(utils.AliasFlags) } func systemd(cmd *cobra.Command, args []string) error { if cmd.Flags().Changed("time") { systemdOptions.StopTimeout = &systemdTimeout } if registry.IsRemote() { logrus.Warnln("The generated units should be placed on your remote system") } report, err := registry.ContainerEngine().GenerateSystemd(registry.GetContext(), args[0], systemdOptions) if err != nil { return err } if files { cwd, err := os.Getwd() if err != nil { return errors.Wrap(err, "error getting current working directory") } for name, content := range report.Units { path := filepath.Join(cwd, fmt.Sprintf("%s.service", name)) f, err := os.Create(path) if err != nil { return err } _, err = f.WriteString(content) if err != nil { return err } err = f.Close() if err != nil { return err } // add newline if default format is given if format == "" { path += "\n" } // modify in place so we can print the // paths when --files is set report.Units[name] = path } } switch format { case "json": return printJSON(report.Units) case "": return printDefault(report.Units) default: return errors.Errorf("unknown --format argument: %s", format) } } func printDefault(units map[string]string) error { for _, content := range units { fmt.Print(content) } return nil } func printJSON(units map[string]string) error { b, err := json.MarshalIndent(units, "", " ") if err != nil { return err } fmt.Println(string(b)) return nil }