Skip to content

Commit cf8ce25

Browse files
committed
added running container replace method including containerrename and containerremove
1 parent 6f94a1f commit cf8ce25

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ ImageRemove(imageID string) ([]types.ImageDelete, error)
579579
VolumesPrune(pruneFilter filters.Args) (*types.VolumesPruneReport, error)
580580
GetDockerClient() *client.Client
581581
CalculateStats(jsonStats *types.StatsJSON) *models.Stats
582+
ContainerReplace(containerID) error
582583
```
583584

584585
## Listing all tag versions from DockerHub

docker/docker.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,109 @@ func (cl *Client) CalculateStats(jsonStats *types.StatsJSON) *models.Stats {
529529
return stats
530530
}
531531

532+
func (cl *Client) ContainerReplace(containerID string, image string, tag string) error {
533+
534+
originalContainer, err := cl.ContainerGet(containerID)
535+
if err != nil {
536+
if cl.log != nil {
537+
cl.log.Error("failed to get container with id", containerID, err)
538+
}
539+
return err
540+
}
541+
542+
originalContainerName := originalContainer.Name
543+
tempContainerName := originalContainerName + "_temp"
544+
rErr := cl.ContainerRename(originalContainer.ID, tempContainerName)
545+
if rErr != nil {
546+
return rErr
547+
}
548+
549+
originalConf := originalContainer.Config
550+
// replace image with the new image
551+
originalConf.Image = image + ":" + tag
552+
553+
newlyCreatedContainer, ccErr := cl.ContainerCreate(originalContainerName, originalConf, originalContainer.HostConfig, nil)
554+
if ccErr != nil {
555+
// revert renaming back the old container
556+
rbErr := cl.ContainerRename(containerID, originalContainerName)
557+
if rbErr != nil {
558+
return rbErr
559+
}
560+
if cl.log != nil {
561+
cl.log.Error("failed to create a new container with original name", originalContainerName, ccErr)
562+
}
563+
return ccErr
564+
}
565+
566+
sErr := cl.ContainerStart(newlyCreatedContainer.ID)
567+
if sErr != nil {
568+
if cl.log != nil {
569+
cl.log.Error("failed to start newly created container", originalContainerName, newlyCreatedContainer.ID, sErr)
570+
}
571+
// undo previous changes to origial container and remove newly created container
572+
cerr := cl.ContainerRename(containerID, originalContainerName)
573+
cerr = cl.ContainerRemove(newlyCreatedContainer.ID)
574+
if cerr != nil {
575+
return cerr
576+
}
577+
578+
return sErr
579+
}
580+
581+
// removing old container
582+
killAfter := time.Second * 5
583+
stopErr := cl.ContainerStop(containerID, &killAfter)
584+
if stopErr != nil {
585+
if cl.log != nil {
586+
cl.log.Error("failed to stop old container", containerID, stopErr)
587+
}
588+
return stopErr
589+
}
590+
591+
_, remErr := cl.ContainersPrune(filters.NewArgs())
592+
if remErr != nil {
593+
if cl.log != nil {
594+
cl.log.Error("failed to remove old container", containerID, remErr)
595+
}
596+
return remErr
597+
}
598+
599+
return nil
600+
}
601+
602+
// ContainerRemove - removing the container. timeout in 10 seconds, force removing all
603+
func (cl *Client) ContainerRemove(containerID string) error {
604+
605+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
606+
defer cancel()
607+
608+
remErr := cl.client.ContainerRemove(ctx, containerID, types.ContainerRemoveOptions{Force: true, RemoveVolumes: true, RemoveLinks: true})
609+
if remErr != nil {
610+
if cl.log != nil {
611+
cl.log.Error("failed to remove old container", containerID, remErr)
612+
}
613+
return remErr
614+
}
615+
return nil
616+
}
617+
618+
// replaceRevert reverts the phases done by ContainerReplace function in case of errors
619+
func (cl *Client) ContainerRename(containerID string, newContainerName string) error {
620+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
621+
defer cancel()
622+
623+
// revert renaming back
624+
rbErr := cl.client.ContainerRename(ctx, containerID, newContainerName)
625+
if rbErr != nil {
626+
if cl.log != nil {
627+
cl.log.Error("failed to rename old container back", newContainerName, rbErr)
628+
}
629+
return rbErr
630+
}
631+
632+
return nil
633+
}
634+
532635
func calculateBlockIO(blkio types.BlkioStats) (blkRead uint64, blkWrite uint64) {
533636
for _, bioEntry := range blkio.IoServiceBytesRecursive {
534637
switch strings.ToLower(bioEntry.Op) {

docker/docker_interfaces.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@ type Docker interface {
4848
VolumesPrune(pruneFilter filters.Args) (*types.VolumesPruneReport, error)
4949
GetDockerClient() *client.Client
5050
CalculateStats(jsonStats *types.StatsJSON) *models.Stats
51+
ContainerRemove(containerID string) error
52+
ContainerRename(containerID string, newContainerName string) error
53+
ContainerReplace(containerID string, image string, tag string) error
5154
}

docker/docker_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ package docker
1616

1717
import (
1818
"io/ioutil"
19+
"strings"
20+
"testing"
1921

2022
mclog "github.com/chryscloud/go-microkit-plugins/log"
2123
)
@@ -32,6 +34,23 @@ var (
3234
cert, _ = ioutil.ReadFile("/media/igor/ubuntu/Nextcloud/Documents/Cocooncam/conffiles/development/docker-keys/docker-client-cert.pem")
3335
)
3436

37+
func TestContainerReplace(t *testing.T) {
38+
cl := NewSocketClient(Log(zl), Host("unix:///var/run/docker.sock"))
39+
containers, err := cl.ContainersList()
40+
if err != nil {
41+
t.Fatal(err)
42+
}
43+
for _, cont := range containers {
44+
img := cont.Image
45+
if strings.Contains(img, "chryscloud/chrysedgeproxy:0.0.2") {
46+
err := cl.ContainerReplace(cont.ID, "chryscloud/chrysedgeproxy", "0.0.4")
47+
if err != nil {
48+
t.Fatal(err)
49+
}
50+
}
51+
}
52+
}
53+
3554
//TODO: tests need to be modified to run without actual docker config
3655
// func TestSocketClient(t *testing.T) {
3756
// cl := NewSocketClient(Log(zl), Host("unix:///var/run/docker.sock"))

0 commit comments

Comments
 (0)