mirror of
https://github.com/Dannecron/netology-devops.git
synced 2025-12-25 23:32:37 +03:00
homework 13.1: add project
This commit is contained in:
@@ -62,3 +62,4 @@
|
|||||||
* [12.3. Развертывание кластера на собственных серверах, лекция 1](/src/homework/12-kubernetes/12.3)
|
* [12.3. Развертывание кластера на собственных серверах, лекция 1](/src/homework/12-kubernetes/12.3)
|
||||||
* [12.4. Развертывание кластера на собственных серверах, лекция 2](/src/homework/12-kubernetes/12.4)
|
* [12.4. Развертывание кластера на собственных серверах, лекция 2](/src/homework/12-kubernetes/12.4)
|
||||||
* [12.5. Сетевые решения CNI](/src/homework/12-kubernetes/12.5)
|
* [12.5. Сетевые решения CNI](/src/homework/12-kubernetes/12.5)
|
||||||
|
* [13.1. контейнеры, поды, deployment, statefulset, services, endpoints](/src/homework/13-kubernates-config/13.1)
|
||||||
|
|||||||
41
src/homework/13-kubernates-config/13.1/readme.md
Normal file
41
src/homework/13-kubernates-config/13.1/readme.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
Выполнение [домашнего задания](https://github.com/netology-code/devkub-homeworks/blob/main/13-kubernetes-config-01-objects.md)
|
||||||
|
по теме "13.1. контейнеры, поды, deployment, statefulset, services, endpoints"
|
||||||
|
|
||||||
|
## Q/A
|
||||||
|
|
||||||
|
> Настроив кластер, подготовьте приложение к запуску в нём. Приложение стандартное: бекенд, фронтенд, база данных.
|
||||||
|
|
||||||
|
### Задание 1
|
||||||
|
|
||||||
|
> Подготовить тестовый конфиг для запуска приложения.
|
||||||
|
>
|
||||||
|
> Для начала следует подготовить запуск приложения в stage окружении с простыми настройками. Требования:
|
||||||
|
> * pod содержит в себе 2 контейнера — фронтенд, бекенд;
|
||||||
|
> * регулируется с помощью deployment фронтенд и бекенд;
|
||||||
|
> * база данных — через statefulset.
|
||||||
|
|
||||||
|
Директория с проектом приложения: [project](/src/homework/13-kubernates-config/project).
|
||||||
|
|
||||||
|
В первую очередь необходимо собрать образы приложения и опубликовать их в `registry`,
|
||||||
|
который будет доступен из кластера. Например, [hub.docker.com](https://hub.docker.com/)
|
||||||
|
|
||||||
|
// todo
|
||||||
|
|
||||||
|
### Задание 2
|
||||||
|
|
||||||
|
> Подготовить конфиг для production окружения.
|
||||||
|
>
|
||||||
|
> Следующим шагом будет запуск приложения в production окружении. Требования сложнее:
|
||||||
|
> * каждый компонент (база, бекенд, фронтенд) запускаются в своем поде, регулируются отдельными deployment’ами;
|
||||||
|
> * для связи используются service (у каждого компонента свой);
|
||||||
|
> * в окружении фронта прописан адрес сервиса бекенда;
|
||||||
|
> * в окружении бекенда прописан адрес сервиса базы данных.
|
||||||
|
|
||||||
|
// todo
|
||||||
|
|
||||||
|
### Задание 3
|
||||||
|
|
||||||
|
> Приложению потребовалось внешнее api, и для его использования лучше добавить endpoint в кластер, направленный на это api. Требования:
|
||||||
|
> * добавлен endpoint до внешнего api (например, геокодер).
|
||||||
|
|
||||||
|
// todo
|
||||||
11
src/homework/13-kubernates-config/project/README.md
Normal file
11
src/homework/13-kubernates-config/project/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Как запускать
|
||||||
|
Перед сборкой и запуском нужно подготовить файлы .env в директориях backend и frontend, скопировав переменные из файлов .env.example. Значения переменных могут отличаться для запуска в разных средах.
|
||||||
|
```
|
||||||
|
docker-compose up --build
|
||||||
|
```
|
||||||
|
Первый запуск может потребовать перезапуск из-за создания БД.
|
||||||
|
|
||||||
|
# Как работает
|
||||||
|
Запускаются 3 компонента (фронт, бек, база данных). Бекенд связывается с базой через link в докере.
|
||||||
|
|
||||||
|
Фронтенд запускается на 8000 порту, бекенд - на 9000.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DATABASE_URL=postgres://postgres:postgres@db:5432/news
|
||||||
14
src/homework/13-kubernates-config/project/backend/Dockerfile
Normal file
14
src/homework/13-kubernates-config/project/backend/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
FROM python:3.9-buster
|
||||||
|
|
||||||
|
RUN mkdir /app && python -m pip install pipenv
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ADD Pipfile /app/Pipfile
|
||||||
|
ADD Pipfile.lock /app/Pipfile.lock
|
||||||
|
|
||||||
|
RUN pipenv install
|
||||||
|
|
||||||
|
ADD main.py /app/main.py
|
||||||
|
|
||||||
|
CMD pipenv run uvicorn main:app --reload --host 0.0.0.0 --port 9000
|
||||||
18
src/homework/13-kubernates-config/project/backend/Pipfile
Normal file
18
src/homework/13-kubernates-config/project/backend/Pipfile
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[[source]]
|
||||||
|
name = "pypi"
|
||||||
|
url = "https://pypi.org/simple"
|
||||||
|
verify_ssl = true
|
||||||
|
|
||||||
|
[dev-packages]
|
||||||
|
|
||||||
|
[packages]
|
||||||
|
fastapi = "*"
|
||||||
|
uvicorn = "*"
|
||||||
|
sqlalchemy = "*"
|
||||||
|
databases = {extras = ["postgresql"], version = "*"}
|
||||||
|
asyncpg = "*"
|
||||||
|
pydantic = "*"
|
||||||
|
psycopg2 = "*"
|
||||||
|
|
||||||
|
[requires]
|
||||||
|
python_version = "3.9"
|
||||||
190
src/homework/13-kubernates-config/project/backend/Pipfile.lock
generated
Normal file
190
src/homework/13-kubernates-config/project/backend/Pipfile.lock
generated
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
{
|
||||||
|
"_meta": {
|
||||||
|
"hash": {
|
||||||
|
"sha256": "8ea4c718d8a2b5f2b1b961eb1e75c301b40fb82646b9c6f39839a6d14ee9059d"
|
||||||
|
},
|
||||||
|
"pipfile-spec": 6,
|
||||||
|
"requires": {
|
||||||
|
"python_version": "3.9"
|
||||||
|
},
|
||||||
|
"sources": [
|
||||||
|
{
|
||||||
|
"name": "pypi",
|
||||||
|
"url": "https://pypi.org/simple",
|
||||||
|
"verify_ssl": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"asyncpg": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:11102ac2febbc208427f39e4555537ecf188bd70ef7b285fc92c6c16b748b4c6",
|
||||||
|
"sha256:255839c8c52ebd72d6d0159564d7eb8f70fcf6cc9ce7cdc7e98328fd3279bf52",
|
||||||
|
"sha256:2710b5740cbd572e0fddc20986a44707f05d3f84e29fab72abe87fb8c2fc6885",
|
||||||
|
"sha256:43c44d323c3bd6514fbe6a892ccfdc551259bd92e98dd34ad1a52bad8c7974f3",
|
||||||
|
"sha256:812dafa4c9e264d430adcc0f5899f0dc5413155a605088af696f952d72d36b5e",
|
||||||
|
"sha256:98bef539326408da0c2ed0714432e4c79e345820697914318013588ff235b581",
|
||||||
|
"sha256:a19429d480a387346ae74b38da20e8da004337f14e5066f4bd6a10a8bbe74d3c",
|
||||||
|
"sha256:a2031df7573c80186339039cc2c4e684648fea5eaa9537c24f18c509bda2cd3f",
|
||||||
|
"sha256:a88654ede00596a7bdaa08066ff0505aed491f790621dcdb478066c7ddfd1a3d",
|
||||||
|
"sha256:b784138e69752aaa905b60c5a07a891445706824358fe1440d47113db72c8946",
|
||||||
|
"sha256:bd6e1f3db9889b5d987b6a1cab49c5b5070756290f3420a4c7a63d942d73ab69",
|
||||||
|
"sha256:ceedd46f569f5efb8b4def3d1dd6a0d85e1a44722608d68aa1d2d0f8693c1bff",
|
||||||
|
"sha256:d82d94badd34c8adbc5c85b85085317444cd9e062fc8b956221b34ba4c823b56",
|
||||||
|
"sha256:df84f3e93cd08cb31a252510a2e7be4bb15e6dff8a06d91f94c057a305d5d55d",
|
||||||
|
"sha256:f86378bbfbec7334af03bad4d5fd432149286665ecc8bfbcb7135da56b15d34b"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.23.0"
|
||||||
|
},
|
||||||
|
"click": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||||
|
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||||
|
"version": "==7.1.2"
|
||||||
|
},
|
||||||
|
"databases": {
|
||||||
|
"extras": [
|
||||||
|
"postgresql"
|
||||||
|
],
|
||||||
|
"hashes": [
|
||||||
|
"sha256:1521db7f6d3c581ff81b3552e130b27a13aefea2a57295e65738081831137afc",
|
||||||
|
"sha256:f82b02c28fdddf7ffe7ee1945f5abef44d687ba97b9a1c81492c7f035d4c90e6"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.4.3"
|
||||||
|
},
|
||||||
|
"fastapi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:478b7e0cbb52c9913b9903d88ae14195cb8a479c4596e0b2f2238d317840a7dc",
|
||||||
|
"sha256:7619282fbce0ec53c7dfa3fa262280c00ace9f6d772cfd06e4ab219dce66985e"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.65.1"
|
||||||
|
},
|
||||||
|
"h11": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6",
|
||||||
|
"sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==0.12.0"
|
||||||
|
},
|
||||||
|
"psycopg2": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:00195b5f6832dbf2876b8bf77f12bdce648224c89c880719c745b90515233301",
|
||||||
|
"sha256:068115e13c70dc5982dfc00c5d70437fe37c014c808acce119b5448361c03725",
|
||||||
|
"sha256:26e7fd115a6db75267b325de0fba089b911a4a12ebd3d0b5e7acb7028bc46821",
|
||||||
|
"sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3",
|
||||||
|
"sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051",
|
||||||
|
"sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5",
|
||||||
|
"sha256:6a3d9efb6f36f1fe6aa8dbb5af55e067db802502c55a9defa47c5a1dad41df84",
|
||||||
|
"sha256:a49833abfdede8985ba3f3ec641f771cca215479f41523e99dace96d5b8cce2a",
|
||||||
|
"sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e",
|
||||||
|
"sha256:b8cae8b2f022efa1f011cc753adb9cbadfa5a184431d09b273fb49b4167561ad",
|
||||||
|
"sha256:d160744652e81c80627a909a0e808f3c6653a40af435744de037e3172cf277f5",
|
||||||
|
"sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7",
|
||||||
|
"sha256:f22ea9b67aea4f4a1718300908a2fb62b3e4276cf00bd829a97ab5894af42ea3",
|
||||||
|
"sha256:f974c96fca34ae9e4f49839ba6b78addf0346777b46c4da27a7bf54f48d3057d",
|
||||||
|
"sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==2.8.6"
|
||||||
|
},
|
||||||
|
"pydantic": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd",
|
||||||
|
"sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739",
|
||||||
|
"sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f",
|
||||||
|
"sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840",
|
||||||
|
"sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23",
|
||||||
|
"sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287",
|
||||||
|
"sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62",
|
||||||
|
"sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b",
|
||||||
|
"sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb",
|
||||||
|
"sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820",
|
||||||
|
"sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3",
|
||||||
|
"sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b",
|
||||||
|
"sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e",
|
||||||
|
"sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3",
|
||||||
|
"sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316",
|
||||||
|
"sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b",
|
||||||
|
"sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4",
|
||||||
|
"sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20",
|
||||||
|
"sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e",
|
||||||
|
"sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505",
|
||||||
|
"sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1",
|
||||||
|
"sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.8.2"
|
||||||
|
},
|
||||||
|
"sqlalchemy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:014ea143572fee1c18322b7908140ad23b3994036ef4c0d630110faf942652f8",
|
||||||
|
"sha256:0172423a27fbcae3751ef016663b72e1a516777de324a76e30efa170dbd3dd2d",
|
||||||
|
"sha256:01aa5f803db724447c1d423ed583e42bf5264c597fd55e4add4301f163b0be48",
|
||||||
|
"sha256:0352db1befcbed2f9282e72843f1963860bf0e0472a4fa5cf8ee084318e0e6ab",
|
||||||
|
"sha256:09083c2487ca3c0865dc588e07aeaa25416da3d95f7482c07e92f47e080aa17b",
|
||||||
|
"sha256:0d5d862b1cfbec5028ce1ecac06a3b42bc7703eb80e4b53fceb2738724311443",
|
||||||
|
"sha256:14f0eb5db872c231b20c18b1e5806352723a3a89fb4254af3b3e14f22eaaec75",
|
||||||
|
"sha256:1e2f89d2e5e3c7a88e25a3b0e43626dba8db2aa700253023b82e630d12b37109",
|
||||||
|
"sha256:26155ea7a243cbf23287f390dba13d7927ffa1586d3208e0e8d615d0c506f996",
|
||||||
|
"sha256:2ed6343b625b16bcb63c5b10523fd15ed8934e1ed0f772c534985e9f5e73d894",
|
||||||
|
"sha256:34fcec18f6e4b24b4a5f6185205a04f1eab1e56f8f1d028a2a03694ebcc2ddd4",
|
||||||
|
"sha256:4d0e3515ef98aa4f0dc289ff2eebb0ece6260bbf37c2ea2022aad63797eacf60",
|
||||||
|
"sha256:5de2464c254380d8a6c20a2746614d5a436260be1507491442cf1088e59430d2",
|
||||||
|
"sha256:6607ae6cd3a07f8a4c3198ffbf256c261661965742e2b5265a77cd5c679c9bba",
|
||||||
|
"sha256:8110e6c414d3efc574543109ee618fe2c1f96fa31833a1ff36cc34e968c4f233",
|
||||||
|
"sha256:816de75418ea0953b5eb7b8a74933ee5a46719491cd2b16f718afc4b291a9658",
|
||||||
|
"sha256:861e459b0e97673af6cc5e7f597035c2e3acdfb2608132665406cded25ba64c7",
|
||||||
|
"sha256:87a2725ad7d41cd7376373c15fd8bf674e9c33ca56d0b8036add2d634dba372e",
|
||||||
|
"sha256:a006d05d9aa052657ee3e4dc92544faae5fcbaafc6128217310945610d862d39",
|
||||||
|
"sha256:bce28277f308db43a6b4965734366f533b3ff009571ec7ffa583cb77539b84d6",
|
||||||
|
"sha256:c10ff6112d119f82b1618b6dc28126798481b9355d8748b64b9b55051eb4f01b",
|
||||||
|
"sha256:d375d8ccd3cebae8d90270f7aa8532fe05908f79e78ae489068f3b4eee5994e8",
|
||||||
|
"sha256:d37843fb8df90376e9e91336724d78a32b988d3d20ab6656da4eb8ee3a45b63c",
|
||||||
|
"sha256:e47e257ba5934550d7235665eee6c911dc7178419b614ba9e1fbb1ce6325b14f",
|
||||||
|
"sha256:e98d09f487267f1e8d1179bf3b9d7709b30a916491997137dd24d6ae44d18d79",
|
||||||
|
"sha256:ebbb777cbf9312359b897bf81ba00dae0f5cb69fba2a18265dcc18a6f5ef7519",
|
||||||
|
"sha256:ee5f5188edb20a29c1cc4a039b074fdc5575337c9a68f3063449ab47757bb064",
|
||||||
|
"sha256:f03bd97650d2e42710fbe4cf8a59fae657f191df851fc9fc683ecef10746a375",
|
||||||
|
"sha256:f1149d6e5c49d069163e58a3196865e4321bad1803d7886e07d8710de392c548",
|
||||||
|
"sha256:f3c5c52f7cb8b84bfaaf22d82cb9e6e9a8297f7c2ed14d806a0f5e4d22e83fb7",
|
||||||
|
"sha256:f597a243b8550a3a0b15122b14e49d8a7e622ba1c9d29776af741f1845478d79",
|
||||||
|
"sha256:fc1f2a5a5963e2e73bac4926bdaf7790c4d7d77e8fc0590817880e22dd9d0b8b",
|
||||||
|
"sha256:fc4cddb0b474b12ed7bdce6be1b9edc65352e8ce66bc10ff8cbbfb3d4047dbf4",
|
||||||
|
"sha256:fcb251305fa24a490b6a9ee2180e5f8252915fb778d3dafc70f9cc3f863827b9"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==1.3.24"
|
||||||
|
},
|
||||||
|
"starlette": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed",
|
||||||
|
"sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==0.14.2"
|
||||||
|
},
|
||||||
|
"typing-extensions": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497",
|
||||||
|
"sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342",
|
||||||
|
"sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"
|
||||||
|
],
|
||||||
|
"version": "==3.10.0.0"
|
||||||
|
},
|
||||||
|
"uvicorn": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:3292251b3c7978e8e4a7868f4baf7f7f7bb7e40c759ecc125c37e99cdea34202",
|
||||||
|
"sha256:7587f7b08bd1efd2b9bad809a3d333e972f1d11af8a5e52a9371ee3a5de71524"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.13.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"develop": {}
|
||||||
|
}
|
||||||
96
src/homework/13-kubernates-config/project/backend/main.py
Normal file
96
src/homework/13-kubernates-config/project/backend/main.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import os
|
||||||
|
from typing import List
|
||||||
|
import databases
|
||||||
|
import sqlalchemy
|
||||||
|
from fastapi import FastAPI
|
||||||
|
from pydantic import BaseModel
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
|
||||||
|
app = FastAPI()
|
||||||
|
|
||||||
|
origins = [
|
||||||
|
'http://localhost',
|
||||||
|
'http://localhost:8000',
|
||||||
|
'http://localhost:9000',
|
||||||
|
'*',
|
||||||
|
]
|
||||||
|
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=origins,
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=['*'],
|
||||||
|
allow_headers=['*'],
|
||||||
|
)
|
||||||
|
|
||||||
|
DATABASE_URL = os.environ.get('DATABASE_URL',
|
||||||
|
'postgres://postgres:postgres@db:5432/news')
|
||||||
|
|
||||||
|
database = databases.Database(DATABASE_URL)
|
||||||
|
|
||||||
|
metadata = sqlalchemy.MetaData()
|
||||||
|
|
||||||
|
news = sqlalchemy.Table(
|
||||||
|
'news',
|
||||||
|
metadata,
|
||||||
|
sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True),
|
||||||
|
sqlalchemy.Column('title', sqlalchemy.String),
|
||||||
|
sqlalchemy.Column('short_description', sqlalchemy.String),
|
||||||
|
sqlalchemy.Column('description', sqlalchemy.String),
|
||||||
|
sqlalchemy.Column('preview', sqlalchemy.String),
|
||||||
|
)
|
||||||
|
|
||||||
|
engine = sqlalchemy.create_engine(
|
||||||
|
DATABASE_URL
|
||||||
|
)
|
||||||
|
metadata.create_all(engine)
|
||||||
|
|
||||||
|
|
||||||
|
class ShortNote(BaseModel):
|
||||||
|
id: int
|
||||||
|
title: str
|
||||||
|
short_description: str
|
||||||
|
preview: str
|
||||||
|
|
||||||
|
|
||||||
|
class Note(BaseModel):
|
||||||
|
id: int
|
||||||
|
title: str
|
||||||
|
short_description: str
|
||||||
|
description: str
|
||||||
|
preview: str
|
||||||
|
|
||||||
|
|
||||||
|
async def fill_db():
|
||||||
|
news_objects = await database.fetch_all(news.select())
|
||||||
|
if news_objects:
|
||||||
|
return
|
||||||
|
news_objects = []
|
||||||
|
for i in range(25):
|
||||||
|
news_objects.append({'title': f'title {i}',
|
||||||
|
'short_description': f'small text {i}' * 10,
|
||||||
|
'description': f'{i} some more text, ' * 100,
|
||||||
|
'preview': '/static/image.png'})
|
||||||
|
query = news.insert()
|
||||||
|
await database.execute_many(query=query, values=news_objects)
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_event('startup')
|
||||||
|
async def startup():
|
||||||
|
await database.connect()
|
||||||
|
await fill_db()
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_event('shutdown')
|
||||||
|
async def shutdown():
|
||||||
|
await database.disconnect()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get('/api/news/', response_model=List[ShortNote])
|
||||||
|
async def get_news():
|
||||||
|
return await database.fetch_all(news.select())
|
||||||
|
|
||||||
|
|
||||||
|
@app.get('/api/news/{new_id}', response_model=Note)
|
||||||
|
async def read_item(new_id: int):
|
||||||
|
return await database.fetch_one(news.select().where(news.c.id == new_id))
|
||||||
21
src/homework/13-kubernates-config/project/docker-compose.yml
Normal file
21
src/homework/13-kubernates-config/project/docker-compose.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
version: "3.7"
|
||||||
|
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
build: ./frontend
|
||||||
|
ports:
|
||||||
|
- 8000:80
|
||||||
|
|
||||||
|
backend:
|
||||||
|
build: ./backend
|
||||||
|
links:
|
||||||
|
- db
|
||||||
|
ports:
|
||||||
|
- 9000:9000
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:13-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_DB: news
|
||||||
1
src/homework/13-kubernates-config/project/frontend/.env
Normal file
1
src/homework/13-kubernates-config/project/frontend/.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
BASE_URL=http://localhost:9000
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
BASE_URL=http://localhost:9000
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
FROM node:lts-buster as builder
|
||||||
|
|
||||||
|
RUN mkdir /app
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ADD package.json /app/package.json
|
||||||
|
ADD package-lock.json /app/package-lock.json
|
||||||
|
|
||||||
|
RUN npm i
|
||||||
|
|
||||||
|
ADD . /app
|
||||||
|
|
||||||
|
RUN npm run build && rm -rf /app/node_modules
|
||||||
|
|
||||||
|
FROM nginx:latest
|
||||||
|
|
||||||
|
RUN mkdir /app
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=builder /app/ /app
|
||||||
|
|
||||||
|
RUN mv /app/markup/* /app && rm -rf /app/markup
|
||||||
|
|
||||||
|
ADD demo.conf /etc/nginx/conf.d/default.conf
|
||||||
@@ -0,0 +1,407 @@
|
|||||||
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the `main` element consistently in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background on active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57-
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers.
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10.
|
||||||
|
* 2. Remove the padding in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font: normal 400 13px/1.25 'Arial', sans-serif;
|
||||||
|
color: #000;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.b-page {
|
||||||
|
min-width: 320px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0px auto;
|
||||||
|
min-height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.b-page__title {
|
||||||
|
margin: 0 0 40px;
|
||||||
|
font-size: 3em;
|
||||||
|
line-height: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.b-page__image {
|
||||||
|
float: left;
|
||||||
|
margin: 0 20px 15px 0;
|
||||||
|
}
|
||||||
|
.b-page__text p {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
}
|
||||||
|
.b-page__text p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.b-items__item {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.b-items__item:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.b-preview {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.b-preview__title {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.b-preview__image {
|
||||||
|
float: left;
|
||||||
|
margin: 0 20px 10px 0;
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
.b-preview__text p {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
}
|
||||||
|
.b-preview__text p:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
124
src/homework/13-kubernates-config/project/frontend/build/main.js
Normal file
124
src/homework/13-kubernates-config/project/frontend/build/main.js
Normal file
File diff suppressed because one or more lines are too long
20
src/homework/13-kubernates-config/project/frontend/demo.conf
Normal file
20
src/homework/13-kubernates-config/project/frontend/demo.conf
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _ default_server;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root /app;
|
||||||
|
index markup/index.html;
|
||||||
|
try_files $uri /index.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* /detail {
|
||||||
|
root /app;
|
||||||
|
index markup/index.html;
|
||||||
|
try_files $uri /item.html;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* /static {
|
||||||
|
root /app;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export const BASE_URL = process.env.BASE_URL;
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import '../styles/index.less';
|
||||||
|
import {BASE_URL} from './config';
|
||||||
|
|
||||||
|
const URL_LIST = '/api/news/';
|
||||||
|
const URL_DETAIL = '/api/news/1/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Запрос данных
|
||||||
|
*/
|
||||||
|
function getData(url, detail = false) {
|
||||||
|
fetch(url)
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
if (detail) {
|
||||||
|
renderItem(data);
|
||||||
|
} else {
|
||||||
|
renderList(data);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рендер списка
|
||||||
|
*/
|
||||||
|
function renderList(data = []) {
|
||||||
|
if (!data.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = document.querySelector('.js-list');
|
||||||
|
|
||||||
|
for (let item of data) {
|
||||||
|
let block = document.createElement('article');
|
||||||
|
|
||||||
|
block.className = 'b-items__item b-preview';
|
||||||
|
block.id = item.id;
|
||||||
|
block.innerHTML = `
|
||||||
|
<a href="/detail/${item.id}/"><h2 class="b-preview__title">${item.title}</h2></a>
|
||||||
|
<img src="${item.preview}" class="b-preview__image" alt="${item.title}"/>
|
||||||
|
<div class="b-preview__text">${item.short_description}</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
content.append(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Рендер деталки
|
||||||
|
*/
|
||||||
|
function renderItem (data) {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let block = document.querySelector('.js-item');
|
||||||
|
|
||||||
|
block.innerHTML = `
|
||||||
|
<a><h1 class="b-page__title">${data.title}</h1>
|
||||||
|
<img src="${data.preview}" class="b-page__image" alt="${data.title}"/>
|
||||||
|
<div class="b-page__text">${data.description}</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let url = window.location.pathname;
|
||||||
|
let regexp = /^\/$/;
|
||||||
|
let regexpDetail = /\/detail\/\d*\/$/;
|
||||||
|
|
||||||
|
console.log(BASE_URL);
|
||||||
|
|
||||||
|
if (regexpDetail.test(url)) {
|
||||||
|
getData(BASE_URL + URL_DETAIL, true);
|
||||||
|
} else if (regexp.test(url)) {
|
||||||
|
getData(BASE_URL + URL_LIST);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<title>Список</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link href="/build/main.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main class="b-page">
|
||||||
|
<h1 class="b-page__title">Список</h1>
|
||||||
|
<div class="b-page__content b-items js-list"></div>
|
||||||
|
</main>
|
||||||
|
<script src="/build/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<title>Детальная</title>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link href="/build/main.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<article class="b-page js-item"></article>
|
||||||
|
<script src="/build/main.js"></script>
|
||||||
|
</body>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[{"id":1,"title":"title1","image":"static/img.png","short_description":"text1"}]
|
||||||
9280
src/homework/13-kubernates-config/project/frontend/package-lock.json
generated
Normal file
9280
src/homework/13-kubernates-config/project/frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "devops-testapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"scripts": {
|
||||||
|
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js --mode production",
|
||||||
|
"dev": "cross-env NODE_ENV=development webpack --watch --progress --config webpack.config.js --mode development"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.9.6",
|
||||||
|
"@babel/preset-env": "^7.9.6",
|
||||||
|
"autoprefixer": "^9.8.0",
|
||||||
|
"babel-loader": "^8.1.0",
|
||||||
|
"css-loader": "^3.5.3",
|
||||||
|
"dotenv-webpack": "^7.0.2",
|
||||||
|
"group-css-media-queries-loader": "^3.0.2",
|
||||||
|
"less-loader": "^6.1.0",
|
||||||
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
|
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||||
|
"postcss-loader": "^3.0.0",
|
||||||
|
"style-loader": "^1.2.1",
|
||||||
|
"svg-inline-loader": "^0.8.2",
|
||||||
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
|
"webpack": "^4.43.0",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-dev-server": "^3.11.0",
|
||||||
|
"webpack-obfuscator": "^1.2.2",
|
||||||
|
"webpackbar": "^4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/polyfill": "^7.10.1",
|
||||||
|
"cross-env": "^7.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,9 @@
|
|||||||
|
.b-items {
|
||||||
|
&__item {
|
||||||
|
margin-top: 30px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
.b-page {
|
||||||
|
min-width: 320px;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0px auto;
|
||||||
|
min-height: 100vh;
|
||||||
|
width: 100%;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0 0 40px;
|
||||||
|
font-size: 3em;
|
||||||
|
line-height: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {}
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
float: left;
|
||||||
|
margin: 0 20px 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
p {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
.b-preview {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0 0 20px;
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__image {
|
||||||
|
float: left;
|
||||||
|
margin: 0 20px 10px 0;
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
p {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
@import "normalize.css";
|
||||||
|
|
||||||
|
body {
|
||||||
|
font: normal 400 13px/1.25 'Arial', sans-serif;
|
||||||
|
color: #000;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
@import "bem/b-page";
|
||||||
|
@import "bem/b-items";
|
||||||
|
@import "bem/b-preview";
|
||||||
349
src/homework/13-kubernates-config/project/frontend/styles/normalize.css
vendored
Normal file
349
src/homework/13-kubernates-config/project/frontend/styles/normalize.css
vendored
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
|
||||||
|
|
||||||
|
/* Document
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the line height in all browsers.
|
||||||
|
* 2. Prevent adjustments of font size after orientation changes in iOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sections
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the margin in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the `main` element consistently in IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
main {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the font size and margin on `h1` elements within `section` and
|
||||||
|
* `article` contexts in Chrome, Firefox, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grouping content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in Firefox.
|
||||||
|
* 2. Show the overflow in Edge and IE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hr {
|
||||||
|
box-sizing: content-box; /* 1 */
|
||||||
|
height: 0; /* 1 */
|
||||||
|
overflow: visible; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Text-level semantics
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the gray background on active links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Remove the bottom border in Chrome 57-
|
||||||
|
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: none; /* 1 */
|
||||||
|
text-decoration: underline; /* 2 */
|
||||||
|
text-decoration: underline dotted; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||||
|
* 2. Correct the odd `em` font sizing in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, monospace; /* 1 */
|
||||||
|
font-size: 1em; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||||
|
* all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the border on images inside links in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Change the font styles in all browsers.
|
||||||
|
* 2. Remove the margin in Firefox and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
optgroup,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: inherit; /* 1 */
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
line-height: 1.15; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the overflow in IE.
|
||||||
|
* 1. Show the overflow in Edge.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input { /* 1 */
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||||
|
* 1. Remove the inheritance of text transform in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
select { /* 1 */
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
[type="button"],
|
||||||
|
[type="reset"],
|
||||||
|
[type="submit"] {
|
||||||
|
-webkit-appearance: button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner border and padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
[type="button"]::-moz-focus-inner,
|
||||||
|
[type="reset"]::-moz-focus-inner,
|
||||||
|
[type="submit"]::-moz-focus-inner {
|
||||||
|
border-style: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the focus styles unset by the previous rule.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button:-moz-focusring,
|
||||||
|
[type="button"]:-moz-focusring,
|
||||||
|
[type="reset"]:-moz-focusring,
|
||||||
|
[type="submit"]:-moz-focusring {
|
||||||
|
outline: 1px dotted ButtonText;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the padding in Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
padding: 0.35em 0.75em 0.625em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the text wrapping in Edge and IE.
|
||||||
|
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||||
|
* 3. Remove the padding so developers are not caught out when they zero out
|
||||||
|
* `fieldset` elements in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
color: inherit; /* 2 */
|
||||||
|
display: table; /* 1 */
|
||||||
|
max-width: 100%; /* 1 */
|
||||||
|
padding: 0; /* 3 */
|
||||||
|
white-space: normal; /* 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||||
|
*/
|
||||||
|
|
||||||
|
progress {
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the default vertical scrollbar in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Add the correct box sizing in IE 10.
|
||||||
|
* 2. Remove the padding in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="checkbox"],
|
||||||
|
[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="number"]::-webkit-inner-spin-button,
|
||||||
|
[type="number"]::-webkit-outer-spin-button {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the odd appearance in Chrome and Safari.
|
||||||
|
* 2. Correct the outline style in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"] {
|
||||||
|
-webkit-appearance: textfield; /* 1 */
|
||||||
|
outline-offset: -2px; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the inner padding in Chrome and Safari on macOS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||||
|
* 2. Change font properties to `inherit` in Safari.
|
||||||
|
*/
|
||||||
|
|
||||||
|
::-webkit-file-upload-button {
|
||||||
|
-webkit-appearance: button; /* 1 */
|
||||||
|
font: inherit; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interactive
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in Edge, IE 10+, and Firefox.
|
||||||
|
*/
|
||||||
|
|
||||||
|
details {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the correct display in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
summary {
|
||||||
|
display: list-item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Misc
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
template {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the correct display in IE 10.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
const isDevMode = process.env.NODE_ENV === 'development';
|
||||||
|
const path = require('path');
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const WebpackBar = require('webpackbar');
|
||||||
|
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||||
|
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||||
|
const JavaScriptObfuscator = require('webpack-obfuscator');
|
||||||
|
|
||||||
|
const Dotenv = require('dotenv-webpack');
|
||||||
|
|
||||||
|
module.exports = (env) => ({
|
||||||
|
entry: path.join(__dirname, 'js/index.js'),
|
||||||
|
output: {
|
||||||
|
path: __dirname + '/build',
|
||||||
|
filename: 'main.js',
|
||||||
|
},
|
||||||
|
devtool: isDevMode ? 'eval-cheap-module-source-map' : 'none',
|
||||||
|
module: {
|
||||||
|
rules: isDevMode ? developmentModuleRules : productionModuleRules
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin(),
|
||||||
|
new WebpackBar({
|
||||||
|
name: `${isDevMode ? 'development' : 'production'} build progress`
|
||||||
|
}),
|
||||||
|
new Dotenv()
|
||||||
|
],
|
||||||
|
optimization: {
|
||||||
|
minimizer: isDevMode ? [] : minimiztionPlugins
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const productionModuleRules = [
|
||||||
|
{
|
||||||
|
test: /\.svg$/,
|
||||||
|
loader: 'svg-inline-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /.js$/,
|
||||||
|
exclude: /(node_modules|bower_components)/,
|
||||||
|
use: {
|
||||||
|
loader: 'babel-loader',
|
||||||
|
options: {
|
||||||
|
presets: ['@babel/preset-env']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /.less$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
options: {
|
||||||
|
publicPath: __dirname + "/build",
|
||||||
|
filename: 'main.css'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'css-loader',
|
||||||
|
{
|
||||||
|
loader: `postcss-loader`,
|
||||||
|
options: {
|
||||||
|
options: {
|
||||||
|
plugins: () => [autoprefixer()]
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'group-css-media-queries-loader',
|
||||||
|
'less-loader'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const developmentModuleRules = [
|
||||||
|
{
|
||||||
|
test: /\.svg$/,
|
||||||
|
loader: 'svg-inline-loader'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /.less$/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
options: {
|
||||||
|
publicPath: __dirname + "/build",
|
||||||
|
filename: 'main.css'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'css-loader',
|
||||||
|
'less-loader'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const minimiztionPlugins = [
|
||||||
|
new UglifyJsPlugin({
|
||||||
|
parallel: true,
|
||||||
|
uglifyOptions: {
|
||||||
|
output: {
|
||||||
|
comments: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new OptimizeCSSAssetsPlugin(),
|
||||||
|
new JavaScriptObfuscator({
|
||||||
|
rotateStringArray: true,
|
||||||
|
rotateUnicodeArray: true
|
||||||
|
}, ['main.js'])
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user