Skip to content

Commit

Permalink
Initialize volumes from images (#1546)
Browse files Browse the repository at this point in the history
Signed-off-by: Javier López Barba <javier@okteto.com>
  • Loading branch information
jLopezbarb committed May 19, 2021
1 parent c17c22b commit 04a628b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 9 deletions.
65 changes: 56 additions & 9 deletions pkg/cmd/stack/translate.go
Expand Up @@ -342,7 +342,8 @@ func translatePersistentVolumeClaim(volumeName string, s *model.Stack) apiv1.Per
func translateStatefulSet(svcName string, s *model.Stack) *appsv1.StatefulSet {
svc := s.Services[svcName]

initContainerCommand, initContainerVolumeMounts := getInitContainerCommandAndVolumeMounts(*svc)
initContainers := getInitContainers(svcName, svc)

return &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: svcName,
Expand All @@ -364,14 +365,7 @@ func translateStatefulSet(svcName string, s *model.Stack) *appsv1.StatefulSet {
},
Spec: apiv1.PodSpec{
TerminationGracePeriodSeconds: pointer.Int64Ptr(svc.StopGracePeriod),
InitContainers: []apiv1.Container{
{
Name: fmt.Sprintf("init-%s", svcName),
Image: "busybox",
Command: initContainerCommand,
VolumeMounts: initContainerVolumeMounts,
},
},
InitContainers: initContainers,
Containers: []apiv1.Container{
{
Name: svcName,
Expand All @@ -394,6 +388,59 @@ func translateStatefulSet(svcName string, s *model.Stack) *appsv1.StatefulSet {
}
}

func getInitContainers(svcName string, svc *model.Service) []apiv1.Container {
addPermissionsContainer := getAddPermissionsInitContainer(svcName, svc)
initContainers := []apiv1.Container{
addPermissionsContainer,
}
initializationContainer := getInitializeVolumeContentContainer(svcName, svc)
if initializationContainer != nil {
initContainers = append(initContainers, *initializationContainer)
}

return initContainers
}

func getAddPermissionsInitContainer(svcName string, svc *model.Service) apiv1.Container {
initContainerCommand, initContainerVolumeMounts := getInitContainerCommandAndVolumeMounts(*svc)
initContainer := apiv1.Container{
Name: fmt.Sprintf("init-%s", svcName),
Image: "busybox",
Command: initContainerCommand,
VolumeMounts: initContainerVolumeMounts,
}
return initContainer
}

func getInitializeVolumeContentContainer(svcName string, svc *model.Service) *apiv1.Container {
c := &apiv1.Container{
Name: fmt.Sprintf("init-volume-%s", svcName),
Image: svc.Image,
ImagePullPolicy: apiv1.PullIfNotPresent,
VolumeMounts: []apiv1.VolumeMount{},
}
command := "echo initializing volume..."
for idx, v := range svc.Volumes {
subpath := fmt.Sprintf("data-%d", idx)
if v.LocalPath != "" {
subpath = v.LocalPath
}
c.VolumeMounts = append(
c.VolumeMounts,
apiv1.VolumeMount{
Name: getVolumeClaimName(&v),
MountPath: fmt.Sprintf("/init-volume-%d", idx),
SubPath: subpath,
},
)
command = fmt.Sprintf("%s && (cp -Rv %s/. /init-volume-%d || true)", command, v.RemotePath, idx)
}
if len(c.VolumeMounts) != 0 {
c.Command = []string{"sh", "-c", command}
return c
}
return nil
}
func getInitContainerCommandAndVolumeMounts(svc model.Service) ([]string, []apiv1.VolumeMount) {
volumeMounts := make([]apiv1.VolumeMount, 0)

Expand Down
21 changes: 21 additions & 0 deletions pkg/cmd/stack/translate_test.go
Expand Up @@ -335,6 +335,27 @@ func Test_translateStatefulSet(t *testing.T) {
if !reflect.DeepEqual(result.Spec.Template.Spec.InitContainers[0], initContainer) {
t.Errorf("Wrong statefulset init container: '%v' but expected '%v'", result.Spec.Template.Spec.InitContainers[0], initContainer)
}
initVolumeContainer := apiv1.Container{
Name: fmt.Sprintf("init-volume-%s", "svcName"),
Image: "image",
ImagePullPolicy: apiv1.PullIfNotPresent,
Command: []string{"sh", "-c", "echo initializing volume... && (cp -Rv /volume1/. /init-volume-0 || true) && (cp -Rv /volume2/. /init-volume-1 || true)"},
VolumeMounts: []apiv1.VolumeMount{
{
MountPath: "/init-volume-0",
Name: pvcName,
SubPath: "data-0",
},
{
MountPath: "/init-volume-1",
Name: pvcName,
SubPath: "data-1",
},
},
}
if !reflect.DeepEqual(result.Spec.Template.Spec.InitContainers[1], initVolumeContainer) {
t.Errorf("Wrong statefulset init container: '%v' but expected '%v'", result.Spec.Template.Spec.InitContainers[1], initVolumeContainer)
}
c := result.Spec.Template.Spec.Containers[0]
if c.Name != "svcName" {
t.Errorf("Wrong statefulset container.name: '%s'", c.Name)
Expand Down

0 comments on commit 04a628b

Please sign in to comment.