diff --git a/pkg/box/docker/docker.go b/pkg/box/docker/docker.go index 50c438c..dd124e4 100644 --- a/pkg/box/docker/docker.go +++ b/pkg/box/docker/docker.go @@ -67,8 +67,8 @@ func (box *DockerBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.B if opts.CommonInfo.NetworkVpn != nil { // set all network configs on the sidecar to avoid option conflicts sidecarOpts := &commonModel.SidecarVpnInjectOpts{ - MainContainerName: containerName, - VpnInfo: opts.CommonInfo.NetworkVpn, + MainContainerId: containerName, + NetworkVpn: opts.CommonInfo.NetworkVpn, } if sidecarContainerId, err := box.dockerCommon.SidecarVpnInject(sidecarOpts, portConfig); err != nil { return nil, err diff --git a/pkg/box/kubernetes/kubernetes.go b/pkg/box/kubernetes/kubernetes.go index 4e727e6..049c749 100644 --- a/pkg/box/kubernetes/kubernetes.go +++ b/pkg/box/kubernetes/kubernetes.go @@ -59,11 +59,22 @@ func (box *KubeBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.Box box.eventBus.Publish(newServiceCreateIgnoreKubeEvent(namespace, service.Name)) } + // inject sidecar-volume + if opts.CommonInfo.ShareDir != nil { + sidecarOpts := &commonModel.SidecarShareInjectOpts{ + MainContainerName: util.ToLowerKebabCase(opts.Template.Image.Repository), + ShareDir: opts.CommonInfo.ShareDir, + } + if err := box.kubeCommon.SidecarShareInject(sidecarOpts, &deployment.Spec.Template.Spec); err != nil { + return nil, err + } + } + // create secret and inject sidecar-vpn if opts.CommonInfo.NetworkVpn != nil { sidecarOpts := &commonModel.SidecarVpnInjectOpts{ - MainContainerName: boxName, - VpnInfo: opts.CommonInfo.NetworkVpn, + MainContainerId: boxName, + NetworkVpn: opts.CommonInfo.NetworkVpn, } if err := box.kubeCommon.SidecarVpnInject(namespace, sidecarOpts, &deployment.Spec.Template.Spec); err != nil { return nil, err @@ -84,6 +95,10 @@ func (box *KubeBoxClient) createBox(opts *boxModel.CreateOptions) (*boxModel.Box } box.eventBus.Publish(newDeploymentCreateKubeEvent(namespace, deployment.Name)) + // upload shared directory + if opts.CommonInfo.ShareDir != nil { + } + podInfo, err := box.client.PodDescribeFromDeployment(deployment) if err != nil { return nil, err diff --git a/pkg/common/docker/client.go b/pkg/common/docker/client.go index 0b4b20b..cf60bd3 100644 --- a/pkg/common/docker/client.go +++ b/pkg/common/docker/client.go @@ -111,7 +111,7 @@ func buildSidecarVpnName(containerName string) string { func (common *DockerCommonClient) SidecarVpnInject(opts *commonModel.SidecarVpnInjectOpts, portConfig *docker.ContainerPortConfigOpts) (string, error) { // sidecarName - containerName := buildSidecarVpnName(opts.MainContainerName) + containerName := buildSidecarVpnName(opts.MainContainerId) // constants imageName := commonModel.SidecarVpnImageName @@ -119,20 +119,20 @@ func (common *DockerCommonClient) SidecarVpnInject(opts *commonModel.SidecarVpnI vpnConfigPath := "/usr/share/client.ovpn" if err := common.PullImageOffline(imageName, func() { - common.eventBus.Publish(newSidecarVpnConnectDockerEvent(opts.VpnInfo.Name)) - common.eventBus.Publish(newSidecarVpnConnectDockerLoaderEvent(opts.VpnInfo.Name)) + common.eventBus.Publish(newSidecarVpnConnectDockerEvent(opts.NetworkVpn.Name)) + common.eventBus.Publish(newSidecarVpnConnectDockerLoaderEvent(opts.NetworkVpn.Name)) }); err != nil { return "", err } containerConfig, err := docker.BuildContainerConfig(&docker.ContainerConfigOpts{ ImageName: imageName, - Hostname: opts.MainContainerName, + Hostname: opts.MainContainerId, Env: []docker.ContainerEnv{{Key: "OPENVPN_CONFIG", Value: vpnConfigPath}}, Ports: portConfig.Ports, Tty: false, Cmd: []string{}, - Labels: commonModel.NewSidecarLabels().AddSidecarMain(opts.MainContainerName), + Labels: commonModel.NewSidecarLabels().AddSidecarMain(opts.MainContainerId), }) if err != nil { return "", err @@ -151,7 +151,7 @@ func (common *DockerCommonClient) SidecarVpnInject(opts *commonModel.SidecarVpnI CaptureInterrupt: false, // edge case: killing this while creating will leave an orphan sidecar container OnContainerCreateCallback: func(containerId string) error { // upload openvpn config file - return common.client.CopyFileToContainer(containerId, opts.VpnInfo.LocalPath, vpnConfigPath) + return common.client.CopyFileToContainer(containerId, opts.NetworkVpn.LocalPath, vpnConfigPath) }, OnContainerStatusCallback: func(status string) { common.eventBus.Publish(newSidecarVpnCreateStatusDockerEvent(status)) diff --git a/pkg/common/kubernetes/builder.go b/pkg/common/kubernetes/builder.go index 84309f7..992b5dd 100644 --- a/pkg/common/kubernetes/builder.go +++ b/pkg/common/kubernetes/builder.go @@ -111,6 +111,7 @@ func injectSidecarVpn(podSpec *corev1.PodSpec, mainContainerName string) { { Name: fmt.Sprintf("%ssleep", commonModel.SidecarPrefixName), Image: "busybox", + Stdin: true, // fixes PostStartHookError Lifecycle: &corev1.Lifecycle{ PostStart: &corev1.LifecycleHandler{ Exec: &corev1.ExecAction{ @@ -134,7 +135,6 @@ func buildSidecarShareContainer(remoteDir string) corev1.Container { return corev1.Container{ Name: fmt.Sprintf("%sshare", commonModel.SidecarPrefixName), Image: "busybox", // only requirement is the "tar" binary - TTY: true, Stdin: true, VolumeMounts: []corev1.VolumeMount{ { @@ -148,9 +148,9 @@ func buildSidecarShareContainer(remoteDir string) corev1.Container { func injectSidecarShare(podSpec *corev1.PodSpec, mainContainerName string, remoteDir string) { // mount read-only shared volume to main container - for _, c := range podSpec.Containers { + for index, c := range podSpec.Containers { if c.Name == mainContainerName { - c.VolumeMounts = append( + podSpec.Containers[index].VolumeMounts = append( c.VolumeMounts, corev1.VolumeMount{ Name: sidecarShareVolume, diff --git a/pkg/common/kubernetes/builder_test.go b/pkg/common/kubernetes/builder_test.go index c885fd4..d6e28ce 100644 --- a/pkg/common/kubernetes/builder_test.go +++ b/pkg/common/kubernetes/builder_test.go @@ -124,6 +124,7 @@ spec: - 1s name: sidecar-sleep resources: {} + stdin: true - image: my-image name: my-name resources: {} @@ -174,3 +175,64 @@ status: {} assert.YAMLEqf(t, expected, kubernetes.ObjectToYaml(actual), "unexpected pod") } + +func TestInjectSidecarShare(t *testing.T) { + + expected := ` +apiVersion: v1 +kind: Pod +metadata: + creationTimestamp: null +spec: + containers: + - image: my-image + name: my-name + resources: {} + volumeMounts: + - mountPath: /tmp/foo + name: sidecar-share-volume + readOnly: true + - image: busybox + name: sidecar-share + resources: {} + stdin: true + volumeMounts: + - mountPath: /tmp/foo + name: sidecar-share-volume + volumes: + - hostPath: + path: my-path + name: my-volume + - emptyDir: {} + name: sidecar-share-volume +status: {} +` + + containerName := "my-name" + shareDir := "/tmp/foo" + actual := &corev1.Pod{ + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: containerName, + Image: "my-image", + }, + }, + Volumes: []corev1.Volume{ + { + Name: "my-volume", + VolumeSource: corev1.VolumeSource{ + HostPath: &corev1.HostPathVolumeSource{ + Path: "my-path", + }, + }, + }, + }, + }, + } + injectSidecarShare(&actual.Spec, containerName, shareDir) + // fix model + actual.TypeMeta = metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"} + + assert.YAMLEqf(t, expected, kubernetes.ObjectToYaml(actual), "unexpected pod") +} diff --git a/pkg/common/kubernetes/client.go b/pkg/common/kubernetes/client.go index 4fc781b..0d6cdff 100644 --- a/pkg/common/kubernetes/client.go +++ b/pkg/common/kubernetes/client.go @@ -54,15 +54,22 @@ func (common *KubeCommonClient) SidecarVpnDelete(namespace string, mainContainer func (common *KubeCommonClient) SidecarVpnInject(namespace string, opts *commonModel.SidecarVpnInjectOpts, podSpec *corev1.PodSpec) error { // create secret - secret := buildSidecarVpnSecret(namespace, opts.MainContainerName, opts.VpnInfo.ConfigValue) + secret := buildSidecarVpnSecret(namespace, opts.MainContainerId, opts.NetworkVpn.ConfigValue) common.eventBus.Publish(newSecretCreateKubeEvent(namespace, secret.Name)) if err := common.client.SecretCreate(namespace, secret); err != nil { return err } // update pod - injectSidecarVpn(podSpec, opts.MainContainerName) - common.eventBus.Publish(newSidecarVpnConnectKubeEvent(opts.VpnInfo.Name)) + injectSidecarVpn(podSpec, opts.MainContainerId) + common.eventBus.Publish(newSidecarVpnConnectKubeEvent(opts.NetworkVpn.Name)) return nil } + +func (common *KubeCommonClient) SidecarShareInject(opts *commonModel.SidecarShareInjectOpts, podSpec *corev1.PodSpec) error { + // update pod + injectSidecarShare(podSpec, opts.MainContainerName, opts.ShareDir.RemotePath) + common.eventBus.Publish(newSidecarShareMountKubeEvent(opts.ShareDir.RemotePath)) + return nil +} diff --git a/pkg/common/kubernetes/events.go b/pkg/common/kubernetes/events.go index bb6021e..b881d9a 100644 --- a/pkg/common/kubernetes/events.go +++ b/pkg/common/kubernetes/events.go @@ -43,3 +43,7 @@ func newSecretDeleteKubeEvent(namespace string, name string) *kubeCommonEvent { func newSidecarVpnConnectKubeEvent(vpnName string) *kubeCommonEvent { return &kubeCommonEvent{kind: event.LogInfo, value: fmt.Sprintf("sidecar-vpn connect: vpnName=%s", vpnName)} } + +func newSidecarShareMountKubeEvent(shareDir string) *kubeCommonEvent { + return &kubeCommonEvent{kind: event.LogInfo, value: fmt.Sprintf("sidecar-share mount: shareDir=%s", shareDir)} +} diff --git a/pkg/common/model/options.go b/pkg/common/model/options.go index 2139398..9b55517 100644 --- a/pkg/common/model/options.go +++ b/pkg/common/model/options.go @@ -40,10 +40,11 @@ func NewStdStreamOpts(tty bool) *StreamOptions { } type SidecarVpnInjectOpts struct { - MainContainerName string - VpnInfo *NetworkVpnInfo + MainContainerId string + NetworkVpn *NetworkVpnInfo } type SidecarShareInjectOpts struct { MainContainerName string + ShareDir *ShareDirInfo } diff --git a/pkg/task/docker/docker.go b/pkg/task/docker/docker.go index 2ddb4ad..f21a7f4 100644 --- a/pkg/task/docker/docker.go +++ b/pkg/task/docker/docker.go @@ -45,8 +45,8 @@ func (task *DockerTaskClient) runTask(opts *taskModel.RunOptions) error { var networkMode string if opts.CommonInfo.NetworkVpn != nil { sidecarOpts := &commonModel.SidecarVpnInjectOpts{ - MainContainerName: containerName, - VpnInfo: opts.CommonInfo.NetworkVpn, + MainContainerId: containerName, + NetworkVpn: opts.CommonInfo.NetworkVpn, } if sidecarContainerId, err := task.dockerCommon.SidecarVpnInject(sidecarOpts, &docker.ContainerPortConfigOpts{}); err != nil { return err diff --git a/pkg/task/kubernetes/kubernetes.go b/pkg/task/kubernetes/kubernetes.go index 0c36d29..1846435 100644 --- a/pkg/task/kubernetes/kubernetes.go +++ b/pkg/task/kubernetes/kubernetes.go @@ -62,11 +62,22 @@ func (task *KubeTaskClient) runTask(opts *taskModel.RunOptions) error { }, }) + // inject sidecar-volume + if opts.CommonInfo.ShareDir != nil { + sidecarOpts := &commonModel.SidecarShareInjectOpts{ + MainContainerName: util.ToLowerKebabCase(opts.Template.Image.Repository), + ShareDir: opts.CommonInfo.ShareDir, + } + if err := task.kubeCommon.SidecarShareInject(sidecarOpts, &jobSpec.Spec.Template.Spec); err != nil { + return err + } + } + // create secret and inject sidecar-vpn if opts.CommonInfo.NetworkVpn != nil { sidecarOpts := &commonModel.SidecarVpnInjectOpts{ - MainContainerName: jobName, - VpnInfo: opts.CommonInfo.NetworkVpn, + MainContainerId: jobName, + NetworkVpn: opts.CommonInfo.NetworkVpn, } if err := task.kubeCommon.SidecarVpnInject(namespace, sidecarOpts, &jobSpec.Spec.Template.Spec); err != nil { return err @@ -93,6 +104,10 @@ func (task *KubeTaskClient) runTask(opts *taskModel.RunOptions) error { } task.eventBus.Publish(newJobCreateKubeEvent(namespace, jobName)) + // upload shared directory + if opts.CommonInfo.ShareDir != nil { + } + podInfo, err := task.client.JobDescribe(namespace, jobName) if err != nil { return err