Skip to content

Commit

Permalink
delete docker box sidecar
Browse files Browse the repository at this point in the history
  • Loading branch information
niqdev committed Oct 7, 2023
1 parent d71fd5b commit e5f5128
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 41 deletions.
68 changes: 55 additions & 13 deletions pkg/box/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ func (box *DockerBoxClient) close() error {
// TODO limit resources by size?
func (box *DockerBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.BoxInfo, error) {

// pull image
imageName := opts.Template.Image.Name()
if err := box.docker.PullImageOffline(imageName, func() {
box.eventBus.Publish(newImagePullDockerLoaderEvent(imageName))
}); err != nil {
return nil, err
}

// boxName
containerName := opts.Template.GenerateName()

Expand Down Expand Up @@ -70,23 +78,13 @@ func (box *DockerBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.B

// use vpn network
networkMode = docker.ContainerNetworkMode(sidecarContainerId)

// TODO remove sidecar on exit
// defer box.docker.Client.ContainerRemove(sidecarContainerId)
}
} else {
// defaults
hostname = containerName
networkMode = docker.DefaultNetworkMode()
}

imageName := opts.Template.Image.Name()
if err := box.docker.PullImageOffline(imageName, func() {
box.eventBus.Publish(newImagePullDockerLoaderEvent(imageName))
}); err != nil {
return nil, err
}

var containerEnv []docker.ContainerEnv
for _, e := range opts.Template.EnvironmentVariables() {
containerEnv = append(containerEnv, docker.ContainerEnv{Key: e.Key, Value: e.Value})
Expand Down Expand Up @@ -184,6 +182,23 @@ func (box *DockerBoxClient) execBox(template *boxModel.BoxV1, info *boxModel.Box
command := template.Shell
box.eventBus.Publish(newContainerExecDockerEvent(info.Id, info.Name, command))

// attempt to restart all associated sidecars
sidecars, err := box.docker.GetSidecars(info.Name)
if err != nil {
return err
}
for _, sidecar := range sidecars {
restartsOpts := &docker.ContainerRestartOpts{
ContainerId: sidecar.Id,
OnRestartCallback: func(status string) {
box.eventBus.Publish(newContainerRestartDockerEvent(sidecar.Id, status))
},
}
if err := box.docker.Client.ContainerRestart(restartsOpts); err != nil {
return err
}
}

restartsOpts := &docker.ContainerRestartOpts{
ContainerId: info.Id,
OnRestartCallback: func(status string) {
Expand Down Expand Up @@ -221,6 +236,16 @@ func (box *DockerBoxClient) execBox(template *boxModel.BoxV1, info *boxModel.Box
for _, port := range containerDetails.Ports {
box.publishPortInfo(template.NetworkPorts(false), containerDetails.Info.ContainerName, port)
}
// print sidecar ports
for _, sidecar := range sidecars {
sidecarDetails, err := box.docker.Client.ContainerInspect(sidecar.Id)
if err != nil {
return err
}
for _, port := range sidecarDetails.Ports {
box.publishPortInfo(template.NetworkPorts(false), containerDetails.Info.ContainerName, port)
}
}
}

execOpts := &docker.ContainerExecOpts{
Expand All @@ -238,6 +263,12 @@ func (box *DockerBoxClient) execBox(template *boxModel.BoxV1, info *boxModel.Box
box.eventBus.Publish(newContainerExecExitDockerEvent(info.Id))

if deleteOnExit {
for _, sidecar := range sidecars {
if err := box.docker.Client.ContainerRemove(sidecar.Id); err != nil {
box.eventBus.Publish(newContainerExecErrorDockerEvent(sidecar.Id, errors.Wrap(err, "error sidecar exec remove")))
}
}

if err := box.docker.Client.ContainerRemove(info.Id); err != nil {
box.eventBus.Publish(newContainerExecErrorDockerEvent(info.Id, errors.Wrap(err, "error container exec remove")))
}
Expand Down Expand Up @@ -358,12 +389,12 @@ func (box *DockerBoxClient) listBoxes() ([]boxModel.BoxInfo, error) {
return nil, err
}

var result []boxModel.BoxInfo
var boxes []boxModel.BoxInfo
for index, c := range containers {
result = append(result, newBoxInfo(c))
boxes = append(boxes, newBoxInfo(c))
box.eventBus.Publish(newContainerListDockerEvent(index, c.ContainerName, c.ContainerId, c.Healthy))
}
return result, nil
return boxes, nil
}

func (box *DockerBoxClient) deleteBoxes(names []string) ([]string, error) {
Expand All @@ -386,6 +417,17 @@ func (box *DockerBoxClient) deleteBoxes(names []string) ([]string, error) {
// silently ignore
box.eventBus.Publish(newContainerRemoveIgnoreDockerEvent(boxInfo.Id))
}

// delete all sidecars
sidecars, _ := box.docker.GetSidecars(boxInfo.Name)
for _, sidecar := range sidecars {
if err := box.docker.Client.ContainerRemove(sidecar.Id); err != nil {
box.eventBus.Publish(newContainerRemoveDockerEvent(sidecar.Id))
} else {
// silently ignore
box.eventBus.Publish(newContainerRemoveIgnoreDockerEvent(sidecar.Id))
}
}
}
}
return deleted, nil
Expand Down
23 changes: 13 additions & 10 deletions pkg/client/docker/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,24 +273,27 @@ func newContainerDetails(container types.ContainerJSON) (ContainerDetails, error
return ContainerDetails{}, errors.Wrapf(err, "error parsing container created time %s", container.Created)
}

if len(container.NetworkSettings.Networks) != 1 {
return ContainerDetails{}, errors.Wrapf(err, "found %d container networks, expected only 1", len(container.NetworkSettings.Networks))
var networkInfo NetworkInfo
if len(container.NetworkSettings.Networks) > 1 {
return ContainerDetails{}, errors.Wrapf(err, "found %d container networks, expected at most 1", len(container.NetworkSettings.Networks))
} else if len(container.NetworkSettings.Networks) == 1 {
networkName := maps.Keys(container.NetworkSettings.Networks)[0]
network := container.NetworkSettings.Networks[networkName]
networkInfo = NetworkInfo{
Id: network.NetworkID,
Name: networkName,
IpAddress: network.IPAddress,
MacAddress: network.MacAddress,
}
}
networkName := maps.Keys(container.NetworkSettings.Networks)[0]
network := container.NetworkSettings.Networks[networkName]

return ContainerDetails{
Info: newContainerInfo(container.ID, container.Name, container.State.Status),
Created: created.UTC(),
Labels: container.Config.Labels,
Env: envs,
Ports: ports,
Network: NetworkInfo{
Id: network.NetworkID,
Name: networkName,
IpAddress: network.IPAddress,
MacAddress: network.MacAddress,
},
Network: networkInfo,
}, nil
}

Expand Down
39 changes: 29 additions & 10 deletions pkg/common/docker/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package docker

import (
"fmt"
"github.com/hckops/hckctl/pkg/schema"
"strings"

"github.com/pkg/errors"
Expand Down Expand Up @@ -75,20 +76,38 @@ func (common *DockerCommonClient) PullImageOffline(imageName string, onImagePull
func buildVpnSidecarName(containerName string) string {
// expect valid name always
tokens := strings.Split(containerName, "-")
return fmt.Sprintf("sidecar-vpn-%s", tokens[len(tokens)-1])
return fmt.Sprintf("%svpn-%s", commonModel.SidecarPrefixName, tokens[len(tokens)-1])
}

type StartVpnSidecarOptions struct {
MainContainerName string
VpnInfo *commonModel.VpnNetworkInfo
ContainerPorts []docker.ContainerPort
OnPortBindCallback func(port docker.ContainerPort)
func sidecarLabel() string {
return fmt.Sprintf("%s=%s", commonModel.LabelSchemaKind, schema.KindSidecarV1.String())
}

func (common *DockerCommonClient) StartVpnSidecar(baseContainerName string, vpnInfo *commonModel.VpnNetworkInfo, portConfig *docker.ContainerPortConfigOpts) (string, error) {
func (common *DockerCommonClient) GetSidecars(containerName string) ([]commonModel.SidecarInfo, error) {

// filter by prefix and label
containers, err := common.Client.ContainerList(commonModel.SidecarPrefixName, sidecarLabel())
if err != nil {
return nil, err
}

var sidecars []commonModel.SidecarInfo
for _, c := range containers {
// expect valid name always
tokens := strings.Split(c.ContainerName, "-")
// include only associated containers
if strings.HasSuffix(containerName, tokens[len(tokens)-1]) {
sidecars = append(sidecars, commonModel.SidecarInfo{Id: c.ContainerId, Name: c.ContainerName})
// TODO common.eventBus.Publish
}
}
return sidecars, nil
}

func (common *DockerCommonClient) StartVpnSidecar(mainContainerName string, vpnInfo *commonModel.VpnNetworkInfo, portConfig *docker.ContainerPortConfigOpts) (string, error) {

// sidecarName
containerName := buildVpnSidecarName(baseContainerName)
containerName := buildVpnSidecarName(mainContainerName)

// constants
imageName := commonModel.SidecarVpnImageName
Expand All @@ -104,12 +123,12 @@ func (common *DockerCommonClient) StartVpnSidecar(baseContainerName string, vpnI

containerConfig, err := docker.BuildContainerConfig(&docker.ContainerConfigOpts{
ImageName: imageName,
Hostname: baseContainerName,
Hostname: mainContainerName,
Env: []docker.ContainerEnv{{Key: "OPENVPN_CONFIG", Value: vpnConfigPath}},
Ports: portConfig.Ports,
Tty: false,
Cmd: []string{},
Labels: commonModel.Labels{},
Labels: commonModel.NewSidecarLabels().AddSidecarMain(mainContainerName),
})
if err != nil {
return "", err
Expand Down
1 change: 1 addition & 0 deletions pkg/common/model/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const (
KubernetesProvider = "kube"
CloudProvider = "cloud"

SidecarPrefixName = "sidecar-"
SidecarVpnImageName = "hckops/alpine-openvpn:latest"
MountShareDir = "/hck/share"
)
12 changes: 12 additions & 0 deletions pkg/common/model/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package model

import (
"fmt"
"github.com/hckops/hckctl/pkg/schema"
"path/filepath"
"strings"

Expand All @@ -21,6 +22,7 @@ const (
LabelTemplateGitDir = "com.hckops.template.git.dir"
LabelTemplateGitName = "com.hckops.template.git.name"
LabelTemplateCachePath = "com.hckops.template.cache.path"
LabelSidecarMain = "com.hckops.sidecar.main"
)

func (l Labels) AddLabel(key string, value string) Labels {
Expand Down Expand Up @@ -96,3 +98,13 @@ func (l Labels) ToGitTemplateInfo() *GitTemplateInfo {
Name: l[LabelTemplateGitName],
}
}

func NewSidecarLabels() Labels {
return map[string]string{
LabelSchemaKind: schema.KindSidecarV1.String(),
}
}

func (l Labels) AddSidecarMain(containerName string) Labels {
return l.AddLabel(LabelSidecarMain, containerName)
}
5 changes: 5 additions & 0 deletions pkg/common/model/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ func (image *Image) ResolveVersion() string {

type Parameters map[string]string

type SidecarInfo struct {
Id string
Name string
}

type NetworkInfo struct {
Vpn *VpnNetworkInfo
}
Expand Down
16 changes: 9 additions & 7 deletions pkg/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type SchemaKind int
const (
KindConfigV1 SchemaKind = iota
KindApiV1
KindSidecarV1
KindBoxV1
KindLabV1
KindTaskV1
Expand All @@ -31,13 +32,14 @@ const (
)

var kinds = map[SchemaKind]string{
KindConfigV1: "config/v1",
KindApiV1: "api/v1",
KindBoxV1: "box/v1",
KindLabV1: "lab/v1",
KindTaskV1: "task/v1",
KindFlowV1: "flow/v1",
KindDumpV1: "dump/v1",
KindConfigV1: "config/v1",
KindApiV1: "api/v1",
KindSidecarV1: "sidecar/v1",
KindBoxV1: "box/v1",
KindLabV1: "lab/v1",
KindTaskV1: "task/v1",
KindFlowV1: "flow/v1",
KindDumpV1: "dump/v1",
}

func (s SchemaKind) String() string {
Expand Down
3 changes: 2 additions & 1 deletion pkg/schema/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import (
)

func TestProviderFlag(t *testing.T) {
assert.Equal(t, 7, len(kinds))
assert.Equal(t, 8, len(kinds))
assert.Equal(t, "config/v1", KindConfigV1.String())
assert.Equal(t, "api/v1", KindApiV1.String())
assert.Equal(t, "sidecar/v1", KindSidecarV1.String())
assert.Equal(t, "box/v1", KindBoxV1.String())
assert.Equal(t, "lab/v1", KindLabV1.String())
assert.Equal(t, "task/v1", KindTaskV1.String())
Expand Down

0 comments on commit e5f5128

Please sign in to comment.