diff --git a/RAP4/customizations/bootstrap/files/DeploymentInterface.php b/RAP4/customizations/bootstrap/files/DeploymentInterface.php
new file mode 100644
index 00000000..0d3d9225
--- /dev/null
+++ b/RAP4/customizations/bootstrap/files/DeploymentInterface.php
@@ -0,0 +1,8 @@
+userName = $userName;
+ $this->ee = $ee;
+ }
+
+ public function deploy() {
+ // Your Docker deployment code here
+ /** Deployed with Docker Compose */
+
+ // Stop any existing prototype container for this user
+ $remove = new Command(
+ "docker rm",
+ [ "-f",
+ "\"{$this->$userName}\""
+ ],
+ $ee->getLogger()
+ );
+ $remove->execute();
+
+ // Run student prototype with Docker
+ $this->$command = new Command(
+ "echo \"{$this->$zipContentForCommandline} {$this->$mainAldForCommandLine}\" | docker run",
+ [ "--name \"{$this->$userName}\"",
+ "--rm", # deletes the container when it is stopped. Useful to prevent container disk space usage to explode.
+ "-i",
+ "-p 8000:80",
+ "-a stdin", // stdin ensures that the content of the script is available in the container.
+ "--network proxy", // the reverse proxy Traefik is in the proxy network
+ "--label traefik.enable=true", // label for Traefik to route trafic
+ "--label traefik.docker.network=proxy", // solving RAP issue #92
+ "--label traefik.http.routers.{$this->$userName}-insecure.rule=\"Host(\\`{$this->$hostName}\\`)\"", // e.g. student123.rap.cs.ou.nl
+ "--label student-prototype", // label used by cleanup process to remove all (expired) student prototypes
+ "-e AMPERSAND_DBHOST=" . getenv('AMPERSAND_DBHOST'), // use same database host as the RAP4 application itself
+ "-e AMPERSAND_DBNAME=\"student_{$this->$userName}\"",
+ "-e AMPERSAND_DBUSER=" . getenv('AMPERSAND_DBUSER'), // TODO change db user to a student prototype specific user with less privileges and limited to databases with prefix 'student_'
+ "-e AMPERSAND_DBPASS=" . getenv('AMPERSAND_DBPASS'),
+ "-e AMPERSAND_PRODUCTION_MODE=\"false\"", // student must be able to reset his/her application
+ "-e AMPERSAND_DEBUG_MODE=\"true\"", // show student detailed log information, is needed otherwise user is e.g. not redirected to reinstall page
+ "-e AMPERSAND_SERVER_URL=\"https://{$this->$hostName}\"",
+ "-e AMPERSAND_LOG_CONFIG={$this->$studentProtoLogConfig}", // use high level logging
+ $this->$studentProtoImage // image name to run
+ ],
+ $ee->getLogger()
+ );
+ $this->$command->execute();
+
+ // Add docker container also to rap_db network
+ $command2 = new Command(
+ "docker network connect rap_db {$this->$userName}",
+ [],
+ $ee->getLogger()
+ );
+ $command2->execute();
+ }
+}
\ No newline at end of file
diff --git a/RAP4/customizations/bootstrap/files/ExecEngineFunctions.php b/RAP4/customizations/bootstrap/files/ExecEngineFunctions.php
index 2fee6f68..3a6bede8 100644
--- a/RAP4/customizations/bootstrap/files/ExecEngineFunctions.php
+++ b/RAP4/customizations/bootstrap/files/ExecEngineFunctions.php
@@ -9,6 +9,7 @@
use Ampersand\Rule\ExecEngine;
use Ampersand\Core\Link;
use Ampersand\Extension\RAP4\Command;
+use RAP4\Prototype;
/* Ampersand commands must not be changed in this file, but in a configuration yaml file.
*
@@ -290,179 +291,193 @@
* Phan analyzes the inner body of this closure as if it were a closure declared in ExecEngine.
*/
ExecEngine::registerFunction('Prototype', function (string $path, Atom $scriptAtom, Atom $scriptVersionAtom, string $userName) {
- /** @var \Ampersand\Rule\ExecEngine $ee */
$ee = $this; // because autocomplete does not work on $this
+ $prototype = new Prototype($path, $scriptAtom, $scriptVersionAtom, $userName, $ee);
+ $prototype->execute();
+});
+//ExecEngine::registerFunction('Prototype', function (string $path, Atom $scriptAtom, Atom $scriptVersionAtom, string $userName) {
+ ///** @var \Ampersand\Rule\ExecEngine $ee */
+ //$ee = $this; // because autocomplete does not work on $this
- $scriptContentPairs = $scriptVersionAtom->getLinks('content[ScriptVersion*ScriptContent]');
+ // $scriptContentPairs = $scriptVersionAtom->getLinks('content[ScriptVersion*ScriptContent]');
- $serverName = getenv('RAP_HOST_NAME');
- $studentProtoImage = getenv('RAP_STUDENT_PROTO_IMAGE');
- $studentProtoLogConfig = getenv('RAP_STUDENT_PROTO_LOG_CONFIG');
- if ($studentProtoLogConfig === false) {
- $studentProtoLogConfig = 'logging.yaml';
- }
+ // $serverName = getenv('RAP_HOST_NAME');
+ // $studentProtoImage = getenv('RAP_STUDENT_PROTO_IMAGE');
+ // $studentProtoLogConfig = getenv('RAP_STUDENT_PROTO_LOG_CONFIG');
+ // if ($studentProtoLogConfig === false) {
+ // $studentProtoLogConfig = 'logging.yaml';
+ // }
- if (count($scriptContentPairs) != 1) {
- throw new Exception("No (or multiple) script content found for '{$scriptVersionAtom}'", 500);
- }
+ // if (count($scriptContentPairs) != 1) {
+ // throw new Exception("No (or multiple) script content found for '{$scriptVersionAtom}'", 500);
+ // }
- $scriptContent = $scriptContentPairs[0]->tgt()->getId();
- $scriptContentForCommandline = base64_encode($scriptContent);
+ // $scriptContent = $scriptContentPairs[0]->tgt()->getId();
//paths
- $relDir = pathinfo($path, PATHINFO_DIRNAME);
- $workDir = realpath($ee->getApp()->getSettings()->get('global.absolutePath')) . "/data/" . $relDir;
+ // $relDir = pathinfo($path, PATHINFO_DIRNAME);
+ // $workDir = realpath($ee->getApp()->getSettings()->get('global.absolutePath')) . "/data/" . $relDir;
//zip
- $projectFolder = "{$workDir}/project";
- $mainAdl = "{$projectFolder}/main.adl";
+ // $projectFolder = "{$workDir}/project";
+ // $mainAdl = "{$projectFolder}/main.adl";
- mkdir($projectFolder);
- file_put_contents($mainAdl, $scriptContent);
-
- $zipFile = "{$workDir}/project.zip";
- $zip = new \ZipArchive;
- $zip->open($zipFile, \ZipArchive::CREATE);
- $files = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator($projectFolder),
- \RecursiveIteratorIterator::LEAVES_ONLY
- );
+ // mkdir($projectFolder);
+ // file_put_contents($mainAdl, $scriptContent);
- foreach ($files as $name => $file) {
- if (!$file->isDir()) {
- $filePath = $file->getRealPath();
- $relativePath = substr($filePath, strlen($projectFolder) + 1);
+ // $zipFile = "{$workDir}/project.zip";
+ // $zip = new \ZipArchive;
+ // $zip->open($zipFile, \ZipArchive::CREATE);
+ // $files = new \RecursiveIteratorIterator(
+ // new \RecursiveDirectoryIterator($projectFolder),
+ // \RecursiveIteratorIterator::LEAVES_ONLY
+ // );
- $zip->addFile($filePath, $relativePath);
- }
- }
+ // foreach ($files as $name => $file) {
+ // if (!$file->isDir()) {
+ // $filePath = $file->getRealPath();
+ // $relativePath = substr($filePath, strlen($projectFolder) + 1);
- $zip->close();
+ // $zip->addFile($filePath, $relativePath);
+ // }
+ // }
- $zipContent = file_get_contents($zipFile);
- $zipContentForCommandline = base64_encode($zipContent);
- $mainAldForCommandLine = base64_encode("main.adl");
+ // $zip->close();
- $pattern = '/[\W+]/';
+ // $zipContent = file_get_contents($zipFile);
+ // $zipContentForCommandline = base64_encode($zipContent);
+ // $mainAldForCommandLine = base64_encode("main.adl");
- $userName=strtolower($userName);
- $userName = preg_replace($pattern, '-', $userName);
+ // $pattern = '/[\W+]/';
- $deployment = getenv('RAP_DEPLOYMENT');
- if ($deployment == 'Kubernetes') {
- /** Deployed on Kubernetes Cluster
- * Save student-manifest-template.yaml at a logical location
- * - Copy student-manifest-template.yaml as student-manifest-{{student}}.yaml to /data/
- * - replace {{student}} and {{namespace}}
- * - replace {{adl-base64}} with base64 compiled adl file
- * - save
- * - run kubectl apply -f "student-manifest-{{student}}.yaml"
- */
+ // $userName=strtolower($userName);
+ // $userName = preg_replace($pattern, '-', $userName);
- $namespace=getenv('RAP_KUBERNETES_NAMESPACE');
- $containerImage=getenv('RAP_STUDENT_PROTO_IMAGE');
+ // $deployment = getenv('RAP_DEPLOYMENT');
+ // if ($deployment == 'Kubernetes') {
+ // /** Deployed on Kubernetes Cluster
+ // * Save student-manifest-template.yaml at a logical location
+ // * - Copy student-manifest-template.yaml as student-manifest-{{student}}.yaml to /data/
+ // * - replace {{student}} and {{namespace}}
+ // * - replace {{adl-base64}} with base64 compiled adl file
+ // * - save
+ // * - run kubectl apply -f "student-manifest-{{student}}.yaml"
+ // */
- $hostname=getenv('RAP_HOST_NAME');
- $hostname="{$userName}.{$hostname}";
+ // $namespace=getenv('RAP_KUBERNETES_NAMESPACE');
- $suffix=substr($namespace, 3);
+ // $getImageCommand = new Command(
+ // "kubectl get deployment/student-prototype{$suffix} -n {$namespace}",
+ // [ "-o=jsonpath='{$.spec.template.spec.containers[0].image}'"
+ // ],
+ // $ee->getLogger()
+ // );
- $dbName="rap-db{$suffix}";
-
- $dbSecret="db-secrets{$suffix}";
+ // $getImageCommand->execute();
- $tlsSecret="{$userName}-tls{$suffix}";
+ // $containerImage=$getImageCommand->getResponse();
- // Location to save files
- $manifestFile = $ee->getApp()->getSettings()->get('global.absolutePath') . '/bootstrap/files/student-manifest-template.yaml';
+ // $hostname=getenv('RAP_HOST_NAME');
+ // $hostname="{$userName}.{$hostname}";
- // Open student-manifest-template.yaml
- $manifest=file_get_contents($manifestFile);
- if ($manifest === false) {
- throw new Exception("Student manifest template not found for '{$scriptVersionAtom}', workDir: {$workDir}, manifestFile: {$manifestFile}", 500);
- }
- // replace {{student}}, {{namespace}} and {{scriptContent}}
- $manifest=str_replace("{{student}}", $userName, $manifest);
- $manifest=str_replace("{{namespace}}", $namespace, $manifest);
- $manifest=str_replace("{{containerImage}}", $containerImage, $manifest);
- $manifest=str_replace("{{dbName}}", $dbName, $manifest);
- $manifest=str_replace("{{dbSecrets}}", $dbSecret, $manifest);
- $manifest=str_replace("{{hostName}}", $hostname, $manifest);
- $manifest=str_replace("{{tlsSecret}}", $tlsSecret, $manifest);
- $manifest=str_replace("{{zipContent}}", $zipContentForCommandline, $manifest);
- $manifest=str_replace("{{mainAdl}}", $mainAldForCommandLine, $manifest);
+ // $suffix=substr($namespace, 3);
+
+ // $dbName="rap-db{$suffix}";
- // Save manifest file
- $studentManifestFile="{$workDir}/student-manifest-{$userName}.yaml";
- file_put_contents($studentManifestFile, $manifest);
+ // $dbSecret="db-secrets{$suffix}";
+
+ // $tlsSecret="{$userName}-tls{$suffix}";
+
+ // // Location to save files
+ // $manifestFile = $ee->getApp()->getSettings()->get('global.absolutePath') . '/bootstrap/files/student-manifest-template.yaml';
+
+ // // Open student-manifest-template.yaml
+ // $manifest=file_get_contents($manifestFile);
+ // if ($manifest === false) {
+ // throw new Exception("Student manifest template not found for '{$scriptVersionAtom}', workDir: {$workDir}, manifestFile: {$manifestFile}", 500);
+ // }
+ // // replace {{student}}, {{namespace}} and {{scriptContent}}
+ // $manifest=str_replace("{{student}}", $userName, $manifest);
+ // $manifest=str_replace("{{namespace}}", $namespace, $manifest);
+ // $manifest=str_replace("{{containerImage}}", $containerImage, $manifest);
+ // $manifest=str_replace("{{dbName}}", $dbName, $manifest);
+ // $manifest=str_replace("{{dbSecrets}}", $dbSecret, $manifest);
+ // $manifest=str_replace("{{hostName}}", $hostname, $manifest);
+ // $manifest=str_replace("{{tlsSecret}}", $tlsSecret, $manifest);
+ // $manifest=str_replace("{{zipContent}}", $zipContentForCommandline, $manifest);
+ // $manifest=str_replace("{{mainAdl}}", $mainAldForCommandLine, $manifest);
- // Call Kubernetes API to add script
- $command = new Command(
- "kubectl apply",
- [ "-f",
- "\"{$studentManifestFile}\""
- ],
- $ee->getLogger()
- );
- $command->execute();
- }
- else {
- /** Deployed with Docker Compose */
-
- // Stop any existing prototype container for this user
- $remove = new Command(
- "docker rm",
- [ "-f",
- "\"{$userName}\""
- ],
- $ee->getLogger()
- );
- $remove->execute();
+ // // Save manifest file
+ // $studentManifestFile="{$workDir}/student-manifest-{$userName}.yaml";
+ // file_put_contents($studentManifestFile, $manifest);
- // Run student prototype with Docker
- $command = new Command(
- "echo \"{$zipContentForCommandline} {$mainAldForCommandLine}\" | docker run",
- [ "--name \"{$userName}\"",
- "--rm", # deletes the container when it is stopped. Useful to prevent container disk space usage to explode.
- "-i",
- "-p 8000:80",
- "-a stdin", // stdin ensures that the content of the script is available in the container.
- "--network proxy", // the reverse proxy Traefik is in the proxy network
- "--label traefik.enable=true", // label for Traefik to route trafic
- "--label traefik.docker.network=proxy", // solving RAP issue #92
- "--label traefik.http.routers.{$userName}-insecure.rule=\"Host(\\`{$userName}.{$serverName}\\`)\"", // e.g. student123.rap.cs.ou.nl
- "--label student-prototype", // label used by cleanup process to remove all (expired) student prototypes
- "-e AMPERSAND_DBHOST=" . getenv('AMPERSAND_DBHOST'), // use same database host as the RAP4 application itself
- "-e AMPERSAND_DBNAME=\"student_{$userName}\"",
- "-e AMPERSAND_DBUSER=" . getenv('AMPERSAND_DBUSER'), // TODO change db user to a student prototype specific user with less privileges and limited to databases with prefix 'student_'
- "-e AMPERSAND_DBPASS=" . getenv('AMPERSAND_DBPASS'),
- "-e AMPERSAND_PRODUCTION_MODE=\"false\"", // student must be able to reset his/her application
- "-e AMPERSAND_DEBUG_MODE=\"true\"", // show student detailed log information, is needed otherwise user is e.g. not redirected to reinstall page
- "-e AMPERSAND_SERVER_URL=\"https://{$userName}.{$serverName}\"",
- "-e AMPERSAND_LOG_CONFIG={$studentProtoLogConfig}", // use high level logging
- $studentProtoImage // image name to run
- ],
- $ee->getLogger()
- );
- $command->execute();
+ // // Call Kubernetes API to add script
+ // $command = new Command(
+ // "kubectl apply",
+ // [ "-f",
+ // "\"{$studentManifestFile}\""
+ // ],
+ // $ee->getLogger()
+ // );
+ // $command->execute();
+ // }
+ // else {
+ // /** Deployed with Docker Compose */
+
+ // // Stop any existing prototype container for this user
+ // $remove = new Command(
+ // "docker rm",
+ // [ "-f",
+ // "\"{$userName}\""
+ // ],
+ // $ee->getLogger()
+ // );
+ // $remove->execute();
- // Add docker container also to rap_db network
- $command2 = new Command(
- "docker network connect rap_db {$userName}",
- [],
- $ee->getLogger()
- );
- $command2->execute();
- }
+ // // Run student prototype with Docker
+ // $command = new Command(
+ // "echo \"{$zipContentForCommandline} {$mainAldForCommandLine}\" | docker run",
+ // [ "--name \"{$userName}\"",
+ // "--rm", # deletes the container when it is stopped. Useful to prevent container disk space usage to explode.
+ // "-i",
+ // "-p 8000:80",
+ // "-a stdin", // stdin ensures that the content of the script is available in the container.
+ // "--network proxy", // the reverse proxy Traefik is in the proxy network
+ // "--label traefik.enable=true", // label for Traefik to route trafic
+ // "--label traefik.docker.network=proxy", // solving RAP issue #92
+ // "--label traefik.http.routers.{$userName}-insecure.rule=\"Host(\\`{$userName}.{$serverName}\\`)\"", // e.g. student123.rap.cs.ou.nl
+ // "--label student-prototype", // label used by cleanup process to remove all (expired) student prototypes
+ // "-e AMPERSAND_DBHOST=" . getenv('AMPERSAND_DBHOST'), // use same database host as the RAP4 application itself
+ // "-e AMPERSAND_DBNAME=\"student_{$userName}\"",
+ // "-e AMPERSAND_DBUSER=" . getenv('AMPERSAND_DBUSER'), // TODO change db user to a student prototype specific user with less privileges and limited to databases with prefix 'student_'
+ // "-e AMPERSAND_DBPASS=" . getenv('AMPERSAND_DBPASS'),
+ // "-e AMPERSAND_PRODUCTION_MODE=\"false\"", // student must be able to reset his/her application
+ // "-e AMPERSAND_DEBUG_MODE=\"true\"", // show student detailed log information, is needed otherwise user is e.g. not redirected to reinstall page
+ // "-e AMPERSAND_SERVER_URL=\"https://{$userName}.{$serverName}\"",
+ // "-e AMPERSAND_LOG_CONFIG={$studentProtoLogConfig}", // use high level logging
+ // $studentProtoImage // image name to run
+ // ],
+ // $ee->getLogger()
+ // );
+ // $command->execute();
+
+ // // Add docker container also to rap_db network
+ // $command2 = new Command(
+ // "docker network connect rap_db {$userName}",
+ // [],
+ // $ee->getLogger()
+ // );
+ // $command2->execute();
+ // }
- sleep(5); // helps to reduce "bad gateway" and "404 page not found" errors.
+ // sleep(5); // helps to reduce "bad gateway" and "404 page not found" errors.
// Populate 'protoOk' upon success
- setProp('protoOk[ScriptVersion*ScriptVersion]', $scriptVersionAtom, $command->getExitcode() == 0);
+ // setProp('protoOk[ScriptVersion*ScriptVersion]', $scriptVersionAtom, $command->getExitcode() == 0);
- $message = $command->getExitcode() === 0 ? "Open prototype" : $command->getResponse();
- $scriptVersionAtom->link($message, 'compileresponse[ScriptVersion*CompileResponse]')->add();
-});
+ // $message = $command->getExitcode() === 0 ? "Open prototype" : $command->getResponse();
+ // $scriptVersionAtom->link($message, 'compileresponse[ScriptVersion*CompileResponse]')->add();
+//});
/**
* @phan-closure-scope \Ampersand\Rule\ExecEngine
diff --git a/RAP4/customizations/bootstrap/files/KubernetesDeployment.php b/RAP4/customizations/bootstrap/files/KubernetesDeployment.php
new file mode 100644
index 00000000..54f84cb1
--- /dev/null
+++ b/RAP4/customizations/bootstrap/files/KubernetesDeployment.php
@@ -0,0 +1,73 @@
+userName = $userName;
+ $this->ee = $ee;
+ }
+
+ public function deploy() {
+ // Your Kubernetes deployment code here
+ /** Deployed on Kubernetes Cluster
+ * Save student-manifest-template.yaml at a logical location
+ * - Copy student-manifest-template.yaml as student-manifest-{{student}}.yaml to /data/
+ * - replace {{student}} and {{namespace}}
+ * - replace {{adl-base64}} with base64 compiled adl file
+ * - save
+ * - run kubectl apply -f "student-manifest-{{student}}.yaml"
+ */
+ $namespace=getenv('RAP_KUBERNETES_NAMESPACE');
+ $suffix=substr($namespace, 3);
+
+ $getImageCommand = new Command(
+ "kubectl get deployment/student-prototype{$suffix} -n {$namespace}",
+ [ "-o=jsonpath='{\$.spec.template.spec.containers[0].image}'"
+ ],
+ $ee->getLogger()
+ );
+ $getImageCommand->execute();
+ $containerImage=$getImageCommand->getResponse();
+
+ $dbName="rap-db{$suffix}";
+ $dbSecret="db-secrets{$suffix}";
+ $tlsSecret="{$this->$userName}-tls{$suffix}";
+ // Location to save files
+ $manifestFile = $ee->getApp()->getSettings()->get('global.absolutePath') . '/bootstrap/files/student-manifest-template.yaml';
+ // Open student-manifest-template.yaml
+ $manifest=file_get_contents($manifestFile);
+ if ($manifest === false) {
+ throw new Exception("Student manifest template not found for '{$this->$scriptVersionAtom}', workDir: {$this->$workDir}, manifestFile: {$manifestFile}", 500);
+ }
+ // replace {{student}}, {{namespace}} and {{scriptContent}}
+ $manifest=str_replace("{{student}}", $this->$userName, $manifest);
+ $manifest=str_replace("{{namespace}}", $namespace, $manifest);
+ $manifest=str_replace("{{containerImage}}", $containerImage, $manifest);
+ $manifest=str_replace("{{dbName}}", $dbName, $manifest);
+ $manifest=str_replace("{{dbSecrets}}", $dbSecret, $manifest);
+ $manifest=str_replace("{{hostName}}", $this->$hostName, $manifest);
+ $manifest=str_replace("{{tlsSecret}}", $tlsSecret, $manifest);
+ $manifest=str_replace("{{zipContent}}", $this->$zipContentForCommandline, $manifest);
+ $manifest=str_replace("{{mainAdl}}", $this->$mainAldForCommandLine, $manifest);
+ // Save manifest file
+ $studentManifestFile="{$this->$workDir}/student-manifest-{$this->$userName}.yaml";
+ file_put_contents($studentManifestFile, $manifest);
+ // Call Kubernetes API to add script
+ $this->$command = new Command(
+ "kubectl apply",
+ [ "-f",
+ "\"{$studentManifestFile}\""
+ ],
+ $ee->getLogger()
+ );
+ $this->$command->execute();
+ }
+}
\ No newline at end of file
diff --git a/RAP4/customizations/bootstrap/files/Prototype.php b/RAP4/customizations/bootstrap/files/Prototype.php
new file mode 100644
index 00000000..8d1a1593
--- /dev/null
+++ b/RAP4/customizations/bootstrap/files/Prototype.php
@@ -0,0 +1,128 @@
+scriptAtom = $scriptAtom;
+ $this->scriptVersionAtom = $scriptVersionAtom;
+ $this->ee = $ee;
+
+ $this->getEnvironmentVariables();
+
+ $relDir = pathinfo($path, PATHINFO_DIRNAME);
+ $this->$workDir = realpath($ee->getApp()->getSettings()->get('global.absolutePath')) . "/data/" . $relDir;
+
+ $pattern = '/[\W+]/';
+
+ $user = strtolower($userName);
+ $this->$userName = preg_replace($pattern, '-', $user);
+
+ if ($deployment == 'Kubernetes') {
+ $this->deploymentHandler = new KubernetesDeployment($userName, $ee);
+ } else {
+ $this->deploymentHandler = new DockerDeployment($userName, $ee);
+ }
+ }
+
+ public function execute() {
+ $this->prepareScriptContent();
+ $this->createZipFile();
+ $this->handleDeployment();
+
+ sleep(5); // helps to reduce "bad gateway" and "404 page not found" errors.
+
+ $this->populateProtoOk();
+ }
+
+ private function getEnvironmentVariables(){
+ $serverName=getenv('RAP_HOST_NAME');
+ $this->$hostName="{$this->$userName}.{$serverName}";
+ $this->$studentProtoImage = getenv('RAP_STUDENT_PROTO_IMAGE');
+ $this->$studentProtoLogConfig = getenv('RAP_STUDENT_PROTO_LOG_CONFIG');
+ if ($this->$studentProtoLogConfig === false) {
+ $this->$studentProtoLogConfig = 'logging.yaml';
+ }
+ $this->$deployment = getenv('RAP_DEPLOYMENT');
+ }
+
+ private function prepareScriptContent() : void {
+ // Code for preparing script content
+ $scriptContentPairs = $this->$scriptVersionAtom->getLinks('content[ScriptVersion*ScriptContent]');
+ if (count($scriptContentPairs) != 1) {
+ throw new Exception("No (or multiple) script content found for '{$this->$scriptVersionAtom}'", 500);
+ }
+ $this->$scriptContent = $scriptContentPairs[0]->tgt()->getId();
+ }
+
+ private function createZipFile() {
+ // Code for creating zip file
+ $projectFolder = "{$this->$workDir}/project";
+ $mainAdl = "{$projectFolder}/main.adl";
+
+ mkdir($projectFolder);
+ file_put_contents($mainAdl, $this->$scriptContent);
+
+ $zipFile = "{$this->$workDir}/project.zip";
+ $zip = new \ZipArchive;
+ $zip->open($zipFile, \ZipArchive::CREATE);
+ $files = new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator($projectFolder),
+ \RecursiveIteratorIterator::LEAVES_ONLY
+ );
+
+ foreach ($files as $name => $file) {
+ if (!$file->isDir()) {
+ $filePath = $file->getRealPath();
+ $relativePath = substr($filePath, strlen($projectFolder) + 1);
+
+ $zip->addFile($filePath, $relativePath);
+ }
+ }
+
+ $zip->close();
+
+ $zipContent = file_get_contents($zipFile);
+ $this->$zipContentForCommandline = base64_encode($zipContent);
+ $this->$mainAldForCommandLine = base64_encode("main.adl");
+ }
+
+ private function handleDeployment() {
+ // Code for handling deployment
+ $this->$deploymentHandler->deploy();
+ }
+
+ private function populateProtoOk() {
+ // Code for populating 'protoOk'
+ setProp('protoOk[ScriptVersion*ScriptVersion]', $this->$scriptVersionAtom, $this->$command->getExitcode() == 0);
+
+ $message = $this->$command->getExitcode() === 0 ? "$userName}.{$this->$serverName}\" target=\"_blank\">Open prototype" : $this->$command->getResponse();
+ $this->$scriptVersionAtom->link($message, 'compileresponse[ScriptVersion*CompileResponse]')->add();
+ }
+}