Browse Source

Parse volumes_from

Signed-off-by: aiordache <[email protected]>
aiordache 4 years ago
parent
commit
774234750d
2 changed files with 116 additions and 36 deletions
  1. 0 1
      local/compose/convergence.go
  2. 116 35
      local/compose/create.go

+ 0 - 1
local/compose/convergence.go

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

+ 116 - 35
local/compose/create.go

@@ -50,6 +50,11 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
 
 
 	prepareNetworks(project)
 	prepareNetworks(project)
 
 
+	err = prepareVolumes(project)
+	if err != nil {
+		return err
+	}
+
 	if err := s.ensureNetworks(ctx, project.Networks); err != nil {
 	if err := s.ensureNetworks(ctx, project.Networks); err != nil {
 		return err
 		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) {
 func prepareNetworks(project *types.Project) {
 	for k, network := range project.Networks {
 	for k, network := range project.Networks {
 		network.Labels = network.Labels.Add(networkLabel, k)
 		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,
 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) {
 	autoRemove bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
 
 
-	hash, err := jsonHash(s)
+	hash, err := jsonHash(service)
 	if err != nil {
 	if err != nil {
 		return nil, nil, nil, err
 		return nil, nil, nil, err
 	}
 	}
@@ -171,25 +199,11 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		stdinOpen   = service.StdinOpen
 		stdinOpen   = service.StdinOpen
 		attachStdin = false
 		attachStdin = false
 	)
 	)
-	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)
+
+	volumeMounts, binds, mounts, err := s.buildContainerVolumes(ctx, *p, service, inherit)
 	if err != nil {
 	if err != nil {
 		return nil, nil, nil, err
 		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{
 	containerConfig := container.Config{
 		Hostname:        service.Hostname,
 		Hostname:        service.Hostname,
@@ -203,7 +217,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		AttachStderr:    true,
 		AttachStderr:    true,
 		AttachStdout:    true,
 		AttachStdout:    true,
 		Cmd:             runCmd,
 		Cmd:             runCmd,
-		Image:           image,
+		Image:           getImageName(service, p.Name),
 		WorkingDir:      service.WorkingDir,
 		WorkingDir:      service.WorkingDir,
 		Entrypoint:      entrypoint,
 		Entrypoint:      entrypoint,
 		NetworkDisabled: service.NetworkMode == "disabled",
 		NetworkDisabled: service.NetworkMode == "disabled",
@@ -212,21 +226,11 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		StopSignal:      service.StopSignal,
 		StopSignal:      service.StopSignal,
 		Env:             convert.ToMobyEnv(service.Environment),
 		Env:             convert.ToMobyEnv(service.Environment),
 		Healthcheck:     convert.ToMobyHealthCheck(service.HealthCheck),
 		Healthcheck:     convert.ToMobyHealthCheck(service.HealthCheck),
-		// Volumes:         // FIXME unclear to me the overlap with HostConfig.Mounts
-		Volumes:     volumeMounts,
+		Volumes:         volumeMounts,
+
 		StopTimeout: convert.ToSeconds(service.StopGracePeriod),
 		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)
 	portBindings := buildContainerPortBindingOptions(service)
 
 
 	resources := getDeployResources(service)
 	resources := getDeployResources(service)
@@ -234,7 +238,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 	hostConfig := container.HostConfig{
 	hostConfig := container.HostConfig{
 		AutoRemove:     autoRemove,
 		AutoRemove:     autoRemove,
 		Binds:          binds,
 		Binds:          binds,
-		Mounts:         bindMounts,
+		Mounts:         mounts,
 		CapAdd:         strslice.StrSlice(service.CapAdd),
 		CapAdd:         strslice.StrSlice(service.CapAdd),
 		CapDrop:        strslice.StrSlice(service.CapDrop),
 		CapDrop:        strslice.StrSlice(service.CapDrop),
 		NetworkMode:    networkMode,
 		NetworkMode:    networkMode,
@@ -244,6 +248,8 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		Sysctls:      service.Sysctls,
 		Sysctls:      service.Sysctls,
 		PortBindings: portBindings,
 		PortBindings: portBindings,
 		Resources:    resources,
 		Resources:    resources,
+		VolumeDriver: service.VolumeDriver,
+		VolumesFrom:  service.VolumesFrom,
 	}
 	}
 
 
 	networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
 	networkConfig := buildDefaultNetworkConfig(service, networkMode, getContainerName(p.Name, service, number))
@@ -297,6 +303,69 @@ func buildContainerPortBindingOptions(s types.ServiceConfig) nat.PortMap {
 	return bindings
 	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) {
 func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby.ImageInspect, inherit *moby.Container) ([]mount.Mount, error) {
 	var mounts = map[string]mount.Mount{}
 	var mounts = map[string]mount.Mount{}
 	if inherit != nil {
 	if inherit != nil {
@@ -318,7 +387,6 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
 	}
 	}
 	if img.ContainerConfig != nil {
 	if img.ContainerConfig != nil {
 		for k := range img.ContainerConfig.Volumes {
 		for k := range img.ContainerConfig.Volumes {
-
 			mount, err := buildMount(p, types.ServiceVolumeConfig{
 			mount, err := buildMount(p, types.ServiceVolumeConfig{
 				Type:   types.VolumeTypeVolume,
 				Type:   types.VolumeTypeVolume,
 				Target: k,
 				Target: k,
@@ -327,6 +395,7 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
 				return nil, err
 				return nil, err
 			}
 			}
 			mounts[k] = mount
 			mounts[k] = mount
+
 		}
 		}
 	}
 	}
 	for _, v := range s.Volumes {
 	for _, v := range s.Volumes {
@@ -337,6 +406,17 @@ func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby
 		mounts[mount.Target] = mount
 		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))
 	values := make([]mount.Mount, 0, len(mounts))
 	for _, v := range mounts {
 	for _, v := range mounts {
 		values = append(values, v)
 		values = append(values, v)
@@ -362,9 +442,10 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 		}
 		}
 
 
 		mount, err := buildMount(p, types.ServiceVolumeConfig{
 		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 {
 		if err != nil {
 			return nil, err
 			return nil, err