github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/specgen/generate/container_create.go (about)

     1  package generate
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	cdi "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
    10  	"github.com/containers/common/libimage"
    11  	"github.com/hanks177/podman/v4/libpod"
    12  	"github.com/hanks177/podman/v4/libpod/define"
    13  	"github.com/hanks177/podman/v4/pkg/namespaces"
    14  	"github.com/hanks177/podman/v4/pkg/specgen"
    15  	"github.com/hanks177/podman/v4/pkg/util"
    16  	spec "github.com/opencontainers/runtime-spec/specs-go"
    17  	"github.com/opencontainers/selinux/go-selinux/label"
    18  	"github.com/pkg/errors"
    19  	"github.com/sirupsen/logrus"
    20  )
    21  
    22  // MakeContainer creates a container based on the SpecGenerator.
    23  // Returns the created, container and any warnings resulting from creating the
    24  // container, or an error.
    25  func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGenerator, clone bool, c *libpod.Container) (*spec.Spec, *specgen.SpecGenerator, []libpod.CtrCreateOption, error) {
    26  	rtc, err := rt.GetConfigNoCopy()
    27  	if err != nil {
    28  		return nil, nil, nil, err
    29  	}
    30  
    31  	// If joining a pod, retrieve the pod for use, and its infra container
    32  	var pod *libpod.Pod
    33  	var infra *libpod.Container
    34  	if s.Pod != "" {
    35  		pod, err = rt.LookupPod(s.Pod)
    36  		if err != nil {
    37  			return nil, nil, nil, errors.Wrapf(err, "error retrieving pod %s", s.Pod)
    38  		}
    39  		if pod.HasInfraContainer() {
    40  			infra, err = pod.InfraContainer()
    41  			if err != nil {
    42  				return nil, nil, nil, err
    43  			}
    44  		}
    45  	}
    46  
    47  	options := []libpod.CtrCreateOption{}
    48  	compatibleOptions := &libpod.InfraInherit{}
    49  	var infraSpec *spec.Spec
    50  	if infra != nil {
    51  		options, infraSpec, compatibleOptions, err = Inherit(*infra, s, rt)
    52  		if err != nil {
    53  			return nil, nil, nil, err
    54  		}
    55  	}
    56  
    57  	if err := FinishThrottleDevices(s); err != nil {
    58  		return nil, nil, nil, err
    59  	}
    60  	// Set defaults for unset namespaces
    61  	if s.PidNS.IsDefault() {
    62  		defaultNS, err := GetDefaultNamespaceMode("pid", rtc, pod)
    63  		if err != nil {
    64  			return nil, nil, nil, err
    65  		}
    66  		s.PidNS = defaultNS
    67  	}
    68  	if s.IpcNS.IsDefault() {
    69  		defaultNS, err := GetDefaultNamespaceMode("ipc", rtc, pod)
    70  		if err != nil {
    71  			return nil, nil, nil, err
    72  		}
    73  		s.IpcNS = defaultNS
    74  	}
    75  	if s.UtsNS.IsDefault() {
    76  		defaultNS, err := GetDefaultNamespaceMode("uts", rtc, pod)
    77  		if err != nil {
    78  			return nil, nil, nil, err
    79  		}
    80  		s.UtsNS = defaultNS
    81  	}
    82  	if s.UserNS.IsDefault() {
    83  		defaultNS, err := GetDefaultNamespaceMode("user", rtc, pod)
    84  		if err != nil {
    85  			return nil, nil, nil, err
    86  		}
    87  		s.UserNS = defaultNS
    88  
    89  		mappings, err := util.ParseIDMapping(namespaces.UsernsMode(s.UserNS.NSMode), nil, nil, "", "")
    90  		if err != nil {
    91  			return nil, nil, nil, err
    92  		}
    93  		s.IDMappings = mappings
    94  	}
    95  	if s.NetNS.IsDefault() {
    96  		defaultNS, err := GetDefaultNamespaceMode("net", rtc, pod)
    97  		if err != nil {
    98  			return nil, nil, nil, err
    99  		}
   100  		s.NetNS = defaultNS
   101  	}
   102  	if s.CgroupNS.IsDefault() {
   103  		defaultNS, err := GetDefaultNamespaceMode("cgroup", rtc, pod)
   104  		if err != nil {
   105  			return nil, nil, nil, err
   106  		}
   107  		s.CgroupNS = defaultNS
   108  	}
   109  
   110  	if s.ContainerCreateCommand != nil {
   111  		options = append(options, libpod.WithCreateCommand(s.ContainerCreateCommand))
   112  	}
   113  
   114  	if s.Rootfs != "" {
   115  		options = append(options, libpod.WithRootFS(s.Rootfs, s.RootfsOverlay))
   116  	}
   117  
   118  	newImage, resolvedImageName, imageData, err := getImageFromSpec(ctx, rt, s)
   119  	if err != nil {
   120  		return nil, nil, nil, err
   121  	}
   122  	if newImage != nil {
   123  		// If the input name changed, we could properly resolve the
   124  		// image. Otherwise, it must have been an ID where we're
   125  		// defaulting to the first name or an empty one if no names are
   126  		// present.
   127  		if strings.HasPrefix(newImage.ID(), resolvedImageName) {
   128  			names := newImage.Names()
   129  			if len(names) > 0 {
   130  				resolvedImageName = names[0]
   131  			}
   132  		}
   133  
   134  		options = append(options, libpod.WithRootFSFromImage(newImage.ID(), resolvedImageName, s.RawImageName))
   135  	}
   136  	if err := s.Validate(); err != nil {
   137  		return nil, nil, nil, errors.Wrap(err, "invalid config provided")
   138  	}
   139  
   140  	finalMounts, finalVolumes, finalOverlays, err := finalizeMounts(ctx, s, rt, rtc, newImage)
   141  	if err != nil {
   142  		return nil, nil, nil, err
   143  	}
   144  
   145  	if len(s.HostUsers) > 0 {
   146  		options = append(options, libpod.WithHostUsers(s.HostUsers))
   147  	}
   148  
   149  	command, err := makeCommand(s, imageData, rtc)
   150  	if err != nil {
   151  		return nil, nil, nil, err
   152  	}
   153  
   154  	infraVol := (len(compatibleOptions.Mounts) > 0 || len(compatibleOptions.Volumes) > 0 || len(compatibleOptions.ImageVolumes) > 0 || len(compatibleOptions.OverlayVolumes) > 0)
   155  	opts, err := createContainerOptions(rt, s, pod, finalVolumes, finalOverlays, imageData, command, infraVol, *compatibleOptions)
   156  	if err != nil {
   157  		return nil, nil, nil, err
   158  	}
   159  	options = append(options, opts...)
   160  
   161  	if containerType := s.InitContainerType; len(containerType) > 0 {
   162  		options = append(options, libpod.WithInitCtrType(containerType))
   163  	}
   164  	if len(s.Name) > 0 {
   165  		logrus.Debugf("setting container name %s", s.Name)
   166  		options = append(options, libpod.WithName(s.Name))
   167  	}
   168  	if len(s.Devices) > 0 {
   169  		opts = ExtractCDIDevices(s)
   170  		options = append(options, opts...)
   171  	}
   172  	runtimeSpec, err := SpecGenToOCI(ctx, s, rt, rtc, newImage, finalMounts, pod, command, compatibleOptions)
   173  	if clone { // the container fails to start if cloned due to missing Linux spec entries
   174  		if c == nil {
   175  			return nil, nil, nil, errors.New("the given container could not be retrieved")
   176  		}
   177  		conf := c.Config()
   178  		if conf != nil && conf.Spec != nil && conf.Spec.Linux != nil {
   179  			out, err := json.Marshal(conf.Spec.Linux)
   180  			if err != nil {
   181  				return nil, nil, nil, err
   182  			}
   183  			err = json.Unmarshal(out, runtimeSpec.Linux)
   184  			if err != nil {
   185  				return nil, nil, nil, err
   186  			}
   187  		}
   188  		if s.ResourceLimits != nil {
   189  			switch {
   190  			case s.ResourceLimits.CPU != nil:
   191  				runtimeSpec.Linux.Resources.CPU = s.ResourceLimits.CPU
   192  			case s.ResourceLimits.Memory != nil:
   193  				runtimeSpec.Linux.Resources.Memory = s.ResourceLimits.Memory
   194  			case s.ResourceLimits.BlockIO != nil:
   195  				runtimeSpec.Linux.Resources.BlockIO = s.ResourceLimits.BlockIO
   196  			case s.ResourceLimits.Devices != nil:
   197  				runtimeSpec.Linux.Resources.Devices = s.ResourceLimits.Devices
   198  			}
   199  		}
   200  	}
   201  	if len(s.HostDeviceList) > 0 {
   202  		options = append(options, libpod.WithHostDevice(s.HostDeviceList))
   203  	}
   204  	if infraSpec != nil && infraSpec.Linux != nil { // if we are inheriting Linux info from a pod...
   205  		// Pass Security annotations
   206  		if len(infraSpec.Annotations[define.InspectAnnotationLabel]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationLabel]) == 0 {
   207  			runtimeSpec.Annotations[define.InspectAnnotationLabel] = infraSpec.Annotations[define.InspectAnnotationLabel]
   208  		}
   209  		if len(infraSpec.Annotations[define.InspectAnnotationSeccomp]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationSeccomp]) == 0 {
   210  			runtimeSpec.Annotations[define.InspectAnnotationSeccomp] = infraSpec.Annotations[define.InspectAnnotationSeccomp]
   211  		}
   212  		if len(infraSpec.Annotations[define.InspectAnnotationApparmor]) > 0 && len(runtimeSpec.Annotations[define.InspectAnnotationApparmor]) == 0 {
   213  			runtimeSpec.Annotations[define.InspectAnnotationApparmor] = infraSpec.Annotations[define.InspectAnnotationApparmor]
   214  		}
   215  	}
   216  	return runtimeSpec, s, options, err
   217  }
   218  func ExecuteCreate(ctx context.Context, rt *libpod.Runtime, runtimeSpec *spec.Spec, s *specgen.SpecGenerator, infra bool, options ...libpod.CtrCreateOption) (*libpod.Container, error) {
   219  	ctr, err := rt.NewContainer(ctx, runtimeSpec, s, infra, options...)
   220  	if err != nil {
   221  		return ctr, err
   222  	}
   223  
   224  	return ctr, rt.PrepareVolumeOnCreateContainer(ctx, ctr)
   225  }
   226  
   227  // ExtractCDIDevices process the list of Devices in the spec and determines if any of these are CDI devices.
   228  // The CDI devices are added to the list of CtrCreateOptions.
   229  // Note that this may modify the device list associated with the spec, which should then only contain non-CDI devices.
   230  func ExtractCDIDevices(s *specgen.SpecGenerator) []libpod.CtrCreateOption {
   231  	devs := make([]spec.LinuxDevice, 0, len(s.Devices))
   232  	var cdiDevs []string
   233  	var options []libpod.CtrCreateOption
   234  
   235  	for _, device := range s.Devices {
   236  		if isCDIDevice(device.Path) {
   237  			logrus.Debugf("Identified CDI device %v", device.Path)
   238  			cdiDevs = append(cdiDevs, device.Path)
   239  			continue
   240  		}
   241  		logrus.Debugf("Non-CDI device %v; assuming standard device", device.Path)
   242  		devs = append(devs, device)
   243  	}
   244  	s.Devices = devs
   245  	if len(cdiDevs) > 0 {
   246  		options = append(options, libpod.WithCDI(cdiDevs))
   247  	}
   248  	return options
   249  }
   250  
   251  // isCDIDevice checks whether the specified device is a CDI device.
   252  func isCDIDevice(device string) bool {
   253  	return cdi.IsQualifiedName(device)
   254  }
   255  
   256  func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *libpod.Pod, volumes []*specgen.NamedVolume, overlays []*specgen.OverlayVolume, imageData *libimage.ImageData, command []string, infraVolumes bool, compatibleOptions libpod.InfraInherit) ([]libpod.CtrCreateOption, error) {
   257  	var options []libpod.CtrCreateOption
   258  	var err error
   259  
   260  	if s.PreserveFDs > 0 {
   261  		options = append(options, libpod.WithPreserveFDs(s.PreserveFDs))
   262  	}
   263  
   264  	if s.Stdin {
   265  		options = append(options, libpod.WithStdin())
   266  	}
   267  
   268  	if s.Timezone != "" {
   269  		options = append(options, libpod.WithTimezone(s.Timezone))
   270  	}
   271  	if s.Umask != "" {
   272  		options = append(options, libpod.WithUmask(s.Umask))
   273  	}
   274  	if s.Volatile {
   275  		options = append(options, libpod.WithVolatile())
   276  	}
   277  	if s.PasswdEntry != "" {
   278  		options = append(options, libpod.WithPasswdEntry(s.PasswdEntry))
   279  	}
   280  
   281  	if s.Privileged {
   282  		options = append(options, libpod.WithMountAllDevices())
   283  	}
   284  
   285  	useSystemd := false
   286  	switch s.Systemd {
   287  	case "always":
   288  		useSystemd = true
   289  	case "false":
   290  		break
   291  	case "", "true":
   292  		if len(command) == 0 && imageData != nil {
   293  			command = imageData.Config.Cmd
   294  		}
   295  
   296  		if len(command) > 0 {
   297  			useSystemdCommands := map[string]bool{
   298  				"/sbin/init":           true,
   299  				"/usr/sbin/init":       true,
   300  				"/usr/local/sbin/init": true,
   301  			}
   302  			// Grab last command in case this is launched from a shell
   303  			cmd := command
   304  			if len(command) > 2 {
   305  				// Podman build will add "/bin/sh" "-c" to
   306  				// Entrypoint. Remove and search for systemd
   307  				if command[0] == "/bin/sh" && command[1] == "-c" {
   308  					cmd = command[2:]
   309  				}
   310  			}
   311  			if useSystemdCommands[cmd[0]] || (filepath.Base(cmd[0]) == "systemd") {
   312  				useSystemd = true
   313  			}
   314  		}
   315  	default:
   316  		return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd)
   317  	}
   318  	logrus.Debugf("using systemd mode: %t", useSystemd)
   319  	if useSystemd {
   320  		// is StopSignal was not set by the user then set it to systemd
   321  		// expected StopSigal
   322  		if s.StopSignal == nil {
   323  			stopSignal, err := util.ParseSignal("RTMIN+3")
   324  			if err != nil {
   325  				return nil, errors.Wrapf(err, "error parsing systemd signal")
   326  			}
   327  			s.StopSignal = &stopSignal
   328  		}
   329  
   330  		options = append(options, libpod.WithSystemd())
   331  	}
   332  	if len(s.SdNotifyMode) > 0 {
   333  		options = append(options, libpod.WithSdNotifyMode(s.SdNotifyMode))
   334  	}
   335  	if pod != nil {
   336  		logrus.Debugf("adding container to pod %s", pod.Name())
   337  		options = append(options, rt.WithPod(pod))
   338  	}
   339  	destinations := []string{}
   340  	// Take all mount and named volume destinations.
   341  	for _, mount := range s.Mounts {
   342  		destinations = append(destinations, mount.Destination)
   343  	}
   344  	for _, volume := range volumes {
   345  		destinations = append(destinations, volume.Dest)
   346  	}
   347  	for _, overlayVolume := range overlays {
   348  		destinations = append(destinations, overlayVolume.Destination)
   349  	}
   350  	for _, imageVolume := range s.ImageVolumes {
   351  		destinations = append(destinations, imageVolume.Destination)
   352  	}
   353  
   354  	if len(destinations) > 0 || !infraVolumes {
   355  		options = append(options, libpod.WithUserVolumes(destinations))
   356  	}
   357  
   358  	if len(volumes) != 0 {
   359  		var vols []*libpod.ContainerNamedVolume
   360  		for _, v := range volumes {
   361  			vols = append(vols, &libpod.ContainerNamedVolume{
   362  				Name:    v.Name,
   363  				Dest:    v.Dest,
   364  				Options: v.Options,
   365  			})
   366  		}
   367  		options = append(options, libpod.WithNamedVolumes(vols))
   368  	}
   369  
   370  	if len(overlays) != 0 {
   371  		var vols []*libpod.ContainerOverlayVolume
   372  		for _, v := range overlays {
   373  			vols = append(vols, &libpod.ContainerOverlayVolume{
   374  				Dest:    v.Destination,
   375  				Source:  v.Source,
   376  				Options: v.Options,
   377  			})
   378  		}
   379  		options = append(options, libpod.WithOverlayVolumes(vols))
   380  	}
   381  
   382  	if len(s.ImageVolumes) != 0 {
   383  		var vols []*libpod.ContainerImageVolume
   384  		for _, v := range s.ImageVolumes {
   385  			vols = append(vols, &libpod.ContainerImageVolume{
   386  				Dest:      v.Destination,
   387  				Source:    v.Source,
   388  				ReadWrite: v.ReadWrite,
   389  			})
   390  		}
   391  		options = append(options, libpod.WithImageVolumes(vols))
   392  	}
   393  
   394  	if s.Command != nil {
   395  		options = append(options, libpod.WithCommand(s.Command))
   396  	}
   397  	if s.Entrypoint != nil {
   398  		options = append(options, libpod.WithEntrypoint(s.Entrypoint))
   399  	}
   400  	if len(s.ContainerStorageConfig.StorageOpts) > 0 {
   401  		options = append(options, libpod.WithStorageOpts(s.StorageOpts))
   402  	}
   403  	// If the user did not specify a workdir on the CLI, let's extract it
   404  	// from the image.
   405  	if s.WorkDir == "" && imageData != nil {
   406  		options = append(options, libpod.WithCreateWorkingDir())
   407  		s.WorkDir = imageData.Config.WorkingDir
   408  	}
   409  	if s.WorkDir == "" {
   410  		s.WorkDir = "/"
   411  	}
   412  	if s.CreateWorkingDir {
   413  		options = append(options, libpod.WithCreateWorkingDir())
   414  	}
   415  	if s.StopSignal != nil {
   416  		options = append(options, libpod.WithStopSignal(*s.StopSignal))
   417  	}
   418  	if s.StopTimeout != nil {
   419  		options = append(options, libpod.WithStopTimeout(*s.StopTimeout))
   420  	}
   421  	if s.Timeout != 0 {
   422  		options = append(options, libpod.WithTimeout(s.Timeout))
   423  	}
   424  	if s.LogConfiguration != nil {
   425  		if len(s.LogConfiguration.Path) > 0 {
   426  			options = append(options, libpod.WithLogPath(s.LogConfiguration.Path))
   427  		}
   428  		if s.LogConfiguration.Size > 0 {
   429  			options = append(options, libpod.WithMaxLogSize(s.LogConfiguration.Size))
   430  		}
   431  		if len(s.LogConfiguration.Options) > 0 && s.LogConfiguration.Options["tag"] != "" {
   432  			options = append(options, libpod.WithLogTag(s.LogConfiguration.Options["tag"]))
   433  		}
   434  
   435  		if len(s.LogConfiguration.Driver) > 0 {
   436  			options = append(options, libpod.WithLogDriver(s.LogConfiguration.Driver))
   437  		}
   438  	}
   439  	// Security options
   440  	if len(s.SelinuxOpts) > 0 {
   441  		options = append(options, libpod.WithSecLabels(s.SelinuxOpts))
   442  	} else if pod != nil && len(compatibleOptions.SelinuxOpts) == 0 {
   443  		// duplicate the security options from the pod
   444  		processLabel, err := pod.ProcessLabel()
   445  		if err != nil {
   446  			return nil, err
   447  		}
   448  		if processLabel != "" {
   449  			selinuxOpts, err := label.DupSecOpt(processLabel)
   450  			if err != nil {
   451  				return nil, err
   452  			}
   453  			options = append(options, libpod.WithSecLabels(selinuxOpts))
   454  		}
   455  	}
   456  	options = append(options, libpod.WithPrivileged(s.Privileged))
   457  
   458  	// Get namespace related options
   459  	namespaceOpts, err := namespaceOptions(s, rt, pod, imageData)
   460  	if err != nil {
   461  		return nil, err
   462  	}
   463  	options = append(options, namespaceOpts...)
   464  
   465  	if len(s.ConmonPidFile) > 0 {
   466  		options = append(options, libpod.WithConmonPidFile(s.ConmonPidFile))
   467  	}
   468  	options = append(options, libpod.WithLabels(s.Labels))
   469  	if s.ShmSize != nil {
   470  		options = append(options, libpod.WithShmSize(*s.ShmSize))
   471  	}
   472  	if s.Rootfs != "" {
   473  		options = append(options, libpod.WithRootFS(s.Rootfs, s.RootfsOverlay))
   474  	}
   475  	// Default used if not overridden on command line
   476  
   477  	if s.RestartPolicy != "" {
   478  		if s.RestartRetries != nil {
   479  			options = append(options, libpod.WithRestartRetries(*s.RestartRetries))
   480  		}
   481  		options = append(options, libpod.WithRestartPolicy(s.RestartPolicy))
   482  	}
   483  
   484  	if s.ContainerHealthCheckConfig.HealthConfig != nil {
   485  		options = append(options, libpod.WithHealthCheck(s.ContainerHealthCheckConfig.HealthConfig))
   486  		logrus.Debugf("New container has a health check")
   487  	}
   488  
   489  	if len(s.Secrets) != 0 {
   490  		manager, err := rt.SecretsManager()
   491  		if err != nil {
   492  			return nil, err
   493  		}
   494  		var secrs []*libpod.ContainerSecret
   495  		for _, s := range s.Secrets {
   496  			secr, err := manager.Lookup(s.Source)
   497  			if err != nil {
   498  				return nil, err
   499  			}
   500  			secrs = append(secrs, &libpod.ContainerSecret{
   501  				Secret: secr,
   502  				UID:    s.UID,
   503  				GID:    s.GID,
   504  				Mode:   s.Mode,
   505  				Target: s.Target,
   506  			})
   507  		}
   508  		options = append(options, libpod.WithSecrets(secrs))
   509  	}
   510  
   511  	if len(s.EnvSecrets) != 0 {
   512  		options = append(options, libpod.WithEnvSecrets(s.EnvSecrets))
   513  	}
   514  
   515  	if len(s.DependencyContainers) > 0 {
   516  		deps := make([]*libpod.Container, 0, len(s.DependencyContainers))
   517  		for _, ctr := range s.DependencyContainers {
   518  			depCtr, err := rt.LookupContainer(ctr)
   519  			if err != nil {
   520  				return nil, errors.Wrapf(err, "%q is not a valid container, cannot be used as a dependency", ctr)
   521  			}
   522  			deps = append(deps, depCtr)
   523  		}
   524  		options = append(options, libpod.WithDependencyCtrs(deps))
   525  	}
   526  	if s.PidFile != "" {
   527  		options = append(options, libpod.WithPidFile(s.PidFile))
   528  	}
   529  
   530  	if len(s.ChrootDirs) != 0 {
   531  		options = append(options, libpod.WithChrootDirs(s.ChrootDirs))
   532  	}
   533  
   534  	options = append(options, libpod.WithSelectedPasswordManagement(s.Passwd))
   535  
   536  	return options, nil
   537  }
   538  
   539  func Inherit(infra libpod.Container, s *specgen.SpecGenerator, rt *libpod.Runtime) (opts []libpod.CtrCreateOption, infraS *spec.Spec, compat *libpod.InfraInherit, err error) {
   540  	inheritSpec := &specgen.SpecGenerator{}
   541  	_, compatibleOptions, err := ConfigToSpec(rt, inheritSpec, infra.ID())
   542  	if err != nil {
   543  		return nil, nil, nil, err
   544  	}
   545  	options := []libpod.CtrCreateOption{}
   546  	infraConf := infra.Config()
   547  	infraSpec := infraConf.Spec
   548  
   549  	// need to set compatOptions to the currently filled specgenOptions so we do not overwrite
   550  	compatibleOptions.CapAdd = append(compatibleOptions.CapAdd, s.CapAdd...)
   551  	compatibleOptions.CapDrop = append(compatibleOptions.CapDrop, s.CapDrop...)
   552  	compatibleOptions.HostDeviceList = append(compatibleOptions.HostDeviceList, s.HostDeviceList...)
   553  	compatibleOptions.ImageVolumes = append(compatibleOptions.ImageVolumes, s.ImageVolumes...)
   554  	compatibleOptions.Mounts = append(compatibleOptions.Mounts, s.Mounts...)
   555  	compatibleOptions.OverlayVolumes = append(compatibleOptions.OverlayVolumes, s.OverlayVolumes...)
   556  	compatibleOptions.SelinuxOpts = append(compatibleOptions.SelinuxOpts, s.SelinuxOpts...)
   557  	compatibleOptions.Volumes = append(compatibleOptions.Volumes, s.Volumes...)
   558  
   559  	compatByte, err := json.Marshal(compatibleOptions)
   560  	if err != nil {
   561  		return nil, nil, nil, err
   562  	}
   563  	err = json.Unmarshal(compatByte, s)
   564  	if err != nil {
   565  		return nil, nil, nil, err
   566  	}
   567  	return options, infraSpec, compatibleOptions, nil
   568  }