mirror of
https://gitea.elkins.co/Networking/ccl.git
synced 2025-03-09 12:41:40 -05:00
Huge amount of linting
Linting
This commit is contained in:
parent
9c27d0e6f5
commit
b91eb62c34
@ -38,7 +38,7 @@ var createCmd = &cobra.Command{
|
|||||||
names or categories. Multiple arguments are supported.`,
|
names or categories. Multiple arguments are supported.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.CreateCommands() }, 0)
|
execForEach(conts, func(c *container.Container) command.Set { return c.CreateCommands() }, 0)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,12 +34,12 @@ import (
|
|||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
func execForEach(tgts []container.Container, getSet func(*container.Container) command.CommandSet, groupScale int) {
|
func execForEach(tgts []*container.Container, getSet func(*container.Container) command.Set, groupScale int) {
|
||||||
runLevel := make(map[int][]*container.Container)
|
runLevel := make(map[int][]*container.Container)
|
||||||
|
|
||||||
for i := range tgts {
|
for i := range tgts {
|
||||||
rl := tgts[i].StartGroup * groupScale
|
rl := tgts[i].StartGroup * groupScale
|
||||||
runLevel[rl] = append(runLevel[rl], &tgts[i])
|
runLevel[rl] = append(runLevel[rl], tgts[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
rls := maps.Keys(runLevel)
|
rls := maps.Keys(runLevel)
|
||||||
@ -58,8 +58,10 @@ func execForEach(tgts []container.Container, getSet func(*container.Container) c
|
|||||||
wg := new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
for i := range cs {
|
for i := range cs {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(cont *container.Container, set command.CommandSet) {
|
cont := cs[i]
|
||||||
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
set := getSet(cont)
|
||||||
for _, cmd := range set.Commands {
|
for _, cmd := range set.Commands {
|
||||||
if err := cmd.Execute(output, fake, set.ID); err != nil {
|
if err := cmd.Execute(output, fake, set.ID); err != nil {
|
||||||
cont.LogEntry().WithFields(log.Fields{
|
cont.LogEntry().WithFields(log.Fields{
|
||||||
@ -69,7 +71,7 @@ func execForEach(tgts []container.Container, getSet func(*container.Container) c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}(cs[i], getSet(cs[i]))
|
}()
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
if r != 0 {
|
if r != 0 {
|
||||||
|
@ -39,7 +39,7 @@ affected: the old image will still remain, though untagged, and any defined cont
|
|||||||
will still use it.`,
|
will still use it.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.PullCommands() }, 0)
|
execForEach(conts, func(c *container.Container) command.Set { return c.PullCommands() }, 0)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +38,9 @@ var recreateCmd = &cobra.Command{
|
|||||||
one or more container names or categories. If empty, "all" is assumed.`,
|
one or more container names or categories. If empty, "all" is assumed.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StopCommands() }, -1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StopCommands() }, -1)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.RecreateCommands() }, 0)
|
execForEach(conts, func(c *container.Container) command.Set { return c.RecreateCommands() }, 0)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.ConditionalStartCommands() }, 1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.ConditionalStartCommands() }, 1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ var restartCmd = &cobra.Command{
|
|||||||
one or more container names or categories. If empty, "all" is assumed.`,
|
one or more container names or categories. If empty, "all" is assumed.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StopCommands() }, -1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StopCommands() }, -1)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StartCommands() }, 1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StartCommands() }, 1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ var rmCmd = &cobra.Command{
|
|||||||
If running, they will first be stopped.`,
|
If running, they will first be stopped.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StopCommands() }, -1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StopCommands() }, -1)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.RemoveCommands() }, 0)
|
execForEach(conts, func(c *container.Container) command.Set { return c.RemoveCommands() }, 0)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
17
cmd/root.go
17
cmd/root.go
@ -38,7 +38,7 @@ import (
|
|||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "ccl",
|
Use: "ccl",
|
||||||
Short: "Manage a set of pre-configured of podman containers",
|
Short: "Manage a set of pre-configured of podman containers",
|
||||||
Version: Version,
|
Version: version,
|
||||||
Long: `ccl is a utility to manage a set of podman containers. Use with various subcommands
|
Long: `ccl is a utility to manage a set of podman containers. Use with various subcommands
|
||||||
to define, start, stop, or update the container images. Configuration is read
|
to define, start, stop, or update the container images. Configuration is read
|
||||||
from a toml configuration file, and the utility uses this information to
|
from a toml configuration file, and the utility uses this information to
|
||||||
@ -52,9 +52,9 @@ execute the necessary podman commands.`,
|
|||||||
requireConn := []string{"create", "pull", "recreate", "restart", "rm", "start", "stop", "update"}
|
requireConn := []string{"create", "pull", "recreate", "restart", "rm", "start", "stop", "update"}
|
||||||
if slices.Contains(requireConn, cmd.Name()) {
|
if slices.Contains(requireConn, cmd.Name()) {
|
||||||
// connect to podman
|
// connect to podman
|
||||||
ConnectMust()
|
connectMust()
|
||||||
} else {
|
} else {
|
||||||
if err := Connect(); err != nil {
|
if err := connect(); err != nil {
|
||||||
log.WithField("error", err).Warnln("Connection failed")
|
log.WithField("error", err).Warnln("Connection failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,14 +84,15 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Connect() error {
|
func connect() error {
|
||||||
var err error
|
var err error
|
||||||
conn, err = bindings.NewConnection(context.WithValue(context.Background(), "output", output), socket)
|
key := struct{ string }{"output"}
|
||||||
|
conn, err = bindings.NewConnection(context.WithValue(context.Background(), key, output), socket)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConnectMust() {
|
func connectMust() {
|
||||||
if err := Connect(); err != nil {
|
if err := connect(); err != nil {
|
||||||
log.WithField("error", err).Errorf("Could not connect")
|
log.WithField("error", err).Errorf("Could not connect")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
@ -105,7 +106,7 @@ func init() {
|
|||||||
output = io.Discard
|
output = io.Discard
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
rootCmd.PersistentFlags().StringVarP(&config.ConfigFile, "config", "c", config.CONFIG_FILE_DEFAULT, "pathname of config file")
|
rootCmd.PersistentFlags().StringVarP(&config.ConfigFile, "config", "c", config.ConfigFileDefault, "pathname of config file")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "show additional info from command execution")
|
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "show additional info from command execution")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&fake, "no-action", "n", false, "do not actually execute commands")
|
rootCmd.PersistentFlags().BoolVarP(&fake, "no-action", "n", false, "do not actually execute commands")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&incDisabled, "include-disabled", "a", false, "include category=. containers in actions")
|
rootCmd.PersistentFlags().BoolVarP(&incDisabled, "include-disabled", "a", false, "include category=. containers in actions")
|
||||||
|
@ -36,9 +36,9 @@ var startCmd = &cobra.Command{
|
|||||||
ValidArgsFunction: validNouns,
|
ValidArgsFunction: validNouns,
|
||||||
Long: `Start configured containers. They must be created first. Arguments can be
|
Long: `Start configured containers. They must be created first. Arguments can be
|
||||||
one or more container names or categories. If empty, "all" is assumed.`,
|
one or more container names or categories. If empty, "all" is assumed.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StartCommands() }, 1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StartCommands() }, 1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ var stopCmd = &cobra.Command{
|
|||||||
one or more container names or categories. If empty, "all" is assumed.`,
|
one or more container names or categories. If empty, "all" is assumed.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.StopCommands() }, -1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.StopCommands() }, -1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,8 +38,8 @@ var updateCmd = &cobra.Command{
|
|||||||
one or more container names or categories. If empty, "all" is assumed.`,
|
one or more container names or categories. If empty, "all" is assumed.`,
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
conts := config.Union(args, contMask)
|
conts := config.Union(args, contMask)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.UpdateCommands() }, -1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.UpdateCommands() }, -1)
|
||||||
execForEach(conts, func(c *container.Container) command.CommandSet { return c.ConditionalStartCommands() }, 1)
|
execForEach(conts, func(c *container.Container) command.Set { return c.ConditionalStartCommands() }, 1)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,14 +35,14 @@ var versionCmd = &cobra.Command{
|
|||||||
Short: "Show version info",
|
Short: "Show version info",
|
||||||
Long: `Output the ccl binary's version`,
|
Long: `Output the ccl binary's version`,
|
||||||
Run: func(cmd *cobra.Command, _ []string) {
|
Run: func(cmd *cobra.Command, _ []string) {
|
||||||
fmt.Println("ccl version", Version)
|
fmt.Println("ccl version", version)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//go:embed version.txt
|
//go:embed version.txt
|
||||||
version string
|
rawVersion string
|
||||||
Version string = strings.TrimSpace(version)
|
version = strings.TrimSpace(rawVersion)
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
Package command is used to manage the container management instructions required to carry out
|
||||||
|
tasks desired by the user, such as "create"
|
||||||
|
|
||||||
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -27,46 +30,64 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandType int
|
// Type is one of the Ct... constants, indicating the underlying method
|
||||||
|
// for executing a command.
|
||||||
|
type cType int
|
||||||
|
|
||||||
|
// Types of commands:
|
||||||
|
// - CtNop: No operation; an empty placeholder
|
||||||
|
// - CtShell: A shell command -- string to be fed to /bin/sh -c
|
||||||
|
// - CtFunc: A go function of type `func() error`
|
||||||
|
// - CtIndirect: A reference to another command. When executed, the underlying command is executed.
|
||||||
|
// - CtSet: An ordered list of commands
|
||||||
|
// - CtDebug: A debug message is printed upon execution, but does no other action
|
||||||
|
// - CtConditional: A function and two commands are provided. When evaluated,
|
||||||
|
// the function, having signature `func() bool`, is executed. If the result is
|
||||||
|
// true, then the first command is executed, and if false the second one.
|
||||||
const (
|
const (
|
||||||
CT_NOP CommandType = iota
|
ctNop cType = iota
|
||||||
CT_SHELL
|
ctShell
|
||||||
CT_FUNC
|
ctFunc
|
||||||
CT_INDIRECT
|
ctIndirect
|
||||||
CT_SET
|
ctSet
|
||||||
CT_DEBUG
|
ctDebug
|
||||||
CT_CONDITIONAL
|
ctConditional
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ct CommandType) String() string {
|
func (ct cType) String() string {
|
||||||
switch ct {
|
switch ct {
|
||||||
case CT_NOP:
|
case ctNop:
|
||||||
return "NOP"
|
return "NOP"
|
||||||
case CT_SHELL:
|
case ctShell:
|
||||||
return "SHELL"
|
return "SHELL"
|
||||||
case CT_FUNC:
|
case ctFunc:
|
||||||
return "FUNC"
|
return "FUNC"
|
||||||
case CT_INDIRECT:
|
case ctIndirect:
|
||||||
return "INDIRECT"
|
return "INDIRECT"
|
||||||
case CT_SET:
|
case ctSet:
|
||||||
return "SET"
|
return "SET"
|
||||||
case CT_DEBUG:
|
case ctDebug:
|
||||||
return "DEBUG"
|
return "DEBUG"
|
||||||
case CT_CONDITIONAL:
|
case ctConditional:
|
||||||
return "CONDITIONAL"
|
return "CONDITIONAL"
|
||||||
default:
|
default:
|
||||||
return "UNKOWN"
|
return "UNKOWN"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command combines a Type with an `interface{}`, representing a task (or a set
|
||||||
|
// of tasks, in the case of CtSet) to be executed. Create a Command with one of
|
||||||
|
// the `NewXxxCommand` functions.
|
||||||
type Command struct {
|
type Command struct {
|
||||||
Type CommandType
|
Type cType
|
||||||
Command interface{}
|
Command interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Commands reflects an ordered grouping of `Command`s
|
||||||
type Commands []Command
|
type Commands []Command
|
||||||
|
|
||||||
type CommandSet struct{
|
// Set bundes a `Commands` object with an arbitrary ID for verbose output
|
||||||
|
type Set struct {
|
||||||
ID string
|
ID string
|
||||||
Commands
|
Commands
|
||||||
}
|
}
|
||||||
@ -83,32 +104,46 @@ type conditional struct {
|
|||||||
ElseCmd Command
|
ElseCmd Command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewShell creates a new shell-type command from a string. Upon execution, the
|
||||||
|
// string will be fed to `/bin/sh -c`
|
||||||
func NewShell(cmd string) Command {
|
func NewShell(cmd string) Command {
|
||||||
return Command{CT_SHELL, cmd}
|
return Command{ctShell, cmd}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFunc creates a command consisting of go function of type `func() error`
|
||||||
func NewFunc(name string, f func() error) Command {
|
func NewFunc(name string, f func() error) Command {
|
||||||
return Command{CT_FUNC, errFunc{name, f}}
|
return Command{ctFunc, errFunc{name, f}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewIndirect creates a reference to another command. When executed, the underlying
|
||||||
|
// command is executed.
|
||||||
func NewIndirect(c Command) Command {
|
func NewIndirect(c Command) Command {
|
||||||
return Command{CT_INDIRECT, c}
|
return Command{ctIndirect, c}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSet(cs CommandSet) Command {
|
// NewSet creates a single command containing an ordered list of commands. These
|
||||||
return Command{CT_SET, cs.Commands}
|
// commands will be executed in order with this set-type command is executed.
|
||||||
|
func NewSet(cs Set) Command {
|
||||||
|
return Command{ctSet, cs.Commands}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDebug returns a command that prints a debug message upon execution, but
|
||||||
|
// does no other action
|
||||||
func NewDebug(msg string) Command {
|
func NewDebug(msg string) Command {
|
||||||
return Command{CT_DEBUG, msg}
|
return Command{ctDebug, msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewNop returns a placeholder command. When executed, nothing is done other
|
||||||
|
// than to note that it was encountered in the output.
|
||||||
func NewNop() Command {
|
func NewNop() Command {
|
||||||
return Command{CT_NOP, nil}
|
return Command{ctNop, nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewConditional takes a function and two commands as arguments. When evaluated,
|
||||||
|
// the function, having signature `func() bool`, is executed. If the result is
|
||||||
|
// true, then the first command is executed, and if false the second one.
|
||||||
func NewConditional(name string, ifPart func() bool, thenPart Command, elsePart Command) Command {
|
func NewConditional(name string, ifPart func() bool, thenPart Command, elsePart Command) Command {
|
||||||
return Command{CT_CONDITIONAL, conditional{
|
return Command{ctConditional, conditional{
|
||||||
Name: name,
|
Name: name,
|
||||||
Condition: ifPart,
|
Condition: ifPart,
|
||||||
ThenCmd: thenPart,
|
ThenCmd: thenPart,
|
||||||
@ -116,7 +151,9 @@ func NewConditional(name string, ifPart func() bool, thenPart Command, elsePart
|
|||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmds CommandSet) Execute(output io.Writer, fake bool) error {
|
// Execute the Set with the privileges of the user running the process.
|
||||||
|
// Warning: in the case of a shell command, this could do anything.
|
||||||
|
func (cmds Set) Execute(output io.Writer, fake bool) error {
|
||||||
for _, c := range cmds.Commands {
|
for _, c := range cmds.Commands {
|
||||||
if err := c.Execute(output, fake, cmds.ID); err != nil {
|
if err := c.Execute(output, fake, cmds.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -125,11 +162,13 @@ func (cmds CommandSet) Execute(output io.Writer, fake bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Execute the Command with the privileges of the user running the process.
|
||||||
|
// Warning: in the case of a shell command, this could do anything.
|
||||||
func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error {
|
func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error {
|
||||||
switch c.Type {
|
switch c.Type {
|
||||||
case CT_NOP:
|
case ctNop:
|
||||||
fmt.Fprintf(output, "%s: %s\n", commandSetID, c.Type)
|
fmt.Fprintf(output, "%s: %s\n", commandSetID, c.Type)
|
||||||
case CT_SHELL:
|
case ctShell:
|
||||||
cmd := c.Command.(string)
|
cmd := c.Command.(string)
|
||||||
fmt.Fprintf(output, "%s: %s sh -c \"%s\"\n", commandSetID, c.Type, cmd)
|
fmt.Fprintf(output, "%s: %s sh -c \"%s\"\n", commandSetID, c.Type, cmd)
|
||||||
if !fake {
|
if !fake {
|
||||||
@ -137,7 +176,7 @@ func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error
|
|||||||
fmt.Fprint(output, string(out))
|
fmt.Fprint(output, string(out))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case CT_FUNC:
|
case ctFunc:
|
||||||
ef := c.Command.(errFunc)
|
ef := c.Command.(errFunc)
|
||||||
fmt.Fprintf(output, "%s: %s %s\n", commandSetID, c.Type, ef.Name)
|
fmt.Fprintf(output, "%s: %s %s\n", commandSetID, c.Type, ef.Name)
|
||||||
if !fake {
|
if !fake {
|
||||||
@ -146,10 +185,10 @@ func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
case CT_INDIRECT:
|
case ctIndirect:
|
||||||
ct := c.Command.(Command)
|
ct := c.Command.(Command)
|
||||||
return ct.Execute(output, fake, commandSetID)
|
return ct.Execute(output, fake, commandSetID)
|
||||||
case CT_SET:
|
case ctSet:
|
||||||
cs := c.Command.(Commands)
|
cs := c.Command.(Commands)
|
||||||
for i := range cs {
|
for i := range cs {
|
||||||
err := cs[i].Execute(output, fake, commandSetID)
|
err := cs[i].Execute(output, fake, commandSetID)
|
||||||
@ -157,7 +196,7 @@ func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case CT_CONDITIONAL:
|
case ctConditional:
|
||||||
cond := c.Command.(conditional)
|
cond := c.Command.(conditional)
|
||||||
if fake {
|
if fake {
|
||||||
// in a fake setting, we don't know which branch will be followed,
|
// in a fake setting, we don't know which branch will be followed,
|
||||||
@ -173,11 +212,10 @@ func (c Command) Execute(output io.Writer, fake bool, commandSetID string) error
|
|||||||
fmt.Fprintf(output, "%s: %s %s: %v\n", commandSetID, c.Type, cond.Name, branch)
|
fmt.Fprintf(output, "%s: %s %s: %v\n", commandSetID, c.Type, cond.Name, branch)
|
||||||
if branch {
|
if branch {
|
||||||
return cond.ThenCmd.Execute(output, fake, commandSetID)
|
return cond.ThenCmd.Execute(output, fake, commandSetID)
|
||||||
} else {
|
|
||||||
return cond.ElseCmd.Execute(output, fake, commandSetID)
|
|
||||||
}
|
}
|
||||||
|
return cond.ElseCmd.Execute(output, fake, commandSetID)
|
||||||
}
|
}
|
||||||
case CT_DEBUG:
|
case ctDebug:
|
||||||
msg := c.Command.(string)
|
msg := c.Command.(string)
|
||||||
fmt.Fprintf(output, "%s: %s %s\n", commandSetID, c.Type, msg)
|
fmt.Fprintf(output, "%s: %s %s\n", commandSetID, c.Type, msg)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,27 @@
|
|||||||
|
/*
|
||||||
|
Package config is used manage initialize and house the main program data
|
||||||
|
structures, as well as marshalling the configuration to and from toml.
|
||||||
|
|
||||||
|
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -18,15 +42,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CONFIG_FILE_DEFAULT = "/etc/ccl.toml"
|
ConfigFileDefault = "/etc/ccl.toml" // ConfigFileDefault is default configuration file path
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ConfigFile = CONFIG_FILE_DEFAULT
|
ConfigFile = ConfigFileDefault // ConfigFile is the path to the configuration file to use in a particular invocation.
|
||||||
Networks = []network.Network{}
|
Networks = []*network.Network{} // Networks is the program-global set of congiured network.Networks structures
|
||||||
Containers = []container.Container{}
|
Containers = []*container.Container{} // Containers is the program-global set of configured container.Container structures.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Categories returns a slice of all of the distinct categories found in the
|
||||||
|
// configured containers.
|
||||||
func Categories() []string {
|
func Categories() []string {
|
||||||
categories := []string{"all"}
|
categories := []string{"all"}
|
||||||
gs := hashset.New()
|
gs := hashset.New()
|
||||||
@ -40,7 +66,12 @@ func Categories() []string {
|
|||||||
return categories
|
return categories
|
||||||
}
|
}
|
||||||
|
|
||||||
func Union(ids []string, catMask []string) (conts []container.Container) {
|
// Union - given a list of identifiers ("all", a category, or a container
|
||||||
|
// name), as well as a category mask, will yieLd a list of configured
|
||||||
|
// containers that match the identifiers but not the mask. As envisioned, the
|
||||||
|
// default mask would be ".", i.e., the tool would normally exclude containers
|
||||||
|
// "disabled" by setting their category to a singLe period (".")
|
||||||
|
func Union(ids []string, catMask []string) (conts []*container.Container) {
|
||||||
if len(ids) == 0 {
|
if len(ids) == 0 {
|
||||||
ids = []string{"all"}
|
ids = []string{"all"}
|
||||||
}
|
}
|
||||||
@ -60,7 +91,7 @@ func Union(ids []string, catMask []string) (conts []container.Container) {
|
|||||||
}
|
}
|
||||||
for _, c := range h.Values() {
|
for _, c := range h.Values() {
|
||||||
name := c.(string)
|
name := c.(string)
|
||||||
match := slices.IndexFunc(Containers, func(c container.Container) bool { return c.Name == name })
|
match := slices.IndexFunc(Containers, func(c *container.Container) bool { return c.Name == name })
|
||||||
conts = append(conts, Containers[match])
|
conts = append(conts, Containers[match])
|
||||||
}
|
}
|
||||||
if len(conts) == 0 {
|
if len(conts) == 0 {
|
||||||
@ -69,7 +100,7 @@ func Union(ids []string, catMask []string) (conts []container.Container) {
|
|||||||
"catMask": catMask,
|
"catMask": catMask,
|
||||||
}).Warnln("No matching containers. If disabled, try adding -a")
|
}).Warnln("No matching containers. If disabled, try adding -a")
|
||||||
}
|
}
|
||||||
slices.SortFunc(conts, func(a, b container.Container) bool {
|
slices.SortFunc(conts, func(a, b *container.Container) bool {
|
||||||
if a.Category < b.Category {
|
if a.Category < b.Category {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -81,8 +112,9 @@ func Union(ids []string, catMask []string) (conts []container.Container) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnionNetworks(ids []string) []network.Network {
|
// UnionNetworks is like Union but for Networks, and also no mask.
|
||||||
nets := make([]network.Network, len(Networks))
|
func UnionNetworks(ids []string) []*network.Network {
|
||||||
|
nets := make([]*network.Network, len(Networks))
|
||||||
rejects := []int{}
|
rejects := []int{}
|
||||||
copy(nets, Networks)
|
copy(nets, Networks)
|
||||||
for i := range nets {
|
for i := range nets {
|
||||||
@ -101,11 +133,14 @@ func UnionNetworks(ids []string) []network.Network {
|
|||||||
return nets
|
return nets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init will parse the configuration file, create and populate the in-memory
|
||||||
|
// data structures. Will call container.Init() on each container created in
|
||||||
|
// this way.
|
||||||
func Init(conn context.Context) error {
|
func Init(conn context.Context) error {
|
||||||
// A parsing convenience
|
// A parsing convenience
|
||||||
type parse struct {
|
type parse struct {
|
||||||
Networks []network.Network
|
Networks []*network.Network
|
||||||
Containers []container.Container
|
Containers []*container.Container
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := os.ReadFile(ConfigFile)
|
f, err := os.ReadFile(ConfigFile)
|
||||||
@ -121,22 +156,29 @@ func Init(conn context.Context) error {
|
|||||||
for i := range Containers {
|
for i := range Containers {
|
||||||
Containers[i].Init(conn, Networks)
|
Containers[i].Init(conn, Networks)
|
||||||
}
|
}
|
||||||
slices.SortFunc(Containers, func(a, b container.Container) bool {
|
slices.SortFunc(Containers, func(a, b *container.Container) bool {
|
||||||
return a.Name < b.Name
|
return a.Name < b.Name
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show will output a toml configuration of the provided identifiers ("all",
|
||||||
|
// category, or container name). The resulting string would presumably be sent
|
||||||
|
// to the terminal or a file.
|
||||||
|
//
|
||||||
|
// Other than ordering of fields and possible inclusion of some fields with
|
||||||
|
// their default values, the generated toml should be completely compatible
|
||||||
|
// with the actual configuration. Dogfood safe.
|
||||||
func Show(ids []string, contMask []string) string {
|
func Show(ids []string, contMask []string) string {
|
||||||
type parse struct {
|
type parse struct {
|
||||||
Containers []container.Container `toml:"containers,omitempty"`
|
Containers []*container.Container `toml:"containers,omitempty"`
|
||||||
Networks []network.Network `toml:"networks,omitempty"`
|
Networks []*network.Network `toml:"networks,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
getNet := func(name string) *network.Network {
|
getNet := func(name string) *network.Network {
|
||||||
for i := range Networks {
|
for i := range Networks {
|
||||||
if Networks[i].Name == name {
|
if Networks[i].Name == name {
|
||||||
return &Networks[i]
|
return Networks[i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
Package container encapuslates both the metadata structure and main
|
||||||
|
operations to be presented to the user in the `cmd` module.
|
||||||
|
|
||||||
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@ -19,7 +22,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package container
|
package container
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -41,6 +43,9 @@ import (
|
|||||||
"gopkg.in/guregu/null.v4"
|
"gopkg.in/guregu/null.v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Container houses the metadata that may be specified by this utility when
|
||||||
|
// creating a container. A couple of fields (Name and Image) are mandatory to
|
||||||
|
// specify, but the rest will use the libpod or otherwise sensible defaults.
|
||||||
type Container struct {
|
type Container struct {
|
||||||
Category string `toml:"category"`
|
Category string `toml:"category"`
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
@ -54,9 +59,9 @@ type Container struct {
|
|||||||
Restart string `toml:"restart,omitempty"`
|
Restart string `toml:"restart,omitempty"`
|
||||||
Umask null.Int `toml:"umask,omitempty"`
|
Umask null.Int `toml:"umask,omitempty"`
|
||||||
User string `toml:"user,omitempty"`
|
User string `toml:"user,omitempty"`
|
||||||
ExposeTcp []uint16 `toml:"expose_tcp,omitempty"`
|
ExposeTCP []uint16 `toml:"expose_tcp,omitempty"`
|
||||||
ExposeUdp []uint16 `toml:"expose_udp,omitempty"`
|
ExposeUDP []uint16 `toml:"expose_udp,omitempty"`
|
||||||
PortsTcp map[uint16]uint16 `toml:"ports,omitempty"`
|
PortsTCP map[uint16]uint16 `toml:"ports,omitempty"`
|
||||||
NetNS string `toml:"netns,omitempty"`
|
NetNS string `toml:"netns,omitempty"`
|
||||||
StartGroup int `toml:"group,omitempty"`
|
StartGroup int `toml:"group,omitempty"`
|
||||||
|
|
||||||
@ -66,13 +71,15 @@ type Container struct {
|
|||||||
wasRunning bool
|
wasRunning bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) Init(conn context.Context, nets []network.Network) error {
|
// Init will initialize a new container structure by filling in network details
|
||||||
|
// and by querying other metadata from libpod, if possible.
|
||||||
|
func (c *Container) Init(conn context.Context, nets []*network.Network) error {
|
||||||
// initialize user-provided definitions
|
// initialize user-provided definitions
|
||||||
for i := range c.Networks {
|
for i := range c.Networks {
|
||||||
var n *network.Network
|
var n *network.Network
|
||||||
for j := range nets {
|
for j := range nets {
|
||||||
if nets[j].Name == c.Networks[i].Name {
|
if nets[j].Name == c.Networks[i].Name {
|
||||||
n = &nets[j]
|
n = nets[j]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if n == nil {
|
if n == nil {
|
||||||
@ -115,9 +122,12 @@ func (c *Container) Init(conn context.Context, nets []network.Network) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LogEntry will return a *logrus.LogEntry, with some basic fields populated
|
||||||
|
// for this container. The idea is that the calling code would add other fields
|
||||||
|
// (optionally) and do something with the error.
|
||||||
func (c *Container) LogEntry() *log.Entry {
|
func (c *Container) LogEntry() *log.Entry {
|
||||||
f := log.Fields{
|
f := log.Fields{
|
||||||
"container": c.Name,
|
"container": c.Name,
|
||||||
"wasRunning": c.wasRunning,
|
"wasRunning": c.wasRunning,
|
||||||
}
|
}
|
||||||
if c.cdata != nil && c.cdata.ID != "" {
|
if c.cdata != nil && c.cdata.ID != "" {
|
||||||
@ -134,14 +144,16 @@ func (c *Container) pull() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) newCommandSet(op string, cmds cmd.Commands) cmd.CommandSet {
|
func (c *Container) newCommandSet(op string, cmds cmd.Commands) cmd.Set {
|
||||||
return cmd.CommandSet{
|
return cmd.Set{
|
||||||
ID: fmt.Sprintf("%s-%s", op, c.Name),
|
ID: fmt.Sprintf("%s-%s", op, c.Name),
|
||||||
Commands: cmds,
|
Commands: cmds,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) PullCommands() cmd.CommandSet {
|
// PullCommands will return a cmd.Set to pull the specified image using the
|
||||||
|
// libpod API
|
||||||
|
func (c *Container) PullCommands() cmd.Set {
|
||||||
return c.newCommandSet("PULL", cmd.Commands{
|
return c.newCommandSet("PULL", cmd.Commands{
|
||||||
cmd.NewFunc("do_pull", func() error {
|
cmd.NewFunc("do_pull", func() error {
|
||||||
return c.pull()
|
return c.pull()
|
||||||
@ -149,7 +161,9 @@ func (c *Container) PullCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) CreateCommands() cmd.CommandSet {
|
// CreateCommands returns a cmd.Set that will create a container from the
|
||||||
|
// configured metadata. The container should not exist.
|
||||||
|
func (c *Container) CreateCommands() cmd.Set {
|
||||||
if c.Image == "" {
|
if c.Image == "" {
|
||||||
return c.newCommandSet("CREATE", cmd.Commands{
|
return c.newCommandSet("CREATE", cmd.Commands{
|
||||||
cmd.NewFunc("image_error", func() error {
|
cmd.NewFunc("image_error", func() error {
|
||||||
@ -179,15 +193,15 @@ func (c *Container) CreateCommands() cmd.CommandSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expose := map[uint16]string{}
|
expose := map[uint16]string{}
|
||||||
for _, p := range c.ExposeTcp {
|
for _, p := range c.ExposeTCP {
|
||||||
expose[p] = "tcp"
|
expose[p] = "tcp"
|
||||||
}
|
}
|
||||||
for _, p := range c.ExposeUdp {
|
for _, p := range c.ExposeUDP {
|
||||||
expose[p] = "udp"
|
expose[p] = "udp"
|
||||||
}
|
}
|
||||||
|
|
||||||
portMappings := []types.PortMapping{}
|
portMappings := []types.PortMapping{}
|
||||||
for ph, pc := range c.PortsTcp {
|
for ph, pc := range c.PortsTCP {
|
||||||
portMappings = append(portMappings, types.PortMapping{
|
portMappings = append(portMappings, types.PortMapping{
|
||||||
HostPort: ph,
|
HostPort: ph,
|
||||||
ContainerPort: pc,
|
ContainerPort: pc,
|
||||||
@ -256,15 +270,17 @@ func (c *Container) CreateCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) RecreateCommands() cmd.CommandSet {
|
// RecreateCommands will stop (if running), remove (if exists), (re)create, and restart (if
|
||||||
|
// it was initially running) a container. The image is not pulled.
|
||||||
|
func (c *Container) RecreateCommands() cmd.Set {
|
||||||
return c.newCommandSet("RECREATE", cmd.Commands{
|
return c.newCommandSet("RECREATE", cmd.Commands{
|
||||||
cmd.NewSet(c.RemoveCommands()),
|
cmd.NewSet(c.RemoveCommands()),
|
||||||
cmd.NewSet(c.CreateCommands()),
|
cmd.NewSet(c.CreateCommands()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// unexported version just removes the container without attempting a stop.
|
// RemoveCommands removes a container (as if by `podman rm -f`)
|
||||||
func (c *Container) RemoveCommands() cmd.CommandSet {
|
func (c *Container) RemoveCommands() cmd.Set {
|
||||||
return c.newCommandSet("remove", cmd.Commands{
|
return c.newCommandSet("remove", cmd.Commands{
|
||||||
cmd.NewFunc("remove_if_exists", func() error {
|
cmd.NewFunc("remove_if_exists", func() error {
|
||||||
c.cdataLock.Lock()
|
c.cdataLock.Lock()
|
||||||
@ -281,7 +297,8 @@ func (c *Container) RemoveCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) StartCommands() cmd.CommandSet {
|
// StartCommands will start a container if it's not already running.
|
||||||
|
func (c *Container) StartCommands() cmd.Set {
|
||||||
return c.newCommandSet("START", cmd.Commands{
|
return c.newCommandSet("START", cmd.Commands{
|
||||||
cmd.NewFunc("start_container", func() error {
|
cmd.NewFunc("start_container", func() error {
|
||||||
c.cdataLock.Lock()
|
c.cdataLock.Lock()
|
||||||
@ -318,6 +335,8 @@ func (c *Container) StartCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRunning returns true if libpod reports the container status is running, or
|
||||||
|
// false otherwise. If an error happens, the default value is false.
|
||||||
func (c *Container) IsRunning() bool {
|
func (c *Container) IsRunning() bool {
|
||||||
if c.cdata != nil && c.cdata.State != nil {
|
if c.cdata != nil && c.cdata.State != nil {
|
||||||
return c.cdata.State.Running
|
return c.cdata.State.Running
|
||||||
@ -325,6 +344,7 @@ func (c *Container) IsRunning() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsCreated tests whether libpod sees the container as being created (running or not)
|
||||||
func (c *Container) IsCreated() bool {
|
func (c *Container) IsCreated() bool {
|
||||||
if c.cdata == nil || c.cdata.ID == "" {
|
if c.cdata == nil || c.cdata.ID == "" {
|
||||||
return false
|
return false
|
||||||
@ -332,7 +352,9 @@ func (c *Container) IsCreated() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) UpdateCommands() cmd.CommandSet {
|
// UpdateCommands will pull the image (to force updates) and then recreate the
|
||||||
|
// container. It will be stopped first.
|
||||||
|
func (c *Container) UpdateCommands() cmd.Set {
|
||||||
return c.newCommandSet("UPDATE", cmd.Commands{
|
return c.newCommandSet("UPDATE", cmd.Commands{
|
||||||
cmd.NewSet(c.PullCommands()),
|
cmd.NewSet(c.PullCommands()),
|
||||||
cmd.NewSet(c.StopCommands()),
|
cmd.NewSet(c.StopCommands()),
|
||||||
@ -341,7 +363,10 @@ func (c *Container) UpdateCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) ConditionalStartCommands() cmd.CommandSet {
|
// ConditionalStartCommands - several of the other command sets would leave the
|
||||||
|
// container in the stopped state. This set will restart a container if it was
|
||||||
|
// running when this container was first initialized.
|
||||||
|
func (c *Container) ConditionalStartCommands() cmd.Set {
|
||||||
if c.wasRunning {
|
if c.wasRunning {
|
||||||
return c.StartCommands()
|
return c.StartCommands()
|
||||||
}
|
}
|
||||||
@ -350,7 +375,9 @@ func (c *Container) ConditionalStartCommands() cmd.CommandSet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Container) StopCommands() cmd.CommandSet {
|
// StopCommands will stop a container if it is running, defining a 10 second
|
||||||
|
// timeout before the processes are killed by lippod
|
||||||
|
func (c *Container) StopCommands() cmd.Set {
|
||||||
return c.newCommandSet("STOP", cmd.Commands{
|
return c.newCommandSet("STOP", cmd.Commands{
|
||||||
cmd.NewFunc("stop_if_running", func() error {
|
cmd.NewFunc("stop_if_running", func() error {
|
||||||
c.cdataLock.Lock()
|
c.cdataLock.Lock()
|
||||||
@ -385,6 +412,8 @@ func (c *Container) populateCData() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pid will return the host process id of the main container process (pid
|
||||||
|
// 1 inside the container)
|
||||||
func (c *Container) Pid() int {
|
func (c *Container) Pid() int {
|
||||||
if c.cdata != nil && c.cdata.State != nil {
|
if c.cdata != nil && c.cdata.State != nil {
|
||||||
return c.cdata.State.Pid
|
return c.cdata.State.Pid
|
||||||
@ -394,7 +423,7 @@ func (c *Container) Pid() int {
|
|||||||
|
|
||||||
func (c *Container) assureNetNS() error {
|
func (c *Container) assureNetNS() error {
|
||||||
if nil == c.cdata || nil == c.cdata.NetworkSettings {
|
if nil == c.cdata || nil == c.cdata.NetworkSettings {
|
||||||
return fmt.Errorf("Network namespace not available!")
|
return fmt.Errorf("network namespace not available")
|
||||||
}
|
}
|
||||||
netns := c.cdata.NetworkSettings.SandboxKey
|
netns := c.cdata.NetworkSettings.SandboxKey
|
||||||
if err := exec.Command("rm", "-f", "/var/run/netns/"+c.Name).Run(); err != nil {
|
if err := exec.Command("rm", "-f", "/var/run/netns/"+c.Name).Run(); err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user