mirror of
https://gitea.elkins.co/Networking/ccl.git
synced 2024-12-04 13:37:50 -06:00
Pull images if necessary before creating. Add pull command.
This commit is contained in:
parent
787c06e4d1
commit
84c431c8d4
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
|
||||
ccl
|
||||
/ccl
|
||||
/ccl.toml
|
||||
|
55
cmd/pull.go
Normal file
55
cmd/pull.go
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright © 2022 Joel D. Elkins <joel@elkins.co>
|
||||
|
||||
Pepullission 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 pepullit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this pepullission 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 cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gitea.elkins.co/Networking/ccl/internal/pkg/config"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// pullCmd represents the pull command
|
||||
var pullCmd = &cobra.Command{
|
||||
Use: "pull",
|
||||
Short: "Pull updated images",
|
||||
ValidArgsFunction: validNouns,
|
||||
Args: cobra.OnlyValidArgs,
|
||||
Long: `Pull updated images for one or more containers or categories. Defined containers are not
|
||||
affected: the old image will still remain, though untagged, and any defined containers
|
||||
will still use it.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
conts := config.Union(args)
|
||||
for _, cont := range conts {
|
||||
fmt.Fprintln(output, "PULL", cont.Name)
|
||||
for _, cmd := range cont.PullCommands() {
|
||||
if err := cmd.Execute(output, fake); err != nil {
|
||||
cont.LogEntry().WithField("error", err).Errorln("Pull failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(pullCmd)
|
||||
}
|
@ -20,14 +20,14 @@ type command string
|
||||
|
||||
var (
|
||||
ConfigFile string = CONFIG_FILE_DEFAULT
|
||||
networks = &[]network.Network{}
|
||||
containers = &[]container.Container{}
|
||||
Networks = []network.Network{}
|
||||
Containers = []container.Container{}
|
||||
)
|
||||
|
||||
func Categories() []string {
|
||||
categories := []string{"all"}
|
||||
gs := hashset.New()
|
||||
for _, c := range *containers {
|
||||
for _, c := range Containers {
|
||||
gs.Add(c.Category)
|
||||
}
|
||||
for _, c := range gs.Values() {
|
||||
@ -38,11 +38,11 @@ func Categories() []string {
|
||||
|
||||
func Union(ids []string) (conts []container.Container) {
|
||||
if len(ids) == 0 {
|
||||
return *containers
|
||||
return Containers
|
||||
}
|
||||
h := hashset.New()
|
||||
for _, id := range ids {
|
||||
for _, c := range *containers {
|
||||
for _, c := range Containers {
|
||||
if id == "all" || c.Name == id || c.Category == id {
|
||||
h.Add(c.Name)
|
||||
}
|
||||
@ -50,8 +50,8 @@ func Union(ids []string) (conts []container.Container) {
|
||||
}
|
||||
for _, c := range h.Values() {
|
||||
name := c.(string)
|
||||
match := slices.IndexFunc(*containers, func(c container.Container) bool { return c.Name == name })
|
||||
conts = append(conts, (*containers)[match])
|
||||
match := slices.IndexFunc(Containers, func(c container.Container) bool { return c.Name == name })
|
||||
conts = append(conts, Containers[match])
|
||||
}
|
||||
if len(conts) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
@ -61,13 +61,13 @@ func Union(ids []string) (conts []container.Container) {
|
||||
return
|
||||
}
|
||||
|
||||
// A parsing convenience
|
||||
type parse struct {
|
||||
Networks []network.Network
|
||||
Containers []container.Container
|
||||
}
|
||||
|
||||
func Init(conn context.Context) error {
|
||||
// A parsing convenience
|
||||
type parse struct {
|
||||
Networks []network.Network
|
||||
Containers []container.Container
|
||||
}
|
||||
|
||||
f, err := os.ReadFile(ConfigFile)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -77,9 +77,9 @@ func Init(conn context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containers, networks = &p.Containers, &p.Networks
|
||||
Containers, Networks = p.Containers, p.Networks
|
||||
for i := range p.Containers {
|
||||
p.Containers[i].Init(conn, networks)
|
||||
p.Containers[i].Init(conn, Networks)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -56,13 +56,13 @@ type Container struct {
|
||||
cdata *define.InspectContainerData
|
||||
}
|
||||
|
||||
func (c *Container) Init(conn context.Context, nets *[]network.Network) error {
|
||||
func (c *Container) Init(conn context.Context, nets []network.Network) error {
|
||||
// initialize user-provided definitions
|
||||
for i := range c.Networks {
|
||||
var n *network.Network
|
||||
for j := range *nets {
|
||||
if (*nets)[j].Name == c.Networks[i].Name {
|
||||
n = &(*nets)[j]
|
||||
for j := range nets {
|
||||
if nets[j].Name == c.Networks[i].Name {
|
||||
n = &nets[j]
|
||||
}
|
||||
}
|
||||
if n == nil {
|
||||
@ -105,10 +105,30 @@ func (c *Container) LogEntry() *log.Entry {
|
||||
return log.WithFields(f)
|
||||
}
|
||||
|
||||
func (c *Container) pull() error {
|
||||
_, err := images.Pull(c.conn, c.Image, &images.PullOptions{})
|
||||
return err
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return c.populateCData()
|
||||
}
|
||||
|
||||
func (c *Container) PullCommands() []command.Command {
|
||||
return []command.Command{
|
||||
command.NewErrFunc("do_pull", func() error {
|
||||
return c.pull()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Container) CreateCommands() []command.Command {
|
||||
if c.Image == "" {
|
||||
log.WithField("container", c.Name).Error("Image not defined")
|
||||
return []command.Command{command.NewNop()}
|
||||
return []command.Command{
|
||||
command.NewErrFunc("image_error", func() error {
|
||||
return fmt.Errorf("Image not configured")
|
||||
}),
|
||||
}
|
||||
}
|
||||
sysctl := map[string]string{}
|
||||
nets := map[string]types.PerNetworkOptions{}
|
||||
@ -156,12 +176,27 @@ func (c *Container) CreateCommands() []command.Command {
|
||||
},
|
||||
}
|
||||
if err := spec.Validate(); err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"container": c.Name,
|
||||
"error": err,
|
||||
}).Warn("Specgen does not validate")
|
||||
c.LogEntry().WithField("error", err).Warnf("Spec does not validate")
|
||||
}
|
||||
return []command.Command{
|
||||
command.NewErrFunc("bail_if_exists", func() error {
|
||||
if ex, err := containers.Exists(c.conn, c.Name, &containers.ExistsOptions{}); err != nil || ex {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("Container %s exists already", c.Name)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
command.NewErrFunc("pull_if_necessary", func() error {
|
||||
if ex, err := images.Exists(c.conn, c.Image, &images.ExistsOptions{}); err != nil || !ex {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.pull()
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
command.NewErrFunc("do_create", func() error {
|
||||
_, err := containers.CreateWithSpec(c.conn, &spec, nil)
|
||||
if err != nil {
|
||||
@ -258,11 +293,11 @@ func (c *Container) UpdateCommands() []command.Command {
|
||||
wasRunning := false
|
||||
return []command.Command{
|
||||
command.NewErrFunc("do_update_and_stop", func() error {
|
||||
_, err := images.Pull(c.conn, c.Image, &images.PullOptions{})
|
||||
err := c.pull()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wasRunning = (c.cdata.State != nil) && c.cdata.State.Running
|
||||
wasRunning = c.cdata != nil && c.cdata.State != nil && c.cdata.State.Running
|
||||
if wasRunning {
|
||||
var timeout uint = 10
|
||||
err := containers.Stop(c.conn, c.cdata.ID, &containers.StopOptions{Timeout: &timeout})
|
||||
@ -313,8 +348,8 @@ func (c *Container) StopCommands() []command.Command {
|
||||
func (c *Container) populateCData() error {
|
||||
// TODO: locking
|
||||
var err error
|
||||
size := false
|
||||
c.cdata, err = containers.Inspect(c.conn, c.Name, &containers.InspectOptions{Size: &size})
|
||||
no := false
|
||||
c.cdata, err = containers.Inspect(c.conn, c.Name, &containers.InspectOptions{Size: &no})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user