Skip to content
Open

lab 4 #1215

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
64 changes: 64 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Translations
*.mo
*.pot


# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Environments
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Pyre type checker
.pyre/
.idea/*
.env
/backup_worker.iml
59 changes: 59 additions & 0 deletions CI.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
## Continuous Integration (CI) Best Practices


### **Fine-tuned Triggers**
- Limiting the CI to run only when changes occur in specific folders or files, rather than on every single commit or push. This conserves resources.
```yaml
on:
push:
paths:
- 'app_python/**'
```

### **Explicit Environment Setup**
- Specifying the environment (like the OS) and the exact version of the tools (like Python) ensures consistency across CI runs.
```yaml
runs-on: ubuntu-latest
```

### **Dependency Caching**
- Caching dependencies speeds up CI runs, as they don't have to be fetched from the internet every time.
```yaml
- name: Cache pip
uses: actions/cache@v2
```

### **Linter Integration**
- Linters like `flake8` ensure code quality and adherence to coding standards.
```yaml
- name: Lint with flake8
```

### **Comprehensive Tests**
- Run unit tests to catch regressions and ensure that the software behaves as expected.
```yaml
- name: Run Tests
```

### Docker Integration
- Building and pushing Docker images as part of CI ensures the latest code changes are always available as Docker images.
```yaml
- name: Login to Docker Hub
- name: Build and Push Docker Image
```

### Secrets Management
- Sensitive information, like login credentials, should be stored securely using platform features like [GitHub Secrets](https://docs.github.com/en/actions/reference/encrypted-secrets).

### **Visibility with Status Badges**
- A status badge in README provides a quick overview of the health of project.
```markdown
![Python CI Workflow](![Python CI Workflow](https://github.com/eukuz/devops-course-labs/workflows/Python%20CI%20Workflow/badge.svg)
```

### **Fail-fast Strategy**
- If any step in the CI process fails, the entire job should stop immediately. This saves resources and provides faster feedback.

### **Matrix Builds**
- Running tests on multiple versions of a tool (e.g., Python) ensures compatibility across versions.

Binary file added __MACOSX/._core-course-labs-lab4
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._.DS_Store
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._.gitignore
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._.idea
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._CI.MD
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._README.md
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._app_js
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._app_python
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._lab4.md
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._terraform
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/._vkTerraform
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/.idea/._workspace.xml
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_js/._Dockerfile
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_js/._JS.md
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_js/._index.html
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_js/._server.js
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_python/._.flake8
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_python/._TEST.MD
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_python/._app.py
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/app_python/._logic.py
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/terraform/._TF.md
Binary file not shown.
Binary file not shown.
Binary file added __MACOSX/core-course-labs-lab4/terraform/._main.tf
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
5 changes: 5 additions & 0 deletions app_js/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.idea/*
README.md
*.md
node_modules/*
Dockerfile
9 changes: 9 additions & 0 deletions app_js/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM node:19-alpine3.15 AS builder
RUN addgroup -S rungroup && adduser -S runuser -G rungroup
WORKDIR /usr/src/app
COPY package*.json ./
RUN chown -R runuser:rungroup .

USER runuser
COPY . .
CMD ["node", "server.js"]
72 changes: 72 additions & 0 deletions app_js/JS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Joke Display Web Application

This simple web application fetches jokes from the [JokeAPI](https://v2.jokeapi.dev/)
and displays them in the center of the screen. You can press the "Another Joke"
button to get a new joke. If a "joke" property is available in the response,
it will be displayed. If the "joke" property is null, it will display the "setup"
and "delivery" properties as a complete joke.

## Installation

To run this application locally, follow these steps:

1. Make sure you have [Node.js](https://nodejs.org/) installed on your computer.

2. Navigate to the project directory:

```bash
cd app_js
```

3. Start a simple HTTP server using Node.js:

```bash
node server.js
```

4. Open your web browser and visit [http://localhost:3000](http://localhost:3000) to use the application.

### Build and run with Docker
1. Clone the repository. Go to `app_js` folder
2. Build an image

```
docker build -t maksktl/app_js:latest .
```

or pull an image from docker hub

```
docker pull maksktl/app_js:latest
```
3. Create and run a container from the built image
```
docker run -d -p 3000:3000 maksktl/app_js
```
4. Access the website `localhost:3000`

## Usage

- When you open the application in your web browser, you will initially see "Loading..." in the center of the screen.

- Press the "Another Joke" button to fetch and display a new joke from the JokeAPI.

- If the "joke" property is available in the response, it will be displayed.

- If the "joke" property is null, it will display the "setup" and "delivery" properties as a complete joke.

- If there is an error in fetching the joke, it will display an error message.

## Technologies Used

- JavaScript
- HTML
- CSS
- XMLHttpRequest
- Node.js (for serving the application)
- Docker
- Docker linter: hadolint
## Author

- Name: Maxim Matantsev
- Email: m.matantsev@innopolis.university
84 changes: 84 additions & 0 deletions app_js/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<title>HTTP GET Request Example</title>
<style>
body {
display: flex;
flex-direction: column; /* Display content and button in a column */
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}

#content {
text-align: center;
font-size: 24px;
padding: 20px;
border: 1px solid #ccc;
background-color: #f0f0f0;
}

#button-container {
margin-top: 20px;
}

button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
</style>
</head>
<body>
<div id="content">Loading...</div>
<div id="button-container">
<button id="nextJokeButton">Another Joke</button>
</div>

<script>
// Function to make an HTTP GET request
function httpRequest(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback(null, JSON.parse(xhr.responseText));
} else {
callback(xhr.status, null);
}
}
};
xhr.open("GET", url, true);
xhr.send();
}

// Function to update the content with the fetched joke
function updateContent(error, data) {
var contentDiv = document.getElementById("content");
if (error) {
contentDiv.textContent = "Error fetching joke.";
} else {
if (data.joke != null) {
contentDiv.textContent = data.joke;
} else if (data.setup != null) {
contentDiv.textContent = data.setup + "\n - " + data.delivery;
} else {
contentDiv.textContent = "No joke available.";
}
}
}

// Function to fetch and display a new joke when the button is clicked
function fetchAndDisplayNextJoke() {
httpRequest("https://v2.jokeapi.dev/joke/Any", updateContent);
}

// Add an event listener to the "Another Joke" button
var button = document.getElementById("nextJokeButton");
fetchAndDisplayNextJoke()
button.addEventListener("click", fetchAndDisplayNextJoke);
</script>
</body>
</html>
28 changes: 28 additions & 0 deletions app_js/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const http = require('http');
const fs = require('fs');
const path = require('path');

const server = http.createServer((req, res) => {

if (req.url === '/') {
const filePath = path.join(__dirname, 'index.html');
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Internal Server Error');
} else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(data);
}
});
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found');
}
});

const port = process.env.PORT || 3000;

server.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
Binary file added app_python/.DS_Store
Binary file not shown.
4 changes: 4 additions & 0 deletions app_python/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
demo.gif
Dockerfile
*.md
.flake8
3 changes: 3 additions & 0 deletions app_python/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[flake8]
exclude = venv, .git, pycache
max-line-length = 88
11 changes: 11 additions & 0 deletions app_python/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 22.10.0
hooks:
- id: black
37 changes: 37 additions & 0 deletions app_python/DOCKER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Report
=========

## Best practices

1. Avoid unnecessary privileges. Most containers run by the root user, while most of the
time it is not needed. Good practise to avoid it, and create a special user for those purposes.
* Make executables owned by root and not writable. This will block the executing user
from modifying existing binaries or scripts, which could enable different attacks.

2. Reduce attack surface.
* Use trusted and maintained images to reduce number of vulnerabilities and problems.
* Expose only those ports that application needs.

3. Prevent confidential data leaks.
* Use `.dockerignore` file to exclude not relevant files from build context.

4. Keep layer sanity. The order in the Dockerfile instructions is very important.
RUN, COPY, ADD, and other instructions will create a new container layer, grouping multiple commands
together will reduce the number of layers.

5. Don’t install unnecessary packages to reduce complexity, dependencies, file sizes, and build times.

6. Sort multi-line arguments alphanumerically for the ease to maintain and update.

7. Place Docker layers in such order to maximize build cache.

8. Use linting to detect bad practices in the Dockerfile.

9. Use labels to maintain and organise images.

10. Multi-stage builds to make build efficiency and light in weight


# Linter for Dockerfile

Hadolint linter was used in this application for Dockerfile.
Loading