Parse volumes_from

Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
aiordache 2021-01-15 09:49:56 +01:00
parent 747d2de397
commit 774234750d
2 changed files with 116 additions and 36 deletions

View File

@ -93,7 +93,6 @@ func (s *composeService) ensureService(ctx context.Context, observedState Contai
}
for _, container := range actual {
container := container
name := getCanonicalContainerName(container)
diverged := container.Labels[configHashLabel] != expected

View File

@ -50,6 +50,11 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
prepareNetworks(project)
err = prepareVolumes(project)
if err != nil {
return err
}
if err := s.ensureNetworks(ctx, project.Networks); err != nil {
return err
}
@ -91,6 +96,29 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
})
}
func prepareVolumes(p *types.Project) error {
for i := range p.Services {
volumesFrom, dependServices, err := getVolumesFrom(p, p.Services[i].VolumesFrom)
if err != nil {
return err
}
p.Services[i].VolumesFrom = volumesFrom
if len(dependServices) > 0 {
if p.Services[i].DependsOn == nil {
p.Services[i].DependsOn = make(types.DependsOnConfig, len(dependServices))
}
for _, service := range p.Services {
if contains(dependServices, service.Name) {
p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
Condition: types.ServiceConditionStarted,
}
}
}
}
}
return nil
}
func prepareNetworks(project *types.Project) {
for k, network := range project.Networks {
network.Labels = network.Labels.Add(networkLabel, k)
@ -134,7 +162,7 @@ func getImageName(service types.ServiceConfig, projectName string) string {
func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig, number int, inherit *moby.Container,
autoRemove bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
hash, err := jsonHash(s)
hash, err := jsonHash(service)
if err != nil {
return nil, nil, nil, err
}
@ -171,25 +199,11 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
stdinOpen = service.StdinOpen
attachStdin = false
)
image := getImageName(service, p.Name)
imgInspect, _, err := s.apiClient.ImageInspectWithRaw(ctx, image)
volumeMounts, binds, mounts, err := s.buildContainerVolumes(ctx, *p, service, inherit)
if err != nil {
return nil, nil, nil, err
}
mountOptions, err := buildContainerMountOptions(*p, service, imgInspect, inherit)
if err != nil {
return nil, nil, nil, err
}
volumeMounts := map[string]struct{}{}
binds := []string{}
for _, m := range mountOptions {
if m.Type == mount.TypeVolume {
volumeMounts[m.Target] = struct{}{}
if m.Source != "" {
binds = append(binds, fmt.Sprintf("%s:%s:%s", m.Source, m.Target, "rw"))
}
}
}
containerConfig := container.Config{
Hostname: service.Hostname,
@ -203,7 +217,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
AttachStderr: true,
AttachStdout: true,
Cmd: runCmd,
Image: image,
Image: getImageName(service, p.Name),
WorkingDir: service.WorkingDir,
Entrypoint: entrypoint,
NetworkDisabled: service.NetworkMode == "disabled",
@ -212,21 +226,11 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
StopSignal: service.StopSignal,
Env: convert.ToMobyEnv(service.Environment),
Healthcheck: convert.ToMobyHealthCheck(service.HealthCheck),
// Volumes: // FIXME unclear to me the overlap with HostConfig.Mounts
Volumes: volumeMounts,
Volumes: volumeMounts,
StopTimeout: convert.ToSeconds(service.StopGracePeriod),
}
// append secrets mounts
bindMounts, err := buildContainerSecretMounts(*p, service)
if err != nil {
return nil, nil, nil, err
}
for _, m := range mountOptions {
if m.Type == mount.TypeBind || m.Type == mount.TypeTmpfs {
bindMounts = append(bindMounts, m)
}
}
portBindings := buildContainerPortBindingOptions(service)
resources := getDeployResources(service)
@ -234,7 +238,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
hostConfig := container.HostConfig{
AutoRemove: autoRemove,
Binds: binds,
Mounts: bindMounts,
Mounts: mounts,
CapAdd: strslice.StrSlice(service.CapAdd),
CapDrop: strslice.StrSlice(service.CapDrop),
NetworkMode: networkMode,
@ -244,6 +248,8 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
Sysctls: service.Sysctls,
PortBindings: portBindings,
Resources: resources,
VolumeDriver: service.VolumeDriver,
VolumesFrom: service.VolumesFrom,
}
networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
@ -297,6 +303,69 @@ func buildContainerPortBindingOptions(s types.ServiceConfig) nat.PortMap {
return bindings
}
func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []string, error) {
var volumes = []string{}
var services = []string{}
// parse volumes_from
if len(volumesFrom) == 0 {
return volumes, services, nil
}
for _, vol := range volumesFrom {
spec := strings.Split(vol, ":")
if spec[0] == "container" {
volumes = append(volumes, strings.Join(spec[1:], ":"))
continue
}
serviceName := spec[0]
services = append(services, serviceName)
service, err := project.GetService(serviceName)
if err != nil {
return nil, nil, err
}
firstContainer := getContainerName(project.Name, service, 1)
v := fmt.Sprintf("%s:%s", firstContainer, strings.Join(spec[1:], ":"))
volumes = append(volumes, v)
}
return volumes, services, nil
}
func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Project, service types.ServiceConfig,
inherit *moby.Container) (map[string]struct{}, []string, []mount.Mount, error) {
var mounts = []mount.Mount{}
image := getImageName(service, p.Name)
imgInspect, _, err := s.apiClient.ImageInspectWithRaw(ctx, image)
if err != nil {
return nil, nil, nil, err
}
mountOptions, err := buildContainerMountOptions(p, service, imgInspect, inherit)
if err != nil {
return nil, nil, nil, err
}
// filter binds and volumes mount targets
volumeMounts := map[string]struct{}{}
binds := []string{}
for _, m := range mountOptions {
if m.Type == mount.TypeVolume {
volumeMounts[m.Target] = struct{}{}
if m.Source != "" {
binds = append(binds, fmt.Sprintf("%s:%s:rw", m.Source, m.Target))
}
}
}
for _, m := range mountOptions {
if m.Type == mount.TypeBind || m.Type == mount.TypeTmpfs {
mounts = append(mounts, m)
}
}
return volumeMounts, binds, mounts, nil
}
func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby.ImageInspect, inherit *moby.Container) ([]mount.Mount, error) {
var mounts = map[string]mount.Mount{}
if inherit != nil {
@ -318,7 +387,6 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
}
if img.ContainerConfig != nil {
for k := range img.ContainerConfig.Volumes {
mount, err := buildMount(p, types.ServiceVolumeConfig{
Type: types.VolumeTypeVolume,
Target: k,
@ -327,6 +395,7 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
return nil, err
}
mounts[k] = mount
}
}
for _, v := range s.Volumes {
@ -337,6 +406,17 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
mounts[mount.Target] = mount
}
secrets, err := buildContainerSecretMounts(p, s)
if err != nil {
return nil, err
}
for _, s := range secrets {
if _, found := mounts[s.Target]; found {
continue
}
mounts[s.Target] = s
}
values := make([]mount.Mount, 0, len(mounts))
for _, v := range mounts {
values = append(values, v)
@ -362,9 +442,10 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
}
mount, err := buildMount(p, types.ServiceVolumeConfig{
Type: types.VolumeTypeBind,
Source: definedSecret.File,
Target: target,
Type: types.VolumeTypeBind,
Source: definedSecret.File,
Target: target,
ReadOnly: true,
})
if err != nil {
return nil, err