in pkg/transformer/kubernetes/k8sutils.go [480:659]
func (k *Kubernetes) UpdateKubernetesObjects(name string, service kobject.ServiceConfig, opt kobject.ConvertOptions, objects *[]runtime.Object) error {
// Configure the environment variables.
envs, err := ConfigEnvs(service, opt)
if err != nil {
return errors.Wrap(err, "Unable to load env variables")
}
// Configure the container volumes.
volumesMount, volumes, pvc, cms, err := k.ConfigVolumes(name, service)
if err != nil {
return errors.Wrap(err, "k.ConfigVolumes failed")
}
// Configure Tmpfs
if len(service.TmpFs) > 0 {
TmpVolumesMount, TmpVolumes := k.ConfigTmpfs(name, service)
volumes = append(volumes, TmpVolumes...)
volumesMount = append(volumesMount, TmpVolumesMount...)
}
if pvc != nil && opt.Controller != StatefulStateController {
// Looping on the slice pvc instead of `*objects = append(*objects, pvc...)`
// because the type of objects and pvc is different, but when doing append
// one element at a time it gets converted to runtime.Object for objects slice
for _, p := range pvc {
*objects = append(*objects, p)
}
}
if cms != nil {
for _, c := range cms {
*objects = append(*objects, c)
}
}
// Configure the container ports.
ports := ConfigPorts(service)
// Configure capabilities
capabilities := ConfigCapabilities(service)
// Configure annotations
annotations := transformer.ConfigAnnotations(service)
// fillTemplate fills the pod template with the value calculated from config
fillTemplate := func(template *api.PodTemplateSpec) error {
template.Spec.Containers[0].Name = GetContainerName(service)
template.Spec.Containers[0].Env = envs
template.Spec.Containers[0].Command = service.Command
template.Spec.Containers[0].Args = service.Args
template.Spec.Containers[0].WorkingDir = service.WorkingDir
template.Spec.Containers[0].VolumeMounts = append(template.Spec.Containers[0].VolumeMounts, volumesMount...)
template.Spec.Containers[0].Stdin = service.Stdin
template.Spec.Containers[0].TTY = service.Tty
if opt.Controller != StatefulStateController || opt.Volumes == "configMap" {
template.Spec.Volumes = append(template.Spec.Volumes, volumes...)
}
template.Spec.Affinity = ConfigAffinity(service)
template.Spec.TopologySpreadConstraints = ConfigTopologySpreadConstraints(service)
// Configure the HealthCheck
template.Spec.Containers[0].LivenessProbe = configProbe(service.HealthChecks.Liveness)
template.Spec.Containers[0].ReadinessProbe = configProbe(service.HealthChecks.Readiness)
if service.StopGracePeriod != "" {
template.Spec.TerminationGracePeriodSeconds, err = DurationStrToSecondsInt(service.StopGracePeriod)
if err != nil {
log.Warningf("Failed to parse duration \"%v\" for service \"%v\"", service.StopGracePeriod, name)
}
}
TranslatePodResource(&service, template)
// Configure resource reservations
podSecurityContext := &api.PodSecurityContext{}
//set pid namespace mode
if service.Pid != "" {
if service.Pid == "host" {
// podSecurityContext.HostPID = true
} else {
log.Warningf("Ignoring PID key for service \"%v\". Invalid value \"%v\".", name, service.Pid)
}
}
//set supplementalGroups
if service.GroupAdd != nil {
podSecurityContext.SupplementalGroups = service.GroupAdd
}
// Setup security context
securityContext := &api.SecurityContext{}
if service.Privileged {
securityContext.Privileged = &service.Privileged
}
if service.User != "" {
uid, err := strconv.ParseInt(service.User, 10, 64)
if err != nil {
log.Warn("Ignoring user directive. User to be specified as a UID (numeric).")
} else {
securityContext.RunAsUser = &uid
}
}
//set capabilities if it is not empty
if len(capabilities.Add) > 0 || len(capabilities.Drop) > 0 {
securityContext.Capabilities = capabilities
}
// update template only if securityContext is not empty
if *securityContext != (api.SecurityContext{}) {
template.Spec.Containers[0].SecurityContext = securityContext
}
if !reflect.DeepEqual(*podSecurityContext, api.PodSecurityContext{}) {
template.Spec.SecurityContext = podSecurityContext
}
template.Spec.Containers[0].Ports = ports
template.ObjectMeta.Labels = transformer.ConfigLabelsWithNetwork(name, service.Network)
// Configure the image pull policy
if policy, err := GetImagePullPolicy(name, service.ImagePullPolicy); err != nil {
return err
} else {
template.Spec.Containers[0].ImagePullPolicy = policy
}
// Configure the container restart policy.
if restart, err := GetRestartPolicy(name, service.Restart); err != nil {
return err
} else {
template.Spec.RestartPolicy = restart
}
// Configure hostname/domain_name settings
if service.HostName != "" {
template.Spec.Hostname = service.HostName
}
if service.DomainName != "" {
template.Spec.Subdomain = service.DomainName
}
if serviceAccountName, ok := service.Labels[compose.LabelServiceAccountName]; ok {
template.Spec.ServiceAccountName = serviceAccountName
}
return nil
}
// fillObjectMeta fills the metadata with the value calculated from config
fillObjectMeta := func(meta *metav1.ObjectMeta) {
meta.Annotations = annotations
}
// update supported controller
for _, obj := range *objects {
err = k.UpdateController(obj, fillTemplate, fillObjectMeta)
if err != nil {
return errors.Wrap(err, "k.UpdateController failed")
}
if len(service.Volumes) > 0 {
switch objType := obj.(type) {
case *appsv1.Deployment:
objType.Spec.Strategy.Type = appsv1.RecreateDeploymentStrategyType
case *deployapi.DeploymentConfig:
objType.Spec.Strategy.Type = deployapi.DeploymentStrategyTypeRecreate
case *appsv1.StatefulSet:
// embed all PVCs inside the StatefulSet object
if opt.Volumes == "configMap" {
break
}
persistentVolumeClaims := make([]api.PersistentVolumeClaim, len(pvc))
for i, persistentVolumeClaim := range pvc {
persistentVolumeClaims[i] = *persistentVolumeClaim
persistentVolumeClaims[i].APIVersion = ""
persistentVolumeClaims[i].Kind = ""
}
objType.Spec.VolumeClaimTemplates = persistentVolumeClaims
}
}
}
return nil
}