func CreateArangoPod(ctx context.Context, c podMod.ModInterface, deployment k8sutil.APIObject,
	deploymentSpec api.DeploymentSpec, group api.ServerGroup, pod *core.Pod) (string, types.UID, error) {
	podName, uid, err := k8sutil.CreatePod(ctx, c, pod, deployment.GetNamespace(), deployment.AsOwner())
	if err != nil {
		return "", "", errors.WithStack(err)
	}
	return podName, uid, nil
}
CreateArangoPod creates a new Pod with container provided by parameter 'containerCreator'
If the pod already exists, nil is returned.
If another error occurs, that error is returned.
package resources
import (
	"context"
	"crypto/sha1"
	"encoding/json"
	"fmt"
	"net"
	"net/url"
	"path/filepath"
	"strconv"
	"sync"
	"time"
	"github.com/arangodb/kube-arangodb/pkg/deployment/member"
	podMod "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector/pod"
	core "k8s.io/api/core/v1"
	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
	"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/tls"
	"github.com/arangodb/kube-arangodb/pkg/util"
	"github.com/arangodb/kube-arangodb/pkg/util/errors"
	"github.com/arangodb/kube-arangodb/pkg/deployment/features"
	inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector"
	"github.com/arangodb/kube-arangodb/pkg/util/k8sutil/interfaces"
	"k8s.io/apimachinery/pkg/types"
	api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
	"github.com/arangodb/kube-arangodb/pkg/deployment/pod"
	"github.com/arangodb/kube-arangodb/pkg/util/constants"
	"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
)
func createArangodArgsWithUpgrade(cachedStatus interfaces.Inspector, input pod.Input) ([]string, error) {
	return createArangodArgs(cachedStatus, input, pod.AutoUpgrade().Args(input)...)
}
func createArangodArgs(cachedStatus interfaces.Inspector, input pod.Input, additionalOptions ...k8sutil.OptionPair) ([]string, error) {
	options := k8sutil.CreateOptionPairs(64)
	scheme := "tcp"
	if input.Deployment.IsSecure() {
		scheme = "ssl"
	}
	options.Addf("--server.endpoint", "%s://%s:%d", scheme, input.Deployment.GetListenAddr(), k8sutil.ArangoPort)
	if port := input.GroupSpec.InternalPort; port != nil {
		options.Addf("--server.endpoint", "tcp://127.0.0.1:%d", *port)
	}
	options.Merge(pod.JWT().Args(input))
	options.Merge(pod.Security().Args(input))
	options.Add("--server.storage-engine", input.Deployment.GetStorageEngine().AsArangoArgument())
	options.Add("--log.level", "INFO")
	options.Append(additionalOptions...)
	options.Merge(pod.TLS().Args(input))
	options.Merge(pod.Encryption().Args(input))
	options.Add("--database.directory", k8sutil.ArangodVolumeMountDir)
	options.Add("--log.output", "+")
	options.Merge(pod.SNI().Args(input))
	endpoint, err := pod.GenerateMemberEndpoint(cachedStatus, input.ApiObject, input.Deployment, input.Group, input.Member)
	if err != nil {
		return nil, err
	}
	endpoint = util.StringOrDefault(input.Member.Endpoint, endpoint)
	myTCPURL := scheme + "://" + net.JoinHostPort(endpoint, strconv.Itoa(k8sutil.ArangoPort))
	addAgentEndpoints := false
	switch input.Group {
	case api.ServerGroupAgents:
		options.Add("--agency.disaster-recovery-id", input.Member.ID)
		options.Add("--agency.activate", "true")
		options.Add("--agency.my-address", myTCPURL)
		options.Addf("--agency.size", "%d", input.Deployment.Agents.GetCount())
		options.Add("--agency.supervision", "true")
		options.Add("--foxx.queues", false)
		options.Add("--server.statistics", "false")
		for _, p := range input.Status.Members.Agents {
			if p.ID != input.Member.ID {
				dnsName, err := pod.GenerateMemberEndpoint(cachedStatus, input.ApiObject, input.Deployment, api.ServerGroupAgents, p)
				if err != nil {
					return nil, err
				}
				options.Addf("--agency.endpoint", "%s://%s", scheme, net.JoinHostPort(util.StringOrDefault(p.Endpoint, dnsName), strconv.Itoa(k8sutil.ArangoPort)))
			}
		}
	case api.ServerGroupDBServers:
		addAgentEndpoints = true
		options.Add("--cluster.my-address", myTCPURL)
		options.Add("--cluster.my-role", "PRIMARY")
		options.Add("--foxx.queues", false)
		options.Add("--server.statistics", "true")
	case api.ServerGroupCoordinators:
		addAgentEndpoints = true
		options.Add("--cluster.my-address", myTCPURL)
		options.Add("--cluster.my-role", "COORDINATOR")
		options.Add("--foxx.queues", input.Deployment.Features.GetFoxxQueues())
		options.Add("--server.statistics", "true")
		if input.Deployment.ExternalAccess.HasAdvertisedEndpoint() {
			options.Add("--cluster.my-advertised-endpoint", input.Deployment.ExternalAccess.GetAdvertisedEndpoint())
		}
	case api.ServerGroupSingle:
		options.Add("--foxx.queues", input.Deployment.Features.GetFoxxQueues())
		options.Add("--server.statistics", "true")
		if input.Deployment.GetMode() == api.DeploymentModeActiveFailover {
			addAgentEndpoints = true
			options.Add("--replication.automatic-failover", "true")
			options.Add("--cluster.my-address", myTCPURL)
			options.Add("--cluster.my-role", "SINGLE")
			if input.Deployment.ExternalAccess.HasAdvertisedEndpoint() {
				options.Add("--cluster.my-advertised-endpoint", input.Deployment.ExternalAccess.GetAdvertisedEndpoint())
			}
		}
	}
	if addAgentEndpoints {
		for _, p := range input.Status.Members.Agents {
			dnsName, err := pod.GenerateMemberEndpoint(cachedStatus, input.ApiObject, input.Deployment, api.ServerGroupAgents, p)
			if err != nil {
				return nil, err
			}
			options.Addf("--cluster.agency-endpoint", "%s://%s", scheme, net.JoinHostPort(util.StringOrDefault(p.Endpoint, dnsName), strconv.Itoa(k8sutil.ArangoPort)))
		}
	}
	if features.EncryptionRotation().Enabled() {
		options.Add("--rocksdb.encryption-key-rotation", "true")
	}
	args := options.Copy().Sort().AsArgs()
	if len(input.GroupSpec.Args) > 0 {
		args = append(args, input.GroupSpec.Args...)
	}
	return args, nil
}
func createArangoSyncArgs(apiObject meta.Object, spec api.DeploymentSpec, group api.ServerGroup, groupSpec api.ServerGroupSpec, member api.MemberStatus) []string {
	options := k8sutil.CreateOptionPairs(64)
	var runCmd string
	var port int
	if spec.Sync.Monitoring.GetTokenSecretName() != "" {
		options.Addf("--monitoring.token", "$(%s)", constants.EnvArangoSyncMonitoringToken)
	}
	masterSecretPath := filepath.Join(k8sutil.MasterJWTSecretVolumeMountDir, constants.SecretKeyToken)
	options.Add("--master.jwt-secret", masterSecretPath)
	var masterEndpoint []string
	switch group {
	case api.ServerGroupSyncMasters:
		runCmd = "master"
		port = k8sutil.ArangoSyncMasterPort
		masterEndpoint = spec.Sync.ExternalAccess.ResolveMasterEndpoint(k8sutil.CreateSyncMasterClientServiceDNSNameWithDomain(apiObject, spec.ClusterDomain), port)
		keyPath := filepath.Join(k8sutil.TLSKeyfileVolumeMountDir, constants.SecretTLSKeyfile)
		clientCAPath := filepath.Join(k8sutil.ClientAuthCAVolumeMountDir, constants.SecretCACertificate)
		options.Add("--server.keyfile", keyPath)
		options.Add("--server.client-cafile", clientCAPath)
		options.Add("--mq.type", "direct")
		if spec.IsAuthenticated() {
			clusterSecretPath := filepath.Join(k8sutil.ClusterJWTSecretVolumeMountDir, constants.SecretKeyToken)
			options.Add("--cluster.jwt-secret", clusterSecretPath)
		}
		dbServiceName := k8sutil.CreateDatabaseClientServiceName(apiObject.GetName())
		scheme := "http"
		if spec.IsSecure() {
			scheme = "https"
		}
		options.Addf("--cluster.endpoint", "%s://%s:%d", scheme, dbServiceName, k8sutil.ArangoPort)
	case api.ServerGroupSyncWorkers:
		runCmd = "worker"
		port = k8sutil.ArangoSyncWorkerPort
		masterEndpointHost := k8sutil.CreateSyncMasterClientServiceName(apiObject.GetName())
		masterEndpoint = []string{"https://" + net.JoinHostPort(masterEndpointHost, strconv.Itoa(k8sutil.ArangoSyncMasterPort))}
	}
	for _, ep := range masterEndpoint {
		options.Add("--master.endpoint", ep)
	}
	serverEndpoint := "https://" + net.JoinHostPort(k8sutil.CreatePodDNSNameWithDomain(apiObject, spec.ClusterDomain, group.AsRole(), member.ID), strconv.Itoa(port))
	options.Add("--server.endpoint", serverEndpoint)
	options.Add("--server.port", strconv.Itoa(port))
	args := []string{
		"run",
		runCmd,
	}
	args = append(args, options.Copy().Sort().AsArgs()...)
	if len(groupSpec.Args) > 0 {
		args = append(args, groupSpec.Args...)
	}
	return args
}
func (r *Resources) CreatePodTolerations(group api.ServerGroup, groupSpec api.ServerGroupSpec) []core.Toleration {
	notReadyDur := k8sutil.TolerationDuration{Forever: false, TimeSpan: time.Minute}
	unreachableDur := k8sutil.TolerationDuration{Forever: false, TimeSpan: time.Minute}
	switch group {
	case api.ServerGroupAgents:
		notReadyDur.Forever = true
		unreachableDur.Forever = true
	case api.ServerGroupCoordinators:
		notReadyDur.TimeSpan = 15 * time.Second
		unreachableDur.TimeSpan = 15 * time.Second
	case api.ServerGroupDBServers:
		notReadyDur.TimeSpan = 5 * time.Minute
		unreachableDur.TimeSpan = 5 * time.Minute
	case api.ServerGroupSingle:
		if r.context.GetSpec().GetMode() == api.DeploymentModeSingle {
			notReadyDur.Forever = true
			unreachableDur.Forever = true
		} else {
			notReadyDur.TimeSpan = 5 * time.Minute
			unreachableDur.TimeSpan = 5 * time.Minute
		}
	case api.ServerGroupSyncMasters:
		notReadyDur.TimeSpan = 15 * time.Second
		unreachableDur.TimeSpan = 15 * time.Second
	case api.ServerGroupSyncWorkers:
		notReadyDur.TimeSpan = 1 * time.Minute
		unreachableDur.TimeSpan = 1 * time.Minute
	}
	tolerations := groupSpec.GetTolerations()
	tolerations = k8sutil.AddTolerationIfNotFound(tolerations, k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeNotReady, notReadyDur))
	tolerations = k8sutil.AddTolerationIfNotFound(tolerations, k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeUnreachable, unreachableDur))
	tolerations = k8sutil.AddTolerationIfNotFound(tolerations, k8sutil.NewNoExecuteToleration(k8sutil.TolerationKeyNodeAlphaUnreachable, unreachableDur))
	return tolerations
}
func (r *Resources) RenderPodTemplateForMember(ctx context.Context, cachedStatus inspectorInterface.Inspector, spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*core.PodTemplateSpec, error) {
	if p, err := r.RenderPodForMember(ctx, cachedStatus, spec, status, memberID, imageInfo); err != nil {
		return nil, err
	} else {
		return &core.PodTemplateSpec{
			ObjectMeta: p.ObjectMeta,
			Spec:       p.Spec,
		}, nil
	}
}
func (r *Resources) RenderPodTemplateForMemberFromCurrent(ctx context.Context, cachedStatus inspectorInterface.Inspector, memberID string) (*core.PodTemplateSpec, error) {
	if p, err := r.RenderPodForMemberFromCurrent(ctx, cachedStatus, memberID); err != nil {
		return nil, err
	} else {
		return &core.PodTemplateSpec{
			ObjectMeta: p.ObjectMeta,
			Spec:       p.Spec,
		}, nil
	}
}
func (r *Resources) RenderPodForMemberFromCurrent(ctx context.Context, cachedStatus inspectorInterface.Inspector, memberID string) (*core.Pod, error) {
	spec := r.context.GetSpec()
	status, _ := r.context.GetStatus()
	member, _, ok := status.Members.ElementByID(memberID)
	if !ok {
		return nil, errors.Newf("Member not found")
	}
	imageInfo, imageFound := r.SelectImageForMember(spec, status, member)
	if !imageFound {
		return nil, errors.Newf("ImageInfo not found")
	}
	return r.RenderPodForMember(ctx, cachedStatus, spec, status, member.ID, imageInfo)
}
func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspectorInterface.Inspector, spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*core.Pod, error) {
	log := r.log
	apiObject := r.context.GetAPIObject()
	m, group, found := status.Members.ElementByID(memberID)
	if !found {
		return nil, errors.WithStack(errors.Newf("Member '%s' not found", memberID))
	}
	groupSpec := spec.GetServerGroupSpec(group)
	memberName := m.ArangoMemberName(r.context.GetAPIObject().GetName(), group)
	member, ok := cachedStatus.ArangoMember(memberName)
	if !ok {
		return nil, errors.Newf("ArangoMember %s not found", memberName)
	}
	role := group.AsRole()
	roleAbbr := group.AsRoleAbbreviated()
	newMember := m.DeepCopy()
	newMember.PodName = k8sutil.CreatePodName(apiObject.GetName(), roleAbbr, newMember.ID, CreatePodSuffix(spec))
	var podCreator interfaces.PodCreator
	var args []string
	if group.IsArangod() {
		autoUpgrade := newMember.Conditions.IsTrue(api.ConditionTypeAutoUpgrade) || spec.Upgrade.Get().AutoUpgrade
		memberPod := MemberArangoDPod{
			status:           *newMember,
			groupSpec:        groupSpec,
			spec:             spec,
			group:            group,
			resources:        r,
			imageInfo:        imageInfo,
			context:          r.context,
			autoUpgrade:      autoUpgrade,
			deploymentStatus: status,
			id:               memberID,
			arangoMember:     *member,
		}
		input := memberPod.AsInput()
		var err error
		args, err = createArangodArgs(cachedStatus, input)
		if err != nil {
			return nil, errors.WithStack(err)
		}
		if err := memberPod.Validate(cachedStatus); err != nil {
			return nil, errors.WithStack(errors.Wrapf(err, "Validation of pods resources failed"))
		}
		podCreator = &memberPod
	} else if group.IsArangosync() {
		if !imageInfo.Enterprise {
			log.Debug().Str("image", spec.GetImage()).Msg("Image is not an enterprise image")
			return nil, errors.WithStack(errors.Newf("Image '%s' does not contain an Enterprise version of ArangoDB", spec.GetImage()))
		}
		imageInfo := imageInfo
		if spec.Sync.HasSyncImage() {
			imageInfo.Image = spec.Sync.GetSyncImage()
		}
		var tlsKeyfileSecretName, clientAuthCASecretName, masterJWTSecretName, clusterJWTSecretName string
		masterJWTSecretName = spec.Sync.Authentication.GetJWTSecretName()
		err := k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error {
			return k8sutil.ValidateTokenSecret(ctxChild, cachedStatus.SecretReadInterface(), masterJWTSecretName)
		})
		if err != nil {
			return nil, errors.WithStack(errors.Wrapf(err, "Master JWT secret validation failed"))
		}
		monitoringTokenSecretName := spec.Sync.Monitoring.GetTokenSecretName()
		err = k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error {
			return k8sutil.ValidateTokenSecret(ctxChild, cachedStatus.SecretReadInterface(), monitoringTokenSecretName)
		})
		if err != nil {
			return nil, errors.WithStack(errors.Wrapf(err, "Monitoring token secret validation failed"))
		}
		if group == api.ServerGroupSyncMasters {
			tlsKeyfileSecretName = k8sutil.CreateTLSKeyfileSecretName(apiObject.GetName(), role, newMember.ID)
			if spec.IsAuthenticated() {
				clusterJWTSecretName = spec.Authentication.GetJWTSecretName()
				err = k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error {
					return k8sutil.ValidateTokenSecret(ctxChild, cachedStatus.SecretReadInterface(), clusterJWTSecretName)
				})
				if err != nil {
					return nil, errors.WithStack(errors.Wrapf(err, "Cluster JWT secret validation failed"))
				}
			}
			clientAuthCASecretName = spec.Sync.Authentication.GetClientCASecretName()
			err = k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error {
				return k8sutil.ValidateCACertificateSecret(ctxChild, cachedStatus.SecretReadInterface(), clientAuthCASecretName)
			})
			if err != nil {
				return nil, errors.WithStack(errors.Wrapf(err, "Client authentication CA certificate secret validation failed"))
			}
		}
		args = createArangoSyncArgs(apiObject, spec, group, groupSpec, *newMember)
		memberSyncPod := MemberSyncPod{
			tlsKeyfileSecretName:   tlsKeyfileSecretName,
			clientAuthCASecretName: clientAuthCASecretName,
			masterJWTSecretName:    masterJWTSecretName,
			clusterJWTSecretName:   clusterJWTSecretName,
			groupSpec:              groupSpec,
			spec:                   spec,
			group:                  group,
			resources:              r,
			imageInfo:              imageInfo,
			arangoMember:           *member,
		}
		podCreator = &memberSyncPod
	} else {
		return nil, errors.Newf("unable to render Pod")
	}
	pod, err := RenderArangoPod(cachedStatus, apiObject, role, newMember.ID, newMember.PodName, args, podCreator)
	if err != nil {
		return nil, err
	}
	if features.RandomPodNames().Enabled() {
		pod.GenerateName = pod.Name + "-"
		pod.Name = ""
	}
	return pod, nil
}
func (r *Resources) SelectImage(spec api.DeploymentSpec, status api.DeploymentStatus) (api.ImageInfo, bool) {
	var imageInfo api.ImageInfo
	if current := status.CurrentImage; current != nil {
		imageInfo = *current
	} else {
		info, imageFound := status.Images.GetByImage(spec.GetImage())
		if !imageFound {
			return api.ImageInfo{}, false
		}
		imageInfo = info
		status.CurrentImage = &info
	}
	return imageInfo, true
}
func (r *Resources) SelectImageForMember(spec api.DeploymentSpec, status api.DeploymentStatus, member api.MemberStatus) (api.ImageInfo, bool) {
	if member.Image != nil {
		return *member.Image, true
	}
	return r.SelectImage(spec, status)
}
func (r *Resources) createPodForMember(ctx context.Context, cachedStatus inspectorInterface.Inspector, spec api.DeploymentSpec, arangoMember *api.ArangoMember, memberID string, imageNotFoundOnce *sync.Once) error {
	log := r.log
	status, lastVersion := r.context.GetStatus()
	imageInfo, imageFound := r.SelectImage(spec, status)
	if !imageFound {
		imageNotFoundOnce.Do(func() {
			log.Debug().Str("image", spec.GetImage()).Msg("Image ID is not known yet for image")
		})
		return nil
	}
	template := arangoMember.Status.Template
	if template == nil {
		return errors.Newf("Template not yet propagated")
	}
	if status.CurrentImage == nil {
		status.CurrentImage = &imageInfo
	}
	m, group, found := status.Members.ElementByID(memberID)
	if m.Image == nil {
		m.Image = status.CurrentImage
		if err := status.Members.Update(m, group); err != nil {
			return errors.WithStack(err)
		}
	}
	imageInfo = *m.Image
	apiObject := r.context.GetAPIObject()
	if !found {
		return errors.WithStack(errors.Newf("Member '%s' not found", memberID))
	}
	groupSpec := spec.GetServerGroupSpec(group)
	role := group.AsRole()
	m.PodName = template.PodSpec.GetName()
	newPhase := api.MemberPhaseCreated
	if group.IsArangod() {
		autoUpgrade := m.Conditions.IsTrue(api.ConditionTypeAutoUpgrade)
		if autoUpgrade {
			newPhase = api.MemberPhaseUpgrading
		}
		ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout())
		defer cancel()
		podName, uid, err := CreateArangoPod(ctxChild, r.context.PodsModInterface(), apiObject, spec, group, CreatePodFromTemplate(template.PodSpec))
		if err != nil {
			return errors.WithStack(err)
		}
		m.PodName = podName
		m.PodUID = uid
		m.PodSpecVersion = template.PodSpecChecksum
		m.ArangoVersion = m.Image.ArangoDBVersion
		m.ImageID = m.Image.ImageID
		m.SideCarSpecs = make(map[string]core.Container)
		for _, specSidecar := range groupSpec.GetSidecars() {
			m.SideCarSpecs[specSidecar.Name] = *specSidecar.DeepCopy()
		}
		log.Debug().Str("pod-name", m.PodName).Msg("Created pod")
		if m.Image == nil {
			log.Debug().Str("pod-name", m.PodName).Msg("Created pod with default image")
		} else {
			log.Debug().Str("pod-name", m.PodName).Msg("Created pod with predefined image")
		}
	} else if group.IsArangosync() {
		if group == api.ServerGroupSyncMasters {
			tlsKeyfileSecretName := k8sutil.CreateTLSKeyfileSecretName(apiObject.GetName(), role, m.ID)
			names, err := tls.GetAltNames(spec.Sync.TLS)
			if err != nil {
				return errors.WithStack(errors.Wrapf(err, "Failed to render alt names"))
			}
			names.AltNames = append(names.AltNames,
				k8sutil.CreateSyncMasterClientServiceName(apiObject.GetName()),
				k8sutil.CreateSyncMasterClientServiceDNSNameWithDomain(apiObject, spec.ClusterDomain),
				k8sutil.CreatePodDNSNameWithDomain(apiObject, spec.ClusterDomain, role, m.ID),
			)
			masterEndpoint := spec.Sync.ExternalAccess.ResolveMasterEndpoint(k8sutil.CreateSyncMasterClientServiceDNSNameWithDomain(apiObject, spec.ClusterDomain), k8sutil.ArangoSyncMasterPort)
			for _, ep := range masterEndpoint {
				if u, err := url.Parse(ep); err == nil {
					names.AltNames = append(names.AltNames, u.Hostname())
				}
			}
			owner := apiObject.AsOwner()
			_, err = createTLSServerCertificate(ctx, log, cachedStatus, r.context.SecretsModInterface(), names, spec.Sync.TLS, tlsKeyfileSecretName, &owner)
			if err != nil && !k8sutil.IsAlreadyExists(err) {
				return errors.WithStack(errors.Wrapf(err, "Failed to create TLS keyfile secret"))
			}
		}
		ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout())
		defer cancel()
		podName, uid, err := CreateArangoPod(ctxChild, r.context.PodsModInterface(), apiObject, spec, group, CreatePodFromTemplate(template.PodSpec))
		if err != nil {
			return errors.WithStack(err)
		}
		log.Debug().Str("pod-name", m.PodName).Msg("Created pod")
		m.PodName = podName
		m.PodUID = uid
		m.PodSpecVersion = template.PodSpecChecksum
	}
	member.GetPhaseExecutor().Execute(&m, api.Action{}, newPhase)
	if status.Topology.Enabled() {
		if m.Topology != nil && m.Topology.ID == status.Topology.ID {
			m.Conditions.Update(api.ConditionTypeTopologyAware, true, "Topology Aware", "Topology Aware")
		} else {
			m.Conditions.Update(api.ConditionTypeTopologyAware, false, "Topology spec missing", "Topology spec missing")
		}
	}
	r.log.Info().Str("pod", m.PodName).Msgf("Updating member")
	if err := status.Members.Update(m, group); err != nil {
		return errors.WithStack(err)
	}
	if err := r.context.UpdateStatus(ctx, status, lastVersion); err != nil {
		return errors.WithStack(err)
	}
	r.context.CreateEvent(k8sutil.NewPodCreatedEvent(m.PodName, role, apiObject))
	return nil
}
func RenderArangoPod(cachedStatus inspectorInterface.Inspector, deployment k8sutil.APIObject, role, id, podName string,
	args []string, podCreator interfaces.PodCreator) (*core.Pod, error) {
	p := k8sutil.NewPod(deployment.GetName(), role, id, podName, podCreator)
	for k, v := range podCreator.Annotations() {
		if p.Annotations == nil {
			p.Annotations = map[string]string{}
		}
		p.Annotations[k] = v
	}
	for k, v := range podCreator.Labels() {
		if p.Labels == nil {
			p.Labels = map[string]string{}
		}
		p.Labels[k] = v
	}
	podCreator.Init(&p)
	if initContainers, err := podCreator.GetInitContainers(cachedStatus); err != nil {
		return nil, errors.WithStack(err)
	} else if initContainers != nil {
		p.Spec.InitContainers = append(p.Spec.InitContainers, initContainers...)
	}
	c, err := k8sutil.NewContainer(args, podCreator.GetContainerCreator())
	if err != nil {
		return nil, errors.WithStack(err)
	}
	p.Spec.Volumes, c.VolumeMounts = podCreator.GetVolumes()
	p.Spec.Containers = append(p.Spec.Containers, c)
	if err := podCreator.GetSidecars(&p); err != nil {
		return nil, err
	}
	if err := podCreator.ApplyPodSpec(&p.Spec); err != nil {
		return nil, err
	}
	p.Spec.Affinity = &core.Affinity{
		NodeAffinity:    podCreator.GetNodeAffinity(),
		PodAntiAffinity: podCreator.GetPodAntiAffinity(),
		PodAffinity:     podCreator.GetPodAffinity(),
	}
	return &p, nil
}