Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7a1a7fe
ReadMe file addition to Master Branch
RobertronS Jun 1, 2022
ed7671b
alternative commit
RobertronS Jun 1, 2022
d29e053
Merge branch 'DevOps-Inno-22-summer-master'
RobertronS Jun 1, 2022
f35270e
Lab 1 instructions: Appication description
RobertronS Jun 1, 2022
1e81158
This is for lab1
RobertronS Jul 5, 2022
e87b5c5
Lab 2 - DevOps: Dockerfile
RobertronS Jul 9, 2022
a85e141
Create ci_main.yml
RobertronS Sep 25, 2022
bb325e1
Lab 3 DevOps V1.0
RobertronS Sep 25, 2022
810212f
Update ci_main.yml
RobertronS Sep 25, 2022
1a3adfb
Lab 3 DevOps V1.2
RobertronS Sep 25, 2022
5057337
Lab 3 DevOps V1.3
RobertronS Sep 25, 2022
3b3e142
Lab 3 DevOps V1.4: Fix of test when running in another server
RobertronS Sep 25, 2022
efbe38c
Lab 3 DevOps V1.5: Fix library pytz
RobertronS Sep 25, 2022
ee47920
Lab 3 DevOps V1.6: Add github workflow status badge
RobertronS Sep 26, 2022
ded3a46
Lab 3 DevOps V1.6: Add license
RobertronS Sep 26, 2022
18dbfc8
Lab 3 DevOps V1.8: Fix git ignore
RobertronS Sep 26, 2022
59b7760
Lab 3 DevOps V1.9: Fix git ignore II
RobertronS Sep 26, 2022
0648d86
all pyc files removed
RobertronS Sep 26, 2022
3c136f1
Lab 3 DevOps V1.10: Edit License.md file
RobertronS Sep 26, 2022
e415b88
Lab 3 DevOps V1.11: Edit readme.md file
RobertronS Sep 26, 2022
11d640b
Lab 3 DevOps V1.12: add docker ignore file
RobertronS Sep 26, 2022
c68e3c8
Lab 3 DevOps V1.13: Edit readme.md file
RobertronS Sep 26, 2022
004eebb
Lab 4 DevOps Terraform V1.0
RobertronS Dec 15, 2022
f08c9bd
Lab 4 DevOps Terraform V1.1-Modify tf
RobertronS Dec 15, 2022
5846957
Lab 4 DevOps Terraform V1.2-add terraform
RobertronS Dec 15, 2022
b27c62f
Lab 5 - DevOps (Ansible)
RobertronS Dec 22, 2022
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
103 changes: 103 additions & 0 deletions .github/workflows/ci_main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: ci for time application python app

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:
name: Build application and lint it with flask
runs-on: ubuntu-latest
env:
working_dir: app_python
strategy:
fail-fast: false
matrix:
python-version: ["3.8"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8
python -m pip install Flask
python -m pip install ntplib
- name: Lint with flake8
run: |
# exit on critical errors (syntax errors, undefined names)
flake8 ${{ env.working_dir }}/ --count --select=E9,F63,F7,F82 --show-source --statistics
# treat rest of the errors as warnings (display, but do not terminate build process)
flake8 ${{ env.working_dir }}/ --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

test:
name: Run tests
runs-on: ubuntu-latest
env:
working_dir: app_python
strategy:
fail-fast: false
matrix:
python-version: ["3.8"]
needs: build
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install pytest
python -m pip install requests
python -m pip install Flask
python -m pip install ntplib
python -m pip install pytz
- name: Run tests
run: |
cd app_python
python -m unittest test_app.py

docker:
name: Build, cache and publish docker
needs: build
environment: ci
runs-on: ubuntu-latest
env:
working_dir: app_python
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
with:
context: ./${{ env.working_dir }}
push: true
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/app-python:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- name: Replace old cache with new cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# ignore ALL files in ANY directory named __pycache__
./app_python/__pycache__
*.pyc
terraform/.vagrant/
secret.tfvars
3 changes: 3 additions & 0 deletions ANSIBLE.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## Playbook Run.

![Ansible playbook](./images/lab5/Ansible-playbook.png)
23 changes: 23 additions & 0 deletions CI.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# [GitHub CI actions best practices](https://exercism.org/docs/building/github/gha-best-practices).

### Set timeouts for workflows:

Many workflows don't need nearly as much time to finish, but sometimes unexpected errors occur or a job hangs until the workflow run is killed 6 hours after starting it. Therefore ***it's recommended to specify a shorter timeout***. This has the following advantages:

- PRs won't be pending CI for half the day, issues can be caught early or workflow runs can be restarted.
- The number of overall parallel builds is limited, hanging jobs will not cause issues for other PRs if they are cancelled early.

### Consider if (third-party) actions are really needed:

Actions should be treated like dependencies in your favourite programming language, they are code written by third party authors outside of the control of Exercism. Even if you trust the authors of the action, there may be a hostile takeover of the repository which will indirectly give those people access to Exercism repos, including write access. Therefore, you should carefully consider if introducing a new action is really worth it or if it's better to move the code into a (new) action under Exercism's control.

### Pin actions to SHAs:

When using other actions, pin them to a commit (via their SHA), not to a branch or tag. This ensures that the same code will be executed each time, which is not guaranteed when pinning to a branch or tag. This has two benefits:

- It makes your build stable
- It prevents an attacker from changing a branch/tag to point to malicious code The only exception to this rule could be actions that we (Exercism) have built ourselves.

### Consider setting up a concurrency strategy

It's often not necessary or useful to run CI on intermediate commits if a newer commit has been pushed in the meantime. You can configure a [concurrency strategy](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency) in order to automatically cancel running workflows in the same context.
19 changes: 19 additions & 0 deletions DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## [Docker best practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/).

### Create ephemeral containers:

- The image defined by your `Dockerfile` should generate containers that are as ephemeral as possible. By “ephemeral”, we mean that the container can be stopped and destroyed, then rebuilt and replaced with an absolute minimum set up and configuration.

### Understand build context:

- When you issue a `docker build` command, the current working directory is called the <em>build context</em>. By default, the Dockerfile is assumed to be located here, but you can specify a different location with the file flag (`-f`). Regardless of where the `Dockerfile` actually lives, all recursive contents of files and directories in the current directory are sent to the Docker daemon as the build context.

### Don't install unnecessary packages:

- To reduce complexity, dependencies, file sizes, and build times, avoid installing extra or unnecessary packages just because they might be “nice to have.” For example, you don’t need to include a text editor in a database image.

### Minimize the number of layers:

- Only the instructions `RUN`, `COPY`, `ADD` create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.

- Where possible, use [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/), and only copy the artifacts you need into the final image. This allows you to include tools and debug information in your intermediate build stages without increasing the size of the final image.
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 Roberto Enrique Chavez Rodriguez.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
34 changes: 34 additions & 0 deletions PYTHON.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

Frameworks like `Django` and `Flask` can be used for a production environment, but flask is usually used for prototyping since it is easy to work with; however, flask is slow.

Also with `Flask`we have to use a lot of plugins to get a usual server functionality, that is a disadvantage.

`Django` is a [“batteries included”](https://en.wikipedia.org/wiki/Batteries_Included) framework.

For familiarity, Flask was used to write this application.

About Python best practices, we can say:

### The code:
- It must do what it is supposed to do.
- It must not contain defects and problems.
- It must be easy to read, maintain, or extend.

## Unit tests and best practices.

### [Unit testing best practices](https://docs.python-guide.org/writing/tests/):

- A testing unit should focus on one single functionality and prove it correct.
- Each test unit must be fully independent. Each test must be able to run alone, and also within the test suite, regardless of the order that they are called.
- Learn your tools and learn how to run a single test or a test case. Then, when developing a function inside a module, run this function’s tests frequently, ideally automatically when you save the code.
- Always run the full test suite before a coding session, and run it again after. This will give you more confidence that you did not break anything in the rest of the code.
- Use long and descriptive names for testing functions. The style guide here is slightly different than that of running code, where short names are often preferred. The reason is testing functions are never called explicitly. `square()` or even `sqr()` is ok in running code, but in testing code you would have names such as `test_square_of_number_2()`, `test_square_negative_number()`. These function names are displayed when a test fails, and should be as descriptive as possible.

### Unit tests:

There are three tests:

- `test__api_time_properly_responds()` tests that an existing api returns time properly. The returned time is from Moscow and we need to make sure the api works well to use it later in the other tests.
- `test__api_and_app__time_diff_less_than_2s()` tests that the returned time by the api and the app coincide and differ in at most 2 seconds.
- `test_time_correctly_changed()` tests that the app in fact returns different times every time the app method `print_time()` is called and that it is displayed correctly in a browser.

85 changes: 29 additions & 56 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,45 @@
# Labs
![Python CI workflow status badge](https://github.com/RobertronS/labsDevOpsMasterProgram/actions/workflows/ci_main.yml/badge.svg)

## Introduction
# Innopolis University Advanced DevOps course - Summer 2022.
## How the application works for lab 1:

Welcome to DevOps course labs. All labs are practical and will be built on each other. You will implement simple application, containerize it, implement simple tests, build CI/CD, collect metrics, logs, etc.
- `Flask` is a small and lightweight Python web framework that provides useful tools and features that make creating web applications in Python easier. It gives developers flexibility and is a more accessible framework for new developers since you can build a web application quickly using only a single Python file.
- The python time method `ctime()` converts a time expressed in seconds since the epoch to a string representing local time. If secs is not provided or None, the current time as returned by time() is used. This function is equivalent to asctime(localtime(secs)).
- The `ntplib` module offers a simple interface to query NTP servers from Python.
- Consequently The method `print_time` prints the time that is in the machine where the app is running.
- `if __name__ == “main”:` is used to execute some code *only if the file was run directly*, and not imported.

## Architecture
## Docker section (Lab2):

This repository contains master branch with introduction and one branch with instructions for each lab.
The Dockerfile creation of this work is based on the article [<em> How to Dockerize a Flask Application </em>](https://www.freecodecamp.org/news/how-to-dockerize-a-flask-app/)

## Rules
- In this part of the project, a dockerfile is created. The `Dockerfile` starts with the installation of a python image (`FROM`), in which the application will run. This import is obvious since without python, the app would not run.
- Next, I add the maintainer tag, in which I can let other users know who is the creator of this file.
- There is a couple of `RUN` commands. The first RUN creates a directory in which all the application will be contained in the container, and the second RUN performs command line operations that are needed to run the application.
- The `COPY` command works to copy the the files in our local working directory to the directory in the docker image.
- The `CMD` instruction contains a list of command line commands that will be executed when a container is created from the image.
- Finally, there is an `EXPOSE` tag which simply lets Docker know that the container listens on the specified network ports at runtime. You can specify whether the port listens on TCP or UDP, and the default is TCP if the protocol is not specified. The EXPOSE instruction does not actually publish the port.

Each labs requires the participant to pass all previous labs, therefore participants are required **to submit each lab (and get at least 60% of max grade for each lab) to pass the course**.
- The image can be downloaded from [my Docker Hub](https://hub.docker.com/r/robertrons/app_python/tags). To run the image, you must run this command: `docker run -p 5000:5000 robertrons/app_python:1.0` Then the app will run on: [http://127.0.0.1:5000](http://127.0.0.1:5000)

Grading is based on PRs with your solutions to the corresponding branch of this repository. This repository is read-only for all participants, therefore to be able to create pull requests, a participant should fork this repository to his own workspace and solve labs there. It is recommended to build solution of lab N upon solution of lab N-1, so choose workflow in your fork of this repository wisely. Structure of your repository will not affect your grade, only state of your repository from which the PR is created will be checked and graded (state after last commit in your PR on corresponding lab).
## Continuous integration (Lab3):

### Recommended workflow
### Code testing:

#### For the first lab
1. Fork this repository on your workspace
2. Checkout master branch
3. Complete lab1 tasks
4. Push the code to your repository
5. **UPD.** create new branch (called lab1_submission) from main
6. **UPD.** Create PR to lab1 branch on this repository from lab1_submission
7. Submit zip to moodle
8. Wait for your grade
The file *test_app.py* contains the tests for the *app.py* application file. To run the tests, please use the command `python -m unittest test_app` in a command line interface (cli). Check the file *PYTHON.md* for details of what the tests do.

#### For all other labs
1. Checkout the commit where you finished the previous lab
2. Complete tasks of current lab
3. Push the code to your repository
4. **UPD.** create new branch (called labN_submission) from main
5. **UPD.** Create PR to labN branch on this repository from labN_submission
6. Submit zip to moodle
7. Wait for your grade
Before running the tests command, the python libraries `requests`, `pytz`, and `unittest` should be installed.

### GitHub CI actions:

## Grading
The [configure GitHub Actions](https://docs.docker.com/ci-cd/github-actions/) docker tutorial was used to set up a Docker project.

### Points distribution for the course
A new file ci_main.yml is added that develops the CI tasks for the project. Mainly, 3 jobs are configured for the CI (continuous integration) process:

```
70 - labs
30 - final exam
```
1. **Build the application:** The applicattion is build with all its dependencies and connected with the flask framework.
2. **Run tests:** In this stage, unit tests are executed to test the application's correct functionalities.
3. **Build, chache and publish docker:** In this stage, the application is ready for the integration and a docker project is set up.

### Grade ranges

```
[90;100] - A
[75;90) - B
[60;75) - C
[0;60) - D
```

### Labs grading

Each lab is marked out of 10. All labs have a set of main tasks and a set of extra tasks.

Completing main tasks correctly will give you 10 points out of 10. Completing extra tasks correctly will give you N (depends on the complexity of extra tasks) additional points. Your points for main and extra tasks will be summed and cut to 10 if you have more than 10. Basically, extra points will allow you to get max points even if some main tasks are not finished correctly, but will not give you more points for the course.

## Deadlines and labs distribution

Participants will be provided 2 labs simultaneously and have 1 week to submit solutions. Moodle will contain presentations and deadlines.

**UPD.** You are required to submit zip file with your source code to corresponding assignment in moodle. This is required for the university as proof of work.

### Late submission policy

Submitting results after the deadline will result in maximum of 6 points for the corresponding lab. As stated before, all labs must be submitted to pass the course.
The CI workflow status badge:

![Python time app workflow](https://github.com/RobertronS/labsDevOpsMasterProgram/actions/workflows/ci_main.yml/badge.svg)
30 changes: 30 additions & 0 deletions TF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Best practices for Terraform

- Dont't change terraform state file (.tfstate) manually, it is better to do this by using "apply" command
- Set up a shared remote storage
- Backup state file
- Use 1 state file per Environment (test, dev, or production)
- Use CI for terraform code
- Generate README for each module with input and output variables
- Update terraform version
- Terraform version manager
- Run terraform in docker container

### About Naming Conventions:

- Use _ (underscore) instead of - (dash) everywhere (in resource names, data source names, variable names, outputs, etc).
- Prefer to use lowercase letters and numbers (even though UTF-8 is supported).

## Vagrant.

Not possible to work with vagrant (VPN issues)

![VagrantIssues](../images/lab4/vagrant_issues.png)

## Terraform WorkSpace

![Terraform](./images/lab4/terraform_workspace.png)

## Yandex Cloud VM

![Virtual Machine](./images/lab5/yandex-cloud.png)
7 changes: 7 additions & 0 deletions ansible/ansible.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[defaults]
private_key_file = inventory/sshk.txt
inventory = inventory/inventory.txt
interpreter_python = auto

[ssh_connection]
ssh_args = -o ServerAliveInterval=100 -o ControlMaster=auto -o ControlPersist=10m
1 change: 1 addition & 0 deletions ansible/inventory/inventory.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
158.160.55.161 ansible_user=robertron ansible_sudo_pass=""
8 changes: 8 additions & 0 deletions ansible/inventory/sshk.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jdHIAAAAGYmNyeXB0AAAAGAAAABDId99Q5t
RAJkeEv2Fjm9b4AAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAINzpvrn2zpaFGwbC
UixYuI6NvvVkuBGqWEPkHTkVlEN3AAAAoKUycK/nCDd+7UP9jVubSe+bh0lKDi0BfR8ZkP
nE0PC7aRqFPaVqxQM7QC4doiROWZTX9yds8WQX4jf/kDz1vjUP+5SipKugg9OsyOhiqkf3
0I9c0BkT8HSQQ6nUUf5VfEA04+I0mWRD8L8UgQt5bEngWAAvzCB2I6skNX3AaK9AzjzEaI
altEeogPUwgn07KUJED8k+WOyXp/RL4lGkaSo=
-----END OPENSSH PRIVATE KEY-----
1 change: 1 addition & 0 deletions ansible/inventory/sshk.txt.pub
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINzpvrn2zpaFGwbCUixYuI6NvvVkuBGqWEPkHTkVlEN3 robertron@LAPTOP-FQ1HKILG
4 changes: 4 additions & 0 deletions ansible/playbooks/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- hosts: all
roles:
- role: ../roles/role-docker
become: true
Loading