Skip to content

Commit

Permalink
Simpifying portsToExpose on CRD (#207)
Browse files Browse the repository at this point in the history
* simplifying CRDs.portsToExpose

* adding log level on initcontainer
  • Loading branch information
dgkanatsios committed Apr 6, 2022
1 parent 69772cd commit e1546de
Show file tree
Hide file tree
Showing 14 changed files with 71 additions and 106 deletions.
2 changes: 1 addition & 1 deletion cmd/e2e/build_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ func createE2eBuild(buildname, buildID, img string) *mpsv1alpha1.GameServerBuild
Spec: mpsv1alpha1.GameServerBuildSpec{
BuildID: buildID,
TitleID: "1E03",
PortsToExpose: []mpsv1alpha1.PortToExpose{{ContainerName: containerName, PortName: portKey}},
PortsToExpose: []int32{80},
BuildMetadata: []mpsv1alpha1.BuildMetadataItem{
{Key: "metadatakey1", Value: "metadatavalue1"},
{Key: "metadatakey2", Value: "metadatavalue2"},
Expand Down
2 changes: 1 addition & 1 deletion cmd/e2e/gameserverapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func createGameServerBuild(name, namespace, img string) mpsv1alpha1.GameServerBu
Spec: mpsv1alpha1.GameServerBuildSpec{
BuildID: uuid.New().String(),
TitleID: "1E03",
PortsToExpose: []mpsv1alpha1.PortToExpose{{ContainerName: "netcore-sample", PortName: "gameport"}},
PortsToExpose: []int32{80},
BuildMetadata: []mpsv1alpha1.BuildMetadataItem{
{Key: "metadatakey1", Value: "metadatavalue1"},
{Key: "metadatakey2", Value: "metadatavalue2"},
Expand Down
18 changes: 8 additions & 10 deletions cmd/e2e/utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,17 +334,15 @@ func verifyPodsInHostNetwork(ctx context.Context, kubeClient client.Client, gsb
for _, container := range pod.Spec.Containers {
containerName := container.Name
for _, portToExpose := range gsb.Spec.PortsToExpose {
// get the ports that this container needs exposed, from the GameServerBuild definition
if containerName == portToExpose.ContainerName {
for _, containerPortMapping := range container.Ports {
// found a port
if containerPortMapping.Name == portToExpose.PortName {
// let's make sure that hostPort is the same as containerPort (work done by the controller)
if containerPortMapping.HostPort != containerPortMapping.ContainerPort {
return fmt.Errorf("hostPort != containerPort for hostNetwork pod %s container %s, port %s", pod.Name, containerName, portToExpose.PortName)
}
for _, containerPortMapping := range container.Ports {
// found a port
if containerPortMapping.ContainerPort == portToExpose {
// let's make sure that hostPort is the same as containerPort (work done by the controller)
if containerPortMapping.HostPort != containerPortMapping.ContainerPort {
return fmt.Errorf("hostPort != containerPort for hostNetwork pod %s container %s, port %d", pod.Name, containerName, portToExpose)
}
}

}
}

Expand Down Expand Up @@ -500,7 +498,7 @@ func createTestBuild(buildName, buildID, img string) *mpsv1alpha1.GameServerBuil
Spec: mpsv1alpha1.GameServerBuildSpec{
BuildID: buildID,
TitleID: "1E03",
PortsToExpose: []mpsv1alpha1.PortToExpose{{ContainerName: containerName, PortName: portKey}},
PortsToExpose: []int32{80},
StandingBy: 2,
Max: 4,
Template: corev1.PodTemplateSpec{
Expand Down
23 changes: 23 additions & 0 deletions cmd/initcontainer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,18 @@ func main() {
getGameServerNameNamespaceFromEnv()
logger = log.WithFields(log.Fields{"GameServerName": sessionHostId, "GameServerNamespace": crdNamespace})

setLogLevel()

getRestEnvVariables()

gamePorts, gamePortConfiguration, err := parsePorts()
if err != nil {
logger.Fatalf("Could not parse game ports %s", err)
}
logger.Debugf("Parsed ports %v", gamePorts)

buildMetadata := parseBuildMetadata()
logger.Debugf("Parsed build metadata %v", buildMetadata)

config := &GsdkConfig{
HeartbeatEndpoint: fmt.Sprintf("%s:%s", nodeInternalIP, heartbeatEndpointPort),
Expand All @@ -86,6 +90,7 @@ func main() {

logger.Info("Marshalling to JSON")
configJson, err := json.Marshal(config)
logger.Debugf("Marshalled JSON: %s", configJson)
handleError(err)

logger.Info("Getting and creating folder(s)")
Expand All @@ -96,12 +101,15 @@ func main() {
logger.Infof("Creating empty GSDK JSON file %s", gsdkConfigFilePath)
f, err := os.Create(gsdkConfigFilePath)
handleError(err)
logger.Debugf("Created empty GSDK JSON file %s", gsdkConfigFilePath)

logger.Infof("Saving GSDK JSON to file %s", gsdkConfigFilePath)
_, err = f.Write(configJson)
handleError(err)
logger.Debugf("Saved GSDK JSON to file %s", gsdkConfigFilePath)
}

// parseBuildMetadata parses the build metadata from the corresponding environment variable
func parseBuildMetadata() map[string]string {
buildMetadata := make(map[string]string)
if os.Getenv("PF_GAMESERVER_BUILD_METADATA") != "" {
Expand All @@ -118,6 +126,7 @@ func parseBuildMetadata() map[string]string {
return buildMetadata
}

// parsePorts parses the portName/containerPort/hostPort from the gamePortsString
func parsePorts() (map[string]string, []GamePort, error) {
// format is port.Name + "," + containerPort + "," + hostPort + "?" + ...
// similar to how docker run -p works https://docs.docker.com/config/containers/container-networking/
Expand Down Expand Up @@ -148,6 +157,7 @@ func parsePorts() (map[string]string, []GamePort, error) {
return gamePorts, gamePortConfiguration, nil
}

// handleError panics if error != nil
func handleError(e error) {
if e != nil {
logger.Fatalf("panic because error: %s", e)
Expand Down Expand Up @@ -201,3 +211,16 @@ func getRestEnvVariables() {
nodeInternalIP = os.Getenv("PF_NODE_INTERNAL_IP")
checkEnvOrFatal("PF_NODE_INTERNAL_IP", nodeInternalIP)
}

// setLogLevel sets the log level based on the LOG_LEVEL environment variable
func setLogLevel() {
log.SetOutput(os.Stdout)
log.SetFormatter(&log.TextFormatter{})

logLevel, err := log.ParseLevel(os.Getenv("LOG_LEVEL"))
if err != nil {
logLevel = log.InfoLevel
}

log.SetLevel(logLevel)
}
4 changes: 2 additions & 2 deletions pkg/operator/api/v1alpha1/gameserver_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ type GameServerSpec struct {
// Build is the BuildID for this GameServer
BuildID string `json:"buildID,omitempty"`
//+kubebuilder:validation:Required
// PortsToExpose is an array of tuples of container/port names that correspond to the ports that will be exposed on the VM
PortsToExpose []PortToExpose `json:"portsToExpose,omitempty"`
// PortsToExpose is an array of ports that will be exposed on the VM
PortsToExpose []int32 `json:"portsToExpose,omitempty"`
// BuildMetadata is the metadata for the GameServerBuild this GameServer belongs to
BuildMetadata []BuildMetadataItem `json:"buildMetadata,omitempty"`
}
Expand Down
10 changes: 2 additions & 8 deletions pkg/operator/api/v1alpha1/gameserverbuild_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ type GameServerBuildSpec struct {
BuildID string `json:"buildID,omitempty"`

//+kubebuilder:validation:Required
// PortsToExpose is an array of tuples of container/port names that correspond to the ports that will be exposed on the VM
PortsToExpose []PortToExpose `json:"portsToExpose,omitempty"`
// PortsToExpose is an array of ports that will be exposed on the VM
PortsToExpose []int32 `json:"portsToExpose,omitempty"`

//+kubebuilder:default=5
//+kubebuilder:validation:Minimum=0
Expand Down Expand Up @@ -108,12 +108,6 @@ type GameServerBuildList struct {
Items []GameServerBuild `json:"items"`
}

// PortToExpose is a tuple of container/port names that correspond to the ports that will be exposed on the VM
type PortToExpose struct {
ContainerName string `json:"containerName"`
PortName string `json:"portName"`
}

func init() {
SchemeBuilder.Register(&GameServerBuild{}, &GameServerBuildList{})
}
Expand Down
19 changes: 2 additions & 17 deletions pkg/operator/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,11 @@ spec:
minimum: 0
type: integer
portsToExpose:
description: PortsToExpose is an array of tuples of container/port
names that correspond to the ports that will be exposed on the VM
description: PortsToExpose is an array of ports that will be exposed
on the VM
items:
description: PortToExpose is a tuple of container/port names that
correspond to the ports that will be exposed on the VM
properties:
containerName:
type: string
portName:
type: string
required:
- containerName
- portName
type: object
format: int32
type: integer
type: array
standingBy:
description: StandingBy is the requested number of standingBy servers
Expand Down
17 changes: 4 additions & 13 deletions pkg/operator/config/crd/bases/mps.playfab.com_gameservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,20 +72,11 @@ spec:
type: object
type: array
portsToExpose:
description: PortsToExpose is an array of tuples of container/port
names that correspond to the ports that will be exposed on the VM
description: PortsToExpose is an array of ports that will be exposed
on the VM
items:
description: PortToExpose is a tuple of container/port names that
correspond to the ports that will be exposed on the VM
properties:
containerName:
type: string
portName:
type: string
required:
- containerName
- portName
type: object
format: int32
type: integer
type: array
template:
description: Template describes the pod template specification of
Expand Down
2 changes: 1 addition & 1 deletion pkg/operator/config/manager/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ kind: Kustomization
images:
- name: controller
newName: thundernetes-operator
newTag: dcc9988
newTag: 104c3bb
3 changes: 2 additions & 1 deletion pkg/operator/controllers/gameserver_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,8 @@ func (r *GameServerReconciler) unassignPorts(gs *mpsv1alpha1.GameServer) error {
for i := 0; i < len(gs.Spec.Template.Spec.Containers); i++ {
container := gs.Spec.Template.Spec.Containers[i]
for j := 0; j < len(container.Ports); j++ {
if sliceContainsPortToExpose(gs.Spec.PortsToExpose, container.Name, container.Ports[j].Name) {
// if the hostPort is > 0, this means that it has been assigned by the controller
if container.Ports[j].HostPort > 0 {
hostPorts = append(hostPorts, container.Ports[j].HostPort)
}
}
Expand Down
25 changes: 13 additions & 12 deletions pkg/operator/controllers/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ func NewGameServerForGameServerBuild(gsb *mpsv1alpha1.GameServerBuild, portRegis
Labels: map[string]string{LabelBuildID: gsb.Spec.BuildID, LabelBuildName: gsb.Name},
},
Spec: mpsv1alpha1.GameServerSpec{
Template: gsb.Spec.Template,
// we're doing a DeepCopy since we modify the hostPort
Template: *gsb.Spec.Template.DeepCopy(),
BuildID: gsb.Spec.BuildID,
TitleID: gsb.Spec.TitleID,
PortsToExpose: gsb.Spec.PortsToExpose,
Expand All @@ -122,18 +123,18 @@ func NewGameServerForGameServerBuild(gsb *mpsv1alpha1.GameServerBuild, portRegis
// we don't create any status since we have the .Status subresource enabled
}
// assigning host ports for all the containers in the Template.Spec
for i := 0; i < len(gsb.Spec.Template.Spec.Containers); i++ {
container := gsb.Spec.Template.Spec.Containers[i]
for i := 0; i < len(gs.Spec.Template.Spec.Containers); i++ {
container := gs.Spec.Template.Spec.Containers[i]
for i := 0; i < len(container.Ports); i++ {
if sliceContainsPortToExpose(gsb.Spec.PortsToExpose, container.Name, container.Ports[i].Name) {
if sliceContainsPortToExpose(gsb.Spec.PortsToExpose, container.Ports[i].ContainerPort) {
port, err := portRegistry.GetNewPort()
if err != nil {
return nil, err
}
container.Ports[i].HostPort = port

// if the user has specified that they want to use the host's network, we override the container port
if gsb.Spec.Template.Spec.HostNetwork {
if gs.Spec.Template.Spec.HostNetwork {
container.Ports[i].ContainerPort = port
}
}
Expand Down Expand Up @@ -284,9 +285,9 @@ func getInitContainerEnvVariables(gs *mpsv1alpha1.GameServer) []corev1.EnvVar {
// get game ports
for _, container := range gs.Spec.Template.Spec.Containers {
for _, port := range container.Ports {
containerPort := strconv.Itoa(int(port.ContainerPort))
hostPort := strconv.Itoa(int(port.HostPort))
if sliceContainsPortToExpose(gs.Spec.PortsToExpose, container.Name, port.Name) {
if port.HostPort > 0 { // hostPort has been set, this means that this port is in the portsToExpose array
containerPort := strconv.Itoa(int(port.ContainerPort))
hostPort := strconv.Itoa(int(port.HostPort))
b.WriteString(port.Name + "," + containerPort + "," + hostPort + "?")
}
}
Expand Down Expand Up @@ -337,10 +338,10 @@ func getGameServerEnvVariables(gs *mpsv1alpha1.GameServer) []corev1.EnvVar {
return envList
}

// sliceContainsPortToExpose returns true if the specific containerName/tuple value is contained in the slice
func sliceContainsPortToExpose(slice []mpsv1alpha1.PortToExpose, containerName, portName string) bool {
for _, item := range slice {
if item.ContainerName == containerName && item.PortName == portName {
// sliceContainsPortToExpose returns true if the port is contained in the portsToExpose slice
func sliceContainsPortToExpose(portsToExpose []int32, port int32) bool {
for _, item := range portsToExpose {
if item == port {
return true
}
}
Expand Down
32 changes: 7 additions & 25 deletions pkg/operator/controllers/utilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,12 @@ var _ = Describe("Utilities tests", func() {
Expect(containsString([]string{"foo"}, "bar")).To(BeFalse())
})
It("should find if containerName/portName tuple is contained in the PortToExpose slice", func() {
p := []mpsv1alpha1.PortToExpose{
{
ContainerName: "container1",
PortName: "port1",
},
{
ContainerName: "container1",
PortName: "port2",
},
{
ContainerName: "container2",
PortName: "port1",
},
p := []int32{
5, 10, 15,
}
Expect(sliceContainsPortToExpose(p, "container1", "port1")).To(BeTrue())
Expect(sliceContainsPortToExpose(p, "container1", "port2")).To(BeTrue())
Expect(sliceContainsPortToExpose(p, "container2", "port2")).To(BeFalse())
Expect(sliceContainsPortToExpose(p, 5)).To(BeTrue())
Expect(sliceContainsPortToExpose(p, 10)).To(BeTrue())
Expect(sliceContainsPortToExpose(p, 16)).To(BeFalse())
})
It("should return env variables for GameServer", func() {
gs := &mpsv1alpha1.GameServer{
Expand All @@ -86,15 +75,8 @@ var _ = Describe("Utilities tests", func() {
Spec: mpsv1alpha1.GameServerSpec{
TitleID: "test-title",
BuildID: "test-build",
PortsToExpose: []mpsv1alpha1.PortToExpose{
{
ContainerName: "container1",
PortName: "port1",
},
{
ContainerName: "container1",
PortName: "port2",
},
PortsToExpose: []int32{
80, 443,
},
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Expand Down
3 changes: 1 addition & 2 deletions samples/netcore/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ static void Main(string[] args)
var portInfo = gameServerConnectionInfo.GamePortsConfiguration.Where(x=>x.Name == httpPortKey);
if(portInfo.Count() == 0)
{
Console.WriteLine("No port info found for " + httpPortKey);
return;
throw new Exception("No port info found for " + httpPortKey);
}
httpPort = portInfo.Single().ServerListeningPort;

Expand Down

0 comments on commit e1546de

Please sign in to comment.