Skip to content

Commit

Permalink
Merge branch 'master' into task_issue_template
Browse files Browse the repository at this point in the history
  • Loading branch information
mrniket committed Aug 14, 2018
2 parents afd7be0 + d92018a commit a3cf403
Show file tree
Hide file tree
Showing 10 changed files with 259 additions and 107 deletions.
6 changes: 5 additions & 1 deletion aimmo-game-creator/game_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,11 @@ def _make_rc(self, environment_variables, game_id):
container = kubernetes.client.V1Container(
env=[kubernetes.client.V1EnvVar(
name=env_name,
value=env_value) for env_name, env_value in environment_variables.items()],
value=env_value) for env_name, env_value in environment_variables.items()] +
[kubernetes.client.V1EnvVar(
name='POD_NAME',
value_from=kubernetes.client.V1EnvVarSource(
field_ref=kubernetes.client.V1ObjectFieldSelector(field_path='metadata.name')))],
image='ocadotechnology/aimmo-game:{}'.format(os.environ.get('IMAGE_SUFFIX', 'latest')),
ports=[kubernetes.client.V1ContainerPort(container_port=5000)],
name='aimmo-game',
Expand Down
81 changes: 56 additions & 25 deletions aimmo-game/simulation/worker_managers/kubernetes_worker_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,65 @@ def __init__(self, *args, **kwargs):
self.api = kubernetes.client.CoreV1Api()
self.game_id = os.environ['GAME_ID']
self.game_url = os.environ['GAME_URL']
self.pod_name = os.environ['POD_NAME']
super(KubernetesWorkerManager, self).__init__(*args, **kwargs)

def make_pod(self, player_id):
container = kubernetes.client.V1Container(
env=[kubernetes.client.V1EnvVar(
name='DATA_URL',
value='%s/player/%d' % (self.game_url, player_id))],
name='aimmo-game-worker',
image='ocadotechnology/aimmo-game-worker:%s' % os.environ.get('IMAGE_SUFFIX', 'latest'),
ports=[kubernetes.client.V1ContainerPort(
container_port=5000,
protocol='TCP')],
resources=kubernetes.client.V1ResourceRequirements(
limits={'cpu': '10m', 'memory': '64Mi'},
requests={'cpu': '7m', 'memory': '32Mi'}),
security_context=kubernetes.client.V1SecurityContext(
capabilities=kubernetes.client.V1Capabilities(
drop=['all'],
add=['NET_BIND_SERVICE'])))
pod_manifest = kubernetes.client.V1PodSpec(containers=[container])
@staticmethod
def _create_a_label_selector_from_labels(label_list):
return ','.join(label_list)

def _make_owner_references(self):
try:
return [kubernetes.client.V1OwnerReference(
api_version="v1",
block_owner_deletion=True,
controller=True,
kind="Pod",
name=self.pod_name,
uid=self._get_game_uid()
)]
except IndexError:
# Couldn't find the current pod
return []

def _make_container(self, player_id):
return kubernetes.client.V1Container(
env=[kubernetes.client.V1EnvVar(
name='DATA_URL',
value='%s/player/%d' % (self.game_url, player_id))],
name='aimmo-game-worker',
image='ocadotechnology/aimmo-game-worker:%s' % os.environ.get('IMAGE_SUFFIX', 'latest'),
ports=[kubernetes.client.V1ContainerPort(
container_port=5000,
protocol='TCP')],
resources=kubernetes.client.V1ResourceRequirements(
limits={'cpu': '10m', 'memory': '64Mi'},
requests={'cpu': '7m', 'memory': '32Mi'}),
security_context=kubernetes.client.V1SecurityContext(
capabilities=kubernetes.client.V1Capabilities(
drop=['all'],
add=['NET_BIND_SERVICE']))
)

def make_pod(self, player_id):
pod_manifest = kubernetes.client.V1PodSpec(containers=[self._make_container(player_id)])
metadata = kubernetes.client.V1ObjectMeta(
labels={
'app': 'aimmo-game-worker',
'game': self.game_id,
'player': str(player_id)},
generate_name="aimmo-%s-worker-%s-" % (self.game_id, player_id))
labels={
'app': 'aimmo-game-worker',
'game': self.game_id,
'player': str(player_id)},
generate_name="aimmo-%s-worker-%s-" % (self.game_id, player_id),
owner_references=self._make_owner_references()
)

return kubernetes.client.V1Pod(metadata=metadata, spec=pod_manifest)

def _get_game_uid(self):
pod_list = self.api.list_namespaced_pod(namespace=K8S_NAMESPACE,
field_selector='metadata.name={}'.format(self.pod_name))
pod_metadata = pod_list.items[0].metadata
return pod_metadata.uid

def _wait_for_pod_creation(self, pod_name, player_id):

for _ in range(90):
Expand Down Expand Up @@ -78,9 +107,11 @@ def remove_worker(self, player_id):
app_label = 'app=aimmo-game-worker'
game_label = 'game={}'.format(self.game_id)
player_label = 'player={}'.format(player_id)

label_selector = self._create_a_label_selector_from_labels([app_label,
game_label,
player_label])
pods = self.api.list_namespaced_pod(namespace=K8S_NAMESPACE,
label_selector=','.join([app_label, game_label, player_label]))
label_selector=label_selector)

for pod in pods.items:
LOGGER.info('Deleting pod: {}'.format(pod.metadata.name))
Expand Down
1 change: 0 additions & 1 deletion aimmo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ def connection_parameters(request, game_id):
LOGGER.error(e)
return HttpResponse('Unknown error occurred when getting the current avatar',
status=500)

env_connection_settings.update({'avatar_id': avatar_id})
return JsonResponse(env_connection_settings)

Expand Down
6 changes: 1 addition & 5 deletions game_frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ const initialState = {
},
game: {
connectionParameters: {
id: getGameIDFromURL() || 1,
game_url_base: '',
game_url_path: '',
game_url_port: 0,
game_ssl_flag: false
game_id: getGameIDFromURL() || 1
}
},
consoleLog: {
Expand Down
4 changes: 2 additions & 2 deletions game_frontend/src/redux/api/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import { fromEvent } from 'rxjs/observable/fromEvent'
import { pipe } from 'rxjs/Rx'

const connectToGame = () =>
map(response => {
const { game_url_base: gameUrlBase, game_url_path: gameUrlPath, avatar_id: avatarId } = response
map(action => {
const { game_url_base: gameUrlBase, game_url_path: gameUrlPath, avatar_id: avatarId } = action.payload.parameters
return io(gameUrlBase, {
path: gameUrlPath,
query: {
Expand Down
4 changes: 2 additions & 2 deletions game_frontend/src/redux/features/Editor/epics.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const getCodeEpic = (action$, store, { api }) =>
action$.pipe(
ofType(types.GET_CODE_REQUEST),
mergeMap(action =>
api.get(`code/${store.getState().game.connectionParameters.id}/`).pipe(
api.get(`code/${store.getState().game.connectionParameters.game_id}/`).pipe(
map(response => actions.getCodeReceived(response.code)),
catchError(error => Observable.of({
type: types.GET_CODE_FAILURE,
Expand All @@ -26,7 +26,7 @@ const postCodeEpic = (action$, store, { api }) =>
.pipe(
ofType(types.POST_CODE_REQUEST),
api.post(
`/aimmo/api/code/${store.getState().game.connectionParameters.id}/`,
`/aimmo/api/code/${store.getState().game.connectionParameters.game_id}/`,
() => ({ code: store.getState().editor.code })
),
map(response => actions.postCodeReceived()),
Expand Down
26 changes: 25 additions & 1 deletion game_frontend/src/redux/features/Game/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,34 @@ const unityEvent = (unityEvent, unityData, successAction, failAction) => (
}
)

const connectionParametersReceived = parameters => (
{
type: types.CONNECTION_PARAMETERS_RECEIVED,
payload: {
parameters
}
}
)

const unitySendAvatarIDSuccess = () => (
{
type: types.UNITY_SEND_AVATAR_ID_SUCCESS
}
)

const unitySendAvatarIDFail = () => (
{
type: types.UNITY_SEND_AVATAR_ID_FAIL
}
)

export default {
socketConnectToGameRequest,
sendGameStateFail,
sendGameStateSuccess,
socketGameStateReceived,
unityEvent
unityEvent,
connectionParametersReceived,
unitySendAvatarIDSuccess,
unitySendAvatarIDFail
}
40 changes: 29 additions & 11 deletions game_frontend/src/redux/features/Game/epics.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import actions from './actions'
import types from './types'
import { Observable } from 'rxjs'
import { map, mergeMap, catchError } from 'rxjs/operators'
import { map, mergeMap, catchError, delay, tap } from 'rxjs/operators'
import { ofType } from 'redux-observable'

const connectToGameEpic = (action$, store, { api: { get, socket } }) => action$.pipe(
const getConnectionParametersEpic = (action$, store, { api: { get } }) => action$.pipe(
ofType(types.SOCKET_CONNECT_TO_GAME_REQUEST),
mergeMap(action =>
get(`games/${store.getState().game.connectionParameters.id}/connection_parameters/`).pipe(
socket.connectToGame(),
socket.startListeners(),
catchError(error => Observable.of({
type: types.SOCKET_CONNECT_TO_GAME_FAIL,
payload: error,
error: true
}))
get(`games/${store.getState().game.connectionParameters.game_id}/connection_parameters/`).pipe(
map(response => actions.connectionParametersReceived(response))
)
)
)
Expand All @@ -30,7 +24,31 @@ const sendGameStateEpic = (action$, store, { api: { unity } }) => action$.pipe(
unity.sendExternalEvent(unity.emitToUnity)
)

const connectToGameEpic = (action$, store, { api: { socket, unity } }) => action$.pipe(
ofType(types.CONNECTION_PARAMETERS_RECEIVED),
socket.connectToGame(),
socket.startListeners(),
catchError(error => Observable.of({
type: types.SOCKET_CONNECT_TO_GAME_FAIL,
payload: error,
error: true
}))
)

const sendAvatarIDEpic = (action$, store, { api: { unity } }) => action$.pipe(
ofType(types.CONNECTION_PARAMETERS_RECEIVED),
map(action => actions.unityEvent(
'SetCurrentAvatarID',
parseInt(action.payload.parameters['avatar_id']),
actions.unitySendAvatarIDSuccess(),
actions.unitySendAvatarIDFail
)),
unity.sendExternalEvent(unity.emitToUnity)
)

export default {
getConnectionParametersEpic,
connectToGameEpic,
sendGameStateEpic
sendGameStateEpic,
sendAvatarIDEpic
}
Loading

0 comments on commit a3cf403

Please sign in to comment.