func NewPodForGameServer(gs *mpsv1alpha1.GameServer) *corev1.Pod {
	pod := &corev1.Pod{
		ObjectMeta: metav1.ObjectMeta{
			Name:      gs.Name,  
			Namespace: gs.Namespace,
			Labels: map[string]string{
				LabelBuildID:          gs.Spec.BuildID,
				LabelBuildName:        gs.Labels[LabelBuildName],
				LabelOwningGameServer: gs.Name,
				LabelOwningOperator:   "thundernetes",
			},
			OwnerReferences: []metav1.OwnerReference{
				*metav1.NewControllerRef(gs, schema.GroupVersionKind{
					Group:   mpsv1alpha1.GroupVersion.Group,
					Version: mpsv1alpha1.GroupVersion.Version,
					Kind:    GameServerKind,
				}),
			},
		},
		Spec: gs.Spec.PodSpec,
	}
	modifyRestartPolicy(pod)
	createDataVolumeOnPod(pod)
	for i := 0; i < len(pod.Spec.Containers); i++ {
		attachDataVolumeOnContainer(&pod.Spec.Containers[i])
		pod.Spec.Containers[i].Env = append(pod.Spec.Containers[i].Env, getGameServerEnvVariables(gs)...)
	}
	attachSidecar(gs, pod)
	attachInitContainer(gs, pod)
	addServiceAccountName(pod)
	return pod
}
NewPodForGameServer returns a Kubernetes Pod struct for a specified GameServer
Pod has the same name as the GameServer
It also sets a label called "GameServer" with the value of the corresponding GameServer resource
package controllers
import (
	"bytes"
	"context"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
	mpsv1alpha1 "github.com/playfab/thundernetes/operator/api/v1alpha1"
	corev1 "k8s.io/api/core/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/log"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
	SidecarContainerName = "thundernetes-sidecar"
	InitContainerName    = "initcontainer"
	GameServerKind      = "GameServer"
	GameServerBuildKind = "GameServerBuild"
	DataVolumeName      = "data"
	DataVolumeMountPath = "/data"
	MinPort int32 = 10000
	MaxPort int32 = 50000
	RandStringSize = 5
	LabelBuildID          = "BuildID"
	LabelBuildName        = "BuildName"
	LabelOwningGameServer = "OwningGameServer"
	LabelOwningOperator   = "OwningOperator"
	serviceAccountGameServerEditor = "thundernetes-gameserver-editor"
	GsdkConfigFile             = "/data/Config/gsdkConfig.json"
	LogDirectory               = "/data/GameLogs/"
	CertificatesDirectory      = "/data/GameCertificates"
	GameSharedContentDirectory = "/data/GameSharedContent"
	SidecarPort int32 = 56001
)
var SidecarImage string
var InitContainerImage string
func init() {
	rand.Seed(time.Now().UTC().UnixNano())  
	SidecarImage = os.Getenv("THUNDERNETES_SIDECAR_IMAGE")
	if SidecarImage == "" {
		panic("THUNDERNETES_SIDECAR_IMAGE cannot be empty")
	}
	InitContainerImage = os.Getenv("THUNDERNETES_INIT_CONTAINER_IMAGE")
	if InitContainerImage == "" {
		panic("THUNDERNETES_INIT_CONTAINER_IMAGE cannot be empty")
	}
}
func generateName(prefix string) string {
	return prefix + "-" + randString(RandStringSize)
}
func randString(n int) string {
	letters := []rune("abcdefghijklmnopqrstuvwxyz")
	b := make([]rune, n)
	for i := range b {
		b[i] = letters[rand.Intn(len(letters))]
	}
	return string(b)
}
func GetPublicIPForNode(ctx context.Context, r client.Reader, nodeName string) (string, error) {
	log := log.FromContext(ctx)
	var node corev1.Node
	if err := r.Get(ctx, client.ObjectKey{Name: nodeName}, &node); err != nil {
		return "", err
	}
	for _, x := range node.Status.Addresses {
		if x.Type == corev1.NodeExternalIP {
			return x.Address, nil
		}
	}
	log.Info(fmt.Sprintf("Node with name %s does not have a Public IP, will try to return the internal IP", nodeName))
	for _, x := range node.Status.Addresses {
		if x.Type == corev1.NodeInternalIP {
			return x.Address, nil
		}
	}
	return "", fmt.Errorf("node %s does not have a Public or Internal IP", nodeName)
}
func NewGameServerForGameServerBuild(gsb *mpsv1alpha1.GameServerBuild, portRegistry *PortRegistry) (*mpsv1alpha1.GameServer, error) {
	gs := &mpsv1alpha1.GameServer{
		ObjectMeta: metav1.ObjectMeta{
			Name:      generateName(gsb.Name),
			Namespace: gsb.Namespace,
			OwnerReferences: []metav1.OwnerReference{
				*metav1.NewControllerRef(gsb, schema.GroupVersionKind{
					Group:   mpsv1alpha1.GroupVersion.Group,
					Version: mpsv1alpha1.GroupVersion.Version,
					Kind:    GameServerBuildKind,
				}),
			},
			Labels: map[string]string{LabelBuildID: gsb.Spec.BuildID, LabelBuildName: gsb.Name},
		},
		Spec: mpsv1alpha1.GameServerSpec{
			PodSpec:       gsb.Spec.PodSpec,
			BuildID:       gsb.Spec.BuildID,
			TitleID:       gsb.Spec.TitleID,
			PortsToExpose: gsb.Spec.PortsToExpose,
			BuildMetadata: gsb.Spec.BuildMetadata,
		},
	}
	for i := 0; i < len(gsb.Spec.PodSpec.Containers); i++ {
		container := gsb.Spec.PodSpec.Containers[i]
		for i := 0; i < len(container.Ports); i++ {
			if sliceContainsPortToExpose(gsb.Spec.PortsToExpose, container.Name, container.Ports[i].Name) {
				port, err := portRegistry.GetNewPort()
				if err != nil {
					return nil, err
				}
				container.Ports[i].HostPort = port
			}
		}
	}
	return gs, nil
}