PalisadoesFoundation / talawa-api

API Backend for the Talawa Mobile App. Click on the link below to see our documentation
https://docs.talawa.io/
GNU General Public License v3.0
207 stars 696 forks source link

Cloud Based API Instance for Developers #1428

Open palisadoes opened 9 months ago

palisadoes commented 9 months ago

We need to have a cloud based API instance for developers to test against. It must:

  1. Be integrated into our CI/CD pipeline so that the app is rebuilt with every newly merged PR.
  2. Initialize the database to a known working state with appropriate services will be restarted when this happens: (there are existing API calls for this):
    1. with each CI/CD update
    2. every 24 hours
  3. Use a talawa.io sub-domain as the endpoint
  4. The API instance will have a rate limiting mechanism to reduce the risk of abuse
  5. Preferably use a free service
  6. Use a palisadoes role based account for management
  7. The demo cloud API must be easily switched between branches as the code source. We will be migrating to master as the default branch soon.

Please coordinate these efforts with @noman2002 and @kb-0311. Ask to be assigned this task by them.

kirtanchandak commented 9 months ago

@noman2002 @kb-0311 I can give this issue a try

kirtanchandak commented 9 months ago

there is file named push-documentation.yml in github/workflows folder. Do we need to make changes here or create a new file?

palisadoes commented 9 months ago
  1. We used to have this working with Heroku using this file. https://github.com/PalisadoesFoundation/talawa-api/blob/develop/.github/workflows/ci.yml.archive
  2. There was some setup that was required with the Heroku cloud to make it work correctly whenever we did a merge. We decided to stop using Heroku due to the cost of having the instance running. We would like to use a fremium service.
noman2002 commented 9 months ago

@kirtanchandak Please proceed with this. You can use that file, you just need to do some minor changes. But I would suggest please check other solutions like render.com instead of Heroku.

vasujain275 commented 9 months ago

Hi @noman2002 @kirtanchandak, I have been working on this same issue containerization talawa-api using docker here - https://github.com/PalisadoesFoundation/talawa-api/pull/1418 that was merged yesterday and was working on developing a ci/cd pipeline for this exact use case, @kirtanchandak can I work on this issue if you haven't made any significant progress yet?

palisadoes commented 9 months ago

One issue per person

vasujain275 commented 9 months ago

One issue per person

Okay

github-actions[bot] commented 8 months ago

This issue did not get any activity in the past 10 days and will be closed in 180 days if no update occurs. Please check if the develop branch has fixed it and report again or close the issue.

palisadoes commented 8 months ago

@kirtanchandak Are you still working on this?

vasujain275 commented 8 months ago

@palisadoes I can work on this if @kirtanchandak is not working on this

palisadoes commented 8 months ago

Assigning to@vasujain275. Please work with @noman2002 and @kb-0311 for comments, advice and reviewing the PR

vasujain275 commented 8 months ago

Hi @noman2002 and @kb-0311, I did some research and found that the MongoDB Atlas free tier is good enough for our use case. I looked into redis free tier at render.com, it has 25 MB of memory with a 50 connection limit and no persistence storage. We can also host our API on render.com but it will be shut down after an inactivity of 5 minutes and will be restarted when called again. Will that render.com's inactivity delay or redis free tier will be a problem?

kb-0311 commented 8 months ago

@vasujain275

  1. Instead of render are there other free tier cloud instances that we can use to deploy our application?
  2. Well in production the Redis server was to be used as an in-memory cache, not a global cache so we also need to have the option to access the file system/ services of the server where the API is deployed.
  3. Render and stuff is fine but if possible can you also explore free credit use of GCP and/or Azure? Do let me know if those are feasible.
vasujain275 commented 8 months ago

@kb-0311 We can use the AWS free tier, which will have a t2.micro ec2 instance free for 12 months per account ( we will need a credit card to avail this 12-month free tier ). We can use the docker file and docker-compose file I created in a recent issue, we can set a ci/cd pipeline to push our image to the docker hub on each push and then pull to e2c using GitHub actions. We can then run docker-compose on e2c also using GitHub ci/cd that can run containers of both redis and MongoDB, although I think it will be best to run MongoDB on Atlas as it has a good free tier and will reduce the load on our t2.micro ec2 instance if we run it on atlas. We can also use azure/gcp, they also have this exact free tier of 12 months that requires a credit card on signup.

palisadoes commented 8 months ago

@vasujain275 Ideally we also want:

  1. A single account to manage all the required resources.
  2. The ability to have trusted contributors update the cloud service parameters to make sure the CI/CD functions
  3. Ensure that only one person has the right to purchase new services or upgrade any existing ones. This will help reduce long term costs and potential abuse.

Other:

  1. @kb-0311 @noman2002 Do you have anything else to add?
  2. Is the most recent comment from @vasujain275 in keeping with the desired outcome?
vasujain275 commented 8 months ago

@palisadoes

  1. Only a single aws account is required to manage this cloud instance.
  2. We only need to add the cloud service parameters as github secrets of this talawa-api repo. Then the secrets can be safely and easily used in our github actions using environment variables.
  3. Addition of github secrets can be done by any trusted contributors.
  4. Only the person who will sign up for aws instance will have the right to purchase new services or upgrade any existing ones.
  5. No one will need to directly ssh into the instance to make changes, as they will be done via ci/cd pipeline.
  6. As for MongoDB Atlas, we will only need to add the MongoDB Atlas Cluster url as github secret of this repo.

Q. How can github actions do all the changes in our aws instance? Ans. Docker Containers, we will never install the talwa api directly to our aws instance instead we will use docker container of our api that can be rebuilt and restarted every time we push changes to our repo.

My proposed solution -

  1. Firstly, I will create all github actions files and docker compose files required to completely set up talawa-api instance on aws via ci/cd.
  2. I will then test all the github actions and compose files on my personal aws ec2 instance to make sure all the things are working as intended. This way I will not be required to have direct access to talawa-api actual production ec2 instance.
  3. When all the github actions are completed and tested by me then one of the trusted contributors can signup for aws instance and MongoDB Atlas. Then he will set up the required env variables as github secrets in this repo.

@noman2002 @kb-0311 , appreciate your feedback on possible improvements in this approach

palisadoes commented 8 months ago
  1. Based on your answer we will need to manage two cloud accounts. Can this be done using only one account?
  2. We need to make sure that more than one person can access the AWS dashboard for purposes of troubleshooting. Can this be done without them having access to the credit card information to add new services?
  3. If we use a MongoDB Atlas account, how can we guarantee the same AWS access requirement above?
kb-0311 commented 8 months ago

@vasujain275

  1. Yes your solution and flow make sense to me.
  2. At this stage it would be easier to showcase the CI/CD pipeline using your forked talawa-api instance as the base for now and your free tier AWS ec2 instance as the deployment server.
  3. Create a new branch and configure the docker-compose file as necessary, since you are the owner of the forked repo you can also add the GitHub secrets for Altas and aws.
  4. Then make demo PR merges to that branch and demonstrate how to CI/CD pipeline will work using a video.
  5. This will help us understand potential problems that could occur at a given point more precisely.

@palisadoes

  1. Can you elaborate on the two accounts? Are you referring to one account for aws and another for MongoDB Atlas or something else?
  2. In aws and MongoDB I think there are certain ABAC and RBAC features for this purpose. Maybe we can take a look at that? @vasujain275
vasujain275 commented 8 months ago

@palisadoes

  1. By two accounts, If you referring to one account for aws and another for MongoDB Atlas then in my opinion it's better to have them separated as it will decrease the load on our ec2 machine.
  2. As @kb-0311 suggests there is role-based access in both aws and MongoDB Atlas that we can use to give limited access to another person for troubleshooting purposes.

@kb-0311 I will start working on this by creating a new branch "deployment" in my forked repo and will follow the process you mentioned in the previous comment.

palisadoes commented 8 months ago
  1. Yes one in AWS and the other with Mongo
  2. Remember this will be solely for demo purposes not a heavily used system with only a few transactions per hour for developers to test against. Keep this in mind with your final recommendation.
vasujain275 commented 8 months ago

@palisadoes Okay I will keep that in mind

palisadoes commented 8 months ago

What's the status on this? It's an important part of our 2023 road map. We need this up and running by very early January.

vasujain275 commented 8 months ago

@palisadoes

Sorry for the delay, I have programmed deploy.yml locally but having some issues with my credit card on aws so not able to test it. I will positively resolve it within a couple of days.

palisadoes commented 8 months ago

@vasujain275 If AWS is a difficulty, what would be the minimal Ubuntu VPS required with GoDaddy to get a test instance running? We could provide access via a public/private SSH key for security.

We really need to get this going.

vasujain275 commented 8 months ago

@palisadoes I got the AWS ec2 instance working, I only had debit cards and it was not accepting them. I found a credit card and it worked, I have been testing the code for the past couple of hours. Creating a PR in couple of minutes

palisadoes commented 8 months ago

Please answer my question on the GoDaddy VPS.

With that solution we would have a fixed cost and not have to worry about unexpected cloud charges.

Let me know

vasujain275 commented 8 months ago

@palisadoes

  1. Yeah, we can do a basic GoDaddy VPS and that works fine because we just need an Ubuntu Server.
  2. As for the aws free tier machine, it is really slow and can cause issues in the long run. Build times are around 15min on that.
  3. GoDaddy VPS would be a much better option than aws free tier as we don't have to worry about unexpected web charges as you mentioned and will have better performance.
  4. Regarding MongoDB hosted on different cloud, I agree with you that having one cloud is better option and from my testing it will not affect our performance. We should go with one cloud instance only.
  5. I am improving the docker compose file with more layer caching so that we can reduce build time and overall make the process more efficient.
palisadoes commented 8 months ago

If we had a VPS we could host mongo on the local server for simplicity.

What would your minimum be?

Remember, we will be resetting the DB every 24 hours. So we don't need a lot of disk.

vasujain275 commented 8 months ago

@palisadoes I believe that hosting MongoDB, Redis, and Talawa API on the same VPS is feasible. In this scenario, I think the basic plan (1 vCPU / 2GB RAM / 40GB Storage) would be sufficient.

palisadoes commented 8 months ago

@vasujain275

  1. Please DM me your ssh public key in slack so I can add you to the server.
  2. What directory structure would you propose to get this set up?
  3. Under what user would this all run under? I'd prefer for everything to run as a dedicated unprivileged account.

@kb-0311

vasujain275 commented 8 months ago

@palisadoes

  1. Dmed you my ssh public key on slack.
  2. We will need only one directory that is talawa-api/ repo dir that will pull new changes on new push. Other data like MongoDB and redis persistent storage will be stored in docker volumes that are created by docker-compose.
  3. For routine operations, let's use a dedicated unprivileged account. But for tasks like installing dependencies and GitHub Actions also need sudo. I propose a user with sudo privileges for these tasks.
palisadoes commented 8 months ago
  1. Check slack for details.
  2. Please continue the discussion in the PR
github-actions[bot] commented 7 months ago

This issue did not get any activity in the past 10 days and will be closed in 180 days if no update occurs. Please check if the develop branch has fixed it and report again or close the issue.

vasujain275 commented 7 months ago

@kb-0311 @palisadoes So moving forward we need -

  1. All scripts converted to python instead of bash.
  2. A way to populate .env file variables from github repo secrets on every merge during deploy.yml workflow.
palisadoes commented 7 months ago

Yes.

  1. Use this when executing commands. It gives better error reporting than os.system
    1. https://docs.python.org/3/library/subprocess.html#subprocess.Popen.communicate
  2. Use this for parsing arguments. It will make the CLI more readable and there are fail-safes and built in help
    1. https://docs.python.org/3/library/argparse.html
  3. Make sure the scripts follow the Google python style guide
    1. https://google.github.io/styleguide/pyguide.html
    2. Especially this section
      1. https://google.github.io/styleguide/pyguide.html
  4. The scripts must be python black, pycodestyle, pylint, pydocstyle and flake8 compliant. Do not put the checks in the YAML. This may be another PR
palisadoes commented 7 months ago

@vasujain275 @kb-0311

The workflow is failing.

This needs to be fixed. It states there is no space on the system, this could also be an authorization issue as I have seen erroneous space related errors related to access.

vasujain275 commented 7 months ago

@palisadoes

The cloud instance of talawa-api was out of storage due to old containers and images created by workflow: Screenshot_14-Jan_22-51-38_5075

Added the step to remove all the unwanted images and containers after the talawa-api containers are up and running in deploy.yaml workflow in this pr - https://github.com/PalisadoesFoundation/talawa-api/pull/1687

Already fixed the deploy.sh file on the GoDaay VPS and tested the workflow too.

vasujain275 commented 7 months ago

Do not put the checks in the YAML. This may be another PR

@palisadoes Should I only add python scripts to pr for now and leave deploy.yaml workflow unchanged? Please clarify.

palisadoes commented 7 months ago
  1. Focus on the scripts first
  2. Then we can work on the deployment secrets
palisadoes commented 7 months ago

We will need to move the functionality of deploy.yaml over to push.yaml where all our other push logic is located.

palisadoes commented 7 months ago

@vasujain275

The workflow is failing again:

vasujain275 commented 7 months ago

@palisadoes It failed because I was testing python scripts on the vps, otherwise it is working fine

palisadoes commented 7 months ago
  1. Thanks @vasujain275 - One more step to go.
    1. https://github.com/PalisadoesFoundation/talawa-api/pull/1704
  2. Now we need to move the deploy.yml functionality over to push.yml
vasujain275 commented 7 months ago

@palisadoes

  1. I am working on moving the functionality from deploy.yml to push.yml.
  2. Additionally, don't we need a way to populate the .env file on the VPS with Talawa API GitHub repository secrets for better security?"
palisadoes commented 7 months ago

Yes, that can be done with a separate python deployment script just for creating the .env file. It can

  1. Create its own base .env file
  2. Use argparse for each required variable retrieved from the appropriate GitHub secrets
vasujain275 commented 6 months ago

@palisadoes The deploy action to Cloud API will be down for a few hours as I am migrating it to a new process and python scripts. I will raise a PR once I am done testing the new scripts thoroughly.

Manik2708 commented 6 months ago

@palisadoes The deploy action to Cloud API will be down for a few hours as I am migrating it to a new process and python scripts. I will raise a PR once I am done testing the new scripts thoroughly.

Hi, actually I saw that there are no tests for Redis Caching Services. I have an idea to do this, @palisadoes told me to discuss it with you: 1) We would not do unit tests as mocking can bypass the tests easily. 2) Rather we can use integration tests in which we can directly contact with a testing client which would be running on a different port. 3) Dependency injection can be done with tsyringe Your insights would be helpful! @xoldyckk @EshaanAgg

vasujain275 commented 6 months ago

@Manik2708, great idea, but we need a better rate limiter for our API right now. I have thought about implementing it with Redis. Currently, I am working on two different issues. Maybe you can first implement the rate limiting using Redis. After that, we can test Redis caching, as the rate limiter is of higher priority and will be beneficial to the project a lot.

Manik2708 commented 6 months ago

@Manik2708, great idea, but we need a better rate limiter for our API right now. I have thought about implementing it with Redis. Currently, I am working on two different issues. Maybe you can first implement the rate limiting using Redis. After that, we can test Redis caching, as the rate limiter is of higher priority and will be beneficial to the project a lot.

Is the issue opened for this? Like can I get more context about rate limiting?

Manik2708 commented 6 months ago

@Manik2708, great idea, but we need a better rate limiter for our API right now. I have thought about implementing it with Redis. Currently, I am working on two different issues. Maybe you can first implement the rate limiting using Redis. After that, we can test Redis caching, as the rate limiter is of higher priority and will be beneficial to the project a lot.

Is the issue opened for this? Like can I get more context about rate limiting?

Also, I saw that Dependency Injection through tsyringe doesn't provide control over file execution. For better and strong architecture we have to use Nest.js I also raised the issue regarding this in their library: https://github.com/microsoft/tsyringe/issues/235, So there is still a problem of Dependency Injection!