Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgraded UI, Fixed minor bugs, Added Instructions for Production #31

Merged
merged 10 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 119 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ When ready, type:

```
cd backend/Docker
docker build -t playground-f .
docker build -t playground-prod .
```

To confirm that it worked, type `docker images` and you should see
`playground-f` in the list of images under the `REPOSITORY` column, for example:
`playground-prod` in the list of images under the `REPOSITORY` column, for example:

```
REPOSITORY TAG IMAGE ID CREATED SIZE
playground-f latest 8c2439e40e81 1 hour ago 201MB
playground-prod latest 8c2439e40e81 1 hour ago 201MB
```

Now move one directory up where we will set up the Python environment and the
Expand Down Expand Up @@ -95,7 +95,11 @@ curl \
--location \
--request POST '127.0.0.1:5000/run' \
--header 'Content-Type: application/json' \
--data-raw '{"code": "program hello\nprint *, \"Hello World New Line\"\nprint *, \"Hello Mars\"\nend program hello", "programInput": "", "libs": ""}'
--data-raw '{
"code": "program hello\r\n ! This is a comment line; it is ignored by the compiler\r\n print *, 'Hello, World!'\r\nend program hello\r\n",
"programInput": "",
"libs" : []
}'
```

If everything is set up correctly so far, you should get the following response:
Expand Down Expand Up @@ -133,3 +137,114 @@ playground.

Please report any issues or suggestions for improvement by opening a
[new GitHub issue](https://github.com/fortran-lang/playground/issues/new).

## Production Guide
This is a setup guide to host the server on AWS EC2. It's assuming you already have an account setup and know about free tier limitations.
#### Setting up EC2
1. Select the EC2 Launch Instance Wizard choose Ubuntu(22.04 x86) as your OS under AMI section.
2. Choose t2.micro instance if you want to stay within free tier or your preferred instance type and head to the next section. Keep configuration as default.
3. Select the storage you need, 20 GBs should be more than enough and it'll still stay under free tier. Go to next step and leave tags as default.
4. Configure the security group as follows:
![security group](https://imgur.com/a/zGTCN6F)
5. Click next to choose your key pair.(You'll be connecting to SSH via this key so keep it safe, if you don't have one already generate a new one)

Now, we need to attach an Elastic IP to this instance, as instances are allocated only a dynamic IP, also free tier only allows 1 hour of use without an elastic IP.

1. Select Elastic IP in the navigation pane, and generate a new Elastic IP.
2. Associate this Elastic IP to the instance you've just created.
3. Go to your instance and copy this Elastic IP(you'll see it listed under the v4 IP address)

#### Setting up the EC2 instance
1. Locate your key.pem file you generated in step 5 and connect to your server by using SSH:
```
sudo ssh -i <pem file> ubuntu@<Public IP of the EC2 instance>
```
2. Update your instance
```sudo apt-get update```
3. Install pip
```sudo apt install python3-pip```
4. Install nginx
`sudo apt-get install nginx`
5 Install node.js and npm using nvm.
Get NVM
``curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash`
``
Activate nvm
`. ~/.nvm/nvm.sh`
Install node
`nvm install --lts`

#### Setting up the playground on VM
1. Clone the repository
`git clone https://github.com/fortran-lang/playground.git`
2. Assign all read and write permissions to the project directory
```sudo chmod 777 playground```
```cd playground```
3. Go to frontend directory`cd playground/frontend`, before we build a production version we need to replace our API calls with the public IP.
a. Open App.js file which has our API call:
`sudo nano playground/frontend/src/App.js`
b. Replace the http://127.0.0.1:5000 url with http://{your public ip}:5000

4. Install modules `npm install`, create a build from those modules `npm run build`
4. Create a directory for the frontend with the following command:
`sudo mkdir /var/www/html/react`
Next, copy all contents from the build directory to the react directory:
`sudo cp -r /home/ubuntu/playground/frontend/build/* /var/www/html/react/`

5. To go on, set proper ownership of the react directory with the following command:
`sudo chown -R www-data:www-data /var/www/html/react`
6. Next, create an Nginx virtual host configuration file to host your React app.
`nano /etc/nginx/conf.d/react.conf`
add this to the file:
`server {
listen 80;
listen [::]:80;
root /var/www/html/react/;
index index.html index.htm;
# MODIFY SERVER_NAME EXAMPLE
location / {
try_files $uri $uri/ =404;
}
}`
7. Restart nginx
`systemctl restart nginx`

####Setting up Docker
Refer this link for [setting up docker](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository "setting up docker") (setup via repository).
After successfully installing docker switch to the Docker directory `cd playground/backend/docker`
and build the docker image `sudo docker build -t playground-prod .` .

#### Setting up the backend server
1. Go to the backend folder `cd playground/backend`.
2. Install pipenv to install packages from the pipfile
`sudo pip install pipenv`
3. Make a directory for virtual environment(this will be useful when setting up the service) using `mkdir .venv` and install all required modules using `pipenv install`
4. Start the server using:
```sudo pipenv run gunicorn --bind 0.0.0.0:5000 wsgi:app```

You'll now be able to use the app. You should also setup a service for the gunicorn server so that it starts automatically when the server boots.

#### Setting up the service
1. Create a service file for our app `sudo nano /etc/systemd/system/backend.service`
2. Write the following configuration:
```
[Unit]
Description=Gunicorn instance to serve backend for playground
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/playground/backend
Environment="PATH=/home/ubuntu/playground/backend/.venv/bin"
ExecStart=sudo /home/ubuntu/playground/backend/.venv/bin/gunicorn --workers 3 -b :5000 wsgi:app
[Install]
WantedBy=multi-user.target
```
Press Ctrl + X and save the file.
3. Start the service using `sudo systemctl start backend`
4. Then enable it so that it starts at boot:
`sudo systemctl enable myproject`

Now, You'll can directly cater requests to the port and your app should work. I recommend using a
reverse proxy for your requests by altering the nginx configuration and adding an endpoint
for the API.
5 changes: 5 additions & 0 deletions backend/Docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,8 @@ RUN git clone https://github.com/fortran-lang/stdlib.git
WORKDIR /fortran/playground/libraries/stdlib
RUN git checkout stdlib-fpm
WORKDIR /fortran/playground
COPY fpm.toml /fortran/playground/fpm.toml
COPY main.f90 /fortran/playground/app/main.f90
RUN /fortran/fpm build


14 changes: 14 additions & 0 deletions backend/Docker/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name = "playground"
author = "Ashirwad Mishra"
maintainer = "[email protected]"

[build]
auto-executables = true
auto-tests = true
auto-examples = true

[install]
library = false

[dependencies.stdlib]
path = "libraries/stdlib"
3 changes: 3 additions & 0 deletions backend/Docker/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
program sample
print*, "Sample Program"
end program sample
1 change: 1 addition & 0 deletions backend/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ docker = "*"
flask-cors = "*"
pyyaml = "*"
tomlkit = "*"
gunicorn = "*"

[dev-packages]
8 changes: 6 additions & 2 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Starting container
client = docker.from_env()
container = client.containers.run("playground-f", tty=True, detach=True, network_disabled=True, mem_limit="16g")
container = client.containers.run("playground-prod", tty=True, detach=True, network_disabled=True)

#Converting tutorial YAML
with open('tutorial.yml', 'r') as file:
Expand Down Expand Up @@ -80,7 +80,11 @@ def run_code():
edit_file(data["code"], data["programInput"], data["libs"])
code_result = execute_code_in_container()
if code_result.output[0] == None:
print(code_result.output)
output = jsonify({"executed": ""})
if '<ERROR>' in code_result.output[1].decode():
output = jsonify({"executed" : code_result.output[1].decode()})

return output, 202
output = jsonify({"executed": code_result.output[0].decode()})
print(code_result.output)
Expand All @@ -90,4 +94,4 @@ def run_code():


if __name__ == "__main__":
app.run(debug=True)
app.run(host='0.0.0.0')
3 changes: 3 additions & 0 deletions backend/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from app import app
if __name__=='__main__':
app.run()
17 changes: 16 additions & 1 deletion frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,26 @@
}

.options{

display: flex;
flex-direction: column;
width: 4em;

}

.output-formmating{
white-space: pre-wrap;

}
}

.tutButton {
display: flex;
justify-content: space-between;
}

.selector{
display: flex;
align-items: center;
margin: 2px;
}

Loading